merged
antoine.perederii 1 year ago
commit 7bbedee03c

@ -1,65 +0,0 @@
kind: pipeline
type: docker
name: HeartTrack
trigger:
branch:
- master
- merged
event:
- push
steps:
# Test ✔️
- name: test
image: composer:2.6
commands:
- cd Sources
# Installe les dépendances PHP si nécessaire
- composer install --no-interaction
- ./vendor/bin/phpunit tests
# Sonar static code analisis deployment
# TODO : use an image that already have unzip
- name: code-analysis
image: php:8.1-cli
environment:
SONAR_TOKEN:
from_secret: SONAR_TOKEN
commands:
- apt-get update && apt-get install -y curl unzip
- export SONAR_SCANNER_VERSION=4.7.0.2747
- export SONAR_SCANNER_HOME=$HOME/.sonar/sonar-scanner-$SONAR_SCANNER_VERSION-linux
- curl --create-dirs -sSLo $HOME/.sonar/sonar-scanner.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-$SONAR_SCANNER_VERSION-linux.zip
- unzip -o $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/
- export PATH=$SONAR_SCANNER_HOME/bin:$PATH
- export SONAR_SCANNER_OPTS="-server"
- cd Sources
- sonar-scanner -D sonar.projectKey=HeartTrack -D sonar.host.url=https://codefirst.iut.uca.fr/sonar
depends_on: [ test ]
# build image and push on the registry ✔️
- name: docker-build-and-push
image: plugins/docker
settings:
dockerfile: Sources/config/Dockerfile
context: Sources
registry: hub.codefirst.iut.uca.fr
repo: hub.codefirst.iut.uca.fr/david.d_almeida/web
username:
from_secret: SECRET_REGISTRY_USERNAME
password:
from_secret: SECRET_REGISTRY_PASSWORD
git_auth: true
- name: notify
image: ruby:2.1
when:
status: [ success ]
ref:
include:
- refs/tags/*-demo
commands:
- sh ./notifymail.sh
depends_on: [ docker-build-and-push ]

1
.gitignore vendored

@ -6,6 +6,7 @@ dist
*.swo
.env
loginDatabase.php
# Cache file on macOS
.DS_Store

@ -0,0 +1,243 @@
[retour au README.md](../../../README.md)
[Retour aux Documents](../../README_DOCUMENTS.md)
[Retour au diagramme de classes](../README_DIAGRAMMES.md)
# BDD
```plantuml
@startuml
skinparam classAttributeIconSize 0
package MLD{
entity "Athlete" as athlete {
{static} idAthlete
username
nom
prenom
email
sexe
taille
poids
motDePasse
dateNaissance
isCoach
}
entity "Amitie" as friendship{
{static}# idAthlete1
{static}# idAthlete2
début
}
entity "Notification" as notif {
{static} idNotif
message
date
statut
urgence
#athleteId
}
entity "Envoi" as sendNotif{
{static}# idAthlete
{static}# idNotif
}
entity "Statistique" as stats {
{static} idStatistique
poids
fcMoyenne
fcMax
caloriesBruleesMoy
date
#athleteId
}
entity "Entrainement" as training {
{static} idEntrainement
date
description
latitude
longitude
feedback
#athleteId
}
entity "Participe" as takepart {
{static} #athleteId
{static} #entrainementId
}
entity "Donne" as givepart {
{static} #coachId
{static} #entrainementId
}
entity "SourceDonnee" as source {
{static} idSource
type
modele
precision
#athleteId
}
entity "Activite" as activity {
{static} idActivité
type
date
heureDeDebut
heureDeFin
effortRessent
variabilite
variance
ecartType
moyenne
maximum
minimum
temperatureMoyenne
#athleteId
#sourceId
}
entity "FréquenceCardiaque" as fc {
{static} idFc
altitude
temps : time
température
bpm
longitude
latitude
#activitéId
}
}
activity --> athlete
activity --> source
activity <-- fc
athlete <-- source
stats --> athlete
takepart --> athlete
takepart --> training
givepart --> athlete
givepart --> training
sendNotif --> athlete
sendNotif --> notif
friendship --> athlete
notif --> athlete
athlete <-- friendship
@enduml
```
```plantuml
@startuml
class Athlete {
idAthlete
username
nom
prenom
email
sexe
taille
poids
motDePasse
dateNaissance
isCoach
}
class Amitie {
idAthlete1
idAthlete2
}
class Notification {
idNotif
message
date
statut
urgence
athleteId
}
class Envoi {
idAthlete
idNotif
}
class Statistique {
idStatistique
poids
fcMoyenne
fcMax
caloriesBruleesMoy
date
athleteId
}
class Entrainement {
idEntrainement
date
description
latitude
longitude
feedback
athleteId
}
class Participe {
athleteId
entrainementId
}
class Donne {
coachId
entrainementId
}
class SourceDonnee {
idSource
type
modele
precision
athleteId
}
class Activite {
idActivite
type
date
heureDeDebut
heureDeFin
effortRessent
variabilite
variance
ecartType
moyenne
maximum
minimum
temperatureMoyenne
athleteId
sourceId
}
class FrequenceCardiaque {
idFc
altitude
temps
temperature
bpm
longitude
latitude
activiteId
}
Athlete "1" --o "0..*" Amitie
Athlete "1" --o "0..*" Notification
Athlete "1" --o "0..*" Statistique
Athlete "1" --o "0..*" Entrainement
Entrainement "0..*" --o "0..*" Athlete : Participants
Entrainement "0..*" --o "0..*" Athlete : Coachs
Athlete "1" --o "0..*" SourceDonnee
Activite "1" --o "0..*" FrequenceCardiaque
@enduml
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 2.0 MiB

@ -18,13 +18,14 @@
"Shared\\": "src/shared",
"App\\Router\\": "src/app/router",
"App\\Controller\\": "src/app/controller",
"App\\Router\\Response\\" : "src/app/router/response",
"App\\Router\\Middleware\\" : "src/app/router/middleware",
"App\\Router\\Request\\" : "src/app/router/request",
"App\\Router\\Response\\": "src/app/router/response",
"App\\Router\\Middleware\\": "src/app/router/middleware",
"App\\Router\\Request\\": "src/app/router/request",
"Shared\\Exception\\": "src/shared/exception",
"Shared\\Attributes\\": "src/shared/attributes",
"App\\Views\\Directives\\" : "src/app/views/directives",
"Data\\Core\\": "src/data/core/"
"Data\\Core\\": "src/data/core/",
"Database\\": "src/data/core/database"
}
},
"require": {
@ -36,12 +37,15 @@
"ext-couchbase": "*",
"ext-pdo": "*"
},
"config": {
"process-timeout": 2000
},
"require-dev": {
"phpunit/phpunit": "*"
},
"scripts": {
"dev": "php -S localhost:8080 -t public -d display_errors=1 -d error_reporting=E_ALL",
"dev:console": "export APP_ENV=console && php public/index.php",
"dev:html" : "export APP_ENV=html && php -S localhost:8080 -t public -d display_errors=1 -d error_reporting=E_ALL"
"dev:html": "export APP_ENV=html && php -S localhost:8080 -t public -d display_errors=1 -d error_reporting=E_ALL"
}
}

@ -10,12 +10,13 @@ $dotenv->safeLoad();
// const DB_DATABASE = $_ENV['DB_DATABASE'] ?? 'heartTrack';
// const DB_USER = $_ENV['DB_USER'] ?? 'toto';
// const DB_PASSWORD = $_ENV['DB_PASSWORD'] ?? 'achanger';
define("APP_ENV", 'development');
define("APP_ENV", getenv('APP_ENV'));
const DB_SERVER = 'mysql';
const DB_HOST = 'localhost';
const DB_DATABASE = 'heartTrack';
const DB_USER = 'toto';
const DB_PASSWORD = 'achanger';
const DB_DATABASE = 'sae_3';
const DB_USER = 'Perederii';
const DB_PASSWORD = '';
//const APP_ENV = 'console';
const DSN = "mysql:host=" . DB_HOST . ";dbname=" . DB_DATABASE;
const DSN = DB_SERVER . ":host=" . DB_HOST . ";dbname=" . DB_DATABASE;

@ -12,7 +12,7 @@ use Manager\DataManager;
use Repository\IUserRepository;
use Shared\ArgumentControllerResolver;
use Shared\IArgumentResolver;
use Stub\AuthService;
use Network\AuthService;
use Stub\NotificationRepository;
use Stub\TrainingRepository;
use Stub\UserRepository;
@ -30,13 +30,13 @@ use Network\RelationshipService;
use Network\INotificationService;
use Stub\NotificationService;
use App\Router\Session;
use Stub\StubData;
use Twig\Environment;
use Twig\Loader\FilesystemLoader;
use Shared\IHashPassword;
use Shared\HashPassword;
use Shared\Log;
$appFactory = new AppCreator();
$appFactory->registerService(IArgumentResolver::class, ArgumentControllerResolver::class);
@ -54,7 +54,6 @@ $appFactory->registerService(IUserRepository::class, UserRepository::class);
$appFactory->registerService(\Twig\Loader\LoaderInterface::class, function() {
return new FilesystemLoader(__DIR__ . '/../src/app/views/Templates');
});
@ -69,7 +68,7 @@ $app = $appFactory->create();
if (!is_null($app)){
// Ajout des Middleware
/*$app->use(new LoggingMiddleware());*/
$app->use(new AuthMiddleware());
$app->use(new AuthMiddleware($appFactory->getDicontainer()->get(IAuthService::class) ));
$app->mapControllers();
$app->run(RequestFactory::createFromGlobals());
}

@ -29,9 +29,6 @@ class App
private FrontController $frontController;
private Session $session;
public function __construct(string $appName, int $version, \App\Container $diContainer)
{
$this->appName = $appName;
@ -39,7 +36,7 @@ class App
$this->container = $diContainer;
$this->router = new Router("");
$this->frontController = new FrontController($this->router,$this->container);
$this->session = Session::getInstance();
Session::getInstance();
}
public function use(IHttpMiddleware $middleware)
@ -142,7 +139,7 @@ class App
$route = $attribute->newInstance();
$this->router->addControllerRoute(
implode('|', $route->getMethods()),
$route->getMethods(),
$prefix . $route->getPath(),
$controllerClass,
$method->getName(),

@ -24,6 +24,13 @@ class AppCreator
return $this;
}
public function registerSingleton(string $serviceId, $service): self
{
$this->container->set($serviceId, $service, Container::SINGLETON);
$this->services[] = $serviceId;
return $this;
}
/**
* Create an instance or perform actions based on the current application environment.
*
@ -33,6 +40,7 @@ class AppCreator
{
// Check the application environment
switch (APP_ENV) {
case 'console':
// Load the Console.php file in case of the 'console' environment
require_once __DIR__ . '/../console/Console.php';
@ -40,7 +48,6 @@ class AppCreator
case 'development':
// Create a new instance of the App class in the 'development' environment
return new App("HeartTrack", 1, $this->container);
break;
case 'html':
// Load the index.test.php file in case of the 'html' environment
require_once __DIR__ . '/index.test.php';
@ -53,7 +60,6 @@ class AppCreator
}
function AddControllers($namespacePrefix = 'App\Controller', $pathToControllers = __DIR__ . '/controller'): self
{
$controllerFiles = glob($pathToControllers . '/*.php');
@ -71,7 +77,8 @@ class AppCreator
if ($reflectionClass->isSubclassOf(BaseController::class)) {
// Register in DI container
$this->container->set($fullClassName, function () use ($fullClassName) {
$controllerInstance = new $fullClassName();
/** @var $controllerInstance * */
$controllerInstance = $this->container->resolve($fullClassName);
$controllerInstance->setContainer($this->container);
return $controllerInstance;
});
@ -81,11 +88,15 @@ class AppCreator
return $this;
}
public function getServiceRegistered(): array
{
return $this->services;
}
public function getDicontainer()
{
return $this->container;
}
}

@ -11,31 +11,45 @@ class Container implements ContainerInterface
{
private array $entries = [];
const SINGLETON = 'singleton';
const TRANSIENT = 'transient';
public function get(string $id)
{
if ($this->has($id)) {
$entry = $this->entries[$id];
if (is_callable($entry)) {
return $entry($this);
if ($entry['lifecycle'] === self::SINGLETON) {
if ($entry['instance'] === null) {
$entry['instance'] = $this->resolve($entry['concrete']);
}
return $entry['instance'];
}
$id = $entry;
if (is_callable($entry['concrete'])) {
return $entry['concrete']($this);
}
return $this->resolve($entry['concrete']);
}
return $this->resolve($id);
}
public function has(string $id): bool
{
return isset($this->entries[$id]);
}
public function set(string $id, callable|string $concrete): void
public function set(string $id, callable|string $concrete, string $lifecycle = self::TRANSIENT): void
{
$this->entries[$id] = $concrete;
$this->entries[$id] = [
'concrete' => $concrete,
'lifecycle' => $lifecycle,
'instance' => null
];
}
public function resolve(string $id)

@ -1,8 +1,19 @@
<?php
namespace App\Controller;
namespace App\Controller;
use Database\ActivityGateway;
use Database\ActivityMapper;
use Database\AnalyzeGateway;
use Database\AthleteEntity;
use Database\AthleteMapper;
use Database\EntrainementGateway;
use Database\EntrainementMapper;
use Database\NotificationEntity;
use Database\NotificationGateway;
use Database\NotificationMapper;
use DateTime;
use Model\Notification;
use Shared\Validation;
use App\Container;
use App\Router\Request\IRequest;
@ -12,92 +23,229 @@ use Twig\Environment;
use Data\Core\Preferences;
use Shared\Log;
use Manager\UserManager;
use Database\Connexion;
use Database\AthleteGateway;
class AthleteController extends BaseController
{
private Environment $twig;
protected Preferences $preference;
// private UserManager $userMgr;
public function __construct()
{
//session_start();
$this->preference = new Preferences();
// $this->userMgr = $manager;
}
// #[Route(path: '/search-user', name: 'search-user', methods: ['GET'])]
// public function searchUser(string $username, IRequest $req): Response
// {
// $taberror = [];
// if(!Validation::val_string($username)){
// print("Nom invalide.");
// }
// else {
// try {
// $athleteGateway = new AthleteGateway(new Connexion("mysql:host=localhost;dbname=sae_3", "Perederii", ""));
//// $listSearch=$this->container->get(UserManager::class)->searchUsersByName($username);
// $listSearch = $athleteGateway->getAthlete();
// $map = new AthleteMapper ();
// $athleteEntity = $map->athleteSqlToEntity($listSearch);
// foreach ($athleteEntity as $entity) {
// $users = $map->athleteEntityToModel($entity);
// $listUsers[$i++]=['nom' => $users->getNom(), 'prenom'=>$users->getPrenom(), 'img'=>'john_doe'];
// }
//
// $i=0;
// foreach ($users as $user){
// echo "<h1> HELLO </h1>";
// $listUsers[$i++]=['nom' => $user->getNom(), 'prenom'=>$user->getPrenom(), 'img'=>'john_doe', 'username'=>$user->getUsername()];
// }
// echo "<h1> HEllO </h1>";
// //$currentUser=$this->container->get(UserManager::class)->getCurrentUser();
// //$currentUser=$_SESSION['user'];
// $response = $this->render('./page/addfriend.html.twig',[
// 'css' => $_COOKIE['preferences'],
// 'pp' => "test",
// 'user' => 'johndoe',//$currentUser->getUsername(),
// 'role' => 'Athlete',//$currentUser->getRole(),
// 'users' => $listUsers
// ]);
// } catch (\Throwable $th) {
// throw $th;
// return $this->render("addfriend.html.twig", ['tabError' => $taberror ]);
// }
// }
// return $response;
//
// }
#[Route(path: '/search-user', name: 'search-user', methods: ['GET'])]
public function searchUser(string $username, IRequest $req): Response
{
$taberror = [];
if(!Validation::val_string($username)){
if (!Validation::val_string($username)) {
print("Nom invalide.");
}
else {
} else {
try {
$listSearch=$this->container->get(UserManager::class)->searchUsersByName($username);
$i=0;
foreach ($listSearch as $user){
$listUsers[$i++]=['nom' => $user->getNom(), 'prenom'=>$user->getPrenom(), 'img'=>'john_doe', 'username'=>$user->getUsername()];
$athleteGateway = new AthleteGateway(new Connexion(DSN, DB_USER, DB_PASSWORD));
if($username==null){
$listSearch=$athleteGateway->getAthlete();
} else {
$listSearch = $athleteGateway->getAthleteByName($username);
}
//$currentUser=$this->container->get(UserManager::class)->getCurrentUser();
//$currentUser=$_SESSION['user'];
$map = new AthleteMapper();
$athleteEntity = $map->athleteSqlToEntity($listSearch);
$listUsers = [];
foreach ($athleteEntity as $entity) {
$user = $map->athleteEntityToModel($entity);
$listUsers[] = ['idathlete' => number_format($user->getId(), 1), 'nom' => $user->getNom(),
'prenom' => $user->getPrenom(),'email' => $user->getEmail(), 'sexe' => $user->getSexe(),
'taille' => $user->getTaille(), 'poids' => $user->getPoids(), 'motdepasse' => $user->getMotDePasse(),
'datenaissance' => $user->getDateNaissance(), 'iscoach' => $user->getRole(), 'img' => 'test',
'username' => $user->getUsername()];
}
$response = $this->render('./page/addfriend.html.twig',[
'css' => $_COOKIE['preferences'],
'pp' => "test",
'user' => 'johndoe',//$currentUser->getUsername(),
'pp' => 'test',
'user' => 'John',//$currentUser->getUsername(),
'role' => 'Athlete',//$currentUser->getRole(),
'users' => $listUsers
]);
} catch (\Throwable $th) {
throw $th;
return $this->render("addfriend.html.twig", ['tabError' => $taberror ]);
return $this->render("addfriend.html.twig", ['tabError' => $taberror]);
}
}
return $response;
}
#[Route(path: '/analyses', name: 'analyses', methods: ['GET'])]
public function analyses(): Response
#[Route(path: '/analyze', name: 'analyze_details', methods: ['GET'])]
public function activityDetails(int $id): Response
{
return $this->render('./page/analyze.html.twig',[
try {
// Utilisez $id pour récupérer les détails de l'activité depuis la base de données
// $activityGateway = new ActivityGateway(new Connexion(DSN, DB_USER, DB_PASSWORD));
// $activityEntity = $activityGateway->getActivityById($id); // Assurez-vous d'avoir une méthode similaire dans votre gateway
$analyzeGateway = new AnalyzeGateway(new Connexion(DSN, DB_USER, DB_PASSWORD));
$analyzeEntity = $analyzeGateway->getFrequenceCardiaqueByIdActivity($id);
$response = $this->render('./page/analyze.html.twig', [
'css' => $this->preference->getCookie(),
'pp' => "test2",
'user' => 'johndoe',//$currentUser->getUsername(),
'role' => 'Athlete',//$currentUser->getRole(),
'friendship' => [],
'analyzes' => [],
'mails' => [],
'users' => [],
'infoUser' => [],
'exos' => [],
'member' => []
'activity' => [],
'analyzes' => $analyzeEntity,
]);
} catch (\Throwable $th) {
throw $th;
return $this->render("./page/analyze.html.twig", ['tabError' => $taberror]);
}
return $response;
}
//
// #[Route(path: '/analyses/{id}', name: 'analyses', methods: ['GET'])]
// public function analyses(): Response
// {
// try {
// $activityGateway = new ActivityGateway(new Connexion(DSN, DB_USER, DB_PASSWORD));
// $listSearch = $activityGateway->getActivity();
// $map = new ActivityMapper();
// $activityGateway = $map->activitySqlToEntity($listSearch);
// $listActivity = [];
// foreach ($activityGateway as $entity) {
// $activity = $map->activityEntityToModel($entity);
// $listActivity[] = ['idactivity' => number_format($activity->getIdActivity(), 1), 'type' => $activity->getType(),
// 'date' => $activity->getDate()->format("D j F Y"), 'heureDebut' => $activity->getHeureDebut()->format("H\h i"), 'heureFin' => $activity->getHeureFin()->format("H\h i"),
// 'effortRessenti' => $activity->getEffortRessenti(), 'variabilite' => $activity->getVariability(), 'variance' => $activity->getVariance(),
// 'ecartType' => $activity->getStandardDeviation(), 'moyenne' => $activity->getAverage(),
// 'max' => $activity->getMaximum(), 'min' => $activity->getMinimum(), 'temperature' =>$activity->getAvrTemperature()];
// }
//
// $response = $this->render('./page/analyze.html.twig',[
// 'css' => $this->preference->getCookie(),
// 'pp' => "test2",
// 'user' => 'johndoe',//$currentUser->getUsername(),
// 'role' => 'Athlete',//$currentUser->getRole(),
// 'friendship' => [],
// 'analyzes' => $listActivity,
// 'mails' => [],
// 'users' => [],
// 'infoUser' => [],
// 'exos' => [],
// 'member' => []
// ]);
// } catch (\Throwable $th) {
// throw $th;
// return $this->render("./page/analyze.html.twig", ['tabError' => $taberror]);
// }
// return $response;
// }
#[Route(path: '/activity', name: 'activity', methods: ['GET'])]
public function activity(): Response
{
return $this->render('./page/activity.html.twig',[
try {
$activityGateway = new ActivityGateway(new Connexion(DSN, DB_USER, DB_PASSWORD));
$listSearch = $activityGateway->getActivity();
$map = new ActivityMapper();
$activityGateway = $map->activitySqlToEntity($listSearch);
$listActivity = [];
foreach ($activityGateway as $entity) {
$activity = $map->activityEntityToModel($entity);
$listActivity[] = ['idactivity' => number_format($activity->getIdActivity()), 'type' => $activity->getType(),
'date' => $activity->getDate()->format("D j F Y"), 'heureDebut' => $activity->getHeureDebut()->format("H\h i"), 'heureFin' => $activity->getHeureFin()->format("H\h i"),
'effortRessenti' => $activity->getEffortRessenti(), 'variabilite' => $activity->getVariability(), 'variance' => $activity->getVariance(),
'ecartType' => $activity->getStandardDeviation(), 'moyenne' => $activity->getAverage(),
'max' => $activity->getMaximum(), 'min' => $activity->getMinimum(), 'temperature' => $activity->getAvrTemperature()];
}
$response = $this->render('./page/activity.html.twig', [
'css' => $this->preference->getCookie(),
'pp' => "test",
'pp' => "test2",
'user' => 'johndoe',//$currentUser->getUsername(),
'role' => 'Athlete',//$currentUser->getRole(),
'friendship' => [],
'analyzes' => [],
'analyzes' => $listActivity,
'mails' => [],
'users' => [],
'infoUser' => [],
'exos' => [],
'member' => []
]);
} catch (\Throwable $th) {
throw $th;
return $this->render("./page/analyze.html.twig", ['tabError' => $taberror]);
}
return $response;
}
#[Route(path: '/exercice', name: 'exercice', methods: ['GET'])] // 8
public function exercice(): Response
{
return $this->render('./page/exercice.html.twig',[
try {
$entrainementGateway = new EntrainementGateway(new Connexion(DSN, DB_USER, DB_PASSWORD));
$listSearch = $entrainementGateway->getEntrainements();
$map = new EntrainementMapper();
$entrainementEntity = $map->entrainementSqlToEntity($listSearch);
$listUsers = [];
foreach ($entrainementEntity as $entity) {
$training = $map->entrainementEntityToModel($entity);
$listUsers[] = ['idTraining' => number_format($training->getId(), 1), 'date' => $training->getDate()->format("D j F Y"),
'location' => $training->getLocation(), 'description' => $training->getDescription(),
'feedback' => $training->getFeedback()];
}
$response = $this->render('./page/exercice.html.twig',[
'css' => $this->preference->getCookie(),
'pp' => "test2",
'user' => 'johndoe',//$currentUser->getUsername(),
@ -107,9 +255,15 @@ class AthleteController extends BaseController
'mails' => [],
'users' => [],
'infoUser' => [],
'exos' => [],
'exos' => $listUsers,
'member' => []
]);
} catch (\Throwable $th) {
throw $th;
return $this->render("addfriend.html.twig", ['tabError' => $taberror]);
}
return $response;
}
#[Route(path: '/exercices', name: 'exercices', methods: ['POST'])] // 8
@ -142,12 +296,21 @@ class AthleteController extends BaseController
public function addFriend(string $username, IRequest $req): Response
{
try {
//Ajouter la personne sur laquelle on a clique dans la liste de currentuser
$listSearch=$this->container->get(UserManager::class)->searchUsersByName($username);
$i=0;
foreach ($listSearch as $user){
$listUsers[$i++]=['nom' => $user->getNom(), 'prenom'=>$user->getPrenom(), 'img'=>'test', 'username'=>$user->getUsername()];
$athleteGateway = new AthleteGateway(new Connexion(DSN, DB_USER, DB_PASSWORD));
$map = new AthleteMapper();
$userSearched = $athleteGateway->getAthleteByFirstName("Bryan");
$athleteEntity = $map->athleteSqlToEntity($userSearched);
$users=[];
foreach ($athleteEntity as $user) {
// $this->userMgr->getCurrentUser()->addFriend($user);
// $currentUser->addFriend($user);
$users = ['nom' => $user->getNom(), 'prenom' => $user->getPrenom(), 'img' => 'test', 'username' => $user->getUsername()];
}
$notif = new NotificationGateway(new Connexion(DSN, DB_USER, DB_PASSWORD));
$mapper = new NotificationMapper();
$date = new DateTime();
$myNotif = new Notification(21, "Demande d'ami de la part de " . $users['nom'], $date, true, 7, 1);
$notif->addNotification($mapper->notificationToEntity($myNotif));
return $this->render('./page/addfriend.html.twig',[
'css' => $this->preference->getCookie(),
'pp' => "test2",
@ -156,7 +319,7 @@ class AthleteController extends BaseController
'friendship' => [],
'analyzes' => [],
'mails' => [],
'users' => $listUsers,
'users' => $users,
'infoUser' => [],
'exos' => [],
'member' => [],
@ -171,7 +334,18 @@ class AthleteController extends BaseController
#[Route(path: '/friend', name: 'friend', methods: ['GET'])]
public function friend(): Response
{
return $this->render('./page/addfriend.html.twig',[
try {
$athleteGateway = new AthleteGateway(new Connexion(DSN, DB_USER, DB_PASSWORD));
$map=new AthleteMapper();
$friendEntity = $athleteGateway->getAthlete();
$listUserEntity = $map->athleteSqlToEntity($friendEntity);
$friendList = [];
foreach ($listUserEntity as $userEntity) {
$friendList[] = ['nom' => $userEntity->getNom(), 'prenom' => $userEntity->getPrenom(), 'img' => 'test', 'username' => 'test'];
}
$response = $this->render('./page/addfriend.html.twig',[
'css' => $this->preference->getCookie(),
'pp' => "test2",
'user' => 'John',//$currentUser->getUsername(),
@ -179,11 +353,17 @@ class AthleteController extends BaseController
'friendship' => [],
'analyzes' => [],
'mails' => [],
'users' => [],
'users' => $friendList,
'infoUser' => [],
'exos' => [],
'member' => [],
]);
} catch (\Throwable $th) {
throw $th;
return $this->render("addfriend.html.twig", ['tabError' => $taberror]);
}
return $response;
}
/*#[Route(path: '/friendlist', name: 'friendlist', methods: ['POST'])]
@ -219,20 +399,38 @@ class AthleteController extends BaseController
#[Route(path: '/friendlist', name: 'friendlist2', methods: ['GET'])]
public function friendlist2(): Response
{
$friendList = $this->container->get(UserManager::class)->getFriends();//$currentUser->getFriends();
return $this->render('./page/friend.html.twig',[
try {
$athleteGateway = new AthleteGateway(new Connexion(DSN, DB_USER, DB_PASSWORD));
$map=new AthleteMapper();
$friendEntity = $athleteGateway->getListIdFriends(1/*$currentUser->getId()*/);
$friendList = [];
$listUserEntity = [];
foreach($friendEntity as $users) {
if ($users['idathlete1']==1/*$currentUser->getId()*/){
$user=(int)$users['idathlete2'];
} else {
$user=(int)$users['idathlete1'];
}
$listUserEntity[] = $map->athleteSqlToEntity($athleteGateway->getAthleteById(1));
}
foreach ($listUserEntity as $user) {
$friendList[] = ['nom' => $user[0]->getNom(), 'prenom' => $user[0]->getPrenom(), 'img' => 'test', 'username' => 'test'];
}
$response = $this->render('./page/friend.html.twig',[
'css' => $this->preference->getCookie(),
'pp' => "test2",
'user' => "Doe",
'role' => "Athlète",
'friendship' => $friendList,
'analyzes' => [],
'mails' => [],
'users' => [],
'infoUser' => [],
'exos' => [],
'member' => [],
]);
} catch (\Throwable $th) {
throw $th;
return $this->render("addfriend.html.twig", ['tabError' => $taberror]);
}
return $response;
}
// #[Route(path: '/delete-friend', name: 'delete-friend', methods: ['POST'])]

@ -4,171 +4,179 @@ namespace App\Controller;
use App\Container;
use App\Router\Request\IRequest;
use App\Router\Response\RedirectResponse;
use App\Router\Response\Response;
use App\Router\Response\IResponse;
use App\Router\Session;
use Database\AthleteGateway;
use Database\AthleteMapper;
use Database\Connexion;
use Manager\UserManager;
use Shared\Attributes\Route;
use Shared\Validation;
use Twig\Environment;
use Data\Core\Preferences;
use Shared\Log;
use function PHPUnit\Framework\isEmpty;
class AuthController extends BaseController
{
protected Preferences $preference;
public function __construct(){
$this->preference = new Preferences();
private UserManager $userMgr;
public function __construct(UserManager $manager){
parent::__construct();
$this->userMgr = $manager;
}
#[Route('/login', name: 'login')]
public function login(?string $username, ?string $password ,IRequest $request): Response {
// if user is already logged in, don't display the login page again
if ($user) {
return $this->redirectToRoute('blog_index');
#[Route('/login', name: 'login',methods: ['POST'])]
public function login(string $email,string $password, IRequest $request): IResponse {
$error = [];
try {
$log=$email; // should check email with verrify email
$mdp=Validation::clean_string($password);
if($this->userMgr->login($log,$mdp)){
// Log::dd($this->userMgr->getCurrentUser());
// $athleteGateway = new AthleteGateway(new Connexion(DSN, DB_USER, DB_PASSWORD));
// $user = $athleteGateway->getUserByEmail($email);
// $map = new AthleteMapper();
// $userEntity = $map->athleteSqlToEntity($user);
//
// $users = ['username' => $userEntity[0]->getUsername(), 'nom' => $userEntity[0]->getNom(),
// 'prenom' => $userEntity[0]->getPrenom(),'email' => $userEntity[0]->getEmail(), 'sexe' => $userEntity[0]->getSexe(),
// 'taille' => $userEntity[0]->getTaille(), 'poids' => $userEntity[0]->getPoids(), 'motdepasse' => $userEntity[0]->getMotDePasse(),
// 'datenaissance' => $userEntity[0]->getDateNaissance(), 'iscoach' => $userEntity[0]->getIsCoach(), 'img' => 'test'];
return $this->render('./page/home.html.twig', [
'css' => $this->preference->getCookie(),
'pp' => 'test',
// 'user' => $this->userMgr->getCurrentUser()->getUsername(),
// 'role' => $this->userMgr->getCurrentUser()->getRole()
]);
}
else{
$error [] = "Erreur de connexion. Essayez encore";
// this statement solves an edge-case: if you change the locale in the login
// page, after a successful login you are redirected to a page in the previous
// locale. This code regenerates the referrer URL whenever the login page is
// browsed, to ensure that its locale is always the current one.
$this->saveTargetPath($request->getSession(), 'main', $this->generateUrl('admin_index'));
return $this->render('./page/login.html.twig',[
'css' => $this->preference->getCookie(),
'login_error'=> $error,
]);
}
return $this->render('security/login.html.twig', [
// last username entered by the user (if any)
'last_username' => $helper->getLastUsername(),
// last authentication error (if any)
'error' => $helper->getLastAuthenticationError(),
// should only cath a type of Exception not all
} catch (\Throwable $th) {
$error [] =$th->getMessage();
return $this->render('./page/login.html.twig',[
'css' => $this->preference->getCookie(),
'login_error'=> $error,
]);
}
// #[Route('/login', name: 'login')]
// public function login(?string $username, ?string $password ,IRequest $request): Response {
// // if user is already logged in, don't display the login page again
// if ($user) {
// return $this->redirectToRoute('blog_index');
// }
// // this statement solves an edge-case: if you change the locale in the login
// // page, after a successful login you are redirected to a page in the previous
// // locale. This code regenerates the referrer URL whenever the login page is
// // browsed, to ensure that its locale is always the current one.
// $this->saveTargetPath($request->getSession(), 'main', $this->generateUrl('admin_index'));
// return $this->render('security/login.html.twig', [
// // last username entered by the user (if any)
// 'last_username' => $helper->getLastUsername(),
// // last authentication error (if any)
// 'error' => $helper->getLastAuthenticationError(),
// ]);
// }
#[Route(path: '/register', name: 'register', methods: ['POST'])]
public function register(string $username,string $mdp,string $confirmMdp,string $nom,string $prenom,string $dateNaissance,string $sexe,string $taille,string $poids, IRequest $req): Response
{
}
#[Route('/login', name: 'login2',methods: ['GET'])]
public function login2(IRequest $request): IResponse {
// CONFIRMER LES DONNESS !!!!! IMPORTANT
return $this->render('./page/login.html.twig',[
'css' => $this->preference->getCookie()
]);
return $this->render('./page/home.html.twig',[
}
#[Route('/register', name: 'register2' , methods:['GET'])]
public function register2(IRequest $request): IResponse{
return $this->render('./page/register.html.twig',[
'css' => $this->preference->getCookie()
]);
}
#[Route(path: '/regist', name: 'regist', methods: ['GET'])]
public function register2(): Response
#[Route('/register', name: 'register' , methods:['POST'])]
public function register(
string $nom,
string $prenom,
string $username,
string $mail,
string $motDePasse,
string $sexe,
float $taille,
float $poids,
string $dateNaissance,
string $roleName,
IRequest $request): IResponse
{
// CONFIRMER LES DONNESS !!!!! IMPORTANT
$error = [];
try {
$registrationData = [
'nom' => $nom,
'prenom' => $prenom,
'username' => $username,
'email' => $mail,
'sexe' => $sexe,
'taille' => $taille,
'poids' => $poids,
'dateNaissance' => $dateNaissance,
'roleName' => $roleName
];
if ($this->userMgr->register($mail, $motDePasse, $registrationData) ) {
return new RedirectResponse('/');
} else {
$error [] = 'L\'inscription a échoué. Veuillez réessayer.';
return $this->render('./page/register.html.twig',[
'css' => $this->preference->getCookie()
'css' => $this->preference->getCookie(),
'register_error'=> $error,
]);
}
} catch (\Throwable $e) {
$error [] =$e->getMessage();
return $this->render('./page/register.html.twig', ['css' => $this->preference->getCookie(),"register_error" => $error ]);
function inscription() {
$model = new ModelVisitor();
$log=Validation::clean_string($_POST['pseudo']);
$mdp=Validation::clean_string($_POST['password']);
if($model->createAUser($log,$mdp)){
if(ModelUser::login($log, $mdp)){
UserControler::displayView();
}
}
}
function connexion(){
$model = new ModelVisitor();
if(!isset($_POST['pseudo']) || !isset($_POST['password'])) throw new Exception(" some wrong with credentials !!!!!");
$log=Validation::clean_string($_POST['pseudo']);
$mdp=Validation::clean_string($_POST['password']);
if(ModelUser::login($log, $mdp)){
UserControler::displayView();
}
}
#[Route(path: '/pass', name: 'pass', methods: ['GET'])]
public function pass(): Response
{
}
// CONFIRMER LES DONNESS !!!!! IMPORTANT
//string $ancienMotDePasse,string $nouveauMotDePasse,string $confirmerMotDePasse,
#[Route(path: '/forgetPassword', name: 'forget-password2', methods: ['GET'])]
public function forgetPassword2(IRequest $request): IResponse
{
return $this->render('./page/password.html.twig',[
'css' => $this->preference->getCookie(),
'pp' => "test2",
'user' => "Doe",
'role' => "Athlète",
'friendship' => [],
'analyzes' => [],
'mails' => [],
'users' => [],
'infoUser' => [],
'exos' => [],
'member' => []
]);
}
#[Route(path: '/log', name: 'log', methods: ['GET'])]
public function login2(): Response
#[Route(path: '/forgetPassword', name: 'forget-password', methods: ['POST'])]
public function forgetPassword(string $mail, IRequest $request): IResponse
{
// CONFIRMER LES DONNESS !!!!! IMPORTANT
return $this->render('./page/login.html.twig',[
return $this->render('./page/password.html.twig',[
'css' => $this->preference->getCookie(),
'pp' => "test2",
'user' => "Doe",
'role' => "Athlète",
'friendship' => [],
'analyzes' => [],
'mails' => [],
'users' => [],
'infoUser' => [],
'exos' => [],
'member' => []
]);
}
#[Route(path: '/password', name: 'password', methods: ['POST'])]
public function password(string $email, IRequest $req): Response
#[Route(path: '/logout', name: 'logout', methods: ['GET'])]
public function logout(IRequest $request): IResponse
{
$error = [];
// CONFIRMER LES DONNESS !!!!! IMPORTANT
try {
return $this->render('./page/login.html.twig',[
'css' => $this->preference->getCookie(),
'pp' => "test2",
'user' => "Doe",
'role' => "Athlète",
'friendship' => [],
'analyzes' => [],
'mails' => [],
'users' => [],
'infoUser' => [],
'exos' => [],
'member' => []
]);
if($this->userMgr->deconnecter()){
return new RedirectResponse('/');
}
else{
$error [] = "Erreur de deconnexion. Essayez encore";
return new RedirectResponse('/');
}
} catch (\Throwable $th) {
$error [] =$th->getMessage();
return new RedirectResponse('/');
}
}
}
?>

@ -8,13 +8,14 @@ use App\Router\Response\RedirectResponse;
use App\Router\Response\Response;
use Psr\Container\ContainerInterface;
use Shared\Log;
abstract class BaseController
{
protected Preferences $preference;
public function __construct(){
$this->preference = new Preferences();
}
protected ContainerInterface $container;
@ -62,18 +63,5 @@ abstract class BaseController
return new RedirectResponse($url, $status);
}
protected function redirectToRoute(string $route, array $parameters = [], int $status = 302): RedirectResponse
{
return $this->redirect($this->generateUrl($route, $parameters), $status);
}
/*
* TODO : Should hanle ierror if the route is not existing
* */
protected function generateUrl(string $route, array $parameters = []): string
{
return $this->container->get(\App\Router\Router::class)->generate($route, $parameters);
}
}

@ -7,6 +7,7 @@ use App\Router\Request\IRequest;
use App\Router\Response\Response;
use App\Router\Response\IResponse;
use Manager\DataManager;
use Shared\Attributes\Route;
use Twig\Environment;
use Data\Core\Preferences;
@ -16,16 +17,16 @@ use Shared\Log;
class CoachController extends BaseController
{
private ICoachManager $coachManager;
private $security;
private Environment $twig;
// private ICoachManager $coachManager;
// private $security;
// private Environment $twig;
protected Preferences $preference;
public function __construct(DataManager $dataManager, Security $security)
public function __construct()
{
session_start();
$this->coachManager = $dataManager->coachMgr;
$this->security = $security;
// session_start();
// $this->coachManager = $dataManager->coachMgr;
// $this->security = $security;
$this->preference = new Preferences();
}

File diff suppressed because it is too large Load Diff

@ -48,6 +48,7 @@ class FrontController {
$this->handleError(404, $e->getMessage());
}
catch(\Throwable $e){
Log::dd($e->getLine() . $e->getFile() . $e->getMessage() );
$this->handleError(501, $e->getMessage());
}
}
@ -65,7 +66,7 @@ class FrontController {
// TODO : Don't work need Antoine help
private function handleError(int $statusCode, $message) : void {
if (!$this->container->has(\Twig\Environment::class)) {
throw new \LogicException('You cannot use the "renderView" method if the Twig Bundle is not available. Try running "composer require symfony/twig-bundle".');
throw new \LogicException('You cannot use the "renderView" method if the Twig Bundle is not available. Try running "composer require ".');
}
$response = new Response($this->container->get(\Twig\Environment::class)->render('./error/error.html.twig',['title'=> $message , "code" => $statusCode, "name" => $message, "descr" => $message ]),$statusCode);

@ -4,7 +4,10 @@ namespace App\Controller;
use App\Container;
use App\Router\Request\IRequest;
use App\Router\Response\IResponse;
use App\Router\Response\RedirectResponse;
use App\Router\Response\Response;
use Manager\ActivityManager;
use Shared\Attributes\Route;
use Twig\Environment;
use Data\Core\Preferences;
@ -12,21 +15,18 @@ use Shared\Log;
class HeartRateController extends BaseController
{
private ActivityManager $activityMgr;
private Environment $twig;
protected Preferences $preference;
public function __construct()
public function __construct(ActivityManager $manager)
{
session_start();
$this->preference = new Preferences();
parent::__construct();
$this->activityMgr = $manager;
}
#[Route(path: '/import', name: 'import', methods: ['GET'])]
public function import(): Response
{
return $this->render('./page/import.html.twig',[
return $this->render('./page/import.html.twig', [
'css' => $this->preference->getCookie(),
'pp' => "test2",
'user' => "Doe",
@ -41,5 +41,54 @@ class HeartRateController extends BaseController
]);
}
#[Route(path: '/upload', name: 'upload', methods: ['POST'])]
public function uploadFile(string $activityType, int $effort, IRequest $req): IResponse
{
$error = $this->validateRequest($effort);
if (!empty($error)) {
return $this->renderError($error);
}
$tmp_file = $_FILES['uploaded_file']['tmp_name'];
if (!$this->isValidFile($tmp_file)) {
return $this->renderError(['Failed to get file be sure that you provide the file']);
}
$content = file_get_contents($tmp_file);
try {
if ($this->activityMgr->uploadFile($activityType, 5, $content)) {
return new RedirectResponse('/home');
}
} catch (\Exception $e) {
return $this->renderError([$e->getMessage()]);
}
return $this->renderError(['Failed to save activity.']);
}
private function validateRequest(int $effort): array
{
$error = [];
if ($effort < 0 || $effort > 5) {
$error[] = 'Invalid effort level.';
}
$fileExtension = pathinfo($_FILES['uploaded_file']['name'], PATHINFO_EXTENSION);
if ($fileExtension !== 'fit') {
$error[] = 'Invalid file type. Only .fit files are allowed.';
}
return $error;
}
private function isValidFile(string $tmp_file): bool
{
return file_exists($tmp_file) && is_uploaded_file($tmp_file);
}
private function renderError(array $error): Response
{
// Consolidez la logique de rendu ici
return $this->render('./error/error.html.twig', ['title'=> "Failed" , "code" => 400, "name" => "error import", "descr" => $error[0] ], new Response('$error', 400));
}
}

@ -5,6 +5,11 @@ namespace App\Controller;
use App\Container;
use App\Router\Request\IRequest;
use App\Router\Response\Response;
use Database\AthleteGateway;
use Database\AthleteMapper;
use Database\Connexion;
use Database\NotificationGateway;
use Database\NotificationMapper;
use Shared\Attributes\Route;
use Twig\Environment;
use Data\Core\Preferences;
@ -12,33 +17,49 @@ use Shared\Log;
class SocialController extends BaseController
{
private Environment $twig;
protected Preferences $preference;
public function __construct()
{
session_start();
public function __construct(){
$this->preference = new Preferences();
}
#[Route(path: '/mail', name: 'mail', methods: ['GET'])]
#[Route(path: '/notification', name: 'notification', methods: ['GET'])]
public function mail(): Response
{
return $this->render('./page/mail.html.twig',[
try {
$notificationGateway = new NotificationGateway(new Connexion(DSN, DB_USER, DB_PASSWORD));
$listSearch = $notificationGateway->getNotifications();
$map = new NotificationMapper();
$notificationEntity = $map->notificationSqlToEntity($listSearch);
$listUsers = [];
foreach ($notificationEntity as $entity) {
$notification = $map->notificationEntityToModel($entity);
$listUsers[] = ['idnotif' => $notification->getId(), 'message' => $notification->getMessage(),
'date' => $notification->getDate()->format("D j F Y"),'statut' => $notification->getStatut(), 'urgence' => $notification->getUrgence(),
'idathlete' => $notification->getToUserId()];
}
$response = $this->render('./page/notification.html.twig',[
'css' => $this->preference->getCookie(),
'pp' => "test2",
'user' => "Doe",
'role' => "Athlète",
'friendship' => [],
'analyzes' => [],
'mails' => [],
'mails' => $listUsers,
'users' => [],
'infoUser' => [],
'exos' => [],
'member' => []
]);
} catch (\Throwable $th) {
throw $th;
return $this->render("notification.html.twig", ['tabError' => $taberror]);
}
return $response;
}

@ -4,25 +4,32 @@ namespace App\Controller;
use App\Container;
use App\Router\Request\IRequest;
use App\Router\Response\RedirectResponse;
use App\Router\Response\Response;
use App\Router\Response\IResponse;
use App\Router\Session;
use DateInterval;
use DateTime;
use Manager\UserManager;
use Shared\Attributes\Route;
use Shared\Validation;
use Twig\Environment;
use Data\Core\Preferences;
use Shared\Log;
use function PHPUnit\Framework\isEmpty;
use Database\Athletegateway;
use Database\Connexion;
class UserController extends BaseController
{
private Environment $twig;
protected Preferences $preference;
public function __construct()
{
session_start();
$this->preference = new Preferences();
private UserManager $userMgr;
public function __construct(UserManager $manager){
parent::__construct();
$this->userMgr = $manager;
}
#[Route(path: '/', name: 'index', methods: ['GET'])]
public function index(): Response
{
@ -44,6 +51,100 @@ class UserController extends BaseController
#[Route(path: '/home', name: 'home', methods: ['GET'])]
public function home(): Response
{
$athleteGateway = new AthleteGateway(new Connexion(DSN, DB_USER, DB_PASSWORD));
$activity = $athleteGateway->getListActivity('1');//$currentUser->getId()
// $charts = [];
// $i = 0;
// while ($i <= 12) {
// if ($activity[$i]['mois'] == null) {
// $activity[$i]['mois'] = $i;
// $activity[$i]['nbactivite'] = 0;
// } elseif (($indice = intval($activity[$i]['mois'])) != $i) {
// $temp = $activity[$i]; // Stocker temporairement les données actuelles
// $activity[$i]['mois'] = $i;
// $activity[$i]['nbactivite'] = 0;
// $activity[$indice]['mois'] = $indice;
// $activity[$indice]['nbactivite'] = $temp['nbactivite']; // Restaurer les données
// }
// $charts[] = ['act' => $activity[$i]['nbactivite'], 'mois' => $activity[$i]['mois']];
// $i++;
// }
$charts = [];
$monthNames = [
'Janvier', 'Fevrier', 'Mars', 'Avril', 'Mai', 'Juin',
'Juillet', 'Aout', 'Septembre', 'Octobre', 'Novembre', 'Decembre'
];
$currentDate = new DateTime();
$interval = new DateInterval('P1M'); // Période d'un mois
for ($i = 0; $i < 12; $i++) {
$currentMonth = $currentDate->format('n'); // Format numérique du mois (1 à 12)
$currentMonthName = $monthNames[$currentMonth - 1]; // Mois correspondant dans le tableau
// Recherche de l'indice du mois dans le tableau $activity
$activityIndex = null;
for ($j = 0; $j < count($activity); $j++) {
if (!empty($activity[$j]['mois']) && $activity[$j]['mois'] == $currentMonth) {
$activityIndex = $j;
break;
}
}
// Récupération du nombre d'activités et réinitialisation à 0
$nbActivity = isset($activityIndex) ? $activity[$activityIndex]['nbactivite'] : 0;
if (isset($activityIndex)) {
$activity[$activityIndex]['nbactivite'] = 0;
}
// Log::dd($currentMonth);
$charts[] = ['act' => $nbActivity, 'mois' => $currentMonth];
$currentDate->sub($interval);
}
// Inverser l'ordre des éléments si nécessaire
$charts = array_reverse($charts);
// Log::dd($charts);
//
// $charts = [];
// $monthNames = [
// 'Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
// 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'
// ];
//
// $currentDate = new DateTime();
// $interval = new DateInterval('P1M'); // Période d'un mois
//
// for ($i = 0; $i < 12; $i++) {
//// $currentDate; // Soustraire un mois
//// Log::dd($currentDate);
// $currentMonth = $currentDate->format('n'); // Format numérique du mois (1 à 12)
//// Log::dd($currentMonth);
// $currentMonthName = $monthNames[$currentMonth - 1]; // Mois correspondant dans le tableau
// for($j = 12; $j > 0; $j--) {
// if(!empty($activity[$j]['mois']) || $activity[$j]['mois'] == $currentMonth) {
// $nbAct = $activity[$j]['nbactivite'];
// $activity[$j]['nbactivite'] = 0;
//// Log::dd($activity);
// break;
// }
// }
//
// $nbActivity = isset($nbAct) ? $nbAct : 0;
//// Log::dd($nbActivity);
//
// $charts[] = ['act' => $nbActivity, 'mois' => $currentMonthName];
// $currentDate->sub($interval);
// }
// Log::dd($charts);
// Inverser l'ordre des éléments si nécessaire
// $charts = array_reverse($charts);
//
// Log::dd($charts);
return $this->render('./page/home.html.twig',[
'css' => $this->preference->getCookie(),
'pp' => "test2",
@ -51,6 +152,7 @@ class UserController extends BaseController
'role' => "Athlète",
'friendship' => [],
'analyzes' => [],
'charts' => $charts,
'mails' => [],
'users' => [],
'infoUser' => [],
@ -119,45 +221,25 @@ class UserController extends BaseController
]);
}
#[Route(path: '/psettings', name: 'psettings', methods: ['POST'])]
public function psettings(string $nom,string $prenom,string $dateNaissance,string $mail,string $tel, IRequest $req): Response
{
return $this->render('./page/settings.html.twig',[
'css' => $this->preference->getCookie(),
'pp' => "test2",
'user' => $prenom,
'role' => "Athlète",
'friendship' => [],
'analyzes' => [],
'mails' => [],
'users' => [],
'infoUser' => [],
'exos' => [],
'member' => []
]);
}
#[Route(path: '/mdp', name: 'mdp', methods: ['POST'])]
public function mdp(string $ancienMotDePasse,string $nouveauMotDePasse,string $confirmerMotDePasse, IRequest $req): Response
{
// CONFIRMER LES DONNESS !!!!! IMPORTANT
return $this->render('./page/settings.html.twig',[
'css' => $this->preference->getCookie(),
'pp' => "test2",
'user' => "Doe",
'role' => "Athlète",
'friendship' => [],
'analyzes' => [],
'mails' => [],
'users' => [],
'infoUser' => [],
'exos' => [],
'member' => []
]);
}
// #[Route(path: '/logout', name: 'logout', methods: ['GET'])]
// public function logout(IRequest $request): IResponse
// {
// $error = [];
//
// try {
//
// if($this->userMgr->deconnecter()){
// return new RedirectResponse('/');
// }
// else{
// $error [] = "Erreur de deconnexion. Essayez encore";
// return new RedirectResponse('/');
// }
//
// } catch (\Throwable $th) {
// $error [] =$th->getMessage();
// return new RedirectResponse('/');
// }
// }
}

@ -1,12 +1,15 @@
<?php
namespace App\Router;
use App\Router\Request\IRequest;
/**
* Router class to manage a collection of routes in the application.
* It provides functionalities to add routes and check if a given URL matches any of the defined routes.
*/
class Router {
class Router
{
/**
* The base path for routing.
@ -34,7 +37,8 @@ class Router {
*
* @param string $path The base path for the router.
*/
public function __construct(string $path = "/PHP/project/index.php") {
public function __construct(string $path = "/PHP/project/index.php")
{
$this->path = $path;
$this->routes = new \AltoRouter();
}
@ -46,7 +50,8 @@ class Router {
* @param Route $route The route object.
* @throws \InvalidArgumentException If method is not supported.
*/
public function add(string $method, Route $route) {
public function add(string $method, Route $route)
{
if (!in_array($method, self::$verbs)) {
throw new \InvalidArgumentException("Method not supported");
}
@ -55,20 +60,28 @@ class Router {
/**
* Adds a route for a controller action.
*
* @param string $method The HTTP method.
* TODO : the problème is that AltoRouter is a map so i can't have mutilple Route just by doing this:(i need to find a logic to resolve this beavior) #[Route('/login', name: 'login',methods: ['POST','GET'])]
* @param string|array $methods HTTP method.
* @param string $path The path for the route.
* @param mixed $controller The controller object.
* @param string $action The action method in the controller.
* @param string $name (Optional) The name of the route.
* @throws \InvalidArgumentException If method is not supported.
*/
public function addControllerRoute(string $method, string $path, $controller, string $action, string $name = '') {
public function addControllerRoute(string|array $methods, string $path, $controller, string $action, string $name = '')
{
if (is_string($methods)) {
$methods = [$methods]; // Convert to an array if it's a string
}
foreach ($methods as $method) {
if (!in_array($method, self::$verbs)) {
throw new \InvalidArgumentException("Method not supported");
}
$this->routes->map($method, $path, [$controller, $action], $name);
}
}
// TODO: Implement the extractParams method.
// public function extractParams(string $path) {}
@ -80,7 +93,8 @@ class Router {
* @param callable $callable The callback function.
* @param string $name The name of the route.
*/
public function get(string $path, callable $callable, $name) {
public function get(string $path, callable $callable, $name)
{
$this->routes->map('GET', $path, $callable, $name);
}
@ -92,7 +106,8 @@ class Router {
* @param IRequest $request The request object.
* @return array|null The matched route or null if no match.
*/
public function match(IRequest $request): ?array {
public function match(IRequest $request): ?array
{
return $this->routes->match($request->getRequestUri(), $request->getMethod()) ?: null;
}
@ -101,14 +116,15 @@ class Router {
*
* @return array The array of routes.
*/
public function getRoutes() {
public function getRoutes()
{
return []; // TODO: Implement the actual logic to return routes.
}
public function generate (string $routeName, array $params = array()): string
public function generate(string $routeName, array $params = array()): string
{
return $this->routes->generate($routeName,$params);
return $this->routes->generate($routeName, $params);
}
}

@ -111,8 +111,7 @@ class Session
if ( $this->sessionState == self::SESSION_STARTED )
{
$this->sessionState = !session_destroy();
unset( $_SESSION );
session_unset(); // Clear all session variables
return !$this->sessionState;
}

@ -2,26 +2,24 @@
namespace App\Router\Middleware;
use App\Router\Session;
use Network\IAuthService;
use Shared\Log;
use App\Router\Request\IRequest;
use App\Router\Response\RedirectResponse;
class AuthMiddleware extends Middleware {
public function handle(IRequest $request, callable $next) {
// if (isset($_SESSION['user'])) {
// $resp =new RedirectResponse("/");
// $resp->send();
// exit;
// }
// La page nest pas redirigée correctement
// Firefox a détecté que le serveur redirige la demande pour cette adresse dune manière qui naboutira pas.
// La cause de ce problème peut être la désactivation ou le refus des cookies.
// if (!isset($_SESSION['user'])) {
// $resp =new RedirectResponse("/log");
// $resp->send();
// exit;
// }
private IAuthService $auth;
public function __construct(IAuthService $auth) {
$this->auth = $auth;
}
public function handle(IRequest $request, callable $next) {
$excludedUrls = ['/login', '/register','/forgetPassword', '/'];
// Log::dd($this->auth->getCurrentUser());
if ($this->auth->getCurrentUser() === null && !in_array($request->getRequestUri(), $excludedUrls)) {
$resp = new RedirectResponse("/login");
$resp->send();
exit;
}
return parent::handle($request, $next);
}
}

@ -2,6 +2,9 @@
namespace App\Router\Response;
use App\Router\Session;
use Shared\Log;
class RedirectResponse implements IResponse
{
private $content;
@ -49,6 +52,7 @@ class RedirectResponse implements IResponse
public function send(): void
{
http_response_code($this->statusCode);
foreach ($this->headers as $name => $value) {

@ -1,6 +1,8 @@
<?php
namespace App\Router\Response;
use Shared\Log;
class Response implements IResponse {
private string $content;
private int $statusCode;

@ -1,6 +1,7 @@
<!DOCTYPE html>
<html lang="en">
<head>
{#<<<<<<< HEAD#}
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
@ -9,9 +10,9 @@
<title>{% block title %}{% endblock %}</title>
<link href="/css/{% block css %}base_theme{% endblock %}.css" rel="stylesheet" />
<script src="https://use.fontawesome.com/releases/v6.3.0/js/all.js" crossorigin="anonymous"></script>
</head>
<body class="bg-primary">
<div id="layoutAuthentication">
</head>
<body class="bg-primary">
<div id="layoutAuthentication">
<div id="layoutAuthentication_content">
<main>
{% block main %}
@ -34,14 +35,54 @@
<input class="form-check-input" id="inputRememberPassword" type="checkbox" value="" />
<label class="form-check-label" for="inputRememberPassword">Mémoriser le mot de passe</label>
</div>
<div class="d-flex align-items-center justify-content-between mt-4 mb-0">
<a class="small" href="password.html">Mot de passe oublié ?</a>
<a class="btn btn-primary" href="index.html">Se connecter</a>
</div>
</form>
</div>
<div class="card-footer text-center py-3">
<div class="small"><a href="register.html">Besoin d'un compte ? Inscrivez-vous !</a></div>
{#=======#}
{#<head>#}
{# <meta charset="utf-8" />#}
{# <meta http-equiv="X-UA-Compatible" content="IE=edge" />#}
{# <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />#}
{# <meta name="description" content="" />#}
{# <meta name="author" content="" />#}
{# <title>{% block title %}{% endblock %}</title>#}
{# <link href="/css/{% block css %}base_theme{% endblock %}.css" rel="stylesheet" />#}
{# <script src="https://use.fontawesome.com/releases/v6.3.0/js/all.js" crossorigin="anonymous"></script>#}
{#</head>#}
{#<body class="bg-primary">#}
{#<div id="layoutAuthentication">#}
{# <div id="layoutAuthentication_content">#}
{# <main>#}
{# {% block main %}#}
{# <div class="container">#}
{# <div class="row justify-content-center">#}
{# <div class="col-lg-5">#}
{# <div class="card shadow-lg border-0 rounded-lg mt-5">#}
{# <div class="card-header"><h3 class="text-center font-weight-light my-4">Connexion</h3></div>#}
{# <div class="card-body">#}
{# <form>#}
{# <div class="form-floating mb-3">#}
{# <input class="form-control" id="inputEmail" type="email" placeholder="nom@exemple.com" />#}
{# <label for="inputEmail">Adresse eMail</label>#}
{# </div>#}
{# <div class="form-floating mb-3">#}
{# <input class="form-control" id="inputPassword" type="password" placeholder="Mot de passe" />#}
{# <label for="inputPassword">Mot de passe</label>#}
{# </div>#}
{# <div class="form-check mb-3">#}
{# <input class="form-check-input" id="inputRememberPassword" type="checkbox" value="" />#}
{# <label class="form-check-label" for="inputRememberPassword">Mémoriser le mot de passe</label>#}
{# </div>#}
{# <div class="d-flex align-items-center justify-content-between mt-4 mb-0">#}
{# <a class="small" href="password.html">Mot de passe oublié ?</a>#}
{# <a class="btn btn-primary" href="index.html">Se connecter</a>#}
{# </div>#}
{# </form>#}
{# </div>#}
{# <div class="card-footer text-center py-3">#}
{# <div class="small"><a href="register.html">Besoin d'un compte ? Inscrivez-vous !</a></div>#}
{#>>>>>>> origin/merged_PLE#}
</div>
</div>
</div>

@ -7,9 +7,12 @@
<meta name="description" content="Accueil" />
<meta name="author" content="PINAGOT Antoine" />
<title>{% block title %}{% endblock %}</title>
<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/simple-datatables@7.1.2/dist/style.min.css" rel="stylesheet" />
<link href="/css/{% block css %}styles{% endblock %}.css" rel="stylesheet" />
<script src="https://use.fontawesome.com/releases/v6.3.0/js/all.js" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
</head>
<body class="sb-nav-fixed">
<nav class="sb-topnav navbar navbar-expand navbar-dark bg-dark">
@ -55,9 +58,9 @@
<div class="sb-nav-link-icon"><img src="/assets/img/sprinter.png"></div>
Exercices
</a>
<a class="nav-link" href="/analyses">
<a class="nav-link" href="/activity">
<div class="sb-nav-link-icon"><i class="fas fa-chart-area"></i></div>
Analyses
Activités
</a>
<div class="sb-sidenav-menu-heading">Social</div>
<a class="nav-link" href="/friendlist">
@ -68,7 +71,7 @@
<div class="sb-nav-link-icon"><img src="/assets/img/coaching.png"></div>
Coaching
</a>
<a class="nav-link" href="/mail">
<a class="nav-link" href="/notification">
<div class="sb-nav-link-icon"><img src="/assets/img/letter.png"></div>
Messagerie
</a>

@ -21,7 +21,7 @@
<h1 class="display-1">{% block nb %}{% endblock %}</h1>
<p class="lead">{% block name %}{% endblock %}</p>
<p>{% block descr %}{% endblock %}</p>
<a href="/">
<a href="/home">
<i class="fas fa-arrow-left me-1"></i>
Retour à l'accueil
</a>

@ -4,30 +4,84 @@
{% block css %}{{css}}{% endblock %}
{% block title %}Exercices - HearthTrack{% endblock %}
{% block title %}Analyses - HearthTrack{% endblock %}
{% block user %}{{user}} - {{role}}{% endblock %}
{% block body %}
<div class="container-fluid px-4">
<h1 class="mt-4">Exercices</h1>
<div class="container-fluid px-4">
<h1 class="mt-4">Analyses</h1>
<ol class="breadcrumb mb-4">
<li class="breadcrumb-item"><a href="/">Accueil</a></li>
<li class="breadcrumb-item active">Exercices</li>
<li class="breadcrumb-item"><a href="/home">Accueil</a></li>
<li class="breadcrumb-item active">Analyses</li>
</ol>
<div class="card-body">
<div class="datatable-container">
<form method="post" action="/exercices">
Type : <input type="text" name="type"/>
Intensité : <input type="text" name="intensite"/>
Date : <input type="text" name="date"/>
<button class="btn btn-primary btn-mrg" id="btnNavbarSearch" type="submit">Ajouter l'exercice</button>
</form>
<table id="datatablesSimple" class="datatable-table">
<thead>
<tr>
<th>Date</th>
<th>Heure de début</th>
<th>Heure de fin</th>
<th>Type</th>
<th>effort ressenti</th>
<th>Variabilité</th>
<th>Variance</th>
<th>Ecart type</th>
<th>Moyenne</th>
<th>Maximum</th>
<th>Minimum</th>
<th>Temperature moyenne</th>
<th></th>
</tr>
</thead>
<tfoot>
<tr>
<th>Date</th>
<th>Heure de début</th>
<th>Heure de fin</th>
<th>Type</th>
<th>effort ressenti</th>
<th>Variabilité</th>
<th>Variance</th>
<th>Ecart type</th>
<th>Moyenne</th>
<th>Maximum</th>
<th>Minimum</th>
<th>Temperature moyenne</th>
</tr><tr></tr>
</tfoot>
<tbody>
{% for analyze in analyzes %}
<tr>
<td>{{analyze.date}}</td>
<td>{{analyze.heureDebut}}</td>
<td>{{analyze.heureFin}}</td>
<td>{{analyze.type}}</td>
<td>{{analyze.effortRessenti}}</td>
<td>{{analyze.variabilite}}</td>
<td>{{analyze.variance}}</td>
<td>{{analyze.ecartType}}</td>
<td>{{analyze.moyenne}} Bpm</td>
<td>{{analyze.max}} Bpm</td>
<td>{{analyze.min}} Bpm</td>
<td>{{analyze.temperature}} °C</td>
<td><a href="/analyze?id={{ analyze.idactivity }}">En savoir plus</a></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<h1>{{responce}}</h1>
{% endblock %}
{% block script %}
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
<script src="js/scripts.js"></script>
<script src="https://cdn.jsdelivr.net/npm/simple-datatables@7.1.2/dist/umd/simple-datatables.min.js" crossorigin="anonymous"></script>
<script src="js/datatables-simple-demo.js"></script>
{% endblock %}

@ -12,7 +12,7 @@
<div class="container-fluid px-4">
<h1 class="mt-4">Liste d'ami</h1>
<ol class="breadcrumb mb-4">
<li class="breadcrumb-item"><a href="/">Accueil</a></li>
<li class="breadcrumb-item"><a href="/home">Accueil</a></li>
<li class="breadcrumb-item active">Ami</li>
</ol>

@ -12,7 +12,7 @@
<div class="container-fluid px-4">
<h1 class="mt-4">Coaching</h1>
<ol class="breadcrumb mb-4">
<li class="breadcrumb-item"><a href="/">Accueil</a></li>
<li class="breadcrumb-item"><a href="/home">Accueil</a></li>
<li class="breadcrumb-item active">Coaching</li>
</ol>

@ -4,63 +4,151 @@
{% block css %}{{css}}{% endblock %}
{% block title %}Analyses - HearthTrack{% endblock %}
{% block title %}Exercices - HearthTrack{% endblock %}
{% block user %}{{user}} - {{role}}{% endblock %}
{% block body %}
<div class="container-fluid px-4">
<h1 class="mt-4">Analyses</h1>
<div class="container-fluid px-4">
<h1 class="mt-4">Exercices</h1>
<ol class="breadcrumb mb-4">
<li class="breadcrumb-item"><a href="/">Accueil</a></li>
<li class="breadcrumb-item active">Analyses</li>
<li class="breadcrumb-item"><a href="/home">Accueil</a></li>
<li class="breadcrumb-item active">Exercices</li>
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
</ol>
<div class="card-body">
<div class="datatable-container">
<table id="datatablesSimple" class="datatable-table">
<thead>
<tr>
<th>Date</th>
<th>Type</th>
<th>BMP</th>
<th>KM/H</th>
<th>Distance</th>
<th></th>
</tr>
</thead>
<tfoot>
<tr>
<th>Date</th>
<th>Type</th>
<th>BPM</th>
<th>KM/H</th>
<th>Distance</th>
</tr><tr></tr>
{# <table id="datatablesSimple" class="datatable-table">#}
{# <thead>#}
{# <tr>#}
{# <th>id FC</th>#}
{# <th>altitude</th>#}
{# <th>temps</th>#}
{# <th>Temperature</th>#}
{# <th>bpm</th>#}
{# <th>longitude</th>#}
{# <th>latitude</th>#}
{# <th>activiteid</th>#}
{# <th></th>#}
{# </tr>#}
{# </thead>#}
{# {% for analyze in analyzes %}#}
{# <tbody>#}
{# <tr>#}
{# <td>{{analyze.idfc}}</td>#}
{# <td>{{analyze.altitude}}</td>#}
{# <td>{{analyze.temps}}</td>#}
{# <td>{{analyze.temperature}}</td>#}
{# <td>{{analyze.bpm}}</td>#}
{# <td>{{analyze.longitude}}</td>#}
{# <td>{{analyze.latitude}}</td>#}
{# <td>{{analyze.activiteid}}</td>#}
{# <td><a href="/home">Home</a></td>#}
{# </tr>#}
{# </tbody>#}
{# {% endfor %}#}
{# </table>#}
{# <div>#}
{# <canvas id="myChart" width="400" height="200">#}
{# <p>Hello Fallback World</p>#}
{# </canvas>#}
{# </div>#}
{# <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>#}
{# <script>#}
{# const ctx = document.getElementById('myChart');#}
{# new Chart(ctx, {#}
{# type: 'line',#}
{# data: {#}
{# labels: [#}
{# {% for analyze in analyzes %}#}
{# {{analyze.temps}}#}
{# {% endfor %}#}
{# ],#}
{# datasets: [{#}
{# label: 'Batement par minute',#}
{# data: [#}
{# {% for analyze in analyzes %}#}
{# {{analyze.bpm}}#}
{# {% endfor %}#}
{# ],#}
{# borderWidth: 1#}
{# }]#}
{# },#}
{# options: {#}
{# scales: {#}
{# y: {#}
{# beginAtZero: true#}
{# }#}
{# }#}
{# }#}
{# });#}
{# </script>#}
<div>
<canvas id="myChart" height="50">
<p>Hello Fallback World</p>
</canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
const ctx = document.getElementById('myChart');
const labels = [
{% for analyze in analyzes %}
'{{ analyze.temps }}',
{% endfor %}
];
const data = [
{% for analyze in analyzes %}
{{ analyze.bpm }},
{% endfor %}
];
new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: 'Batement par minute',
data: data,
borderWidth: 1,
tension: 0.2,
fill: false,
borderColor: 'rgb(255, 0, 0)'
}]
},
options: {
scales: {
y: {
beginAtZero: false
}
}
}
});
</script>
<div class="card-body">
<div id="map" style="height: 500px;"></div>
<script>
document.addEventListener("DOMContentLoaded", function () {
{#var lat = {{ analyze.latitude }}#}
var map = L.map('map').setView([45.75771709151474, 3.113484980409329], 14);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
</tfoot>
<tbody>
{% for analyze in analyzes %}
<tr>
<td>{{analyze.date}}</td>
<td>{{analyze.type}}</td>
<td>{{analyze.bpm}}</td>
<td>{{analyze.kmh}} Km/H</td>
<td>{{analyze.distance}} Km</td>
<td><a href="#about">En savoir plus</a></td>
</tr>
var marker = L.marker([{{ analyze.latitude }}, {{ analyze.longitude }}]).addTo(map);
marker.bindPopup(`
<strong>Date:</strong> {{ analyze.temps }}<br>
<strong>FC:</strong> {{ analyze.bpm }}<br>
<strong>Altitude:</strong> {{ analyze.altitude }}<br>
<strong>Temperature:</strong> {{ analyze.temperature }}
`);
{% endfor %}
</tbody>
</table>
});
</script>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block script %}
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
<script src="js/scripts.js"></script>
<script src="https://cdn.jsdelivr.net/npm/simple-datatables@7.1.2/dist/umd/simple-datatables.min.js" crossorigin="anonymous"></script>
<script src="js/datatables-simple-demo.js"></script>
<h1>{{responce}}</h1>
{% endblock %}

@ -13,7 +13,7 @@
<div class="container-fluid px-4">
<h1 class="mt-4">Coaching</h1>
<ol class="breadcrumb mb-4">
<li class="breadcrumb-item"><a href="/">Accueil</a></li>
<li class="breadcrumb-item"><a href="/home">Accueil</a></li>
<li class="breadcrumb-item active">Coaching</li>
</ol>
<style>.btn-mrg{margin:15px; margin-left:83%}</style>

@ -9,10 +9,11 @@
{% block user %}{{user}} - {{role}}{% endblock %}
{% block body %}
<div class="container-fluid px-4">
<h1 class="mt-4">Exercices</h1>
<ol class="breadcrumb mb-4">
<li class="breadcrumb-item"><a href="/">Accueil</a></li>
<li class="breadcrumb-item"><a href="/home">Accueil</a></li>
<li class="breadcrumb-item active">Exercices</li>
</ol>
<style>.btn-mrg{margin:15px; margin-left:85%}</style>
@ -25,18 +26,39 @@
<thead>
<tr>
<th>Date</th>
<th>Type</th>
<th>Intensité prévue</th>
<th>Status</th>
<th>Description</th>
<th>Localisation</th>
<th>FeedBack</th>
</tr>
</thead>
<tbody>
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
{% for exo in exos %}
<tr>
<td>{{exo.date}}</td>
<td>{{exo.type}}</td>
<td>{{exo.intensite}}</td>
<td>{{exo.status}}</td>
<td>{{ exo.date }}</td>
<td>{{ exo.description }}</td>
<td>
<div id="map-{{ loop.index }}"
data-lat=45.758285982369415
data-lng=3.110223414416445
style="height: 300px; width: 650px;"></div>
<script>
document.addEventListener("DOMContentLoaded", function() {
var map{{ loop.index }} = L.map('map-{{ loop.index }}').setView([45.75771709151474, 3.113484980409329], 14);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map{{ loop.index }});
var marker{{ loop.index }} = L.marker([45.75771709151474, 3.113484980409329]).addTo(map{{ loop.index }});
marker{{ loop.index }}.bindPopup(`
<strong>Date:</strong> {{ exo.date }}<br>
<strong>Description:</strong> {{ exo.description }}<br>
<strong>Feedback:</strong> {{ exo.feedback }}
`);
});
</script>
</td>
<td>{{ exo.feedback }}</td>
</tr>
{% endfor %}
</tbody>

@ -12,7 +12,7 @@
<div class="container-fluid px-4">
<h1 class="mt-4">Liste d'ami</h1>
<ol class="breadcrumb mb-4">
<li class="breadcrumb-item"><a href="/">Accueil</a></li>
<li class="breadcrumb-item"><a href="/home">Accueil</a></li>
<li class="breadcrumb-item active">Ami</li>
</ol>
<style>.btn-mrg{margin:15px; margin-left:87%}</style>

@ -21,8 +21,85 @@
<i class="fas fa-chart-area me-1"></i>
Stastiques globales
</div>
<div class="card-body">
{# <canvas id="myAreaChart" width="100%" height="40"></canvas> #}
<div>
<canvas id="myChart" height="50" width="100">
<p>Hello Fallback World</p>
</canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
const ctx = document.getElementById('myChart');
const labels = [
{% for chart in charts %}
{{ chart.mois }},
{% endfor %}
];
const data = [
{% for chart in charts %}
{{ chart.act }},
{% endfor %}
];
new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: 'Activité du mois',
data: data,
borderWidth: 1,
tension: 0.2,
fill: false,
borderColor: 'rgb(255, 0, 0)'
}]
},
options: {
scales: {
x: {
// type: 'linear', // Utiliser une échelle linéaire pour les mois
position: 'bottom'
},
y: {
beginAtZero: true
}
}
}
});
{#const ctx = document.getElementById('myChart');#}
{#const labels = [#}
{# {% for chart in charts %}#}
{# '{{ chart.mois }}',#}
{# {% endfor %}#}
{#];#}
{#const data = [#}
{# {% for chart in charts %}#}
{# {{ chart.act }},#}
{# {% endfor %}#}
{#];#}
{#new Chart(ctx, {#}
{# type: 'line',#}
{# data: {#}
{# labels: labels,#}
{# datasets: [{#}
{# label: 'Activité du mois',#}
{# data: data,#}
{# borderWidth: 1,#}
{# tension: 0.2,#}
{# fill: false,#}
{# borderColor: 'rgb(255, 0, 0)'#}
{# }]#}
{# },#}
{# options: {#}
{# scales: {#}
{# y: {#}
{# beginAtZero: true#}
{# }#}
{# }#}
{# }#}
{#});#}
</script>
</div>
</div>
</div>

@ -9,33 +9,56 @@
{% block user %}{{user}} - {{role}}{% endblock %}
{% block body %}
<div class="container-fluid px-4">
<div class="container-fluid px-4">
<h1 class="mt-4">Importer</h1>
<ol class="breadcrumb mb-4">
<li class="breadcrumb-item"><a href="home.html">Accueil</a></li>
<li class="breadcrumb-item"><a href="/">Accueil</a></li>
<li class="breadcrumb-item active">Importer</li>
</ol>
<div class="row">
<div class="col">
<div class="card mb-4">
<div class="card-header">
<img src="/assets/img/bupload.png"></i>
Importer un fichier .fit
</div>
<div class="card-body">
<div style="text-align:center; margin-bottom: 15px;">
<label for="file-input">
<img src="/assets/img/uploadW.svg"/>
<div class="flex items-center justify-center">
<div class="sm:max-w-lg w-full p-10 bg-white rounded-xl z-10 ">
<div class="text-center">
<h2 class="mt-5 text-3xl font-bold text-gray-900">
Importer un fichier .fit !
</h2>
<p class="mt-2 text-sm text-gray-400">Let's go</p>
</div>
<form class="mt-8 space-y-3" action="/upload" method="POST" enctype="multipart/form-data">
<div class="grid grid-cols-1 space-y-2">
<label class="text-sm font-bold text-gray-500 tracking-wide">Veuillez renseigner le type d'activité</label>
<input class="text-base p-2 border border-gray-300 rounded-lg focus:outline-none focus:border-indigo-500" type="text" name="activityType" placeholder="Course à pied">
</div>
<div class="grid grid-cols-1 space-y-2">
<label class="text-sm font-bold text-gray-500 tracking-wide">Effort Level (0-5)</label>
<input class="text-base p-2 border border-gray-300 rounded-lg focus:outline-none focus:border-indigo-500" type="number" name="effort" min="0" max="5" placeholder="Enter effort level (0-5)">
</div>
<div class="grid grid-cols-1 space-y-2">
<label class="text-sm font-bold text-gray-500 tracking-wide">Attach Document</label>
<div class="flex items-center justify-center w-full">
<label class="flex flex-col rounded-lg border-4 border-dashed w-full h-60 p-10 group text-center cursor-pointer">
<div class="h-full w-full text-center flex flex-col items-center justify-center items-center ">
<div class="flex flex-auto max-h-48 w-2/5 mx-auto -mt-10">
<img class="has-mask h-36 object-center" src="https://img.freepik.com/free-vector/image-upload-concept-landing-page_52683-27130.jpg?size=338&ext=jpg" alt="freepik image">
</div>
<p class="pointer-none text-gray-500 "><span class="text-sm">Drag and drop</span> files here <br /> or
<span class="text-blue-600 hover:underline">select a file</span>
from your computer</p>
</div>
<input type="file" class="hidden" id="file-input" name="uploaded_file" accept=".fit">
</label>
<form action="/analyses" method="post">
<input id="file-input" type="file" name="fileToUpload" value=""style="visibility: hidden; width:0; height:0;"/>
<input type="submit" value="Soumettre le fichier" name="submit"/>
</form>
<p id="file-name-display" class="text-sm text-gray-500"></p>
</div>
</div>
<p class="text-sm text-gray-300">
<span>File type: .fit</span>
</p>
<div class="flex justify-center">
<button type="submit" class="my-5 w-3/4 flex justify-center bg-blue-500 text-gray-100 p-4 rounded-full tracking-wide
font-semibold focus:outline-none focus:shadow-outline hover:bg-blue-600 shadow-lg cursor-pointer transition ease-in duration-300">
Upload
</button>
</div>
</form>
</div>
</div>
</div>

@ -1,3 +1,6 @@
<!--<<<<<<< HEAD-->
<!--<a href="/log">Se connecter</button>-->
<!--=======-->
<!DOCTYPE html>
<html lang="en">
<head>
@ -28,8 +31,8 @@
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ms-auto me-4 my-3 my-lg-0">
<li class="nav-item"><a class="nav-link me-lg-3" href="/log">Se connecter</a></li>
<li class="nav-item"><a class="nav-link me-lg-3" href="/regist">S'inscire</a></li>
<li class="nav-item"><a class="nav-link me-lg-3" href="/login">Se connecter</a></li>
<li class="nav-item"><a class="nav-link me-lg-3" href="/register">S'inscire</a></li>
</ul>
<button class="btn btn-primary rounded-pill px-3 mb-2 mb-lg-0" data-bs-toggle="modal" data-bs-target="#feedbackModal">
<span class="d-flex align-items-center">
@ -202,7 +205,7 @@
<!-- App badge section-->
<section class="bg-gradient-primary-to-secondary" id="download">
<div class="container px-5">
<h2 class="text-center text-white font-alt mb-4">Application bientôt disponible !</h2>
<h2 class="text-center text-white font-alt mb-4">Application mobile bientôt disponible !</h2>
<!-- <div class="d-flex flex-column flex-lg-row align-items-center justify-content-center">
<a class="me-lg-3 mb-4 mb-lg-0" href="#!"><img class="app-badge" src="assets/img/google-play-badge.svg" alt="..." /></a>
<a href="#!"><img class="app-badge" src="assets/img/app-store-badge.svg" alt="..." /></a>
@ -290,3 +293,4 @@
<script src="https://cdn.startbootstrap.com/sb-forms-latest.js"></script>
</body>
</html>
<!--&gt;>>>>>> origin/merged_PLE-->

@ -1,40 +1,79 @@
{% extends "authbase.html.twig" %}
{% block css %}{{css}}{% endblock %}
{% block css %}{{ css }}{% endblock %}
{% block title %}Connexion - HearthTrack{% endblock %}
{% block main %}
{#<<<<<<< HEAD#}
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-5">
<div class="card shadow-lg border-0 rounded-lg mt-5">
<div class="card-header"><h3 class="text-center font-weight-light my-4">Connexion</h3></div>
<div class="card-body">
<form>
{% if login_error %}
{% for value in login_error %}
<div class="alert alert-danger" role="alert">
{{ value }}
{#=======#}
{# <div class="container">#}
{# <div class="row justify-content-center">#}
{# <div class="col-lg-5">#}
{# <div class="card shadow-lg border-0 rounded-lg mt-5">#}
{# <div class="card-header"><h3 class="text-center font-weight-light my-4">Connexion</h3></div>#}
{# <div class="card-body">#}
{# <form>#}
{# <div class="form-floating mb-3">#}
{# <input class="form-control" id="inputEmail" type="email" placeholder="nom@exemple.com" />#}
{# <label for="inputEmail">Adresse eMail</label>#}
{# </div>#}
{# <div class="form-floating mb-3">#}
{# <input class="form-control" id="inputPassword" type="password" placeholder="Mot de passe" />#}
{# <label for="inputPassword">Mot de passe</label>#}
{# </div>#}
{# <div class="form-check mb-3">#}
{# <input class="form-check-input" id="inputRememberPassword" type="checkbox" value="" />#}
{# <label class="form-check-label" for="inputRememberPassword">Mémoriser le mot de passe</label>#}
{# </div>#}
{# <div class="d-flex align-items-center justify-content-between mt-4 mb-0">#}
{# <a class="small" href="/pass">Mot de passe oublié ?</a>#}
{# <a class="btn btn-primary" href="/home">Se connecter</a>#}
{# </div>#}
{# </form>#}
{# </div>#}
{# <div class="card-footer text-center py-3">#}
{# <div class="small"><a href="/regist">Besoin d'un compte ? Inscrivez-vous !</a></div>#}
{# </div>#}
{#>>>>>>> origin/merged_PLE#}
</div>
{% endfor %}
{% endif %}
<form method="post" action="/login">
<div class="form-floating mb-3">
<input class="form-control" id="inputEmail" type="email" placeholder="nom@exemple.com" />
<label for="inputEmail">Adresse eMail</label>
<input class="form-control" id="email" name="email" type="text" placeholder="Nom d'utilisateur" />
<label for="email">Nom d'utilisateur</label>
</div>
<div class="form-floating mb-3">
<input class="form-control" id="inputPassword" type="password" placeholder="Mot de passe" />
<label for="inputPassword">Mot de passe</label>
<input class="form-control" id="password" name="password" type="password" placeholder="Mot de passe" />
<label for="password">Mot de passe</label>
</div>
<div class="form-check mb-3">
<input class="form-check-input" id="inputRememberPassword" type="checkbox" value="" />
<label class="form-check-label" for="inputRememberPassword">Mémoriser le mot de passe</label>
</div>
<div class="d-flex align-items-center justify-content-between mt-4 mb-0">
<a class="small" href="/pass">Mot de passe oublié ?</a>
<a class="btn btn-primary" href="/home">Se connecter</a>
<a class="small" href="/forgetPassword">Mot de passe oublié ?</a>
<button class="btn btn-primary" type="submit">Se connecter</button>
</div>
</form>
</div>
<div class="card-footer text-center py-3">
<div class="small"><a href="/regist">Besoin d'un compte ? Inscrivez-vous !</a></div>
<div class="small"><a href="/register">Besoin d'un compte ? Inscrivez-vous !</a></div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% endblock %}

@ -23,14 +23,16 @@
<th>Lu</th>
<th>De:</th>
<th>Description</th>
<th>Date</th>
</tr>
</thead>
<tbody>
{% for mail in mails %}
<tr>
<td><img src="/assets/img/verif/{{mail.lu}}.png" width="25px" height="25px"></td>
<td>{{mail.nom}} {{mail.prenom}}</td>
<td><img src="/assets/img/verif/{{mail.idnotif}}.png" width="25px" height="25px"></td>
<td>{{mail.idathlete}}</td>
<td><a href="#">{{mail.message}}</a></td>
<td>{{ mail.date }}</td>
</tr>
{% endfor %}
</tbody>

@ -12,19 +12,31 @@
<div class="card-header"><h3 class="text-center font-weight-light my-4">Récupération du mot de passe</h3></div>
<div class="card-body">
<div class="small mb-3 text-muted">Entrez votre adresse eMail pour recevoir un lien pour changer de mot de passe</div>
<form method="post" action="/password">
{#<<<<<<< HEAD#}
<form method="post" action="/">
{#=======#}
{# <form method="post" action="/password">#}
{#>>>>>>> origin/merged_PLE#}
<div class="form-floating mb-3">
<input class="form-control" id="email" name="email" type="email" placeholder="name@example.com" />
<label for="email">Adresse eMail</label>
</div>
<div class="d-flex align-items-center justify-content-between mt-4 mb-0">
<a class="small" href="/log">Retour à la connexion</a>
{#<<<<<<< HEAD#}
<a class="small" href="/login">Retour à la connexion</a>
{#=======#}
{# <a class="small" href="/log">Retour à la connexion</a>#}
{#>>>>>>> origin/merged_PLE#}
<button class="btn btn-primary" type="submit">Réinitialiser votre mot de passe</button>
</div>
</form>
</div>
<div class="card-footer text-center py-3">
<div class="small"><a href="/regist">Besoin d'un compte ? Inscrivez-vous !</a></div>
{#<<<<<<< HEAD#}
<div class="small"><a href="/register">Besoin d'un compte ? Inscrivez-vous !</a></div>
{#=======#}
{# <div class="small"><a href="/regist">Besoin d'un compte ? Inscrivez-vous !</a></div>#}
{#>>>>>>> origin/merged_PLE#}
</div>
</div>
</div>

@ -12,7 +12,7 @@
<div class="container-fluid px-4">
<h1 class="mt-4">Profile</h1>
<ol class="breadcrumb mb-4">
<li class="breadcrumb-item"><a href="/">Accueil</a></li>
<li class="breadcrumb-item"><a href="/home">Accueil</a></li>
<li class="breadcrumb-item active">Profile</li>
</ol>
<div class="row">

@ -11,82 +11,131 @@
<div class="card shadow-lg border-0 rounded-lg mt-5">
<div class="card-header"><h3 class="text-center font-weight-light my-4">Créer un compte</h3></div>
<div class="card-body">
{# Display error message if register_error is set #}
{% if register_error %}
{% for value in register_error %}
<div class="alert alert-danger" role="alert">
{{ value }}
</div>
{% endfor %}
{% endif %}
<form method="post" action="/register">
<div class="row mb-3">
<div class="col-md-6">
<div class="form-floating mb-3 mb-md-0">
<input class="form-control" id="inputFirstName" type="text" placeholder="Entrez votre nom" />
<label for="inputFirstName">Nom de famille</label>
<input class="form-control" id="nom" name="nom" type="text" placeholder="Entrez votre nom" />
<label for="nom">Nom de famille</label>
</div>
</div>
<div class="col-md-6">
<div class="form-floating">
<input class="form-control" id="inputLastName" type="text" placeholder="Entrez votre prénom" />
<label for="inputLastName">Prénom</label>
<input class="form-control" id="prenom" name="prenom" type="text" placeholder="Entrez votre prénom" />
<label for="prenom">Prénom</label>
</div>
</div>
</div>
<div class="row mb-3">
<div class="col-md-6">
<div class="form-floating mb-3 mb-md-0">
<label for="inputUsername"></label><input class="form-control" id="inputUsername" type="text" placeholder="Entrez votre pseudonyme" />
<label for="inputFirstName">Nom d'utilisateur</label>
{#<<<<<<< HEAD#}
<input class="form-control" id="username" name="username" type="text" placeholder="Entrez votre pseudonyme" />
<label for="username">Nom d'utilisateur</label>
{#=======#}
{# <label for="inputUsername"></label><input class="form-control" id="inputUsername" type="text" placeholder="Entrez votre pseudonyme" />#}
{# <label for="inputFirstName">Nom d'utilisateur</label>#}
{#>>>>>>> origin/merged_PLE#}
</div>
</div>
<div class="col-md-6">
<label for="sexe" >Sexe:</label>
<div class="form-floating">
<label for="inputLastName">Sexe</label>
<label for="gender"></label><select id="gender" name="gender">
<option value="male">Homme</option>
<option value="female">Femme</option>
<option value="unknown">Ne se prononce pas</option>
{#<<<<<<< HEAD#}
<select id="sexe" name="sexe">
<option value="M">Homme</option>
<option value="H">Femme</option>
<option value="M">Ne se prononce pas</option>
{#=======#}
{# <label for="inputLastName">Sexe</label>#}
{# <label for="gender"></label><select id="gender" name="gender">#}
{# <option value="male">Homme</option>#}
{# <option value="female">Femme</option>#}
{# <option value="unknown">Ne se prononce pas</option>#}
{#>>>>>>> origin/merged_PLE#}
</select>
</div>
</div>
</div>
<div class="form-floating mb-3">
<input class="form-control" id="inputEmail" type="email" placeholder="nom@exemple.com" />
<label for="inputEmail">Adresse eMail</label>
<input class="form-control" id="mail" name="mail" type="mail" placeholder="nom@exemple.com" />
<label for="mail">Adresse eMail</label>
</div>
<div class="form-floating mb-3">
<input class="form-control" id="inputDateNaissance" type="date" placeholder="" />
<label for="inputEmail">Date de naissance</label>
<input class="form-control" id="dateNaissance" name="dateNaissance" type="date" placeholder="" />
<label for="dateNaissance">Date de naissance</label>
</div>
<div class="row mb-3">
<div class="col-md-6">
<div class="form-floating mb-3 mb-md-0">
<input class="form-control" id="inputTaille" type="text" placeholder="Entrez votre taille" />
<label for="inputPassword">Taille</label>
<input class="form-control" id="taille" name="taille" type="text" placeholder="Entrez votre taille" />
<label for="taille">Taille</label>
</div>
</div>
<div class="col-md-6">
<div class="form-floating mb-3 mb-md-0">
<label for="inputPoids"></label><input class="form-control" id="inputPoids" type="text" placeholder="Entrez votre poids" />
<label for="inputPasswordConfirm">Poids</label>
{#<<<<<<< HEAD#}
<input class="form-control" id="poids" name="poids" type="text" placeholder="Entrez votre poids" />
<label for="poids">Poids</label>
{#=======#}
{# <label for="inputPoids"></label><input class="form-control" id="inputPoids" type="text" placeholder="Entrez votre poids" />#}
{# <label for="inputPasswordConfirm">Poids</label>#}
{#>>>>>>> origin/merged_PLE#}
</div>
</div>
</div>
<div class="row mb-3">
<div class="col-md-6">
<div class="form-floating mb-3 mb-md-0">
<input class="form-control" id="inputPassword" type="password" placeholder="Créez un mot de passe" />
<label for="inputPassword">Mot de passe</label>
<input class="form-control" id="motDePasse" name="motDePasse" type="password" placeholder="Créez un mot de passe" />
<label for="motDePasse">Mot de passe</label>
</div>
</div>
<div class="col-md-6">
<div class="form-floating mb-3 mb-md-0">
<input class="form-control" id="inputPasswordConfirm" type="password" placeholder="Confirmez votre mot de passe" />
<label for="inputPasswordConfirm">Confirmer le mot de passe</label>
<input class="form-control" id="confirmMdp" name="confirmMdp" type="password" placeholder="Confirmez votre mot de passe" />
<label for="confirmMdp">Confirmer le mot de passe</label>
</div>
</div>
</div>
<div class="row mb-3">
<div class="col-md-6">
<label for="roleName" >Role:</label>
<div class="form-floating">
<select id="roleName" name="roleName">
<option value="Athlete">Athlete</option>
<option value="Coach">Coach</option>
</select>
</div>
</div>
</div>
<div class="mt-4 mb-0">
<div class="d-grid"><a class="btn btn-primary btn-block" href="/log">Créer un compte</a></div>
{#<<<<<<< HEAD#}
<div class="d-grid">
<button type="submit" class="btn btn-primary btn-block">Créer un compte</button>
</div>
{#=======#}
{# <div class="d-grid"><a class="btn btn-primary btn-block" href="/log">Créer un compte</a></div>#}
{#>>>>>>> origin/merged_PLE#}
</div>
</form>
</div>
<div class="card-footer text-center py-3">
<div class="small"><a href="/log">Avez-vous déjà un compte ? Connectez-vous ?</a></div>
{#<<<<<<< HEAD#}
<div class="small"><a href="/login">Avez-vous déjà un compte ? Connectez-vous ?</a></div>
{#=======#}
{# <div class="small"><a href="/log">Avez-vous déjà un compte ? Connectez-vous ?</a></div>#}
{#>>>>>>> origin/merged_PLE#}
</div>
</div>
</div>

@ -12,7 +12,7 @@
<div class="container-fluid px-4">
<h1 class="mt-4">Paramètres</h1>
<ol class="breadcrumb mb-4">
<li class="breadcrumb-item"><a href="/">Accueil</a></li>
<li class="breadcrumb-item"><a href="/home">Accueil</a></li>
<li class="breadcrumb-item active">Paramètres</li>
</ol>
<div class="row">

@ -763,7 +763,13 @@ function profileMenu(Model $model)
do {
$effort = trim(fgets(STDIN));
} while ($effort < 0 || $effort > 5);
try {
$isAddActivity = $model->activityMgr->uploadFile($typeActivity, $effort, $passFile);
}catch (\Throwable $exception){
echo $exception;
}
echo $isAddActivity ? "Activité ajoutée avec succès" : "Erreur lors de l'ajout de l'activité";
case '0':
return;
@ -793,7 +799,7 @@ while (true) {
}*/
break;
case '2': // S'inscrire
if($model->userMgr->login("bruce.lee@example.com", "hello321"))
if($model->userMgr->login("bruce.lee@example.com", "password123"))
$loggedIn = true;
// if (registerUser($model)) {
// $loggedIn = true;

@ -1,86 +0,0 @@
<?php
namespace Data\Core;
use Model\User;
use Model\Athlete;
use Model\CoachAthlete;
use Repository\IUserRepository;
use Shared\IHashPassword;
class AuthService implements IAuthService {
private IUserRepository $userRepository;
private IHashPassword $passwordHacher;
private ?User $currentUser = null;
public function __construct(IUserRepository $userRepository, IHashPassword $passwordHacher) {
$this->userRepository = $userRepository;
$this->passwordHacher = $passwordHacher;
}
public function login(string $email, string $password): bool {
$user = $this->userRepository->getItemByEmail($email);
if ($user === null || !$this->validatePassword($password, $user->getPasswordHash())) {
return false;
}
$this->currentUser = $user;
// Add session handling logic here
return true;
}
public function register(string $email, string $password, array $data): bool {
if ($this->userRepository->getItemByEmail($email)) {
throw new \Exception('User already exists');
}
$hashedPassword = $this->passwordHacher->hashPassword($password);
$prenom = $data['prenom'];
$username = $data['username'];
$nom = $data['nom'];
$email = $data['email'];
$sexe = $data['sexe'];
$taille = $data['taille'];
$poids = $data['poids'];
$dateNaissance = $data['dateNaissance'] ;
$roleName = $data['roleName'];
$role = null;
if($roleName == "Coach"){
$role = new CoachAthlete();
}
else if($roleName == "Athlete"){
$role = new Athlete();
}
// Create a new user instance (you should expand on this with more data as needed)
$user = new User(
random_int(0, 100),
$nom,
$prenom,
$username,
$email,
$hashedPassword,
$sexe,
$taille,
$poids,
$dateNaissance,
//should use reflexion
$role
);
$this->userRepository->addItem($user);
$this->currentUser = $user;
// Add session handling logic here
return true;
}
public function logout(): void {
$this->currentUser = null;
// Add session handling logic here
}
public function getCurrentUser(): ?User {
return $this->currentUser;
}
private function validatePassword(string $password, string $hash): bool {
// Implement password validation logic (e.g., using password_verify if using bcrypt)
}
}

@ -2,15 +2,19 @@
namespace Data\Core;
use Shared\Log;
class Preferences {
private String $cookie;
private Array $theme;
private string $cookie;
private array $theme;
public function __construct(){
if (isset($_COOKIE['preferences'])){
$this->cookie = $_COOKIE['preferences'];
} else {
$this->cookie = setcookie('preferences', 'base_theme', time()+(3600*24)*7);
if(setcookie('preferences', 'base_theme', time()+(3600*24)*7)){
$this->cookie = 'base_theme';
}
}
$this->theme = array(
'base_theme',
@ -19,7 +23,7 @@
);
}
public function majCookie(String $maj){
public function majCookie(string $maj){
try{
foreach($this->theme as $t){
$this->cookie = $maj;
@ -30,8 +34,8 @@
}
}
public function getCookie():String{
return $this->cookie;
public function getCookie():string{
return $this->cookie ?? "base_theme";
}
}

@ -1,120 +0,0 @@
<?php
namespace Database;
class ActiviteGateway {
private $connection;
public function __construct(Connection $connection) {
$this->connection = $connection;
}
public function getActivite() {
$query = "SELECT * FROM Activite";
return $this->connection->executeWithErrorHandling($query);
}
public function getActiviteById(int $activiteId) {
$query = "SELECT * FROM Activite WHERE idActivite = :id";
$params = [':id' => [$activiteId, PDO::PARAM_INT]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getActiviteByType(string $type) {
$query = "SELECT * FROM Activite WHERE type = :type";
$params = [':type' => [$type, PDO::PARAM_STR]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getActiviteByDate(string $date) {
$query = "SELECT * FROM Activite WHERE date = :date";
$params = [':date' => [$date, PDO::PARAM_STR]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getActiviteByTimeRange(string $startTime, string $endTime) {
$query = "SELECT * FROM Activite WHERE heureDebut >= :startTime AND heureFin <= :endTime";
$params = [
':startTime' => [$startTime, PDO::PARAM_STR],
':endTime' => [$endTime, PDO::PARAM_STR]
];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getActiviteByEffort(int $effortRessenti) {
$query = "SELECT * FROM Activite WHERE effortRessenti = :effort";
$params = [':effort' => [$effortRessenti, PDO::PARAM_INT]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getActiviteByVariability(int $variabilite) {
$query = "SELECT * FROM Activite WHERE variabilite = :variability";
$params = [':variability' => [$variabilite, PDO::PARAM_INT]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getActiviteByTemperature(int $temperatureMoyenne) {
$query = "SELECT * FROM Activite WHERE temperatureMoyenne = :temperature";
$params = [':temperature' => [$temperatureMoyenne, PDO::PARAM_INT]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function addActivite(ActiviteEntity $activite) {
$query = "INSERT INTO Activite (type, date, heureDebut, heureDeFin, effortRessenti, variabilite, variance, ecartType, moyenne, maximum, minimum, temperatureMoyenne)
VALUES (:type, :date, :heureDebut, :heureDeFin, :effortRessenti, :variabilite, :variance, :ecartType, :moyenne, :maximum, :minimum, :temperatureMoyenne)";
$params = [
':type' => $activite->getType(),
':date' => $activite->getDate()->format('Y-m-d'), // Format date pour SQL
':heureDebut' => $activite->getHeureDebut()->format('H:i:s'), // Format heure pour SQL
':heureDeFin' => $activite->getHeureFin()->format('H:i:s'), // Format heure pour SQL
':effortRessenti' => $activite->getEffortRessenti(),
':variabilite' => $activite->getVariabilite(),
':variance' => $activite->getVariance(),
':ecartType' => $activite->getEcartType(),
':moyenne' => $activite->getMoyenne(),
':maximum' => $activite->getMaximum(),
':minimum' => $activite->getMinimum(),
':temperatureMoyenne' => $activite->getTemperatureMoyenne(),
];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function updateActivite(ActiviteEntity $oldActivite, ActiviteEntity $newActivite) {
$query = "UPDATE Activite
SET type = :type, date = :date, heureDebut = :heureDebut, heureDeFin = :heureDeFin,
effortRessenti = :effortRessenti, variabilite = :variabilite, variance = :variance, ecartType = :ecartType, moyenne = :moyenne, maximum = :maximum, minimum = :minimum, temperatureMoyenne = :temperatureMoyenne
WHERE idActivite = :idActivite";
$params = [
':idActivite' => $oldActivite->getIdActivite(),
':type' => $newActivite->getType(),
':date' => $newActivite->getDate()->format('Y-m-d'), // Format date pour SQL
':heureDebut' => $newActivite->getHeureDebut()->format('H:i:s'), // Format heure pour SQL
':heureDeFin' => $newActivite->getHeureFin()->format('H:i:s'), // Format heure pour SQL
':effortRessenti' => $newActivite->getEffortRessenti(),
':variabilite' => $newActivite->getVariabilite(),
':variance' => $newActivite->getVariance(),
':ecartType' => $newActivite->getEcartType(),
':moyenne' => $newActivite->getMoyenne(),
':maximum' => $newActivite->getMaximum(),
':minimum' => $newActivite->getMinimum(),
':temperatureMoyenne' => $newActivite->getTemperatureMoyenne(),
];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function deleteActivite(int $idActivite) {
$query = "DELETE FROM Activite WHERE idActivite = :idActivite";
$params = [
':idActivite' => $idActivite,
];
return $this->connection->executeWithErrorHandling($query, $params);
}
}
?>

@ -1,51 +0,0 @@
<?php
namespace Database;
use Model\Activite;
class ActiviteMapper {
public function map(array $data):ActiviteEntity {
$activite = new ActiviteEntity();
$activite->setIdActivite($data['idActivite']);
$activite->setType($data['type']);
$activite->setDate($data['date']);
$activite->setHeureDebut($data['heureDebut']);
$activite->setHeureFin($data['heureFin']);
$activite->setEffortRessenti($data['effortRessenti']);
$activite->setVariabilite($data['variabilite']);
$activite->setVariance($data['variance']);
$activite->setEcartType($data['ecartType']);
$activite->setMoyenne($data['moyenne']);
$activite->setMaximum($data['maximum']);
$activite->setMinimum($data['minimum']);
$activite->setTemperatureMoyenne($data['temperatureMoyenne']);
return $activite;
}
//public function ActiviteEntityToModel(ActiviteEntity entity): Activite;
public function ActiviteEntityToModel(ActiviteEntity $activiteEntity):Activite{
$act = new Activite(
$activiteEntity->getIdActivite(),
$activiteEntity->getType(),
$activiteEntity->getDate(),
$activiteEntity->getHeureDebut(),
$activiteEntity->getHeureFin(),
$activiteEntity->getEffortRessenti(),
$activiteEntity->getVariabilite(),
$activiteEntity->getVariance(),
$activiteEntity->getEcartType(),
$activiteEntity->getMoyenne(),
$activiteEntity->getMaximum(),
$activiteEntity->getMinimum(),
$activiteEntity->getTemperatureMoyenne()
);
return $act;
}
//public function ActiviteToEntity(Activite model): ActiviteEntity;
}
?>

@ -2,12 +2,14 @@
namespace Database;
class ActiviteEntity {
private $idActivite;
use DateTime;
class ActivityEntity {
private $idActivity;
private $type;
private $date;
private $heureDebut;
private $heureFin;
private DateTime $date;
private DateTime $heureDebut;
private DateTime $heureFin;
private $effortRessenti;
private $variabilite;
private $variance;
@ -18,7 +20,7 @@ class ActiviteEntity {
private $temperatureMoyenne;
// Getters
public function getIdActivite() {
public function getIdActivity() {
return $this->idActivity;
}
@ -42,7 +44,7 @@ class ActiviteEntity {
return $this->effortRessenti;
}
public function getVariabilite() {
public function getVariability() {
return $this->variabilite;
}
@ -71,7 +73,7 @@ class ActiviteEntity {
}
// Setters
public function setIdActivite($idActivity) {
public function setIdActivity($idActivity) {
$this->idActivity = $idActivity;
}

@ -0,0 +1,124 @@
<?php
namespace Database;
use \PDO;
use Shared\Log;
class ActivityGateway {
private Connexion $connection;
public function __construct(Connexion $connection) {
$this->connection = $connection;
}
public function getActivity() {
$query = "SELECT * FROM Activite";
return $this->connection->executeWithErrorHandling($query);
}
public function getActivityById(int $activityId) {
$query = "SELECT * FROM Activite WHERE idActivite = :id";
$params = [':id' => $activityId];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getActivityByType(string $type) {
$query = "SELECT * FROM Activite WHERE type = :type";
$params = [':type' => [$type, PDO::PARAM_STR]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getActivityByDate(string $date) {
$query = "SELECT * FROM Activite WHERE date = :date";
$params = [':date' => [$date, PDO::PARAM_STR]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getActivityByTimeRange(string $startTime, string $endTime) {
$query = "SELECT * FROM Activite WHERE heureDebut >= :startTime AND heureFin <= :endTime";
$params = [
':startTime' => [$startTime, PDO::PARAM_STR],
':endTime' => [$endTime, PDO::PARAM_STR]
];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getActivityByEffort(int $effortRessenti) {
$query = "SELECT * FROM Activite WHERE effortRessenti = :effort";
$params = [':effort' => [$effortRessenti, PDO::PARAM_INT]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getActivityByVariability(int $variabilite) {
$query = "SELECT * FROM Activite WHERE variabilite = :variability";
$params = [':variability' => [$variabilite, PDO::PARAM_INT]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getActivityByTemperature(int $temperatureMoyenne) {
$query = "SELECT * FROM Activite WHERE temperatureMoyenne = :temperature";
$params = [':temperature' => [$temperatureMoyenne, PDO::PARAM_INT]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function addActivity(ActivityEntity $activity) {
$query = "INSERT INTO Activite (idactivite, type, date, heurededebut, heuredefin, effortressent, variabilite, variance, ecarttype, moyenne, maximum, minimum, temperaturemoyenne, athleteid, sourceid)
VALUES (:idactivite, :type, :date, :heureDebut, :heureDeFin, :effortRessenti, :variabilite, :variance, :ecartType, :moyenne, :maximum, :minimum, :temperatureMoyenne, :athleteid, :sourceid)";
$params = [
':idactivite' => $activity->getIdActivity(),
':type' => $activity->getType(),
':date' => $activity->getDate()->format('Y-m-d'), // Format date pour SQL
':heureDebut' => $activity->getHeureDebut()->format('H:i:s'), // Format heure pour SQL
':heureDeFin' => $activity->getHeureFin()->format('H:i:s'), // Format heure pour SQL
':effortRessenti' => $activity->getEffortRessenti(),
':variabilite' => $activity->getVariability(),
':variance' => $activity->getVariance(),
':ecartType' => $activity->getEcartType(),
':moyenne' => $activity->getMoyenne(),
':maximum' => $activity->getMaximum(),
':minimum' => $activity->getMinimum(),
':temperatureMoyenne' => $activity->getTemperatureMoyenne(),
':athleteid' => 1,
':sourceid' => 1,
];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function updateActivity(ActivityEntity $oldActivity, ActivityEntity $newActivity) {
$query = "UPDATE Activite
SET type = :type, date = :date, heureDebut = :heureDebut, heureDeFin = :heureDeFin,
effortRessenti = :effortRessenti, variabilite = :variabilite, variance = :variance, ecartType = :ecartType, moyenne = :moyenne, maximum = :maximum, minimum = :minimum, temperatureMoyenne = :temperatureMoyenne
WHERE idActivite = :idActivite";
$params = [
':idActivite' => $oldActivity->getIdActivity(),
':type' => $newActivity->getType(),
':date' => $newActivity->getDate()->format('Y-m-d'), // Format date pour SQL
':heureDebut' => $newActivity->getHeureDebut()->format('H:i:s'), // Format heure pour SQL
':heureDeFin' => $newActivity->getHeureFin()->format('H:i:s'), // Format heure pour SQL
':effortRessenti' => $newActivity->getEffortRessenti(),
':variabilite' => $newActivity->getVariabilite(),
':variance' => $newActivity->getVariance(),
':ecartType' => $newActivity->getEcartType(),
':moyenne' => $newActivity->getMoyenne(),
':maximum' => $newActivity->getMaximum(),
':minimum' => $newActivity->getMinimum(),
':temperatureMoyenne' => $newActivity->getTemperatureMoyenne(),
];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function deleteActivity(int $idActivity) {
$query = "DELETE FROM Activite WHERE idActivite = :idActivity";
$params = [
':idActivity' => $idActivity,
];
return $this->connection->executeWithErrorHandling($query, $params);
}
}
?>

@ -0,0 +1,126 @@
<?php
namespace Database;
use DateTime;
use Model\Activity;
use Shared\Log;
class ActivityMapper {
public function activitySqlToEntity(array $data):array
{
$activityEntities = [];
foreach ($data as $activityData) {
$activity = new ActivityEntity();
if (isset($activityData['idActivite'])) {
$activity->setIdActivity($activityData['idActivite']);
}
if (isset($activityData['type'])) {
$activity->setType($activityData['type']);
}
// if (isset($activityData['date'])) {
// $activity->setDate(DateTime::createFromFormat('yyyy-mm--dd',$activityData['date']));
// }
if (isset($activityData['heureDeDebut'])) {
$activity->setHeureDebut(new DateTime($activityData['heureDeDebut']));
}
if (isset($activityData['heureDeFin'])) {
$activity->setHeureFin(new DateTime($activityData['heureDeFin']));
}
if (isset($activityData['effortRessent'])) {
$activity->setEffortRessenti($activityData['effortRessent']);
}
if (isset($activityData['variabilite'])) {
$activity->setVariabilite($activityData['variabilite']);
}
if (isset($activityData['variance'])) {
$activity->setVariance($activityData['variance']);
}
if (isset($activityData['ecartType'])) {
$activity->setEcartType($activityData['ecartType']);
}
if (isset($activityData['moyenne'])) {
$activity->setMoyenne($activityData['moyenne']);
}
if (isset($activityData['maximum'])) {
$activity->setMaximum($activityData['maximum']);
}
if (isset($activityData['minimum'])) {
$activity->setMinimum($activityData['minimum']);
}
if (isset($activityData['temperatureMoyenne'])) {
$activity->setTemperatureMoyenne($activityData['temperatureMoyenne']);
}
$activityEntities[] = $activity;
}
Log::dd($activityEntities);
return $activityEntities;
}
/**
* @throws \Exception
*/
public function ActivityEntityToModel(ActivityEntity $activiteEntity):Activity {
$date = new DateTime($activiteEntity->getDate());
$heureDebut = new \DateTime($activiteEntity->getHeureDebut());
$heureFin = new \DateTime($activiteEntity->getHeureFin());
$effortRessenti = intval($activiteEntity->getEffortRessenti());
$variability = floatval($activiteEntity->getVariability());
$variance = floatval($activiteEntity->getVariance());
$ecartType = floatval($activiteEntity->getEcartType());
$act = new Activity(
$activiteEntity->getType(),
$date,
$heureDebut,
$heureFin,
$effortRessenti,
$variability,
$variance,
$ecartType,
$activiteEntity->getMoyenne(),
$activiteEntity->getMaximum(),
$activiteEntity->getMinimum(),
$activiteEntity->getTemperatureMoyenne(),
'false'
);
return $act;
}
//public function ActivityToEntity(Activity model): ActivityEntity;
public function activityToEntity(Activity $act):ActivityEntity{
$actEntity = new ActivityEntity();
$actEntity->setIdActivity($act->getIdActivity());
$actEntity->setType($act->getType());
$actEntity->setDate($act->getDate());
$actEntity->setHeureDebut($act->getHeureDebut());
$actEntity->setHeureFin($act->getHeureFin());
$actEntity->setEffortRessenti($act->getEffortRessenti());
$actEntity->setVariabilite($act->getVariability());
$actEntity->setVariance($act->getVariance());
$actEntity->setEcartType($act->getStandardDeviation());
$actEntity->setMoyenne($act->getAverage());
$actEntity->setMaximum($act->getMaximum());
$actEntity->setMinimum($act->getMinimum());
$actEntity->setTemperatureMoyenne($act->getAvrTemperature());
return $actEntity;
}
}
?>

@ -0,0 +1,79 @@
<?php
namespace Database;
class AnalyzeEntity
{
private $idFc;
private $altitude;
private $time;
private $temperature;
private $bpm;
private $longitude;
private $latitude;
private $idactivity;
public function getIdFC()
{
return $this->idFc;
}
public function getAltitude()
{
return $this->altitude;
}
public function getTime()
{
return $this->temps;
}
public function getTemperature()
{
return $this->temperature;
}
public function getBpm()
{
return $this->bpm;
}
public function getLongitude()
{
return $this->longitude;
}
public function getLatitude()
{
return $this->latitude;
}
public function getIdActivity()
{
return $this->idactivity;
}
public function setIdFC($idFc)
{
$this->idFc = $idFc;
}
public function setAltitude($altitude)
{
$this->altitude = $altitude;
}
public function setTime($time)
{
$this->time = $time;
}
public function setTemperature($temperature)
{
$this->temperature = $temperature;
}
public function setBpm($bpm)
{
$this->bpm = $bpm;
}
public function setLongitude($longitude)
{
$this->longitude = $longitude;
}
public function setLatitude($latitude)
{
$this->latitude = $latitude;
}
public function setIdActivity($idactivity)
{
$this->idactivity = $idactivity;
}
}

@ -0,0 +1,24 @@
<?php
namespace Database;
class AnalyzeGateway
{
private Connexion $connection;
public function __construct(Connexion $connection) {
$this->connection = $connection;
}
public function getFrequenceCardiaque() {
$query = "SELECT * FROM FrequenceCardiaque";
return $this->connection->executeWithErrorHandling($query);
}
public function getFrequenceCardiaqueByIdActivity(int $activityId)
{
$query = "SELECT * FROM FrequenceCardiaque WHERE activiteid = :id";
$params = [':id' => $activityId];
return $this->connection->executeWithErrorHandling($query, $params);
}
}

@ -0,0 +1,125 @@
<?php
namespace Database;
use Shared\Log;
class AnalyzeMapper
{
public function analyzeSqlToEntity(array $data):array
{
$analyzeEntities = [];
foreach ($data as $analyzeData) {
$analyze = new ActivityEntity();
if (isset($analyzeData['idactivite'])) {
$analyze->setIdActivity($analyzeData['idactivite']);
}
if (isset($analyzeData['type'])) {
$analyze->setType($analyzeData['type']);
}
if (isset($analyzeData['date'])) {
$analyze->setDate($analyzeData['date']);
}
if (isset($analyzeData['heurededebut'])) {
$analyze->setHeureDebut($analyzeData['heurededebut']);
}
if (isset($analyzeData['heuredefin'])) {
$analyze->setHeureFin($analyzeData['heuredefin']);
}
if (isset($analyzeData['effortressent'])) {
$analyze->setEffortRessenti($analyzeData['effortressent']);
}
if (isset($analyzeData['variabilite'])) {
$analyze->setVariabilite($analyzeData['variabilite']);
}
if (isset($analyzeData['variance'])) {
$analyze->setVariance($analyzeData['variance']);
}
if (isset($analyzeData['ecarttype'])) {
$analyze->setEcartType($analyzeData['ecarttype']);
}
if (isset($analyzeData['moyenne'])) {
$analyze->setMoyenne($analyzeData['moyenne']);
}
if (isset($analyzeData['maximum'])) {
$analyze->setMaximum($analyzeData['maximum']);
}
if (isset($analyzeData['minimum'])) {
$analyze->setMinimum($analyzeData['minimum']);
}
if (isset($analyzeData['temperaturemoyenne'])) {
$analyze->setTemperatureMoyenne($analyzeData['temperaturemoyenne']);
}
$analyzeEntities[] = $analyze;
}
return $analyzeEntities;
}
/**
* @throws \Exception
*/
// public function ActivityEntityToModel(ActivityEntity $activiteEntity):Activity {
// $date = new DateTime($activiteEntity->getDate());
// $heureDebut = new \DateTime($activiteEntity->getHeureDebut());
// $heureFin = new \DateTime($activiteEntity->getHeureFin());
// $effortRessenti = intval($activiteEntity->getEffortRessenti());
// $variability = floatval($activiteEntity->getVariability());
// $variance = floatval($activiteEntity->getVariance());
// $ecartType = floatval($activiteEntity->getEcartType());
//
// $act = new Activity(
// $activiteEntity->getIdActivity(),
// $activiteEntity->getType(),
// $date,
// $heureDebut,
// $heureFin,
// $effortRessenti,
// $variability,
// $variance,
// $ecartType,
// $activiteEntity->getMoyenne(),
// $activiteEntity->getMaximum(),
// $activiteEntity->getMinimum(),
// $activiteEntity->getTemperatureMoyenne(),
// 'false'
// );
//
// return $act;
// }
//public function ActivityToEntity(Activity model): ActivityEntity;
// public function activityToEntity( $act):ActivityEntity{
//
// $act = new ActivityEntity();
// $act->setIdActivity($act->getIdActivity()());
// $act->setType($act->getType());
// $act->setDate($act->getDate());
// $act->setHeureDebut($act->getHeureDebut());
// $act->setHeureFin($act->getHeureFin());
// $act->setEffortRessenti($act->getEffortRessenti());
// $act->setVariabilite($act->getVariability());
// $act->setVariance($act->getVariance());
// $act->setEcartType($act->getEcartType());
// $act->setMoyenne($act->getMoyenne());
// $act->setMaximum($act->getMaximum());
// $act->setMinimum($act->getMinimum());
// $act->setTemperatureMoyenne($act->getTemperatureMoyenne());
//
// return $act;
// }
}

@ -6,12 +6,14 @@ class AthleteEntity {
private $idAthlete;
private $nom;
private $prenom;
private $username;
private $email;
private $sexe;
private $taille;
private $poids;
private $motDePasse;
private $dateNaissance;
private $isCoach;
// Getters
public function getIdAthlete() {
@ -26,6 +28,10 @@ class AthleteEntity {
return $this->prenom;
}
public function getUsername(){
return $this->username;
}
public function getEmail() {
return $this->email;
}
@ -50,6 +56,11 @@ class AthleteEntity {
return $this->dateNaissance;
}
public function getIsCoach(){
return $this->isCoach;
}
// Setters
public function setIdAthlete($idAthlete) {
$this->idAthlete = $idAthlete;
@ -63,6 +74,10 @@ class AthleteEntity {
$this->prenom = $prenom;
}
public function setUsername($username){
$this->username = $username;
}
public function setEmail($email) {
$this->email = $email;
}
@ -86,6 +101,10 @@ class AthleteEntity {
public function setDateNaissance($dateNaissance) {
$this->dateNaissance = $dateNaissance;
}
public function setIsCoach($isCoach){
$this->isCoach = $isCoach;
}
}
?>

@ -2,70 +2,131 @@
namespace Database;
use \PDO;
use Shared\Log;
class AthleteGateway {
private $connection;
private Connexion $connection;
public function __construct(Connexion $connection) {
$this->connection = $connection;
}
public function getAthlete() {
$query = "SELECT * FROM Athlete";
return $this->connection->executeWithErrorHandling($query);
public function getAthlete(): array
{
$query = "SELECT * FROM Athlete WHERE isCoach=FALSE";
$res = $this->connection->executeWithErrorHandling($query);
return $res;
}
public function getAthleteById(int $userId) {
$query = "SELECT * FROM Athlete WHERE idAthlete = :id";
$params = [':id' => [$userId, PDO::PARAM_INT]];
return $this->connection->executeWithErrorHandling($query, $params);
public function getAthleteById(int $userId): array
{
$query = "SELECT * FROM Athlete WHERE idAthlete = :id AND isCoach=FALSE";
$params = [':id' => $userId];
// log::dd($params);
$res = $this->connection->executeWithErrorHandling($query, $params);
return $res;
}
public function getAthleteByName(string $name) {
$query = "SELECT * FROM Athlete WHERE nom = :name";
$params = [':name' => [$name, PDO::PARAM_STR]];
public function getAthleteByName(string $name): array
{
$query = "SELECT * FROM Athlete WHERE nom = :name AND isCoach=FALSE";
$params = [':name' => $name];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getAthleteByFirstName(string $firstName) {
$query = "SELECT * FROM Athlete WHERE prenom = :firstName";
$params = [':firstName' => [$firstName, PDO::PARAM_STR]];
public function getAthleteByFirstName(string $firstName): array
{
$query = "SELECT * FROM Athlete WHERE prenom = :firstName AND isCoach=FALSE";
$params = [':firstName' => $firstName];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getAthleteByEmail(string $email) {
public function getAthleteByEmail(string $email): array
{
$query = "SELECT * FROM Athlete WHERE email = :email AND isCoach=FALSE";
$params = [':email' => $email];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getUserByEmail(string $email): array
{
$query = "SELECT * FROM Athlete WHERE email = :email";
$params = [':email' => [$email, PDO::PARAM_STR]];
$params = [':email' => $email];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getAthleteByGender(string $gender) {
$query = "SELECT * FROM Athlete WHERE sexe = :gender";
$params = [':gender' => [$gender, PDO::PARAM_STR]];
public function getAthleteByGender(string $gender): array
{
$query = "SELECT * FROM Athlete WHERE sexe = :gender AND isCoach=FALSE";
$params = [':gender' => $gender];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getAthleteByHeight(int $height) {
$query = "SELECT * FROM Athlete WHERE taille = :height";
public function getAthleteByHeight(int $height): array
{
$query = "SELECT * FROM Athlete WHERE taille = :height AND isCoach=FALSE";
$params = [':height' => [$height, PDO::PARAM_INT]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getAthleteByWeight(int $weight) {
$query = "SELECT * FROM Athlete WHERE poids = :weight";
public function getAthleteByWeight(int $weight): array
{
$query = "SELECT * FROM Athlete WHERE poids = :weight AND isCoach=FALSE";
$params = [':weight' => [$weight, PDO::PARAM_INT]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getAthleteByBirthDate(string $birthdate) {
$query = "SELECT * FROM Athlete WHERE dateNaissance = :birthdate";
public function getAthleteByBirthDate(string $birthdate): array
{
$query = "SELECT * FROM Athlete WHERE dateNaissance = :birthdate AND isCoach=FALSE";
$params = [':birthdate' => [$birthdate, PDO::PARAM_STR]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function addAthlete(AthleteEntity $athlete) {
$query = "INSERT INTO Athlete (nom, prenom, email, sexe, taille, poids, motDePasse, dateNaissance)
VALUES (:nom, :prenom, :email, :sexe, :taille, :poids, :motDePasse, :dateNaissance)";
public function getListIdFriends(int $idAthlete): array
{
$query = "SELECT idAthlete1, idAthlete2 FROM Friendship WHERE idAthlete1 = :idAthlete OR idAthlete2= :idAthlete";
$params = [
':idAthlete' => $idAthlete,
];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getListActivity(int $idAthlete): array
{
/*$query = "SELECT count(ac.idActivite) AS nbActivite, EXTRACT(MONTH FROM ac.date) AS mois
FROM Athlete at, Activite ac
WHERE at.idAthlete = :idAthlete
AND ac.date > CURRENT_DATE - INTERVAL '1 YEAR'
AND ac.athleteId = at.idAthlete
GROUP BY mois";*/
$query = "SELECT COUNT(ac.idActivite) AS nbActivite, EXTRACT(MONTH FROM ac.date) AS mois
FROM Athlete at
JOIN Activite ac ON ac.athleteId = at.idAthlete
WHERE at.idAthlete = :idAthlete
AND ac.date > CURRENT_DATE - INTERVAL 1 YEAR
GROUP BY mois";
// $query = "SELECT count(ac.idActivite) AS nbActivite, EXTRACT(MONTH FROM ac.date) AS mois
// FROM Athlete at, Activite ac
// WHERE at.idAthlete = :idAthlete
// AND ac.date > CURRENT_DATE - INTERVAL '1 YEAR'
// AND ac.athleteId = at.idAthlete
// GROUP BY mois";
$params = [
':idAthlete' => $idAthlete,
];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function addAthlete(AthleteEntity $athlete): array
{
$query = "INSERT INTO Athlete (nom, prenom, email, sexe, taille, poids, motDePasse, dateNaissance, isCoach)
VALUES (:nom, :prenom, :email, :sexe, :taille, :poids, :motDePasse, :dateNaissance, :isCoach)";
$params = [
':nom' => $athlete->getNom(),
@ -76,19 +137,22 @@ class AthleteGateway {
':poids' => $athlete->getPoids(),
':motDePasse' => $athlete->getMotDePasse(),
':dateNaissance' => $athlete->getDateNaissance(),
':isCoach' => $athlete->getIsCoach(),
];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function updateAthlete(AthleteEntity $oldAthlete, AthleteEntity $newAthlete) {
public function updateAthlete(AthleteEntity $oldAthlete, AthleteEntity $newAthlete): array
{
$query = "UPDATE Athlete
SET nom = :nom, prenom = :prenom, email = :email, sexe = :sexe,
taille = :taille, poids = :poids, motDePasse = :motDePasse, dateNaissance = :dateNaissance
SET username = :username, nom = :nom, prenom = :prenom, email = :email, sexe = :sexe,
taille = :taille, poids = :poids, motDePasse = :motDePasse, dateNaissance = :dateNaissance, isCoach = :isCoach
WHERE idAthlete = :idAthlete";
$params = [
':idAthlete' => $oldAthlete->getIdAthlete(),
':username' => $newAthlete->getUsername(),
':nom' => $newAthlete->getNom(),
':prenom' => $newAthlete->getPrenom(),
':email' => $newAthlete->getEmail(),
@ -97,12 +161,14 @@ class AthleteGateway {
':poids' => $newAthlete->getPoids(),
':motDePasse' => $newAthlete->getMotDePasse(),
':dateNaissance' => $newAthlete->getDateNaissance(),
':isCoach' => $newAthlete->getIsCoach(),
];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function deleteAthlete(int $idAthlete) {
public function deleteAthlete(int $idAthlete): array
{
$query = "DELETE FROM Athlete WHERE idAthlete = :idAthlete";
$params = [

@ -6,14 +6,14 @@ use \PDO;
use \DateTime;
use Model\Role;
use Model\Athlete;
use Shared\Log;
class AthleteMapper {
public function fromSqlToEntity(array $data): array {
public function athleteSqlToEntity(array $data): array {
$athleteEntities = [];
foreach ($data as $athleteData) {
$athlete = new AthleteEntity();
if (isset($athleteData['idAthlete'])) {
$athlete->setIdAthlete($athleteData['idAthlete']);
}
@ -26,6 +26,10 @@ class AthleteMapper {
$athlete->setPrenom($athleteData['prenom']);
}
if (isset($athleteData['username'])) {
$athlete->setUsername($athleteData['username']);
}
if (isset($athleteData['email'])) {
$athlete->setEmail($athleteData['email']);
}
@ -50,6 +54,10 @@ class AthleteMapper {
$athlete->setDateNaissance($athleteData['dateNaissance']);
}
if (isset($athleteData['isCoach'])) {
$athlete->setIsCoach($athleteData['isCoach']);
}
$athleteEntities[] = $athlete;
}
@ -58,19 +66,19 @@ class AthleteMapper {
public function athleteEntityToModel(AthleteEntity $athleteEntity): User {
$role = new Athlete(); // Utilisez la classe Athlete
$dateSpecifique = $athleteEntity->getDateNaissance();
$date = new DateTime($dateSpecifique);
$date = new DateTime($athleteEntity->getDateNaissance());
$poids = floatval($athleteEntity->getPoids());
$taille = floatval($athleteEntity->getTaille());
$user = new User(
$athleteEntity->getIdAthlete(),
$athleteEntity->getNom(),
$athleteEntity->getPrenom(),
$athleteEntity->getUsername(),
$athleteEntity->getEmail(),
$athleteEntity->getMotDePasse(),
$athleteEntity->getSexe(),
$athleteEntity->getTaille(),
$athleteEntity->getPoids(),
$taille,
$poids,
$date,
$role
);
@ -84,12 +92,15 @@ class AthleteMapper {
$ath->setIdAthlete($user->getId());
$ath->setNom($user->getNom());
$ath->setPrenom($user->getPrenom());
$ath->setUsername($user->getUsername());
$ath->setEmail($user->getEmail());
$ath->setSexe($user->getSexe());
$ath->setTaille($user->getTaille());
$ath->setPoids($user->getPoids());
$ath->setMotDePasse($user->getMotDePasse());
$ath->setDateNaissance($user->getDateNaissance());
$ath->setIsCoach(FALSE);
$ath->setCoachId(NULL);
return $ath;
}

@ -6,12 +6,14 @@ class CoachEntity {
private $idCoach;
private $nom;
private $prenom;
private $username;
private $email;
private $sexe;
private $taille;
private $poids;
private $motDePasse;
private $dateNaissance;
private $isCoach;
// Getters
public function getIdCoach() {
@ -26,6 +28,10 @@ class CoachEntity {
return $this->prenom;
}
public function getUsername(){
return $this->username;
}
public function getEmail() {
return $this->email;
}
@ -50,6 +56,11 @@ class CoachEntity {
return $this->dateNaissance;
}
public function getIsCoach(){
return $this->isCoach;
}
// Setters
public function setIdCoach($idCoach) {
$this->idCoach = $idCoach;
@ -63,6 +74,10 @@ class CoachEntity {
$this->prenom = $prenom;
}
public function setUsername($username){
$this->username = $username;
}
public function setEmail($email) {
$this->email = $email;
}
@ -86,6 +101,11 @@ class CoachEntity {
public function setDateNaissance($dateNaissance) {
$this->dateNaissance = $dateNaissance;
}
public function setIsCoach($isCoach){
$this->isCoach = $isCoach;
}
}
?>

@ -10,93 +10,96 @@ class CoachGateway {
$this->connection = $connection;
}
public function getCoach() {
public function getCoach(): array
{
$query = "SELECT * FROM Coach";
return $this->connection->executeWithErrorHandling($query);
}
public function getCoachById(int $userId) {
public function getCoachById(int $userId): array
{
$query = "SELECT * FROM Coach WHERE idCoach = :id";
$params = [':id' => [$userId, PDO::PARAM_INT]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getCoachByName(string $name) {
$query = "SELECT * FROM Coach WHERE nom = :name";
public function getAthleteByCoachId(int $coachId): array
{
$query = "SELECT * FROM Athlete a, Coach c WHERE a.coachId = :id AND a.isCoach = TRUE";
$params = [':id' => [$coachId, PDO::PARAM_INT]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getCoachByName(string $name): array
{
$query = "SELECT * FROM Coach c, Athlete a WHERE c.athleteId = a.idAthlete AND a.nom = :name";
$params = [':name' => [$name, PDO::PARAM_STR]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getCoachByFirstName(string $firstName) {
$query = "SELECT * FROM Coach WHERE prenom = :firstName";
public function getCoachByFirstName(string $firstName): array
{
$query = "SELECT * FROM Coach c, Athlete a WHERE c.athleteId = a.idAthlete AND a.prenom = :firstName";
$params = [':firstName' => [$firstName, PDO::PARAM_STR]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getCoachByEmail(string $email) {
$query = "SELECT * FROM Coach WHERE email = :email";
public function getCoachByEmail(string $email): array
{
$query = "SELECT * FROM Coach c, Athlete a WHERE c.athleteId = a.idAthlete AND a.email = :email";
$params = [':email' => [$email, PDO::PARAM_STR]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getCoachByGender(string $gender) {
$query = "SELECT * FROM Coach WHERE sexe = :gender";
public function getCoachByGender(string $gender): array
{
$query = "SELECT * FROM Coach c, Athlete a WHERE c.athleteId = a.idAthlete AND a.sexe = :gender";
$params = [':gender' => [$gender, PDO::PARAM_STR]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getCoachByHeight(int $height) {
$query = "SELECT * FROM Coach WHERE taille = :height";
public function getCoachByHeight(int $height): array
{
$query = "SELECT * FROM Coach c, Athlete a WHERE c.athleteId = a.idAthlete AND a.taille = :height";
$params = [':height' => [$height, PDO::PARAM_INT]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getCoachByBirthDate(string $birthdate) {
$query = "SELECT * FROM Coach WHERE dateNaissance = :birthdate";
public function getCoachByBirthDate(string $birthdate): array
{
$query = "SELECT * FROM Coach c, Athlete a WHERE c.athleteId = a.idAthlete AND a.dateNaissance = :birthdate";
$params = [':birthdate' => [$birthdate, PDO::PARAM_STR]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function addCoach(CoachEntity $coach) {
$query = "INSERT INTO Coach (nom, prenom, email, sexe, taille, poids, motDePasse, dateNaissance)
VALUES (:nom, :prenom, :email, :sexe, :taille, :poids, :motDePasse, :dateNaissance)";
public function addCoach(CoachEntity $coach): array
{
$query = "INSERT INTO Coach (athleteId)
VALUES (:athleteId)";
$params = [
':nom' => $coach->getNom(),
':prenom' => $coach->getPrenom(),
':email' => $coach->getEmail(),
':sexe' => $coach->getSexe(),
':taille' => $coach->getTaille(),
':poids' => $coach->getPoids(),
':motDePasse' => $coach->getMotDePasse(),
':dateNaissance' => $coach->getDateNaissance(),
':athleteId' => $coach->getAthleteId(),
];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function updateCoach(CoachEntity $oldCoach, CoachEntity $newCoach) {
public function updateCoach(CoachEntity $oldCoach, CoachEntity $newCoach): array
{
$query = "UPDATE Coach
SET nom = :nom, prenom = :prenom, email = :email, sexe = :sexe,
taille = :taille, poids = :poids, motDePasse = :motDePasse, dateNaissance = :dateNaissance
SET athleteId = :athleteId
WHERE idCoach = :idCoach";
$params = [
':idCoach' => $oldCoach->getIdCoach(),
':nom' => $newCoach->getNom(),
':prenom' => $newCoach->getPrenom(),
':email' => $newCoach->getEmail(),
':sexe' => $newCoach->getSexe(),
':taille' => $newCoach->getTaille(),
':poids' => $newCoach->getPoids(),
':motDePasse' => $newCoach->getMotDePasse(),
':dateNaissance' => $newCoach->getDateNaissance(),
':athleteId' => $newCoach->getAthleteId(),
];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function deleteCoach(int $idCoach) {
public function deleteCoach(int $idCoach): array
{
$query = "DELETE FROM Coach WHERE idCoach = :idCoach";
$params = [

@ -1,41 +1,85 @@
<?php
namespace Database;
use Model\CoachAthlete;
use Model\User;
use \PDO;
use \DateTime;
use Model\Role;
use Model\Coach;
use Shared\Log;
class CoachMapper {
public function map(array $data) {
public function coachSqlToEntity(array $data): array {
$coachEntities = [];
foreach ($data as $coachData) {
$coach = new CoachEntity();
$coach->setIdCoach($data['idCoach']);
$coach->setNom($data['nom']);
$coach->setPrenom($data['prenom']);
$coach->setEmail($data['email']);
$coach->setSexe($data['sexe']);
$coach->setTaille($data['taille']);
$coach->setPoids($data['poids']);
$coach->setMotDePasse($data['motDePasse']);
$coach->setDateNaissance($data['dateNaissance']);
return $coach;
if (isset($coachData['idAthlete'])) {
$coach->setIdCoach($coachData['idAthlete']);
}
if (isset($coachData['nom'])) {
$coach->setNom($coachData['nom']);
}
if (isset($coachData['prenom'])) {
$coach->setPrenom($coachData['prenom']);
}
if (isset($coachData['username'])) {
$coach->setUsername($coachData['username']);
}
if (isset($coachData['email'])) {
$coach->setEmail($coachData['email']);
}
if (isset($coachData['sexe'])) {
$coach->setSexe($coachData['sexe']);
}
if (isset($coachData['taille'])) {
$coach->setTaille($coachData['taille']);
}
if (isset($coachData['poids'])) {
$coach->setPoids($coachData['poids']);
}
if (isset($coachData['motDePasse'])) {
$coach->setMotDePasse($coachData['motDePasse']);
}
if (isset($coachData['dateNaissance'])) {
$coach->setDateNaissance($coachData['dateNaissance']);
}
if (isset($coachData['isCoach'])) {
$coach->setIsCoach($coachData['isCoach']);
}
$coachEntities[] = $coach;
}
return $coachEntities;
}
public function CoachEntityToModel(CoachEntity $coachEntity):User{
$role = "Coach";
$role = new CoachAthlete();
$date = new DateTime($coachEntity->getDateNaissance());
$user = new User(
$coachEntity->getIdCoach(),
$coachEntity->getNom(),
$coachEntity->getPrenom(),
$coachEntity->getUsername(),
$coachEntity->getEmail(),
$coachEntity->getMotDePasse(),
$coachEntity->getSexe(),
$coachEntity->getTaille(),
$coachEntity->getPoids(),
$coachEntity->getDateNaissance(),
$date,
$role
);
@ -46,17 +90,10 @@ class CoachMapper {
$coach = new CoachEntity();
$coach->setIdCoach($user->getId());
$coach->setNom($user->getNom());
$coach->setPrenom($user->getPrenom());
$coach->setEmail($user->getEmail());
$coach->setSexe($user->getSexe());
$coach->setTaille($user->getTaille());
$coach->setPoids($user->getPoids());
$coach->setMotDePasse($user->getMotDePasse());
$coach->setDateNaissance($user->getDateNaissance());
$coach->setAthleteId($user->getId());
return $coach;
}
}
?>

@ -2,6 +2,9 @@
namespace Database;
use DateTime;
use Shared\Log;
class Connexion extends \PDO {
private $stmt;
@ -15,13 +18,11 @@ class Connexion extends \PDO {
}
}
public function executeQuery(string $query, array $parameters = []): bool {
public function executeQuery(string $query, array $parameters = []) {
$this->stmt = $this->prepare($query);
//foreach ($parameters as $name => $value) {
// $this->stmt->bindValue($name, $value[0], $value[1]);
//}
foreach ($parameters as $name => $value) {
$bindValueResult = $this->stmt->bindValue($name, $value, \PDO::PARAM_STR);
$dataType = is_numeric($value) ? \PDO::PARAM_INT : \PDO::PARAM_STR;
$bindValueResult = $this->stmt->bindValue($name, $value, $dataType);
if (!$bindValueResult) {
// Gérez l'erreur, par exemple, en lançant une exception.
throw new \PDOException('Failed to bind value for parameter ' . $name);

@ -0,0 +1,71 @@
<?php
namespace Database;
class EntrainementEntity
{
private $idEntrainement;
private $date;
private $description;
private $latitude;
private $longitude;
private $feedback;
private $coachId;
public function getIdEntrainement()
{
return $this->idEntrainement;
}
public function getDate()
{
return $this->date;
}
public function getDescription()
{
return $this->description;
}
public function getLatitude()
{
return $this->latitude;
}
public function getLongitude()
{
return $this->longitude;
}
public function getFeedback()
{
return $this->feedback;
}
public function getCoachId()
{
return $this->coachId;
}
public function setIdEntrainement($idEntrainement)
{
$this->idEntrainement = $idEntrainement;
}
public function setDate($date)
{
$this->date = $date;
}
public function setDescription($description)
{
$this->description = $description;
}
public function setLatitude($latitude)
{
$this->latitude = $latitude;
}
public function setLongitude($longitude)
{
$this->longitude = $longitude;
}
public function setFeedback($feedback)
{
$this->feedback = $feedback;
}
public function setCoachId($coachId)
{
$this->coachId = $coachId;
}
}

@ -0,0 +1,21 @@
<?php
namespace Database;
use Shared\Log;
class EntrainementGateway
{
private Connexion $connection;
public function __construct(Connexion $connection) {
$this->connection = $connection;
}
public function getEntrainements(): array
{
$query = "SELECT * FROM Entrainement";
$res = $this->connection->executeWithErrorHandling($query);
return $res;
}
}

@ -0,0 +1,82 @@
<?php
namespace Database;
use DateTime;
use Model\Athlete;
use Model\Training;
use Model\User;
use Shared\Log;
class EntrainementMapper
{
public function entrainementSqlToEntity(array $data): array {
$entrainementEntities = [];
foreach ($data as $entrainementData) {
$entrainement = new EntrainementEntity();
if (isset($entrainementData['identrainement'])) {
$entrainement->setIdEntrainement($entrainementData['identrainement']);
}
if (isset($entrainementData['date'])) {
$entrainement->setDate($entrainementData['date']);
}
if (isset($entrainementData['description'])) {
$entrainement->setDescription($entrainementData['description']);
}
if (isset($entrainementData['latitude'])) {
$entrainement->setLatitude($entrainementData['latitude']);
}
if (isset($entrainementData['longitude'])) {
$entrainement->setLongitude($entrainementData['longitude']);
}
if (isset($entrainementData['feedback'])) {
$entrainement->setFeedback($entrainementData['feedback']);
}
if (isset($entrainementData['athleteid'])) {
$entrainement->setCoachId($entrainementData['athleteid']);
}
$entrainementEntities[] = $entrainement;
}
return $entrainementEntities;
}
public function entrainementEntityToModel(EntrainementEntity $entrainementEntity): Training {
$date = new DateTime($entrainementEntity->getDate());
$idTraining = intval($entrainementEntity->getIdEntrainement());
$latitude = floatval($entrainementEntity->getLatitude());
$longitude = floatval($entrainementEntity->getLongitude());
return new Training(
$idTraining,
$date,
$latitude,
$longitude,
$entrainementEntity->getDescription(),
$entrainementEntity->getFeedback()
);
}
public function entrainementToEntity(Training $training):EntrainementEntity{
$train = new EntrainementEntity();
$train->setIdEntrainement($training->getId());
$train->setDate($training->getDate());
$train->setDescription($training->getDescription());
$train->setLatitude($training->getLatitude());
$train->setLongitude($training->getLongitude());
$train->setFeedback($training->getFeedback());
$train->setCoachId(1);
return $train;
}
}

@ -0,0 +1,64 @@
<?php
namespace Database;
use Shared\Log;
class NotificationEntity
{
private $idNotif;
private $message;
private $date;
private $statut;
private $urgence;
private $idAthlete;
public function getIdNotif(): int
{
return $this->idNotif;
}
public function getMessage()
{
return $this->message;
}
public function getDate()
{
return $this->date;
}
public function getStatut()
{
return $this->statut;
}
public function getUrgence()
{
return $this->urgence;
}
public function getIdAthlete()
{
return $this->idAthlete;
}
public function setIdNotif($idNotif)
{
$this->idNotif = $idNotif;
}
public function setMessage($message)
{
$this->message = $message;
}
public function setDate($date)
{
$this->date = $date;
}
public function setStatut($statut)
{
$this->statut = $statut;
}
public function setUrgence($urgence)
{
$this->urgence = $urgence;
}
public function setIdAthlete($idAthlete)
{
$this->idAthlete = $idAthlete;
}
}

@ -0,0 +1,27 @@
<?php
namespace Database;
use Shared\Log;
class NotificationGateway
{
private Connexion $connection;
public function __construct(Connexion $connection) {
$this->connection = $connection;
}
public function getNotifications(): array
{
$query = "SELECT * FROM Notification";
$res = $this->connection->executeWithErrorHandling($query);
return $res;
}
public function addNotification(NotificationEntity $notif){
$query = "INSERT INTO Notification (message, date, statut, urgence, athleteid) VALUES (:message, :date, :statut, :urgence, :idAthlete)";
$params = [':message'=>$notif->getMessage(), ':date'=>$notif->getDate(), ':statut'=>$notif->getStatut(), ':urgence'=>$notif->getUrgence(), ':idAthlete'=>$notif->getIdAthlete()];
return $this->connection->executeWithErrorHandling($query, $params);
}
}

@ -0,0 +1,74 @@
<?php
namespace Database;
use DateTime;
use Model\Notification;
use Model\Training;
use Shared\Log;
class NotificationMapper
{
public function notificationSqlToEntity(array $data): array
{
$notificationEntities = [];
foreach ($data as $notificationData) {
$notification = new NotificationEntity();
if (isset($notificationData['idnotif'])) {
$notification->setIdNotif($notificationData['idnotif']);
}
if (isset($notificationData['message'])) {
$notification->setMessage($notificationData['message']);
}
if (isset($notificationData['date'])) {
$notification->setDate($notificationData['date']);
}
if (isset($notificationData['statut'])) {
$notification->setStatut($notificationData['statut']);
}
if (isset($notificationData['urgence'])) {
$notification->setUrgence($notificationData['urgence']);
}
if (isset($notificationData['athleteid'])) {
$notification->setIdAthlete($notificationData['athleteid']);
}
$notificationEntities[] = $notification;
}
return $notificationEntities;
}
public function notificationEntityToModel(NotificationEntity $notificationEntity): Notification
{
$date = new DateTime($notificationEntity->getDate());
return new Notification(
$notificationEntity->getIdNotif(),
$notificationEntity->getMessage(),
$date,
$notificationEntity->getStatut(),
$notificationEntity->getUrgence(),
$notificationEntity->getIdAthlete()
);
}
public function notificationToEntity(Notification $notification): NotificationEntity
{
$notif = new NotificationEntity();
$notif->setIdNotif($notification->getId());
$notif->setMessage($notification->getMessage());
$notif->setDate($notification->getDate()->format('Y-m-d H:i:s'));
$notif->setStatut($notification->getStatut());
$notif->setUrgence($notification->getUrgence());
$notif->setIdAthlete($notification->getToUserId());
return $notif;
}
}

@ -0,0 +1,97 @@
<?php
namespace Database;
class UserGateway
{
private Connexion $connection;
public function __construct(Connexion $connection) {
$this->connection = $connection;
}
public function getUsers(): array
{
$query = "SELECT * FROM Athlete";
$res = $this->connection->executeWithErrorHandling($query);
return $res;
}
public function getUserById(int $userId): array
{
$query = "SELECT * FROM Athlete WHERE idAthlete = :id";
$params = [':id' => $userId];
$res = $this->connection->executeWithErrorHandling($query, $params);
return $res;
}
public function getUserByName(string $name): array
{
$query = "SELECT * FROM Athlete WHERE nom = :name";
$params = [':name' => $name];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getUserByFirstName(string $firstName): array
{
$query = "SELECT * FROM Athlete WHERE prenom = :firstName";
$params = [':firstName' => $firstName];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getUserByEmail(string $email): array
{
$query = "SELECT * FROM Athlete WHERE email = :email";
$params = [':email' => $email];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getUserByGender(string $gender): array
{
$query = "SELECT * FROM Athlete WHERE sexe = :gender";
$params = [':gender' => $gender];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getUserByHeight(int $height): array
{
$query = "SELECT * FROM Athlete WHERE taille = :height";
$params = [':height' => [$height, PDO::PARAM_INT]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getUserByWeight(int $weight): array
{
$query = "SELECT * FROM Athlete WHERE poids = :weight";
$params = [':weight' => [$weight, PDO::PARAM_INT]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getUserByBirthDate(string $birthdate): array
{
$query = "SELECT * FROM Athlete WHERE dateNaissance = :birthdate";
$params = [':birthdate' => [$birthdate, PDO::PARAM_STR]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function deleteUserById(int $idAthlete): array
{
$query = "DELETE FROM Athlete WHERE idAthlete = :idAthlete";
$params = [
':idAthlete' => $idAthlete,
];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function deleteUserByEmail(string $email): array
{
$query = "DELETE FROM Athlete WHERE email = :email";
$params = [
':email' => $email,
];
return $this->connection->executeWithErrorHandling($query, $params);
}
}

@ -0,0 +1,6 @@
INSERT INTO Athlete (username, nom, prenom, email, sexe, taille, poids, motDePasse, dateNaissance, isCoach) VALUES
('johnD63', 'Doe', 'John', 'john.doe@example.com', 'M', 1.80, 75, '$2y$10$U59ioMTGZBM2FGQv.3lcbuL0IkO4Fx1jQU7f5hF7o/hvCX2t46mby', '1985-05-15', TRUE),
('janeS03', 'Smith', 'Jane', 'jane.smith@example.com', 'F', 1.65, 60, '$2y$10$U59ioMTGZBM2FGQv.3lcbuL0IkO4Fx1jQU7f5hF7o/hvCX2t46mby', '1990-03-10', FALSE),
('bryanO', 'Martin', 'Paul', 'paul.martin@example.com', 'M', 1.75, 68, '$2y$10$U59ioMTGZBM2FGQv.3lcbuL0IkO4Fx1jQU7f5hF7o/hvCX2t46mby', '1988-08-20', TRUE),
('dominicT', 'Brown', 'Anna', 'anna.brown@example.com', 'F', 1.70, 58, '$2y$10$U59ioMTGZBM2FGQv.3lcbuL0IkO4Fx1jQU7f5hF7o/hvCX2t46mby', '1992-11-25', FALSE),
('miaT', 'Lee', 'Bruce', 'bruce.lee@example.com', 'M', 1.72, 70, '$2y$10$U59ioMTGZBM2FGQv.3lcbuL0IkO4Fx1jQU7f5hF7o/hvCX2t46mby', '1970-02-05', FALSE);

@ -0,0 +1,22 @@
INSERT INTO FrequenceCardiaque
VALUES
(1, 100, '08:15:00', 15, 130, 45.75771709151474, 3.113484980409329, 1),
(2, ROUND(RAND() * 10 + 90), '08:16:00', ROUND(RAND() * 5 + 10), ROUND(RAND() * 20 + 110), 45.75772709151474, 3.113494980409329, 1),
(3, ROUND(RAND() * 10 + 90), '08:17:00', ROUND(RAND() * 5 + 10), ROUND(RAND() * 20 + 110), 45.75773709151474, 3.113504980409329, 1),
(4, ROUND(RAND() * 10 + 90), '08:18:00', ROUND(RAND() * 5 + 10), ROUND(RAND() * 20 + 110), 45.75774709151474, 3.113514980409329, 1),
(5, ROUND(RAND() * 10 + 90), '08:19:00', ROUND(RAND() * 5 + 10), ROUND(RAND() * 20 + 110), 45.75775709151474, 3.113524980409329, 1),
(6, ROUND(RAND() * 10 + 90), '08:20:00', ROUND(RAND() * 5 + 10), ROUND(RAND() * 20 + 110), 45.75776709151474, 3.113534980409329, 1),
(7, ROUND(RAND() * 10 + 90), '08:21:00', ROUND(RAND() * 5 + 10), ROUND(RAND() * 20 + 110), 45.75777709151474, 3.113544980409329, 1),
(8, ROUND(RAND() * 10 + 90), '08:22:00', ROUND(RAND() * 5 + 10), ROUND(RAND() * 20 + 110), 45.75778709151474, 3.113554980409329, 1),
(9, ROUND(RAND() * 10 + 90), '08:23:00', ROUND(RAND() * 5 + 10), ROUND(RAND() * 20 + 110), 45.75779709151474, 3.113564980409329, 1),
(10, ROUND(RAND() * 10 + 90), '08:24:00', ROUND(RAND() * 5 + 10), ROUND(RAND() * 20 + 110), 45.75780709151474, 3.113574980409329, 1),
(11, ROUND(RAND() * 10 + 90), '08:25:00', ROUND(RAND() * 5 + 10), ROUND(RAND() * 20 + 110), 45.75781709151474, 3.113584980409329, 1),
(12, ROUND(RAND() * 10 + 90), '08:26:00', ROUND(RAND() * 5 + 10), ROUND(RAND() * 20 + 110), 45.75782709151474, 3.113594980409329, 1),
(13, ROUND(RAND() * 10 + 90), '08:27:00', ROUND(RAND() * 5 + 10), ROUND(RAND() * 20 + 110), 45.75783709151474, 3.113604980409329, 1),
(14, ROUND(RAND() * 10 + 90), '08:28:00', ROUND(RAND() * 5 + 10), ROUND(RAND() * 20 + 110), 45.75784709151474, 3.113614980409329, 1),
(15, ROUND(RAND() * 10 + 90), '08:29:00', ROUND(RAND() * 5 + 10), ROUND(RAND() * 20 + 110), 45.75785709151474, 3.113624980409329, 1),
(16, ROUND(RAND() * 10 + 90), '08:30:00', ROUND(RAND() * 5 + 10), ROUND(RAND() * 20 + 110), 45.75786709151474, 3.113634980409329, 1),
(17, ROUND(RAND() * 10 + 90), '08:31:00', ROUND(RAND() * 5 + 10), ROUND(RAND() * 20 + 110), 45.75787709151474, 3.113644980409329, 1),
(18, ROUND(RAND() * 10 + 90), '08:32:00', ROUND(RAND() * 5 + 10), ROUND(RAND() * 20 + 110), 45.75788709151474, 3.113654980409329, 1),
(19, ROUND(RAND() * 10 + 90), '08:33:00', ROUND(RAND() * 5 + 10), ROUND(RAND() * 20 + 110), 45.75789709151474, 3.113664980409329, 1),
(20, ROUND(RAND() * 10 + 90), '08:34:00', ROUND(RAND() * 5 + 10), ROUND(RAND() * 20 + 110), 45.75790709151474, 3.113674980409329, 1);

@ -0,0 +1,26 @@
INSERT INTO Friendship (idAthlete1, idAthlete2, debut) VALUES
(3, 4, '2023-01-01'),
(3, 5, '2023-01-12');
INSERT INTO Notification (idNotif, message, date, statut, urgence, athleteId) VALUES
(1, 'Training session at 10 AM', '2023-03-10', TRUE, 1, 1),
(2, 'Training session at 3 PM', '2023-05-10', TRUE, 1, 2);
INSERT INTO Statistique (idStatistique, poids, fcMoyenne, fcMax, caloriesBruleesMoy, date, athleteId) VALUES
(1, 70, 80, 150, 500, '2023-03-10', 1),
(2, 86, 95, 170, 896, '2023-04-13', 3);
INSERT INTO Entrainement (idEntrainement, date, description, latitude, longitude, feedback, athleteId) VALUES
(1, '2023-03-10', 'Long run in the park', 40.7128, -74.0060, 'Good effort', 1),
(2, '2023-04-13', 'Long run in the forest', 44.7128, -70.0060, 'Pretty good effort', 3);
INSERT INTO Participe (athleteId, entrainementId) VALUES
(1, 1),
(3, 2);
INSERT INTO SourceDonnee (idSource, type, modele, precision2, athleteId) VALUES
(1, 'Heart Rate Monitor', 'HRM-Pro', 98.5, 1);
INSERT INTO Activite (idActivite, type, date, heureDeDebut, heureDeFin, effortRessent, variabilite, variance, ecartType, moyenne, maximum, minimum, temperatureMoyenne, athleteId, sourceId) VALUES
(1, 'Running', '2023-03-10', '08:00:00', '09:00:00', 3, 0.5, 1, 0.1, 140, 160, 120, 20, 1, 1),
(2, 'Running Forest', '2023-04-13', '10:00:00', '12:00:00', 5, 0.5, 1, 0.1, 140, 160, 120, 20, 1, 1);

@ -0,0 +1,107 @@
DROP TABLE IF EXISTS Athlete, Friendship, Notification, Statistique, Entrainement, Participe, SourceDonnee, Activite, FrequenceCardiaque CASCADE;
CREATE TABLE Athlete (
idAthlete INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(255),
nom VARCHAR(255),
prenom VARCHAR(255),
email VARCHAR(255) UNIQUE,
sexe CHAR(1),
taille DECIMAL,
poids DECIMAL,
motDePasse VARCHAR(255),
dateNaissance DATE,
isCoach BOOLEAN
);
CREATE TABLE Friendship (
idAthlete1 INT,
idAthlete2 INT,
debut DATE,
PRIMARY KEY (idAthlete1, idAthlete2),
FOREIGN KEY (idAthlete1) REFERENCES Athlete(idAthlete),
FOREIGN KEY (idAthlete2) REFERENCES Athlete(idAthlete)
);
CREATE TABLE Notification (
idNotif INT AUTO_INCREMENT PRIMARY KEY,
message TEXT,
date DATE,
statut BOOLEAN,
urgence INT,
athleteId INT,
FOREIGN KEY (athleteId) REFERENCES Athlete(idAthlete)
);
CREATE TABLE Statistique (
idStatistique INT AUTO_INCREMENT PRIMARY KEY,
poids DECIMAL,
fcMoyenne DECIMAL,
fcMax DECIMAL,
caloriesBruleesMoy DECIMAL,
date DATE,
athleteId INT,
FOREIGN KEY (athleteId) REFERENCES Athlete(idAthlete)
);
CREATE TABLE Entrainement (
idEntrainement INT AUTO_INCREMENT PRIMARY KEY,
date DATE,
description TEXT,
latitude DECIMAL,
longitude DECIMAL,
feedback TEXT,
athleteId INT,
FOREIGN KEY (athleteId) REFERENCES Athlete(idAthlete)
);
CREATE TABLE Participe (
athleteId INT,
entrainementId INT,
PRIMARY KEY (athleteId, entrainementId),
FOREIGN KEY (athleteId) REFERENCES Athlete(idAthlete),
FOREIGN KEY (entrainementId) REFERENCES Entrainement(idEntrainement)
);
CREATE TABLE SourceDonnee (
idSource INT AUTO_INCREMENT PRIMARY KEY,
type VARCHAR(255),
modele VARCHAR(255),
precision DECIMAL,
athleteId INT,
FOREIGN KEY (athleteId) REFERENCES Athlete(idAthlete)
);
CREATE TABLE Activite (
idActivite INT AUTO_INCREMENT PRIMARY KEY,
type VARCHAR(255),
date DATE,
heureDeDebut TIME,
heureDeFin TIME,
effortRessent DECIMAL,
variabilite DECIMAL,
variance DECIMAL,
ecartType DECIMAL,
moyenne DECIMAL,
maximum DECIMAL,
minimum DECIMAL,
temperatureMoyenne DECIMAL,
athleteId INT,
sourceId INT,
FOREIGN KEY (athleteId) REFERENCES Athlete(idAthlete),
FOREIGN KEY (sourceId) REFERENCES SourceDonnee(idSource)
);
CREATE TABLE FrequenceCardiaque (
idFc INT AUTO_INCREMENT PRIMARY KEY,
altitude DECIMAL,
temps TIME,
temperature DECIMAL,
bpm INT,
longitude DECIMAL,
latitude DECIMAL,
activiteId INT,
FOREIGN KEY (activiteId) REFERENCES Activite(idActivite)
);
-- \i athlete.sql
-- \i friendship.sql

@ -0,0 +1,129 @@
<?php
namespace Network;
use App\Router\Session;
use Database\AthleteGateway;
use Database\AthleteMapper;
use Database\CoachMapper;
use Database\Connexion;
use Database\UserGateway;
use Model\User;
use Model\Athlete;
use Model\CoachAthlete;
use Repository\IUserRepository;
use Shared\IHashPassword;
use Shared\Log;
const USER = 'USER';
class AuthService implements IAuthService
{
private IUserRepository $userRepository;
private IHashPassword $passwordHacher;
private ?User $currentUser = null;
public function __construct(IUserRepository $userRepository, IHashPassword $passwordHacher)
{
$this->userRepository = $userRepository;
$this->passwordHacher = $passwordHacher;
}
public function login(string $email, string $password): bool
{
// $user = $this->userRepository->getItemByEmail($email);
$userGateway = new UserGateway(new Connexion(DSN, DB_USER, DB_PASSWORD));
$userRepository = $userGateway->getUserByEmail($email);
// Log::dd($userRepository[0]['isCoach']);
if($userRepository[0]['isCoach']) {
$map = new CoachMapper();
$coachEntity = $map->coachSqlToEntity($userRepository);
// $user = [];
foreach($coachEntity as $coachs) {
$user = $map->CoachEntityToModel($coachs);
}
} else {
$map = new AthleteMapper();
$athleteEntity = $map->athleteSqlToEntity($userRepository);
foreach($athleteEntity as $coachs) {
$user = $map->AthleteEntityToModel($coachs);
}
}
// Log::dd($user);
// $map->athleteEntityToModel($userRepository)
// $user = ['username' => $userEntity[0]->getUsername(), 'nom' => $userEntity[0]->getNom(),
// 'prenom' => $userEntity[0]->getPrenom(),'email' => $userEntity[0]->getEmail(), 'sexe' => $userEntity[0]->getSexe(),
// 'taille' => $userEntity[0]->getTaille(), 'poids' => $userEntity[0]->getPoids(), 'motdepasse' => $userEntity[0]->getMotDePasse(),
// 'datenaissance' => $userEntity[0]->getDateNaissance(), 'iscoach' => $userEntity[0]->getIsCoach(), 'img' => 'test'];
// Log::dd($this->passwordHacher->isPasswordValid($user->getMotDePasse(),$password));
if ($user === null || !$this->passwordHacher->isPasswordValid($user->getMotDePasse(),$password)) {
return false;
}
$this->currentUser = $user;
// Log::dd(Session::getInstance()->__get(USER));
Session::getInstance()->__set(USER, $this->currentUser->getId());
// Log::dd(Session::getInstance()->__set(USER, $this->currentUser->getId()));
return true;
}
public function register(string $email, string $password, $data): bool
{
if ($this->userRepository->getItemByEmail($email)) {
throw new \Exception('User already exists');
}
$hashedPassword = $this->passwordHacher->hashPassword($password);
$prenom = $data['prenom'];
$username = $data['username'];
$nom = $data['nom'];
$sexe = $data['sexe'];
$taille = $data['taille'];
$poids = $data['poids'];
$dateNaissance = $data['dateNaissance'];
$roleName = $data['roleName'];
$role = null;
if ($roleName == "Coach") {
$role = new CoachAthlete();
} else if ($roleName == "Athlete") {
$role = new Athlete();
}
$user = new User(
$nom,
$prenom,
$username,
$email,
$hashedPassword,
$sexe,
$taille,
$poids,
$dateNaissance,
$role
);
$this->userRepository->addItem($user);
$this->currentUser = $user;
Session::getInstance()->__set(USER,$this->currentUser->getId());
return true;
}
public function logoutUser(): bool
{
$this->currentUser = null;
Session::getInstance()->destroy();
return true;
}
public function getCurrentUser(): ?User
{
if (!empty(Session::getInstance()->__get(USER)) && $this->currentUser === null) {
$this->currentUser = $this->userRepository->getItemById(Session::getInstance()->__get(USER));
}
return $this->currentUser;
}
}

@ -33,18 +33,18 @@ interface IAuthService {
/**
* Register a new user.
*
* @param string $username The username of the new user.
* @param string $emailUser The emailUser of the new user.
* @param string $password The password of the new user.
* @param $data other data {undefined} for the moment.
*
* @return bool True if registration is successful, false otherwise.
*/
public function register(string $username, string $password, $data): bool;
public function register(string $emailUser, string $password, $data): bool;
/**
* Logout the currently authenticated user.
*
* @return void
* @return bool
*/
public function logoutUser(): bool;

@ -27,7 +27,7 @@ class Activity
private float $variability;
private float $variance;
private float $standardDeviation;
private int $average;
private float $average;
private int $maximum;
private int $minimum;
private float $avrTemperature;

@ -2,8 +2,46 @@
namespace Model;
use DateTime;
class Notification
{
private static $lastId = 0;
private int $idNotif;
private string $message;
private \DateTime $date;
private bool $statut;
private string $urgence;
private int $toUserId;
/**
* @param string $type
* @param string $message
*/
public function __construct(
string $message,
DateTime $date,
string $statut,
string $urgence,
int $toUserId
)
{
$this->idNotif = self::generateId();
$this->message = $message;
$this->date = $date;
$this->statut = $statut;
$this->urgence = $urgence;
$this->toUserId =$toUserId;
}
private static function generateId(): int
{
self::$lastId++;
return self::$lastId;
}
public function getId(){ return $this->idNotif;}
public function getDate(){ return $this->date;}
public function getStatut(){ return $this->statut;}
public function getUrgence(){ return $this->urgence;}
/**
* @return string
*/
@ -36,10 +74,6 @@ class Notification
$this->message = $message;
}
private string $type;
private string $message;
private int $toUserId;
/**
* @return int
*/
@ -55,16 +89,6 @@ class Notification
{
$this->toUserId = $toUserId;
}
/**
* @param string $type
* @param string $message
*/
public function __construct(int $toUserId,string $type, string $message)
{
$this->type = $type;
$this->toUserId =$toUserId;
$this->message = $message;
}
public function __toString(): string
{
return var_export($this, true);

@ -18,7 +18,6 @@ use Stub\TrainingRepository;
* @brief Classe abstraite représentant le rôle d'un utilisateur.
*/
abstract class Role {
protected int $id;
protected array $usersList = [];
protected array $usersRequests = [];
protected array $trainingList = [];

@ -4,6 +4,7 @@ namespace Model;
class Training
{
private static $lastId = 0;
private int $idTraining;
private \DateTime $date;
private float $latitude;
@ -12,20 +13,24 @@ class Training
private ?String $feedback;
public function __construct(
int $idTraining,
\DateTime $date,
float $latitude,
float $longitude,
?String $description = null,
?String $feedback = null
) {
$this->idTraining = $idTraining;
$this->idTraining = self::generateId();
$this->date = $date;
$this->latitude = $latitude;
$this->longitude = $longitude;
$this->description = $description;
$this->feedback = $feedback;
}
private static function generateId(): int
{
self::$lastId++;
return self::$lastId;
}
public function getId():int {
return $this->idTraining;
}
@ -33,7 +38,13 @@ class Training
return $this->date;
}
public function getLocation(): String {
return $this->longitude . $this->latitude;
return $this->longitude . ", " . $this->latitude;
}
public function getLatitude(): float {
return $this->latitude;
}
public function getLongitude(): float {
return $this->longitude;
}
public function getDescription(): String
{

@ -16,6 +16,7 @@ namespace Model;
* @brief Classe représentant un utilisateur.
*/
class User {
private static $lastId = 0;
private int $id;
private String $username;
private string $nom;
@ -28,14 +29,7 @@ class User {
private \DateTime $dateNaissance;
private Role $role;
protected array $notifications = [];
/**
* @return array
*/
public function getNotifications(): array
{
return $this->notifications;
}
private array $listFriend = [];
/**
* @param int $id
@ -50,9 +44,11 @@ class User {
* @param \DateTime $dateNaissance
* @param \Model\Role $role
*/
public function __construct(int $id, string $nom, string $prenom, string $username, string $email, string $motDePasse, string $sexe, float $taille, float $poids, \DateTime $dateNaissance, Role $role)
public function __construct(string $nom, string $prenom, string $username, string $email,
string $motDePasse, string $sexe, float $taille, float $poids, \DateTime $dateNaissance,
Role $role)
{
$this->id = $id;
$this->id = self::generateId();
$this->nom = $nom;
$this->prenom = $prenom;
$this->username = $username;
@ -64,6 +60,18 @@ class User {
$this->dateNaissance = $dateNaissance;
$this->role = $role;
}
private static function generateId(): int
{
self::$lastId++;
return self::$lastId;
}
/**
* @return array
*/
public function getNotifications(): array
{
return $this->notifications;
}
public function addNotification($notification): void {
$this->notifications[] = $notification;
@ -289,5 +297,23 @@ class User {
public function __toString() {
return "Athlete [ID: {$this->id}, Username : $this->username, Nom: {$this->nom}, Prénom: {$this->prenom}, Email: {$this->email}]";
}
/**
* Donne la liste des amis de l'utilisateur
*
* @return string Les amis de l'utilisateur.
*/
public function getListFriend(): array {
return $this->listFriend;
}
/**
* Ajoute un utilisateur a sa liste d'amis.
*
* @param User L'utilisateur a ajouter.
*/
public function addFriend(User $user){
array_push($this->listFriend, $user);
}
}
?>

@ -8,12 +8,22 @@
*
* @package manager
*/
namespace Manager;
use adriangibbons\phpFITFileAnalysis;
use Database\ActivityGateway;
use Database\ActivityMapper;
use Database\Connexion;
use Database\NotificationGateway;
use Database\NotificationMapper;
use DateTime;
use Exception;
use Model\Activity;
use Model\Athlete;
use Model\Notification;
use Network\IAuthService;
use Shared\Log;
use Stub\AuthService;
/**
@ -27,14 +37,21 @@ class ActivityManager
*/
private IAuthService $authService;
/**
* @var DataManager
*/
private DataManager $dataManager;
/**
* Constructeur de la classe ActivityManager.
*
* @param IAuthService $authService Le service d'authentification utilisé pour vérifier l'utilisateur actuel.
*/
public function __construct(DataManager $dataManager,IAuthService $authService)
public function __construct(DataManager $dataManager, IAuthService $authService)
{
$this->authService = $authService;
$this->dataManager = $dataManager;
}
/**
@ -63,9 +80,8 @@ class ActivityManager
// Conversion des données en format JSON
$jsonFitData = json_encode($fitData, JSON_PRETTY_PRINT);
// Enregistrement du fichier JSON
file_put_contents('/Users/Perederii/SAE/git/Web/Sources/src/data/model/fitFileSaver/jsonFiles/ActivitySave.json', $jsonFitData);
file_put_contents('./you.json', $jsonFitData);
return true;
} catch (\Exception $e) {
@ -85,12 +101,13 @@ class ActivityManager
* @return bool Retourne true en cas de succès, sinon false.
* @throws Exception En cas d'erreur lors du téléchargement, du traitement ou de l'enregistrement des données.
*/
public function uploadFile($type, $effortRessenti, $file_path_or_data, ?array $options = null): bool
public function uploadFile(string $type, int $effortRessenti, string $file_path_or_data, ?array $options = null): bool
{
try {
// Vérification des options par défaut
if (empty($options)) {
$options = [
'input_is_data' => true,
'fix_data' => ['all'],
'data_every_second' => false,
'units' => 'metric',
@ -99,7 +116,6 @@ class ActivityManager
'overwrite_with_dev_data' => false
];
}
// Ouverture du fichier FIT
if (!($monFichierFit = new phpFITFileAnalysis($file_path_or_data, $options))) {
throw new Exception("Problème lors de l'ouverture du fichier FIT");
@ -110,17 +126,25 @@ class ActivityManager
$lastTimestamp = end($monFichierFit->data_mesgs['record']['timestamp']);
// Conversion des timestamps en objets DateTime
$startDate = \DateTime::createFromFormat('Y-m-d', date('Y-m-d', $firstTimestamp));
$startTime = \DateTime::createFromFormat('H:i:s', date('H:i:s', $firstTimestamp));
$endTime = ($lastTimestamp) ? \DateTime::createFromFormat('H:i:s', date('H:i:s', $lastTimestamp)) : null;
$startDate = new DateTime();
// $startDate = $startDate->format('Y-m-d');
$startTime = new DateTime();//\DateTime::createFromFormat('H:i:s', date('H:i:s', $firstTimestamp));
// $startTime = $startTime->format('H:i:s');
$endTime = ($lastTimestamp) ? new DateTime() : null;
// if(!empty($endTime)) {
// $endTime = $endTime->format('H:i:s');
// }
// Vérification des conversions en DateTime
if (!$startDate || !$startTime || ($lastTimestamp && !$endTime)) {
throw new \Exception("La conversion en DateTime a échoué.");
return false;
}
// Extraction des autres données nécessaires
$heartRateList = $monFichierFit->data_mesgs['record']['heart_rate'];
if(!($heartRateList = $monFichierFit->data_mesgs['record']['heart_rate'])) {
throw new \InvalidArgumentException("Fichier .fit ne comportant pas de fréquences cardiaques.\n Fichier Invalide !");
}
$variability = max($heartRateList) - min($heartRateList);
$average = number_format(array_sum($heartRateList) / count($heartRateList), 2);
$varianceV = array_sum(array_map(fn($x) => pow($x - $average, 2), $heartRateList)) / count($heartRateList);
@ -129,13 +153,24 @@ class ActivityManager
$maximum = max($heartRateList);
$minimum = min($heartRateList);
if(!empty($monFichierFit->data_mesgs['record']['temperature']) && isset($monFichierFit->data_mesgs['record']['temperature'])){
// Extraction de la température moyenne (si disponible
$temperatureList = $monFichierFit->data_mesgs['record']['temperature'];
$averageTemperature = (!empty($temperatureList)) ? number_format(array_sum($temperatureList) / count($temperatureList), 1) : -200;
}
else{
$averageTemperature = -200;
}
if($monFichierFit->data_mesgs['record']['speed']) {
$isPaused = count($monFichierFit->isPaused()) > 0;
} else {
$isPaused = false;
}
// Création de l'objet Activity
$newActivity = new Activity(
15,
$type,
$startDate,
$startTime,
@ -150,16 +185,30 @@ class ActivityManager
$averageTemperature,
$isPaused
);
// $this->dataManager->activityRepository->add($newActivity);
// if ($this->saveFitFileToJSON($monFichierFit)) {
// Ajout de l'activité et enregistrement du fichier FIT en JSON
if ($this->authService->getCurrentUser()->getRole()->addActivity($newActivity) && $this->saveFitFileToJSON($monFichierFit)) {
$activityGateway = new ActivityGateway(new Connexion(DSN, DB_USER, DB_PASSWORD));
$map = new ActivityMapper();
$activityEntity = $map->activityToEntity($newActivity);
if($activityGateway->addActivity($activityEntity)) {
return true;
}
} catch (\Exception $e) {
// TODO : add the activity
// if ($this->authService->getCurrentUser()->getRole()->addActivity($newActivity)) {
// return true;
// }
// }
return false;
}
catch(\Exception $e){
echo $e;
}
return false;
}
}
?>

@ -11,6 +11,7 @@ abstract class DataManager {
public IRelationshipRequestRepository $relationshipRequestRepository;
public ITrainingRepository $trainingRepository;
public INotificationRepository $notificationRepository;
public IActivityRepository $activityRepository;
}
?>

@ -19,7 +19,7 @@ use Network\IAuthService;
use Network\IFriendRequestService;
use Shared\Validation;
use Stub\UserRepository;
use Shared\Log;
class UserManager
{
private IAuthService $authService;
@ -66,7 +66,6 @@ class UserManager
return false;
}
if ($this->authService->login($emailUser, $passwordUser)) {
$this->currentUser = $this->authService->getCurrentUser();
// Check if the current user is correctly set
@ -82,7 +81,7 @@ class UserManager
}
public function addFriend(string $newFriend): bool
/*public function addFriend(string $newFriend): bool
{
$newFriend = $this->dataManager->userRepository->getItemByName($newFriend, 0, 1);
if ($newFriend === null) {
@ -96,6 +95,11 @@ class UserManager
return true;
};
return false;
}*/
public function addFriend(User $user1, User $user2)
{
$this->dataManager->userRepository->addFriend($user1, $user2);
}
public function respondToFriendRequest(int $requestId, bool $choice): bool
@ -134,21 +138,14 @@ class UserManager
return $this->dataManager->userRepository->getItemsByName($name, 0, 10);
}
public function searchUserByName(string $name): ?User
{
return $this->dataManager->userRepository->getItemByName($name, 0, 10);
}
public function getFriends(): array {
return [
[
'nom' => 'John',
'prenom' => 'Doe',
'img' => 'test',
'username' => 'johndoe',
],
[
'nom' => 'Alice',
'prenom' => 'Smith',
'img' => 'test2',
'username' => 'alicesmith',
],
];
$user=$this->dataManager->userRepository->getItemById(1);
return $user->getListFriend();
//return $this->currentUser->getRole()->getUsersList();
}
@ -177,7 +174,9 @@ class UserManager
}
// NEED TO PERSIST
/**
* @throws \Exception
* Enregistre un nouvel utilisateur avec les informations fournies.
*
* @param string $loginUser Le nom d'utilisateur.
@ -195,6 +194,21 @@ class UserManager
// }
// }
$dateNaissance = new \DateTime($data['dateNaissance']);
$dateActuelle = new \DateTime();
// Vérifier si la date est dans le futur
if ($dateNaissance > $dateActuelle) {
throw new \Exception("La date de naissance ne peut pas être dans le futur.");
}
// Vérifier l'âge minimum (par exemple, 18 ans)
$ageMinimum = new \DateTime('-10 years');
if ($dateNaissance > $ageMinimum) {
throw new \Exception("Vous devez avoir au moins 18 ans pour vous inscrire.");
}
$data['dateNaissance'] = $dateNaissance;
$roleName = $data['roleName'];
if ($roleName !== "Athlete" && $roleName !== "Coach") {
throw new \Exception("Rôle non valide");
@ -224,5 +238,9 @@ class UserManager
return false;
}
public function getUserById(int $id): ?User {
return $this->dataManager->userRepository->getItemById($id);
}
}
?>

@ -1,9 +1,12 @@
<?php
namespace Repository;
use Model\User;
interface IUserRepository extends IGenericRepository {
public function addFriend(int $user1,int $user2);
public function deleteFriend(int $user1,int $user2);
public function addFriend(User $user1,user $user2);
public function deleteFriend(User $user1,User $user2);
public function getItemByEmail(string $email);
}

@ -2,6 +2,7 @@
namespace Stub;
use DateTime;
use Repository\INotificationRepository;
use Model\Notification;
@ -10,13 +11,13 @@ class NotificationRepository implements INotificationRepository
private $notifications = []; // Array to store notifications
public function __construct()
{
$date = DateTime::createFromFormat('d/m/Y', date('d/m/Y'));
// Initialize with some sample notifications for user IDs 1, 2, and 3
$this->notifications[] = new Notification(1, 'info', 'Welcome to our service!');
$this->notifications[] = new Notification(2, 'alert', 'Your subscription is about to expire.');
$this->notifications[] = new Notification(3, 'info', 'New features available.');
$this->notifications[] = new Notification(1, 'reminder', 'Dont forget your upcoming appointment.');
$this->notifications[] = new Notification(2, 'update', 'Service update completed.');
// Add more notifications as needed
$this->notifications[] = new Notification('info', $date,'Welcome to our service!', '1', 1);
$this->notifications[] = new Notification('info', $date,'Welcome to our service!', '1', 1);
$this->notifications[] = new Notification('info', $date,'Welcome to our service!', '1', 1);
$this->notifications[] = new Notification('info', $date,'Welcome to our service!', '1', 1);
$this->notifications[] = new Notification('info', $date,'Welcome to our service!', '1', 1);
}
public function getItemById(int $id)
{

@ -27,12 +27,27 @@ class UserRepository implements IUserRepository {
* Constructeur de la classe UserRepository.
*/
public function __construct() {
$this->users[] = new User(1, "Doe", "John", "Doe","john.doe@example.com", "password123", 'M', 1.80, 75, new \DateTime("1985-05-15"), new CoachAthlete());
$this->users[] = new User(2, "Smith", "Jane","Smith", "jane.smith@example.com", "secure456", 'F', 1.65, 60, new \DateTime("1990-03-10"), new Athlete());
$this->users[] = new User(3, "Martin", "Paul","Martin", "paul.martin@example.com", "super789", 'M', 1.75, 68, new \DateTime("1988-08-20"), new CoachAthlete());
$this->users[] = new User(4, "Brown", "Anna","Brown", "anna.brown@example.com", "test000", 'F', 1.70, 58, new \DateTime("1992-11-25"), new Athlete());
$this->users[] = new User(5, "Lee", "Bruce","Lee", "bruce.lee@example.com", "hello321", 'M', 1.72, 70, new \DateTime("1970-02-05"), new Athlete());
$this->users[] = new User(5, "Truc", "Bruce","Truc", "bruce.lee@example.com", "hello321", 'M', 1.72, 70, new \DateTime("1970-02-05"), new Athlete());
$this->users[] = new User("Doe", "John", "Doe","john.doe@example.com", '$2y$10$U59ioMTGZBM2FGQv.3lcbuL0IkO4Fx1jQU7f5hF7o/hvCX2t46mby', 'M', 1.80, 75, new \DateTime("1985-05-15"), new CoachAthlete());
$this->users[] = new User("Smith", "Jane","Smith", "jane.smith@example.com", '$2y$10$U59ioMTGZBM2FGQv.3lcbuL0IkO4Fx1jQU7f5hF7o/hvCX2t46mby', 'F', 1.65, 60, new \DateTime("1990-03-10"), new Athlete());
$this->users[] = new User("Martin", "Paul","Martin", "paul.martin@example.com", '$2y$10$U59ioMTGZBM2FGQv.3lcbuL0IkO4Fx1jQU7f5hF7o/hvCX2t46mby', 'M', 1.75, 68, new \DateTime("1988-08-20"), new CoachAthlete());
$this->users[] = new User("Brown", "Anna","Brown", "anna.brown@example.com", '$2y$10$U59ioMTGZBM2FGQv.3lcbuL0IkO4Fx1jQU7f5hF7o/hvCX2t46mby', 'F', 1.70, 58, new \DateTime("1992-11-25"), new Athlete());
$this->users[] = new User("Lee", "Bruce","Lee", "bruce.lee@example.com", '$2y$10$U59ioMTGZBM2FGQv.3lcbuL0IkO4Fx1jQU7f5hF7o/hvCX2t46mby', 'M', 1.72, 70, new \DateTime("1970-02-05"), new Athlete());
// $this->users[] = new User(1, "Doe", "John", "Doe","john.doe@example.com", "password123", 'M', 1.80, 75, new \DateTime("1985-05-15"), new CoachAthlete());
// $this->users[] = new User(2, "Smith", "Jane","Smith", "jane.smith@example.com", "secure456", 'F', 1.65, 60, new \DateTime("1990-03-10"), new Athlete());
// $this->users[] = new User(3, "Martin", "Paul","Martin", "paul.martin@example.com", "super789", 'M', 1.75, 68, new \DateTime("1988-08-20"), new CoachAthlete());
// $this->users[] = new User(4, "Brown", "Anna","Brown", "anna.brown@example.com", "test000", 'F', 1.70, 58, new \DateTime("1992-11-25"), new Athlete());
// $this->users[] = new User(5, "Lee", "Bruce","Lee", "bruce.lee@example.com", "hello321", 'M', 1.72, 70, new \DateTime("1970-02-05"), new Athlete());
// $this->users[] = new User(6, "Truc", "Bruce","Truc", "bruce.lee@example.com", "hello321", 'M', 1.72, 70, new \DateTime("1970-02-05"), new Athlete());
// $this->users[] = new User(1, "Doe", "John", "Doe","john.doe@example.com", "password123", 'M', 1.80, 75, new \DateTime("1985-05-15"), new CoachAthlete());
// $this->users[] = new User(2, "Smith", "Jane","Smith", "jane.smith@example.com", "secure456", 'F', 1.65, 60, new \DateTime("1990-03-10"), new Athlete());
// $this->users[] = new User(3, "Martin", "Paul","Martin", "paul.martin@example.com", "super789", 'M', 1.75, 68, new \DateTime("1988-08-20"), new CoachAthlete());
// $this->users[] = new User(4, "Brown", "Anna","Brown", "anna.brown@example.com", "test000", 'F', 1.70, 58, new \DateTime("1992-11-25"), new Athlete());
// $this->users[] = new User(5, "Lee", "Bruce","Lee", "bruce.lee@example.com", "hello321", 'M', 1.72, 70, new \DateTime("1970-02-05"), new Athlete());
// $this->users[] = new User(1, "Doe", "John", "Doe","john.doe@example.com", '$2y$10$U59ioMTGZBM2FGQv.3lcbuL0IkO4Fx1jQU7f5hF7o/hvCX2t46mby', 'M', 1.80, 75, new \DateTime("1985-05-15"), new CoachAthlete());
// $this->users[] = new User(2, "Smith", "Jane","Smith", "jane.smith@example.com", '$2y$10$U59ioMTGZBM2FGQv.3lcbuL0IkO4Fx1jQU7f5hF7o/hvCX2t46mby', 'F', 1.65, 60, new \DateTime("1990-03-10"), new Athlete());
// $this->users[] = new User(3, "Martin", "Paul","Martin", "paul.martin@example.com", '$2y$10$U59ioMTGZBM2FGQv.3lcbuL0IkO4Fx1jQU7f5hF7o/hvCX2t46mby', 'M', 1.75, 68, new \DateTime("1988-08-20"), new CoachAthlete());
// $this->users[] = new User(4, "Brown", "Anna","Brown", "anna.brown@example.com", '$2y$10$U59ioMTGZBM2FGQv.3lcbuL0IkO4Fx1jQU7f5hF7o/hvCX2t46mby', 'F', 1.70, 58, new \DateTime("1992-11-25"), new Athlete());
// $this->users[] = new User(5, "Lee", "Bruce","Lee", "bruce.lee@example.com", '$2y$10$U59ioMTGZBM2FGQv.3lcbuL0IkO4Fx1jQU7f5hF7o/hvCX2t46mby', 'M', 1.72, 70, new \DateTime("1970-02-05"), new Athlete());
}
/**
@ -164,39 +179,15 @@ class UserRepository implements IUserRepository {
return false;
}
/**
* Supprime un utilisateur du dépôt.
*
* @param User $username Le username de la personne qui recherche ses amis.
* @return bool Retourne la liste des amis de l'utilisateur passe en paramètre.
*/
//TODO
public function getFriends(): array {
return [
[
'nom' => 'John',
'prenom' => 'Doe',
'img' => 'test',
'username' => 'johndoe',
],
[
'nom' => 'Alice',
'prenom' => 'Smith',
'img' => 'test2',
'username' => 'alicesmith',
],
];
}
public function addFriend(int $user1, int $user2)
public function deleteFriend(User $user1, User $user2)
{
return true;
}
public function deleteFriend(int $user1, int $user2)
public function addFriend(User $user1, User $user2)
{
return true;
$user1->addFriend($user2);
}
}
?>

@ -1,5 +1,7 @@
<?php
namespace Stub;
use Model\Athlete;
use Model\CoachAthlete;
@ -8,39 +10,44 @@ use Repository\IUserRepository;
use Shared\Exception\NotImplementedException;
use Network\IAuthService;
use Shared\IHashPassword;
use Shared\Log;
use Stub\UserRepository;
class AuthService implements IAuthService {
class AuthService implements IAuthService
{
private IUserRepository $userRepository;
private IHashPassword $passwordHacher;
private ?User $currentUser;
public function __construct(UserRepository $userRepository, IHashPassword $passwordHacher) {
public function __construct(UserRepository $userRepository, IHashPassword $passwordHacher)
{
$this->userRepository = $userRepository;
$this->passwordHacher = $passwordHacher;
}
public function login(string $emailUser,string $password): bool {
public function login(string $emailUser, string $password): bool
{
$user = $this->userRepository->getItemByEmail($emailUser);
if (!$user instanceof User) {
throw new \Exception('Unable to find user with that name');
}
if ($user->isValidPassword($password)) {
if (!$this->passwordHacher->isPasswordValid($user->getMotDePasse(), $password)) {
return false;
}
$this->currentUser = $user;
return true;
}
return false;
}
public function register(string $username, string $password, $data): bool
{
$hashedPassword = $this->passwordHacher->hashPassword($password);
$existingUser = $this->userRepository->getItemByEmail($username);
if ($existingUser != null || $existingUser instanceof User ) {
if ($existingUser != null || $existingUser instanceof User) {
throw new \Exception('User already exists');
}
$username = $data['username'];
$prenom = $data['prenom'];
$username = $data['username'];
$nom = $data['nom'];
@ -48,13 +55,12 @@ class AuthService implements IAuthService {
$sexe = $data['sexe'];
$taille = $data['taille'];
$poids = $data['poids'];
$dateNaissance = $data['dateNaissance'] ;
$dateNaissance = $data['dateNaissance'];
$roleName = $data['roleName'];
$role = null;
if($roleName == "Coach"){
if ($roleName == "Coach") {
$role = new CoachAthlete();
}
else if($roleName == "Athlete"){
} else if ($roleName == "Athlete") {
$role = new Athlete();
}
$user = new User(

@ -2,6 +2,8 @@
namespace Shared;
use App\Router\Request\IRequest;
use InvalidArgumentException;
/**
* Responsible for resolving the arguments passed to a controller action.
*/
@ -14,7 +16,7 @@ class ArgumentControllerResolver implements IArgumentResolver{
* @param callable $controller The controller callable.
* @return array An array of resolved arguments.
* @throws \ReflectionException If the controller method does not exist.
* @throws \InvalidArgumentException If an argument cannot be resolved.
* @throws InvalidArgumentException If an argument cannot be resolved.
*/
public function getArguments(IRequest $request, callable $controller): array
{
@ -27,10 +29,10 @@ class ArgumentControllerResolver implements IArgumentResolver{
$reflectionMethod = new \ReflectionMethod($className, $methodName);
} else {
// Handle other types of callables if needed
throw new \InvalidArgumentException("Invalid controller callable format.");
throw new InvalidArgumentException("Invalid controller callable format.");
}
} catch (\ReflectionException $e) {
throw new \InvalidArgumentException("Controller method error: " . $e->getMessage());
throw new InvalidArgumentException("Controller method error: " . $e->getMessage());
}
$args = [];
@ -42,11 +44,10 @@ class ArgumentControllerResolver implements IArgumentResolver{
$name = $param->getName();
$value = $this->getFromRequest($name, $request);
if ($value === null && $param->isDefaultValueAvailable()) {
$value = $param->getDefaultValue();
} elseif ($value === null) {
throw new \InvalidArgumentException("Missing argument: $name");
throw new InvalidArgumentException("Missing argument: $name");
}
$args[] = $value;

@ -26,7 +26,7 @@ final class Validation {
* @throws Exception Si la chaîne n'est pas valide (tentative d'injection de code).
*/
public static function val_string(string $string) : bool {
if (strlen(htmlspecialchars($string, ENT_QUOTES) === 0)) {
if (!$string) {//filter_var($string, FILTER_SANITIZE_STRING) !== $string
throw new Exception("$string n'est pas valide. Tentative d'injection de code (attaque sécurité)!");
} else {
return true;
@ -101,7 +101,7 @@ final class Validation {
* @return string La chaîne nettoyée.
*/
public static function clean_string(string $string) : string {
return filter_var($string, FILTER_SANITIZE_STRING);
return filter_var($string);
}
/**

@ -0,0 +1,215 @@
<?php
use PHPUnit\Framework\TestCase;
//use Database\{Connexion, AthleteGateway,AthleteEntity};
use Database\AthleteEntity;
use Database\AthleteGateway;
use Database\Connexion;
use Database\AthleteMapper;
use Database\CoachGateway;
use Database\CoachEntity;
use Database\CoachMapper;
class GatewayTest extends TestCase {
//Partie concernant les Athlètes
public function testGetAthlete() {
//$dsn = "pgsql:host=londres;port=8888;dbname=dbkemonteiro2;user=kemonteiro2;password=Mdp";
require "loginDatabase.php";
$connexion = new Connexion($dsn,$username,$password);
$athleteGateway = new AthleteGateway($connexion);
$result = $athleteGateway->getAthlete();
//var_dump($result);
}
/* Fonctionne mais en commentaire pour pas add et del a chaque fois
public function testAddAthlete(){
$dsn = "mysql:host=londres;dbname=dbkemonteiro2;";
$username = "kemonteiro2";
$password = "#Phpmyadmin63";
$connexion = new Connexion($dsn,$username,$password);
$athleteGateway = new AthleteGateway($connexion);
$dateSpecifique = "2023-11-26";
$timestamp = strtotime($dateSpecifique);
$dateSQL = date("Y-m-d", $timestamp);
$athleteEntity = new AthleteEntity();
$athleteEntity->setNom('John');
$athleteEntity->setPrenom('Doe');
$athleteEntity->setIdAthlete(1234);
$athleteEntity->setEmail('kevin.monteiro@gmail.fr');
$athleteEntity->setSexe('H');
$athleteEntity->setTaille(169);
$athleteEntity->setPoids(69);
$athleteEntity->setMotDePasse('motdepasse');
$athleteEntity->setDateNaissance($dateSQL);
$result2 = $athleteGateway->addAthlete($athleteEntity);
}
public function testDeleteAthlete(){
$dsn = "mysql:host=londres;dbname=dbkemonteiro2;";
$username = "kemonteiro2";
$password = "#Phpmyadmin63";
$connexion = new Connexion($dsn,$username,$password);
$athleteGateway = new AthleteGateway($connexion);
$result = $athleteGateway->deleteAthlete( //idAthlete );
var_dump($result);
}*/
public function testUpdateAthlete(){
$dsn = "mysql:host=londres;dbname=dbkemonteiro2;";
$username = "kemonteiro2";
$password = "#Phpmyadmin63";
$connexion = new Connexion($dsn,$username,$password);
$athleteGateway = new AthleteGateway($connexion);
$dateSpecifique = "2004-08-26";
$timestamp = strtotime($dateSpecifique);
$dateSQL = date("Y-m-d", $timestamp);
$athleteEntity = new AthleteEntity();
$athleteEntity->setNom('John');
$athleteEntity->setPrenom('Doe');
$athleteEntity->setIdAthlete(13);
$athleteEntity->setEmail('kevin.monteiro@gmail.fr');
$athleteEntity->setSexe('H');
$athleteEntity->setTaille(169);
$athleteEntity->setPoids(69);
$athleteEntity->setMotDePasse('motdepasse');
$athleteEntity->setDateNaissance($dateSQL);
$athleteEntity->setIsCoach(FALSE);
$athleteEntity->setCoachId(NULL);
$athleteEntity2 = new AthleteEntity();
$athleteEntity2->setNom('Monteiro');
$athleteEntity2->setPrenom('Kevin');
$athleteEntity2->setIdAthlete(13);
$athleteEntity2->setEmail('kevin.monteiro@gmail.fr');
$athleteEntity2->setSexe('H');
$athleteEntity2->setTaille(169);
$athleteEntity2->setPoids(69);
$athleteEntity2->setMotDePasse('motdepasse');
$athleteEntity2->setDateNaissance($dateSQL);
$athleteEntity2->setIsCoach(TRUE);
$athleteEntity2->setCoachId(1);
$result = $athleteGateway->updateAthlete($athleteEntity, $athleteEntity2);
}
//Partie concernant les Coachs
public function testGetCoach() {
//$dsn = "pgsql:host=londres;port=8888;dbname=dbkemonteiro2;user=kemonteiro2;password=Mdp";
$dsn = "mysql:host=londres;dbname=dbkemonteiro2;";
$username = "kemonteiro2";
$password = "#Phpmyadmin63";
$connexion = new Connexion($dsn,$username,$password);
$coachGateway = new CoachGateway($connexion);
$result = $coachGateway->getCoach();
var_dump($result);
}
/*
//Fonctionne PAS A PARTIR DE LA
public function testAddCoach(){
$dsn = "mysql:host=londres;dbname=dbkemonteiro2;";
$username = "kemonteiro2";
$password = "#Phpmyadmin63";
$connexion = new Connexion($dsn,$username,$password);
$coachGateway = new CoachGateway($connexion);
$dateSpecifique = "2023-11-26";
$timestamp = strtotime($dateSpecifique);
$dateSQL = date("Y-m-d", $timestamp);
$coachEntity = new CoachEntity();
$coachEntity->setNom('John');
$coachEntity->setPrenom('Doe');
$coachEntity->setIdCoach(1234);
$coachEntity->setEmail('kevin.monteiro@gmail.fr');
$coachEntity->setSexe('H');
$coachEntity->setTaille(169);
$coachEntity->setPoids(69);
$coachEntity->setMotDePasse('motdepasse');
$coachEntity->setDateNaissance($dateSQL);
$result2 = $coachGateway->addCoach($coachEntity);
}
public function testDeleteAthlete(){
$dsn = "mysql:host=londres;dbname=dbkemonteiro2;";
$username = "kemonteiro2";
$password = "#Phpmyadmin63";
$connexion = new Connexion($dsn,$username,$password);
$athleteGateway = new AthleteGateway($connexion);
$result = $athleteGateway->deleteAthlete( //idAthlete );
var_dump($result);
}*/
/*
public function testUpdateAthlete(){
$dsn = "mysql:host=londres;dbname=dbkemonteiro2;";
$username = "kemonteiro2";
$password = "#Phpmyadmin63";
$connexion = new Connexion($dsn,$username,$password);
$athleteGateway = new AthleteGateway($connexion);
$dateSpecifique = "2004-08-26";
$timestamp = strtotime($dateSpecifique);
$dateSQL = date("Y-m-d", $timestamp);
$athleteEntity = new AthleteEntity();
$athleteEntity->setNom('John');
$athleteEntity->setPrenom('Doe');
$athleteEntity->setIdAthlete(13);
$athleteEntity->setEmail('kevin.monteiro@gmail.fr');
$athleteEntity->setSexe('H');
$athleteEntity->setTaille(169);
$athleteEntity->setPoids(69);
$athleteEntity->setMotDePasse('motdepasse');
$athleteEntity->setDateNaissance($dateSQL);
$athleteEntity2 = new AthleteEntity();
$athleteEntity2->setNom('Monteiro');
$athleteEntity2->setPrenom('Kevin');
$athleteEntity2->setIdAthlete(13);
$athleteEntity2->setEmail('kevin.monteiro@gmail.fr');
$athleteEntity2->setSexe('H');
$athleteEntity2->setTaille(169);
$athleteEntity2->setPoids(69);
$athleteEntity2->setMotDePasse('motdepasse');
$athleteEntity2->setDateNaissance($dateSQL);
$result = $athleteGateway->updateAthlete($athleteEntity, $athleteEntity2);
}*/
}

@ -0,0 +1,43 @@
<?php
use PHPUnit\Framework\TestCase;
use Model\User;
use Database\AthleteEntity;
use Database\AthleteGateway;
use Database\Connexion;
use Database\AthleteMapper;
class MapperTest extends TestCase {
public function testMapperAthlete() {
//$dsn = "pgsql:host=londres;port=8888;dbname=dbkemonteiro2;user=kemonteiro2;password=Mdp";
$dsn = "mysql:host=londres;dbname=dbkemonteiro2;";
$username = "kemonteiro2";
$password = "#Phpmyadmin63";
$connexion = new Connexion($dsn,$username,$password);
$athleteGateway = new AthleteGateway($connexion);
$result = $athleteGateway->getAthlete();
$map = new AthleteMapper ();
//SQL To AthleteEntity
$athleteEntity = $map->athleteSqlToEntity($result);
foreach($athleteEntity as $ath){
$result = $ath->getNom();
var_dump($result);
//Pour chaque AthleteEntity : Athlete Entity To User avec Role Athlete(Model)
$user = $map->athleteEntityToModel($ath);
var_dump($user->getId());
//Pour chaque Athlete du Model -> Athlete Entity
$res = $map->athleteToEntity($user);
var_dump($res->getIdAthlete());
}
}
}

@ -0,0 +1,7 @@
<?php
$dsn = "psql:host=localhost;dbname=sae_3;";
$username = "Perederii";
$password = "";
?>

@ -1,4 +1,5 @@
<?php
use Shared\Log;
class AltoRouter {
@ -100,6 +101,8 @@ class AltoRouter {
public function generate($routeName, array $params = array()) {
// Check if named route exists
if(!isset($this->namedRoutes[$routeName])) {
throw new \Exception("Route '{$routeName}' does not exist.");
}

@ -430,7 +430,6 @@ return array(
'PHPUnit\\Framework\\MockObject\\Stub\\ReturnValueMap' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnValueMap.php',
'PHPUnit\\Framework\\MockObject\\Stub\\Stub' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/Stub.php',
'PHPUnit\\Framework\\NoChildTestSuiteException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/NoChildTestSuiteException.php',
'PHPUnit\\Framework\\PhptAssertionFailedError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/PhptAssertionFailedError.php',
'PHPUnit\\Framework\\ProcessIsolationException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ProcessIsolationException.php',
'PHPUnit\\Framework\\Reorderable' => $vendorDir . '/phpunit/phpunit/src/Framework/Reorderable.php',
'PHPUnit\\Framework\\SelfDescribing' => $vendorDir . '/phpunit/phpunit/src/Framework/SelfDescribing.php',
@ -956,93 +955,6 @@ return array(
'PharIo\\Version\\VersionConstraintValue' => $vendorDir . '/phar-io/version/src/VersionConstraintValue.php',
'PharIo\\Version\\VersionNumber' => $vendorDir . '/phar-io/version/src/VersionNumber.php',
'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
'SebastianBergmann\\CliParser\\AmbiguousOptionException' => $vendorDir . '/sebastian/cli-parser/src/exceptions/AmbiguousOptionException.php',
'SebastianBergmann\\CliParser\\Exception' => $vendorDir . '/sebastian/cli-parser/src/exceptions/Exception.php',
'SebastianBergmann\\CliParser\\OptionDoesNotAllowArgumentException' => $vendorDir . '/sebastian/cli-parser/src/exceptions/OptionDoesNotAllowArgumentException.php',
'SebastianBergmann\\CliParser\\Parser' => $vendorDir . '/sebastian/cli-parser/src/Parser.php',
'SebastianBergmann\\CliParser\\RequiredOptionArgumentMissingException' => $vendorDir . '/sebastian/cli-parser/src/exceptions/RequiredOptionArgumentMissingException.php',
'SebastianBergmann\\CliParser\\UnknownOptionException' => $vendorDir . '/sebastian/cli-parser/src/exceptions/UnknownOptionException.php',
'SebastianBergmann\\CodeCoverage\\BranchAndPathCoverageNotSupportedException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/BranchAndPathCoverageNotSupportedException.php',
'SebastianBergmann\\CodeCoverage\\CodeCoverage' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage.php',
'SebastianBergmann\\CodeCoverage\\Data\\ProcessedCodeCoverageData' => $vendorDir . '/phpunit/php-code-coverage/src/Data/ProcessedCodeCoverageData.php',
'SebastianBergmann\\CodeCoverage\\Data\\RawCodeCoverageData' => $vendorDir . '/phpunit/php-code-coverage/src/Data/RawCodeCoverageData.php',
'SebastianBergmann\\CodeCoverage\\DeadCodeDetectionNotSupportedException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/DeadCodeDetectionNotSupportedException.php',
'SebastianBergmann\\CodeCoverage\\Driver\\Driver' => $vendorDir . '/phpunit/php-code-coverage/src/Driver/Driver.php',
'SebastianBergmann\\CodeCoverage\\Driver\\PathExistsButIsNotDirectoryException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/PathExistsButIsNotDirectoryException.php',
'SebastianBergmann\\CodeCoverage\\Driver\\PcovDriver' => $vendorDir . '/phpunit/php-code-coverage/src/Driver/PcovDriver.php',
'SebastianBergmann\\CodeCoverage\\Driver\\PcovNotAvailableException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/PcovNotAvailableException.php',
'SebastianBergmann\\CodeCoverage\\Driver\\Selector' => $vendorDir . '/phpunit/php-code-coverage/src/Driver/Selector.php',
'SebastianBergmann\\CodeCoverage\\Driver\\WriteOperationFailedException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/WriteOperationFailedException.php',
'SebastianBergmann\\CodeCoverage\\Driver\\XdebugDriver' => $vendorDir . '/phpunit/php-code-coverage/src/Driver/XdebugDriver.php',
'SebastianBergmann\\CodeCoverage\\Driver\\XdebugNotAvailableException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/XdebugNotAvailableException.php',
'SebastianBergmann\\CodeCoverage\\Driver\\XdebugNotEnabledException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/XdebugNotEnabledException.php',
'SebastianBergmann\\CodeCoverage\\Exception' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/Exception.php',
'SebastianBergmann\\CodeCoverage\\FileCouldNotBeWrittenException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/FileCouldNotBeWrittenException.php',
'SebastianBergmann\\CodeCoverage\\Filter' => $vendorDir . '/phpunit/php-code-coverage/src/Filter.php',
'SebastianBergmann\\CodeCoverage\\InvalidArgumentException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/InvalidArgumentException.php',
'SebastianBergmann\\CodeCoverage\\NoCodeCoverageDriverAvailableException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverAvailableException.php',
'SebastianBergmann\\CodeCoverage\\NoCodeCoverageDriverWithPathCoverageSupportAvailableException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverWithPathCoverageSupportAvailableException.php',
'SebastianBergmann\\CodeCoverage\\Node\\AbstractNode' => $vendorDir . '/phpunit/php-code-coverage/src/Node/AbstractNode.php',
'SebastianBergmann\\CodeCoverage\\Node\\Builder' => $vendorDir . '/phpunit/php-code-coverage/src/Node/Builder.php',
'SebastianBergmann\\CodeCoverage\\Node\\CrapIndex' => $vendorDir . '/phpunit/php-code-coverage/src/Node/CrapIndex.php',
'SebastianBergmann\\CodeCoverage\\Node\\Directory' => $vendorDir . '/phpunit/php-code-coverage/src/Node/Directory.php',
'SebastianBergmann\\CodeCoverage\\Node\\File' => $vendorDir . '/phpunit/php-code-coverage/src/Node/File.php',
'SebastianBergmann\\CodeCoverage\\Node\\Iterator' => $vendorDir . '/phpunit/php-code-coverage/src/Node/Iterator.php',
'SebastianBergmann\\CodeCoverage\\ParserException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/ParserException.php',
'SebastianBergmann\\CodeCoverage\\ReflectionException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/ReflectionException.php',
'SebastianBergmann\\CodeCoverage\\ReportAlreadyFinalizedException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/ReportAlreadyFinalizedException.php',
'SebastianBergmann\\CodeCoverage\\Report\\Clover' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Clover.php',
'SebastianBergmann\\CodeCoverage\\Report\\Cobertura' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Cobertura.php',
'SebastianBergmann\\CodeCoverage\\Report\\Crap4j' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Crap4j.php',
'SebastianBergmann\\CodeCoverage\\Report\\Html\\Colors' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Colors.php',
'SebastianBergmann\\CodeCoverage\\Report\\Html\\CustomCssFile' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/CustomCssFile.php',
'SebastianBergmann\\CodeCoverage\\Report\\Html\\Dashboard' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Renderer/Dashboard.php',
'SebastianBergmann\\CodeCoverage\\Report\\Html\\Directory' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Renderer/Directory.php',
'SebastianBergmann\\CodeCoverage\\Report\\Html\\Facade' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Facade.php',
'SebastianBergmann\\CodeCoverage\\Report\\Html\\File' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Renderer/File.php',
'SebastianBergmann\\CodeCoverage\\Report\\Html\\Renderer' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Renderer.php',
'SebastianBergmann\\CodeCoverage\\Report\\PHP' => $vendorDir . '/phpunit/php-code-coverage/src/Report/PHP.php',
'SebastianBergmann\\CodeCoverage\\Report\\Text' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Text.php',
'SebastianBergmann\\CodeCoverage\\Report\\Thresholds' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Thresholds.php',
'SebastianBergmann\\CodeCoverage\\Report\\Xml\\BuildInformation' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/BuildInformation.php',
'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Coverage' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Coverage.php',
'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Directory' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Directory.php',
'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Facade' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Facade.php',
'SebastianBergmann\\CodeCoverage\\Report\\Xml\\File' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/File.php',
'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Method' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Method.php',
'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Node' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Node.php',
'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Project' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Project.php',
'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Report' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Report.php',
'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Source' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Source.php',
'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Tests' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Tests.php',
'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Totals' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Totals.php',
'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Unit' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Unit.php',
'SebastianBergmann\\CodeCoverage\\StaticAnalysisCacheNotConfiguredException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/StaticAnalysisCacheNotConfiguredException.php',
'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CacheWarmer' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/CacheWarmer.php',
'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CachingFileAnalyser' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/CachingFileAnalyser.php',
'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CodeUnitFindingVisitor' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/CodeUnitFindingVisitor.php',
'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\ExecutableLinesFindingVisitor' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/ExecutableLinesFindingVisitor.php',
'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\FileAnalyser' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/FileAnalyser.php',
'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\IgnoredLinesFindingVisitor' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/IgnoredLinesFindingVisitor.php',
'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\ParsingFileAnalyser' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/ParsingFileAnalyser.php',
'SebastianBergmann\\CodeCoverage\\TestIdMissingException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/TestIdMissingException.php',
'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\Known' => $vendorDir . '/phpunit/php-code-coverage/src/TestSize/Known.php',
'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\Large' => $vendorDir . '/phpunit/php-code-coverage/src/TestSize/Large.php',
'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\Medium' => $vendorDir . '/phpunit/php-code-coverage/src/TestSize/Medium.php',
'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\Small' => $vendorDir . '/phpunit/php-code-coverage/src/TestSize/Small.php',
'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\TestSize' => $vendorDir . '/phpunit/php-code-coverage/src/TestSize/TestSize.php',
'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\Unknown' => $vendorDir . '/phpunit/php-code-coverage/src/TestSize/Unknown.php',
'SebastianBergmann\\CodeCoverage\\Test\\TestStatus\\Failure' => $vendorDir . '/phpunit/php-code-coverage/src/TestStatus/Failure.php',
'SebastianBergmann\\CodeCoverage\\Test\\TestStatus\\Known' => $vendorDir . '/phpunit/php-code-coverage/src/TestStatus/Known.php',
'SebastianBergmann\\CodeCoverage\\Test\\TestStatus\\Success' => $vendorDir . '/phpunit/php-code-coverage/src/TestStatus/Success.php',
'SebastianBergmann\\CodeCoverage\\Test\\TestStatus\\TestStatus' => $vendorDir . '/phpunit/php-code-coverage/src/TestStatus/TestStatus.php',
'SebastianBergmann\\CodeCoverage\\Test\\TestStatus\\Unknown' => $vendorDir . '/phpunit/php-code-coverage/src/TestStatus/Unknown.php',
'SebastianBergmann\\CodeCoverage\\UnintentionallyCoveredCodeException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/UnintentionallyCoveredCodeException.php',
'SebastianBergmann\\CodeCoverage\\Util\\DirectoryCouldNotBeCreatedException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/DirectoryCouldNotBeCreatedException.php',
'SebastianBergmann\\CodeCoverage\\Util\\Filesystem' => $vendorDir . '/phpunit/php-code-coverage/src/Util/Filesystem.php',
'SebastianBergmann\\CodeCoverage\\Util\\Percentage' => $vendorDir . '/phpunit/php-code-coverage/src/Util/Percentage.php',
'SebastianBergmann\\CodeCoverage\\Version' => $vendorDir . '/phpunit/php-code-coverage/src/Version.php',
'SebastianBergmann\\CodeCoverage\\XmlException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/XmlException.php',
'SebastianBergmann\\CodeUnitReverseLookup\\Wizard' => $vendorDir . '/sebastian/code-unit-reverse-lookup/src/Wizard.php',
'SebastianBergmann\\CodeUnit\\ClassMethodUnit' => $vendorDir . '/sebastian/code-unit/src/ClassMethodUnit.php',
'SebastianBergmann\\CodeUnit\\ClassUnit' => $vendorDir . '/sebastian/code-unit/src/ClassUnit.php',

@ -12,24 +12,21 @@ return array(
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
'Stub\\' => array($baseDir . '/src/data/stub', $baseDir . '/src/data/stub/service', $baseDir . '/src/data/stub/repository'),
'Repository\\' => array($baseDir . '/src/data/model/repository'),
'Network\\' => array($baseDir . '/src/data/core/network'),
'Model\\' => array($baseDir . '/src/data/model'),
'Manager\\' => array($baseDir . '/src/data/model/manager'),
'Dotenv\\' => array($vendorDir . '/vlucas/phpdotenv/src'),
'Data\\' => array($baseDir . '/src/data'),
'Shared\\Exception\\' => array($baseDir . '/src/shared/exception'),
'Shared\\Attributes\\' => array($baseDir . '/src/shared/attributes'),
'Shared\\' => array($baseDir . '/src/shared'),
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
'PhpParser\\' => array($vendorDir . '/nikic/php-parser/lib/PhpParser'),
'PhpOption\\' => array($vendorDir . '/phpoption/phpoption/src/PhpOption'),
'Repository\\' => array($baseDir . '/src/data/model/repository'),
'Psr\\Container\\' => array($vendorDir . '/psr/container/src', $vendorDir . '/sebastian/cli-parser/src'),
'PhpParser\\' => array($vendorDir . '/nikic/php-parser/lib/PhpParser'),
'PhpOption\\' => array($vendorDir . '/phpoption/phpoption/src/PhpOption', $vendorDir . '/phpunit/php-code-coverage/src/PhpOption'),
'Network\\' => array($baseDir . '/src/data/core/network'),
'Model\\' => array($baseDir . '/src/data/model'),
'Manager\\' => array($baseDir . '/src/data/model/manager'),
'Hearttrack\\' => array($baseDir . '/src'),
'GrahamCampbell\\ResultType\\' => array($vendorDir . '/graham-campbell/result-type/src'),
'Dotenv\\' => array($vendorDir . '/vlucas/phpdotenv/src'),
'DeepCopy\\' => array($vendorDir . '/myclabs/deep-copy/src/DeepCopy'),
'Database\\' => array($baseDir . '/src/data/core/database'),
'Data\\Core\\' => array($baseDir . '/src/data/core'),
'Data\\' => array($baseDir . '/src/data'),
'Console\\' => array($baseDir . '/src/console'),

@ -63,10 +63,10 @@ class ComposerStaticInit1887e85fc3cfddacf8d7e17588dae6f1
'D' =>
array (
'Dotenv\\' => 7,
'Data\\' => 5,
'Doctrine\\Instantiator\\' => 22,
'DeepCopy\\' => 9,
'Database\\' => 9,
'Data\\Core\\' => 10,
'Data\\' => 5,
),
'C' =>
array (
@ -130,6 +130,7 @@ class ComposerStaticInit1887e85fc3cfddacf8d7e17588dae6f1
'Psr\\Container\\' =>
array (
0 => __DIR__ . '/..' . '/psr/container/src',
1 => __DIR__ . '/..' . '/sebastian/cli-parser/src',
),
'PhpParser\\' =>
array (
@ -138,6 +139,7 @@ class ComposerStaticInit1887e85fc3cfddacf8d7e17588dae6f1
'PhpOption\\' =>
array (
0 => __DIR__ . '/..' . '/phpoption/phpoption/src/PhpOption',
1 => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/PhpOption',
),
'Network\\' =>
array (
@ -163,18 +165,14 @@ class ComposerStaticInit1887e85fc3cfddacf8d7e17588dae6f1
array (
0 => __DIR__ . '/..' . '/vlucas/phpdotenv/src',
),
'Doctrine\\Instantiator\\' =>
array (
0 => __DIR__ . '/..' . '/graham-campbell/result-type/src',
),
'Dotenv\\' =>
array (
0 => __DIR__ . '/..' . '/vlucas/phpdotenv/src',
),
'DeepCopy\\' =>
array (
0 => __DIR__ . '/..' . '/myclabs/deep-copy/src/DeepCopy',
),
'Database\\' =>
array (
0 => __DIR__ . '/../..' . '/src/data/core/database',
),
'Data\\Core\\' =>
array (
0 => __DIR__ . '/../..' . '/src/data/core',
@ -642,7 +640,6 @@ class ComposerStaticInit1887e85fc3cfddacf8d7e17588dae6f1
'PHPUnit\\Framework\\MockObject\\Stub\\ReturnValueMap' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnValueMap.php',
'PHPUnit\\Framework\\MockObject\\Stub\\Stub' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/Stub.php',
'PHPUnit\\Framework\\NoChildTestSuiteException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/NoChildTestSuiteException.php',
'PHPUnit\\Framework\\PhptAssertionFailedError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/PhptAssertionFailedError.php',
'PHPUnit\\Framework\\ProcessIsolationException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ProcessIsolationException.php',
'PHPUnit\\Framework\\Reorderable' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Reorderable.php',
'PHPUnit\\Framework\\SelfDescribing' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/SelfDescribing.php',
@ -1168,93 +1165,6 @@ class ComposerStaticInit1887e85fc3cfddacf8d7e17588dae6f1
'PharIo\\Version\\VersionConstraintValue' => __DIR__ . '/..' . '/phar-io/version/src/VersionConstraintValue.php',
'PharIo\\Version\\VersionNumber' => __DIR__ . '/..' . '/phar-io/version/src/VersionNumber.php',
'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
'SebastianBergmann\\CliParser\\AmbiguousOptionException' => __DIR__ . '/..' . '/sebastian/cli-parser/src/exceptions/AmbiguousOptionException.php',
'SebastianBergmann\\CliParser\\Exception' => __DIR__ . '/..' . '/sebastian/cli-parser/src/exceptions/Exception.php',
'SebastianBergmann\\CliParser\\OptionDoesNotAllowArgumentException' => __DIR__ . '/..' . '/sebastian/cli-parser/src/exceptions/OptionDoesNotAllowArgumentException.php',
'SebastianBergmann\\CliParser\\Parser' => __DIR__ . '/..' . '/sebastian/cli-parser/src/Parser.php',
'SebastianBergmann\\CliParser\\RequiredOptionArgumentMissingException' => __DIR__ . '/..' . '/sebastian/cli-parser/src/exceptions/RequiredOptionArgumentMissingException.php',
'SebastianBergmann\\CliParser\\UnknownOptionException' => __DIR__ . '/..' . '/sebastian/cli-parser/src/exceptions/UnknownOptionException.php',
'SebastianBergmann\\CodeCoverage\\BranchAndPathCoverageNotSupportedException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/BranchAndPathCoverageNotSupportedException.php',
'SebastianBergmann\\CodeCoverage\\CodeCoverage' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage.php',
'SebastianBergmann\\CodeCoverage\\Data\\ProcessedCodeCoverageData' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Data/ProcessedCodeCoverageData.php',
'SebastianBergmann\\CodeCoverage\\Data\\RawCodeCoverageData' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Data/RawCodeCoverageData.php',
'SebastianBergmann\\CodeCoverage\\DeadCodeDetectionNotSupportedException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/DeadCodeDetectionNotSupportedException.php',
'SebastianBergmann\\CodeCoverage\\Driver\\Driver' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Driver/Driver.php',
'SebastianBergmann\\CodeCoverage\\Driver\\PathExistsButIsNotDirectoryException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/PathExistsButIsNotDirectoryException.php',
'SebastianBergmann\\CodeCoverage\\Driver\\PcovDriver' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Driver/PcovDriver.php',
'SebastianBergmann\\CodeCoverage\\Driver\\PcovNotAvailableException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/PcovNotAvailableException.php',
'SebastianBergmann\\CodeCoverage\\Driver\\Selector' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Driver/Selector.php',
'SebastianBergmann\\CodeCoverage\\Driver\\WriteOperationFailedException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/WriteOperationFailedException.php',
'SebastianBergmann\\CodeCoverage\\Driver\\XdebugDriver' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Driver/XdebugDriver.php',
'SebastianBergmann\\CodeCoverage\\Driver\\XdebugNotAvailableException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/XdebugNotAvailableException.php',
'SebastianBergmann\\CodeCoverage\\Driver\\XdebugNotEnabledException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/XdebugNotEnabledException.php',
'SebastianBergmann\\CodeCoverage\\Exception' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/Exception.php',
'SebastianBergmann\\CodeCoverage\\FileCouldNotBeWrittenException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/FileCouldNotBeWrittenException.php',
'SebastianBergmann\\CodeCoverage\\Filter' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Filter.php',
'SebastianBergmann\\CodeCoverage\\InvalidArgumentException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/InvalidArgumentException.php',
'SebastianBergmann\\CodeCoverage\\NoCodeCoverageDriverAvailableException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverAvailableException.php',
'SebastianBergmann\\CodeCoverage\\NoCodeCoverageDriverWithPathCoverageSupportAvailableException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverWithPathCoverageSupportAvailableException.php',
'SebastianBergmann\\CodeCoverage\\Node\\AbstractNode' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/AbstractNode.php',
'SebastianBergmann\\CodeCoverage\\Node\\Builder' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/Builder.php',
'SebastianBergmann\\CodeCoverage\\Node\\CrapIndex' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/CrapIndex.php',
'SebastianBergmann\\CodeCoverage\\Node\\Directory' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/Directory.php',
'SebastianBergmann\\CodeCoverage\\Node\\File' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/File.php',
'SebastianBergmann\\CodeCoverage\\Node\\Iterator' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/Iterator.php',
'SebastianBergmann\\CodeCoverage\\ParserException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/ParserException.php',
'SebastianBergmann\\CodeCoverage\\ReflectionException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/ReflectionException.php',
'SebastianBergmann\\CodeCoverage\\ReportAlreadyFinalizedException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/ReportAlreadyFinalizedException.php',
'SebastianBergmann\\CodeCoverage\\Report\\Clover' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Clover.php',
'SebastianBergmann\\CodeCoverage\\Report\\Cobertura' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Cobertura.php',
'SebastianBergmann\\CodeCoverage\\Report\\Crap4j' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Crap4j.php',
'SebastianBergmann\\CodeCoverage\\Report\\Html\\Colors' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Colors.php',
'SebastianBergmann\\CodeCoverage\\Report\\Html\\CustomCssFile' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/CustomCssFile.php',
'SebastianBergmann\\CodeCoverage\\Report\\Html\\Dashboard' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Renderer/Dashboard.php',
'SebastianBergmann\\CodeCoverage\\Report\\Html\\Directory' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Renderer/Directory.php',
'SebastianBergmann\\CodeCoverage\\Report\\Html\\Facade' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Facade.php',
'SebastianBergmann\\CodeCoverage\\Report\\Html\\File' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Renderer/File.php',
'SebastianBergmann\\CodeCoverage\\Report\\Html\\Renderer' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Renderer.php',
'SebastianBergmann\\CodeCoverage\\Report\\PHP' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/PHP.php',
'SebastianBergmann\\CodeCoverage\\Report\\Text' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Text.php',
'SebastianBergmann\\CodeCoverage\\Report\\Thresholds' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Thresholds.php',
'SebastianBergmann\\CodeCoverage\\Report\\Xml\\BuildInformation' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/BuildInformation.php',
'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Coverage' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Coverage.php',
'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Directory' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Directory.php',
'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Facade' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Facade.php',
'SebastianBergmann\\CodeCoverage\\Report\\Xml\\File' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/File.php',
'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Method' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Method.php',
'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Node' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Node.php',
'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Project' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Project.php',
'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Report' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Report.php',
'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Source' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Source.php',
'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Tests' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Tests.php',
'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Totals' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Totals.php',
'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Unit' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Unit.php',
'SebastianBergmann\\CodeCoverage\\StaticAnalysisCacheNotConfiguredException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/StaticAnalysisCacheNotConfiguredException.php',
'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CacheWarmer' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/CacheWarmer.php',
'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CachingFileAnalyser' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/CachingFileAnalyser.php',
'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CodeUnitFindingVisitor' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/CodeUnitFindingVisitor.php',
'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\ExecutableLinesFindingVisitor' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/ExecutableLinesFindingVisitor.php',
'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\FileAnalyser' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/FileAnalyser.php',
'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\IgnoredLinesFindingVisitor' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/IgnoredLinesFindingVisitor.php',
'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\ParsingFileAnalyser' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/ParsingFileAnalyser.php',
'SebastianBergmann\\CodeCoverage\\TestIdMissingException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/TestIdMissingException.php',
'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\Known' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestSize/Known.php',
'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\Large' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestSize/Large.php',
'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\Medium' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestSize/Medium.php',
'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\Small' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestSize/Small.php',
'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\TestSize' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestSize/TestSize.php',
'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\Unknown' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestSize/Unknown.php',
'SebastianBergmann\\CodeCoverage\\Test\\TestStatus\\Failure' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestStatus/Failure.php',
'SebastianBergmann\\CodeCoverage\\Test\\TestStatus\\Known' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestStatus/Known.php',
'SebastianBergmann\\CodeCoverage\\Test\\TestStatus\\Success' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestStatus/Success.php',
'SebastianBergmann\\CodeCoverage\\Test\\TestStatus\\TestStatus' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestStatus/TestStatus.php',
'SebastianBergmann\\CodeCoverage\\Test\\TestStatus\\Unknown' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestStatus/Unknown.php',
'SebastianBergmann\\CodeCoverage\\UnintentionallyCoveredCodeException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/UnintentionallyCoveredCodeException.php',
'SebastianBergmann\\CodeCoverage\\Util\\DirectoryCouldNotBeCreatedException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/DirectoryCouldNotBeCreatedException.php',
'SebastianBergmann\\CodeCoverage\\Util\\Filesystem' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Util/Filesystem.php',
'SebastianBergmann\\CodeCoverage\\Util\\Percentage' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Util/Percentage.php',
'SebastianBergmann\\CodeCoverage\\Version' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Version.php',
'SebastianBergmann\\CodeCoverage\\XmlException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/XmlException.php',
'SebastianBergmann\\CodeUnitReverseLookup\\Wizard' => __DIR__ . '/..' . '/sebastian/code-unit-reverse-lookup/src/Wizard.php',
'SebastianBergmann\\CodeUnit\\ClassMethodUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/ClassMethodUnit.php',
'SebastianBergmann\\CodeUnit\\ClassUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/ClassUnit.php',

28
package-lock.json generated

@ -0,0 +1,28 @@
{
"name": "Web",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"chart.js": "^4.4.1"
}
},
"node_modules/@kurkle/color": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz",
"integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw=="
},
"node_modules/chart.js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.1.tgz",
"integrity": "sha512-C74QN1bxwV1v2PEujhmKjOZ7iUM4w6BWs23Md/6aOZZSlwMzeCIDGuZay++rBgChYru7/+QFeoQW0fQoP534Dg==",
"dependencies": {
"@kurkle/color": "^0.3.0"
},
"engines": {
"pnpm": ">=7"
}
}
}
}

@ -0,0 +1,5 @@
{
"dependencies": {
"chart.js": "^4.4.1"
}
}
Loading…
Cancel
Save