Controllers

A continuación se desglosaran ciertas partes del código que nos ayudaran a entender como funcionan ciertos apartados del sitio en el backend, desarollado con laravel.

CursoController

El controlador de Laravel maneja una amplia gama de funcionalidades relacionadas con la gestión de cursos, la asignación de usuarios a cursos, la generación de certificados, y la administración de capítulos y subcapítulos dentro de los cursos, a continuación se presenta el código del mismo.

<?php
namespace App\Http\Controllers;

use App\Models\Usuario;
use Illuminate\Support\Facades\Storage;
use Illuminate\Http\Request;
use App\Models\Curso_usuario;
use App\Models\Curso;
use App\Models\Capitulo;
use App\Models\Preguntas_examen;
use App\Models\Examen;
use App\Models\Comentario;
use App\Models\Progress;
use App\Models\SubCapitulo;
use App\Models\Pregunta_a_examen;
use Barryvdh\DomPDF\Facade\Pdf;
use Illuminate\Support\Facades\DB;

class CursosController extends Controller
{
    public function index()
    {
        $cursos = Curso::all();
        return view('cursos.index', compact('cursos'));
    }

    public function create()
    {
        return view('cursos.create');
    }

    public function generarCertificado($id, $curso)
    {
        $curso_get = Curso::find($curso);
        $usuario = Usuario::find($id);
        if (!$curso_get) {
            $error = 'No se encontró el curso';
            return back()->with('error', $error);
        }

        if (!$usuario) {
            $error = 'No se encontró el usuario';
            return back()->with('error', $error);
        }

        $data = [
            'courseName' => $curso_get->titulo,
            'userName' => $usuario->nombre,
            'userEmail' => $usuario->email,
            'userGender' => $usuario->genero,
            'totalTime' => 10, // Horas totales para completar el curso
            'examScore' => 95, // Calificación del examen
            'date' => now()->format('d-m-Y H:i'),
        ];

        // Cargar la vista del certificado
        $pdf = PDF::loadView('cursos.certificado', $data);

        // Establecer opciones para el PDF
        $pdf->setOption('page-size', 'A4'); // Tamaño de la página
        $pdf->setOption('margin-top', '0'); // Margen superior
        $pdf->setOption('margin-right', '0'); // Margen derecho
        $pdf->setOption('margin-bottom', '0'); // Margen inferior
        $pdf->setOption('margin-left', '0'); // Margen izquierdo

        // Opciones para ajustar tamaño y dimensiones
        $pdf->setOption('width', '210mm'); // Ancho para A4
        $pdf->setOption('height', '297mm'); // Altura para A4
        $pdf->setOption('disable-smart-shrinking', true);
        // Generar y devolver el PDF
        return $pdf->download('Certificado ' . $usuario->nombre . '.pdf');
    }
    // return view('cursos.certificado', compact('data'));

    public function curso_usuario($id)
    {
        $id_usuario = session()->get('usuario_id');

        $curso = Curso::with(['capitulos.subcapitulos'])->findOrFail($id);
        $asignacion_curso = Curso_usuario::where('id_usuario', $id_usuario)
            ->where('id_curso', $curso->id)
            ->first();
        if ($asignacion_curso) {
            $cursoData = $curso->toArray();
            $comentarios = Comentario::where('id_curso', $curso->id)->get();
            return view('cursos.curso_usuario', compact('cursoData', 'comentarios'));
        }
        $error = 'No te has inscrito a este curso. Inscríbete para ver el contenido';
        $cursos = Curso::all();
        return redirect()->route('index')->with('error', $error);
    }

    public function crear_curso_admin(Request $request)
    {
        $data = $request->all();
        try {
        $validatedData = $request->validate([
            'titulo' => 'required|string|max:255',
            'descripcion' => 'nullable|string',
            // 'preguntas' => 'required|array',
            'descripcion' => 'required|string',
            'id_usuario' => 'required|integer',
            'categoria' => 'required|string|max:255',
            'estado' => 'required|string|max:50',
            'precio' => 'required|numeric',
            'contenidoCurso' => 'required|string',
            'imagen' => 'nullable|file|mimes:jpeg,png,jpg,gif,svg|max:2048',
            'recursos.*' => 'nullable|file|mimes:pdf,doc,docx,ppt,pptx|max:10240',
            'capitulos.*.titulo' => 'required|string|max:255',
            'capitulos.*.descripcion' => 'required|string',
            'capitulos.*.subcapitulos.*.titulo' => 'required|string|max:255',
            'capitulos.*.subcapitulos.*.contenido' => 'required|string',
            'capitulos.*.subcapitulos.*.video' => 'nullable|file|mimes:mp4,avi,mkv|max:51200',
        ]);


        
            $Curso = new Curso();
            $Curso->titulo = $validatedData['titulo'];
            $Curso->descripcion = $validatedData['descripcion'];
            $Curso->id_usuario = $validatedData['id_usuario'];
            $Curso->categoria = $validatedData['categoria'];
            $Curso->estado = $validatedData['estado'];
            $Curso->precio = $validatedData['precio'];
            $Curso->contenido = $validatedData['contenidoCurso'];
            $Curso->horas = isset($validatedData['horas']) ? $validatedData['horas'] : 10;

  

            if ($request->hasFile('recursos')) {
                $resourceNames = [];
                foreach ($request->file('recursos') as $index => $recurso) {
                    $resourceName = 'recurso_' . $Curso->id . '_NO_' . ($index + 1) . '.' . $recurso->extension();
                    $recurso->storeAs('cursos/recursos', $resourceName);
                    $resourceNames[] = $resourceName;
                }
                $Curso->recursos = implode(',', $resourceNames);
            }
            if ($request->hasFile('imagen')) {
                $imageName = 'portada_' . $Curso->id . '.' . $request->file('imagen')->extension();
                $request->file('imagen')->storeAs('cursos/portada', $imageName);
                $Curso->imagen = $imageName;
            }

            $Curso->save();

            foreach ($validatedData['capitulos'] as $i => $capituloData) {
                $Capitulo = new Capitulo();
                $Capitulo->id_curso = $Curso->id;
                $Capitulo->titulo = $capituloData['titulo'];
                $Capitulo->descripcion = $capituloData['descripcion'];

                if (isset($capituloData['video']) && $request->hasFile("capitulos.$i.video")) {
                    $videoName = 'Curso_' . $Curso->id . '_Capitulo_' . ($i + 1) . '.' . $request->file("capitulos.$i.video")->extension();
                    $request->file("capitulos.$i.video")->storeAs('cursos/videos', $videoName);
                    $Capitulo->video = $videoName;
                }

                $Capitulo->save();

                foreach ($capituloData['subcapitulos'] as $j => $subcapituloData) {
                    $Subcapitulo = new SubCapitulo();
                    $Subcapitulo->id_capitulo = $Capitulo->id;
                    $Subcapitulo->titulo = $subcapituloData['titulo'];
                    $Subcapitulo->contenido = $subcapituloData['contenido'];

                    if ($request->hasFile("capitulos.$i.subcapitulos.$j.video")) {
                        $videoName = 'CURSO_' . $Curso->id . '_Capitulo_' . ($i + 1) . '_Subcapitulo_' . ($j + 1) . '.' . $request->file("capitulos.$i.subcapitulos.$j.video")->extension();
                        $request->file("capitulos.$i.subcapitulos.$j.video")->storeAs('cursos/videos', $videoName);
                        $Subcapitulo->video = $videoName;
                    }

                    $Subcapitulo->save();
                }
            }

            $Curso->save();
            return redirect()->route('curso.vista', ['id' => $Curso->id]);
        } catch (\Throwable $th) {
            return back()->with('error', $th->getMessage());
        }
    }

    public function mostrarCursos()
    {
        $cursos = Curso::all();
        return view('cursos.admin.cursos', compact('cursos'));
    }

    public function mostrarVideoCurso($filename)
    {
        $path = 'cursos/videos/' . $filename;

        if (Storage::exists($path)) {
            return response()->file(storage_path('app/' . $path));
        }

        abort(404);
    }

    public function mostrarPortadaCurso($filename)
    {
        $path = 'cursos/portada/' . $filename;

        if (Storage::exists($path)) {
            return response()->file(storage_path('app/' . $path));
        }

        abort(404);
    }

    public function tarjetaCurso($id)
    {
        $id_usuario = session()->get('usuario_id');
        $inscrito = false;
        $curso = Curso::find($id);
        $verificar_asignacion = Curso_usuario::where('id_usuario', $id_usuario)
            ->where('id_curso', $curso->id)
            ->first();
        $verificar_asignacion ? ($inscrito = true) : ($inscrito = false);
        return view('cursos.tarjetaCurso', compact('curso', 'inscrito'));
    }

    public function mostrarCurso($id)
    {
        $curso = Curso::with(['capitulos.subcapitulos'])->findOrFail($id);
        $cursoData = $curso->toArray();
        $comentarios = Comentario::where('id_curso', $curso->id)->get();
        return view('cursos.admin.curso', compact('cursoData', 'comentarios'));
    }

    public function store(Request $request)
    {
        $request->validate([
            'titulo' => 'required|string|max:255',
            'descripcion' => 'required',
            'id_usuario' => 'required|exists:users,id',
            'categoria' => 'required|string|max:255',
            'nivel' => 'required|string|max:255',
            'horas' => 'required|integer',
            'estado' => 'required|string|max:255',
            'precio' => 'required|numeric',
            'capitulos' => 'array',
            'capitulos.*.titulo' => 'required|string|max:255',
            'capitulos.*.descripcion' => 'required',
            'capitulos.*.subcapitulos' => 'array',
            'capitulos.*.subcapitulos.*.titulo' => 'required|string|max:255',
            'capitulos.*.subcapitulos.*.contenido' => 'required',
            'capitulos.*.subcapitulos.*.video' => 'nullable|string|max:255',
        ]);

        DB::transaction(function () use ($request) {
            $curso = Curso::create($request->only(['titulo', 'descripcion', 'id_usuario', 'categoria', 'nivel', 'horas', 'estado', 'precio', 'imagen', 'contenido']));

            foreach ($request->capitulos as $capituloData) {
                $capitulo = $curso->capitulos()->create([
                    'titulo' => $capituloData['titulo'],
                    'descripcion' => $capituloData['descripcion'],
                ]);

                foreach ($capituloData['subcapitulos'] as $subcapituloData) {
                    $capitulo->subcapitulos()->create($subcapituloData);
                }
            }
        });

        return redirect()->route('cursos.index')->with('success', 'Curso creado exitosamente');
    }

    public function show(Curso $curso)
    {
        return view('cursos.show', compact('curso'));
    }

    public function edit(Curso $curso)
    {
        return view('cursos.edit', compact('curso'));
    }

    public function update(Request $request, Curso $curso)
    {
        $request->validate([
            'titulo' => 'required|string|max:255',
            'descripcion' => 'required',
            'id_usuario' => 'required|exists:users,id',
            'categoria' => 'required|string|max:255',
            'nivel' => 'required|string|max:255',
            'horas' => 'required|integer',
            'estado' => 'required|string|max:255',
            'precio' => 'required|numeric',
            'capitulos' => 'array',
            'capitulos.*.titulo' => 'required|string|max:255',
            'capitulos.*.descripcion' => 'required',
            'capitulos.*.subcapitulos' => 'array',
            'capitulos.*.subcapitulos.*.titulo' => 'required|string|max:255',
            'capitulos.*.subcapitulos.*.contenido' => 'required',
            'capitulos.*.subcapitulos.*.video' => 'nullable|string|max:255',
        ]);

        DB::transaction(function () use ($request, $curso) {
            $curso->update($request->only(['titulo', 'descripcion', 'id_usuario', 'categoria', 'nivel', 'horas', 'estado', 'precio', 'imagen', 'contenido']));

            foreach ($request->capitulos as $capituloData) {
                $capitulo = $curso->capitulos()->updateOrCreate(['id' => $capituloData['id']], ['titulo' => $capituloData['titulo'], 'descripcion' => $capituloData['descripcion']]);

                foreach ($capituloData['subcapitulos'] as $subcapituloData) {
                    $capitulo->subcapitulos()->updateOrCreate(['id' => $subcapituloData['id']], $subcapituloData);
                }
            }
        });

        return redirect()->route('cursos.index')->with('success', 'Curso actualizado exitosamente');
    }

    public function expedirCertificado(Request $request)
    {
        $id_usuario = $request->session()->get('usuario_id');
        $usuario = Usuario::where('id', $id_usuario)->first();
        $pdf = Pdf::loadView('cursos.user.profile', json_decode(json_encode($usuario), true));
        return $pdf->download('invoice.pdf');
    }


    public function eliminar_curso_admin(Request $request)
    {
        try {
            $request->validate([
                'id_curso' => 'required|string|max:255',
            ]);
    
            $curso = Curso::find($request->id_curso);
            if (!$curso) {
                return back()->with('error', 'El curso no existe.');
            }
    
            // Eliminar imagen de portada
            if ($curso->imagen) {
                Storage::delete('cursos/portada/' . $curso->imagen);
            }
    
            // Eliminar recursos
            if ($curso->recursos) {
                $recursos = explode(',', $curso->recursos);
                foreach ($recursos as $recurso) {
                    Storage::delete('cursos/recursos/' . $recurso);
                }
            }
    
            // Eliminar capítulos y subcapítulos asociados
            foreach ($curso->capitulos as $capitulo) {
                // Eliminar video del capítulo
                if ($capitulo->video) {
                    Storage::delete('cursos/videos/' . $capitulo->video);
                }
    
                foreach ($capitulo->subcapitulos as $subcapitulo) {
                    // Eliminar video del subcapítulo
                    if ($subcapitulo->video) {
                        Storage::delete('cursos/videos/' . $subcapitulo->video);
                    }
                }
    
                // Eliminar subcapítulos
                $capitulo->subcapitulos()->delete();
            }
    
            // Eliminar capítulos
            $curso->capitulos()->delete();
    
            // Finalmente, eliminar el curso
            $result = $curso->delete();
    
            $mensaje = 'Se ha eliminado el curso y sus recursos correctamente.';
            return $result ? back()->with('mensaje', $mensaje) : back()->with('error', 'No se pudo eliminar el curso.');
        } catch (\Throwable $th) {
            return back()->with('error', $th->getMessage());
        }
    }
    

    public function destroy(Curso $curso)
    {
        $curso->delete();
        return redirect()->route('cursos.index')->with('success', 'Curso eliminado exitosamente');
    }

    public function crearProgreso(Request $request)
    {
        try {
            // Validación de los datos recibidos
            $validatedData = $request->validate([
                'id_usuario' => 'required|exists:usuarios,id',
                'id_curso' => 'required|exists:cursos,id',
                'id_subcapitulo' => 'required|exists:subcapitulos,id',
                'completed' => 'boolean',
            ]);

            // Crear nuevo progreso
            $progress2 = Progress::where('id_curso', $validatedData['id_curso'])->where('id_subcapitulo', $validatedData['id_subcapitulo'])->where('id_usuario', $validatedData['id_usuario'])->first();
            
            if ($progress2) {
                return response()->json(["Error" => "Ya se ha registrado"]);
            }
            $progress = Progress::create([
                'id_usuario' => $validatedData['id_usuario'],
                'id_curso' => $validatedData['id_curso'],
                'id_subcapitulo' => $validatedData['id_subcapitulo'],
                'completed' => $validatedData['completed'] ?? false,
            ]);

            // Devolver una respuesta JSON de éxito
            return response()->json(
                [
                    'message' => 'Progreso guardado correctamente',
                    'progress' => $progress,
                ],
                201,
            );
        } catch (\Exception $e) {
            // Manejo de errores
            return response()->json(
                [
                    'error' => 'Error al crear el progreso',
                    'details' => $e->getMessage(),
                ],
                500,
            );
        }
    }

    public function calcularProgreso($curso)
    {
        try {
            $id_curso = $curso;
            $id_usuario = session()->get('usuario_id');
            $acumulador = 0;

            // Obtener el curso con capítulos y subcapítulos
            $curso = Curso::with(['capitulos.subcapitulos'])->findOrFail($id_curso);

            // Iterar sobre los capítulos y contar los subcapítulos
            foreach ($curso->capitulos as $capitulo) {
                $acumulador += count($capitulo->subcapitulos);
            }

            // Obtener el progreso del usuario en el curso
            $progreso_usuario = Progress::where('id_usuario', $id_usuario)
                ->where('id_curso', $curso->id)
                ->get();
            $acumulador_completed = 0;

            // Contar subcapítulos completados
            foreach ($progreso_usuario as $progreso) {
                if ($progreso->completed) {
                    $acumulador_completed++;
                }
            }

            // Calcular el progreso total en porcentaje
            $total_score = $acumulador > 0 ? ($acumulador_completed / $acumulador) * 100 : 0;

            // Asignar el curso como completado si el progreso es mayor o igual a 8%
            if ($total_score >= 8) {
                Curso_usuario::where('id_usuario', $id_usuario)
                    ->where('id_curso', $id_curso)
                    ->update(['completed' => true]);
            }

            // Devolver una respuesta JSON con el progreso calculado
            return response()->json(
                [
                    'message' => 'Progreso calculado correctamente',
                    'total_score' => $total_score,
                    'completed' => $total_score >= 8,
                ],
                200,
            );
        } catch (\Exception $e) {
            // Manejo de errores
            return response()->json(
                [
                    'error' => 'Error al calcular el progreso',
                    'details' => $e->getMessage(),
                ],
                500,
            );
        }
    }
}

Descripción de Codigo

  1. Índex: Recupera y muestra todos los cursos en la vista cursos.index.

  2. Créate: Muestra el Formulario para crear un nuevo curso.

  3. Generarcertificado: Genera un certificado en formato PDF para un usuario específico que haya completado un curso. Verifica si el curso y el usuario existen antes de proceder, y luego genera el PDF con los datos del curso y del usuario.

  4. Curso_usuario: Muestra la información de un curso específico para un usuario en función de su ID. Verifica si el usuario está inscrito en el curso antes de mostrar la vista del curso con los comentarios.

  5. Crear_curso_admin: Maneja la creación de un curso nuevo, validando los datos recibidos desde el formulario. Este método también maneja la subida de archivos (como imágenes y videos), la creación de capítulos y subcapítulos, y la asociación de estos con el curso.

  6. Mostrarcursos: Muestra todos los cursos en la vista cursos.admin.cursos destinada al administrador.

  7. Mostrarvideocurso: Muestra un video asociado a un curso desde el almacenamiento local, si existe.

  8. Mostrarvideocurso: Muestra la imagen de portada de un curso desde el almacenamiento local, si existe.

  9. Tarjetacurso: Muestra una vista detallada de un curso específico, verificando si el usuario está inscrito en dicho curso.

  10. Mostrarcurso: Muestra la información detallada de un curso específico, incluyendo capítulos y subcapítulos, junto con los comentarios asociados al curso.

  11. Store: Crea un nuevo curso y sus capítulos y subcapítulos asociados, validando los datos proporcionados por el usuario. Usa una transacción de base de datos para garantizar la integridad de los datos.

  12. Show: Muestra la información detallada de un curso específico.

  13. Edit: Muestra el formulario de edición para un curso específico.

  14. Update: Actualiza los datos de un curso existente junto con sus capítulos y subcapítulos, asegurando la validación de los datos proporcionados. Este método también usa una transacción de base de datos.

  15. Expedircertificados: Genera y descarga un certificado en formato PDF para el perfil del usuario, basado en la vista cursos.user.profile.

  16. Eliminar_curso_admin: Elimina un curso específico junto con sus recursos asociados (imágenes, videos, y capítulos). También maneja la eliminación de archivos almacenados localmente.

  17. Destroy: Elimina un curso específico de la base de datos y redirige al índice de cursos con un mensaje de éxito.

  18. Crearprogreso: Crea un nuevo registro de progreso para un usuario en un curso específico, asegurando que no exista un progreso duplicado.

  19. Calcularprogreso: Calcula el progreso del usuario en un curso específico, iterando sobre los capítulos y subcapítulos completados y devolviendo el progreso en formato JSON.

ExamenController

// Some code

PreguntasExamenController

Este controlador sigue las convenciones del controlador de recursos. Un controlador de recursos en Laravel maneja las operaciones CRUD (Crear, Leer, Actualizar, Eliminar) para un modelo específico.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class PreguntasExamenController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        //
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        //
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        //
    }
}

Descripción de Codigo

  1. Index: Este método está destinado a manejar la lógica para mostrar una lista de recursos (en este caso, una lista de preguntas de examen).

  2. Create: Este método se usa para mostrar un formulario para crear un nuevo recurso (una nueva pregunta de examen).

  3. Store: Este método maneja la lógica para almacenar un nuevo recurso en la base de datos. Toma un objeto Request como parámetro, que contiene los datos enviados desde el formulario.

  4. Show: Este método se utiliza para mostrar un recurso específico basado en su identificador ($id).

  5. Update: Este método maneja la lógica para actualizar un recurso existente en la base de datos. Toma como parámetros el objeto Request con los datos actualizados y el identificador del recurso.

  6. Destroy: Este método maneja la lógica para eliminar un recurso específico de la base de datos basado en su identificador.

UserController

Este controlador de Laravel, gestiona diversas operaciones relacionadas con la autenticación y la gestión de usuarios dentro de una plataforma de cursos.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Comentario;
use Illuminate\Support\Facades\Storage;
use App\Models\Curso;
use App\Models\Progress;
use App\Models\Curso_usuario;
use App\Models\Password_recovery;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Mail;
use Carbon\Carbon;
use App\Models\Usuario;
use App\Models\Verificacion;

class UsersControllers extends Controller
{
    public function request_recovery(Request $request)
    {
        try {
            // Validar datos del request
            $validatedData = $request->validate([
                'email' => 'required|max:255',
            ]);
            if (!(preg_match('/^[a-zA-Z0-9._%+-]+@stcs\.com\.mx$/', $request->email))) {
                $error = "El correo electrónico no es el corporativo. Ingresa con el dominio @stcs.com.mx";
                return view('cursos.user.recovery', compact('error'));
            }
            // Buscar el usuario por email
            $usuario = Usuario::where('email', $request->email)->first();

            if (!$usuario) {
                $error = "El correo electrónico no está registrado.";
                return view('cursos.user.recovery', compact('error'));
            }

            // Generar un token de recuperación
            $token = str_pad(rand(0, 999999), 6, '0', STR_PAD_LEFT);
            $recovery = new Password_recovery();
            $recovery->id_usuario = $usuario->id;
            $recovery->token = $token;
            $recovery->expires_at = Carbon::now()->addMinutes(30);
            $recovery->save();

            // Detalles del correo de recuperación
            $details = [
                'server' => 'plataforma de cursos',
                'username' => $usuario->nombre,
                'token' => $token,
                'support_link' => 'https://example.com/support',
                'feedback_link' => 'https://example.com/feedback'
            ];

            // Enviar correo de recuperación
            Mail::to($usuario->email)->send(new \App\Mail\PasswordRecovery($details));
            $id_usuario = $usuario->id;
            return view('cursos.user.recovery_final', compact('id_usuario'));
        } catch (\Throwable $th) {
            $error = $th->getMessage();
            return view('cursos.user.recovery', compact('error', 'id_usuario'));
        }
    }

    
    public function password_recovery(Request $request)
    {
        try {
            // Validación del req body
            $validatedData = $request->validate([
                'token' => 'required|max:10',
                'password' => 'required|max:255',
                'confirm_password' => 'required|max:255',
            ]);

            // Buscamos el token en la base
            $recovery = Password_recovery::where('token', $request->token)->first();

            if (!($recovery || $recovery->expires_at->isFuture())) {
                $error = "El token de recuperación es inválido o ha expirado.";
                return view('cursos.user.recovery_final', compact('error'));
            }

            // Buscamos el usuario
            $usuario = Usuario::find($recovery->id_usuario);

            if (!$usuario) {
                $error = "Usuario no encontrado";
                return view('cursos.user.recovery_final', compact('error'));

            }
            // Actualizamos la contraseña del usuario
            $usuario->password = Hash::make($request->password);
            $usuario->save();

            // Eliminamos el registro de recuperación
            $recovery->delete();
            $id_usuario = $usuario->id;
            $success = true;

            return view('cursos.user.recovery_final', compact('success'));
        } catch (\Throwable $th) {
            $error = $th->getMessage();
            return view('cursos.user.recovery_final', compact('error'));
        }
    }

    public function registroView() {
        return view('cursos.user.register');
    }
    
    public function registro(Request $request) {
        try {

        //Aquí se recibe la data del body (O form)
        $validatedData = $request->validate([
            'nombre' => 'required|max:30',
            'apellidos' => 'required|max:40',
            'email' => 'required|max:255',
            'password' => 'required|max:30',
            'genero' => 'max:30',
            'confirm_password' => 'required|max:30|same:password',
            'fecha_nac' => 'max:50',
        ]);

            //Validamos que sea el correo corporativo
            if (!(preg_match('/^[a-zA-Z0-9._%+-]+@stcs\.com\.mx$/', $request->email))) {
                $error = "El correo electrónico no es el corporativo.";
                return view("cursos.user.register", compact('error'));
            }
            //Validamos si ya existe el correo
            if (Usuario::where('email', $request->email)->exists()) {
                $error = "Correo electrónico ya registrado, por favor inicia sesión.";
                return view("cursos.user.register", compact('error'));
            }

            //Creamos un nuevo objeto Usuario y almacenamos sus datos
            $usuario = new Usuario();
            $usuario->nombre = $request->nombre;
            $usuario->email = $request->email;
            $usuario->genero = $request->genero;
            $usuario->id_rol = 3; // <-- Rol 3 de usuaro por defecto
            $usuario->apellidos = $request->apellidos;
            $usuario->fecha_nac = Carbon::parse($request->fecha_nac); //Se parsea la fecha a una valida por el servidor
            $usuario->password = Hash::make($request->password); //Se encripta la contraseña
            $usuario->save();
    
            $token = str_pad(rand(0, 999999), 6, '0', STR_PAD_LEFT); //Se genera el código de verificación
            $verificacion = new Verificacion(); //Se crea un objeto Verificacion
            $verificacion->id_usuario = $usuario->id; 
            $verificacion->token = $token;
            $verificacion->verified = false;
            $verificacion->expires_at = Carbon::now()->addMinutes(15); //Parsea la hora actual a una valida por el servidor y a la hora actual le suma 15 minutos. (Esto para comparar la hora en la que se ingrese el codigo de verificacion y la hora de expiración)
            $verificacion->save();
            //Almacenamos los datos que se enviarán en el correo.
            $details = [
                'username' => $usuario->nombre,
                'server' => 'plataforma de cursos',
                'code' => $token,
                'reset_link' => 'https://example.com/reset-password',
                '2fa_link' => 'https://example.com/2fa-setup',
                'support_link' => 'https://example.com/support',
                'feedback_link' => 'https://example.com/feedback'
            ];
                Mail::to($usuario->email)->send(new \App\Mail\Verificacion($details));
                $id_usuario = $usuario->id;
                return view("cursos.user.verify", compact('id_usuario'));
        } catch (\Throwable $th) {
                $error = $th->getMessage();
                return view("cursos.user.register", compact('error'));
        }
    }

    public function mostrarImagenUsuario($filename)
    {
        $path = 'usuario/' . $filename;
    
        if (Storage::exists($path)) {
            return response()->file(storage_path('app/' . $path));
        }
    
        abort(404);
    }

    public function verify(Request $request)
    {
        //Validamos los datos del req body
        $validatedData = $request->validate([
            'token' => 'max:10',
            'id_usuario' => 'integer',
        ]);

        if ($request->id_usuario) {
            $verificacion = Verificacion::where('token', $request->token)->where('id_usuario', $request->id_usuario)->first();
            if ($verificacion) {
                if (!$verificacion->verified) {
                    if ($verificacion->expires_at->isFuture()) {
                        $verificacion->verified = true;
                        $verificacion->save();
                        $request->session()->put('logged', true);
                        $request->session()->put('usuario_id', $request->id_usuario);
                        return redirect()->route('index');
                    } else {
                        $verificacion->delete();
                        $id_usuario = $request->id_usuario;
                        $error = "El código de verificación ha expirado.";
                        return view('cursos.user.verify', compact('id_usuario', 'error'));
                    }
                } else {
                    $error = "Usuario ya verificado, por favor inicia sesión.";
                    return view('cursos.user.verify', compact('error'));
                }
            } else {
                $id_usuario = $request->id_usuario;
                if (!$request->token) {
                    $error = "Por favor rellena todos los campos.";
                } else {
                    $error = "Código incorrecto.";
                }
                return view('cursos.user.verify', compact('id_usuario', 'error'));
            }
        }
        $id_usuario = $request->id_usuario;
        return view('cursos.user.verify', compact('id_usuario'));
    }

    public function verifyRequest(Request $request) {
        try {
            $validatedData = $request->validate([
                'email' => 'required|max:255',
            ]);
            if (!(preg_match('/^[a-zA-Z0-9._%+-]+@stcs\.com\.mx$/', $request->email))) {
                $error = "El correo electrónico no es el corporativo.";
                return view("cursos.user.verify", compact('error'));
            }
            $usuario = Usuario::where('email', $request->email)->first();

            if ($usuario) {
                $validar = Verificacion::where('id_usuario', $usuario->id)->first();
                if ($validar) {
                    if ($validar->verified) {
                        $error = "El correo ya ha sido verificado";
                        return view("cursos.user.verify", compact('error'));
                    }
                }
                $token = str_pad(rand(0, 999999), 6, '0', STR_PAD_LEFT); //Se genera el código de verificación
                $verificacion = new Verificacion(); //Se crea un objeto Verificacion
                $verificacion->id_usuario = $usuario->id; 
                $verificacion->token = $token;
                $verificacion->verified = false;
                $verificacion->expires_at = Carbon::now()->addMinutes(15); //Parsea la hora actual a una valida por el servidor y a la hora actual le suma 15 minutos. (Esto para comparar la hora en la que se ingrese el codigo de verificacion y la hora de expiración)
                $verificacion->save();
                //Almacenamos los datos que se enviarán en el correo.
                $details = [
                    'username' => $usuario->nombre,
                    'server' => 'plataforma de cursos',
                    'code' => $token,
                    'reset_link' => 'https://example.com/reset-password',
                    '2fa_link' => 'https://example.com/2fa-setup',
                    'support_link' => 'https://example.com/support',
                    'feedback_link' => 'https://example.com/feedback'
                ];
                    Mail::to($usuario->email)->send(new \App\Mail\Verificacion($details));
                    $id_usuario = $usuario->id;
                    return view("cursos.user.verify", compact('id_usuario'));
            }
            $error = "El correo no está registrado.";
            return view("cursos.user.verify", compact('error'));
        } catch (\Throwable $th) {
                $error = $th->getMessage();
                return view("cursos.user.verify", compact('error'));
        }

    }

    public function verifyApiRequest($id) {
        try {
            $usuario = Usuario::where('id', $id)->first();

            if ($usuario) {
                $validar = Verificacion::where('id_usuario', $usuario->id)->first();
                if ($validar) {
                    if ($validar->verified) {
                        $error = "El correo ya ha sido verificado";
                        return response()->json($error);
                    }
                }
                $token = str_pad(rand(0, 999999), 6, '0', STR_PAD_LEFT); //Se genera el código de verificación
                $verificacion = new Verificacion(); //Se crea un objeto Verificacion
                $verificacion->id_usuario = $usuario->id; 
                $verificacion->token = $token;
                $verificacion->verified = false;
                $verificacion->expires_at = Carbon::now()->addMinutes(15); //Parsea la hora actual a una valida por el servidor y a la hora actual le suma 15 minutos. (Esto para comparar la hora en la que se ingrese el codigo de verificacion y la hora de expiración)
                $verificacion->save();
                //Almacenamos los datos que se enviarán en el correo.
                $details = [
                    'username' => $usuario->nombre,
                    'server' => 'plataforma de cursos',
                    'code' => $token,
                    'reset_link' => 'https://example.com/reset-password',
                    '2fa_link' => 'https://example.com/2fa-setup',
                    'support_link' => 'https://example.com/support',
                    'feedback_link' => 'https://example.com/feedback'
                ];
                    Mail::to($usuario->email)->send(new \App\Mail\Verificacion($details));
                    $id_usuario = $usuario->id;
                    $enviado = true;
                    return response()->json($enviado);
            }
            $error = "El correo no está registrado.";
            return response()->json($error);
        } catch (\Throwable $th) {
                $error = $th->getMessage();
            return response()->json($error);
        }

    }

    public function recoveryView() {
        return view('cursos.user.recovery');
    }
    public function verifyView() {
        return view('cursos.user.verify');
    }

    public function logueoView() {
        return view('cursos.user.login');
    }

    public function logueo(Request $request)
    {
        // Validamos los datos de entrada
        $credentials = $request->only('email', 'password');

        $usuario = Usuario::where('email', $credentials['email'])->first();

        if ($usuario && Hash::check($credentials['password'], $usuario->password)) {
            // Autenticación exitosa, almacenamos la variable de sesión
            
            $request->session()->put('logged', true);
            $request->session()->put('usuario_id', $usuario->id);

            // Redirigir al usuario a la página deseada
            return redirect()->intended('/');
        } else {
            $error = "Contraseña y/o correo incorrectos.";
            return view('cursos.user.login', compact('error') );
        }
        if (!$usuario) {
            $error = "Correo no registrado.";
            return view('cursos.user.login', compact('error') );
        }
    }

    public function logout(Request $request)
    {
        try {
        // Cerramos la sesión del usuario
        $request->session()->forget('logged');
        $request->session()->forget('usuario_id');
        return redirect()->route('login');
    } catch (\Throwable $th) {
        $error = $th->getMessage();
        return redirect()->route('login', compact('error'));
        }
    }

public function index()
    {
        $users = Usuario::all(); // Obtén todos los usuarios
        return view('cursos.admin.usuarioslist', compact('users'));
    }

    public function usuarios() {
        $usuarios = Usuario::all();
        return view('cursos.admin.usuarios', compact('usuarios'));
    }

    public function show($id)
    {
        $user = User::findOrFail($id);
        return response()->json($user);
    }

    public function eliminar_perfil_admin(Request $request) {
        try {
            $request-> validate([
                'id_usuario' => 'required|string|max:255',
            ]);
            $result = Usuario::where('id', $request->id_usuario)->delete();
            $mensaje = 'Se ha eliminado el perfil correctamente.';
            return ($result) ? back()->with('mensaje', $mensaje) : back()->with('error', $error);
        } catch (\Throwable $th) {
            return back()->with('error', $th->getMessage());
        }
    }

    public function actualizar_perfil_admin(Request $request)
    {
        try {
            // Validar el archivo y otros parámetros
            $request->validate([
                'archivo' => 'nullable|file|mimes:jpg,jpeg,png,gif|max:4096', // 4MB en kilobytes
                'nombre' => 'required|max:255',
                'id_rol' => 'required|max:255',
                'email' => 'required|max:255',
                'id_usuario' => 'required|string|max:255',
                'apellidos' => 'required|string|max:255',
                'genero' => 'required|string|max:255',
                'fecha_nac' => 'required|date|before:today', // Asegúrate de que la fecha sea válida
            ]);
            
            $usuario = Usuario::find($request->input('id_usuario'));
            
            if ($usuario) {
                if ($request->hasFile('archivo')) {
                    $nombreArchivo = 'perfil_' . $usuario->id . '.' . $request->file('archivo')->getClientOriginalExtension();
                    $ruta = $request->file('archivo')->storeAs('usuario', $nombreArchivo, 'local');
    
                    $usuario->foto = $nombreArchivo; 
                }
                $usuario->nombre = $request->input('nombre');
                $usuario->id_rol = $request->input('id_rol');
                $usuario->email = $request->input('email');
                $usuario->apellidos = $request->input('apellidos');
                $usuario->fecha_nac = $request->input('fecha_nac');
                $usuario->save();
                
                $mensaje = 'Se ha actualizado el perfil correctamente.';
                return back()->with('mensaje', $mensaje);
            } else {
                return back()->with('error', 'Usuario no encontrado');
            }
        } catch (\Throwable $th) {
            $error = $th->getMessage();
            return back()->with('error', $error);
        }
    }

    public function comentario_usuario(Request $request) {
        try {
            $request->validate([
                'id_usuario' => 'required|string|max:255',
                'id_curso' => 'required|string|max:255',
            ]);
            $Comentario = new Comentario();
            $Comentario->id_usuario = $request->id_usuario;
            $Comentario->id_curso = $request->id_curso;
            $Comentario->contenido = $request->comentario;
            $Comentario->save();
            return back();
        } catch (\Throwable $th) {
            return back()->with('error', $th->getMessage());
        }


    }

    public function usuario_curso(Request $request, $id) {
        try {
            $request->validate([
                'id_usuario' => 'required|string|max:255',
            ]);
    
            $usuario = Usuario::find($request->id_usuario);
            if (!$usuario) {
                return back()->with('error', 'Usuario no encontrado.');
            }
    
            $curso = Curso::find($id);
            if (!$curso) {
                return back()->with('error', 'Curso no encontrado.');
            }
            $verificar_asignacion = Curso_usuario::where('id_usuario', $usuario->id)->where('id_curso', $curso->id)->first();
            
            if ($verificar_asignacion) {
                return back()->with('error', 'Ya estás inscrito en el curso.: ');
            }
            $asignar_curso = new Curso_usuario();
            $asignar_curso->diploma = "0";
            $asignar_curso->valoracion = "0";
            $asignar_curso->progreso = 0.0;
            $asignar_curso->id_usuario = $usuario->id;
            $asignar_curso->id_curso = $curso->id;
            $asignar_curso->save();
    
            return redirect()->route('curso.usuario', $id);
        } catch (\Throwable $th) {
            // Manejo de errores
            return back()->with('error', 'Ocurrió un error al asignar el curso: ' . $th->getMessage());
        }
    }
    

    public function actualizar_perfil(Request $request)
    {
        try {
            // Validar el archivo y otros parámetros
            $request->validate([
                'archivo' => 'nullable|file|mimes:jpg,jpeg,png,gif|max:4096', // 4MB en kilobytes
                'nombre' => 'required|max:255',
                'id_usuario' => 'required|string|max:255',
                'apellidos' => 'required|string|max:255',
                'genero' => 'required|string|max:255',
                'fecha_nac' => 'required|date|before:today', // Asegúrate de que la fecha sea válida
            ]);
            
            $usuario = Usuario::find($request->input('id_usuario'));
            
            if ($usuario) {
                if ($request->hasFile('archivo')) {
                    $nombreArchivo = 'perfil_' . $usuario->id . '.' . $request->file('archivo')->getClientOriginalExtension();
                    $ruta = $request->file('archivo')->storeAs('usuario', $nombreArchivo, 'local');
    
                    $usuario->foto = $nombreArchivo; 
                }
                $usuario->nombre = $request->input('nombre');
                $usuario->genero = $request->genero;
                $usuario->apellidos = $request->input('apellidos');
                $usuario->fecha_nac = $request->input('fecha_nac');
                $usuario->save();
                
                $mensaje = 'Se ha actualizado el perfil correctamente.';
                return back()->with('mensaje', $mensaje);
            } else {
                return back()->with('error', 'Usuario no encontrado');
            }
        } catch (\Throwable $th) {
            $error = $th->getMessage();
            return back()->with('error', $error);
        }
    }
    
    


    public function mostrarUsuario(Request $request, $id) {
        try {
            $usuario = Usuario::where('id', $id)->first();
            if (!$usuario) {
                return response()->json(['error' => 'Usuario no encontrado'], 404);
            }
            return response()->json($usuario);
        } catch (\Throwable $th) {
            return response()->json(['error' => $th->getMessage()], 500);
        }
    }
    

    public function perfil(Request $request) {
        $id_usuario = $request->session()->get('usuario_id');
        $usuario = Usuario::where('id', $id_usuario)->first();
    
        $cursos = Curso_usuario::where('id_usuario', $usuario->id)->get();
        
        if (!$cursos) {
            $resultados = false;
            return view('cursos.user.profile', compact('usuario', 'resultados'));
        }

        $cursos_info = [];
    
        foreach ($cursos as $curso_usuario) {
            $curso = Curso::with(['capitulos.subcapitulos'])->findOrFail($curso_usuario->id_curso);
    
            $acumulador = 0;
    
            foreach ($curso->capitulos as $capitulo) {
                $acumulador += count($capitulo->subcapitulos);
            }
    
            $progreso_usuario = Progress::where('id_usuario', $id_usuario)
                ->where('id_curso', $curso->id)
                ->get();

            $acumulador_completed = 0;

            foreach ($progreso_usuario as $progreso) {
                if ($progreso->completed) {
                    $acumulador_completed++;
                }
            }
    
            $total_score = $acumulador > 0 ? ($acumulador_completed / $acumulador) * 100 : 0;
    
            if ($total_score >= 8) {
                Curso_usuario::where('id_usuario', $id_usuario)
                    ->where('id_curso', $curso->id)
                    ->update(['completed' => true]);
            }
    
            $resultados[] = [
                'id' => $curso->id,
                'titulo' => $curso->titulo,
                'porcentaje' => $total_score,
                'imagen' => $curso->imagen // Asumiendo que el campo de la imagen se llama 'imagen'
            ];
        }
        if (!isset($resultados)) {
            return view('cursos.user.profile', compact('usuario'));
        }
    
        return view('cursos.user.profile', compact('usuario', 'resultados'));
    }
    
    
}

Descripción de Codigo

  1. Request_recovery: Valida si el correo electrónico proporcionado pertenece al dominio corporativo, verifica si el usuario existe en la base de datos , genera un token de recuperación que expira en 30 minutos y lo envía por correo electrónico al usuario.

  2. Password_recovery: Valida el token de recuperación y las nuevas contraseñas ingresadas, verifica si el token es válido y no ha expirado, si es válido, actualiza la contraseña del usuario y elimina el registro del token, muestra una vista con un mensaje de éxito o error.

  3. Registroview: Muestra la vista de registro para nuevos usuarios.

  4. Registro: Valida los datos ingresados en el formulario de registro, verifica si el correo electrónico ya está registrado y si pertenece al dominio corporativo, crea un nuevo usuario, lo guarda en la base de datos, y genera un código de verificación que se envía por correo electrónico, redirige a la vista de verificación con el ID del usuario.

  5. Verify: Valida el token de verificación y el ID del usuario, verifica si el token es válido y no ha expirado, si es válido, marca al usuario como verificado, almacena su sesión, y redirige al índice de la plataforma.

  6. VerifyRequest: Genera un nuevo token de verificación para un usuario existente y lo envía por correo electrónico.

  7. Logueo: Muestra la vista de inicio de sesión, valida las credenciales ingresadas, verifica si el usuario existe y si la contraseña es correcta, si es correcto, almacena la sesión del usuario y lo redirige a la página principal.

  8. Gestion usuarios: Muestra una lista de todos los usuarios registrados, muestra una vista con todos los usuarios en la plataforma, elimina el perfil de un usuario específico, actualiza el perfil de un usuario, incluyendo su información personal y su imagen de perfil.

  9. Usuario_curso: Asigna un curso específico a un usuario, verificando si ya está inscrito o no.

  10. MostrarImagenUsuario: Muestra la imagen de perfil del usuario almacenada en el servidor.

Last updated