Your IP : 216.73.216.79


Current Path : /var/www/html/ains/frontend/controllers/
Upload File :
Current File : /var/www/html/ains/frontend/controllers/ReadingRecordController.php

<?php

namespace frontend\controllers;

use yii;
use yii\web\Controller;
use frontend\models\ReadingRecord;
use frontend\models\FrontendUser;
use yii\web\UploadedFile;
use frontend\models\Book;

class ReadingRecordController extends Controller {

    public function behaviors() {
        $this->enableCsrfValidation = true;
    }

    public function actionSaverecord() {
        $status = 'failed';

        // Audit fields
        $userId = Yii::$app->user->identity->id;
        $now = date("Y-m-d H:i:s");

        // Use Yii's request component instead of raw $_POST for better security
        $post = Yii::$app->request->post();

        $allowedFields = [
            'jenis_rekod' => 'record_type',
            'kategori' => 'record_cat',
            'jenis' => 'record_type2',
            'bahasa' => 'record_language',
            'tajuk' => 'record_title',
            'tahun' => 'record_year_publish',
            'penulis' => 'record_author',
            'isbn' => 'record_isbn',
            'mukasurat' => 'record_total_page',
            'penerbit' => 'record_publisher',
            'pautan' => 'record_url',
            'penilaian' => 'record_rating',
            'rumusan' => 'record_summary',
            'pengajaran' => 'record_lesson',
            'record_book_id' => 'record_book_id',
            'record_book_thumbnail' => 'record_book_thumbnail',
            'record_update_id' => 'record_update_id'
        ];

        if (isset($post['record_update_id']) && !empty($post['record_update_id'])) {
            $model = ReadingRecord::findOne($post['record_update_id']);
            $model->record_approval_status = 'pending';
            $model->updated_at = $now;
            $model->updated_by = $userId;
            $model->updated_user_type = 'frontend_user';
        } else {
            $model = new ReadingRecord();

            // Generate UUID
            $model->record_code = (new \yii\db\Query)->select(new \yii\db\Expression('UUID()'))->scalar();

            $model->record_student_id = $userId;
            $model->record_approval_status = 'pending';
            $model->created_at = $now;
            $model->created_by = $userId;
            $model->created_user_type = 'frontend_user';
            $model->updated_at = $now;
            $model->updated_by = $userId;
            $model->updated_user_type = 'frontend_user';
        }

        foreach ($allowedFields as $postKey => $modelAttr) {
            if (!empty($post[$postKey])) {
                $model->$modelAttr = $post[$postKey];
            }
        }

        // --- SECURE IMAGE UPLOAD ---
        $coverImg = UploadedFile::getInstanceByName('kulit');

        if ($coverImg !== null) {
            // 1. Validate Extension
            $allowedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
            $extension = strtolower($coverImg->extension);

            if (!in_array($extension, $allowedExtensions)) {
                return 'failed:invalid_image_extension';
            }

            // 2. Validate MIME Type (prevents extension spoofing)
            $finfo = new \finfo(FILEINFO_MIME_TYPE);
            $mimeType = $finfo->file($coverImg->tempName);
            $allowedMimeTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];

            if (!in_array($mimeType, $allowedMimeTypes)) {
                return 'failed:invalid_image_mime';
            }

            // 3. Validate File Size (e.g., max 5MB)
            if ($coverImg->size > 5 * 1024 * 1024) {
                return 'failed:image_too_large';
            }

            // 4. Generate a safe, unique filename (never trust user filenames)
            $safeFileName = Yii::$app->security->generateRandomString(32) . '.' . $extension;
            $relativePath = 'uploads/record/' . $safeFileName;

            // 5. Upload to Google Cloud Storage
            if (\common\components\GcsHelper::save($coverImg->tempName, $relativePath)) {
                $model->record_cover_img = $relativePath;
            } else {
                return 'failed:upload_error';
            }
        } else {
            if (!empty($model->record_book_thumbnail)) {
                $model->record_cover_img = $model->record_book_thumbnail;
            }
        }

        if (empty($model->record_total_page))
            $model->record_total_page = 1;

        if ($model->save()) {

            ReadingRecord::updatepoints($model->record_id);
            FrontendUser::updatetotal($model->record_student_id);

            $status = 'success';
        } else {
            $status = 'failed:' . json_encode($model->errors);
        }

        return $status;
    }

    public function actionTeachersaverecord() {
        $status = 'success';

        // Use Yii's request component instead of raw $_POST for better security
        $post = Yii::$app->request->post();

        $allowedFields = [
            'jenis_rekod' => 'record_type',
            'kategori' => 'record_cat',
            'jenis' => 'record_type2',
            'bahasa' => 'record_language',
            'tajuk' => 'record_title',
            'tahun' => 'record_year_publish',
            'penulis' => 'record_author',
            'isbn' => 'record_isbn',
            'mukasurat' => 'record_total_page',
            'penerbit' => 'record_publisher',
            'pautan' => 'record_url',
            'penilaian' => 'record_rating',
            'rumusan' => 'record_summary',
            'pengajaran' => 'record_lesson',
            'record_book_id' => 'record_book_id',
            'record_book_thumbnail' => 'record_book_thumbnail',
            'student_list' => 'student_list'
        ];

        // Audit fields
        $userId = Yii::$app->user->identity->id;
        $now = date("Y-m-d H:i:s");
        $record_cover_img = '';

        // --- SECURE IMAGE UPLOAD ---
        $coverImg = UploadedFile::getInstanceByName('kulit');

        if ($coverImg !== null) {
            // 1. Validate Extension
            $allowedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
            $extension = strtolower($coverImg->extension);

            if (!in_array($extension, $allowedExtensions)) {
                return 'failed:invalid_image_extension';
            }

            // 2. Validate MIME Type (prevents extension spoofing)
            $finfo = new \finfo(FILEINFO_MIME_TYPE);
            $mimeType = $finfo->file($coverImg->tempName);
            $allowedMimeTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];

            if (!in_array($mimeType, $allowedMimeTypes)) {
                return 'failed:invalid_image_mime';
            }

            // 3. Validate File Size (e.g., max 5MB)
            if ($coverImg->size > 5 * 1024 * 1024) {
                return 'failed:image_too_large';
            }

            // 4. Generate a safe, unique filename (never trust user filenames)
            $safeFileName = Yii::$app->security->generateRandomString(32) . '.' . $extension;
            $relativePath = 'uploads/record/' . $safeFileName;

            // 5. Upload to Google Cloud Storage
            if (\common\components\GcsHelper::save($coverImg->tempName, $relativePath)) {
                $record_cover_img = $relativePath;
            } else {
                return 'failed:upload_error';
            }
        }

        if (isset($_POST['student_list'])) {
            foreach ($_POST['student_list'] as $student_id) {

                $model = new ReadingRecord();
                $model->record_code = (new \yii\db\Query)->select(new \yii\db\Expression('UUID()'))->scalar();
                $model->record_approval_status = 'approved';
                $model->record_approval_at = $now;
                $model->record_approval_by = $userId;
                $model->record_approval_user_type = 'frontend_user';
                $model->created_at = $now;
                $model->created_by = $userId;
                $model->created_user_type = 'frontend_user';
                $model->updated_at = $now;
                $model->updated_by = $userId;
                $model->updated_user_type = 'frontend_user';
                $model->record_cover_img = $record_cover_img;
                $model->record_student_id = $student_id;

                foreach ($allowedFields as $postKey => $modelAttr) {
                    if (!empty($post[$postKey])) {
                        $model->$modelAttr = $post[$postKey];
                    }
                }

                if ($model->save()) {
                    ReadingRecord::updatepoints($model->record_id);
                    FrontendUser::updatetotal($model->record_student_id);
                } else {
                    $status = 'failed:' . json_encode($model->errors);
                }
            }
        }

        return $status;
    }

    public function actionUpdatestatus() {
        $id = $_GET['id'];
        $status = $_GET['status'];
        $output = 'failed';
        $model = ReadingRecord::findOne($id);
        if (!empty($model)) {
            $model->record_approval_status = $status;
            $model->record_approval_at = date("Y-m-d H:i:s");
            $model->record_approval_by = Yii::$app->user->identity->id;
            $model->record_approval_user_type = 'frontend_user';
            if (!empty($_GET['comment'])) {
                $model->record_approval_comments = $_GET['comment'];
            }
            if ($status == 'rejected') {
                $model->record_points = 0;
            }
            if ($model->save()) {
                FrontendUser::updatetotal($model->record_student_id);
                $output = 'success';
            }
        }
        return $output;
    }
}