Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d03b943fcf | |||
| 9dc7bf6640 | |||
| 62ddd3cdc7 | |||
| 7b7a55534a | |||
| c6932cab66 | |||
| 9055087d00 | |||
| 36234a5256 | |||
| 78caabe3f1 | |||
| 691f55f9d0 |
@@ -1,4 +0,0 @@
|
||||
CINEMA_DB_HOST=dwarves.iut-fbleau.fr
|
||||
CINEMA_DB_USER=foo
|
||||
CINEMA_DB_PASSWORD=foo
|
||||
CINEMA_DB_NAME=foo
|
||||
@@ -328,4 +328,3 @@ TSWLatexianTemp*
|
||||
# Uncomment the next line to have this generated file ignored.
|
||||
#*Notes.bib
|
||||
|
||||
.env
|
||||
@@ -35,6 +35,8 @@ Les notions suivantes seront abordées :
|
||||
| 3 | [Intéractions avec le client](./cours/cm_interaction_client_serveur.pdf) | [tp2](./tp/tp2) |
|
||||
| 4 | [PHP/MySQL](./cours/cm_extension_mysqli.pdf) | [tp3](./tp/tp3) |
|
||||
| 5 | [Cookies et sessions](./cours/cm_cookies_sessions.pdf) | [tp3](./tp/tp3) , [tp4](./tp/tp4) |
|
||||
| 6 | [PHP Objet](./cours/cm_objet.pdf), [MVC avec codeigniter](./cours/cm_mvc.pdf) | [tp5](./tp/tp5) |
|
||||
| 7 | [securite](./cours/cm_securite.pdf) | |
|
||||
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,117 @@
|
||||
# SAE S2.02 : Consultation/modificaion d'une base de jeux vidéos
|
||||
|
||||
## Le thème
|
||||
|
||||
Le projet utilise une [base de données](./sql/game.sql.gz) de jeux vidéos (créée par
|
||||
Jérôme Cutrona, IUT de Reims). Il consiste à écrire une application web qui permet :
|
||||
|
||||
- la consultation/recherche d'informations contenues dans la bd (catégories, genres, jeux),
|
||||
- la création, édition, suppression d'un jeu.
|
||||
|
||||
La [base de données](./sql/game.sql.gz) a la structure suivante :
|
||||
<div align="center">
|
||||
<img src="./img/game.svg">
|
||||
</div>
|
||||
|
||||
## Principes généraux, fonctionnalités
|
||||
|
||||
1. La partie consultation permet l'accès à plusieurs vues :
|
||||
- liste d'ensemble des catégories et genres de jeux (sous forme de lien),
|
||||
- détails d'une catégorie et d'un genre avec la liste de ses jeux (sous forme de lien),
|
||||
- détails d'un jeu (les genres et catégories du jeu sont des liens).
|
||||
|
||||
2. La partie modification permet, pour un jeu :
|
||||
- l'édition (sans modification du poster)
|
||||
- la création (poster facultatif)
|
||||
- la suppression
|
||||
3. Tri des listes de jeux par titre ou par année
|
||||
4. fonction de recherche textuelle
|
||||
|
||||
## Contraintes de réalisations
|
||||
- Votre code utilisera codeigniter v3, exactement comme en TP.
|
||||
- Vous utiliserez le serveur de base de données mariaDB de l'iut, comme en TP.
|
||||
- Vous travaillerez seul, ou en binôme, à l'intérieur de votre **groupe de TP**.
|
||||
- Vous créerez un dépot GIT par monôme/binôme, avec le nom **sae_r301_grx** ($x\in\{12,34,56\}$) suivant votre groupe TP.
|
||||
Ulysse Jarnouen et Denis Monnerat seront collaborateurs.
|
||||
- Votre dépot contiendra un fichier README.md, avec :
|
||||
- le prénom, nom des membres du binômes
|
||||
- **l'url de votre site sur dwarves.iut-fbleau.fr**
|
||||
|
||||
## Usage de l'IA
|
||||
|
||||
### L'IA est autorisée mais ne remplace pas la compréhension
|
||||
|
||||
Le recours a l'IA peut être autorise comme outil d'assistance, au même titre qu'une documentation, un forum technique ou un IDE.
|
||||
En revanche :
|
||||
- tout code rendu doit être compris par l'étudiant;
|
||||
- tout code non expliqué ou non modifiable en situation sera considéré comme non acquis;
|
||||
- l'étudiant reste responsable de la qualité, de la sécurité et de la cohérence du code rendu.
|
||||
|
||||
## Règles communes concernant l'usage de l'IA
|
||||
|
||||
1. L'usage de l'IA est autorisé comme outil d'assistance.
|
||||
2. Tout code rendu doit pouvoir être expliqué et modifié par l'étudiant.
|
||||
3. Les propositions de l'IA doivent être relues, testées et adaptées.
|
||||
4. Un code non compris ou non maitrise pourra être considére comme non acquis.
|
||||
5. La transparence sur l'usage de l'IA est attendue dans le journal de bord, dans le dépôt et en soutenance.
|
||||
|
||||
Exemple de contenu attendu dans le journal sur la partie "Usage de l'IA":
|
||||
- les prompts utilisés;
|
||||
- les extraits de réponse juges utiles;
|
||||
- ce qui a été retenu, adapte ou rejeté;
|
||||
- les vérifications effectuées après usage.
|
||||
|
||||
## Organisation générale de l'évaluation
|
||||
|
||||
### Workflow de travail attendu
|
||||
|
||||
Afin de structurer le travail, de faciliter le suivi, le projet devra s'appuyer sur un workflow Git simple et obligatoire.
|
||||
|
||||
Pour chaque séance :
|
||||
|
||||
1. Vous devrez créer une branche de travail dédiée a la séance;
|
||||
2. Vous devrez pousser régulièrement vos modifications sur cette branche au cours de la séance ;
|
||||
3. en fin de séance, vous devrez ouvrir une "Pull Request" vers la branche cible définie (main) pour le projet;
|
||||
4. Vous devrez assigner cette Pull Request a l'enseignant;
|
||||
5. L'enseignant examinera et approuvera la Merge Request pour valider le travail réalisé ;
|
||||
6. une fois la Merge Request approuvée, vous pourrez procéder au merge.
|
||||
|
||||
> Il est recommandé que les messages de commit et les titres de Merge Request soient explicites et lies a l'objectif technique traité.
|
||||
|
||||
### Traces de progression
|
||||
|
||||
Voici une liste d'éléments qui prouveront votre progression :
|
||||
|
||||
- dépôt Git avec commits réguliers;
|
||||
- journal de bord court a chaque séance;
|
||||
- liste des taches réalisées et reste a faire;
|
||||
- tableau de répartition des responsabilités.
|
||||
|
||||
Le journal de bord doit suivre une structure simple et identique pour tous les groupes. Il peut rester concis, mais il doit être présent a chaque séance.
|
||||
Structure recommandée pour chaque séance :
|
||||
- objectif de la séance;
|
||||
- travail réalisé;
|
||||
- difficultés rencontrées;
|
||||
- décisions prises ;
|
||||
- travail de chacun dans le binôme;
|
||||
- points a reprendre a la séance suivante;
|
||||
- usage de l'IA, si applicable.
|
||||
|
||||
Le journal de bord doit être conservé dans un fichier Markdown (JOURNAL.md) du dépôt afin de rester consultable avec le reste des traces du projet.
|
||||
|
||||
## Évaluation
|
||||
|
||||
- L'avancement de votre travail sera mesuré à chaque fin de séance de TP (4 semaines).
|
||||
- Votre réalisation sera évalué la semaine du 15 juin.
|
||||
- Tout dépot avec quelques commits récents se verra fortement pénalisé.
|
||||
- Un coefficient multiplicateur de 0 à 1 sera appliqué pour refléter l'équilibre du travail entre les deux membres du binôme.
|
||||
|
||||
### La note ne repose pas uniquement sur le livrable final
|
||||
|
||||
Une application fonctionnelle ne suffit pas a prouver l'acquisition des compétences. L'évaluation reposera sur plusieurs types de preuves :
|
||||
- un livrable fonctionnel;
|
||||
- des traces de progression;
|
||||
- une explication orale individuelle;
|
||||
- une courte mise en situation technique en direct.
|
||||
|
||||
Quand le projet est réalisé en binôme, une partie de la portera sur le travail collectif. Chaque étudiant doit notamment être en mesure d'expliquer un extrait de code introduit ou modifié par son binôme.
|
||||
@@ -0,0 +1,108 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg
|
||||
PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg viewBox="125 35 1123 415" width="998px" height="380px" xmlns="http://www.w3.org/2000/svg" version="1.1">
|
||||
<line x1="600" y1="350" x2="590" y2="350" style="stroke:#333;stroke-width:1;"/>
|
||||
<line x1="508" y1="370" x2="498" y2="370" style="stroke:#333;stroke-width:1;"/>
|
||||
<line x1="590" y1="350" x2="508" y2="370" style="stroke:#333;stroke-width:1;"/>
|
||||
<line x1="592.5" y1="350" x2="596.03553390593" y2="353.53553390593" style="stroke:#333;stroke-width:2;"/>
|
||||
<line x1="592.5" y1="350" x2="596.03553390593" y2="346.46446609407" style="stroke:#333;stroke-width:2;"/>
|
||||
<line x1="503" y1="370" x2="506.53553390593" y2="373.53553390593" style="stroke:#333;stroke-width:2;"/>
|
||||
<line x1="503" y1="370" x2="506.53553390593" y2="366.46446609407" style="stroke:#333;stroke-width:2;"/>
|
||||
<line x1="726" y1="370" x2="736" y2="370" style="stroke:#333;stroke-width:1;"/>
|
||||
<line x1="790" y1="370" x2="800" y2="370" style="stroke:#333;stroke-width:1;"/>
|
||||
<line x1="736" y1="370" x2="790" y2="370" style="stroke:#333;stroke-width:1;"/>
|
||||
<line x1="733.5" y1="370" x2="729.96446609407" y2="373.53553390593" style="stroke:#333;stroke-width:2;"/>
|
||||
<line x1="733.5" y1="370" x2="729.96446609407" y2="366.46446609407" style="stroke:#333;stroke-width:2;"/>
|
||||
<line x1="795" y1="370" x2="791.46446609407" y2="373.53553390593" style="stroke:#333;stroke-width:2;"/>
|
||||
<line x1="795" y1="370" x2="791.46446609407" y2="366.46446609407" style="stroke:#333;stroke-width:2;"/>
|
||||
<line x1="370" y1="110" x2="360" y2="110" style="stroke:#0b0;stroke-width:1;"/>
|
||||
<line x1="238" y1="160" x2="228" y2="160" style="stroke:#0b0;stroke-width:1;"/>
|
||||
<line x1="360" y1="110" x2="238" y2="160" style="stroke:#0b0;stroke-width:1;"/>
|
||||
<line x1="362.5" y1="110" x2="366.03553390593" y2="113.53553390593" style="stroke:#0b0;stroke-width:2;"/>
|
||||
<line x1="362.5" y1="110" x2="366.03553390593" y2="106.46446609407" style="stroke:#0b0;stroke-width:2;"/>
|
||||
<line x1="233" y1="160" x2="236.53553390593" y2="163.53553390593" style="stroke:#0b0;stroke-width:2;"/>
|
||||
<line x1="233" y1="160" x2="236.53553390593" y2="156.46446609407" style="stroke:#0b0;stroke-width:2;"/>
|
||||
<line x1="483" y1="90" x2="493" y2="90" style="stroke:#bbb;stroke-width:1;"/>
|
||||
<line x1="590" y1="170" x2="600" y2="170" style="stroke:#bbb;stroke-width:1;"/>
|
||||
<line x1="493" y1="90" x2="590" y2="170" style="stroke:#bbb;stroke-width:1;"/>
|
||||
<line x1="490.5" y1="90" x2="486.96446609407" y2="93.535533905933" style="stroke:#bbb;stroke-width:2;"/>
|
||||
<line x1="490.5" y1="90" x2="486.96446609407" y2="86.464466094067" style="stroke:#bbb;stroke-width:2;"/>
|
||||
<line x1="595" y1="170" x2="591.46446609407" y2="173.53553390593" style="stroke:#bbb;stroke-width:2;"/>
|
||||
<line x1="595" y1="170" x2="591.46446609407" y2="166.46446609407" style="stroke:#bbb;stroke-width:2;"/>
|
||||
<line x1="810" y1="80" x2="800" y2="80" style="stroke:#bbb;stroke-width:1;"/>
|
||||
<line x1="736" y1="170" x2="726" y2="170" style="stroke:#bbb;stroke-width:1;"/>
|
||||
<line x1="800" y1="80" x2="736" y2="170" style="stroke:#bbb;stroke-width:1;"/>
|
||||
<line x1="802.5" y1="80" x2="806.03553390593" y2="83.535533905933" style="stroke:#bbb;stroke-width:2;"/>
|
||||
<line x1="802.5" y1="80" x2="806.03553390593" y2="76.464466094067" style="stroke:#bbb;stroke-width:2;"/>
|
||||
<line x1="731" y1="170" x2="734.53553390593" y2="173.53553390593" style="stroke:#bbb;stroke-width:2;"/>
|
||||
<line x1="731" y1="170" x2="734.53553390593" y2="166.46446609407" style="stroke:#bbb;stroke-width:2;"/>
|
||||
<line x1="902" y1="100" x2="912" y2="100" style="stroke:#bbb;stroke-width:1;"/>
|
||||
<line x1="1010" y1="180" x2="1020" y2="180" style="stroke:#bbb;stroke-width:1;"/>
|
||||
<line x1="912" y1="100" x2="1010" y2="180" style="stroke:#bbb;stroke-width:1;"/>
|
||||
<line x1="909.5" y1="100" x2="905.96446609407" y2="103.53553390593" style="stroke:#bbb;stroke-width:2;"/>
|
||||
<line x1="909.5" y1="100" x2="905.96446609407" y2="96.464466094067" style="stroke:#bbb;stroke-width:2;"/>
|
||||
<line x1="1015" y1="180" x2="1011.4644660941" y2="183.53553390593" style="stroke:#bbb;stroke-width:2;"/>
|
||||
<line x1="1015" y1="180" x2="1011.4644660941" y2="176.46446609407" style="stroke:#bbb;stroke-width:2;"/>
|
||||
<rect width="88" height="20" x="140" y="130" style="fill:#007;stroke:black;"/>
|
||||
<text width="88" height="20" x="145" y="144" style="fill:#fff;" font-family="Arial" font-size="16px"> category</text>
|
||||
<rect width="88" height="20" x="140" y="150" style="fill:#aea;stroke:black;"/>
|
||||
<text width="88" height="20" x="145" y="164" style="fill:black;" font-family="Arial" font-size="16px">id</text>
|
||||
<rect width="88" height="20" x="140" y="170" style="fill:none;stroke:black;"/>
|
||||
<text width="88" height="20" x="145" y="184" style="fill:black;" font-family="Arial" font-size="16px">description</text>
|
||||
<rect width="78" height="20" x="420" y="340" style="fill:#007;stroke:black;"/>
|
||||
<text width="78" height="20" x="425" y="354" style="fill:#fff;" font-family="Arial" font-size="16px"> developer</text>
|
||||
<rect width="78" height="20" x="420" y="360" style="fill:#aea;stroke:black;"/>
|
||||
<text width="78" height="20" x="425" y="374" style="fill:black;" font-family="Arial" font-size="16px">id</text>
|
||||
<rect width="78" height="20" x="420" y="380" style="fill:none;stroke:black;"/>
|
||||
<text width="78" height="20" x="425" y="394" style="fill:black;" font-family="Arial" font-size="16px">name</text>
|
||||
<rect width="126" height="20" x="600" y="140" style="fill:#007;stroke:black;"/>
|
||||
<text width="126" height="20" x="605" y="154" style="fill:#fff;" font-family="Arial" font-size="16px"> game</text>
|
||||
<rect width="126" height="20" x="600" y="160" style="fill:#aea;stroke:black;"/>
|
||||
<text width="126" height="20" x="605" y="174" style="fill:black;" font-family="Arial" font-size="16px">id</text>
|
||||
<rect width="126" height="20" x="600" y="180" style="fill:none;stroke:black;"/>
|
||||
<text width="126" height="20" x="605" y="194" style="fill:black;" font-family="Arial" font-size="16px">name</text>
|
||||
<rect width="126" height="20" x="600" y="200" style="fill:none;stroke:black;"/>
|
||||
<text width="126" height="20" x="605" y="214" style="fill:black;" font-family="Arial" font-size="16px">releaseYear</text>
|
||||
<rect width="126" height="20" x="600" y="220" style="fill:none;stroke:black;"/>
|
||||
<text width="126" height="20" x="605" y="234" style="fill:black;" font-family="Arial" font-size="16px">shortDescription</text>
|
||||
<rect width="126" height="20" x="600" y="240" style="fill:none;stroke:black;"/>
|
||||
<text width="126" height="20" x="605" y="254" style="fill:black;" font-family="Arial" font-size="16px">price</text>
|
||||
<rect width="126" height="20" x="600" y="260" style="fill:none;stroke:black;"/>
|
||||
<text width="126" height="20" x="605" y="274" style="fill:black;" font-family="Arial" font-size="16px">windows</text>
|
||||
<rect width="126" height="20" x="600" y="280" style="fill:none;stroke:black;"/>
|
||||
<text width="126" height="20" x="605" y="294" style="fill:black;" font-family="Arial" font-size="16px">linux</text>
|
||||
<rect width="126" height="20" x="600" y="300" style="fill:none;stroke:black;"/>
|
||||
<text width="126" height="20" x="605" y="314" style="fill:black;" font-family="Arial" font-size="16px">mac</text>
|
||||
<rect width="126" height="20" x="600" y="320" style="fill:none;stroke:black;"/>
|
||||
<text width="126" height="20" x="605" y="334" style="fill:black;" font-family="Arial" font-size="16px">metacritic</text>
|
||||
<rect width="126" height="20" x="600" y="340" style="fill:none;stroke:black;"/>
|
||||
<text width="126" height="20" x="605" y="354" style="fill:black;" font-family="Arial" font-size="16px">developerId</text>
|
||||
<rect width="126" height="20" x="600" y="360" style="fill:none;stroke:black;"/>
|
||||
<text width="126" height="20" x="605" y="374" style="fill:black;" font-family="Arial" font-size="16px">posterId</text>
|
||||
<rect width="113" height="20" x="370" y="60" style="fill:#007;stroke:black;"/>
|
||||
<text width="113" height="20" x="375" y="74" style="fill:#fff;" font-family="Arial" font-size="16px"> game_category</text>
|
||||
<rect width="113" height="20" x="370" y="80" style="fill:#aea;stroke:black;"/>
|
||||
<text width="113" height="20" x="375" y="94" style="fill:black;" font-family="Arial" font-size="16px">gameId</text>
|
||||
<rect width="113" height="20" x="370" y="100" style="fill:#aea;stroke:black;"/>
|
||||
<text width="113" height="20" x="375" y="114" style="fill:black;" font-family="Arial" font-size="16px">categoryId</text>
|
||||
<rect width="92" height="20" x="810" y="50" style="fill:#007;stroke:black;"/>
|
||||
<text width="92" height="20" x="815" y="64" style="fill:#fff;" font-family="Arial" font-size="16px"> game_genre</text>
|
||||
<rect width="92" height="20" x="810" y="70" style="fill:#aea;stroke:black;"/>
|
||||
<text width="92" height="20" x="815" y="84" style="fill:black;" font-family="Arial" font-size="16px">gameId</text>
|
||||
<rect width="92" height="20" x="810" y="90" style="fill:#aea;stroke:black;"/>
|
||||
<text width="92" height="20" x="815" y="104" style="fill:black;" font-family="Arial" font-size="16px">genreId</text>
|
||||
<rect width="88" height="20" x="1020" y="150" style="fill:#007;stroke:black;"/>
|
||||
<text width="88" height="20" x="1025" y="164" style="fill:#fff;" font-family="Arial" font-size="16px"> genre</text>
|
||||
<rect width="88" height="20" x="1020" y="170" style="fill:#aea;stroke:black;"/>
|
||||
<text width="88" height="20" x="1025" y="184" style="fill:black;" font-family="Arial" font-size="16px">id</text>
|
||||
<rect width="88" height="20" x="1020" y="190" style="fill:none;stroke:black;"/>
|
||||
<text width="88" height="20" x="1025" y="204" style="fill:black;" font-family="Arial" font-size="16px">description</text>
|
||||
<rect width="54" height="20" x="800" y="340" style="fill:#007;stroke:black;"/>
|
||||
<text width="54" height="20" x="805" y="354" style="fill:#fff;" font-family="Arial" font-size="16px"> poster</text>
|
||||
<rect width="54" height="20" x="800" y="360" style="fill:#aea;stroke:black;"/>
|
||||
<text width="54" height="20" x="805" y="374" style="fill:black;" font-family="Arial" font-size="16px">id</text>
|
||||
<rect width="54" height="20" x="800" y="380" style="fill:none;stroke:black;"/>
|
||||
<text width="54" height="20" x="805" y="394" style="fill:black;" font-family="Arial" font-size="16px">jpeg</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 10 KiB |
Binary file not shown.
@@ -19,14 +19,6 @@ SET time_zone = "+00:00";
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `user` (
|
||||
login VARCHAR(50) NOT NULL,
|
||||
email VARCHAR(255) NOT NULL,
|
||||
password VARCHAR(255) NOT NULL,
|
||||
PRIMARY KEY (login)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
|
||||
--
|
||||
-- Table structure for table `Artiste`
|
||||
--
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
<?php
|
||||
$login = isset($_GET['login']) ? trim($_GET['login']) : '';
|
||||
$error = isset($_GET['error']);
|
||||
$registered = isset($_GET['registered']);
|
||||
$loggedOut = isset($_GET['logged_out']);
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Authentification</title>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css"
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
<main class="container">
|
||||
<h1>Authentification</h1>
|
||||
|
||||
<?php if ($registered) { ?>
|
||||
<article>Inscription réussie. Vous pouvez maintenant vous connecter.</article>
|
||||
<?php } ?>
|
||||
|
||||
<?php if ($loggedOut) { ?>
|
||||
<article>Vous avez été déconnecté.</article>
|
||||
<?php } ?>
|
||||
|
||||
<?php if ($error) { ?>
|
||||
<article aria-invalid="true">Login ou mot de passe incorrect.</article>
|
||||
<?php } ?>
|
||||
|
||||
<form action="./verification.php" method="post">
|
||||
<label for="login">Login</label>
|
||||
<input id="login" name="login" value="<?php echo htmlspecialchars($login, ENT_QUOTES); ?>">
|
||||
|
||||
<label for="password">Mot de passe</label>
|
||||
<input id="password" name="password" type="password">
|
||||
|
||||
<button type="submit">Se connecter</button>
|
||||
</form>
|
||||
|
||||
<p><a href="./inscription.php">Créer un compte</a></p>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,14 +0,0 @@
|
||||
<?php
|
||||
session_start();
|
||||
|
||||
$_SESSION = array();
|
||||
|
||||
if (ini_get('session.use_cookies')) {
|
||||
$params = session_get_cookie_params();
|
||||
setcookie(session_name(), '', time() - 3600, $params['path'], $params['domain'], $params['secure'], $params['httponly']);
|
||||
}
|
||||
|
||||
session_destroy();
|
||||
|
||||
header('Location: ./authentification.php?logged_out=1');
|
||||
exit;
|
||||
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
include_once './securite.php';
|
||||
include_once './modeles/modeleFilms.php';
|
||||
|
||||
$currentPage = filter_input(
|
||||
@@ -29,7 +28,7 @@ if ($currentPage > $totalPages && $totalFilms > 0) {
|
||||
}
|
||||
|
||||
//
|
||||
// On charge les fichiers de vue une fois les données prêtes.
|
||||
// on "charge" la vue
|
||||
//
|
||||
|
||||
include_once './vues/header.php';
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
<?php
|
||||
session_start();
|
||||
|
||||
include_once './modeles/modeleUtilisateurs.php';
|
||||
|
||||
$errors = array();
|
||||
$values = array(
|
||||
'login' => '',
|
||||
'email' => '',
|
||||
);
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$values['login'] = isset($_POST['login']) ? trim($_POST['login']) : '';
|
||||
$values['email'] = isset($_POST['email']) ? trim($_POST['email']) : '';
|
||||
$password = isset($_POST['password']) ? $_POST['password'] : '';
|
||||
|
||||
// On valide champ par champ pour pouvoir réafficher proprement le formulaire.
|
||||
if ($values['login'] === '') {
|
||||
$errors['login'] = 'Le login est obligatoire.';
|
||||
} elseif (!preg_match('/^[a-zA-Z0-9_-]{3,30}$/', $values['login'])) {
|
||||
$errors['login'] = 'Le login doit contenir entre 3 et 30 caractères alphanumériques, _ ou -.';
|
||||
}
|
||||
|
||||
if ($values['email'] === '') {
|
||||
$errors['email'] = 'L\'email est obligatoire.';
|
||||
} elseif (!filter_var($values['email'], FILTER_VALIDATE_EMAIL)) {
|
||||
$errors['email'] = 'Le format de l\'email est invalide.';
|
||||
}
|
||||
|
||||
if ($password === '') {
|
||||
$errors['password'] = 'Le mot de passe est obligatoire.';
|
||||
} elseif (strlen($password) < 8) {
|
||||
$errors['password'] = 'Le mot de passe doit contenir au moins 8 caractères.';
|
||||
}
|
||||
|
||||
if ($values['login'] !== '' && findUserByLogin($values['login']) !== null) {
|
||||
$errors['login'] = 'Ce login est déjà utilisé.';
|
||||
}
|
||||
|
||||
if (empty($errors)) {
|
||||
$passwordHash = password_hash($password, PASSWORD_DEFAULT);
|
||||
createUser($values['login'], $values['email'], $passwordHash);
|
||||
|
||||
header('Location: ./authentification.php?registered=1');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Inscription</title>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css"
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
<main class="container">
|
||||
<h1>Inscription</h1>
|
||||
<p>Créez un compte avant d'accéder aux pages du site.</p>
|
||||
|
||||
<form method="post">
|
||||
<label for="login">Login</label>
|
||||
<input
|
||||
id="login"
|
||||
name="login"
|
||||
value="<?php echo htmlspecialchars($values['login'], ENT_QUOTES); ?>"
|
||||
>
|
||||
<?php if (isset($errors['login'])) { ?>
|
||||
<small><?php echo htmlspecialchars($errors['login'], ENT_QUOTES); ?></small>
|
||||
<?php } ?>
|
||||
|
||||
<label for="email">Email</label>
|
||||
<input
|
||||
id="email"
|
||||
name="email"
|
||||
type="email"
|
||||
value="<?php echo htmlspecialchars($values['email'], ENT_QUOTES); ?>"
|
||||
>
|
||||
<?php if (isset($errors['email'])) { ?>
|
||||
<small><?php echo htmlspecialchars($errors['email'], ENT_QUOTES); ?></small>
|
||||
<?php } ?>
|
||||
|
||||
<label for="password">Mot de passe</label>
|
||||
<input id="password" name="password" type="password">
|
||||
<?php if (isset($errors['password'])) { ?>
|
||||
<small><?php echo htmlspecialchars($errors['password'], ENT_QUOTES); ?></small>
|
||||
<?php } ?>
|
||||
|
||||
<button type="submit">S'inscrire</button>
|
||||
</form>
|
||||
|
||||
<p><a href="./authentification.php">Déjà inscrit ? Se connecter</a></p>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,32 +0,0 @@
|
||||
<?php
|
||||
function getConnection()
|
||||
{
|
||||
static $conn = null;
|
||||
|
||||
if ($conn !== null) {
|
||||
return $conn;
|
||||
}
|
||||
|
||||
// On autorise deux modes de configuration :
|
||||
// 1) via des variables d'environnement ;
|
||||
// 2) en remplaçant directement les valeurs par votre login/mot de passe.
|
||||
$host = getenv('DB_HOST');
|
||||
$user = getenv('DB_USER');
|
||||
$password = getenv('DB_PASSWORD');
|
||||
$database = getenv('DB_NAME');
|
||||
|
||||
if ($user === '' || $database === '') {
|
||||
die(
|
||||
"Configurez d'abord l'accès MySQL dans modeles/connexion.php " .
|
||||
"ou via les variables d'environnement CINEMA_DB_HOST, CINEMA_DB_USER, CINEMA_DB_PASSWORD et CINEMA_DB_NAME."
|
||||
);
|
||||
}
|
||||
$conn = mysqli_connect($host, $user, $password, $database, 3306);
|
||||
if ($conn === false) {
|
||||
die('Connexion MySQL impossible : ' . mysqli_connect_error());
|
||||
}
|
||||
|
||||
mysqli_set_charset($conn, 'utf8mb4');
|
||||
|
||||
return $conn;
|
||||
}
|
||||
@@ -1,5 +1,22 @@
|
||||
<?php
|
||||
include_once __DIR__ . '/connexion.php';
|
||||
function getConnection()
|
||||
{
|
||||
static $conn = null;
|
||||
|
||||
if ($conn === null) {
|
||||
$host = getenv('DB_HOST') ?: 'https://dwarves.iut-fbleau.fr';
|
||||
$login = getenv('DB_USER') ?: getenv('USER') ?: getenv('USERNAME') ?: 'root';
|
||||
$password = getenv('DB_PASSWORD') ?: $login;
|
||||
$database = getenv('DB_NAME') ?: $login;
|
||||
$conn = mysqli_connect($host, $login, $password, $database);
|
||||
|
||||
if ($conn !== false) {
|
||||
mysqli_set_charset($conn, 'utf8mb4');
|
||||
}
|
||||
}
|
||||
|
||||
return $conn;
|
||||
}
|
||||
|
||||
function getFilms($page = 1, $perPage = 10)
|
||||
{
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
<?php
|
||||
include_once __DIR__ . '/connexion.php';
|
||||
|
||||
function findUserByLogin($login)
|
||||
{
|
||||
$conn = getConnection();
|
||||
$stmt = mysqli_prepare($conn, 'SELECT login, email, password FROM `user` WHERE login = ?');
|
||||
if ($stmt === false) {
|
||||
die('Préparation SQL impossible : ' . mysqli_error($conn));
|
||||
}
|
||||
|
||||
mysqli_stmt_bind_param($stmt, 's', $login);
|
||||
mysqli_stmt_execute($stmt);
|
||||
mysqli_stmt_bind_result($stmt, $dbLogin, $dbEmail, $dbPassword);
|
||||
|
||||
$user = null;
|
||||
if (mysqli_stmt_fetch($stmt)) {
|
||||
$user = array(
|
||||
'login' => $dbLogin,
|
||||
'email' => $dbEmail,
|
||||
'password' => $dbPassword,
|
||||
);
|
||||
}
|
||||
|
||||
mysqli_stmt_close($stmt);
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
function createUser($login, $email, $passwordHash)
|
||||
{
|
||||
$conn = getConnection();
|
||||
$stmt = mysqli_prepare($conn, 'INSERT INTO `user` (login, email, password) VALUES (?, ?, ?)');
|
||||
if ($stmt === false) {
|
||||
die('Préparation SQL impossible : ' . mysqli_error($conn));
|
||||
}
|
||||
|
||||
mysqli_stmt_bind_param($stmt, 'sss', $login, $email, $passwordHash);
|
||||
$success = mysqli_stmt_execute($stmt);
|
||||
$errorCode = mysqli_errno($conn);
|
||||
mysqli_stmt_close($stmt);
|
||||
|
||||
// 1062 = violation de clé unique (login déjà pris).
|
||||
if (!$success && $errorCode === 1062) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$success) {
|
||||
die('Insertion SQL impossible : ' . mysqli_error($conn));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
<?php
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
// Ce fichier est inclus en tête de chaque page protégée.
|
||||
// Si l'utilisateur n'est pas connecté, on le renvoie vers le formulaire.
|
||||
if (!isset($_SESSION['user_login'])) {
|
||||
header('Location: ./authentification.php');
|
||||
exit;
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<?php
|
||||
session_start();
|
||||
|
||||
include_once './modeles/modeleUtilisateurs.php';
|
||||
|
||||
$login = isset($_POST['login']) ? trim($_POST['login']) : '';
|
||||
$password = isset($_POST['password']) ? $_POST['password'] : '';
|
||||
|
||||
// Cette temporisation ralentit volontairement les tentatives répétées,
|
||||
// ce qui rend les attaques par force brute moins efficaces.
|
||||
usleep(500000);
|
||||
|
||||
if ($login === '' || $password === '') {
|
||||
header('Location: ./authentification.php?error=1&login=' . urlencode($login));
|
||||
exit;
|
||||
}
|
||||
|
||||
$user = findUserByLogin($login);
|
||||
|
||||
if ($user === null) {
|
||||
header('Location: ./authentification.php?error=1&login=' . urlencode($login));
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!password_verify($password, $user['password'])) {
|
||||
header('Location: ./authentification.php?error=1&login=' . urlencode($login));
|
||||
exit;
|
||||
}
|
||||
|
||||
session_regenerate_id(true);
|
||||
$_SESSION['user_login'] = $user['login'];
|
||||
$_SESSION['user_email'] = $user['email'];
|
||||
|
||||
header('Location: ./films.php');
|
||||
exit;
|
||||
@@ -1,24 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Films</title>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css"
|
||||
/>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Films</title>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css"
|
||||
/>
|
||||
|
||||
<link rel="stylesheet" href="./css/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<main class="container">
|
||||
<nav>
|
||||
<ul>
|
||||
<li><strong>Cinema</strong></li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="./films.php">Films</a></li>
|
||||
<li>Connecté : <?php echo htmlspecialchars(isset($_SESSION['user_login']) ? $_SESSION['user_login'] : 'inconnu', ENT_QUOTES); ?></li>
|
||||
<li><a href="./deconnexion.php">Déconnexion</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<link rel="stylesheet" href="./css/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<main class="container">
|
||||
|
||||
@@ -1,27 +1,6 @@
|
||||
<?php
|
||||
// Les valeurs autorisées servent à la fois pour la validation
|
||||
// du formulaire et pour l'affichage dans la vue.
|
||||
$osSet = [
|
||||
'linux' => 'Linux',
|
||||
'windows' => 'Windows',
|
||||
'apple' => 'MacOS',
|
||||
];
|
||||
$osSet = ['linux','apple','windows'];
|
||||
$os = "linux";
|
||||
|
||||
$cookieName = 'preferred_os';
|
||||
$os = 'linux';
|
||||
|
||||
// Si le formulaire est soumis, on valide la valeur reçue avant
|
||||
// de l'enregistrer dans un cookie valable 60 secondes.
|
||||
if (isset($_POST['os']) && array_key_exists($_POST['os'], $osSet)) {
|
||||
$os = $_POST['os'];
|
||||
setcookie($cookieName, $os, time() + 60);
|
||||
|
||||
// On met aussi $_COOKIE à jour pour refléter immédiatement le choix
|
||||
// sans attendre le rechargement suivant du navigateur.
|
||||
$_COOKIE[$cookieName] = $os;
|
||||
} elseif (isset($_COOKIE[$cookieName]) && array_key_exists($_COOKIE[$cookieName], $osSet)) {
|
||||
// En l'absence de soumission, on relit la préférence mémorisée.
|
||||
$os = $_COOKIE[$cookieName];
|
||||
}
|
||||
|
||||
include_once './views/main.php';
|
||||
include './views/main.php';
|
||||
?>
|
||||
|
||||
@@ -1,50 +1,44 @@
|
||||
<!doctype html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Cookie OS préféré</title>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css"
|
||||
/>
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<main class="container">
|
||||
<form method="POST">
|
||||
<fieldset class="grid">
|
||||
<legend>Changez votre os</legend>
|
||||
<?php foreach ($osSet as $value => $label) { ?>
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
name="os"
|
||||
value="<?php echo htmlspecialchars($value, ENT_QUOTES); ?>"
|
||||
<?php echo $os === $value ? 'checked' : ''; ?>
|
||||
>
|
||||
<i class="fa fa-<?php echo htmlspecialchars($value, ENT_QUOTES); ?> fa-2x" aria-hidden="true"></i>
|
||||
<?php echo htmlspecialchars($label, ENT_QUOTES); ?>
|
||||
</label>
|
||||
<?php } ?>
|
||||
</fieldset>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css"
|
||||
/>
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||
|
||||
<button type="submit">Envoyer</button>
|
||||
</form>
|
||||
<article>
|
||||
<header>Votre os</header>
|
||||
<p>
|
||||
<!-- On affiche l'icône et le nom de l'OS courant. -->
|
||||
<i class="fa fa-<?php echo htmlspecialchars($os, ENT_QUOTES); ?> fa-5x" aria-hidden="true"></i>
|
||||
</p>
|
||||
<p><?php echo htmlspecialchars($osSet[$os], ENT_QUOTES); ?></p>
|
||||
<footer>
|
||||
Rafraîchir la page
|
||||
<a href="./" aria-label="Rafraîchir la page">
|
||||
<i class="fa fa-refresh" aria-hidden="true"></i>
|
||||
</a>
|
||||
</footer>
|
||||
</article>
|
||||
</main>
|
||||
</body>
|
||||
</head>
|
||||
<body>
|
||||
<main class="container">
|
||||
<form method="POST">
|
||||
<fieldset class="grid">
|
||||
<legend>Changez votre os</legend>
|
||||
<label>
|
||||
<input type="radio" name="os" value="linux">
|
||||
<i class="fa fa-linux fa-2x" aria-hidden="true"></i>
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="os" value="windows">
|
||||
<i class="fa fa-windows fa-2x" aria-hidden="true"></i>
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="os" value="apple">
|
||||
<i class="fa fa-apple fa-2x" aria-hidden="true"></i>
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
<button type="submit">Envoyer</button>
|
||||
</form>
|
||||
<article>
|
||||
<header>Votre os</header>
|
||||
<?php echo "<i class='fa fa-$os fa-5x'></i>";?>
|
||||
<footer>
|
||||
Rafraîchir la page <a href=""><i class="fa fa-refresh" aria-hidden="true"></i></a>
|
||||
</footer>
|
||||
</article>
|
||||
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -1,83 +1,54 @@
|
||||
<?php
|
||||
function initializeGame()
|
||||
{
|
||||
// Une grille vide contient 9 cases valant 0.
|
||||
$_SESSION['grid'] = array_fill(0, 9, 0);
|
||||
$_SESSION['playerTurn'] = 1;
|
||||
}
|
||||
|
||||
function nextPlayer($player)
|
||||
{
|
||||
return $player === 1 ? 2 : 1;
|
||||
}
|
||||
|
||||
function isWinner($grid, $player)
|
||||
{
|
||||
$winStates = array(
|
||||
array(0, 1, 2), array(3, 4, 5), array(6, 7, 8),
|
||||
array(0, 3, 6), array(1, 4, 7), array(2, 5, 8),
|
||||
array(0, 4, 8), array(2, 4, 6)
|
||||
);
|
||||
$winStates = array
|
||||
(
|
||||
array(0, 1, 2), array(3, 4, 5), array(6, 7, 8), // Horizontal
|
||||
array(0, 3, 6), array(1, 4, 7), array(2, 5, 8), // Vertical
|
||||
array(0, 4, 8), array(2, 4, 6) // Diagonal
|
||||
);
|
||||
|
||||
foreach ($winStates as $winState) {
|
||||
if (
|
||||
$grid[$winState[0]] == $player &&
|
||||
foreach ($winStates as $winState)
|
||||
{
|
||||
if ($grid[$winState[0]] == $player &&
|
||||
$grid[$winState[1]] == $player &&
|
||||
$grid[$winState[2]] == $player
|
||||
) {
|
||||
$grid[$winState[2]] == $player)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function noWinner($grid)
|
||||
{
|
||||
for ($i = 0; $i < 9; $i++) {
|
||||
if ($grid[$i] == 0) {
|
||||
for($i = 0; $i < 9; $i++)
|
||||
if ($grid[$i] == 0)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function getWinner($grid)
|
||||
{
|
||||
if (isWinner($grid, 1)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (isWinner($grid, 2)) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
function displayGrid($grid, $isInteractive = true)
|
||||
function displayGrid($grid)
|
||||
{
|
||||
echo '<table class="morpion">';
|
||||
for ($i = 0; $i < 3; $i++) {
|
||||
echo '<tr>';
|
||||
for ($j = 0; $j < 3; $j++) {
|
||||
echo '<td>';
|
||||
for ($i = 0; $i < 3; $i ++){
|
||||
echo "<tr>";
|
||||
for ($j = 0; $j < 3; $j ++){
|
||||
|
||||
$pos = 3 * $i + $j;
|
||||
if ($grid[$pos] == 0 && $isInteractive) {
|
||||
echo "<td>";
|
||||
|
||||
$pos = 3*$i + $j;
|
||||
if ($grid[$pos] == 0)
|
||||
echo "<a href='?pos=$pos'></a>";
|
||||
}
|
||||
if ($grid[$pos] == 1) {
|
||||
if ($grid[$pos] == 1)
|
||||
echo '<i class="fa fa-times" aria-hidden="true"></i>';
|
||||
}
|
||||
if ($grid[$pos] == 2) {
|
||||
if ($grid[$pos] == 2)
|
||||
echo '<i class="fa fa-circle-o" aria-hidden="true"></i>';
|
||||
}
|
||||
|
||||
echo '</td>';
|
||||
echo "</td>";
|
||||
}
|
||||
echo '</tr>';
|
||||
echo "</tr>";
|
||||
}
|
||||
echo '</table>';
|
||||
echo "</table>";
|
||||
}
|
||||
|
||||
@@ -1,70 +1,11 @@
|
||||
<?php
|
||||
session_start();
|
||||
include 'helpers.php';
|
||||
|
||||
include_once 'helpers.php';
|
||||
// view variables
|
||||
$message = "";
|
||||
$grid = [0,1,0,1,0,2,2,0,0];
|
||||
$playerTurn = 1; // 1 or 2
|
||||
|
||||
// Si on demande une nouvelle partie, on réinitialise l'état stocké
|
||||
// en session puis on recharge la page sans paramètre.
|
||||
if (isset($_GET['reset'])) {
|
||||
initializeGame();
|
||||
header('Location: .');
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!isset($_SESSION['grid']) || !isset($_SESSION['playerTurn'])) {
|
||||
initializeGame();
|
||||
}
|
||||
|
||||
// Variables transmises à la vue.
|
||||
$message = '';
|
||||
$grid = $_SESSION['grid'];
|
||||
$playerTurn = (int) $_SESSION['playerTurn'];
|
||||
|
||||
$winner = getWinner($grid);
|
||||
$isGameOver = $winner !== 0 || noWinner($grid);
|
||||
|
||||
// On joue uniquement si la partie est encore en cours.
|
||||
if (!$isGameOver && isset($_GET['pos'])) {
|
||||
$pos = filter_input(
|
||||
INPUT_GET,
|
||||
'pos',
|
||||
FILTER_VALIDATE_INT,
|
||||
array('options' => array('min_range' => 0, 'max_range' => 8))
|
||||
);
|
||||
|
||||
if ($pos === false || $pos === null) {
|
||||
$message = 'Coup invalide.';
|
||||
} elseif ($grid[$pos] !== 0) {
|
||||
$message = 'Cette case est déjà occupée.';
|
||||
} else {
|
||||
// On enregistre le coup du joueur courant dans la grille.
|
||||
$grid[$pos] = $playerTurn;
|
||||
|
||||
if (isWinner($grid, $playerTurn)) {
|
||||
$message = "Le joueur $playerTurn gagne la partie.";
|
||||
} elseif (noWinner($grid)) {
|
||||
$message = 'Match nul.';
|
||||
} else {
|
||||
$playerTurn = nextPlayer($playerTurn);
|
||||
}
|
||||
|
||||
$_SESSION['grid'] = $grid;
|
||||
$_SESSION['playerTurn'] = $playerTurn;
|
||||
}
|
||||
|
||||
$winner = getWinner($grid);
|
||||
$isGameOver = $winner !== 0 || noWinner($grid);
|
||||
}
|
||||
|
||||
// Si la page est simplement rafraîchie, on recalcule un message cohérent
|
||||
// à partir de l'état stocké en session.
|
||||
if ($message === '') {
|
||||
if ($winner !== 0) {
|
||||
$message = "Le joueur $winner gagne la partie.";
|
||||
} elseif (noWinner($grid)) {
|
||||
$message = 'Match nul.';
|
||||
}
|
||||
}
|
||||
|
||||
include_once './views/tictactoe.php';
|
||||
include './views/tictactoe.php';
|
||||
|
||||
|
||||
@@ -1,35 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Tic Tac Toe</title>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css"
|
||||
/>
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css"
|
||||
/>
|
||||
<link rel="stylesheet" href="./css/style.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<main class="container center">
|
||||
<h4>
|
||||
<?php if ($isGameOver) { ?>
|
||||
Partie terminée
|
||||
<?php } else { ?>
|
||||
Tic Tac Toe : joueur <?php echo $playerTurn; ?> à vous de jouer
|
||||
<?php } ?>
|
||||
</h4>
|
||||
<h4>Tic Tac Toe : <?php echo "player $playerTurn turn";?></h4>
|
||||
<?php
|
||||
// Quand la partie est finie, les liens dans les cases vides
|
||||
// disparaissent pour empêcher tout coup supplémentaire.
|
||||
displayGrid($grid, !$isGameOver);
|
||||
displayGrid($grid);
|
||||
|
||||
if ($message != '') {
|
||||
echo '<h5>' . htmlspecialchars($message, ENT_QUOTES) . " <a href='?reset=1'>nouvelle partie</a></h5>";
|
||||
} else {
|
||||
echo "<p><a href='?reset=1'>Recommencer la partie</a></p>";
|
||||
}
|
||||
?>
|
||||
if ($message != "")
|
||||
echo "<h5>$message <a href='.'>new game</a></h5>";
|
||||
?>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
|
||||
# TP5 : prise en main de codeigniter
|
||||
|
||||
## Installation
|
||||
Téléchargez les sources de [codeigniter v3](https://github.com/pocketarc/codeigniter) (il s'agit d'un fork qui évite certains
|
||||
porblèmes de compatibilité avec des versions récentes de php), et placez les dans votre
|
||||
`public_html`.
|
||||
|
||||
1. Importez dans votre base de données la table [todo.sql](src/sql/todo.sql)
|
||||
2. Copiez le repertoire [assets](src/assets) à la racine de votre application.
|
||||
3. Copiez les [contrôleurs](src/ci), [modèles](src/ci) et [vues](src/ci) dans votre application.
|
||||
4. Configurez les paramètres nécessaires à codeigniter :
|
||||
- `config/config.php`
|
||||
- `config/database.php`
|
||||
|
||||
```php
|
||||
$config['base_url']='/~login/chemin/vers/codeigniter';
|
||||
```
|
||||
Vous devriez obtenir une application `todolist` fonctionnelle à l'url :
|
||||
```
|
||||
https://dwarves.iut-fbleau.fr/~login/chemin/vers/codeigniter/index.php/todo
|
||||
```
|
||||
|
||||

|
||||
|
||||
## Suppression des tâches
|
||||
Modifiez le code pour la suppression des tâches.
|
||||
|
||||
## Edition des tâches
|
||||
Modifiez le code (contrôleur et modèle) pour l'édition des tâches.
|
||||
|
||||
## Tri de la todolist
|
||||
Ajoutez la possibilité de trier la todolist par ordre (croissant/décroissant) alphabètique
|
||||
## Créer sa propre classe controller
|
||||
Il est possible de redefinir, ou d'étendre les classes systèmes dans votre répertoire `application/core`. Par exemple, pour étendre la classe
|
||||
controller de codeigniter, vous pouvez écrire votre propre classe `MY_Controller.php`
|
||||
```php
|
||||
class MY_Controller extends CI_Controller {
|
||||
}
|
||||
```
|
||||
|
||||
Utilisez ce moyen pour définir une nouvelle méthode render, qui permet d'utiliser un layout quelconque pour afficher une vue.
|
||||
## Création de compte
|
||||
|
||||
1. Ajoutez dans votre de base de données une table `user`, qui permettra de stocker des utilisateurs.
|
||||
attributs : nom, prenom, email (clé primaire), password.
|
||||
2. Complétez le contrôleur de création de compte. On rappelle que la base de données doit contenir un hash du mot de passe (cf tp4).
|
||||
```php
|
||||
<?php
|
||||
/**
|
||||
* We just want to hash our password using the current DEFAULT algorithm.
|
||||
* This is presently BCRYPT, and will produce a 60 character result.
|
||||
*
|
||||
* Beware that DEFAULT may change over time, so you would want to prepare
|
||||
* By allowing your storage to expand past 60 characters (255 would be good)
|
||||
*/
|
||||
echo password_hash("rasmuslerdorf", PASSWORD_DEFAULT);
|
||||
?>
|
||||
```
|
||||
```php
|
||||
<?php
|
||||
// Voir l'exemple fourni sur la page de la fonction password_hash()
|
||||
// pour savoir d'où cela provient.
|
||||
$hash = '$2y$07$BCryptRequires22Chrcte/VlQH0piJtjXl.0t1XkA8pw9dMXTpOq';
|
||||
|
||||
if (password_verify('rasmuslerdorf', $hash)) {
|
||||
echo 'Le mot de passe est valide !';
|
||||
} else {
|
||||
echo 'Le mot de passe est invalide.';
|
||||
}
|
||||
?>
|
||||
```
|
||||
|
||||
3. Ajoutez un formulaire d'authentification.
|
||||
4. Utilisez une session pour proteger l'accès à la todolist par authentification.
|
||||
5. Ajouter à la table todo un lien vers la table user, et modifez l'ensemble de l'application pour que
|
||||
chaque utilisateur possède sa propre todolist.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
@@ -0,0 +1,13 @@
|
||||
.action{
|
||||
text-align : right;
|
||||
}
|
||||
.action a {
|
||||
margin-right : 1rem;
|
||||
}
|
||||
table {
|
||||
|
||||
font-size : 1.5rem;
|
||||
}
|
||||
body {
|
||||
padding : 2rem;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
defined('BASEPATH') OR exit('No direct script access allowed');
|
||||
|
||||
class Todo extends CI_Controller {
|
||||
public $filter = 'all';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->load->helper('html');
|
||||
$this->load->helper('url');
|
||||
$this->load->helper('form');
|
||||
|
||||
$this->load->model('model_todo');
|
||||
|
||||
$this->filter = $this->input->get('filter') ?? 'all';
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
$todos = $this->model_todo->getTodos($this->filter);
|
||||
$this->load->view('layout/header');
|
||||
$this->load->view('todos',['todos'=>$todos,'filter'=>$this->filter]);
|
||||
$this->load->view('layout/footer');
|
||||
}
|
||||
|
||||
public function delete($id)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
public function toggle($id)
|
||||
{
|
||||
$this->model_todo->toggleTodo($id);
|
||||
redirect('/todo');
|
||||
}
|
||||
|
||||
public function add()
|
||||
{
|
||||
$todo = ['text'=>$this->input->post('todo'),'done'=>0];
|
||||
$this->model_todo->addTodo($todo);
|
||||
$todos = $this->model_todo->getTodos();
|
||||
$this->index();
|
||||
}
|
||||
public function edit($id)
|
||||
{
|
||||
|
||||
$this->load->library('form_validation');
|
||||
$this->load->model('model_todo');
|
||||
|
||||
$todo = $this->model_todo->getTodo($id);
|
||||
$this->form_validation->set_rules('todo', 'Todo', 'required');
|
||||
if ($this->form_validation->run() === FALSE){
|
||||
$this->load->view('layout/header');
|
||||
$this->load->view('edit',['todo'=>$todo]);
|
||||
$this->load->view('layout/footer');
|
||||
|
||||
|
||||
}else{
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
defined('BASEPATH') OR exit('No direct script access allowed');
|
||||
|
||||
class User extends CI_Controller {
|
||||
|
||||
public function create()
|
||||
{
|
||||
|
||||
$this->load->library('form_validation');
|
||||
$this->form_validation->set_rules('nom', 'Nom', 'required');
|
||||
$this->form_validation->set_rules('prenom', 'Prénom', 'required');
|
||||
$this->form_validation->set_rules('email', 'Adresse mail', 'valid_email');
|
||||
$this->form_validation->set_rules('password', 'current password', 'min_length[5]|required');
|
||||
$this->form_validation->set_rules('cpassword', 'confirm password', 'required|matches[password]');
|
||||
|
||||
|
||||
if ($this->form_validation->run() === FALSE){
|
||||
$this->load->view('layout/header');
|
||||
$this->load->view('create_user_form');
|
||||
$this->load->view('layout/footer');
|
||||
}else{
|
||||
//
|
||||
// TODO
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
public function auth()
|
||||
{
|
||||
//
|
||||
// TODO
|
||||
//
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
class Model_todo extends CI_Model {
|
||||
public function __construct()
|
||||
{
|
||||
$this->load->database();
|
||||
}
|
||||
public function deleteTodo($id)
|
||||
{
|
||||
$this->db->delete('todo',['id'=>$id]);
|
||||
}
|
||||
|
||||
public function getTodos($filter='all')
|
||||
{
|
||||
$where_filter = ["done" => 1, "active" => 0, "all" => "%"];
|
||||
return $this
|
||||
->db
|
||||
->query("SELECT * FROM todo WHERE done LIKE ?",[$where_filter[$filter]])
|
||||
->result();
|
||||
}
|
||||
|
||||
public function toggleTodo($id){
|
||||
|
||||
/* en utilisant Query Builder class
|
||||
* $this
|
||||
->db
|
||||
->set('done','1-done',false)
|
||||
->where('id',$id)
|
||||
->update('todo');
|
||||
*/
|
||||
|
||||
$sql = "UPDATE todo SET done = 1 - done WHERE id = ?";
|
||||
$this
|
||||
->db
|
||||
->query($sql,[$id]);
|
||||
}
|
||||
|
||||
public function editTodo($id,$text)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
public function getTodo($id){
|
||||
$sql = "SELECT * FROM todo where id = ?";
|
||||
return $this
|
||||
->db
|
||||
->query($sql,[$id])->row();
|
||||
}
|
||||
|
||||
public function addTodo($todo)
|
||||
{
|
||||
$this->db->insert('todo', $todo);
|
||||
return $this
|
||||
->db
|
||||
->insert_id();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
|
||||
<?=validation_errors(); ?>
|
||||
<?=form_open('user/create')?>
|
||||
<!-- Grid -->
|
||||
<div class="grid">
|
||||
|
||||
<!-- Markup example 1: input is inside label -->
|
||||
<label for="prenom">
|
||||
Prénom
|
||||
<input type="text" id="prenom" name="prenom" placeholder="Prénom" value="<?=set_value('prenom')?>"required>
|
||||
</label>
|
||||
|
||||
<label for="nom">
|
||||
Nom
|
||||
<input type="text" id="nom" name="nom" placeholder="nom" value="<?=set_value('nom')?>" required>
|
||||
</label>
|
||||
</div>
|
||||
<!-- Markup example 2: input is after label -->
|
||||
<label for="email">Adresse mail</label>
|
||||
<input type="email" id="email" name="email" placeholder="Email" value="<?=set_value('email')?>" required>
|
||||
<div class="grid">
|
||||
<label for="password">Password
|
||||
<input type="password" id="password" name="password" placeholder="Password" value="<?=set_value('password')?>" required>
|
||||
</label>
|
||||
<label for="password">Confirmation password
|
||||
<input type="password" id="cpassword" name="cpassword" placeholder="Password" value="<?=set_value('cpassword')?>" required>
|
||||
</label>
|
||||
|
||||
</div>
|
||||
<!-- Button -->
|
||||
<button type="submit">Submit</button>
|
||||
|
||||
</form>
|
||||
@@ -0,0 +1,13 @@
|
||||
|
||||
<article>
|
||||
<?php echo form_open("/todo/edit/{$todo->id}");?>
|
||||
<form>
|
||||
<label for="email">Todo
|
||||
<input type="text" name="todo" value="<?=set_value('todo',$todo->text)?>" required>
|
||||
</label>
|
||||
|
||||
<!-- Button -->
|
||||
<button type="submit">Submit</button>
|
||||
|
||||
</form>
|
||||
</article>
|
||||
@@ -0,0 +1,3 @@
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,15 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>TODO APP</title>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css"
|
||||
/>
|
||||
<!--link rel="stylesheet" href="https://unpkg.com/@picocss/pico@1.*/css/pico.min.css"-->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||
<?=link_tag('assets/style.css')?>
|
||||
</head>
|
||||
<body>
|
||||
<main class="container">
|
||||
@@ -0,0 +1,42 @@
|
||||
<article>
|
||||
<header>
|
||||
<nav>
|
||||
<ul>
|
||||
<li><strong>TODOS</strong></li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><?=anchor("todo/?filter=all",'All', ['role'=>($filter=='all'?'button':'')])?></li>
|
||||
<li><?=anchor("todo/?filter=active",'Active', ['role'=>($filter=='active'?'button':'')])?></li>
|
||||
<li><?=anchor("todo/?filter=done",'Done', ['role'=>($filter=='done'?'button':'')])?></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
<?=form_open('todo/add')?>
|
||||
<fieldset role="group">
|
||||
<input type="text" placeholder="Buy milk and eggs..." name="todo">
|
||||
<button><i class="fa fa-plus"></i></button>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
<table>
|
||||
<?php foreach($todos as $todo): ?>
|
||||
<?php if ($todo->done): ?>
|
||||
<tr>
|
||||
<td><s><?=$todo->text?></s></td>
|
||||
<td class='action'>
|
||||
<?=anchor("todo/toggle/{$todo->id}", '<i class="fa fa-toggle-on"></i>')?>
|
||||
<?=anchor("todo/delete/{$todo->id}", '<i class="fa fa-trash-o"></i>')?>
|
||||
<?=anchor("todo/edit/{$todo->id}", '<i class="fa fa-edit"></i>')?>
|
||||
|
||||
<?php else: ?>
|
||||
|
||||
<tr><td><?=$todo->text?></td>
|
||||
<td class='action'>
|
||||
<?=anchor("todo/toggle/{$todo->id}", '<i class="fa fa-toggle-off"></i>')?>
|
||||
<?=anchor("todo/delete/{$todo->id}", '<i class="fa fa-trash-o"></i>')?>
|
||||
<?=anchor("todo/edit/{$todo->id}", '<i class="fa fa-edit"></i>')?>
|
||||
<?php endif; ?>
|
||||
</td></tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
</article>
|
||||
@@ -0,0 +1,65 @@
|
||||
-- phpMyAdmin SQL Dump
|
||||
-- version 5.2.1
|
||||
-- https://www.phpmyadmin.net/
|
||||
--
|
||||
-- Hôte : localhost
|
||||
-- Généré le : mar. 23 mai 2023 à 07:22
|
||||
-- Version du serveur : 10.11.2-MariaDB
|
||||
-- Version de PHP : 8.2.4
|
||||
|
||||
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
|
||||
START TRANSACTION;
|
||||
SET time_zone = "+00:00";
|
||||
|
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||
/*!40101 SET NAMES utf8mb4 */;
|
||||
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Structure de la table `todo`
|
||||
--
|
||||
|
||||
CREATE TABLE `todo` (
|
||||
`id` int(11) NOT NULL,
|
||||
`text` varchar(256) NOT NULL,
|
||||
`done` tinyint(1) NOT NULL DEFAULT 0
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Déchargement des données de la table `todo`
|
||||
--
|
||||
|
||||
INSERT INTO `todo` (`id`, `text`, `done`) VALUES
|
||||
(1, 'Avoid excessive caffeine !', 0),
|
||||
(2, 'Be less provocative !', 1),
|
||||
(3, 'Be nice to people', 1);
|
||||
|
||||
--
|
||||
-- Index pour les tables déchargées
|
||||
--
|
||||
|
||||
--
|
||||
-- Index pour la table `todo`
|
||||
--
|
||||
ALTER TABLE `todo`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT pour les tables déchargées
|
||||
--
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT pour la table `todo`
|
||||
--
|
||||
ALTER TABLE `todo`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=58;
|
||||
COMMIT;
|
||||
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||
Reference in New Issue
Block a user