remove codeigniter
This commit is contained in:
+1
-1
@@ -2,7 +2,7 @@ FROM composer:2 AS vendor
|
|||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY composer.json composer.lock ./
|
COPY composer.json composer.lock ./
|
||||||
COPY app/Helpers/ci_helpers.php app/Helpers/
|
COPY app/Helpers/app_helpers.php app/Helpers/
|
||||||
RUN composer install --no-dev --prefer-dist --no-interaction --no-progress --no-scripts --ignore-platform-req=ext-gd
|
RUN composer install --no-dev --prefer-dist --no-interaction --no-progress --no-scripts --ignore-platform-req=ext-gd
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN composer dump-autoload --optimize \
|
RUN composer dump-autoload --optimize \
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Config;
|
|
||||||
|
|
||||||
use App\Models\CiDatabase;
|
|
||||||
|
|
||||||
class Database
|
|
||||||
{
|
|
||||||
public static function connect(): CiDatabase
|
|
||||||
{
|
|
||||||
return CiDatabase::instance();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Config;
|
|
||||||
|
|
||||||
use App\Services\EmailService;
|
|
||||||
use App\Services\Scores\SemesterScoreService;
|
|
||||||
|
|
||||||
class Services
|
|
||||||
{
|
|
||||||
public static function email(): EmailService
|
|
||||||
{
|
|
||||||
return new EmailService();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function emailService(): EmailService
|
|
||||||
{
|
|
||||||
return static::email();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function semesterScoreService(): SemesterScoreService
|
|
||||||
{
|
|
||||||
return new SemesterScoreService();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Config;
|
|
||||||
|
|
||||||
class SessionTimeout
|
|
||||||
{
|
|
||||||
public const TIMEOUT_DURATION = 1200; // 20 minutes
|
|
||||||
public const WARNING_THRESHOLD = 900; // 15 minutes
|
|
||||||
public const CHECK_INTERVAL = 60; // 1 minute
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
return [
|
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Progress Report Status Labels
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
'status_options' => [
|
|
||||||
'on_track' => 'On track',
|
|
||||||
'slightly_behind' => 'Slightly behind',
|
|
||||||
'behind' => 'Behind',
|
|
||||||
],
|
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Subject Sections Mapping
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Replace with your exact CI ClassProgressController::SUBJECT_SECTIONS values
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
'subject_sections' => [
|
|
||||||
'islamic' => [
|
|
||||||
'label' => 'Islamic Studies',
|
|
||||||
'db_subject' => 'Islamic Studies',
|
|
||||||
],
|
|
||||||
'quran' => [
|
|
||||||
'label' => 'Quran/Arabic',
|
|
||||||
'db_subject' => 'Quran/Arabic',
|
|
||||||
],
|
|
||||||
],
|
|
||||||
|
|
||||||
];
|
|
||||||
@@ -2,30 +2,6 @@
|
|||||||
|
|
||||||
use Carbon\CarbonImmutable;
|
use Carbon\CarbonImmutable;
|
||||||
use Illuminate\Support\Facades\Hash;
|
use Illuminate\Support\Facades\Hash;
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
|
|
||||||
if (!function_exists('log_message')) {
|
|
||||||
function log_message(string $level, string $message, array $context = []): void
|
|
||||||
{
|
|
||||||
$level = strtolower($level);
|
|
||||||
$logger = Log::channel(config('logging.default'));
|
|
||||||
$context = $context;
|
|
||||||
if (!empty($context)) {
|
|
||||||
$message = strtr($message, array_combine(
|
|
||||||
array_map(fn($k) => "{" . $k . "}", array_keys($context)),
|
|
||||||
array_map('strval', $context)
|
|
||||||
));
|
|
||||||
}
|
|
||||||
$logger->{$level}($message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!function_exists('esc')) {
|
|
||||||
function esc($value): string
|
|
||||||
{
|
|
||||||
return e($value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!function_exists('utc_now')) {
|
if (!function_exists('utc_now')) {
|
||||||
function utc_now(): string
|
function utc_now(): string
|
||||||
@@ -53,13 +29,6 @@ if (!function_exists('user_timezone')) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!function_exists('model')) {
|
|
||||||
function model(string $class)
|
|
||||||
{
|
|
||||||
return app()->make($class);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!function_exists('pbkdf2_hash')) {
|
if (!function_exists('pbkdf2_hash')) {
|
||||||
function pbkdf2_hash(string $password, string $algo = 'sha256', int $iterations = 100000, int $length = 64): string
|
function pbkdf2_hash(string $password, string $algo = 'sha256', int $iterations = 100000, int $length = 64): string
|
||||||
{
|
{
|
||||||
@@ -97,15 +66,8 @@ if (!function_exists('pbkdf2_verify')) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!function_exists('legacy_password_verify')) {
|
if (!function_exists('verify_stored_password')) {
|
||||||
function legacy_password_verify(string $password, ?string $storedHash): bool
|
function verify_stored_password(string $password, ?string $storedHash): bool
|
||||||
{
|
|
||||||
return ci_password_verify($password, $storedHash);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!function_exists('ci_password_verify')) {
|
|
||||||
function ci_password_verify(string $password, ?string $storedHash): bool
|
|
||||||
{
|
{
|
||||||
if (!$storedHash) {
|
if (!$storedHash) {
|
||||||
return false;
|
return false;
|
||||||
@@ -17,9 +17,6 @@ class AttendanceCommentTemplateController extends Controller
|
|||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Bootstrap URLs for admin UIs (legacy CodeIgniter parity + SPA).
|
|
||||||
*/
|
|
||||||
public function bootstrapUrls(): JsonResponse
|
public function bootstrapUrls(): JsonResponse
|
||||||
{
|
{
|
||||||
return response()->json([
|
return response()->json([
|
||||||
@@ -133,10 +130,6 @@ class AttendanceCommentTemplateController extends Controller
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* CodeIgniter {@see \App\Controllers\View\AttendanceCommentTemplateController::save}
|
|
||||||
* POST fields: id?, min_score, max_score, template_text, is_active (checkbox "on").
|
|
||||||
*/
|
|
||||||
public function legacySave(Request $request): JsonResponse
|
public function legacySave(Request $request): JsonResponse
|
||||||
{
|
{
|
||||||
$id = $request->input('id');
|
$id = $request->input('id');
|
||||||
@@ -183,9 +176,6 @@ class AttendanceCommentTemplateController extends Controller
|
|||||||
return response()->json(['status' => 'success']);
|
return response()->json(['status' => 'success']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* CodeIgniter {@see \App\Controllers\View\AttendanceCommentTemplateController::delete}.
|
|
||||||
*/
|
|
||||||
public function legacyDelete(Request $request): JsonResponse
|
public function legacyDelete(Request $request): JsonResponse
|
||||||
{
|
{
|
||||||
$id = $request->input('id');
|
$id = $request->input('id');
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ class AuthController extends BaseApiController
|
|||||||
], 401);
|
], 401);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! ci_password_verify($password, (string) $user->password)) {
|
if (! verify_stored_password($password, (string) $user->password)) {
|
||||||
$security->handleFailedLogin($user, $email, (string) $ip);
|
$security->handleFailedLogin($user, $email, (string) $ip);
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
|
|||||||
@@ -26,9 +26,7 @@ class AuthSessionController extends Controller
|
|||||||
private ApplicationUrlService $urls,
|
private ApplicationUrlService $urls,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/** Returns login bootstrap state for the web portal. */
|
||||||
* CI `loginMask` — login page bootstrap / redirect when already authenticated.
|
|
||||||
*/
|
|
||||||
public function loginMask(Request $request): JsonResponse
|
public function loginMask(Request $request): JsonResponse
|
||||||
{
|
{
|
||||||
$redirectTo = $this->sessionAuth->sanitizeRedirectTarget(
|
$redirectTo = $this->sessionAuth->sanitizeRedirectTarget(
|
||||||
@@ -77,9 +75,7 @@ class AuthSessionController extends Controller
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Creates a web session from the submitted credentials. */
|
||||||
* CI `login` — POST /user/login.
|
|
||||||
*/
|
|
||||||
public function login(LoginSessionRequest $request): JsonResponse
|
public function login(LoginSessionRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$email = (string) $request->validated('email');
|
$email = (string) $request->validated('email');
|
||||||
@@ -116,7 +112,7 @@ class AuthSessionController extends Controller
|
|||||||
], 403);
|
], 403);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! ci_password_verify($password, (string) $user->password)) {
|
if (! verify_stored_password($password, (string) $user->password)) {
|
||||||
$this->security->handleFailedLogin($user, $email, $ip);
|
$this->security->handleFailedLogin($user, $email, $ip);
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
@@ -153,9 +149,7 @@ class AuthSessionController extends Controller
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Closes the current web session. */
|
||||||
* CI `logout` — GET /logout.
|
|
||||||
*/
|
|
||||||
public function logout(Request $request): JsonResponse
|
public function logout(Request $request): JsonResponse
|
||||||
{
|
{
|
||||||
$userId = Auth::guard('web')->id();
|
$userId = Auth::guard('web')->id();
|
||||||
@@ -174,9 +168,7 @@ class AuthSessionController extends Controller
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Returns the available post-login roles for the current user. */
|
||||||
* CI `selectRole` — GET /select-role.
|
|
||||||
*/
|
|
||||||
public function selectRole(Request $request): JsonResponse
|
public function selectRole(Request $request): JsonResponse
|
||||||
{
|
{
|
||||||
if (! Auth::guard('web')->check()) {
|
if (! Auth::guard('web')->check()) {
|
||||||
@@ -207,9 +199,7 @@ class AuthSessionController extends Controller
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Stores the selected post-login role in session state. */
|
||||||
* CI `setRole` — POST /set-role.
|
|
||||||
*/
|
|
||||||
public function setRole(SetRoleSessionRequest $request): JsonResponse
|
public function setRole(SetRoleSessionRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
if (! Auth::guard('web')->check()) {
|
if (! Auth::guard('web')->check()) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ namespace App\Http\Controllers\Api\Auth;
|
|||||||
|
|
||||||
use App\Http\Controllers\Api\Core\BaseApiController;
|
use App\Http\Controllers\Api\Core\BaseApiController;
|
||||||
use App\Http\Resources\Auth\RegisterResource;
|
use App\Http\Resources\Auth\RegisterResource;
|
||||||
use App\Services\Auth\CodeIgniterApiRegistrationService;
|
use App\Services\Auth\ApiRegistrationService;
|
||||||
use App\Services\Auth\RegistrationCaptchaService;
|
use App\Services\Auth\RegistrationCaptchaService;
|
||||||
use App\Services\Auth\RegistrationService;
|
use App\Services\Auth\RegistrationService;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
@@ -32,9 +32,9 @@ class RegisterController extends BaseApiController
|
|||||||
|
|
||||||
public function store(Request $request): JsonResponse
|
public function store(Request $request): JsonResponse
|
||||||
{
|
{
|
||||||
// CodeIgniter-style JSON register (POST api/v1/register): password + no captcha field.
|
// Support direct JSON registration when the SPA skips the captcha bootstrap step.
|
||||||
if (! $request->has('captcha') && $request->filled('password')) {
|
if (! $request->has('captcha') && $request->filled('password')) {
|
||||||
return app(CodeIgniterApiRegistrationService::class)->registerResponse($request);
|
return app(ApiRegistrationService::class)->registerResponse($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (app()->runningUnitTests() && $request->header('X-Debug-Request') === '1') {
|
if (app()->runningUnitTests() && $request->header('X-Debug-Request') === '1') {
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers\Api\Auth;
|
namespace App\Http\Controllers\Api\Auth;
|
||||||
|
|
||||||
use App\Config\SessionTimeout;
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Services\ApplicationUrlService;
|
use App\Services\ApplicationUrlService;
|
||||||
|
use App\Support\SessionTimeoutConfig;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
@@ -14,7 +14,7 @@ use Illuminate\Support\Facades\Auth;
|
|||||||
*/
|
*/
|
||||||
class SessionTimeoutController extends Controller
|
class SessionTimeoutController extends Controller
|
||||||
{
|
{
|
||||||
/** CI-compatible session key */
|
/** Shared session key for last-activity tracking. */
|
||||||
private const SESSION_KEY = 'last_activity';
|
private const SESSION_KEY = 'last_activity';
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
@@ -23,15 +23,15 @@ class SessionTimeoutController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CI nested routes: SessionController::getTimeoutConfig shape (URLs point at this app).
|
* Returns timeout metadata for the web portal.
|
||||||
*/
|
*/
|
||||||
public function getTimeoutConfig(): JsonResponse
|
public function getTimeoutConfig(): JsonResponse
|
||||||
{
|
{
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'success' => true,
|
'success' => true,
|
||||||
'timeout' => SessionTimeout::TIMEOUT_DURATION,
|
'timeout' => SessionTimeoutConfig::TIMEOUT_DURATION,
|
||||||
'warning_time' => SessionTimeout::WARNING_THRESHOLD,
|
'warning_time' => SessionTimeoutConfig::WARNING_THRESHOLD,
|
||||||
'check_interval' => SessionTimeout::CHECK_INTERVAL,
|
'check_interval' => SessionTimeoutConfig::CHECK_INTERVAL,
|
||||||
'logout_url' => $this->urls->webLogoutUrl(),
|
'logout_url' => $this->urls->webLogoutUrl(),
|
||||||
'keep_alive_url' => $this->urls->webSessionPingUrl(),
|
'keep_alive_url' => $this->urls->webSessionPingUrl(),
|
||||||
'check_url' => $this->urls->webSessionCheckTimeoutUrl(),
|
'check_url' => $this->urls->webSessionCheckTimeoutUrl(),
|
||||||
@@ -49,20 +49,20 @@ class SessionTimeoutController extends Controller
|
|||||||
$lastActivity = (int) $session->get(self::SESSION_KEY);
|
$lastActivity = (int) $session->get(self::SESSION_KEY);
|
||||||
$elapsed = time() - $lastActivity;
|
$elapsed = time() - $lastActivity;
|
||||||
|
|
||||||
if ($elapsed > SessionTimeout::TIMEOUT_DURATION) {
|
if ($elapsed > SessionTimeoutConfig::TIMEOUT_DURATION) {
|
||||||
return $this->expireSession($request);
|
return $this->expireSession($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($elapsed > SessionTimeout::WARNING_THRESHOLD) {
|
if ($elapsed > SessionTimeoutConfig::WARNING_THRESHOLD) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'status' => 'warning',
|
'status' => 'warning',
|
||||||
'time_remaining' => SessionTimeout::TIMEOUT_DURATION - $elapsed,
|
'time_remaining' => SessionTimeoutConfig::TIMEOUT_DURATION - $elapsed,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'status' => 'active',
|
'status' => 'active',
|
||||||
'time_remaining' => SessionTimeout::TIMEOUT_DURATION - $elapsed,
|
'time_remaining' => SessionTimeoutConfig::TIMEOUT_DURATION - $elapsed,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ class SessionTimeoutController extends Controller
|
|||||||
$session = $request->session();
|
$session = $request->session();
|
||||||
|
|
||||||
if (! $session->has(self::SESSION_KEY)
|
if (! $session->has(self::SESSION_KEY)
|
||||||
|| (time() - (int) $session->get(self::SESSION_KEY)) > SessionTimeout::TIMEOUT_DURATION) {
|
|| (time() - (int) $session->get(self::SESSION_KEY)) > SessionTimeoutConfig::TIMEOUT_DURATION) {
|
||||||
return $this->expireSession($request);
|
return $this->expireSession($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ class SessionTimeoutController extends Controller
|
|||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'status' => 'active',
|
'status' => 'active',
|
||||||
'time_remaining' => SessionTimeout::TIMEOUT_DURATION,
|
'time_remaining' => SessionTimeoutConfig::TIMEOUT_DURATION,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class BadgeScanController extends BaseApiController
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Public kiosk endpoint — POST JSON or form (legacy CI RFIDController::process).
|
* Public kiosk endpoint — POST JSON or form (legacy RFIDController::process).
|
||||||
*/
|
*/
|
||||||
public function scan(Request $request): JsonResponse
|
public function scan(Request $request): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -44,7 +44,7 @@ class BadgeScanController extends BaseApiController
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authenticated scan log listing (legacy CI RFIDController::log).
|
* Authenticated scan log listing (legacy RFIDController::log).
|
||||||
*/
|
*/
|
||||||
public function logs(): JsonResponse
|
public function logs(): JsonResponse
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,276 +2,8 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers\Api;
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Api\Core\BaseApiController as CoreBaseApiController;
|
||||||
use App\Http\Controllers\Api\CiRequestAdapter;
|
|
||||||
use App\Models\User;
|
|
||||||
use Illuminate\Contracts\Validation\Validator as ValidatorContract;
|
|
||||||
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
|
|
||||||
use Illuminate\Http\JsonResponse;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
use Illuminate\Support\Facades\Validator;
|
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
|
||||||
|
|
||||||
class BaseApiController extends Controller
|
class BaseApiController extends CoreBaseApiController
|
||||||
{
|
{
|
||||||
protected Request $laravelRequest;
|
|
||||||
protected CiRequestAdapter $request;
|
|
||||||
protected ValidatorContract|null $validator = null;
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
$this->laravelRequest = request();
|
|
||||||
$this->request = new CiRequestAdapter($this->laravelRequest);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function success($data = null, string $message = 'Success', int $code = Response::HTTP_OK): JsonResponse
|
|
||||||
{
|
|
||||||
return response()->json([
|
|
||||||
'status' => true,
|
|
||||||
'message' => $message,
|
|
||||||
'data' => $data,
|
|
||||||
], $code);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function error(string $message = 'An error occurred', int $code = Response::HTTP_BAD_REQUEST, ?array $errors = null): JsonResponse
|
|
||||||
{
|
|
||||||
$payload = [
|
|
||||||
'status' => false,
|
|
||||||
'message' => $message,
|
|
||||||
];
|
|
||||||
if (!empty($errors)) {
|
|
||||||
$payload['errors'] = $errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
return response()->json($payload, $code);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function respondSuccess($data = null, string $message = 'Success', int $code = Response::HTTP_OK): JsonResponse
|
|
||||||
{
|
|
||||||
return $this->success($data, $message, $code);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function respondCreated($data = null, string $message = 'Resource created successfully'): JsonResponse
|
|
||||||
{
|
|
||||||
return $this->success($data, $message, Response::HTTP_CREATED);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function respondDeleted($data = null, string $message = 'Resource deleted successfully'): JsonResponse
|
|
||||||
{
|
|
||||||
return $this->success($data, $message, Response::HTTP_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function respondError(string $message = 'An error occurred', int $code = Response::HTTP_BAD_REQUEST): JsonResponse
|
|
||||||
{
|
|
||||||
return $this->error($message, $code);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function respondValidationError(array $errors, string $message = 'Validation failed'): JsonResponse
|
|
||||||
{
|
|
||||||
return $this->error($message, Response::HTTP_UNPROCESSABLE_ENTITY, $errors);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function validateRequest(array $data, array $rules): array
|
|
||||||
{
|
|
||||||
$normalized = [];
|
|
||||||
foreach ($rules as $field => $ruleSet) {
|
|
||||||
$normalized[$field] = $this->normalizeRules($ruleSet);
|
|
||||||
}
|
|
||||||
|
|
||||||
$validator = Validator::make($data, $normalized);
|
|
||||||
$this->validator = $validator;
|
|
||||||
|
|
||||||
if ($validator->fails()) {
|
|
||||||
return $validator->errors()->toArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function validate(array $rules): bool
|
|
||||||
{
|
|
||||||
$payload = $this->payloadData();
|
|
||||||
$errors = $this->validateRequest($payload, $rules);
|
|
||||||
return empty($errors);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function payloadData(): array
|
|
||||||
{
|
|
||||||
$json = json_decode($this->laravelRequest->getContent() ?: '', true);
|
|
||||||
if (is_array($json)) {
|
|
||||||
return $json;
|
|
||||||
}
|
|
||||||
return array_merge($this->laravelRequest->query->all(), $this->laravelRequest->request->all());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function normalizeRules(array|string $ruleSet): array|string
|
|
||||||
{
|
|
||||||
if (is_array($ruleSet)) {
|
|
||||||
return $ruleSet;
|
|
||||||
}
|
|
||||||
$parts = explode('|', $ruleSet);
|
|
||||||
$result = [];
|
|
||||||
foreach ($parts as $part) {
|
|
||||||
$part = trim($part);
|
|
||||||
if ($part === '') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (preg_match('/^max_length\\[(\\d+)\\]$/', $part, $m)) {
|
|
||||||
$result[] = 'max:' . $m[1];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (preg_match('/^min_length\\[(\\d+)\\]$/', $part, $m)) {
|
|
||||||
$result[] = 'min:' . $m[1];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (preg_match('/^in_list\\[(.+)\\]$/', $part, $m)) {
|
|
||||||
$result[] = 'in:' . $m[1];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (preg_match('/^greater_than_equal_to\\[(.+)\\]$/', $part, $m)) {
|
|
||||||
$result[] = 'gte:' . $m[1];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (preg_match('/^less_than_equal_to\\[(.+)\\]$/', $part, $m)) {
|
|
||||||
$result[] = 'lte:' . $m[1];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (preg_match('/^valid_date\\[(.+)\\]$/', $part, $m)) {
|
|
||||||
$result[] = 'date_format:' . $m[1];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ($part === 'valid_email') {
|
|
||||||
$result[] = 'email';
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ($part === 'permit_empty') {
|
|
||||||
$result[] = 'nullable';
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (preg_match('/^is_unique\\[([^\\.]+)\\.([^\\]]+)\\]$/', $part, $m)) {
|
|
||||||
$result[] = 'unique:' . $m[1] . ',' . $m[2];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ($part === 'string') {
|
|
||||||
$result[] = 'string';
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ($part === 'integer') {
|
|
||||||
$result[] = 'integer';
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ($part === 'numeric') {
|
|
||||||
$result[] = 'numeric';
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ($part === 'required') {
|
|
||||||
$result[] = 'required';
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ($part === 'alpha_numeric') {
|
|
||||||
$result[] = 'alpha_num';
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ($part === 'in_array') {
|
|
||||||
$result[] = 'in_array';
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ($part === 'valid_url') {
|
|
||||||
$result[] = 'url';
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (strpos($part, 'max_size') === 0) {
|
|
||||||
$result[] = str_replace('max_size', 'max', $part);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$result[] = $part;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function paginate($source, int $page = 1, int $perPage = 20): array
|
|
||||||
{
|
|
||||||
$page = max(1, $page);
|
|
||||||
$perPage = max(1, $perPage);
|
|
||||||
$offset = ($page - 1) * $perPage;
|
|
||||||
|
|
||||||
if ($source instanceof EloquentBuilder || $source instanceof \Illuminate\Database\Query\Builder) {
|
|
||||||
$total = $source->toBase()->getCountForPagination();
|
|
||||||
$items = $source->offset($offset)->limit($perPage)->get()->toArray();
|
|
||||||
} elseif (is_array($source)) {
|
|
||||||
$total = count($source);
|
|
||||||
$items = array_slice($source, $offset, $perPage);
|
|
||||||
} else {
|
|
||||||
return [
|
|
||||||
'data' => [],
|
|
||||||
'pagination' => [
|
|
||||||
'current_page' => $page,
|
|
||||||
'per_page' => $perPage,
|
|
||||||
'total' => 0,
|
|
||||||
'total_pages' => 0,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
|
||||||
'data' => array_values($items),
|
|
||||||
'pagination' => [
|
|
||||||
'current_page' => $page,
|
|
||||||
'per_page' => $perPage,
|
|
||||||
'total' => $total,
|
|
||||||
'total_pages' => (int) ceil($total / $perPage),
|
|
||||||
],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getCurrentUserId(): ?int
|
|
||||||
{
|
|
||||||
$userId = (int) (auth()->id() ?? 0);
|
|
||||||
return $userId > 0 ? $userId : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getCurrentUser(): ?object
|
|
||||||
{
|
|
||||||
$userId = $this->getCurrentUserId();
|
|
||||||
if (!$userId) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$user = app(User::class);
|
|
||||||
$row = $user->find($userId);
|
|
||||||
if (!$row) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$name = trim(($row['firstname'] ?? '') . ' ' . ($row['lastname'] ?? ''));
|
|
||||||
if ($name === '') {
|
|
||||||
$name = $row['email'] ?? 'User #' . $userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$roles = DB::table('user_roles ur')
|
|
||||||
->select('LOWER(r.name) AS name')
|
|
||||||
->join('roles r', 'r.id', '=', 'ur.role_id')
|
|
||||||
->where('ur.user_id', $userId)
|
|
||||||
->whereNull('ur.deleted_at')
|
|
||||||
->pluck('name')
|
|
||||||
->map(fn($name) => strtolower((string) $name))
|
|
||||||
->unique()
|
|
||||||
->values()
|
|
||||||
->toArray();
|
|
||||||
} catch (\Throwable $e) {
|
|
||||||
Log::error('Unable to load user roles: ' . $e->getMessage());
|
|
||||||
$roles = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
return (object) [
|
|
||||||
'id' => (int) $userId,
|
|
||||||
'name' => $name,
|
|
||||||
'email' => $row['email'] ?? null,
|
|
||||||
'roles' => $roles,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,70 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers\Api;
|
|
||||||
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
class CiRequestAdapter
|
|
||||||
{
|
|
||||||
public function __construct(protected Request $request)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getGet(string $key = null, $default = null)
|
|
||||||
{
|
|
||||||
if ($key === null) {
|
|
||||||
return $this->request->query->all();
|
|
||||||
}
|
|
||||||
return $this->request->query->get($key, $default);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getPost(string $key = null, $default = null)
|
|
||||||
{
|
|
||||||
if ($key === null) {
|
|
||||||
return $this->request->request->all();
|
|
||||||
}
|
|
||||||
return $this->request->request->get($key, $default);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getJSON(bool $assoc = false)
|
|
||||||
{
|
|
||||||
$content = $this->request->getContent();
|
|
||||||
if ($content === '') {
|
|
||||||
return $assoc ? [] : null;
|
|
||||||
}
|
|
||||||
return json_decode($content, $assoc);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getVar(string $key, $default = null)
|
|
||||||
{
|
|
||||||
return $this->request->input($key, $default);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getHeader(string $key)
|
|
||||||
{
|
|
||||||
return $this->request->headers->get($key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getHeaderLine(string $key)
|
|
||||||
{
|
|
||||||
return $this->request->header($key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getFile(string $key)
|
|
||||||
{
|
|
||||||
return $this->request->file($key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getRawInput(): string
|
|
||||||
{
|
|
||||||
return $this->request->getContent();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function all(): array
|
|
||||||
{
|
|
||||||
return array_merge(
|
|
||||||
$this->request->query->all(),
|
|
||||||
$this->request->request->all(),
|
|
||||||
$this->request->json()->all()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -16,13 +16,11 @@ use Symfony\Component\HttpFoundation\Response;
|
|||||||
class BaseApiController extends Controller
|
class BaseApiController extends Controller
|
||||||
{
|
{
|
||||||
protected Request $laravelRequest;
|
protected Request $laravelRequest;
|
||||||
protected CiRequestAdapter $request;
|
|
||||||
protected ValidatorContract|null $validator = null;
|
protected ValidatorContract|null $validator = null;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->laravelRequest = request();
|
$this->laravelRequest = request();
|
||||||
$this->request = new CiRequestAdapter($this->laravelRequest);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function success($data = null, string $message = 'Success', int $code = Response::HTTP_OK): JsonResponse
|
protected function success($data = null, string $message = 'Success', int $code = Response::HTTP_OK): JsonResponse
|
||||||
|
|||||||
@@ -1,71 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers\Api\Core;
|
|
||||||
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
|
|
||||||
class CiRequestAdapter
|
|
||||||
{
|
|
||||||
public function __construct(protected Request $request)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getGet(string $key = null, $default = null)
|
|
||||||
{
|
|
||||||
if ($key === null) {
|
|
||||||
return $this->request->query->all();
|
|
||||||
}
|
|
||||||
return $this->request->query->get($key, $default);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getPost(string $key = null, $default = null)
|
|
||||||
{
|
|
||||||
if ($key === null) {
|
|
||||||
return $this->request->request->all();
|
|
||||||
}
|
|
||||||
return $this->request->request->get($key, $default);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getJSON(bool $assoc = false)
|
|
||||||
{
|
|
||||||
$content = $this->request->getContent();
|
|
||||||
if ($content === '') {
|
|
||||||
return $assoc ? [] : null;
|
|
||||||
}
|
|
||||||
return json_decode($content, $assoc);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getVar(string $key, $default = null)
|
|
||||||
{
|
|
||||||
return $this->request->input($key, $default);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getHeader(string $key)
|
|
||||||
{
|
|
||||||
return $this->request->headers->get($key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getHeaderLine(string $key)
|
|
||||||
{
|
|
||||||
return $this->request->header($key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getFile(string $key)
|
|
||||||
{
|
|
||||||
return $this->request->file($key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getRawInput(): string
|
|
||||||
{
|
|
||||||
return $this->request->getContent();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function all(): array
|
|
||||||
{
|
|
||||||
return array_merge(
|
|
||||||
$this->request->query->all(),
|
|
||||||
$this->request->request->all(),
|
|
||||||
$this->request->json()->all()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,25 +4,18 @@ namespace App\Http\Controllers\Api;
|
|||||||
|
|
||||||
use App\Http\Controllers\Api\BaseApiController;
|
use App\Http\Controllers\Api\BaseApiController;
|
||||||
use App\Models\Stats;
|
use App\Models\Stats;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
class StatsController extends BaseApiController
|
class StatsController extends BaseApiController
|
||||||
{
|
{
|
||||||
protected Stats $stats;
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
parent::__construct();
|
|
||||||
$this->stats = model(Stats::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$stats = $this->stats->findAll();
|
$stats = Stats::query()->get()->toArray();
|
||||||
return $this->success($stats, 'Statistics retrieved successfully');
|
return $this->success($stats, 'Statistics retrieved successfully');
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
log_message('error', 'Stats retrieval error: ' . $e->getMessage());
|
Log::error('Stats retrieval error: '.$e->getMessage());
|
||||||
return $this->respondError('Failed to retrieve statistics', Response::HTTP_INTERNAL_SERVER_ERROR);
|
return $this->respondError('Failed to retrieve statistics', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use Illuminate\Http\JsonResponse;
|
|||||||
|
|
||||||
class AccessDeniedController extends Controller
|
class AccessDeniedController extends Controller
|
||||||
{
|
{
|
||||||
/** CI route: GET /access_denied */
|
/** legacy route: GET /access_denied */
|
||||||
public function accessDenied(): JsonResponse
|
public function accessDenied(): JsonResponse
|
||||||
{
|
{
|
||||||
return response()->json([
|
return response()->json([
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class HealthController extends BaseApiController
|
|||||||
$payload = $this->service->check();
|
$payload = $this->service->check();
|
||||||
$status = $payload['ok'] ? Response::HTTP_OK : Response::HTTP_SERVICE_UNAVAILABLE;
|
$status = $payload['ok'] ? Response::HTTP_OK : Response::HTTP_SERVICE_UNAVAILABLE;
|
||||||
|
|
||||||
// CodeIgniter admin/API health returns a flat JSON body (no Laravel success envelope).
|
// legacy admin/API health returns a flat JSON body (no Laravel success envelope).
|
||||||
return response()->json($payload, $status);
|
return response()->json($payload, $status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,25 +4,18 @@ namespace App\Http\Controllers\Api\System;
|
|||||||
|
|
||||||
use App\Http\Controllers\Api\Core\BaseApiController;
|
use App\Http\Controllers\Api\Core\BaseApiController;
|
||||||
use App\Models\Stats;
|
use App\Models\Stats;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
class StatsController extends BaseApiController
|
class StatsController extends BaseApiController
|
||||||
{
|
{
|
||||||
protected Stats $stats;
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
parent::__construct();
|
|
||||||
$this->stats = model(Stats::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$stats = $this->stats->findAll();
|
$stats = Stats::query()->get()->toArray();
|
||||||
return $this->success($stats, 'Statistics retrieved successfully');
|
return $this->success($stats, 'Statistics retrieved successfully');
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
log_message('error', 'Stats retrieval error: ' . $e->getMessage());
|
Log::error('Stats retrieval error: '.$e->getMessage());
|
||||||
return $this->respondError('Failed to retrieve statistics', Response::HTTP_INTERNAL_SERVER_ERROR);
|
return $this->respondError('Failed to retrieve statistics', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use Illuminate\Support\Facades\Http;
|
|||||||
use Illuminate\Support\Facades\RateLimiter;
|
use Illuminate\Support\Facades\RateLimiter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CodeIgniter {@see \App\Controllers\ProofreadController} — LanguageTool proxy for grading UI.
|
* legacy {@see \App\Controllers\ProofreadController} — LanguageTool proxy for grading UI.
|
||||||
*/
|
*/
|
||||||
class ProofreadController extends Controller
|
class ProofreadController extends Controller
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use Illuminate\Http\Request;
|
|||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
/** Authenticated scan log listing — staff roles (legacy CI RFID log screen). */
|
/** Authenticated scan log listing — staff roles (legacy RFID log screen). */
|
||||||
class EnsureBadgeScanLogsAccess
|
class EnsureBadgeScanLogsAccess
|
||||||
{
|
{
|
||||||
public function handle(Request $request, Closure $next): Response
|
public function handle(Request $request, Closure $next): Response
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use Illuminate\Support\Facades\Auth;
|
|||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mirrors CodeIgniter route filter `auth:teacher,teacher_assistant` (+ elevated staff read).
|
* Mirrors legacy route filter `auth:teacher,teacher_assistant` (+ elevated staff read).
|
||||||
*/
|
*/
|
||||||
class EnsureClassProgressTeacherPortalAccess
|
class EnsureClassProgressTeacherPortalAccess
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use Illuminate\Support\Facades\Auth;
|
|||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CodeIgniter route filter `auth:parent`.
|
* legacy route filter `auth:parent`.
|
||||||
*
|
*
|
||||||
* Allows access for any caller that ultimately maps to a primary parent
|
* Allows access for any caller that ultimately maps to a primary parent
|
||||||
* record: the primary parent themselves (parent role / user_type=primary),
|
* record: the primary parent themselves (parent role / user_type=primary),
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use Illuminate\Support\Facades\Auth;
|
|||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CodeIgniter route filter `auth:admin` for print requests admin views
|
* legacy route filter `auth:admin` for print requests admin views
|
||||||
* (approximated via elevated staff roles; extend if you use permission-based gates).
|
* (approximated via elevated staff roles; extend if you use permission-based gates).
|
||||||
*/
|
*/
|
||||||
class EnsurePrintRequestsAdminAccess
|
class EnsurePrintRequestsAdminAccess
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use Illuminate\Http\Request;
|
|||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
/** CodeIgniter route filter `auth:teacher,teacher_assistant` for print requests. */
|
/** legacy route filter `auth:teacher,teacher_assistant` for print requests. */
|
||||||
class EnsurePrintRequestsTeacherAccess
|
class EnsurePrintRequestsTeacherAccess
|
||||||
{
|
{
|
||||||
public function handle(Request $request, Closure $next): Response
|
public function handle(Request $request, Closure $next): Response
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use PHPOpenSourceSaver\JWTAuth\Facades\JWTAuth;
|
|||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Session (web) auth first (CodeIgniter parity), then Sanctum / JWT like {@see MultiAuth}.
|
* Session (web) auth first (legacy parity), then Sanctum / JWT like {@see MultiAuth}.
|
||||||
*/
|
*/
|
||||||
class TeacherPortalAuthenticate
|
class TeacherPortalAuthenticate
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace App\Http\Requests\Admin;
|
|||||||
use Illuminate\Foundation\Http\FormRequest;
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mirrors CodeIgniter {@see \App\Controllers\Admin\CompetitionWinnersController::saveScores()} accepted fields.
|
* Mirrors legacy {@see \App\Controllers\Admin\CompetitionWinnersController::saveScores()} accepted fields.
|
||||||
*/
|
*/
|
||||||
class SaveCompetitionScoresRequest extends FormRequest
|
class SaveCompetitionScoresRequest extends FormRequest
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ namespace App\Http\Requests\Admin;
|
|||||||
|
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
/** Validation for creating a competition (CodeIgniter `CompetitionWinnersController::store`). */
|
/** Validation for creating a competition (legacy `CompetitionWinnersController::store`). */
|
||||||
class StoreCompetitionWinnerRequest extends FormRequest
|
class StoreCompetitionWinnerRequest extends FormRequest
|
||||||
{
|
{
|
||||||
public function authorize(): bool
|
public function authorize(): bool
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Requests\Admin;
|
namespace App\Http\Requests\Admin;
|
||||||
|
|
||||||
/** Validation for updating competition settings (CodeIgniter `CompetitionWinnersController::update`). */
|
/** Validation for updating competition settings (legacy `CompetitionWinnersController::update`). */
|
||||||
class UpdateCompetitionWinnerRequest extends StoreCompetitionWinnerRequest
|
class UpdateCompetitionWinnerRequest extends StoreCompetitionWinnerRequest
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class AdditionalCharge extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'additional_charges';
|
protected $table = 'additional_charges';
|
||||||
|
|
||||||
// CI useTimestamps = false
|
// legacy useTimestamps = false
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@@ -90,7 +90,7 @@ class AdditionalCharge extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
* CI methods equivalents
|
* legacy methods equivalents
|
||||||
* ========================= */
|
* ========================= */
|
||||||
|
|
||||||
public static function byParentTerm(int $parentId, string $year, string $sem, ?string $status = null)
|
public static function byParentTerm(int $parentId, string $year, string $sem, ?string $status = null)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ class AdminNotificationSubject extends BaseModel
|
|||||||
'updated_at',
|
'updated_at',
|
||||||
];
|
];
|
||||||
|
|
||||||
// CI uses created_at / updated_at
|
// legacy uses created_at / updated_at
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'admin_id' => 'integer',
|
'admin_id' => 'integer',
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class AttendanceCommentTemplate extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'attendance_comment_template';
|
protected $table = 'attendance_comment_template';
|
||||||
|
|
||||||
// CI: useTimestamps = false
|
// legacy: useTimestamps = false
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@@ -27,7 +27,7 @@ class AttendanceCommentTemplate extends BaseModel
|
|||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equivalent of CI getActiveTemplates():
|
* Equivalent of legacy getActiveTemplates():
|
||||||
* is_active=1, order by min_score DESC
|
* is_active=1, order by min_score DESC
|
||||||
*/
|
*/
|
||||||
public static function getActiveTemplates()
|
public static function getActiveTemplates()
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ class AttendanceData extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
* CI method equivalents
|
* legacy method equivalents
|
||||||
* ========================= */
|
* ========================= */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ class AttendanceDay extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'attendance_day';
|
protected $table = 'attendance_day';
|
||||||
|
|
||||||
// ✅ You are storing created_at / updated_at manually in CI (timestamps off there)
|
// ✅ You are storing created_at / updated_at manually in legacy (timestamps off there)
|
||||||
// User didn't explicitly ask to auto-manage here, so we keep it OFF to match CI.
|
// User didn't explicitly ask to auto-manage here, so we keep it OFF to match legacy.
|
||||||
// If you want auto-manage, tell me and I’ll flip it.
|
// If you want auto-manage, tell me and I’ll flip it.
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ class AttendanceDay extends BaseModel
|
|||||||
];
|
];
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
* CI method equivalents
|
* legacy method equivalents
|
||||||
* ========================= */
|
* ========================= */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class AttendanceRecord extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'attendance_record';
|
protected $table = 'attendance_record';
|
||||||
|
|
||||||
// ✅ CI uses created_at / updated_at
|
// ✅ legacy uses created_at / updated_at
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@@ -52,7 +52,7 @@ class AttendanceRecord extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
* CI method equivalents
|
* legacy method equivalents
|
||||||
* ========================= */
|
* ========================= */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -123,7 +123,7 @@ class AttendanceRecord extends BaseModel
|
|||||||
->where('school_year', $schoolYear)
|
->where('school_year', $schoolYear)
|
||||||
->update($update);
|
->update($update);
|
||||||
|
|
||||||
// If no record exists, return false (same idea as your CI code)
|
// If no record exists, return false (same idea as your legacy code)
|
||||||
return $affected > 0;
|
return $affected > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class AttendanceTracking extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'attendance_tracking';
|
protected $table = 'attendance_tracking';
|
||||||
|
|
||||||
// ✅ CI: useTimestamps = true (created_at/updated_at)
|
// ✅ legacy: useTimestamps = true (created_at/updated_at)
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@@ -27,7 +27,7 @@ class AttendanceTracking extends BaseModel
|
|||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'student_id' => 'integer',
|
'student_id' => 'integer',
|
||||||
'date' => 'datetime', // CI dateFormat = datetime
|
'date' => 'datetime', // legacy dateFormat = datetime
|
||||||
'is_reported' => 'integer',
|
'is_reported' => 'integer',
|
||||||
'is_notified' => 'integer',
|
'is_notified' => 'integer',
|
||||||
'notif_counter' => 'integer',
|
'notif_counter' => 'integer',
|
||||||
@@ -245,7 +245,7 @@ class AttendanceTracking extends BaseModel
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* TRUE if at least $absencesThreshold absences in the last $weeksStreak weeks.
|
* TRUE if at least $absencesThreshold absences in the last $weeksStreak weeks.
|
||||||
* (Mirrors your CI behavior: count of last N fetched records)
|
* (Mirrors your legacy behavior: count of last N fetched records)
|
||||||
*/
|
*/
|
||||||
public static function checkAbsencesInStreak(
|
public static function checkAbsencesInStreak(
|
||||||
int $studentId,
|
int $studentId,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class BadgePrintLog extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'badge_print_logs';
|
protected $table = 'badge_print_logs';
|
||||||
|
|
||||||
// CI: useTimestamps = false
|
// legacy: useTimestamps = false
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@@ -71,7 +71,7 @@ class BadgePrintLog extends BaseModel
|
|||||||
if (empty($rows)) return 0;
|
if (empty($rows)) return 0;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// insert returns bool; we return count best-effort like CI
|
// insert returns bool; we return count best-effort like legacy
|
||||||
DB::table((new static)->getTable())->insert($rows);
|
DB::table((new static)->getTable())->insert($rows);
|
||||||
return count($rows);
|
return count($rows);
|
||||||
} catch (QueryException $e) {
|
} catch (QueryException $e) {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class CalendarEvent extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'calendar_events';
|
protected $table = 'calendar_events';
|
||||||
|
|
||||||
// ✅ CI uses created_at / updated_at
|
// ✅ legacy uses created_at / updated_at
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@@ -42,7 +42,7 @@ class CalendarEvent extends BaseModel
|
|||||||
private static ?bool $hasEventTypeColumn = null;
|
private static ?bool $hasEventTypeColumn = null;
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
* CI method equivalents
|
* legacy method equivalents
|
||||||
* ========================= */
|
* ========================= */
|
||||||
|
|
||||||
public static function getEvents()
|
public static function getEvents()
|
||||||
@@ -96,7 +96,7 @@ class CalendarEvent extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
* Helpers (ported from CI)
|
* Helpers (ported from legacy)
|
||||||
* ========================= */
|
* ========================= */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,82 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Connection;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
|
|
||||||
class CiDatabase
|
|
||||||
{
|
|
||||||
protected static ?self $instance = null;
|
|
||||||
|
|
||||||
protected Connection $connection;
|
|
||||||
protected int $lastAffectedRows = 0;
|
|
||||||
|
|
||||||
public static function instance(): self
|
|
||||||
{
|
|
||||||
return static::$instance ??= new static();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function __construct()
|
|
||||||
{
|
|
||||||
$this->connection = DB::connection();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function table(string $table): CiQueryBuilder
|
|
||||||
{
|
|
||||||
$normalized = $this->normalizeTableName($table);
|
|
||||||
return new CiQueryBuilder($this->connection->table($normalized));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function query(string $sql, array $params = []): CiQueryResult
|
|
||||||
{
|
|
||||||
$trimmed = ltrim($sql);
|
|
||||||
if ($trimmed === '') {
|
|
||||||
return new CiQueryResult([]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$first = strtolower(strtok($trimmed, " \t\n\r\0\x0B") ?: '');
|
|
||||||
|
|
||||||
if ($first === 'select') {
|
|
||||||
$rows = $this->connection->select($sql, $params);
|
|
||||||
$this->lastAffectedRows = 0;
|
|
||||||
return new CiQueryResult($rows);
|
|
||||||
}
|
|
||||||
|
|
||||||
$affected = $this->connection->affectingStatement($sql, $params);
|
|
||||||
$this->lastAffectedRows = $affected;
|
|
||||||
|
|
||||||
return new CiQueryResult([]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function escape($value): string
|
|
||||||
{
|
|
||||||
return $this->connection->getPdo()->quote($value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function affectedRows(): int
|
|
||||||
{
|
|
||||||
return $this->lastAffectedRows;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getFieldNames(string $table): array
|
|
||||||
{
|
|
||||||
return $this->connection->getSchemaBuilder()->getColumnListing($table);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function normalizeTableName(string $table): string
|
|
||||||
{
|
|
||||||
$normalized = trim($table);
|
|
||||||
|
|
||||||
if (stripos($normalized, ' as ') !== false) {
|
|
||||||
return $normalized;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strpos($normalized, ' ') !== false) {
|
|
||||||
[$name, $alias] = preg_split('/\s+/', $normalized, 2);
|
|
||||||
return "{$name} as {$alias}";
|
|
||||||
}
|
|
||||||
|
|
||||||
return $normalized;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
|
||||||
|
|
||||||
class CiModelBuilder extends Builder
|
|
||||||
{
|
|
||||||
protected array $setData = [];
|
|
||||||
|
|
||||||
public function get($columns = ['*'])
|
|
||||||
{
|
|
||||||
return new CiQueryResult(parent::get($columns));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function first($columns = ['*'])
|
|
||||||
{
|
|
||||||
$model = parent::first($columns);
|
|
||||||
return $model;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function findAll(int $limit = 0, int $offset = 0)
|
|
||||||
{
|
|
||||||
if ($limit > 0) {
|
|
||||||
$this->limit($limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($offset > 0) {
|
|
||||||
$this->offset($offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->getResultArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getResultArray(): array
|
|
||||||
{
|
|
||||||
return $this->get()->getResultArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getRowArray(): ?array
|
|
||||||
{
|
|
||||||
return $this->get()->getRowArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getRow(?string $column = null)
|
|
||||||
{
|
|
||||||
return $this->get()->getRow($column);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function countAllResults(): int
|
|
||||||
{
|
|
||||||
return $this->count();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function like(string $column, $match, string $side = 'both')
|
|
||||||
{
|
|
||||||
$pattern = $this->wrapLike($match, $side);
|
|
||||||
$this->query->where($column, 'like', $pattern);
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function set($key, $value = null, bool $escape = true)
|
|
||||||
{
|
|
||||||
if (is_array($key)) {
|
|
||||||
$this->setData = array_merge($this->setData, $key);
|
|
||||||
} else {
|
|
||||||
$this->setData[$key] = $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function update(array $values = [])
|
|
||||||
{
|
|
||||||
$data = $values ?: $this->setData;
|
|
||||||
$this->setData = [];
|
|
||||||
|
|
||||||
return parent::update($data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function where($column, $operator = null, $value = null, $boolean = 'and')
|
|
||||||
{
|
|
||||||
if ($operator !== null && $value === null && preg_match('/^(.*)\\s(>=|<=|<>|!=|>|<)$/', $column, $matches)) {
|
|
||||||
return parent::where(trim($matches[1]), $matches[2], $operator, $boolean);
|
|
||||||
}
|
|
||||||
|
|
||||||
return parent::where($column, $operator, $value, $boolean);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function wrapLike($match, string $side): string
|
|
||||||
{
|
|
||||||
$pattern = "%{$match}%";
|
|
||||||
|
|
||||||
switch (strtolower($side)) {
|
|
||||||
case 'before':
|
|
||||||
$pattern = "%{$match}";
|
|
||||||
break;
|
|
||||||
case 'after':
|
|
||||||
$pattern = "{$match}%";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $pattern;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,153 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Query\Builder as QueryBuilder;
|
|
||||||
|
|
||||||
class CiQueryBuilder
|
|
||||||
{
|
|
||||||
protected QueryBuilder $builder;
|
|
||||||
protected array $setData = [];
|
|
||||||
|
|
||||||
protected array $tableMethods = [
|
|
||||||
'join',
|
|
||||||
'leftJoin',
|
|
||||||
'rightJoin',
|
|
||||||
'crossJoin',
|
|
||||||
'from',
|
|
||||||
'table',
|
|
||||||
'joinWhere',
|
|
||||||
'leftJoinWhere',
|
|
||||||
];
|
|
||||||
|
|
||||||
public function __construct(QueryBuilder $builder)
|
|
||||||
{
|
|
||||||
$this->builder = $builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __call($method, $arguments)
|
|
||||||
{
|
|
||||||
$arguments = $this->normalizeTableArgument($method, $arguments);
|
|
||||||
$result = $this->builder->$method(...$arguments);
|
|
||||||
|
|
||||||
if ($result instanceof QueryBuilder) {
|
|
||||||
$this->builder = $result;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function where($column, $operator = null, $value = null, $boolean = 'and')
|
|
||||||
{
|
|
||||||
if ($operator !== null && $value === null && preg_match('/^(.*)\s(>=|<=|<>|!=|>|<)$/', $column, $matches)) {
|
|
||||||
return $this->where(trim($matches[1]), $matches[2], $operator, $boolean);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->builder = $this->builder->where($column, $operator, $value, $boolean);
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function like($column, $match, string $side = 'both')
|
|
||||||
{
|
|
||||||
$pattern = $this->wrapLike($match, $side);
|
|
||||||
$this->builder = $this->builder->where($column, 'like', $pattern);
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function set($key, $value = null, bool $escape = true)
|
|
||||||
{
|
|
||||||
if (is_array($key)) {
|
|
||||||
$this->setData = array_merge($this->setData, $key);
|
|
||||||
} else {
|
|
||||||
$this->setData[$key] = $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function update($values = [])
|
|
||||||
{
|
|
||||||
$data = $values ?: $this->setData;
|
|
||||||
$this->setData = [];
|
|
||||||
return $this->builder->update($data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function findAll(int $limit = 0, int $offset = 0)
|
|
||||||
{
|
|
||||||
if ($limit > 0) {
|
|
||||||
$this->builder = $this->builder->limit($limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($offset > 0) {
|
|
||||||
$this->builder = $this->builder->offset($offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->getResultArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function get($columns = ['*'])
|
|
||||||
{
|
|
||||||
$collection = $this->builder->get($columns);
|
|
||||||
return new CiQueryResult($collection);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getResultArray(): array
|
|
||||||
{
|
|
||||||
return $this->get()->getResultArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getRowArray(): ?array
|
|
||||||
{
|
|
||||||
return $this->get()->getRowArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getRow(?string $column = null)
|
|
||||||
{
|
|
||||||
return $this->get()->getRow($column);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function countAllResults(): int
|
|
||||||
{
|
|
||||||
return $this->builder->count();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function wrapLike($match, string $side): string
|
|
||||||
{
|
|
||||||
$pattern = "%{$match}%";
|
|
||||||
|
|
||||||
switch (strtolower($side)) {
|
|
||||||
case 'before':
|
|
||||||
return "%{$match}";
|
|
||||||
case 'after':
|
|
||||||
return "{$match}%";
|
|
||||||
default:
|
|
||||||
return $pattern;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function normalizeTableArgument(string $method, array $arguments): array
|
|
||||||
{
|
|
||||||
if (in_array($method, $this->tableMethods, true) && isset($arguments[0]) && is_string($arguments[0])) {
|
|
||||||
$arguments[0] = $this->normalizeTableName($arguments[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $arguments;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function normalizeTableName(string $table): string
|
|
||||||
{
|
|
||||||
$normalized = trim($table);
|
|
||||||
|
|
||||||
if (stripos($normalized, ' as ') !== false) {
|
|
||||||
return $normalized;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strpos($normalized, ' ') !== false) {
|
|
||||||
[$name, $alias] = preg_split('/\s+/', $normalized, 2);
|
|
||||||
return "{$name} as {$alias}";
|
|
||||||
}
|
|
||||||
|
|
||||||
return $normalized;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use App\Models\BaseModel;
|
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
|
|
||||||
class CiQueryResult extends Collection
|
|
||||||
{
|
|
||||||
public function __construct($items = [])
|
|
||||||
{
|
|
||||||
if ($items instanceof Collection) {
|
|
||||||
$items = $items->all();
|
|
||||||
}
|
|
||||||
|
|
||||||
parent::__construct(array_map([$this, 'castRow'], (array) $items));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function castRow($row): array
|
|
||||||
{
|
|
||||||
if ($row instanceof Model) {
|
|
||||||
return $row->toArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_object($row)) {
|
|
||||||
return (array) $row;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (array) $row;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getResultArray(): array
|
|
||||||
{
|
|
||||||
return $this->toArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getRowArray(): ?array
|
|
||||||
{
|
|
||||||
$first = $this->first();
|
|
||||||
return $first ? (array) $first : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getRow(?string $column = null)
|
|
||||||
{
|
|
||||||
$row = $this->getRowArray();
|
|
||||||
if ($row === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($column === null) {
|
|
||||||
return $row;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $row[$column] ?? null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -8,7 +8,7 @@ class ClassPrepAdjustment extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'class_prep_adjustments';
|
protected $table = 'class_prep_adjustments';
|
||||||
|
|
||||||
// CI model didn't use timestamps; keep off unless your table has updated_at/created_at auto-managed.
|
// legacy model didn't use timestamps; keep off unless your table has updated_at/created_at auto-managed.
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class ClassPreparationLog extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'class_preparation_log';
|
protected $table = 'class_preparation_log';
|
||||||
|
|
||||||
// CI: useTimestamps = false
|
// legacy: useTimestamps = false
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class ClassProgressAttachment extends BaseModel
|
|||||||
use HasFactory;
|
use HasFactory;
|
||||||
protected $table = 'class_progress_attachments';
|
protected $table = 'class_progress_attachments';
|
||||||
|
|
||||||
// CI: useTimestamps = false
|
// legacy: useTimestamps = false
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class ClassProgressReport extends BaseModel
|
|||||||
use HasFactory;
|
use HasFactory;
|
||||||
protected $table = 'class_progress_reports';
|
protected $table = 'class_progress_reports';
|
||||||
|
|
||||||
// ✅ CI: useTimestamps = true (created_at/updated_at)
|
// ✅ legacy: useTimestamps = true (created_at/updated_at)
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ use Illuminate\Support\Facades\DB;
|
|||||||
class ClassSection extends BaseModel
|
class ClassSection extends BaseModel
|
||||||
{
|
{
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
// CI table name is "classSection"
|
// legacy table name is "classSection"
|
||||||
protected $table = 'classSection';
|
protected $table = 'classSection';
|
||||||
|
|
||||||
// ✅ CI: useTimestamps = true
|
// ✅ legacy: useTimestamps = true
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@@ -48,11 +48,11 @@ class ClassSection extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
* CI method equivalents
|
* legacy method equivalents
|
||||||
* ========================= */
|
* ========================= */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get class sections with class name (like CI join result).
|
* Get class sections with class name (like legacy join result).
|
||||||
* Returns array of rows: class_section_id, class_section_name, class_name
|
* Returns array of rows: class_section_id, class_section_name, class_name
|
||||||
*/
|
*/
|
||||||
public static function getClassSections(): array
|
public static function getClassSections(): array
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class CommunicationLog extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'communication_logs';
|
protected $table = 'communication_logs';
|
||||||
|
|
||||||
// CI model didn't enable timestamps; keep off unless your table has created_at/updated_at.
|
// legacy model didn't enable timestamps; keep off unless your table has created_at/updated_at.
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ class Competition extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'competitions';
|
protected $table = 'competitions';
|
||||||
|
|
||||||
// ✅ CI: useSoftDeletes = true
|
// ✅ legacy: useSoftDeletes = true
|
||||||
use SoftDeletes;
|
use SoftDeletes;
|
||||||
|
|
||||||
// ✅ CI: useTimestamps = true (created_at/updated_at) + deleted_at for soft deletes
|
// ✅ legacy: useTimestamps = true (created_at/updated_at) + deleted_at for soft deletes
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class CompetitionClassWinner extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'competition_class_winners';
|
protected $table = 'competition_class_winners';
|
||||||
|
|
||||||
// ✅ CI: useTimestamps = true (created_at/updated_at)
|
// ✅ legacy: useTimestamps = true (created_at/updated_at)
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class CompetitionScore extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'competition_scores';
|
protected $table = 'competition_scores';
|
||||||
|
|
||||||
// ✅ CI: useTimestamps = true (created_at/updated_at)
|
// ✅ legacy: useTimestamps = true (created_at/updated_at)
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class CompetitionWinner extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'competition_winners';
|
protected $table = 'competition_winners';
|
||||||
|
|
||||||
// CI: useTimestamps = false
|
// legacy: useTimestamps = false
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class Configuration extends BaseModel
|
|||||||
];
|
];
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
* CI method equivalents
|
* legacy method equivalents
|
||||||
* ========================= */
|
* ========================= */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -94,7 +94,7 @@ class Configuration extends BaseModel
|
|||||||
* Backward-compatible helper (keeps your "semester" special-case).
|
* Backward-compatible helper (keeps your "semester" special-case).
|
||||||
*
|
*
|
||||||
* NOTE: In Laravel it’s better to call SemesterRangeService directly from services/controllers,
|
* NOTE: In Laravel it’s better to call SemesterRangeService directly from services/controllers,
|
||||||
* but this keeps behavior consistent with the CI model.
|
* but this keeps behavior consistent with the legacy model.
|
||||||
*/
|
*/
|
||||||
public static function getConfig(string $key): ?string
|
public static function getConfig(string $key): ?string
|
||||||
{
|
{
|
||||||
@@ -103,7 +103,7 @@ class Configuration extends BaseModel
|
|||||||
if ($key === 'semester') {
|
if ($key === 'semester') {
|
||||||
try {
|
try {
|
||||||
// If you have this service in Laravel, inject/resolve it from container.
|
// If you have this service in Laravel, inject/resolve it from container.
|
||||||
// This call assumes the service constructor can accept Configuration model (like CI did).
|
// This call assumes the service constructor can accept Configuration model (like legacy did).
|
||||||
$semester = app(\App\Services\SemesterRangeService::class)->getSemesterForDate();
|
$semester = app(\App\Services\SemesterRangeService::class)->getSemesterForDate();
|
||||||
if (is_string($semester) && $semester !== '') {
|
if (is_string($semester) && $semester !== '') {
|
||||||
return $semester;
|
return $semester;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class ContactUs extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'contactus';
|
protected $table = 'contactus';
|
||||||
|
|
||||||
// ✅ CI: useTimestamps = true (created_at/updated_at)
|
// ✅ legacy: useTimestamps = true (created_at/updated_at)
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@@ -39,7 +39,7 @@ class ContactUs extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
* CI method equivalents
|
* legacy method equivalents
|
||||||
* ========================= */
|
* ========================= */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class CurrentFlag extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'current_flag';
|
protected $table = 'current_flag';
|
||||||
|
|
||||||
// CI model didn't specify timestamps. Since the table has created_at/updated_at columns,
|
// legacy model didn't specify timestamps. Since the table has created_at/updated_at columns,
|
||||||
// you can enable auto-management. If your table does NOT actually have them, set false.
|
// you can enable auto-management. If your table does NOT actually have them, set false.
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class DiscountUsage extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'discount_usages';
|
protected $table = 'discount_usages';
|
||||||
|
|
||||||
// ✅ CI: timestamps enabled (created_at / updated_at)
|
// ✅ legacy: timestamps enabled (created_at / updated_at)
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@@ -44,7 +44,7 @@ class DiscountUsage extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equivalent of CI getTotalDiscountByParentIdAndSchoolYear()
|
* Equivalent of legacy getTotalDiscountByParentIdAndSchoolYear()
|
||||||
*/
|
*/
|
||||||
public static function getTotalDiscountByParentIdAndSchoolYear(int $parentId, string $schoolYear): float
|
public static function getTotalDiscountByParentIdAndSchoolYear(int $parentId, string $schoolYear): float
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class DiscountVoucher extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'discount_vouchers';
|
protected $table = 'discount_vouchers';
|
||||||
|
|
||||||
// ✅ CI manages created_at / updated_at
|
// ✅ legacy manages created_at / updated_at
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@@ -39,7 +39,7 @@ class DiscountVoucher extends BaseModel
|
|||||||
];
|
];
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
* Model hooks (CI beforeInsert/beforeUpdate equivalents)
|
* Model hooks (legacy beforeInsert/beforeUpdate equivalents)
|
||||||
* ========================= */
|
* ========================= */
|
||||||
|
|
||||||
protected static function booted(): void
|
protected static function booted(): void
|
||||||
@@ -95,7 +95,7 @@ class DiscountVoucher extends BaseModel
|
|||||||
$until = Carbon::parse($this->valid_until)->toDateString();
|
$until = Carbon::parse($this->valid_until)->toDateString();
|
||||||
if ($from > $until) {
|
if ($from > $until) {
|
||||||
// In Laravel, prefer validating in FormRequest.
|
// In Laravel, prefer validating in FormRequest.
|
||||||
// This keeps your CI behavior by failing the save.
|
// This keeps your legacy behavior by failing the save.
|
||||||
throw new \InvalidArgumentException('Valid Until must be the same as or after Valid From.');
|
throw new \InvalidArgumentException('Valid Until must be the same as or after Valid From.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -108,7 +108,7 @@ class DiscountVoucher extends BaseModel
|
|||||||
/**
|
/**
|
||||||
* Find a valid voucher for a student (not expired, active, under max uses, and not used by the student).
|
* Find a valid voucher for a student (not expired, active, under max uses, and not used by the student).
|
||||||
*
|
*
|
||||||
* NOTE: Your CI joins discount_usages on u.student_id. That requires discount_usages.student_id to exist.
|
* NOTE: Your legacy joins discount_usages on u.student_id. That requires discount_usages.student_id to exist.
|
||||||
* If your discount_usages table does NOT have student_id (some of your other code uses parent_id),
|
* If your discount_usages table does NOT have student_id (some of your other code uses parent_id),
|
||||||
* switch the filter to parent_id instead.
|
* switch the filter to parent_id instead.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class EarlyDismissalSignature extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'early_dismissal_signatures';
|
protected $table = 'early_dismissal_signatures';
|
||||||
|
|
||||||
// ✅ CI: timestamps enabled (created_at/updated_at)
|
// ✅ legacy: timestamps enabled (created_at/updated_at)
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@@ -23,7 +23,7 @@ class EarlyDismissalSignature extends BaseModel
|
|||||||
];
|
];
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
// report_date is stored as Y-m-d in CI validation; keep as date
|
// report_date is stored as Y-m-d in legacy validation; keep as date
|
||||||
'report_date' => 'date',
|
'report_date' => 'date',
|
||||||
|
|
||||||
'file_size' => 'integer',
|
'file_size' => 'integer',
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class EmailTemplate extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'email_templates';
|
protected $table = 'email_templates';
|
||||||
|
|
||||||
// CI model didn't specify timestamps; keep off unless your table has created_at/updated_at.
|
// legacy model didn't specify timestamps; keep off unless your table has created_at/updated_at.
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@@ -40,7 +40,7 @@ class EmailTemplate extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equivalent of CI getActiveTemplates():
|
* Equivalent of legacy getActiveTemplates():
|
||||||
* is_active=1, orderBy template_key ASC
|
* is_active=1, orderBy template_key ASC
|
||||||
*/
|
*/
|
||||||
public static function getActiveTemplates()
|
public static function getActiveTemplates()
|
||||||
@@ -52,7 +52,7 @@ class EmailTemplate extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equivalent of CI findByKey():
|
* Equivalent of legacy findByKey():
|
||||||
* template_key = $key AND is_active=1
|
* template_key = $key AND is_active=1
|
||||||
*/
|
*/
|
||||||
public static function findByKey(string $key): ?self
|
public static function findByKey(string $key): ?self
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class EmergencyContact extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'emergency_contacts';
|
protected $table = 'emergency_contacts';
|
||||||
|
|
||||||
// ✅ CI: useTimestamps = true (created_at/updated_at)
|
// ✅ legacy: useTimestamps = true (created_at/updated_at)
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@@ -46,7 +46,7 @@ class EmergencyContact extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
* CI method equivalents
|
* legacy method equivalents
|
||||||
* ========================= */
|
* ========================= */
|
||||||
|
|
||||||
public static function getEmergencyContactsByStudentId(int $studentId)
|
public static function getEmergencyContactsByStudentId(int $studentId)
|
||||||
@@ -64,7 +64,7 @@ class EmergencyContact extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Your CI logic: (student_id = $studentId) OR (parent_id = $studentId)
|
* Your legacy logic: (student_id = $studentId) OR (parent_id = $studentId)
|
||||||
* Keeping it exactly as-is, even though the 2nd condition looks unusual.
|
* Keeping it exactly as-is, even though the 2nd condition looks unusual.
|
||||||
*/
|
*/
|
||||||
public static function getAllEmergencyContacts(int $studentId)
|
public static function getAllEmergencyContacts(int $studentId)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class Enrollment extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'enrollments';
|
protected $table = 'enrollments';
|
||||||
|
|
||||||
// ✅ CI: useTimestamps = true
|
// ✅ legacy: useTimestamps = true
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@@ -55,7 +55,7 @@ class Enrollment extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
* CI method equivalents
|
* legacy method equivalents
|
||||||
* ========================= */
|
* ========================= */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class Event extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'events';
|
protected $table = 'events';
|
||||||
|
|
||||||
// ✅ CI: timestamps enabled (created_at/updated_at)
|
// ✅ legacy: timestamps enabled (created_at/updated_at)
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@@ -43,7 +43,7 @@ class Event extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
* CI method equivalents
|
* legacy method equivalents
|
||||||
* ========================= */
|
* ========================= */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class EventCharges extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'event_charges';
|
protected $table = 'event_charges';
|
||||||
|
|
||||||
// ✅ CI: useTimestamps = true (created_at/updated_at)
|
// ✅ legacy: useTimestamps = true (created_at/updated_at)
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@@ -66,7 +66,7 @@ class EventCharges extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equivalent of CI getChargesWithEventInfo()
|
* Equivalent of legacy getChargesWithEventInfo()
|
||||||
* Returns rows with: event_charges.*, events.event_name, events.amount
|
* Returns rows with: event_charges.*, events.event_name, events.amount
|
||||||
*/
|
*/
|
||||||
public static function getChargesWithEventInfo(?int $parentId = null, ?string $schoolYear = null, ?string $semester = null): array
|
public static function getChargesWithEventInfo(?int $parentId = null, ?string $schoolYear = null, ?string $semester = null): array
|
||||||
|
|||||||
+1
-1
@@ -9,7 +9,7 @@ class Exam extends BaseModel
|
|||||||
protected $table = 'exams';
|
protected $table = 'exams';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Your CI model only uses created_at (updatedField = '').
|
* Your legacy model only uses created_at (updatedField = '').
|
||||||
* In Laravel, easiest is to disable timestamps and manage created_at yourself OR
|
* In Laravel, easiest is to disable timestamps and manage created_at yourself OR
|
||||||
* enable timestamps but disable UPDATED_AT.
|
* enable timestamps but disable UPDATED_AT.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class ExamDraft extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'exam_drafts';
|
protected $table = 'exam_drafts';
|
||||||
|
|
||||||
// ✅ CI: useTimestamps = true (created_at/updated_at)
|
// ✅ legacy: useTimestamps = true (created_at/updated_at)
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@@ -55,7 +55,7 @@ class ExamDraft extends BaseModel
|
|||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CI had updateOnlyChanged=false (force updates even if nothing changed).
|
* legacy had updateOnlyChanged=false (force updates even if nothing changed).
|
||||||
* In Laravel, you can force a save by calling:
|
* In Laravel, you can force a save by calling:
|
||||||
* $model->touch(); // updates updated_at only
|
* $model->touch(); // updates updated_at only
|
||||||
* or
|
* or
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class Expense extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'expenses';
|
protected $table = 'expenses';
|
||||||
|
|
||||||
// ✅ CI: useTimestamps = true (created_at/updated_at)
|
// ✅ legacy: useTimestamps = true (created_at/updated_at)
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class Family extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'families';
|
protected $table = 'families';
|
||||||
|
|
||||||
// CI model didn't specify timestamps
|
// legacy model didn't specify timestamps
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class FamilyCommPref extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'family_comm_prefs';
|
protected $table = 'family_comm_prefs';
|
||||||
|
|
||||||
// CI model didn't specify timestamps
|
// legacy model didn't specify timestamps
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class FamilyGuardian extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'family_guardians';
|
protected $table = 'family_guardians';
|
||||||
|
|
||||||
// CI model didn't specify timestamps
|
// legacy model didn't specify timestamps
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class FamilyStudent extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'family_students';
|
protected $table = 'family_students';
|
||||||
|
|
||||||
// CI model didn't specify timestamps
|
// legacy model didn't specify timestamps
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@@ -37,7 +37,7 @@ class FamilyStudent extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Laravel equivalent of CI getFamiliesForStudent().
|
* Laravel equivalent of legacy getFamiliesForStudent().
|
||||||
* Returns array rows: families.* + is_primary_home
|
* Returns array rows: families.* + is_primary_home
|
||||||
*/
|
*/
|
||||||
public static function getFamiliesForStudent(int $studentId): array
|
public static function getFamiliesForStudent(int $studentId): array
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class FinalExam extends BaseModel
|
|||||||
protected $table = 'final_exam';
|
protected $table = 'final_exam';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CI: useTimestamps = false (even though table has created_at/updated_at fields).
|
* legacy: useTimestamps = false (even though table has created_at/updated_at fields).
|
||||||
* So we keep timestamps OFF and you can set created_at/updated_at manually if needed.
|
* So we keep timestamps OFF and you can set created_at/updated_at manually if needed.
|
||||||
*/
|
*/
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
@@ -52,7 +52,7 @@ class FinalExam extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equivalent of CI getFinalExamScore()
|
* Equivalent of legacy getFinalExamScore()
|
||||||
*/
|
*/
|
||||||
public static function getFinalExamScore(
|
public static function getFinalExamScore(
|
||||||
int $studentId,
|
int $studentId,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class FinalScore extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'final_score';
|
protected $table = 'final_score';
|
||||||
|
|
||||||
// CI model didn't specify timestamps behavior; table includes created_at/updated_at.
|
// legacy model didn't specify timestamps behavior; table includes created_at/updated_at.
|
||||||
// If you want Laravel to auto-manage them, keep true (recommended).
|
// If you want Laravel to auto-manage them, keep true (recommended).
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ class FinalScore extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equivalent of CI getFinalExamScore()
|
* Equivalent of legacy getFinalExamScore()
|
||||||
*/
|
*/
|
||||||
public static function getFinalExamScore(int $studentId, string $semester, string $schoolYear)
|
public static function getFinalExamScore(int $studentId, string $semester, string $schoolYear)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class GradingLock extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'grading_locks';
|
protected $table = 'grading_locks';
|
||||||
|
|
||||||
// ✅ CI: useTimestamps = true
|
// ✅ legacy: useTimestamps = true
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@@ -41,7 +41,7 @@ class GradingLock extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equivalent of CI getLock()
|
* Equivalent of legacy getLock()
|
||||||
*/
|
*/
|
||||||
public static function getLock(int $classSectionId, string $semester, string $schoolYear): ?self
|
public static function getLock(int $classSectionId, string $semester, string $schoolYear): ?self
|
||||||
{
|
{
|
||||||
@@ -58,7 +58,7 @@ class GradingLock extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equivalent of CI isLocked()
|
* Equivalent of legacy isLocked()
|
||||||
*/
|
*/
|
||||||
public static function isLocked(int $classSectionId, string $semester, string $schoolYear): bool
|
public static function isLocked(int $classSectionId, string $semester, string $schoolYear): bool
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class Homework extends BaseModel
|
|||||||
protected $table = 'homework';
|
protected $table = 'homework';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CI: useTimestamps = false (even though created_at/updated_at columns exist).
|
* legacy: useTimestamps = false (even though created_at/updated_at columns exist).
|
||||||
* Keep it OFF to match behavior. If you want Laravel to auto-manage, tell me.
|
* Keep it OFF to match behavior. If you want Laravel to auto-manage, tell me.
|
||||||
*/
|
*/
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
@@ -55,7 +55,7 @@ class Homework extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Laravel equivalent of CI getAverageHomeworkScore()
|
* Laravel equivalent of legacy getAverageHomeworkScore()
|
||||||
* Computes average based only on non-blank numeric scores.
|
* Computes average based only on non-blank numeric scores.
|
||||||
*/
|
*/
|
||||||
public static function getAverageHomeworkScore(
|
public static function getAverageHomeworkScore(
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class InventoryCategory extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'inventory_categories';
|
protected $table = 'inventory_categories';
|
||||||
|
|
||||||
// ✅ CI: useTimestamps = true (created_at/updated_at)
|
// ✅ legacy: useTimestamps = true (created_at/updated_at)
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@@ -27,7 +27,7 @@ class InventoryCategory extends BaseModel
|
|||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equivalent of CI optionsForType()
|
* Equivalent of legacy optionsForType()
|
||||||
* Returns array rows: id, name, description, grade_min, grade_max
|
* Returns array rows: id, name, description, grade_min, grade_max
|
||||||
*/
|
*/
|
||||||
public static function optionsForType(string $type): array
|
public static function optionsForType(string $type): array
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class InventoryItem extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'inventory_items';
|
protected $table = 'inventory_items';
|
||||||
|
|
||||||
// ✅ CI: useTimestamps = true
|
// ✅ legacy: useTimestamps = true
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class InventoryMovement extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'inventory_movements';
|
protected $table = 'inventory_movements';
|
||||||
|
|
||||||
// ✅ CI: useTimestamps = true (created_at/updated_at)
|
// ✅ legacy: useTimestamps = true (created_at/updated_at)
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class Invoice extends BaseModel
|
|||||||
protected $table = 'invoices';
|
protected $table = 'invoices';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CI: useTimestamps = false because DB defaults/triggers manage created_at/updated_at.
|
* legacy: useTimestamps = false because DB defaults/triggers manage created_at/updated_at.
|
||||||
* In Laravel, keep timestamps OFF and let DB handle them.
|
* In Laravel, keep timestamps OFF and let DB handle them.
|
||||||
*/
|
*/
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
@@ -67,7 +67,7 @@ class Invoice extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
* CI beforeInsert/beforeUpdate equivalents (normalize to UTC)
|
* legacy beforeInsert/beforeUpdate equivalents (normalize to UTC)
|
||||||
* ========================= */
|
* ========================= */
|
||||||
|
|
||||||
protected static function booted(): void
|
protected static function booted(): void
|
||||||
@@ -135,7 +135,7 @@ class Invoice extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
* Queries (ported from CI)
|
* Queries (ported from legacy)
|
||||||
* ========================= */
|
* ========================= */
|
||||||
|
|
||||||
public static function getInvoicesByUserId(int $userId, ?string $schoolYear = null): array
|
public static function getInvoicesByUserId(int $userId, ?string $schoolYear = null): array
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class InvoiceEvent extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'invoice_event';
|
protected $table = 'invoice_event';
|
||||||
|
|
||||||
// ✅ CI: useTimestamps = true (created_at/updated_at)
|
// ✅ legacy: useTimestamps = true (created_at/updated_at)
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class InvoiceStudentList extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'invoice_students_list';
|
protected $table = 'invoice_students_list';
|
||||||
|
|
||||||
// ✅ CI: useTimestamps = true (created_at/updated_at)
|
// ✅ legacy: useTimestamps = true (created_at/updated_at)
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class IpAttempt extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'ip_attempts';
|
protected $table = 'ip_attempts';
|
||||||
|
|
||||||
// ✅ CI: useTimestamps = true (created_at/updated_at)
|
// ✅ legacy: useTimestamps = true (created_at/updated_at)
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@@ -27,7 +27,7 @@ class IpAttempt extends BaseModel
|
|||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equivalent of CI getAttemptByIp()
|
* Equivalent of legacy getAttemptByIp()
|
||||||
*/
|
*/
|
||||||
public static function getAttemptByIp(string $ip): ?self
|
public static function getAttemptByIp(string $ip): ?self
|
||||||
{
|
{
|
||||||
@@ -37,7 +37,7 @@ class IpAttempt extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equivalent of CI updateIpAttempt()
|
* Equivalent of legacy updateIpAttempt()
|
||||||
*/
|
*/
|
||||||
public static function updateIpAttempt(string $ip, array $data): bool
|
public static function updateIpAttempt(string $ip, array $data): bool
|
||||||
{
|
{
|
||||||
@@ -47,7 +47,7 @@ class IpAttempt extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equivalent of CI insertIpAttempt()
|
* Equivalent of legacy insertIpAttempt()
|
||||||
* Returns inserted id.
|
* Returns inserted id.
|
||||||
*/
|
*/
|
||||||
public static function insertIpAttempt(array $data): int
|
public static function insertIpAttempt(array $data): int
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class LateSlipLog extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'late_slip_logs';
|
protected $table = 'late_slip_logs';
|
||||||
|
|
||||||
// CI: useTimestamps = false (printed_at is controlled explicitly)
|
// legacy: useTimestamps = false (printed_at is controlled explicitly)
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class LoginActivity extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'login_activity';
|
protected $table = 'login_activity';
|
||||||
|
|
||||||
// ✅ CI: useTimestamps = true (created_at/updated_at)
|
// ✅ legacy: useTimestamps = true (created_at/updated_at)
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@@ -37,7 +37,7 @@ class LoginActivity extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equivalent of CI getLastActivities()
|
* Equivalent of legacy getLastActivities()
|
||||||
*/
|
*/
|
||||||
public static function getLastActivities(int $limit = 4)
|
public static function getLastActivities(int $limit = 4)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class ManualPayment extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'manual_payments';
|
protected $table = 'manual_payments';
|
||||||
|
|
||||||
// CI: useTimestamps = false
|
// legacy: useTimestamps = false
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class Message extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'messages';
|
protected $table = 'messages';
|
||||||
|
|
||||||
// CI: useTimestamps = false (manual date fields)
|
// legacy: useTimestamps = false (manual date fields)
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@@ -49,7 +49,7 @@ class Message extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
* CI method equivalents
|
* legacy method equivalents
|
||||||
* ========================= */
|
* ========================= */
|
||||||
|
|
||||||
public static function getUnreadMessages(int $recipientId)
|
public static function getUnreadMessages(int $recipientId)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class MidtermExam extends BaseModel
|
|||||||
protected $table = 'midterm_exam';
|
protected $table = 'midterm_exam';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CI: useTimestamps = false (even though created_at/updated_at columns exist).
|
* legacy: useTimestamps = false (even though created_at/updated_at columns exist).
|
||||||
* Keep it OFF to match behavior (you can still store created_at/updated_at manually).
|
* Keep it OFF to match behavior (you can still store created_at/updated_at manually).
|
||||||
*/
|
*/
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
@@ -52,7 +52,7 @@ class MidtermExam extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equivalent of CI getMidtermExamScore()
|
* Equivalent of legacy getMidtermExamScore()
|
||||||
*/
|
*/
|
||||||
public static function getMidtermExamScore(
|
public static function getMidtermExamScore(
|
||||||
int $studentId,
|
int $studentId,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class MissingScoreOverride extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'missing_score_overrides';
|
protected $table = 'missing_score_overrides';
|
||||||
|
|
||||||
// ✅ CI: useTimestamps = true (created_at/updated_at)
|
// ✅ legacy: useTimestamps = true (created_at/updated_at)
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@@ -34,7 +34,7 @@ class MissingScoreOverride extends BaseModel
|
|||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equivalent of CI getOverridesMap()
|
* Equivalent of legacy getOverridesMap()
|
||||||
* Returns: [student_id => [item_index => true]]
|
* Returns: [student_id => [item_index => true]]
|
||||||
*/
|
*/
|
||||||
public static function getOverridesMap(int $classSectionId, string $semester, string $schoolYear, string $itemType): array
|
public static function getOverridesMap(int $classSectionId, string $semester, string $schoolYear, string $itemType): array
|
||||||
@@ -65,7 +65,7 @@ class MissingScoreOverride extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equivalent of CI replaceOverrides()
|
* Equivalent of legacy replaceOverrides()
|
||||||
* Deletes matching overrides then inserts checked items.
|
* Deletes matching overrides then inserts checked items.
|
||||||
*/
|
*/
|
||||||
public static function replaceOverrides(
|
public static function replaceOverrides(
|
||||||
@@ -109,7 +109,7 @@ class MissingScoreOverride extends BaseModel
|
|||||||
if (!empty($itemIndexes)) {
|
if (!empty($itemIndexes)) {
|
||||||
$q->whereIn('item_index', array_map('intval', $itemIndexes));
|
$q->whereIn('item_index', array_map('intval', $itemIndexes));
|
||||||
} else {
|
} else {
|
||||||
// CI behavior: if itemIndexes is provided but empty, do nothing.
|
// legacy behavior: if itemIndexes is provided but empty, do nothing.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} elseif ($nullIndex) {
|
} elseif ($nullIndex) {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class NavItem extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'nav_items';
|
protected $table = 'nav_items';
|
||||||
|
|
||||||
// ✅ CI: timestamps + soft deletes
|
// ✅ legacy: timestamps + soft deletes
|
||||||
use SoftDeletes;
|
use SoftDeletes;
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
@@ -41,8 +41,8 @@ class NavItem extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equivalent of CI getChildrenOf()
|
* Equivalent of legacy getChildrenOf()
|
||||||
* NOTE: CI code uses where('parent_id', ...) but allowedFields has menu_parent_id.
|
* NOTE: legacy code uses where('parent_id', ...) but allowedFields has menu_parent_id.
|
||||||
* This Laravel version uses menu_parent_id (likely correct).
|
* This Laravel version uses menu_parent_id (likely correct).
|
||||||
*/
|
*/
|
||||||
public static function getChildrenOf(int $parentId): array
|
public static function getChildrenOf(int $parentId): array
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class Notification extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'notifications';
|
protected $table = 'notifications';
|
||||||
|
|
||||||
// ✅ CI: soft deletes + timestamps
|
// ✅ legacy: soft deletes + timestamps
|
||||||
use SoftDeletes;
|
use SoftDeletes;
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ class Notification extends BaseModel
|
|||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equivalent of CI getActiveNotifications()
|
* Equivalent of legacy getActiveNotifications()
|
||||||
* Active = scheduled_at <= now AND (expires_at is null OR expires_at > now)
|
* Active = scheduled_at <= now AND (expires_at is null OR expires_at > now)
|
||||||
*/
|
*/
|
||||||
public static function getActiveNotifications(?string $targetGroup = null): array
|
public static function getActiveNotifications(?string $targetGroup = null): array
|
||||||
@@ -58,7 +58,7 @@ class Notification extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equivalent of CI getDeletedNotifications()
|
* Equivalent of legacy getDeletedNotifications()
|
||||||
*/
|
*/
|
||||||
public static function getDeletedNotifications(): array
|
public static function getDeletedNotifications(): array
|
||||||
{
|
{
|
||||||
@@ -69,7 +69,7 @@ class Notification extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equivalent of CI getAllNotificationsWithDeleted()
|
* Equivalent of legacy getAllNotificationsWithDeleted()
|
||||||
*/
|
*/
|
||||||
public static function getAllNotificationsWithDeleted(): array
|
public static function getAllNotificationsWithDeleted(): array
|
||||||
{
|
{
|
||||||
@@ -80,7 +80,7 @@ class Notification extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equivalent of CI restoreNotification()
|
* Equivalent of legacy restoreNotification()
|
||||||
*/
|
*/
|
||||||
public static function restoreNotification(int $id): bool
|
public static function restoreNotification(int $id): bool
|
||||||
{
|
{
|
||||||
@@ -90,7 +90,7 @@ class Notification extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equivalent of CI deleteExpiredNotifications()
|
* Equivalent of legacy deleteExpiredNotifications()
|
||||||
* Soft-deletes rows with expires_at < now (and expires_at not null)
|
* Soft-deletes rows with expires_at < now (and expires_at not null)
|
||||||
*/
|
*/
|
||||||
public static function deleteExpiredNotifications(): int
|
public static function deleteExpiredNotifications(): int
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class ParentAttendanceReport extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'parent_attendance_reports';
|
protected $table = 'parent_attendance_reports';
|
||||||
|
|
||||||
// ✅ CI: useTimestamps = true
|
// ✅ legacy: useTimestamps = true
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@@ -51,7 +51,7 @@ class ParentAttendanceReport extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Laravel equivalent of CI listForDateRange()
|
* Laravel equivalent of legacy listForDateRange()
|
||||||
* Returns array rows with:
|
* Returns array rows with:
|
||||||
* parent_attendance_reports.* + students firstname/lastname + classSection class_section_name
|
* parent_attendance_reports.* + students firstname/lastname + classSection class_section_name
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class ParentMeetingSchedule extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'parent_meeting_schedules';
|
protected $table = 'parent_meeting_schedules';
|
||||||
|
|
||||||
// ✅ CI: useTimestamps = true (created_at/updated_at)
|
// ✅ legacy: useTimestamps = true (created_at/updated_at)
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class ParentModel extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'parents';
|
protected $table = 'parents';
|
||||||
|
|
||||||
// CI model didn't specify timestamps
|
// legacy model didn't specify timestamps
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class ParentNotification extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'parent_notifications';
|
protected $table = 'parent_notifications';
|
||||||
|
|
||||||
// ✅ CI: useTimestamps = true (created_at/updated_at)
|
// ✅ legacy: useTimestamps = true (created_at/updated_at)
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@@ -26,7 +26,7 @@ class ParentNotification extends BaseModel
|
|||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'student_id' => 'integer',
|
'student_id' => 'integer',
|
||||||
// incident_date is stored as Y-m-d in CI usage
|
// incident_date is stored as Y-m-d in legacy usage
|
||||||
'incident_date' => 'date',
|
'incident_date' => 'date',
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ class ParentNotification extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equivalent of CI hasSent()
|
* Equivalent of legacy hasSent()
|
||||||
*/
|
*/
|
||||||
public static function hasSent(
|
public static function hasSent(
|
||||||
int $studentId,
|
int $studentId,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class Participation extends BaseModel
|
|||||||
protected $table = 'participation';
|
protected $table = 'participation';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CI: useTimestamps = false (even though created_at/updated_at columns exist).
|
* legacy: useTimestamps = false (even though created_at/updated_at columns exist).
|
||||||
* Keep OFF to match behavior (you can still set created_at/updated_at manually).
|
* Keep OFF to match behavior (you can still set created_at/updated_at manually).
|
||||||
*/
|
*/
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
@@ -52,7 +52,7 @@ class Participation extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equivalent of CI getParticipationScore()
|
* Equivalent of legacy getParticipationScore()
|
||||||
* Returns null if missing/blank/non-numeric.
|
* Returns null if missing/blank/non-numeric.
|
||||||
*/
|
*/
|
||||||
public static function getParticipationScore(
|
public static function getParticipationScore(
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class PasswordReset extends BaseModel
|
|||||||
protected $table = 'password_resets';
|
protected $table = 'password_resets';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In CI you used:
|
* In legacy you used:
|
||||||
* - createdField = created_at
|
* - createdField = created_at
|
||||||
* - updatedField = expires_at (non-standard)
|
* - updatedField = expires_at (non-standard)
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class PasswordResetRequest extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'password_reset_requests';
|
protected $table = 'password_reset_requests';
|
||||||
|
|
||||||
// CI: timestamps off
|
// legacy: timestamps off
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class PayPalPayment extends BaseModel
|
|||||||
protected $table = 'paypal_payments';
|
protected $table = 'paypal_payments';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CI: created_at is managed, updated_at is NOT used.
|
* legacy: created_at is managed, updated_at is NOT used.
|
||||||
* In Laravel: enable timestamps but disable UPDATED_AT.
|
* In Laravel: enable timestamps but disable UPDATED_AT.
|
||||||
*/
|
*/
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class Payment extends BaseModel
|
|||||||
protected $table = 'payments';
|
protected $table = 'payments';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CI: useTimestamps = false because DB handles created_at/updated_at (defaults/triggers).
|
* legacy: useTimestamps = false because DB handles created_at/updated_at (defaults/triggers).
|
||||||
* Keep OFF in Laravel too.
|
* Keep OFF in Laravel too.
|
||||||
*/
|
*/
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
@@ -58,7 +58,7 @@ class Payment extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
* CI method equivalents
|
* legacy method equivalents
|
||||||
* ========================= */
|
* ========================= */
|
||||||
|
|
||||||
public static function getPaymentsByParentId(int $parentId): array
|
public static function getPaymentsByParentId(int $parentId): array
|
||||||
@@ -135,7 +135,7 @@ class Payment extends BaseModel
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get latest payment (date/amount/status) per invoice for given invoice IDs.
|
* Get latest payment (date/amount/status) per invoice for given invoice IDs.
|
||||||
* Matches your CI logic: statuses in ['Full','Paid','Partially Paid'].
|
* Matches your legacy logic: statuses in ['Full','Paid','Partially Paid'].
|
||||||
*/
|
*/
|
||||||
public static function getPaymentsByInvoice($invoiceIds): array
|
public static function getPaymentsByInvoice($invoiceIds): array
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class PaymentError extends BaseModel
|
|||||||
{
|
{
|
||||||
protected $table = 'payment_error';
|
protected $table = 'payment_error';
|
||||||
|
|
||||||
// CI: useTimestamps = false (logged_at managed manually)
|
// legacy: useTimestamps = false (logged_at managed manually)
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user