diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..12806a1 --- /dev/null +++ b/.htaccess @@ -0,0 +1,7 @@ +ErrorDocument 403 /tfjm/server_files/403.php +ErrorDocument 404 /tfjm/server_files/404.php + +Options +FollowSymlinks +Options -Indexes +RewriteEngine On +RewriteRule ^(.*)$ dispatcher.php?path=$1 [QSA,L] diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..0ed6303 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,6 @@ +# Default ignored files +/workspace.xml + +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml \ No newline at end of file diff --git a/.idea/TFJM.iml b/.idea/TFJM.iml new file mode 100644 index 0000000..940f6f9 --- /dev/null +++ b/.idea/TFJM.iml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..a55e7a1 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml new file mode 100644 index 0000000..c28cc86 --- /dev/null +++ b/.idea/dataSources.xml @@ -0,0 +1,15 @@ + + + + + mysql.8 + true + com.mysql.cj.jdbc.Driver + jdbc:mysql://ynerant.fr:3306/tfjm + + + + GMT+1 + + + \ No newline at end of file diff --git a/.idea/deployment.xml b/.idea/deployment.xml new file mode 100644 index 0000000..f213652 --- /dev/null +++ b/.idea/deployment.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..28a804d --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..6fcadc0 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/assets/Autorisation_droit_image_majeur.tex b/assets/Autorisation_droit_image_majeur.tex new file mode 100644 index 0000000..7cb1727 --- /dev/null +++ b/assets/Autorisation_droit_image_majeur.tex @@ -0,0 +1,113 @@ +\documentclass[a4paper,french,11pt]{article} + +\usepackage[T1]{fontenc} +\usepackage[utf8]{inputenc} +\usepackage{lmodern} +\usepackage[frenchb]{babel} + +\usepackage{fancyhdr} +\usepackage{graphicx} +\usepackage{amsmath} +\usepackage{amssymb} +%\usepackage{anyfontsize} +\usepackage{fancybox} +\usepackage{eso-pic,graphicx} +\usepackage{xcolor} + + +% Specials +\newcommand{\writingsep}{\vrule height 4ex width 0pt} + +% Page formating +\hoffset -1in +\voffset -1in +\textwidth 180 mm +\textheight 250 mm +\oddsidemargin 15mm +\evensidemargin 15mm +\pagestyle{fancy} + +% Headers and footers +\fancyfoot{} +\lhead{} +\rhead{} +\renewcommand{\headrulewidth}{0pt} +\lfoot{\footnotesize 11 rue Pierre et Marie Curie, 75231 Paris Cedex 05\\ Numéro siret 431 598 366 00018} +\rfoot{\footnotesize Association agréée par\\le Ministère de l'éducation nationale.} + +\begin{document} + +\includegraphics[height=2cm]{assets/logo_animath.png}\hfill{\fontsize{55pt}{55pt}{$\mathbb{TFJM}^2$}} + +\vfill + +\begin{center} + + +\LARGE +Autorisation d'enregistrement et de diffusion de l'image ({TOURNAMENT_NAME}) +\end{center} +\normalsize + + +\thispagestyle{empty} + +\bigskip + + + +Je soussign\'e {PARTICIPANT_NAME}\\ +demeurant au {ADDRESS} + +\medskip +Cochez la/les cases correspondantes.\\ +\medskip + + \fbox{\textcolor{white}{A}} Autorise l'association Animath, \`a l'occasion du $\mathbb{TFJM}^2$ du {START_DATE} au {END_DATE} {YEAR} à : {PLACE}, \`a me photographier ou \`a me filmer et \`a diffuser les photos et/ou les vid\'eos r\'ealis\'ees \`a cette occasion sur son site et sur les sites partenaires. D\'eclare c\'eder \`a titre gracieux \`a Animath le droit d’utiliser mon image sur tous ses supports d'information : brochures, sites web, r\'eseaux sociaux. Animath devient, par la pr\'esente, cessionnaire des droits pendant toute la dur\'ee pour laquelle ont \'et\'e acquis les droits d'auteur de ces photographies.\\ + +\medskip +Animath s'engage, conform\'ement aux dispositions l\'egales en vigueur relatives au droit \`a l'image, \`a ce que la publication et la diffusion de l'image ainsi que des commentaires l'accompagnant ne portent pas atteinte \`a la vie priv\'ee, \`a la dignit\'e et \`a la r\'eputation de la personne photographiée.\\ + +\medskip + \fbox{\textcolor{white}{A}} Autorise la diffusion dans les medias (Presse, T\'el\'evision, Internet) de photographies prises \`a l'occasion d’une \'eventuelle m\'ediatisation de cet événement.\\ + + \medskip + +Conform\'ement \`a la loi informatique et libert\'es du 6 janvier 1978, vous disposez d'un droit de libre acc\`es, de rectification, de modification et de suppression des donn\'ees qui vous concernent. +Cette autorisation est donc r\'evocable \`a tout moment sur volont\'e express\'ement manifest\'ee par lettre recommand\'ee avec accus\'e de r\'eception adress\'ee \`a Animath, IHP, 11 rue Pierre et Marie Curie, 75231 Paris cedex 05.\\ + +\medskip + \fbox{\textcolor{white}{A}} Autorise Animath à conserver mes données personnelles, dans le cadre défini par la loi n 78-17 du 6 janvier 1978 relative à l'informatique, aux fichiers et aux libertés et les textes la modifiant, pendant une durée de quatre ans à compter de ma dernière participation à un événement organisé par Animath.\\ + + \medskip + \fbox{\textcolor{white}{A}} J'accepte d'être tenu informé d'autres activités organisées par l'association et ses partenaires. + +\bigskip + +Signature pr\'ec\'ed\'ee de la mention \og lu et approuv\'e \fg{} + +\medskip + + + +\begin{minipage}[c]{0.5\textwidth} + +\underline{L'\'el\`eve :}\\ + +Fait \`a :\\ +le +\end{minipage} + + +\vfill +\vfill +\begin{minipage}[c]{0.5\textwidth} +\footnotesize 11 rue Pierre et Marie Curie, 75231 Paris Cedex 05\\ Numéro siret 431 598 366 00018 +\end{minipage} +\begin{minipage}[c]{0.5\textwidth} +\footnotesize +\begin{flushright} +Association agréée par\\le Ministère de l'éducation nationale. +\end{flushright} +\end{minipage} +\end{document} diff --git a/assets/Autorisation_droit_image_mineur.tex b/assets/Autorisation_droit_image_mineur.tex new file mode 100644 index 0000000..4f14a43 --- /dev/null +++ b/assets/Autorisation_droit_image_mineur.tex @@ -0,0 +1,122 @@ +\documentclass[a4paper,french,11pt]{article} + +\usepackage[T1]{fontenc} +\usepackage[utf8]{inputenc} +\usepackage{lmodern} +\usepackage[frenchb]{babel} + +\usepackage{fancyhdr} +\usepackage{graphicx} +\usepackage{amsmath} +\usepackage{amssymb} +%\usepackage{anyfontsize} +\usepackage{fancybox} +\usepackage{eso-pic,graphicx} +\usepackage{xcolor} + + +% Specials +\newcommand{\writingsep}{\vrule height 4ex width 0pt} + +% Page formating +\hoffset -1in +\voffset -1in +\textwidth 180 mm +\textheight 250 mm +\oddsidemargin 15mm +\evensidemargin 15mm +\pagestyle{fancy} + +% Headers and footers +\fancyfoot{} +\lhead{} +\rhead{} +\renewcommand{\headrulewidth}{0pt} +\lfoot{\footnotesize 11 rue Pierre et Marie Curie, 75231 Paris Cedex 05\\ Numéro siret 431 598 366 00018} +\rfoot{\footnotesize Association agréée par\\le Ministère de l'éducation nationale.} + +\begin{document} + +\includegraphics[height=2cm]{assets/logo_animath.png}\hfill{\fontsize{55pt}{55pt}{$\mathbb{TFJM}^2$}} + +\vfill + +\begin{center} + + +\LARGE +Autorisation d'enregistrement et de diffusion de l'image +({TOURNAMENT_NAME}) +\end{center} +\normalsize + + +\thispagestyle{empty} + +\bigskip + + + +Je soussign\'e \dotfill (p\`ere, m\`ere, responsable l\'egal) \\ +agissant en qualit\'e de repr\'esentant de {PARTICIPANT_NAME}\\ +demeurant au {ADDRESS} + +\medskip +Cochez la/les cases correspondantes.\\ +\medskip + + \fbox{\textcolor{white}{A}} Autorise l'association Animath, \`a l'occasion du $\mathbb{TFJM}^2$ du {START_DATE} au {END_DATE} {YEAR} à : {PLACE}, \`a photographier ou \`a filmer l'enfant et \`a diffuser les photos et/ou les vid\'eos r\'ealis\'ees \`a cette occasion sur son site et sur les sites partenaires. D\'eclare c\'eder \`a titre gracieux \`a Animath le droit d’utiliser l'image de l'enfant sur tous ses supports d'information : brochures, sites web, r\'eseaux sociaux. Animath devient, par la pr\'esente, cessionnaire des droits pendant toute la dur\'ee pour laquelle ont \'et\'e acquis les droits d'auteur de ces photographies.\\ + +\medskip +Animath s'engage, conform\'ement aux dispositions l\'egales en vigueur relatives au droit \`a l'image, \`a ce que la publication et la diffusion de l'image de l'enfant ainsi que des commentaires l'accompagnant ne portent pas atteinte \`a la vie priv\'ee, \`a la dignit\'e et \`a la r\'eputation de l’enfant.\\ + +\medskip + \fbox{\textcolor{white}{A}} Autorise la diffusion dans les medias (Presse, T\'el\'evision, Internet) de photographies de mon enfant prises \`a l'occasion d’une \'eventuelle m\'ediatisation de cet événement.\\ + + \medskip + +Conform\'ement \`a la loi informatique et libert\'es du 6 janvier 1978, vous disposez d'un droit de libre acc\`es, de rectification, de modification et de suppression des donn\'ees qui vous concernent. +Cette autorisation est donc r\'evocable \`a tout moment sur volont\'e express\'ement manifest\'ee par lettre recommand\'ee avec accus\'e de r\'eception adress\'ee \`a Animath, IHP, 11 rue Pierre et Marie Curie, 75231 Paris cedex 05.\\ + +\medskip + \fbox{\textcolor{white}{A}} Autorise Animath à conserver mes données personnelles, dans le cadre défini par la loi n 78-17 du 6 janvier 1978 relative à l'informatique, aux fichiers et aux libertés et les textes la modifiant, pendant une durée de quatre ans à compter de ma dernière participation à un événement organisé par Animath.\\ + + \medskip + \fbox{\textcolor{white}{A}} J'accepte d'être tenu informé d'autres activités organisées par l'association et ses partenaires. + + \bigskip + +Signatures pr\'ec\'ed\'ees de la mention \og lu et approuv\'e \fg{} + +\medskip + + +\begin{minipage}[c]{0.5\textwidth} + +\underline{Le responsable l\'egal :}\\ + +Fait \`a :\\ +le : + +\end{minipage} +\begin{minipage}[c]{0.5\textwidth} + +\underline{L'\'el\`eve :}\\ + +Fait \`a :\\ +le +\end{minipage} + + +\vfill +\vfill +\begin{minipage}[c]{0.5\textwidth} +\footnotesize 11 rue Pierre et Marie Curie, 75231 Paris Cedex 05\\ Numéro siret 431 598 366 00018 +\end{minipage} +\begin{minipage}[c]{0.5\textwidth} +\footnotesize +\begin{flushright} +Association agréée par\\le Ministère de l'éducation nationale. +\end{flushright} +\end{minipage} +\end{document} diff --git a/assets/Autorisation_parentale.tex b/assets/Autorisation_parentale.tex new file mode 100644 index 0000000..6c56ac4 --- /dev/null +++ b/assets/Autorisation_parentale.tex @@ -0,0 +1,66 @@ +\documentclass[a4paper,french,11pt]{article} + +\usepackage[T1]{fontenc} +\usepackage[utf8]{inputenc} +\usepackage{lmodern} +\usepackage[french]{babel} + +\usepackage{fancyhdr} +\usepackage{graphicx} +\usepackage{amsmath} +\usepackage{amssymb} +%\usepackage{anyfontsize} +\usepackage{fancybox} +\usepackage{eso-pic,graphicx} +\usepackage{xcolor} + + +% Specials +\newcommand{\writingsep}{\vrule height 4ex width 0pt} + +% Page formating +\hoffset -1in +\voffset -1in +\textwidth 180 mm +\textheight 250 mm +\oddsidemargin 15mm +\evensidemargin 15mm +\pagestyle{fancy} + +% Headers and footers +\fancyfoot{} +\lhead{} +\rhead{} +\renewcommand{\headrulewidth}{0pt} +\lfoot{\footnotesize 11 rue Pierre et Marie Curie, 75231 Paris Cedex 05\\ Numéro siret 431 598 366 00018} +\rfoot{\footnotesize Association agréée par\\le Ministère de l'éducation nationale.} + +\begin{document} + +\includegraphics[height=2cm]{assets/logo_animath.png}\hfill{\fontsize{55pt}{55pt}{$\mathbb{TFJM}^2$}} + +\vfill + +\begin{center} +\Large \bf Autorisation parentale pour les mineurs ({TOURNAMENT_NAME}) +\end{center} + +Je soussigné(e) \hrulefill,\\ +responsable légal, demeurant \writingsep\hrulefill\\ +\writingsep\hrulefill,\\ +\writingsep autorise {PARTICIPANT_NAME},\\ +né(e) le {BIRTHDAY}, +à participer au Tournoi Français des Jeunes Mathématiciennes et Mathématiciens ($\mathbb{TFJM}^2$) organisé \`a : {PLACE}, du {START_DATE} au {END_DATE} {YEAR}. + +{PRONOUN} se rendra au lieu indiqu\'e ci-dessus le vendredi matin et quittera les lieux l'après-midi du dimanche par ses propres moyens et sous la responsabilité du représentant légal. + + + +\vspace{8ex} + +Fait à \vrule width 10cm height 0pt depth 0.4pt, le \phantom{232323}/\phantom{XXX}/{YEAR}, + +\vfill +\vfill + +\end{document} diff --git a/assets/Fiche synthèse.pdf b/assets/Fiche synthèse.pdf new file mode 100644 index 0000000..af8ed1c Binary files /dev/null and b/assets/Fiche synthèse.pdf differ diff --git a/assets/Fiche synthèse.tex b/assets/Fiche synthèse.tex new file mode 100644 index 0000000..bc2daa9 --- /dev/null +++ b/assets/Fiche synthèse.tex @@ -0,0 +1,194 @@ +\documentclass{article} + +\usepackage[utf8]{inputenc} +\usepackage[french]{babel} +\usepackage{graphicx} + +\usepackage[left=2cm,right=2cm,top=2cm,bottom=2cm]{geometry} % marges + +\usepackage{amsthm} +\usepackage{amsmath} +\usepackage{amsfonts} +\usepackage{amssymb} +\usepackage{tikz} + +\newcommand{\N}{{\bf N}} +\newcommand{\Z}{{\bf Z}} +\newcommand{\Q}{{\bf Q}} +\newcommand{\R}{{\bf R}} +\newcommand{\C}{{\bf C}} +\newcommand{\A}{{\bf A}} + +\newtheorem{theo}{Théorème} +\newtheorem{theo-defi}[theo]{Théorème-Définition} +\newtheorem{defi}[theo]{Définition} +\newtheorem{lemme}[theo]{Lemme} +\newtheorem{slemme}[theo]{Sous-lemme} +\newtheorem{prop}[theo]{Proposition} +\newtheorem{coro}[theo]{Corollaire} +\newtheorem{conj}[theo]{Conjecture} + +\title{Note de synthèse} + +\begin{document} +\pagestyle{empty} + +\begin{center} +\begin{Huge} +$\mathbb{TFJM}^2$ +\end{Huge} + +\bigskip + +\begin{Large} +NOTE DE SYNTHESE +\end{Large} +\end{center} + +Tour \underline{~~~~} poule \underline{~~~~} + +\medskip + +Problème \underline{~~~~} défendu par l'équipe \underline{~~~~~~~~~~~~~~~~~~~~~~~~} + +\medskip + +Synthèse par l'équipe \underline{~~~~~~~~~~~~~~~~~~~~~~~~} dans le rôle de : ~ $\square$ Opposant ~ $\square$ Rapporteur + +\section*{Questions traitées} + +\begin{tabular}{r c l} + \begin{tabular}{|c|c|c|c|c|c|} + \hline + Question ~ & ER & ~PR~ & QE & NT \\ + \hline + & & & & \\ + \hline + & & & & \\ + \hline + & & & & \\ + \hline + & & & & \\ + \hline + & & & & \\ + \hline + & & & & \\ + \hline + & & & & \\ + \hline + & & & & \\ + \hline + & & & & \\ + \hline + & & & & \\ + \hline + \end{tabular} +& ~~ & + \begin{tabular}{|c|c|c|c|c|c|} + \hline + Question ~ & ER & ~PR~ & QE & NT \\ + \hline + & & & & \\ + \hline + & & & & \\ + \hline + & & & & \\ + \hline + & & & & \\ + \hline + & & & & \\ + \hline + & & & & \\ + \hline + & & & & \\ + \hline + & & & & \\ + \hline + & & & & \\ + \hline + & & & & \\ + \hline + \end{tabular} \\ + + & & \\ + +ER : entièrement résolue & & PR : partiellement résolue \\ + +\smallskip + +QE : quelques éléments de réponse & & NT : non traitée +\end{tabular} + +~ + +\smallskip + +Remarque : il est possible de cocher entre les cases pour un cas intermédiaire. + +\section*{Evaluation qualitative de la solution} + +Donnez votre avis concernant la solution. Mettez notamment en valeur les points positifs (des idées +importantes, originales, etc.) et précisez ce qui aurait pu améliorer la solution. + +\vfill + +\textbf{Evaluation générale :} ~ $\square$ Excellente ~ $\square$ Bonne ~ $\square$ Suffisante ~ $\square$ Passable + +\newpage + +\section*{Erreurs et imprécisions} + +Listez ci-dessous les cinq erreurs et/ou imprécisions les plus importantes selon vous, par ordre d'importance, en précisant la +question concernée, la page, le paragraphe et le type de remarque. + +\bigskip + +1. Question \underline{~~~~} Page \underline{~~~~} Paragraphe \underline{~~~~} + +$\square$ Erreur majeure ~ $\square$ Erreur mineure ~ $\square$ Imprécision ~ $\square$ Autre : \underline{~~~~~~~~} + +Description : + +\vfill + +2. Question \underline{~~~~} Page \underline{~~~~} Paragraphe \underline{~~~~} + +$\square$ Erreur majeure ~ $\square$ Erreur mineure ~ $\square$ Imprécision ~ $\square$ Autre : \underline{~~~~~~~~} + +Description : + +\vfill + +3. Question \underline{~~~~} Page \underline{~~~~} Paragraphe \underline{~~~~} + +$\square$ Erreur majeure ~ $\square$ Erreur mineure ~ $\square$ Imprécision ~ $\square$ Autre : \underline{~~~~~~~~} + +Description : + +\vfill + +4. Question \underline{~~~~} Page \underline{~~~~} Paragraphe \underline{~~~~} + +$\square$ Erreur majeure ~ $\square$ Erreur mineure ~ $\square$ Imprécision ~ $\square$ Autre : \underline{~~~~~~~~} + +Description : + +\vfill + +5. Question \underline{~~~~} Page \underline{~~~~} Paragraphe \underline{~~~~} + +$\square$ Erreur majeure ~ $\square$ Erreur mineure ~ $\square$ Imprécision ~ $\square$ Autre : \underline{~~~~~~~~} + +Description : + +\vfill + +\section*{Remarques formelles (facultatif)} + +Donnez votre avis concernant la présentation de la solution (lisibilité, etc.). + +\vfill + + + +\end{document} diff --git a/assets/Fiche_sanitaire.pdf b/assets/Fiche_sanitaire.pdf new file mode 100644 index 0000000..b828b9d Binary files /dev/null and b/assets/Fiche_sanitaire.pdf differ diff --git a/assets/Instructions.tex b/assets/Instructions.tex new file mode 100644 index 0000000..da293ef --- /dev/null +++ b/assets/Instructions.tex @@ -0,0 +1,88 @@ +\documentclass[a4paper,french,11pt]{article} + +\usepackage[T1]{fontenc} +\usepackage[utf8]{inputenc} +\usepackage{lmodern} +\usepackage[frenchb]{babel} + +\usepackage{fancyhdr} +\usepackage{graphicx} +\usepackage{amsmath} +\usepackage{amssymb} +%\usepackage{anyfontsize} +\usepackage{fancybox} +\usepackage{eso-pic,graphicx} +\usepackage{xcolor} +\usepackage{hyperref} + + +% Specials +\newcommand{\writingsep}{\vrule height 4ex width 0pt} + +% Page formating +\hoffset -1in +\voffset -1in +\textwidth 180 mm +\textheight 250 mm +\oddsidemargin 15mm +\evensidemargin 15mm +\pagestyle{fancy} + +% Headers and footers +\fancyfoot{} +\lhead{} +\rhead{} +\renewcommand{\headrulewidth}{0pt} +\lfoot{\footnotesize 11 rue Pierre et Marie Curie, 75231 Paris Cedex 05\\ Numéro siret 431 598 366 00018} +\rfoot{\footnotesize Association agréée par\\le Ministère de l'éducation nationale.} + +\begin{document} + +\includegraphics[height=2cm]{assets/logo_animath.png}\hfill{\fontsize{50pt}{50pt}{$\mathbb{TFJM}^2$}} + + + +\begin{center} +\Large \bf Instructions ({TOURNAMENT_NAME}) +\end{center} + +\section{Documents} +\subsection{Autorisation parentale} +Elle est nécessaire si l'élève est mineur au moment du tournoi (y compris si son anniversaire est pendant le tournoi). + +\subsection{Autorisation de prise de vue} +Si l'élève est mineur \textbf{au moment de la signature}, il convient de remplir l'autorisation pour les mineurs. En revanche, s'il est majeur \textbf{au moment de la signature}, il convient de remplir la fiche pour majeur. + +\subsection{Fiche sanitaire} +Elle est nécessaire si l'élève est mineur au moment du tournoi (y compris si son anniversaire est pendant le tournoi). + + +\section{Paiement} + +\subsection{Montant} +Les frais d'inscription sont fixés à {PRICE} euros. Vous devez vous en acquitter \textbf{avant le {END_PAYMENT_DATE} {YEAR}}. Si l'élève est boursier, il en est dispensé, vous devez alors fournir une copie de sa notification de bourse directement sur la plateforme \textbf{avant le {END_PAYMENT_DATE} {YEAR}}. + +\subsection{Procédure} + +Si le paiement de plusieurs élèves est fait en une seule opération, merci de contacter \href{mailto: contact@tfjm.org}{contact@tfjm.org} \textbf{avant le paiement} pour garantir l'identification de ce dernier + +\subsubsection*{Carte bancaire (uniquement les cartes françaises)} +Le paiement s'effectue en ligne via la plateforme à l'adresse : \url{https://www.helloasso.com/associations/animath/evenements/tfjm-2020} + +Vous devez impérativement indiquer dans le champ "Référence" la mention "TFJMpu" suivie des noms et prénoms \textbf{de l'élève}. + +\subsubsection*{Virement} +\textbf{Si vous ne pouvez pas utiliser le paiement par carte}, vous pouvez faire un virement sur le compte ci-dessous en indiquant bien dans le champ "motif" (ou autre champ propre à votre banque dont le contenu est communiqué au destinataire) la mention "TFJMpu" suivie des noms et prénoms \textbf{de l'élève}. + +IBAN FR76 1027 8065 0000 0206 4290 127 + +BIC CMCIFR2A + +\subsubsection*{Autre} + +Si aucune de ces procédures n'est possible pour vous, envoyez un mail à \href{mailto: contact@tfjm.org}{contact@tfjm.org} pour que nous trouvions une solution à vos difficultés. + + + + +\end{document} diff --git a/assets/favicon.ico b/assets/favicon.ico new file mode 100644 index 0000000..97757d3 Binary files /dev/null and b/assets/favicon.ico differ diff --git a/assets/logo.svg b/assets/logo.svg new file mode 100644 index 0000000..699316b --- /dev/null +++ b/assets/logo.svg @@ -0,0 +1,114 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/assets/logo_animath.png b/assets/logo_animath.png new file mode 100644 index 0000000..da4533e Binary files /dev/null and b/assets/logo_animath.png differ diff --git a/assets/style.css b/assets/style.css new file mode 100644 index 0000000..5c8d3ff --- /dev/null +++ b/assets/style.css @@ -0,0 +1,47 @@ +html, body { + height: 100%; + margin: 0; +} + +:root { + --navbar-height: 32px; +} + +.container { + min-height: 78%; +} + +.inner { + margin: 20px; +} + +.alert { + text-align: justify; +} + + +footer .alert { + text-align: center; +} + +#navbar-logo { + height: var(--navbar-height); + display: block; +} + +ul .deroule { + display: none; + position: absolute; + background: #f8f9fa !important; + list-style-type: none; + padding: 20px; + z-index: 42; +} + +li:hover ul.deroule { + display:block; +} + +a.nav-link:hover { + background-color: #d8d9da; +} diff --git a/dispatcher.php b/dispatcher.php new file mode 100644 index 0000000..1f4106f --- /dev/null +++ b/dispatcher.php @@ -0,0 +1,92 @@ + $file) { + if (preg_match('#' . $route . '#', $path, $matches)) { + for ($i = 1; $i < sizeof($file); ++$i) + $_GET[$file[$i]] = $matches[$i]; + + if (!preg_match("#php$#", $file[0])) { + header("Content-Type: " . $file[1]); + readfile($file[0]); + exit(); + } + + $view = $file[0]; + /** @noinspection PhpIncludeInspection */ + require $view; + exit(); + } +} + +require_once "server_files/404.php"; diff --git a/index.html b/index.html new file mode 100644 index 0000000..da8c197 --- /dev/null +++ b/index.html @@ -0,0 +1,12 @@ + + + + + + Erreur + + + +Le mode Rewrite n'est pas activé. + + \ No newline at end of file diff --git a/server_files/403.php b/server_files/403.php new file mode 100644 index 0000000..72127d0 --- /dev/null +++ b/server_files/403.php @@ -0,0 +1,16 @@ + + +
+

+ Vous n'êtes pas autorisé à accéder à cette page. +

+
+ + + +
+

+ Cette page n'existe pas. +

+
+ +prepare("SELECT * FROM `documents` WHERE `file_id` = ?;"); + $req->execute([htmlspecialchars($id)]); + $data = $req->fetch(); + + if ($data === false) + return null; + + return self::fromData($data); + } + + public static function fromData($data) + { + $doc = new Document(); + $doc->fill($data); + return $doc; + } + + private function fill($data) + { + $this->file_id = $data["file_id"]; + $this->user_id = $data["user"]; + $this->team_id = $data["team"]; + $this->tournament_id = $data["tournament"]; + $this->type = DocumentType::fromName($data["type"]); + $this->uploaded_at = $data["uploaded_at"]; + $this->version = isset($data["version"]) ? $data["version"] : 1; + } + + public function getFileId() + { + return $this->file_id; + } + + public function getUserId() + { + return $this->user_id; + } + + public function getTeamId() + { + return $this->team_id; + } + + public function getTournamentId() + { + return $this->tournament_id; + } + + public function getType() + { + return $this->type; + } + + public function getUploadedAt() + { + return $this->uploaded_at; + } + + public function getVersion() + { + return $this->version; + } +} + +class Solution +{ + private $file_id; + private $team_id; + private $tournament_id; + private $problem; + private $uploaded_at; + private $version; + + private function __construct() {} + + public static function fromId($id) + { + global $DB; + $req = $DB->prepare("SELECT * FROM `solutions` WHERE `file_id` = ?;"); + $req->execute([htmlspecialchars($id)]); + $data = $req->fetch(); + + if ($data === false) + return null; + + return self::fromData($data); + } + + public static function fromData($data) + { + $sol = new Solution(); + $sol->fill($data); + return $sol; + } + + private function fill($data) + { + $this->file_id = $data["file_id"]; + $this->team_id = $data["team"]; + $this->tournament_id = $data["tournament"]; + $this->problem = $data["problem"]; + $this->uploaded_at = $data["uploaded_at"]; + $this->version = isset($data["version"]) ? $data["version"] : 1; + } + + public function getFileId() + { + return $this->file_id; + } + + public function getTeamId() + { + return $this->team_id; + } + + public function getTournamentId() + { + return $this->tournament_id; + } + + public function getProblem() + { + return $this->problem; + } + + public function getUploadedAt() + { + return $this->uploaded_at; + } + + public function getVersion() + { + return $this->version; + } +} + +class Synthesis +{ + private $file_id; + private $team_id; + private $tournament_id; + private $dest; + private $round; + private $uploaded_at; + private $version; + + private function __construct() {} + + public static function fromId($id) + { + global $DB; + $req = $DB->prepare("SELECT * FROM `syntheses` WHERE `file_id` = ?;"); + $req->execute([htmlspecialchars($id)]); + $data = $req->fetch(); + + if ($data === false) + return null; + + return self::fromData($data); + } + + public static function fromData($data) + { + $synthese = new Synthesis(); + $synthese->fill($data); + return $synthese; + } + + private function fill($data) + { + $this->file_id = $data["file_id"]; + $this->team_id = $data["team"]; + $this->tournament_id = $data["tournament"]; + $this->dest = $data["dest"]; + $this->round = $data["round"]; + $this->uploaded_at = $data["uploaded_at"]; + $this->version = isset($data["version"]) ? $data["version"] : 1; + } + + public function getFileId() + { + return $this->file_id; + } + + public function getTeamId() + { + return $this->team_id; + } + + public function getTournamentId() + { + return $this->tournament_id; + } + + public function getDest() + { + return $this->dest; + } + + public function getRound() + { + return $this->round; + } + + public function getUploadedAt() + { + return $this->uploaded_at; + } + + public function getVersion() + { + return $this->version; + } +} + +class DestType +{ + const DEFENSEUR = 0; + const OPPOSANT = 1; + const RAPPORTEUR = 2; + + public static function getTranslatedName($status) { + switch ($status) { + case self::OPPOSANT: + return "Opposant"; + case self::RAPPORTEUR: + return "Rapporteur"; + default: + return "Défenseur"; + } + } + + public static function getName($status) { + switch ($status) { + case self::OPPOSANT: + return "OPPOSANT"; + case self::RAPPORTEUR: + return "RAPPORTEUR"; + default: + return "DEFENSEUR"; + } + } + + public static function fromName($name) { + switch ($name) { + case "OPPOSANT": + return self::OPPOSANT; + case "RAPPORTEUR": + return self::RAPPORTEUR; + default: + return self::DEFENSEUR; + } + } +} + +class DocumentType +{ + const PARENTAL_CONSENT = 0; + const PHOTO_CONSENT = 1; + const SANITARY_PLUG = 2; + const SOLUTION = 3; + const SYNTHESIS = 4; + const SCHOLARSHIP = 5; + const MOTIVATION_LETTER = 6; + + public static function getTranslatedName($type) { + switch ($type) { + case self::PARENTAL_CONSENT: + return "Autorisation parentale"; + case self::PHOTO_CONSENT: + return "Autorisation de droit à l'image"; + case self::SANITARY_PLUG: + return "Fiche sanitaire"; + case self::SCHOLARSHIP: + return "Notification de bourse"; + case self::MOTIVATION_LETTER: + return "Lettre de motivation"; + case self::SOLUTION: + return "Solution"; + default: + return "Note de synthèse"; + } + } + + public static function getName($type) { + switch ($type) { + case self::PARENTAL_CONSENT: + return "PARENTAL_CONSENT"; + case self::PHOTO_CONSENT: + return "PHOTO_CONSENT"; + case self::SANITARY_PLUG: + return "SANITARY_PLUG"; + case self::SCHOLARSHIP: + return "SCHOLARSHIP"; + case self::MOTIVATION_LETTER: + return "MOTIVATION_LETTER"; + case self::SOLUTION: + return "SOLUTION"; + default: + return "SYNTHESIS"; + } + } + + public static function fromName($name) { + switch ($name) { + case "PARENTAL_CONSENT": + return self::PARENTAL_CONSENT; + case "PHOTO_CONSENT": + return self::PHOTO_CONSENT; + case "SANITARY_PLUG": + return self::SANITARY_PLUG; + case "SCHOLARSHIP": + return self::SCHOLARSHIP; + case "MOTIVATION_LETTER": + return self::MOTIVATION_LETTER; + case "SOLUTION": + return self::SOLUTION; + default: + return self::SYNTHESIS; + } + } +} \ No newline at end of file diff --git a/server_files/classes/Payment.php b/server_files/classes/Payment.php new file mode 100644 index 0000000..2847403 --- /dev/null +++ b/server_files/classes/Payment.php @@ -0,0 +1,152 @@ +prepare("SELECT * FROM `payments` WHERE `id` = ?;"); + $req->execute([htmlspecialchars($id)]); + $data = $req->fetch(); + + if ($data === false) + return null; + + $payment = new Payment(); + $payment->fill($data); + return $payment; + } + + private function fill($data) + { + $this->id = $data["id"]; + $this->user_id = $data["user"]; + $this->tournament_id = $data["tournament"]; + $this->amount = $data["amount"]; + $this->method = PaymentMethod::fromName($data["method"]); + $this->transaction_infos = $data["transaction_infos"]; + $this->validation_status = ValidationStatus::fromName($data["validation_status"]); + } + + /** + * @return int + */ + public function getId() + { + return $this->id; + } + + /** + * @return int + */ + public function getAmount() + { + return $this->amount; + } + + /** + * @param mixed $amount + */ + public function setAmount($amount) + { + global $DB; + $this->amount = $amount; + $DB->prepare("UPDATE `payments` SET `amount` = ? WHERE `id` = ?;")->execute([$amount, $this->id]); + } + + /** + * @return int + */ + public function getMethod() + { + return $this->method; + } + + /** + * @param int $method + */ + public function setMethod($method) + { + global $DB; + $this->method = $method; + $DB->prepare("UPDATE `payments` SET `method` = ? WHERE `id` = ?;")->execute([PaymentMethod::getName($method), $this->id]); + } + + /** + * @return int + */ + public function getTournamentId() + { + return $this->tournament_id; + } + + /** + * @return Tournament|null + */ + public function getTournament() + { + return Tournament::fromId($this->getTournamentId()); + } + + /** + * @return int + */ + public function getUserId() + { + return $this->user_id; + } + + /** + * @return User|null + */ + public function getUser() + { + return User::fromId($this->getUserId()); + } + + /** + * @return string + */ + public function getTransactionInfos() + { + return $this->transaction_infos; + } + + /** + * @param string $transaction_infos + */ + public function setTransactionInfos($transaction_infos) + { + global $DB; + $this->transaction_infos = $transaction_infos; + $DB->prepare("UPDATE `payments` SET `transaction_infos` = ? WHERE `id` = ?;")->execute([$transaction_infos, $this->id]); + } + + /** + * @return int + */ + public function getValidationStatus() + { + return $this->validation_status; + } + + /** + * @param int $validation_status + */ + public function setValidationStatus($validation_status) + { + global $DB; + $this->validation_status = $validation_status; + $DB->prepare("UPDATE `payments` SET `validation_status` = ? WHERE `id` = ?;")->execute([ValidationStatus::getName($validation_status), $this->id]); + } +} \ No newline at end of file diff --git a/server_files/classes/PaymentMethod.php b/server_files/classes/PaymentMethod.php new file mode 100644 index 0000000..f0d5420 --- /dev/null +++ b/server_files/classes/PaymentMethod.php @@ -0,0 +1,62 @@ +prepare("SELECT * FROM `teams` WHERE `id` = ?;"); + $req->execute([htmlspecialchars($id)]); + $data = $req->fetch(); + + if ($data === false) + return null; + + $team = new Team(); + $team->fill($data); + return $team; + } + + public static function fromTrigram($trigram) + { + global $DB, $YEAR; + $req = $DB->prepare("SELECT * FROM `teams` WHERE `trigram` = ? AND `year` = $YEAR;"); + $req->execute([htmlspecialchars($trigram)]); + $data = $req->fetch(); + + if ($data === false) + return null; + + $team = new Team(); + $team->fill($data); + return $team; + } + + public static function fromAccessCode($access_code) + { + global $DB, $YEAR; + $req = $DB->prepare("SELECT * FROM `teams` WHERE `access_code` = ? AND `year` = $YEAR;"); + $req->execute([htmlspecialchars($access_code)]); + $data = $req->fetch(); + + if ($data === false) + return null; + + $team = new Team(); + $team->fill($data); + return $team; + } + + private function fill($data) + { + $this->id = $data["id"]; + $this->name = $data["name"]; + $this->trigram = $data["trigram"]; + $this->tournament = $data["tournament"]; + $this->encadrants = [$data["encadrant_1"], $data["encadrant_2"], $data["encadrant_3"]]; + $this->participants = [$data["participant_1"], $data["participant_2"], $data["participant_3"], $data["participant_4"], $data["participant_5"], $data["participant_6"]]; + $this->inscription_date = $data["inscription_date"]; + $this->validation_status = ValidationStatus::fromName($data["validation_status"]); + $this->final_selection = $data["final_selection"] == true; + $this->access_code = $data["access_code"]; + $this->year = $data["year"]; + } + + public function getId() + { + return $this->id; + } + + public function getName() + { + return $this->name; + } + + public function setName($name) + { + global $DB; + $this->name = $name; + $DB->prepare("UPDATE `teams` SET `name` = ? WHERE `id` = ?;")->execute([$name, $this->id]); + } + + public function getTrigram() + { + return $this->trigram; + } + + public function setTrigram($trigram) + { + global $DB; + $this->trigram = $trigram; + $DB->prepare("UPDATE `teams` SET `trigram` = ? WHERE `id` = ?;")->execute([$trigram, $this->id]); + } + + public function getTournamentId() + { + return $this->tournament; + } + + /** + * @return Tournament + */ + public function getEffectiveTournament() + { + return $this->isSelectedForFinal() ? Tournament::getFinalTournament() : Tournament::fromId($this->getTournamentId()); + } + + public function setTournamentId($tournament) + { + global $DB; + $this->tournament = $tournament; + $DB->prepare("UPDATE `teams` SET `tournament` = ? WHERE `id` = ?;")->execute([$tournament, $this->id]); + } + + public function getEncadrants() + { + return $this->encadrants; + } + + public function setEncadrant($i, $encadrant) + { + global $DB; + $this->encadrants[$i - 1] = $encadrant; + /** @noinspection SqlResolve */ + $DB->prepare("UPDATE `teams` SET `encadrant_$i` = ? WHERE `id` = ?;")->execute([$encadrant, $this->id]); + } + + public function getParticipants() + { + return $this->participants; + } + + public function setParticipant($i, $participant) + { + global $DB; + $this->participants[$i - 1] = $participant; + /** @noinspection SqlResolve */ + $DB->prepare("UPDATE `teams` SET `participant_$i` = ? WHERE `id` = ?;")->execute([$participant, $this->id]); + } + + public function getInscriptionDate() + { + return $this->inscription_date; + } + + public function getValidationStatus() + { + return $this->validation_status; + } + + public function setValidationStatus($status) + { + global $DB; + $this->validation_status = $status; + /** @noinspection PhpUndefinedMethodInspection */ + $DB->prepare("UPDATE `teams` SET `validation_status` = ? WHERE `id` = ?;")->execute([ValidationStatus::getName($status), $this->id]); + } + + public function isSelectedForFinal() + { + return $this->final_selection; + } + + public function selectForFinal($selected) + { + global $DB; + $this->final_selection = $selected; + $DB->prepare("UPDATE `teams` SET `final_selection` = ? WHERE `id` = ?;")->execute([$selected, $this->id]); + } + + public function getAccessCode() + { + return $this->access_code; + } + + public function getYear() + { + return $this->year; + } + + public static function getAllTeams($only_not_validated = false) + { + global $DB, $YEAR; + $req = $DB->query("SELECT * FROM `teams` WHERE " . ($only_not_validated ? "`validation_status` = 0 AND " : "") . "`year` = $YEAR;"); + + $teams = []; + + while (($data = $req->fetch()) != false) { + $team = new Team(); + $team->fill($data); + $teams[] = $team; + } + + return $teams; + } +} diff --git a/server_files/classes/Tournament.php b/server_files/classes/Tournament.php new file mode 100644 index 0000000..6860bad --- /dev/null +++ b/server_files/classes/Tournament.php @@ -0,0 +1,385 @@ +prepare("SELECT * FROM `tournaments` WHERE `id` = ?;"); + $req->execute([htmlspecialchars($id)]); + $data = $req->fetch(); + + if ($data === false) + return null; + + $tournament = new Tournament(); + $tournament->fill($data); + return $tournament; + } + + public static function fromName($name) + { + global $DB, $YEAR; + $req = $DB->prepare("SELECT * FROM `tournaments` WHERE `name` = ? AND `year` = $YEAR;"); + $req->execute([htmlspecialchars($name)]); + $data = $req->fetch(); + + if ($data === false) + return null; + + $tournament = new Tournament(); + $tournament->fill($data); + return $tournament; + } + + public static function getFinalTournament() + { + global $DB, $YEAR; + $req = $DB->query("SELECT * FROM `tournaments` WHERE `final` AND `year` = $YEAR;"); + $data = $req->fetch(); + + if ($data === false) + return null; + + $tournament = new Tournament(); + $tournament->fill($data); + return $tournament; + } + + public static function getAllTournaments($include_final = true, $only_future = false) + { + global $DB, $YEAR; + $sql = "SELECT * FROM `tournaments` WHERE "; + if (!$include_final) + $sql .= "`final` = 0 AND "; + if ($only_future) + $sql .= "`date_start` > CURRENT_DATE AND "; + $sql .= "`year` = $YEAR ORDER BY `date_start`, `name`;"; + $req = $DB->query($sql); + + $tournaments = []; + + while (($data = $req->fetch()) !== false) { + $tournament = new Tournament(); + $tournament->fill($data); + $tournaments[] = $tournament; + } + + return $tournaments; + } + + private function fill($data) + { + $this->id = $data["id"]; + $this->name = $data["name"]; + $this->size = $data["size"]; + $this->place = $data["place"]; + $this->price = $data["price"]; + $this->description = $data["description"]; + $this->date_start = $data["date_start"]; + $this->date_end = $data["date_end"]; + $this->date_inscription = $data["date_inscription"]; + $this->date_solutions = $data["date_solutions"]; + $this->date_solutions_2 = $data["date_solutions_2"]; + $this->date_syntheses = $data["date_syntheses"]; + $this->date_syntheses_2 = $data["date_syntheses_2"]; + $this->final = $data["final"] == true; + $this->year = $data["year"]; + + global $DB; + $req = $DB->prepare("SELECT `organizer` FROM `organizers` WHERE `tournament` = ?;"); + $req->execute([$this->id]); + + while (($data = $req->fetch()) !== false) + $this->organizers[] = User::fromId($data["organizer"]); + } + + public function getId() + { + return $this->id; + } + + public function getName() + { + return $this->name; + } + + public function setName($name) + { + global $DB; + $this->name = $name; + $DB->prepare("UPDATE `tournaments` SET `name` = ? WHERE `id` = ?;")->execute([$name, $this->id]); + } + + public function getSize() + { + return $this->size; + } + + public function setSize($size) + { + global $DB; + $this->size = $size; + $DB->prepare("UPDATE `tournaments` SET `size` = ? WHERE `id` = ?;")->execute([$size, $this->id]); + } + + public function getPlace() + { + return $this->place; + } + + public function setPlace($place) + { + global $DB; + $this->place = $place; + $DB->prepare("UPDATE `tournaments` SET `place` = ? WHERE `id` = ?;")->execute([$place, $this->id]); + } + + public function getPrice() + { + return $this->price; + } + + public function setPrice($price) + { + global $DB; + $this->price = $price; + $DB->prepare("UPDATE `tournaments` SET `price` = ? WHERE `id` = ?;")->execute([$price, $this->id]); + } + + public function getDescription() + { + return $this->description; + } + + public function setDescription($desc) + { + global $DB; + $this->description = $desc; + $DB->prepare("UPDATE `tournaments` SET `description` = ? WHERE `id` = ?;")->execute([$desc, $this->id]); + } + + public function getStartDate() + { + return $this->date_start; + } + + public function setStartDate($date) + { + global $DB; + $this->date_start = $date; + $DB->prepare("UPDATE `tournaments` SET `date_start` = ? WHERE `id` = ?;")->execute([$date, $this->id]); + } + + public function getEndDate() + { + return $this->date_end; + } + + public function setEndDate($date) + { + global $DB; + $this->date_end = $date; + $DB->prepare("UPDATE `tournaments` SET `date_end` = ? WHERE `id` = ?;")->execute([$date, $this->id]); + } + + public function getInscriptionDate() + { + return $this->date_inscription; + } + + public function setInscriptionDate($date) + { + global $DB; + $this->date_inscription = $date; + $DB->prepare("UPDATE `tournaments` SET `date_inscription` = ? WHERE `id` = ?;")->execute([$date, $this->id]); + } + + public function getSolutionsDate() + { + return $this->date_solutions; + } + + public function setSolutionsDate($date) + { + global $DB; + $this->date_solutions = $date; + $DB->prepare("UPDATE `tournaments` SET `date_solutions` = ? WHERE `id` = ?;")->execute([$date, $this->id]); + } + + public function getSynthesesDate() + { + return $this->date_syntheses; + } + + public function setSynthesesDate($date) + { + global $DB; + $this->date_syntheses = $date; + $DB->prepare("UPDATE `tournaments` SET `date_syntheses` = ? WHERE `id` = ?;")->execute([$date, $this->id]); + } + + public function getSolutionsDate2() + { + return $this->date_solutions_2; + } + + public function setSolutionsDate2($date) + { + global $DB; + $this->date_solutions_2 = $date; + $DB->prepare("UPDATE `tournaments` SET `date_solutions_2` = ? WHERE `id` = ?;")->execute([$date, $this->id]); + } + + public function getSynthesesDate2() + { + return $this->date_syntheses_2; + } + + public function setSynthesesDate2($date) + { + global $DB; + $this->date_syntheses_2 = $date; + $DB->prepare("UPDATE `tournaments` SET `date_syntheses_2` = ? WHERE `id` = ?;")->execute([$date, $this->id]); + } + + public function isFinal() + { + return $this->final; + } + + public function setFinal($final) + { + global $DB; + $this->final = $final; + $DB->prepare("UPDATE `tournaments` SET `final` = ? WHERE `id` = ?;")->execute([$final, $this->id]); + } + + public function getAllTeams() + { + global $DB, $YEAR; + if ($this->final) + $req = $DB->query("SELECT `id` FROM `teams` WHERE `final_selection` AND `year` = $YEAR;"); + else + $req = $DB->query("SELECT `id` FROM `teams` WHERE `tournament` = $this->id AND `year` = $YEAR;"); + + $teams = []; + + while (($data = $req->fetch()) !== false) + $teams[] = Team::fromId($data["id"]); + + return $teams; + } + + public function getOrganizers() + { + return $this->organizers; + } + + public function organize($user_id) + { + foreach ($this->organizers as $organizer) { + if ($organizer->getId() == $user_id) + return true; + } + + return false; + } + + public function addOrganizer(User $user) + { + global $DB; + + $this->organizers[] = $user; + + $req = $DB->prepare("INSERT INTO `organizers`(`organizer`, `tournament`) VALUES(?, ?);"); + $req->execute([$user->getId(), $this->id]); + } + + public function clearOrganizers() + { + global $DB; + + $this->organizers = []; + + $req = $DB->prepare("DELETE FROM `organizers` WHERE `tournament` = ?;"); + $req->execute([$this->id]); + } + + public function getYear() + { + return $this->year; + } + + public function getAllDocuments($team_id = -1) + { + global $DB; + + $req = $DB->query("SELECT * FROM `documents` AS `t1` " + . "INNER JOIN (SELECT `user`, `type`, `tournament`, MAX(`uploaded_at`) AS `last_upload`, COUNT(`team`) AS `version` FROM `documents` GROUP BY `tournament`, `team`, `type`, `user`) `t2` " + . "ON `t1`.`user` = `t2`.`user` AND `t1`.`type` = `t2`.`type` AND `t1`.`tournament` = `t2`.`tournament` " + . "WHERE `t1`.`uploaded_at` = `t2`.`last_upload` AND `t1`.`tournament` = $this->id " . ($team_id == -1 ? "" : "AND `t1`.`team` = $team_id") . " ORDER BY `t1`.`team`, `t1`.`type`;"); + + $docs = []; + + while (($data = $req->fetch()) !== false) + $docs[] = Document::fromData($data); + + return $docs; + } + + public function getAllSolutions($team_id = -1) + { + global $DB; + + $req = $DB->query("SELECT * FROM `solutions` AS `t1` " + . "INNER JOIN (SELECT `team`, `problem`, `tournament`, MAX(`uploaded_at`) AS `last_upload`, COUNT(`team`) AS `version` FROM `solutions` GROUP BY `tournament`, `team`, `problem`) `t2` " + . "ON `t1`.`team` = `t2`.`team` AND `t1`.`problem` = `t2`.`problem` AND `t1`.`tournament` = `t2`.`tournament` " + . "WHERE `t1`.`uploaded_at` = `t2`.`last_upload` AND `t1`.`tournament` = $this->id " . ($team_id == -1 ? "" : "AND `t1`.`team` = $team_id") . " ORDER BY `t1`.`team`, `t1`.`problem`;"); + + $sols = []; + + while (($data = $req->fetch()) !== false) + $sols[] = Solution::fromData($data); + + return $sols; + } + + public function getAllSyntheses($team_id = -1) + { + global $DB; + + $req = $DB->query("SELECT * FROM `syntheses` AS `t1` " + . "INNER JOIN (SELECT `team`, `dest`, `round`, `tournament`, MAX(`uploaded_at`) AS `last_upload`, COUNT(`team`) AS `version` FROM `syntheses` GROUP BY `tournament`, `team`, `dest`, `round`) `t2` " + . "ON `t1`.`team` = `t2`.`team` AND `t1`.`dest` = `t2`.`dest` AND `t1`.`tournament` = `t2`.`tournament` AND `t1`.`round` = `t2`.`round` " + . "WHERE `t1`.`uploaded_at` = `t2`.`last_upload` AND `t1`.`tournament` = $this->id " . ($team_id == -1 ? "" : "AND `t1`.`team` = $team_id") . " ORDER BY `t1`.`team`, `t1`.`round`, `t1`.`dest`;"); + + $syntheses = []; + + while (($data = $req->fetch()) !== false) + $syntheses[] = Synthesis::fromData($data); + + return $syntheses; + } +} \ No newline at end of file diff --git a/server_files/classes/User.php b/server_files/classes/User.php new file mode 100644 index 0000000..cc8111e --- /dev/null +++ b/server_files/classes/User.php @@ -0,0 +1,481 @@ +prepare("SELECT * FROM `users` WHERE `id` = ?;"); + $req->execute([htmlspecialchars($id)]); + $data = $req->fetch(); + + if ($data === false) + return null; + + $user = new User(); + $user->fill($data); + return $user; + } + + public static function fromEmail($email) + { + global $DB, $YEAR; + $req = $DB->prepare("SELECT * FROM `users` WHERE `email` = ? AND `year` = $YEAR;"); + $req->execute([htmlspecialchars($email)]); + $data = $req->fetch(); + + if ($data === false) + return null; + + $user = new User(); + $user->fill($data); + return $user; + } + + private function fill($data) + { + $this->id = $data["id"]; + $this->email = $data["email"]; + $this->pwd_hash = $data["pwd_hash"]; + $this->surname = $data["surname"]; + $this->first_name = $data["first_name"]; + $this->birth_date = $data["birth_date"]; + $this->gender = $data["gender"]; + $this->address = $data["address"]; + $this->postal_code = $data["postal_code"]; + $this->city = $data["city"]; + $this->country = $data["country"]; + $this->phone_number = $data["phone_number"]; + $this->school = $data["school"]; + $this->class = SchoolClass::fromName($data["class"]); + $this->responsible_name = $data["responsible_name"]; + $this->responsible_phone = $data["responsible_phone"]; + $this->responsible_email = $data["responsible_email"]; + $this->description = $data["description"]; + $this->role = Role::fromName($data["role"]); + $this->team_id = $data["team_id"]; + $this->year = $data["year"]; + $this->confirm_email = $data["confirm_email"]; + $this->forgotten_password = $data["forgotten_password"]; + $this->inscription_date = $data["inscription_date"]; + } + public static function getOrganizers() + { + global $DB, $YEAR; + $admins = []; + $req = $DB->query("SELECT * FROM `users` WHERE `role` = 'ORGANIZER' OR `role` = 'ADMIN' AND `year` = $YEAR ORDER BY `role` DESC, `surname`, `first_name`;"); + + while (($data = $req->fetch()) !== false) { + $admin = new User(); + $admin->fill($data); + $admins[] = $admin; + } + + return $admins; + } + + public static function getAdmins() + { + global $DB, $YEAR; + $users = []; + $req = $DB->query("SELECT * FROM `users` WHERE (`role` = 'ADMIN') " + . "AND `year` = $YEAR ORDER BY `role`, `inscription_date`;"); + + while (($data = $req->fetch()) !== false) { + $orphan = new User(); + $orphan->fill($data); + $users[] = $orphan; + } + + return $users; + } + + public static function getAllUsers() + { + global $DB, $YEAR; + $users = []; + $req = $DB->query("SELECT * FROM `users` WHERE `year` = $YEAR ORDER BY `role` DESC, `inscription_date`;"); + + while (($data = $req->fetch()) !== false) { + $orphan = new User(); + $orphan->fill($data); + $users[] = $orphan; + } + + return $users; + } + + public static function getOrphanUsers() + { + global $DB, $YEAR; + $orphans = []; + $req = $DB->query("SELECT * FROM `users` WHERE `role` != 'ADMIN' AND `team_id` IS NULL " + . "AND `year` = $YEAR ORDER BY `role`, `inscription_date`;"); + + while (($data = $req->fetch()) !== false) { + $orphan = new User(); + $orphan->fill($data); + $orphans[] = $orphan; + } + + return $orphans; + } + + public function getEmail() + { + return $this->email; + } + + public function setEmail($email) + { + global $DB; + $this->email = $email; + $DB->prepare("UPDATE `users` SET `email` = ? WHERE `id` = ?;")->execute([$email, $this->getId()]); + } + + public function getId() + { + return $this->id; + } + + public function checkPassword($password) + { + return password_verify($password, $this->pwd_hash); + } + + public function setPassword($password) + { + $this->setPasswordHash(password_hash($password, PASSWORD_BCRYPT)); + } + + private function setPasswordHash($password_hash) + { + global $DB; + $this->pwd_hash = $password_hash; + $DB->prepare("UPDATE `users` SET `pwd_hash` = ? WHERE `id` = ?;")->execute([$password_hash, $this->getId()]); + } + + public function getSurname() + { + return $this->surname; + } + + public function setSurname($surname) + { + global $DB; + $this->surname = $surname; + $DB->prepare("UPDATE `users` SET `surname` = ? WHERE `id` = ?;")->execute([$surname, $this->getId()]); + } + + public function getFirstName() + { + return $this->first_name; + } + + public function setFirstName($first_name) + { + global $DB; + $this->first_name = $first_name; + $DB->prepare("UPDATE `users` SET `first_name` = ? WHERE `id` = ?;")->execute([$first_name, $this->getId()]); + } + + public function getBirthDate() + { + return $this->birth_date; + } + + public function setBirthDate($birth_date) + { + global $DB; + $this->birth_date = $birth_date; + $DB->prepare("UPDATE `users` SET `birth_date` = ? WHERE `id` = ?;")->execute([$birth_date, $this->getId()]); + } + + public function getGender() + { + return $this->gender; + } + + public function setGender($gender) + { + global $DB; + $this->gender = $gender; + $DB->prepare("UPDATE `users` SET `gender` = ? WHERE `id` = ?;")->execute([$gender, $this->getId()]); + } + + public function getAddress() + { + return $this->address; + } + + public function setAddress($address) + { + global $DB; + $this->address = $address; + $DB->prepare("UPDATE `users` SET `address` = ? WHERE `id` = ?;")->execute([$address, $this->getId()]); + } + + public function getPostalCode() + { + return $this->postal_code; + } + + public function setPostalCode($postal_code) + { + global $DB; + $this->postal_code = $postal_code; + $DB->prepare("UPDATE `users` SET `postal_code` = ? WHERE `id` = ?;")->execute([$postal_code, $this->getId()]); + } + + public function getCity() + { + return $this->city; + } + + public function setCity($city) + { + global $DB; + $this->city = $city; + $DB->prepare("UPDATE `users` SET `city` = ? WHERE `id` = ?;")->execute([$city, $this->getId()]); + } + + public function getCountry() + { + return $this->country; + } + + public function setCountry($country) + { + global $DB; + $this->country = $country; + $DB->prepare("UPDATE `users` SET `country` = ? WHERE `id` = ?;")->execute([$country, $this->getId()]); + } + + public function getPhoneNumber() + { + return $this->phone_number; + } + + public function setPhoneNumber($phone_number) + { + global $DB; + $this->phone_number = $phone_number; + $DB->prepare("UPDATE `users` SET `phone_number` = ? WHERE `id` = ?;")->execute([$phone_number, $this->getId()]); + } + + public function getSchool() + { + return $this->school; + } + + public function setSchool($school) + { + global $DB; + $this->school = $school; + $DB->prepare("UPDATE `users` SET `school` = ? WHERE `id` = ?;")->execute([$school, $this->getId()]); + } + + public function getClass() + { + return $this->class; + } + + public function setClass($class) + { + global $DB; + $this->class = $class; + $DB->prepare("UPDATE `users` SET `class` = ? WHERE `id` = ?;")->execute([SchoolClass::getName($class), $this->getId()]); + } + + public function getResponsibleName() + { + return $this->responsible_name; + } + + public function setResponsibleName($responsible_name) + { + global $DB; + $this->responsible_name = $responsible_name; + $DB->prepare("UPDATE `users` SET `responsible_name` = ? WHERE `id` = ?;")->execute([$responsible_name, $this->getId()]); + } + + public function getResponsiblePhone() + { + return $this->responsible_phone; + } + + public function setResponsiblePhone($responsible_phone) + { + global $DB; + $this->responsible_phone = $responsible_phone; + $DB->prepare("UPDATE `users` SET `responsible_phone` = ? WHERE `id` = ?;")->execute([$responsible_phone, $this->getId()]); + } + + public function getResponsibleEmail() + { + return $this->responsible_email; + } + + public function setResponsibleEmail($responsible_email) + { + global $DB; + $this->responsible_email = $responsible_email; + $DB->prepare("UPDATE `users` SET `responsible_email` = ? WHERE `id` = ?;")->execute([$responsible_email, $this->getId()]); + } + + public function getDescription() + { + return $this->description; + } + + public function setDescription($desc) + { + global $DB; + $this->description = $desc; + $DB->prepare("UPDATE `users` SET `description` = ? WHERE `id` = ?;")->execute([$desc, $this->getId()]); + } + + public function getRole() + { + return $this->role; + } + + public function setRole($role) + { + global $DB; + $this->role = $role; + /** @noinspection PhpUndefinedMethodInspection */ + $DB->prepare("UPDATE `users` SET `role` = ? WHERE `id` = ?;")->execute([Role::getName($role), $this->getId()]); + } + + public function getTeamId() + { + return $this->team_id; + } + + public function setTeamId($team_id) + { + global $DB; + $this->team_id = $team_id; + $DB->prepare("UPDATE `users` SET `team_id` = ? WHERE `id` = ?;")->execute([$team_id, $this->getId()]); + } + + public function getYear() + { + return $this->year; + } + + public function getConfirmEmailToken() + { + return $this->confirm_email; + } + + public function setConfirmEmailToken($token) + { + global $DB; + $this->confirm_email = $token; + $DB->prepare("UPDATE `users` SET `confirm_email` = ? WHERE `id` = ?;")->execute([$token, $this->getId()]); + } + + public function getForgottenPasswordToken() + { + return $this->forgotten_password; + } + + public function setForgottenPasswordToken($token) + { + global $DB; + $this->forgotten_password = $token; + $DB->prepare("UPDATE `users` SET `forgotten_password` = ? WHERE `id` = ?;")->execute([$token, $this->getId()]); + } + + public function getInscriptionDate() + { + return $this->inscription_date; + } + + public function getAllDocuments($tournament_id) + { + global $DB; + $req = $DB->query("SELECT * FROM `documents` AS `t1` " + . "INNER JOIN (SELECT `user`, `type`, `tournament`, MAX(`uploaded_at`) AS `last_upload`, COUNT(`team`) AS `version` FROM `documents` GROUP BY `tournament`, `type`, `user`) `t2` " + . "ON `t1`.`user` = `t2`.`user` AND `t1`.`type` = `t2`.`type` AND `t1`.`tournament` = `t2`.`tournament` " + . "WHERE `t1`.`uploaded_at` = `t2`.`last_upload` AND `t1`.`tournament` = $tournament_id AND `t1`.`user` = $this->id ORDER BY `t1`.`type`;"); + + $docs = []; + + while (($data = $req->fetch()) !== false) + $docs[] = Document::fromData($data); + + if ($this->team_id > 0) { + $req = $DB->query("SELECT * FROM `documents` AS `t1` " + . "INNER JOIN (SELECT `user`, `type`, `tournament`, MAX(`uploaded_at`) AS `last_upload`, COUNT(`team`) AS `version` FROM `documents` GROUP BY `tournament`, `type`, `user`) `t2` " + . "ON `t1`.`user` = `t2`.`user` AND `t1`.`type` = `t2`.`type` AND `t1`.`tournament` = `t2`.`tournament` " + . "WHERE `t1`.`uploaded_at` = `t2`.`last_upload` AND `t1`.`tournament` = $tournament_id AND `t1`.`team` = $this->team_id " + . "AND `t1`.`type` = 'MOTIVATION_LETTER';"); + + while (($data = $req->fetch()) !== false) + $docs[] = Document::fromData($data); + } + + return $docs; + } + + public function getPayment() { + global $DB; + + $team = Team::fromId($this->team_id); + $tournament = $team->getEffectiveTournament(); + + $req = $DB->prepare("SELECT `id` FROM `payments` WHERE `user` = ?;"); + $req->execute([$this->id]); + + if (($data = $req->fetch()) !== false) + return Payment::fromId($data["id"]); + + $req = $DB->prepare("INSERT INTO `payments`(`user`, `tournament`, `amount`, `method`, `transaction_infos`, `validation_status`) VALUES (?, ?, ?, ?, ?, ?);"); + $req->execute([$this->id, $tournament->getId(), 0, PaymentMethod::getName(PaymentMethod::NOT_PAID), "L'inscription n'est pas encore payée.", ValidationStatus::getName(ValidationStatus::NOT_READY)]); + + return $this->getPayment(); + } + + public function getOrganizedTournaments() + { + global $DB; + $req = $DB->query("SELECT `tournament` FROM `organizers` JOIN `tournaments` ON `tournaments`.`id` = `tournament` WHERE `organizer` = $this->id ORDER BY `date_start`, `name`;"); + + $tournaments = []; + + while (($data = $req->fetch()) !== false) + $tournaments[] = Tournament::fromId($data["tournament"]); + + return $tournaments; + } +} \ No newline at end of file diff --git a/server_files/classes/ValidationStatus.php b/server_files/classes/ValidationStatus.php new file mode 100644 index 0000000..459d7ad --- /dev/null +++ b/server_files/classes/ValidationStatus.php @@ -0,0 +1,41 @@ + PDO::ERRMODE_EXCEPTION)); +} +catch (Exception $ex) { + die("Erreur lors de la connexion à la base de données : " . $ex->getMessage()); +} + +date_default_timezone_set("Europe/Paris"); + +session_start(); +setlocale(LC_ALL, "fr_FR.utf8"); diff --git a/server_files/controllers/ajouter_equipe.php b/server_files/controllers/ajouter_equipe.php new file mode 100644 index 0000000..95112bb --- /dev/null +++ b/server_files/controllers/ajouter_equipe.php @@ -0,0 +1,63 @@ +query("SELECT `id`, `name` FROM `tournaments` WHERE `date_inscription` > CURRENT_TIMESTAMP AND `year` = $YEAR;"); + +$has_error = false; +$error_message = null; + +if (isset($_POST["add_team"])) { + $new_team = new NewTeam($_POST); + try { + $new_team->makeVerifications(); + $new_team->register(); + } + catch (AssertionError $e) { + $has_error = true; + $error_message = $e->getMessage(); + } +} + +class NewTeam { + public $name; + public $trigram; + public $tournament_id; + public $tournament; + public $access_code; + + public function __construct($data) + { + foreach ($data as $key => $value) + $this->$key = htmlspecialchars($value); + } + + public function makeVerifications() { + ensure($_SESSION["team"] == null, "Vous êtes déjà dans une équipe."); + ensure($this->name != null && $this->name != "", "Vous devez spécifier un nom d'équipe."); + ensure(preg_match("#^[A-Z]{3}$#", $this->trigram), "Le trigramme entré n'est pas valide."); + ensure(!teamExists($this->name), "Une équipe existe déjà avec ce nom."); + ensure(!trigramExists($this->trigram), "Une équipe a déjà choisi ce trigramme."); + $this->tournament = Tournament::fromId($this->tournament_id); + ensure($this->tournament != null, "Le tournoi spécifié n'existe pas."); + } + + public function register() { + global $DB, $YEAR; + + $this->access_code = genRandomPhrase(6); + + $req = $DB->prepare("INSERT INTO `teams` (`name`, `trigram`, `tournament`, `encadrant_1`, `participant_1`, `validation_status`, `access_code`, `year`) + VALUES (?, ?, ?, ?, ?, ?, ?, ?);"); + $req->execute([$this->name, $this->trigram, $this->tournament_id, $_SESSION["role"] == Role::ENCADRANT ? $_SESSION["user_id"] : NULL, + $_SESSION["role"] == Role::PARTICIPANT ? $_SESSION["user_id"] : NULL, ValidationStatus::getName(ValidationStatus::NOT_READY), $this->access_code, $YEAR]); + + $_SESSION["team"] = Team::fromTrigram($this->trigram); + $_SESSION["user"]->setTeamId($_SESSION["team"]->getId()); + + Mailer::sendAddTeamMail($_SESSION["user"], $_SESSION["team"], $this->tournament); + } +} + +require_once "server_files/views/ajouter_equipe.php"; diff --git a/server_files/controllers/ajouter_organisateur.php b/server_files/controllers/ajouter_organisateur.php new file mode 100644 index 0000000..d196a88 --- /dev/null +++ b/server_files/controllers/ajouter_organisateur.php @@ -0,0 +1,59 @@ +makeVerifications(); + $orga->register(); + } + catch (AssertionError $e) { + $has_error = true; + $error_message = $e->getMessage(); + } +} + +class NewOrganizer { + public $surname; + public $first_name; + public $email; + public $admin; + public $password; + public $token; + + public function __construct($data) + { + foreach ($data as $key => $value) + $this->$key = htmlspecialchars($value); + } + + public function makeVerifications() + { + ensure($this->surname != null && $this->surname != "", "Le nom est invalide."); + ensure($this->first_name != null && $this->first_name != "", "Le prénom est invalide."); + ensure(filter_var($this->email, FILTER_VALIDATE_EMAIL), "L'adresse e-mail est invalide."); + $this->email = strtolower($this->email); + ensure(!userExists($this->email), "Cette adresse e-mail est déjà utilisée."); + $this->admin = isset($this->admin) ? 1 : 0; + } + + public function register() { + global $DB, $YEAR; + + $this->password = genRandomPhrase(16, true); + $this->token = genRandomPhrase(64); + + $req = $DB->prepare("INSERT INTO `users`(`email`, `pwd_hash`, `surname`, `first_name`, `role`, `forgotten_password`, `year`) + VALUES (?, ?, ?, ?, ?, ?, ?);"); + $req->execute([$this->email, password_hash($this->password, PASSWORD_BCRYPT), $this->surname, $this->first_name, $this->admin ? "ADMIN" : "ORGANIZER", $this->token, $YEAR]); + + Mailer::sendAddOrganizerMail($this); + } +} + +require_once "server_files/views/ajouter_organisateur.php"; \ No newline at end of file diff --git a/server_files/controllers/ajouter_tournoi.php b/server_files/controllers/ajouter_tournoi.php new file mode 100644 index 0000000..6618de7 --- /dev/null +++ b/server_files/controllers/ajouter_tournoi.php @@ -0,0 +1,111 @@ +makeVerifications(); + $tournament->register(); + } + catch (AssertionError $e) { + $has_error = true; + $error_message = $e->getMessage(); + } +} + +class NewTournament { + public $name; + public $organizers; + public $size; + public $place; + public $price; + public $date_start; + public $date_end; + public $date_inscription; + public $time_inscription; + public $date_solutions; + public $time_solutions; + public $date_syntheses; + public $time_syntheses; + public $date_solutions_2; + public $time_solutions_2; + public $date_syntheses_2; + public $time_syntheses_2; + public $description; + public $final; + public $tournament; + + public function __construct($data) + { + foreach ($data as $key => $value) + $this->$key = ($key == "organizers" ? $value : htmlspecialchars($value)); + } + + public function makeVerifications() + { + global $FINAL; + + ensure($this->name != null && $this->name != "", "Le nom est invalide."); + ensure(!tournamentExists($this->name), "Un tournoi existe déjà avec ce nom."); + ensure(sizeof($this->organizers) > 0, "Aucun organisateur n'a été choisi."); + + $orgas = []; + foreach ($this->organizers as $orga_id) { + $orga = User::fromId($orga_id); + ensure($orga != null, "Un organisateur spécifié n'existe pas."); + ensure($orga->getRole() == Role::ORGANIZER || $orga->getRole() == Role::ADMIN, "Une personne indiquée ne peut pas organiser de tournoi."); + $orgas[] = $orga; + } + $this->organizers = $orgas; + + ensure(preg_match("#[0-9]*#", $this->size), "Le nombre d'équipes indiqué n'est pas un nombre valide."); + $this->size = intval($this->size); + ensure($this->size >= 3 && $this->size <= 15, "Un tournoi doit avoir au moins 3 et au plus 15 équipes."); + + ensure(preg_match("#[0-9]*#", $this->price), "Le tarif pour les participants n'est pas un entier valide."); + $this->price = intval($this->price); + ensure($this->price >= 0, "Le TFJM² ne va pas payer les élèves pour venir."); + ensure($this->price <= 50, "Soyons raisonnable sur le prix."); + + ensure(dateWellFormed($this->date_start), "La date de début n'est pas valide."); + ensure(dateWellFormed($this->date_end), "La date de fin n'est pas valide."); + ensure(dateWellFormed($this->date_inscription . " " . $this->time_inscription), "La date de clôture des inscriptions n'est pas valide."); + ensure(dateWellFormed($this->date_solutions . " " . $this->time_solutions), "La date limite de remise des solutions n'est pas valide."); + ensure(dateWellFormed($this->date_syntheses . " " . $this->time_syntheses), "La date limite de remise des notes de synthèse pour le tour 1 n'est pas valide."); + ensure(dateWellFormed($this->date_solutions_2 . " " . $this->time_solutions_2), "La date limite de visibilité des solutions du tour 2 n'est pas valide."); + ensure(dateWellFormed($this->date_syntheses . " " . $this->time_syntheses), "La date limite de remise des notes de synthèse pour le tour 2 n'est pas valide."); + + $this->final = $this->final ? 1 : 0; + + ensure(!$this->final || $FINAL == NULL, "Une finale nationale est déjà enregistrée."); + } + + public function register() + { + global $DB, $YEAR; + + $req = $DB->prepare("INSERT INTO `tournaments` (`name`, `size`, `place`, `price`, `description`, + `date_start`, `date_end`, `date_inscription`, `date_solutions`, `date_syntheses`, + `date_solutions_2`, `date_syntheses_2`, `final`, `year`) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"); + $req->execute([$this->name, $this->size, $this->place, $this->price, $this->description, $this->date_start, $this->date_end, + "$this->date_inscription $this->time_inscription", "$this->date_solutions $this->time_solutions", + "$this->date_syntheses $this->time_syntheses", "$this->date_solutions_2 $this->time_solutions_2", + "$this->date_syntheses_2 $this->time_syntheses_2", $this->final ? 1 : 0, $YEAR]); + + $this->tournament = Tournament::fromName($this->name); + + /** @var User $organizer */ + foreach ($this->organizers as $organizer) { + $this->tournament->addOrganizer($organizer); + Mailer::sendAddOrganizerForTournamentMail($organizer, $this->tournament); + } + } +} + +require_once "server_files/views/ajouter_tournoi.php"; diff --git a/server_files/controllers/autorisation_droit_image.php b/server_files/controllers/autorisation_droit_image.php new file mode 100644 index 0000000..41b20c5 --- /dev/null +++ b/server_files/controllers/autorisation_droit_image.php @@ -0,0 +1,52 @@ +getEffectiveTournament(); + + $majeur = $user->getBirthDate() > strval($YEAR - 18) . substr($tournament->getStartDate(), 4); + + $tex = file_get_contents("assets/Autorisation_droit_image_" . ($majeur ? "majeur" : "mineur") . ".tex"); + + $tex = preg_replace("#{PARTICIPANT_NAME}#", "\\texttt{" . $user->getFirstName() . " " . $user->getSurname() . "}", $tex); + $tex = preg_replace("#{BIRTHDAY}#", "\\texttt{" . strftime("%d %B %G", strtotime($user->getBirthDate())) . "}", $tex); + $tex = preg_replace("#{ADDRESS}#", "\\texttt{" . $user->getAddress() . ", " . $user->getPostalCode() . ", " . $user->getCity() + . ($user->getCountry() == "France" ? "" : $user->getCountry()) . "}.", $tex); +} + +$tex = preg_replace("#{TOURNAMENT_NAME}#", $tournament->getName(), $tex); +$tex = preg_replace("#{PLACE}#", $tournament->getPlace(), $tex); +$tex = preg_replace("#{START_DATE}#", strftime("%d %B", strtotime($tournament->getStartDate())), $tex); +$tex = preg_replace("#{END_DATE}#", strftime("%d %B", strtotime($tournament->getEndDate())), $tex); +$tex = preg_replace("#{YEAR}#", $YEAR, $tex); + +shell_exec("mkdir tmp"); + +file_put_contents("tmp/file.tex", $tex); + +shell_exec("pdflatex -synctex=1 -interaction=nonstopmode -shell-escape -output-directory=tmp tmp/file.tex"); +header("Content-type: application/pdf"); +readfile("tmp/file.pdf"); + +exit(0); \ No newline at end of file diff --git a/server_files/controllers/autorisation_parentale.php b/server_files/controllers/autorisation_parentale.php new file mode 100644 index 0000000..40cdc29 --- /dev/null +++ b/server_files/controllers/autorisation_parentale.php @@ -0,0 +1,44 @@ +getEffectiveTournament(); + $tex = preg_replace("#{PARTICIPANT_NAME}#", "\\texttt{" . $user->getFirstName() . " " . $user->getSurname() . "}", $tex); + $tex = preg_replace("#{BIRTHDAY}#", "\\texttt{" . strftime("%d %B %G", strtotime($user->getBirthDate())) . "}", $tex); + $tex = preg_replace("#{PRONOUN}#", $user->getGender() == "M" ? "Il" : "Elle", $tex); +} + +$tex = preg_replace("#{TOURNAMENT_NAME}#", $tournament->getName(), $tex); +$tex = preg_replace("#{PLACE}#", $tournament->getPlace(), $tex); +$tex = preg_replace("#{START_DATE}#", strftime("%d %B", strtotime($tournament->getStartDate())), $tex); +$tex = preg_replace("#{END_DATE}#", strftime("%d %B", strtotime($tournament->getEndDate())), $tex); +$tex = preg_replace("#{YEAR}#", $YEAR, $tex); + +shell_exec("mkdir tmp"); + +file_put_contents("tmp/file.tex", $tex); + +shell_exec("pdflatex -synctex=1 -interaction=nonstopmode -shell-escape -output-directory=tmp tmp/file.tex"); +header("Content-type: application/pdf"); +readfile("tmp/file.pdf"); + +exit(0); \ No newline at end of file diff --git a/server_files/controllers/confirmer_mail.php b/server_files/controllers/confirmer_mail.php new file mode 100644 index 0000000..3b2326f --- /dev/null +++ b/server_files/controllers/confirmer_mail.php @@ -0,0 +1,22 @@ +query("SELECT `email` FROM `users` WHERE `confirm_email` = '$token' AND `year` = '$YEAR';"); + if (($data = $result->fetch()) === FALSE) + $error_message = "Le jeton est invalide. Votre compte est peut-être déjà validé ?"; + else { + $DB->exec("UPDATE `users` SET `confirm_email` = NULL WHERE `confirm_email` = '$token';"); + $error_message = "Votre adresse mail a été validée ! Vous pouvez désormais vous connecter."; + $alert = "success"; + } +} +else { + $error_message = "Il n'y a pas de compte à valider !"; + $alert = "warning"; +} +require_once "server_files/views/header.php"; +echo "

$error_message

"; +require_once "server_files/views/footer.php"; diff --git a/server_files/controllers/connexion.php b/server_files/controllers/connexion.php new file mode 100644 index 0000000..47c8b69 --- /dev/null +++ b/server_files/controllers/connexion.php @@ -0,0 +1,170 @@ +makeVerifications(); + $logging_in_user->login(); + } catch (AssertionError $e) { + $has_error = true; + $error_message = $e->getMessage(); + } +} + +if (isset($_POST["forgotten_password"]) && !isset($_SESSION["user_id"])) { + $recuperate_account = new RecuperateAccount($_POST); + try { + $recuperate_account->makeVerifications(); + $recuperate_account->recuperateAccount(); + } catch (AssertionError $e) { + $has_error = true; + $error_message = $e->getMessage(); + } +} + +if (isset($_GET["reset_password"]) && isset($_GET["token"]) && !isset($_SESSION["user_id"])) { + $reset_password = new ResetPassword($_GET, $_POST); + try { + $reset_password->makeVerifications(); + if (isset($_POST["password"])) + $reset_password->resetPassword(); + } catch (AssertionError $e) { + $has_error = true; + $error_message = $e->getMessage(); + } +} + +if (isset($_GET["confirmation-mail"]) && !isset($_SESSION["user_id"])) + sendConfirmEmail(); + +class LoggingInUser +{ + public $email; + /** @var User $user */ + public $user; + private $password; + + public function __construct($data) + { + foreach ($data as $key => $value) + $this->$key = htmlspecialchars($value); + } + + public function makeVerifications() + { + global $URL_BASE; + + ensure(filter_var($this->email, FILTER_VALIDATE_EMAIL), "L'adresse email est invalide."); + $this->user = User::fromEmail($this->email); + ensure($this->user != null, "Le compte n'existe pas."); + ensure($this->user->checkPassword($this->password), "Le mot de passe est incorrect."); + if ($this->user->getConfirmEmailToken() != null) { + $_SESSION["confirm_email"] = $this->email; + throw new AssertionError("L'adresse mail n'a pas été validée. Veuillez vérifier votre boîte mail (surtout vos spams). " + . "Cliquez ici pour renvoyer le mail de confirmation."); + } + } + + public function login() + { + $_SESSION["user_id"] = $this->user->getId(); + loadUserValues(); + } +} + +class RecuperateAccount +{ + public $email; + /** @var User $user */ + public $user; + + public function __construct($data) + { + foreach ($data as $key => $value) + $this->$key = htmlspecialchars($value); + } + + public function makeVerifications() + { + ensure(filter_var($this->email, FILTER_VALIDATE_EMAIL), "L'adresse email est invalide."); + $this->user = User::fromEmail($this->email); + ensure($this->user != null, "Le compte n'existe pas."); + } + + public function recuperateAccount() + { + $token = genRandomPhrase(64); + $this->user->setForgottenPasswordToken($token); + Mailer::sendForgottenPasswordProcedureMail($this->user); + } +} + +class ResetPassword +{ + public $token; + /** @var User $user */ + public $user; + private $password; + private $confirm_password; + + public function __construct($data, $data2) + { + foreach ($data as $key => $value) + $this->$key = htmlspecialchars($value); + foreach ($data2 as $key => $value) + $this->$key = htmlspecialchars($value); + } + + public function makeVerifications() + { + global $DB; + $data = $DB->query("SELECT `id` FROM `users` WHERE `forgotten_password` = '" . $this->token . "';")->fetch(); + ensure($data !== false, "Il n'y a pas de compte à récupérer avec ce jeton."); + $this->user = User::fromId($data["id"]); + + if ($this->password == null) + return; + + ensure($this->password == $this->confirm_password, "Les deux mots de passe sont différents."); + ensure(strlen($this->password) >= 8, "Le mot de passe doit comporter au moins 8 caractères."); + } + + public function resetPassword() + { + $this->user->setForgottenPasswordToken(null); + $this->user->setPassword($this->password); + + Mailer::sendChangePasswordMail($this->user); + + return false; + } +} + +function sendConfirmEmail() +{ + global $URL_BASE; + + $email = htmlspecialchars($_SESSION["confirm_email"]); + + if (!isset($email)) { + header("Location: $URL_BASE/connexion"); + exit(); + } + + $user = User::fromEmail($email); + + if ($user === null) { + unset($_SESSION["confirm_email"]); + header("Location: $URL_BASE/connexion"); + exit(); + } + + Mailer::sendConfirmEmail($user); + + return false; +} + +require_once "server_files/views/connexion.php"; diff --git a/server_files/controllers/deconnexion.php b/server_files/controllers/deconnexion.php new file mode 100644 index 0000000..eb04b0a --- /dev/null +++ b/server_files/controllers/deconnexion.php @@ -0,0 +1,14 @@ + + +
+ Déconnexion réussie ! +
+ +getTournamentId()); + +if ($_SESSION["role"] == Role::ORGANIZER && !$tournament->organize($_SESSION["user_id"])) + require_once "server_files/403.php"; + +if ($team === null) + require_once "server_files/404.php"; + +if (isset($_POST["team_edit"])) { + $edit_team = new EditTeam($_POST); + try { + $edit_team->makeVerifications(); + $edit_team->updateTeam(); + } + catch (AssertionError $e) { + $has_error = true; + $error_message = $e->getMessage(); + } +} + +if (isset($_POST["validate"])) { + $team->setValidationStatus(ValidationStatus::VALIDATED); + Mailer::sendValidateTeam($team, $_POST["message"]); +} +elseif (isset($_POST["unvalidate"])) { + $team->setValidationStatus(ValidationStatus::NOT_READY); + Mailer::sendUnvalidateTeam($team, $_POST["message"]); +} + +if (isset($_POST["select"])) { + $team->selectForFinal(true); + # $team->setValidationStatus(ValidationStatus::NOT_READY); + $sols = $tournament->getAllSolutions($team->getId()); + /** @var Solution $sol */ + foreach ($sols as $sol) { + $old_id = $sol->getFileId(); + do + $id = genRandomPhrase(64); + while (file_exists("$LOCAL_PATH/files/$id")); + + copy("$LOCAL_PATH/files/$old_id", "$LOCAL_PATH/files/$id"); + + $req = $DB->prepare("INSERT INTO `solutions`(`file_id`, `team`, `tournament`, `problem`) VALUES (?, ?, ?, ?);"); + $req->execute([$id, $team->getId(), $FINAL->getId(), $sol->getProblem()]); + } +} + +if (isset($_POST["download_zip"])) { + $final = isset($_POST["final"]); + $tournament_dest = $final ? $FINAL : $tournament; + + $file_name = getZipFile(DocumentType::PARENTAL_CONSENT, $tournament_dest->getId(), $team->getId()); + + header("Content-Type: application/zip"); + header("Content-Disposition: attachment; filename=\"Documents de l'équipe " . $team->getTrigram() . ".zip\""); + header("Content-Length: " . strval(filesize($file_name))); + + readfile($file_name); + + exit(); +} + +if (isset($_POST["select_tournament"])) { + $new_tournament = Tournament::fromId($_POST["select_tournament"]); + ensure($new_tournament != null, "Le tournoi indiqué n'existe pas."); + $team->setTournamentId($new_tournament->getId()); + $DB->prepare("UPDATE `documents` SET `tournament` = ? WHERE `team` = ?;")->execute([$tournament->getId(), $team->getId()]); + $DB->prepare("UPDATE `solutions` SET `tournament` = ? WHERE `team` = ?;")->execute([$tournament->getId(), $team->getId()]); + $DB->prepare("UPDATE `syntheses` SET `tournament` = ? WHERE `team` = ?;")->execute([$tournament->getId(), $team->getId()]); + foreach ($team->getParticipants() as $user) { + if ($user != null) + $DB->prepare("UPDATE `payments` SET `tournament` = ? WHERE `user` = ?;")->execute([$tournament->getId(), $user]); + } + foreach ($team->getEncadrants() as $user) { + if ($user != null) + $DB->prepare("UPDATE `payments` SET `tournament` = ? WHERE `user` = ?;")->execute([$tournament->getId(), $user]); + } + $tournament = $new_tournament; +} + +if (isset($_POST["delete_team"])) { + foreach ($team->getEncadrants() as $encadrant_id) { + quitTeam($encadrant_id); + } + foreach ($team->getParticipants() as $participant_id) { + quitTeam($participant_id); + } + + header("Location: /"); + return; + +} + +class EditTeam +{ + public $name; + public $trigram; + public $tournament_id; + private $team; + private $tournament; + + public function __construct($data) + { + global $team; + + foreach ($data as $key => $value) + $this->$key = htmlspecialchars($value); + + $this->trigram = strtoupper($this->trigram); + $this->team = $team; + $this->tournament = Tournament::fromId($this->tournament_id); + } + + public function makeVerifications() + { + ensure($this->name != "" && $this->name != null, "Veuillez spécifier un nom d'équipe."); + ensure($this->name == $this->team->getName() || !teamExists($this->name), "Une équipe existe déjà avec ce nom."); + ensure(preg_match("#^[A-Z]{3}$#", $this->trigram), "Le trigramme n'est pas valide."); + ensure($this->trigram == $this->team->getTrigram() || !trigramExists($this->trigram), "Une équipe a déjà choisi ce trigramme."); + ensure($this->tournament != null, "Le tournoi indiqué n'existe pas."); + ensure($this->tournament_id == $this->team->getTournamentId() || $_SESSION["role"] == Role::ADMIN, "Vous n'avez pas la permission pour changer cette équipe de tournoi."); + } + + public function updateTeam() + { + global $URL_BASE; + + $this->team->setName($this->name); + $this->team->setTrigram($this->trigram); + $this->team->setTournamentId($this->tournament_id); + + $_SESSION["tournament"] = $this->tournament; + + header("Location: $URL_BASE/equipe/$this->trigram"); + } +} + +$documents = $tournament->getAllDocuments($team->getId()); +$documents_final = null; + +if ($team->isSelectedForFinal()) + $documents_final = $FINAL->getAllDocuments($team->getId()); + +$emails = []; + +if ($_SESSION["role"] == Role::ORGANIZER || $_SESSION["role"] == Role::ADMIN) { + foreach ($team->getEncadrants() as $encadrant_id) { + $encadrant = User::fromId($encadrant_id); + if ($encadrant != null) { + $emails[] = $encadrant->getEmail(); + } + } + + foreach ($team->getParticipants() as $participant_id) { + $participant = User::fromId($participant_id); + if ($participant != null) { + $emails[] = $participant->getEmail(); + if ($participant->getResponsibleEmail() != null) { + $emails[] = $participant->getResponsibleEmail(); + } + } + } +} + +require_once "server_files/views/equipe.php"; diff --git a/server_files/controllers/index.php b/server_files/controllers/index.php new file mode 100644 index 0000000..5a23b80 --- /dev/null +++ b/server_files/controllers/index.php @@ -0,0 +1,20 @@ +getTeamId()); + +if ($_SESSION["role"] != Role::ADMIN) { + if ($_SESSION["role"] == Role::ORGANIZER) { + if (($user->getRole() == Role::PARTICIPANT || $user->getRole() == Role::PARTICIPANT) && ($team == null || $team->getTournamentId() == null || !Tournament::fromId($team->getTournamentId())->organize($_SESSION["user_id"]))) + require_once "server_files/403.php"; + } + elseif ($user->getId() != $_SESSION["user_id"]) + require_once "server_files/403.php"; +} + +if ($user === null) + require_once "server_files/404.php"; + +if ($team != null) { + $documents = $user->getAllDocuments($team->getTournamentId()); + $documents_final = $user->getAllDocuments($FINAL->getId()); + $payment = $user->getPayment(); + $tournament = Tournament::fromId($team->getTournamentId()); +} + +$has_error = false; +$error_message = null; + +if (isset($_POST["kick"])) { + if ($team == null) { + $has_error = true; + $error_message = "La personne à expulser n'est dans aucune équipe."; + } + else { + quitTeam($id); + $team = null; + } +} + +if (isset($_POST["attribute_team"])) { + $attribute_team = new AttributeTeam($_POST); + try { + $attribute_team->makeVerifications(); + $attribute_team->attribute(); + } catch (AssertionError $e) { + $has_error = true; + $error_message = $e->getMessage(); + } +} + +if (isset($_POST["validate_payment"])) { + $validate_payment = new ValidatePayment($_POST); + try { + $validate_payment->makeVerifications(); + $validate_payment->validate(); + } catch (AssertionError $e) { + $has_error = true; + $error_message = $e->getMessage(); + } +} + +if (isset($_POST["view_as"]) && $_SESSION["role"] == Role::ADMIN) { + if (!isset($_SESSION["admin"])) + $_SESSION["admin"] = $_SESSION["user_id"]; + $_SESSION["user_id"] = $user->getId(); + header("Location: /"); + exit(); +} + +if (isset($_POST["delete_account"]) && $team == null && $_SESSION["role"] == Role::ADMIN) { + $DB->prepare("DELETE FROM `documents` WHERE `user` = ?;")->execute([$user->getId()]); + $DB->prepare("DELETE FROM `organizers` WHERE `organizer` = ?;")->execute([$user->getId()]); + $DB->prepare("DELETE FROM `users` WHERE `id` = ?;")->execute([$user->getId()]); + header("Location: /"); + exit(); +} + +class AttributeTeam +{ + private $team_id; + private $team; + private $min_null_index; + + public function __construct($data) + { + $this->team_id = htmlspecialchars($data["team"]); + $this->team = Team::fromId($this->team_id); + } + + public function makeVerifications() + { + global $user; + + ensure($user->getConfirmEmailToken() == null, "Ce participant n'a pas encore validé son adresse e-mail."); + ensure($this->team_id != "no_team", "Vous n'avez pas choisi d'équipe."); + ensure($this->team != null, "Cette équipe n'existe pas."); + ensure($user->getTeamId() <= 0, "Cette personne est déjà dans une équipe !"); + ensure($this->team->getValidationStatus() == ValidationStatus::NOT_READY, "Cette équipe est déjà validée ou en cours de validation."); + + $role = $user->getRole(); + for ($i = 1; $i <= $role == Role::ENCADRANT ? 3 : 6; ++$i) { + if (($role == Role::PARTICIPANT ? $this->team->getParticipants()[$i - 1] : $this->team->getEncadrants()[$i]) == NULL) + break; + } + + $this->min_null_index = $i; + + ensure($role == Role::PARTICIPANT && $this->min_null_index <= 6 || $role == Role::ENCADRANT && $this->min_null_index <= 2, + "Il n'y a plus de place pour vous dans l'équipe."); + } + + public function attribute() + { + global $user, $team; + + $user->setTeamId($this->team->getId()); + + if ($user->getRole() == Role::ENCADRANT) + $this->team->setEncadrant($this->min_null_index, $user->getId()); + else + $this->team->setParticipant($this->min_null_index, $user->getId()); + + Mailer::sendJoinTeamMail($user, $this->team, Tournament::fromId($this->team->getTournamentId())); + + $team = $this->team; + + global $documents, $payment, $tournament; + + $documents = $user->getAllDocuments($team->getTournamentId()); + $payment = $user->getPayment(); + $tournament = Tournament::fromId($team->getTournamentId()); + } +} + +class ValidatePayment +{ + private $accept, $reject; + private $message; + private $payment; + + public function __construct($data) + { + global $user; + + foreach ($data as $key => $value) + $this->$key = htmlspecialchars($value); + + $this->payment = $user->getPayment(); + } + + public function makeVerifications() + { + ensure($this->payment->getValidationStatus() == ValidationStatus::WAITING, "Le paiement n'était pas en attente."); + ensure(isset($this->accept) ^ isset($this->reject), "La sélection de validation est invalide."); + } + + public function validate() + { + global $user, $team, $tournament; + + if ($this->accept) + $this->payment->setValidationStatus(ValidationStatus::VALIDATED); + else + $this->payment->setValidationStatus(ValidationStatus::NOT_READY); + + Mailer::sendValidatePayment($user, $team, $tournament, $this->payment, $this->message); + } +} + +require_once "server_files/views/informations.php"; diff --git a/server_files/controllers/inscription.php b/server_files/controllers/inscription.php new file mode 100644 index 0000000..d0ab6f3 --- /dev/null +++ b/server_files/controllers/inscription.php @@ -0,0 +1,99 @@ +makeVerifications(); + $user->register(); + } catch (AssertionError $e) { + $has_error = true; + $error_message = $e->getMessage(); + } +} + +class NewUser +{ + public $email; + public $first_name; + public $surname; + public $birth_date; + public $gender; + public $address = ""; + public $postal_code; + public $city = ""; + public $country; + public $phone_number; + public $role; + public $school; + public $class; + public $responsible_name; + public $responsible_phone; + public $responsible_email; + public $description; + public $confirm_email_token; + private $password; + private $confirm_password; + + public function __construct($data) + { + foreach ($data as $key => $value) + $this->$key = htmlspecialchars($value); + } + + public function makeVerifications() + { + global $YEAR; + + ensure(filter_var($this->email, FILTER_VALIDATE_EMAIL), "L'adresse e-mail entrée est invalide."); + $this->email = strtolower($this->email); + ensure(!userExists($this->email), "Un compte existe déjà avec cette adresse e-mail."); + ensure(strlen($this->password) >= 8, "Le mot de passe doit comporter au moins 8 caractères."); + ensure($this->password == $this->confirm_password, "Les deux mots de passe sont différents."); + ensure($this->surname != "", "Le nom de famille est obligatoire."); + ensure($this->first_name != "", "Le prénom est obligatoire."); + ensure(dateWellFormed($this->birth_date), "La date de naissance est invalide."); + ensure($this->birth_date < $YEAR . "-01-01", "Vous devez être né."); + ensure($this->gender == "M" || $this->gender == "F", "Merci de spécifier un genre."); + ensure(preg_match("#^[0-9]{4}[0-9]?$#", $this->postal_code) && intval($this->postal_code) >= 01000 && intval($this->postal_code) <= 95999, "Le code postal est invalide."); + if ($this->country == "") + $this->country = "France"; + ensure(strlen($this->phone_number) >= 10 && strlen($this->phone_number) <= 20, "Le numéro de téléphone est invalide."); + $this->role = Role::fromName(strtoupper($this->role)); + + if ($this->role == Role::PARTICIPANT) { + $this->class = SchoolClass::fromName(strtoupper($this->class)); + if ($this->birth_date > strval($YEAR - 18) . "04-01") { + ensure($this->responsible_name != "", "Veuillez spécifier un responsable légal."); + ensure(strlen($this->responsible_phone) >= 10, "Veuillez rentrer le numéro de téléphone de votre responsable légal."); + ensure(filter_var($this->responsible_email, FILTER_VALIDATE_EMAIL), "Veuillez spécifier un responsable légal."); + } + } + else { + $this->class = SchoolClass::ADULT; + } + + if (count(User::getAllUsers()) == 0) + $this->role = Role::ADMIN; + + $this->confirm_email_token = genRandomPhrase(64); + } + + public function register() + { + global $DB, $YEAR; + + $req = $DB->prepare("INSERT INTO `users`(`email`, `pwd_hash`, `confirm_email`, `surname`, `first_name`, `birth_date`, `gender`, + `address`, `postal_code`, `city`, `country`, `phone_number`, `school`, `class`, `role`, `description`, `responsible_name`, `responsible_phone`, `responsible_email`, `year`) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"); + $req->execute([$this->email, password_hash($this->password, PASSWORD_BCRYPT), $this->confirm_email_token, $this->surname, $this->first_name, $this->birth_date, $this->gender, $this->address, + $this->postal_code, $this->city, $this->country, $this->phone_number, $this->school, SchoolClass::getName($this->class), Role::getName($this->role), $this->description, $this->responsible_name, $this->responsible_phone, $this->responsible_email, $YEAR]); + + Mailer::sendRegisterMail($this); + } +} + +require_once "server_files/views/inscription.php"; diff --git a/server_files/controllers/instructions.php b/server_files/controllers/instructions.php new file mode 100644 index 0000000..20b58b4 --- /dev/null +++ b/server_files/controllers/instructions.php @@ -0,0 +1,36 @@ +getEffectiveTournament(); +} + +$tex = preg_replace("#{TOURNAMENT_NAME}#", $tournament->getName(), $tex); +$tex = preg_replace("#{PLACE}#", $tournament->getPlace(), $tex); +$tex = preg_replace("#{PRICE}#", $tournament->getPrice(), $tex); +$tex = preg_replace("#{END_PAYMENT_DATE}#", strftime("%d %B", strtotime($tournament->getInscriptionDate())), $tex); +$tex = preg_replace("#{YEAR}#", $YEAR, $tex); + +shell_exec("mkdir tmp"); +file_put_contents("tmp/file.tex", $tex); +shell_exec("pdflatex -synctex=1 -interaction=nonstopmode -shell-escape -output-directory=tmp tmp/file.tex"); +header("Content-type: application/pdf"); +readfile("tmp/file.pdf"); +shell_exec("rm -rf tmp"); + +exit(0); \ No newline at end of file diff --git a/server_files/controllers/mon_compte.php b/server_files/controllers/mon_compte.php new file mode 100644 index 0000000..71d26cf --- /dev/null +++ b/server_files/controllers/mon_compte.php @@ -0,0 +1,220 @@ +getTournamentId()); + +$has_error = false; +$error_message = null; + +if (isset($_POST["update_account"])) { + $my_account = new MyAccount($_POST); + try { + $my_account->makeVerifications(); + $my_account->updateAccount(); + } + catch (AssertionError $e) { + $has_error = true; + $error_message = $e->getMessage(); + } +} + +if (isset($_POST["update_password"])) { + $new_password = new NewPassword($_POST); + try { + $new_password->makeVerifications(); + $new_password->updatePassword(); + } + catch (AssertionError $e) { + $has_error = true; + $error_message = $e->getMessage(); + } +} + +if (isset($_POST["send_document"])) { + $send_document = new SendDocument(); + try { + $send_document->makeVerifications(); + $send_document->sendDocument(); + } + catch (AssertionError $e) { + $has_error = true; + $error_message = $e->getMessage(); + } +} + +class MyAccount +{ + public $email; + public $surname; + public $first_name; + public $birth_date; + public $gender; + public $address; + public $postal_code; + public $city; + public $country; + public $phone_number; + public $school; + public $class; + public $responsible_name; + public $responsible_phone; + public $responsible_email; + public $description; + private $user; + + public function __construct($data) + { + foreach ($data as $key => $value) + $this->$key = htmlspecialchars($value); + + $this->user = $_SESSION["user"]; + + $keys = ["email", "surname", "first_name", "birth_date", "gender", "address", "postal_code", "city", "country", "phone_number", + "school", "class", "responsible_name", "responsible_phone", "responsible_email", "description"]; + + if ($this->user->getRole() == Role::PARTICIPANT) + $this->class = SchoolClass::fromName(strtoupper($this->class)); + else + $this->class = SchoolClass::ADULT; + + foreach ($keys as $key) + $this->$key = $this->$key != null && $this->$key != "" ? $this->$key : $this->user->$key; + } + + public function makeVerifications() + { + global $YEAR; + + ensure(filter_var($this->email, FILTER_VALIDATE_EMAIL), "L'adresse e-mail entrée est invalide."); + $this->email = strtolower($this->email); + ensure($this->email == $this->user->getEmail() || !userExists($this->email), "Un compte existe déjà avec cette adresse e-mail."); + ensure(dateWellFormed($this->birth_date), "La date de naissance est invalide."); + ensure($this->birth_date < $YEAR . "-01-01", "Vous devez être né."); + ensure($this->gender == "M" || $this->gender == "F", "Merci de spécifier un genre."); + ensure(preg_match("#^[0-9]{4}[0-9]?$#", $this->postal_code) && intval($this->postal_code) >= 01000 && intval($this->postal_code) <= 95999, "Le code postal est invalide."); + ensure(strlen($this->phone_number) >= 10, "Le numéro de téléphone est invalide."); + + if ($this->user->getRole() == Role::PARTICIPANT) { + if ($this->birth_date > strval($YEAR - 18) . "04-01") { + ensure($this->responsible_name != "", "Veuillez spécifier un responsable légal."); + ensure(strlen($this->responsible_phone) >= 10, "Veuillez rentrer le numéro de téléphone de votre responsable légal."); + ensure(filter_var($this->responsible_email, FILTER_VALIDATE_EMAIL), "Veuillez spécifier un responsable légal."); + } + } + } + + public function updateAccount() + { + $this->user->setSurname($this->surname); + $this->user->setFirstName($this->first_name); + $this->user->setBirthDate($this->birth_date); + $this->user->setGender($this->gender); + $this->user->setAddress($this->address); + $this->user->setPostalCode($this->postal_code); + $this->user->setCity($this->city); + $this->user->setCountry($this->country); + $this->user->setPhoneNumber($this->phone_number); + $this->user->setSchool($this->school); + $this->user->setClass($this->class); + $this->user->setResponsibleName($this->responsible_name); + $this->user->setResponsiblePhone($this->responsible_phone); + $this->user->setResponsibleEmail($this->responsible_email); + $this->user->setDescription($this->description); + + if ($this->email != $this->user->getEmail()) { + $this->user->setEmail($this->email); + $this->user->setConfirmEmailToken(genRandomPhrase(64)); + + Mailer::sendChangeEmailAddressMail($this->user); + } + } +} + +class NewPassword +{ + private $user; + private $old_password; + private $new_password; + private $confirm_password; + + public function __construct($data) + { + foreach ($data as $key => $value) + $this->$key = htmlspecialchars($value); + + $this->user = $_SESSION["user"]; + } + + public function makeVerifications() + { + ensure($this->user->checkPassword($this->old_password), "L'ancien mot de passe est incorrect."); + ensure(strlen($this->new_password) >= 8, "Le mot de passe doit comporter au moins 8 caractères."); + ensure($this->new_password == $this->confirm_password, "Les deux mots de passe sont différents."); + } + + public function updatePassword() + { + $this->user->setPassword($this->new_password); + + Mailer::sendChangePasswordMail($this->user); + } +} + +class SendDocument +{ + private $file; + private $type; + + public function __construct() + { + $this->file = $_FILES["document"]; + $this->type = strtoupper(htmlspecialchars($_POST["type"])); + } + + public function makeVerifications() + { + global $LOCAL_PATH; + + ensure($this->file["size"] <= 2e6, "Le fichier doit peser moins que 2 Mo."); + ensure(!$this->file["error"], "Une erreur est survenue."); + $mime = finfo_file(finfo_open(FILEINFO_MIME_TYPE), $this->file["tmp_name"]); + ensure($mime == "application/pdf" || $mime = "image/png" || $mime == "image/jpeg", "Le fichier doit être au format PDF."); + ensure(is_dir("$LOCAL_PATH/files") || mkdir("$LOCAL_PATH/files"), "Un problème est survenue dans l'envoi du fichier. Veuillez contacter l'administrateur du serveur."); + } + + public function sendDocument() + { + global $LOCAL_PATH, $DB, $FINAL; + + do + $id = genRandomPhrase(64); + while (file_exists("$LOCAL_PATH/files/$id")); + + if (!rename($this->file["tmp_name"], "$LOCAL_PATH/files/$id")) + throw new AssertionError("Une erreur est survenue lors de l'envoi du fichier."); + + $req = $DB->prepare("INSERT INTO `documents`(`file_id`, `user`, `team`, `tournament`, `type`) + VALUES (?, ?, ?, ?, ?);"); + $req->execute([$id, $this->type == DocumentType::getName(DocumentType::MOTIVATION_LETTER) ? -1 : $_SESSION["user_id"], $_SESSION["team"]->getId(), + $_SESSION["team"]->isSelectedForFinal() ? $FINAL->getId() : $_SESSION["team"]->getTournamentId(), $this->type]); + } +} + +if ($team != null) { + $documents = $user->getAllDocuments($team->getTournamentId()); + if ($team->isSelectedForFinal()) + $documents_final = $user->getAllDocuments($FINAL->getId()); +} + +require_once "server_files/views/mon_compte.php"; diff --git a/server_files/controllers/mon_equipe.php b/server_files/controllers/mon_equipe.php new file mode 100644 index 0000000..e165dcb --- /dev/null +++ b/server_files/controllers/mon_equipe.php @@ -0,0 +1,193 @@ +makeVerifications(); + $my_team->updateTeam(); + } + catch (AssertionError $e) { + $has_error = true; + $error_message = $e->getMessage(); + } +} + +if (isset($_SESSION["user_id"]) && isset($_SESSION["team"]) && $_SESSION["team"] !== null) { + /** + * @var User $user + * @var Team $team + */ + $user = $_SESSION["user"]; + $team = $_SESSION["team"]; + + $tournament = Tournament::fromId($team->getTournamentId()); + $documents = $tournament->getAllDocuments($team->getId()); + if ($team->isSelectedForFinal()) + $documents_final = $FINAL->getAllDocuments($team->getId()); +} +else + require_once "server_files/403.php"; + +if (isset($_POST["request_validation"])) { + if (!canValidate($team, $tournament)) + $error_message = "Votre équipe ne peut pas demander la validation : il manque soit des participants, soit des documents."; + else { + $team->setValidationStatus(ValidationStatus::WAITING); + Mailer::sendRequestValidationMail($team, $team->isSelectedForFinal() ? $FINAL : $tournament); + } +} + +$DUMPS = [ + ["TKT", 6, "PGA", 3, "IRD", 1], + ["OUI", 8, "LEP", 1, "REX", 7], + ["ASP", 1, "ABC", 3, "TDP", 6], + ["GIF", 8, "ETM", 1, "LPC", 3], + ["MST", 6, "LQF", 1, "WAL", 2], +]; + +$DUMPS_2 = [ + ["TKT", 4, "PGA", 1, "IRD", 6], + ["LEP", 6, "OUI", 5, "REX", 8], + ["ASP", 5, "ABC", 8, "TDP", 4], + ["ETM", 8, "LPC", 4, "GIF", 6], + ["MST", 5, "LQF", 4, "WAL", 8], +]; + +foreach ($DUMPS as $dump) { + $team1 = Team::fromTrigram($dump[0]); + $team2 = Team::fromTrigram($dump[2]); + $team3 = Team::fromTrigram($dump[4]); + $problem1 = $dump[1]; + $problem2 = $dump[3]; + $problem3 = $dump[5]; + + $req1 = $DB->prepare("SELECT * FROM `solutions` WHERE `team` = ? AND `problem` = ? ORDER BY uploaded_at DESC LIMIT 1"); + $req1->execute([$team1->getId(), $problem1]); + $data1 = $req1->fetch(); + $sol1 = Solution::fromData($data1); + $req2 = $DB->prepare("SELECT * FROM `solutions` WHERE `team` = ? AND `problem` = ? ORDER BY uploaded_at DESC LIMIT 1"); + $req2->execute([$team2->getId(), $problem2]); + $data2 = $req2->fetch(); + $sol2 = Solution::fromData($data2); + $req3 = $DB->prepare("SELECT * FROM `solutions` WHERE `team` = ? AND `problem` = ? ORDER BY uploaded_at DESC LIMIT 1"); + $req3->execute([$team3->getId(), $problem3]); + $data3 = $req3->fetch(); + $sol3 = Solution::fromData($data3); + + $req1 = $DB->prepare("UPDATE `teams` SET `opposed_problem` = ?, `rapported_problem` = ? WHERE `id` = ?;"); + $req1->execute([$sol2->getFileId(), $sol3->getFileId(), $team1->getId()]); + + $req2 = $DB->prepare("UPDATE `teams` SET `opposed_problem` = ?, `rapported_problem` = ? WHERE `id` = ?;"); + $req2->execute([$sol3->getFileId(), $sol1->getFileId(), $team2->getId()]); + + $req3 = $DB->prepare("UPDATE `teams` SET `opposed_problem` = ?, `rapported_problem` = ? WHERE `id` = ?;"); + $req3->execute([$sol1->getFileId(), $sol2->getFileId(), $team3->getId()]); +} + +foreach ($DUMPS_2 as $dump) { + $team1 = Team::fromTrigram($dump[0]); + $team2 = Team::fromTrigram($dump[2]); + $team3 = Team::fromTrigram($dump[4]); + $problem1 = $dump[1]; + $problem2 = $dump[3]; + $problem3 = $dump[5]; + + $req1 = $DB->prepare("SELECT * FROM `solutions` WHERE `team` = ? AND `problem` = ? ORDER BY uploaded_at DESC LIMIT 1"); + $req1->execute([$team1->getId(), $problem1]); + $data1 = $req1->fetch(); + $sol1 = Solution::fromData($data1); + $req2 = $DB->prepare("SELECT * FROM `solutions` WHERE `team` = ? AND `problem` = ? ORDER BY uploaded_at DESC LIMIT 1"); + $req2->execute([$team2->getId(), $problem2]); + $data2 = $req2->fetch(); + $sol2 = Solution::fromData($data2); + $req3 = $DB->prepare("SELECT * FROM `solutions` WHERE `team` = ? AND `problem` = ? ORDER BY uploaded_at DESC LIMIT 1"); + $req3->execute([$team3->getId(), $problem3]); + $data3 = $req3->fetch(); + $sol3 = Solution::fromData($data3); + + $req1 = $DB->prepare("UPDATE `teams` SET `opposed_problem_2` = ?, `rapported_problem_2` = ? WHERE `id` = ?;"); + $req1->execute([$sol2->getFileId(), $sol3->getFileId(), $team1->getId()]); + + $req2 = $DB->prepare("UPDATE `teams` SET `opposed_problem_2` = ?, `rapported_problem_2` = ? WHERE `id` = ?;"); + $req2->execute([$sol3->getFileId(), $sol1->getFileId(), $team2->getId()]); + + $req3 = $DB->prepare("UPDATE `teams` SET `opposed_problem_2` = ?, `rapported_problem_2` = ? WHERE `id` = ?;"); + $req3->execute([$sol1->getFileId(), $sol2->getFileId(), $team3->getId()]); +} + + +$req = $DB->prepare("SELECT opposed_problem, rapported_problem, opposed_problem_2, rapported_problem_2 FROM teams WHERE id = ?;"); +$req->execute([$team->getId()]); +$data = $req->fetch(); + +$opposed_solution = Solution::fromId($data["opposed_problem"]); +$rapported_solution = Solution::fromId($data["rapported_problem"]); +$opposed_solution_2 = Solution::fromId($data["opposed_problem_2"]); +$rapported_solution_2 = Solution::fromId($data["rapported_problem_2"]); + +class MyTeam +{ + public $name; + public $trigram; + public $tournament_id; + private $team; + private $tournament; + + public function __construct($data) + { + foreach ($data as $key => $value) + $this->$key = htmlspecialchars($value); + + $this->trigram = strtoupper($this->trigram); + $this->team = $_SESSION["team"]; + $this->tournament = Tournament::fromId($this->tournament_id); + } + + public function makeVerifications() + { + ensure($this->name != "" && $this->name != null, "Veuillez spécifier un nom d'équipe."); + ensure($this->name == $this->team->getName() || !teamExists($this->name), "Une équipe existe déjà avec ce nom."); + ensure(preg_match("#^[A-Z]{3}$#", $this->trigram), "Le trigramme n'est pas valide."); + ensure($this->trigram == $this->team->getTrigram() || !trigramExists($this->trigram), "Une équipe a déjà choisi ce trigramme."); + ensure($this->tournament != null, "Le tournoi indiqué n'existe pas."); + ensure(date("Y-m-d H:i:s") <= $this->tournament->getInscriptionDate(), "Les inscriptions sont terminées."); + ensure($this->team->getValidationStatus() == ValidationStatus::NOT_READY, "Votre équipe est déjà validée ou en cours de validation."); + } + + public function updateTeam() + { + global $URL_BASE, $DB; + + $this->team->setName($this->name); + $this->team->setTrigram($this->trigram); + $this->team->setTournamentId($this->tournament_id); + + $DB->prepare("UPDATE `documents` SET `tournament` = ? WHERE `team` = ?;")->execute([$this->tournament_id, $this->team->getId()]); + $DB->prepare("UPDATE `solutions` SET `tournament` = ? WHERE `team` = ?;")->execute([$this->tournament_id, $this->team->getId()]); + $DB->prepare("UPDATE `syntheses` SET `tournament` = ? WHERE `team` = ?;")->execute([$this->tournament_id, $this->team->getId()]); + foreach ($this->team->getParticipants() as $user) { + if ($user != null) + $DB->prepare("UPDATE `payments` SET `tournament` = ? WHERE `user` = ?;")->execute([$this->tournament_id, $user]); + } + foreach ($this->team->getEncadrants() as $user) { + if ($user != null) + $DB->prepare("UPDATE `payments` SET `tournament` = ? WHERE `user` = ?;")->execute([$this->tournament_id, $user]); + } + + $_SESSION["tournament"] = $this->tournament; + + header("Location: $URL_BASE/mon-equipe"); + } +} + +require_once "server_files/views/mon_equipe.php"; diff --git a/server_files/controllers/organisateurs.php b/server_files/controllers/organisateurs.php new file mode 100644 index 0000000..bfe340e --- /dev/null +++ b/server_files/controllers/organisateurs.php @@ -0,0 +1,8 @@ +getEffectiveTournament(); +$payment = $user->getPayment(); + +if ($team->getValidationStatus() != ValidationStatus::VALIDATED) + require_once "server_files/403.php"; + +if (isset($_POST["pay"])) { + $pay = new Pay($_POST); + try { + $pay->makeVerifications(); + $pay->submit(); + } + catch (AssertionError $e) { + $has_error = true; + $error_message = $e->getMessage(); + } +} + +class Pay { + private $method; + private $infos; + private $scholarship; + + public function __construct($data) + { + foreach ($data as $key => $value) + $this->$key = htmlspecialchars($value); + + $this->method = PaymentMethod::fromName(strtoupper($this->method)); + + $this->scholarship = $_FILES["scholarship"]; + } + + public function makeVerifications() + { + global $payment; + + ensure($payment->getValidationStatus() == ValidationStatus::NOT_READY, "Un paiement est déjà initié."); + ensure($this->method != PaymentMethod::NOT_PAID, "Vous n'avez pas payé."); + ensure($this->method == PaymentMethod::SCHOLARSHIP || ($this->infos != null && strlen($this->infos) > 0), "Merci d'indiquer des informations pour retrouver votre paiement."); + ensure($this->method != PaymentMethod::SCHOLARSHIP || ($this->scholarship != null && !$this->scholarship["error"]), "Si vous êtes boursier, vous devez indiquer votre notifcation de bourse (une erreur est survenue)."); + } + + public function submit() + { + global $DB, $LOCAL_PATH, $payment, $user, $team, $tournament; + + $payment->setMethod($this->method); + $payment->setAmount($this->method == PaymentMethod::SCHOLARSHIP ? 0 : $tournament->getPrice()); + $payment->setValidationStatus(ValidationStatus::WAITING); + if ($this->method == PaymentMethod::SCHOLARSHIP) { + do + $id = genRandomPhrase(64); + while (file_exists("$LOCAL_PATH/files/$id")); + + if (!rename($this->scholarship["tmp_name"], "$LOCAL_PATH/files/$id")) + throw new AssertionError("Une erreur est survenue lors de l'envoi du fichier."); + + $req = $DB->prepare("INSERT INTO `documents`(`file_id`, `user`, `team`, `tournament`, `type`) + VALUES (?, ?, ?, ?, ?);"); + $req->execute([$id, $_SESSION["user_id"], $_SESSION["team"]->getId(), $tournament->getId(), DocumentType::getName(DocumentType::SCHOLARSHIP)]); + $payment->setTransactionInfos($id); + } + else + $payment->setTransactionInfos($this->infos); + + Mailer::requestPaymentValidation($user, $team, $tournament, $payment); + } +} + +require_once "server_files/views/paiement.php"; \ No newline at end of file diff --git a/server_files/controllers/profils.php b/server_files/controllers/profils.php new file mode 100644 index 0000000..51dc8b9 --- /dev/null +++ b/server_files/controllers/profils.php @@ -0,0 +1,16 @@ +getEmail(); +} + +require_once "server_files/views/profils.php"; \ No newline at end of file diff --git a/server_files/controllers/rejoindre_equipe.php b/server_files/controllers/rejoindre_equipe.php new file mode 100644 index 0000000..c7db182 --- /dev/null +++ b/server_files/controllers/rejoindre_equipe.php @@ -0,0 +1,68 @@ +makeVerifications(); + $join_team->joinTeam(); + } catch (AssertionError $e) { + $has_error = true; + $error_message = $e->getMessage(); + } +} + +class JoinTeam +{ + private $access_code; + private $team; + private $min_null_index; + + public function __construct($data) + { + $this->access_code = strtolower(htmlspecialchars($data["access_code"])); + $this->team = Team::fromAccessCode($this->access_code); + } + + public function makeVerifications() + { + ensure(preg_match("#[a-z0-9]{6}#", $this->access_code), "Le code d'accès doit comporter 6 caractères alphanumériques."); + ensure($this->team != null, "Ce code d'accès est invalide."); + ensure($this->team->getValidationStatus() == ValidationStatus::NOT_READY, "Cette équipe est déjà validée ou en cours de validation, vous ne pouvez pas la rejoindre."); + + for ($i = 1; $i <= $_SESSION["role"] == Role::PARTICIPANT ? 6 : 3; ++$i) { + if (($_SESSION["role"] == Role::PARTICIPANT ? $this->team->getParticipants()[$i - 1] : $this->team->getEncadrants()[$i - 1]) == NULL) + break; + } + + $this->min_null_index = $i; + + ensure($_SESSION["role"] == Role::PARTICIPANT && $this->min_null_index <= 6 || $_SESSION["role"] == Role::ENCADRANT && $this->min_null_index <= 3, "Il n'y a plus de place pour vous dans l'équipe."); + } + + public function joinTeam() + { + global $team; + + $user = $_SESSION["user"]; + + $user->setTeamId($this->team->getId()); + + if ($_SESSION["role"] == Role::ENCADRANT) + $this->team->setEncadrant($this->min_null_index, $user->getId()); + else + $this->team->setParticipant($this->min_null_index, $user->getId()); + + $team = $_SESSION["team"] = $this->team; + $tournament = $_SESSION["tournament"] = Tournament::fromId($this->team->getTournamentId()); + + Mailer::sendJoinTeamMail($user, $this->team, $tournament); + } +} + +require_once "server_files/views/rejoindre_equipe.php"; diff --git a/server_files/controllers/solutions.php b/server_files/controllers/solutions.php new file mode 100644 index 0000000..66262b7 --- /dev/null +++ b/server_files/controllers/solutions.php @@ -0,0 +1,72 @@ +getTournamentId()); + +$has_error = false; +$error_message = null; + +if (isset($_POST["send_solution"])) { + $save_solution = new SaveSolution(); + try { + $save_solution->makeVerifications(); + $save_solution->saveSolution(); + } catch (AssertionError $e) { + $has_error = true; + $error_message = $e->getMessage(); + } +} + +$solutions = $tournament->getAllSolutions($team->getId()); +$solutions_final = null; +if ($team->isSelectedForFinal()) + $solutions_final = $FINAL->getAllSolutions($team->getId()); + +class SaveSolution +{ + private $problem; + private $file; + + public function __construct() + { + $this->file = $_FILES["solution"]; + $this->problem = htmlspecialchars($_POST["problem"]); + } + + public function makeVerifications() + { + global $LOCAL_PATH; + + ensure(preg_match("#[1-9]#", $this->problem), "Le numéro du problème est invalide."); + ensure($this->file["size"] <= 2e6, "Le fichier doit peser moins que 2 Mo."); + ensure(!$this->file["error"], "Une erreur est survenue."); + ensure(finfo_file(finfo_open(FILEINFO_MIME_TYPE), $this->file["tmp_name"]) == "application/pdf", "Le fichier doit être au format PDF."); + ensure(is_dir("$LOCAL_PATH/files") || mkdir("$LOCAL_PATH/files"), "Un problème est survenue dans l'envoi du fichier. Veuillez contacter l'administrateur du serveur."); + } + + public function saveSolution() + { + global $LOCAL_PATH, $DB, $team, $tournament, $FINAL; + + do + $id = genRandomPhrase(64); + while (file_exists("$LOCAL_PATH/files/$id")); + + if (!rename($this->file["tmp_name"], "$LOCAL_PATH/files/$id")) + throw new AssertionError("Une erreur est survenue lors de l'envoi du fichier."); + + $req = $DB->prepare("INSERT INTO `solutions`(`file_id`, `team`, `tournament`, `problem`) VALUES (?, ?, ?, ?);"); + $req->execute([$id, $team->getId(), $team->isSelectedForFinal() ? $FINAL->getId() : $tournament->getId(), $this->problem]); + + return false; + } +} + +require_once "server_files/views/solutions.php"; diff --git a/server_files/controllers/solutions_orga.php b/server_files/controllers/solutions_orga.php new file mode 100644 index 0000000..945c9f8 --- /dev/null +++ b/server_files/controllers/solutions_orga.php @@ -0,0 +1,24 @@ +getName() . ".zip\""); + header("Content-Length: " . strval(filesize($file_name))); + + readfile($file_name); + + exit(); +} + +$user = $_SESSION["user"]; +$tournaments = $_SESSION["role"] == Role::ADMIN ? Tournament::getAllTournaments() : $user->getOrganizedTournaments(); + +require_once "server_files/views/solutions_orga.php"; diff --git a/server_files/controllers/syntheses.php b/server_files/controllers/syntheses.php new file mode 100644 index 0000000..804618d --- /dev/null +++ b/server_files/controllers/syntheses.php @@ -0,0 +1,73 @@ +getTournamentId()); + +if (isset($_POST["send_synthesis"])) { + $save_synthesis = new SaveSynthesis(); + try { + $save_synthesis->makeVerifications(); + $save_synthesis->saveSynthesis(); + } catch (AssertionError $e) { + $has_error = true; + $error_message = $e->getMessage(); + } +} + +$syntheses = $tournament->getAllSyntheses($team->getId()); +$syntheses_final = null; +if ($team->isSelectedForFinal()) + $syntheses_final = $FINAL->getAllSyntheses($team->getId()); + +class SaveSynthesis +{ + private $dest; + private $round; + private $file; + + public function __construct() + { + $this->file = $_FILES["synthese"]; + $this->round = htmlspecialchars($_POST["round"]); + $this->dest = DestType::fromName(strtoupper(htmlspecialchars($_POST["dest"]))); + } + + public function makeVerifications() + { + global $LOCAL_PATH, $tournament; + + ensure($this->dest != DestType::DEFENSEUR, "La source est invalide."); + ensure($this->round == 1 || $this->round == 2, "Le tour est invalide."); + $now = date("Y-m-d H:i"); + ensure($this->round == 1 && $now < $tournament->getSynthesesDate() || $this->round == 2 && $now < $tournament->getSynthesesDate2(), "Vous ne pouvez plus rendre de note de synthèse pour le tour $this->round."); + ensure($this->file["size"] <= 2e6, "Le fichier doit peser moins que 2 Mo."); + ensure(!$this->file["error"], "Une erreur est survenue."); + ensure(finfo_file(finfo_open(FILEINFO_MIME_TYPE), $this->file["tmp_name"]) == "application/pdf", "Le fichier doit être au format PDF."); + ensure(is_dir("$LOCAL_PATH/files") || mkdir("$LOCAL_PATH/files"), "Un problème est survenue dans l'envoi du fichier. Veuillez contacter l'administrateur du serveur."); + } + + public function saveSynthesis() + { + global $LOCAL_PATH, $DB, $team, $tournament, $FINAL; + do + $id = genRandomPhrase(64); + while (file_exists("$LOCAL_PATH/files/$id")); + + if (!rename($this->file["tmp_name"], "$LOCAL_PATH/files/$id")) + throw new AssertionError("Une erreur est survenue lors de l'envoi du fichier."); + + $req = $DB->prepare("INSERT INTO `syntheses`(`file_id`, `team`, `tournament`, `round`, `dest`) VALUES (?, ?, ?, ?, ?);"); + $req->execute([$id, $team->getId(), $team->isSelectedForFinal() ? $FINAL->getId() : $tournament->getId(), $this->round, $this->dest]); + + return false; + } +} + +require_once "server_files/views/syntheses.php"; diff --git a/server_files/controllers/syntheses_orga.php b/server_files/controllers/syntheses_orga.php new file mode 100644 index 0000000..c4415e2 --- /dev/null +++ b/server_files/controllers/syntheses_orga.php @@ -0,0 +1,22 @@ +getName() . ".zip\""); + header("Content-Length: " . filesize($file_name)); + + readfile($file_name); + + exit(); +} + +$user = $_SESSION["user"]; +$tournaments = $_SESSION["role"] == Role::ADMIN ? Tournament::getAllTournaments() : $user->getOrganizedTournaments(); + +require_once "server_files/views/syntheses_orga.php"; \ No newline at end of file diff --git a/server_files/controllers/tournoi.php b/server_files/controllers/tournoi.php new file mode 100644 index 0000000..e34bb9a --- /dev/null +++ b/server_files/controllers/tournoi.php @@ -0,0 +1,167 @@ +organize($_SESSION["user_id"])) + require_once "server_files/403.php"; + +$has_error = false; +$error_message = null; + +if (isset($_POST["edit_tournament"])) { + $update_tournament = new UpdateTournament($_POST); + try { + $update_tournament->makeVerifications(); + $update_tournament->updateTournament(); + } catch (AssertionError $e) { + $has_error = true; + $error_message = $e->getMessage(); + } +} + +$orgas = $tournament->getOrganizers(); +$teams = $tournament->getAllTeams(); + +class UpdateTournament +{ + public $name; + public $organizers; + public $size; + public $place; + public $price; + public $date_start; + public $date_end; + public $date_inscription; + public $time_inscription; + public $date_solutions; + public $time_solutions; + public $date_syntheses; + public $time_syntheses; + public $date_solutions_2; + public $time_solutions_2; + public $date_syntheses_2; + public $time_syntheses_2; + public $description; + public $final; + + public function __construct($data) + { + global $tournament; + + foreach ($data as $key => $value) + $this->$key = ($key == "organizers" ? $value : htmlspecialchars($value)); + + if ($_SESSION["role"] != Role::ADMIN) { + $this->organizers = []; + /** @var User $organizer */ + foreach ($tournament->getOrganizers() as $organizer) + $this->organizers[] = $organizer->getId(); + } + } + + public function makeVerifications() + { + global $tournament; + + ensure($this->name != null && $this->name != "", "Le nom est invalide."); + ensure($this->name == $tournament->getName() || !tournamentExists($this->name), "Un tournoi existe déjà avec ce nom."); + ensure(sizeof($this->organizers) > 0, "Aucun organisateur n'a été choisi."); + + $orgas = []; + foreach ($this->organizers as $orga_id) { + $orga = User::fromId($orga_id); + ensure($orga != null, "Un organisateur spécifié n'existe pas."); + ensure($orga->getRole() == Role::ORGANIZER || $orga->getRole() == Role::ADMIN, "Une personne indiquée ne peut pas organiser de tournoi."); + $orgas[] = $orga; + } + $this->organizers = $orgas; + + ensure(preg_match("#[0-9]*#", $this->size), "Le nombre d'équipes indiqué n'est pas un nombre valide."); + $this->size = intval($this->size); + ensure($this->size >= 3 && $this->size <= 15, "Un tournoi doit avoir au moins 3 et au plus 15 équipes."); + + ensure(preg_match("#[0-9]*#", $this->price), "Le tarif pour les participants n'est pas un entier valide."); + $this->price = intval($this->price); + ensure($this->price >= 0, "Le TFJM² ne va pas payer les élèves pour venir."); + ensure($this->price <= 50, "Soyons raisonnable sur le prix."); + + ensure(dateWellFormed($this->date_start), "La date de début n'est pas valide."); + ensure(dateWellFormed($this->date_end), "La date de fin n'est pas valide."); + ensure(dateWellFormed($this->date_inscription . " " . $this->time_inscription), "La date de clôture des inscriptions n'est pas valide."); + ensure(dateWellFormed($this->date_solutions . " " . $this->time_solutions), "La date limite de remise des solutions n'est pas valide."); + ensure(dateWellFormed($this->date_syntheses . " " . $this->time_syntheses), "La date limite de remise des notes de synthèse pour le tour 1 n'est pas valide."); + ensure(dateWellFormed($this->date_solutions_2 . " " . $this->time_solutions_2), "La date limite de visibilité des solutions du tour 2 n'est pas valide."); + ensure(dateWellFormed($this->date_syntheses_2 . " " . $this->time_syntheses_2), "La date limite de remise des notes de synthèse pour le tour 2 n'est pas valide."); + } + + public function updateTournament() + { + global $URL_BASE, $tournament; + + $tournament->setName($this->name); + $tournament->setSize($this->size); + $tournament->setPlace($this->place); + $tournament->setPrice($this->price); + $tournament->setStartDate($this->date_start); + $tournament->setEndDate($this->date_end); + $tournament->setInscriptionDate("$this->date_inscription $this->time_inscription"); + $tournament->setSolutionsDate("$this->date_solutions $this->time_solutions"); + $tournament->setSynthesesDate("$this->date_syntheses $this->time_syntheses"); + $tournament->setSolutionsDate2("$this->date_solutions_2 $this->time_solutions_2"); + $tournament->setSynthesesDate2("$this->date_syntheses_2 $this->time_syntheses_2"); + $tournament->setDescription($this->description); + + foreach ($this->organizers as $organizer) { + if (!$tournament->organize($organizer->getId())) + Mailer::sendAddOrganizerForTournamentMail($organizer, $tournament); + } + + $tournament->clearOrganizers(); + /** @var User $organizer */ + foreach ($this->organizers as $organizer) + $tournament->addOrganizer($organizer); + + header("Location: $URL_BASE/tournoi/" . $this->name); + exit(); + } +} + +if ($_SESSION["role"] == Role::ORGANIZER || $_SESSION["role"] == Role::ADMIN) { + $emails = []; + $emails_validated = []; + foreach ($tournament->getOrganizers() as $organizer) { + $emails[] = $organizer->getEmail(); + $emails_validated[] = $organizer->getEmail(); + } + + foreach ($teams as $team) { + foreach ($team->getEncadrants() as $encadrant_id) { + $encadrant = User::fromId($encadrant_id); + if ($encadrant != null) { + $emails[] = $encadrant->getEmail(); + if ($team->getValidationStatus() == ValidationStatus::VALIDATED) + $emails_validated[] = $encadrant->getEmail(); + } + } + + foreach ($team->getParticipants() as $participant_id) { + $participant = User::fromId($participant_id); + if ($participant != null) { + $emails[] = $participant->getEmail(); + if ($team->getValidationStatus() == ValidationStatus::VALIDATED) + $emails_validated[] = $participant->getEmail(); + if ($participant->getResponsibleEmail() != null) { + $emails[] = $participant->getResponsibleEmail(); + if ($team->getValidationStatus() == ValidationStatus::VALIDATED) + $emails_validated[] = $participant->getResponsibleEmail(); + } + } + } + } +} + +require_once "server_files/views/tournoi.php"; diff --git a/server_files/controllers/tournois.php b/server_files/controllers/tournois.php new file mode 100644 index 0000000..7a304fc --- /dev/null +++ b/server_files/controllers/tournois.php @@ -0,0 +1,42 @@ +getOrganizers() as $organizer) { + $emails[] = $organizer->getEmail(); + $emails_validated[] = $organizer->getEmail(); + } + + foreach ($tournament->getAllTeams() as $team) { + foreach ($team->getEncadrants() as $encadrant_id) { + $encadrant = User::fromId($encadrant_id); + if ($encadrant != null) { + $emails[] = $encadrant->getEmail(); + if ($team->getValidationStatus() == ValidationStatus::VALIDATED) + $emails_validated[] = $encadrant->getEmail(); + } + } + + foreach ($team->getParticipants() as $participant_id) { + $participant = User::fromId($participant_id); + if ($participant != null) { + $emails[] = $participant->getEmail(); + if ($team->getValidationStatus() == ValidationStatus::VALIDATED) + $emails_validated[] = $participant->getEmail(); + if ($participant->getResponsibleEmail() != null) { + $emails[] = $participant->getResponsibleEmail(); + if ($team->getValidationStatus() == ValidationStatus::VALIDATED) + $emails_validated[] = $participant->getResponsibleEmail(); + } + } + } + } + } +} + +require_once "server_files/views/tournois.php"; diff --git a/server_files/controllers/view_file.php b/server_files/controllers/view_file.php new file mode 100644 index 0000000..cdc4904 --- /dev/null +++ b/server_files/controllers/view_file.php @@ -0,0 +1,102 @@ +getTeamId()); + $tournament = Tournament::fromId($file->getTournamentId()); + $trigram = $team->getTrigram(); + + if ($_SESSION["role"] == Role::ORGANIZER && !$tournament->organize($_SESSION["user_id"])) + require_once "server_files/403.php"; + + if ($type == DocumentType::SOLUTION) { + $problem = $file->getProblem(); + $name = "Problème $problem $trigram"; + + if (($_SESSION["role"] == Role::PARTICIPANT || $_SESSION["role"] == Role::ENCADRANT) && (!isset($_SESSION["team"]) || $_SESSION["team"]->getId() != $team->getId())) { + $req = $DB->prepare("SELECT opposed_problem, rapported_problem, opposed_problem_2, rapported_problem_2 FROM teams WHERE id = ?;"); + $req->execute([$_SESSION["team"]->getId()]); + $data = $req->fetch(); + if ($id != $data["opposed_problem"] && $id != $data["rapported_problem"]) { + if (date("Y-m-d H:i") < $tournament->getSolutionsDate2() || ($id != $data["opposed_problem_2"] && $id != $data["rapported_problem_2"])) + require_once "server_files/403.php"; + } + } + } + else if ($type == DocumentType::SYNTHESIS) { + $dest = $file->getDest(); + $name = "Note de synthèse $trigram " . ($dest == DestType::OPPOSANT ? "de l'opposant" : "du rapporteur"); + + if (($_SESSION["role"] == Role::PARTICIPANT || $_SESSION["role"] == Role::ENCADRANT) && (!isset($_SESSION["team"]) || $_SESSION["team"]->getId() != $team->getId())) + require_once "server_files/403.php"; + } + else { + $user = User::fromId($file->getUserId()); + $type = $file->getType(); + + if (($_SESSION["role"] == Role::PARTICIPANT || $_SESSION["role"] == Role::ENCADRANT)) { + if ($type != DocumentType::MOTIVATION_LETTER && $user->getId() != $_SESSION["user_id"] || $file->getTeamId() != $team->getId()) + require_once "server_files/403.php"; + } + + switch ($type) { + case DocumentType::PARENTAL_CONSENT: + $name = "Autorisation parentale"; + break; + case DocumentType::PHOTO_CONSENT: + $name = "Autorisation de droit à l'image"; + break; + case DocumentType::SANITARY_PLUG: + $name = "Fiche sanitaire"; + break; + case DocumentType::SCHOLARSHIP: + $name = "Notification de bourse"; + break; + } + if ($type == DocumentType::MOTIVATION_LETTER) + $name = "Lettre de motivation de l'équipe $trigram"; + else { + $surname = $user->getSurname(); + $first_name = $user->getFirstName(); + $name .= " de $first_name $surname"; + } + } +} +else + require_once "server_files/404.php"; + +$mime = finfo_file(finfo_open(FILEINFO_MIME_TYPE), "$LOCAL_PATH/files/$id"); +if ($mime == "application/pdf") + $name .= ".pdf"; +elseif ($mime == "image/png") + $name .= ".png"; +else + $name = ".jpg"; + +header("Content-Type: $mime"); +header("Content-Disposition: inline; filename=\"$name\""); + +readfile("$LOCAL_PATH/files/$id"); + +exit(); \ No newline at end of file diff --git a/server_files/model.php b/server_files/model.php new file mode 100644 index 0000000..e650c24 --- /dev/null +++ b/server_files/model.php @@ -0,0 +1,267 @@ +getRole(); + + if ($user->getTeamId() !== null) { + $team = $_SESSION["team"] = Team::fromId($user->getTeamId()); + $_SESSION["tournament"] = Tournament::fromId($team->getTournamentId()); + } + + if (isset($_GET["view-as-admin"])) { + if (isset($_SESSION["admin"])) { + $_SESSION["user_id"] = $_SESSION["admin"]; + unset($_SESSION["admin"]); + } + header("Location: /"); + exit(); + } + } +} + +function quitTeam($user_id = -1) +{ + global $DB, $URL_BASE; + + header("Location: $URL_BASE"); + + /** @var User $user */ + $user = $_SESSION["user"]; + if ($user_id == -1) + $user_id = $user->getId(); + else + $user = User::fromId($user_id); + $role = $user->getRole(); + + if ($role == Role::ADMIN || $role == Role::ORGANIZER) + return; + + for ($i = 1; $i <= ($role == Role::ENCADRANT ? 3 : 6); ++$i) + /** @noinspection SqlResolve */ + $DB->exec("UPDATE `teams` SET `" . strtolower(Role::getName($role)) . "_$i` = NULL WHERE `" . strtolower(Role::getName($role)) . "_$i` = $user_id;"); + $user->setTeamId(null); + $DB->exec("UPDATE `teams` SET `encadrant_1` = `encadrant_2`, `encadrant_2` = NULL WHERE `encadrant_1` IS NULL;"); + $DB->exec("UPDATE `teams` SET `encadrant_2` = `encadrant_3`, `encadrant_3` = NULL WHERE `encadrant_2` IS NULL;"); + for ($i = 1; $i <= 5; ++$i) { + /** @noinspection SqlResolve */ + $DB->exec("UPDATE `teams` SET `participant_$i` = `participant_" . strval($i + 1) . "`, `participant_" . strval($i + 1) . "` = NULL WHERE `participant_$i` IS NULL;"); + } + + $req = $DB->query("SELECT `file_id` FROM `documents` WHERE `user` = $user_id;"); + while (($data = $req->fetch()) !== false) + unlink("$URL_BASE/files/" . $data["file_id"]); + $DB->exec("DELETE FROM `documents` WHERE `user` = $user_id;"); + + if ($DB->exec("DELETE FROM `teams` WHERE `encadrant_1` IS NULL AND `participant_1` IS NULL;") > 0) { + $team_id = $user->getTeamId(); + $req = $DB->query("SELECT `file_id` FROM `solutions` WHERE `team` = $team_id;"); + while (($data = $req->fetch()) !== false) + unlink("$URL_BASE/files/" . $data["file_id"]); + $DB->exec("DELETE FROM `solutions` WHERE `team` = $team_id;"); + + $req = $DB->query("SELECT `file_id` FROM `syntheses` WHERE `team` = $team_id;"); + while (($data = $req->fetch()) !== false) + unlink("$URL_BASE/files/" . $data["file_id"]); + $DB->exec("DELETE FROM `syntheses` WHERE `team` = $team_id;"); + } + + $_SESSION["team"] = null; + unset($_SESSION["team"]); +} + +function userExists($email) +{ + global $DB, $YEAR; + + $req = $DB->prepare("SELECT `id` FROM `users` WHERE `email` = ? AND `year` = '$YEAR';"); + $req->execute([$email]); + return $req->fetch(); +} + +function teamExists($name) +{ + global $DB, $YEAR; + + $req = $DB->prepare("SELECT `id` FROM `teams` WHERE `name` = ? AND `year` = '$YEAR';"); + $req->execute([$name]); + return $req->fetch(); +} + +function trigramExists($trigram) +{ + global $DB, $YEAR; + + $req = $DB->prepare("SELECT `id` FROM `teams` WHERE `trigram` = ? AND `year` = '$YEAR';"); + $req->execute([$trigram]); + return $req->fetch(); +} + +function tournamentExists($name) +{ + global $DB, $YEAR; + + $req = $DB->prepare("SELECT `id` FROM `tournaments` WHERE `name` = ? AND `year` = '$YEAR';"); + $req->execute([$name]); + return $req->fetch(); +} + +function canValidate(Team $team, Tournament $tournament) +{ + global $DB, $YEAR; + + $can_validate = $team->getValidationStatus() == ValidationStatus::NOT_READY; + $can_validate &= $team->getEncadrants()[0] != NULL; + $can_validate &= $team->getParticipants()[3] != NULL; + + // Le TFJM² 2020 se déroulant en ligne, les papiers ne sont plus nécessaires +/* for ($i = 1; $i <= 2; ++$i) { + if ($team->getEncadrants()[$i - 1] === NULL) + continue; + + $req = $DB->prepare("SELECT COUNT(*) AS `version` FROM `documents` WHERE `user` = ? AND `tournament` = ? AND `type` = ?;"); + $req->execute([$team->getEncadrants()[$i - 1], $tournament->getId(), "PHOTO_CONSENT"]); + $d = $req->fetch(); + $can_validate &= $d["version"] > 0; + }*/ + + + // Le TFJM² 2020 se déroulant en ligne, les papiers ne sont plus nécessaires +/* for ($i = 1; $i <= 6; ++$i) { + if ($team->getParticipants()[$i] === NULL) + continue; + + $req = $DB->prepare("SELECT COUNT(*) AS `version` FROM `documents` WHERE `user` = ? AND `tournament` = ? AND `type` = ?;"); + $req->execute([$team->getParticipants()[$i], $tournament->getId(), "PHOTO_CONSENT"]); + $d = $req->fetch(); + $can_validate &= $d["version"] > 0; + + $birth_date = $DB->query("SELECT `birth_date` FROM `users` WHERE `id` = " . $team->getParticipants()[$i] . ";")->fetch()["birth_date"]; + if ($birth_date > strval($YEAR - 18) . substr($tournament->getStartDate(), 4)) { + $req = $DB->prepare("SELECT COUNT(*) AS `version` FROM `documents` WHERE `user` = ? AND `tournament` = ? AND `type` = ?;"); + $req->execute([$team->getParticipants()[$i], $tournament->getId(), "PARENTAL_CONSENT"]); + $d = $req->fetch(); + $can_validate &= $d["version"] > 0; + + $req = $DB->prepare("SELECT COUNT(*) AS `version` FROM `documents` WHERE `user` = ? AND `tournament` = ? AND `type` = ?;"); + $req->execute([$team->getParticipants()[$i], $tournament->getId(), "SANITARY_PLUG"]); + $d = $req->fetch(); + $can_validate &= $d["version"] > 0; + } + } */ + + // La lettre de motivation n'est plus nécessaire, mais existe toujours +/* $req = $DB->prepare("SELECT COUNT(*) AS `version` FROM `documents` WHERE `team` = ? AND `tournament` = ? AND `type` = ?;"); + $req->execute([$team->getId(), $tournament->getId(), "MOTIVATION_LETTER"]); + $d = $req->fetch(); + $can_validate &= $d["version"] > 0;*/ + + $can_validate &= date("Y-m-d H:i:s") <= $tournament->getInscriptionDate(); + + return $can_validate; +} + +function printDocuments($documents) +{ + if (sizeof($documents) == 0) { + echo "
\nPas de document envoyé pour le moment.\n
\n"; + return; + } + + echo "
\n"; + foreach ($documents as $document) { + $file_id = $document->getFileId(); + $name = DocumentType::getTranslatedName($document->getType()); + $version = $document->getVersion(); + if ($document->getType() == DocumentType::MOTIVATION_LETTER) { + $team = Team::fromId($document->getTeamId()); + echo "Lettre de motivation de l'équipe " . $team->getTrigram(); + } + else { + $user = User::fromId($document->getUserId()); + $surname = $user->getSurname(); + $first_name = $user->getFirstName(); + echo "$name de $first_name $surname"; + } + + echo " (version $version) : Télécharger
\n"; + } + echo "
\n"; +} + +function getZipFile($document_type, $tournament_id, $team_id = -1) +{ + global $LOCAL_PATH; + + $tournament = Tournament::fromId($tournament_id); + + $zip = new ZipArchive(); + + $file_name = tempnam("tmp", "tfjm-"); + + if ($zip->open($file_name, ZipArchive::CREATE) !== true) { + die("Impossible de créer le fichier zip."); + } + + switch ($document_type) { + case DocumentType::SOLUTION: + $data = $tournament->getAllSolutions($team_id); + break; + case DocumentType::SYNTHESIS: + $data = $tournament->getAllSyntheses($team_id); + break; + default: + $data = $tournament->getAllDocuments($team_id); + break; + } + + /** @var Document | Solution | Synthesis $file */ + foreach ($data as $file) { + $file_id = $file->getFileId(); + $team = Team::fromId($file->getTeamId()); + switch ($document_type) { + case DocumentType::SOLUTION: + $name = "Problème " . $file->getProblem() . " " . $team->getTrigram() . ".pdf"; + break; + case DocumentType::SYNTHESIS: + $name = "Note de synthèse " . $team->getTrigram() . " pour " . ($file->getDest() == DestType::OPPOSANT ? "l'opposant" : "le rapporteur") . ".pdf"; + break; + default: + $user = User::fromId($file->getUserId()); + switch ($file->getType()) { + case DocumentType::PARENTAL_CONSENT: + $name = "Autorisation parentale de " . $user->getFirstName() . " " . $user->getSurname() . ".pdf"; + break; + case DocumentType::PHOTO_CONSENT: + $name = "Autorisation de droit à l'image de " . $user->getFirstName() . " " . $user->getSurname() . ".pdf"; + break; + case DocumentType::SCHOLARSHIP: + $name = "Notification de bourse de " . $user->getFirstName() . " " . $user->getSurname() . ".pdf"; + break; + case DocumentType::MOTIVATION_LETTER: + $name = "Lettre de motivation de l'équipe " . $team->getTrigram() . ".pdf"; + break; + default: + $name = "Fiche sanitaire de " . $user->getFirstName() . " " . $user->getSurname() . ".pdf"; + break; + } + break; + } + + $zip->addFile("$LOCAL_PATH/files/$file_id", $name); + } + + $zip->close(); + + return $file_name; +} \ No newline at end of file diff --git a/server_files/services/mail.php b/server_files/services/mail.php new file mode 100644 index 0000000..0c174cd --- /dev/null +++ b/server_files/services/mail.php @@ -0,0 +1,263 @@ +\r\n"; + $headers .= "Reply-To: \"Contact TFJM²\" \r\n"; + $headers .= "Content-Type: text/html; charset=UTF-8\r\n"; + + mail($email, $subject, $content, $headers); + } + + private static function broadcastToTeam(Team $team, $subject, $content, $from = "contact") + { + $content = preg_replace("#{TEAM_NAME}#", $team->getName(), $content); + $content = preg_replace("#{TRIGRAM}#", $team->getTrigram(), $content); + + foreach ($team->getEncadrants() as $participant_id) { + $participant = User::fromId($participant_id); + if ($participant == null) + continue; + + $c = preg_replace("#{FIRST_NAME}#", $participant->getFirstName(), $content); + $c = preg_replace("#{SURNAME}#", $participant->getSurname(), $c); + self::sendMail($participant->getEmail(), $subject, $c, $from); + } + + foreach ($team->getParticipants() as $participant_id) { + $participant = User::fromId($participant_id); + if ($participant == null) + continue; + + $c = preg_replace("#{FIRST_NAME}#", $participant->getFirstName(), $content); + $c = preg_replace("#{SURNAME}#", $participant->getSurname(), $c); + self::sendMail($participant->getEmail(), $subject, $c, $from); + } + } + + private static function broadcastToAdmins($subject, $content, $from = "contact") + { + /** @var User $admin */ + foreach (User::getAdmins() as $admin) { + $c = preg_replace("#{FIRST_NAME}#", $admin->getFirstName(), $content); + $c = preg_replace("#{SURNAME}#", $admin->getSurname(), $c); + self::sendMail($admin->getEmail(), $subject, $c, $from); + } + } + + private static function brodcastToOrgas(Tournament $tournament, $subject, $content, $from = "contact") + { + foreach ($tournament->getOrganizers() as $orga) { + if ($orga->getRole() == Role::ADMIN) + continue; + + $c = preg_replace("#{FIRST_NAME}#", $orga->getFirstName(), $content); + $c = preg_replace("#{SURNAME}#", $orga->getSurname(), $c); + self::sendMail($orga->getEmail(), $subject, $c, $from); + } + + self::broadcastToAdmins($subject, $content, $from); + } + + private static function getTemplate($name) + { + global $LOCAL_PATH; + return file_get_contents("$LOCAL_PATH/server_files/services/mail_templates/$name.html"); + } + + public static function sendRegisterMail(NewUser $new_user) + { + global $YEAR; + + $content = self::getTemplate("register"); + $content = preg_replace("#{FIRST_NAME}#", $new_user->first_name, $content); + $content = preg_replace("#{SURNAME}#", $new_user->surname, $content); + $content = preg_replace("#{TOKEN}#", $new_user->confirm_email_token, $content); + + self::sendMail($new_user->email, "Inscription au TFJM² $YEAR", $content); + } + + public static function sendConfirmEmail(User $user) + { + global $YEAR; + + $content = self::getTemplate("confirm_email"); + $content = preg_replace("#{FIRST_NAME}#", $user->getFirstName(), $content); + $content = preg_replace("#{SURNAME}#", $user->getSurname(), $content); + $content = preg_replace("#{TOKEN}#", $user->getConfirmEmailToken(), $content); + + self::sendMail($user->getEmail(), "Confirmation d'adresse e-mail – TFJM² $YEAR", $content); + } + + public static function sendChangeEmailAddressMail(User $user) + { + $content = self::getTemplate("change_email_address"); + $content = preg_replace("#{FIRST_NAME}#", $user->getFirstName(), $content); + $content = preg_replace("#{SURNAME}#", $user->getSurname(), $content); + $content = preg_replace("#{TOKEN}#", $user->getConfirmEmailToken(), $content); + + self::sendMail($user->getEmail(), "Changement d'adresse e-mail – TFJM²", $content); + } + + public static function sendForgottenPasswordProcedureMail(User $user) + { + $content = self::getTemplate("forgotten_password"); + $content = preg_replace("#{FIRST_NAME}#", $user->getFirstName(), $content); + $content = preg_replace("#{SURNAME}#", $user->getSurname(), $content); + $content = preg_replace("#{TOKEN}#", $user->getForgottenPasswordToken(), $content); + + self::sendMail($user->getEmail(), "Mot de passe oublié – TFJM²", $content); + } + + public static function sendChangePasswordMail(User $user) + { + $content = self::getTemplate("change_password"); + $content = preg_replace("#{FIRST_NAME}#", $user->getFirstName(), $content); + $content = preg_replace("#{SURNAME}#", $user->getSurname(), $content); + + self::sendMail($user->getEmail(), "Mot de passe changé – TFJM²", $content); + } + + public static function sendAddTeamMail(User $user, Team $team, Tournament $tournament) + { + global $YEAR; + + $content = self::getTemplate("add_team"); + $content = preg_replace("#{FIRST_NAME}#", $user->getFirstName(), $content); + $content = preg_replace("#{SURNAME}#", $user->getSurname(), $content); + $content = preg_replace("#{TEAM_NAME}#", $team->getName(), $content); + $content = preg_replace("#{TRIGRAM}#", $team->getTrigram(), $content); + $content = preg_replace("#{TOURNAMENT_NAME}#", $tournament->getName(), $content); + $content = preg_replace("#{ACCESS_CODE}#", $team->getAccessCode(), $content); + + self::sendMail($user->getEmail(), "Ajout d'une équipe TFJM² $YEAR", $content); + } + + public static function sendJoinTeamMail(User $user, Team $team, Tournament $tournament) + { + global $YEAR; + + $content = self::getTemplate("join_team"); + $content = preg_replace("#{FIRST_NAME}#", $user->getFirstName(), $content); + $content = preg_replace("#{SURNAME}#", $user->getSurname(), $content); + $content = preg_replace("#{TEAM_NAME}#", $team->getName(), $content); + $content = preg_replace("#{TRIGRAM}#", $team->getTrigram(), $content); + $content = preg_replace("#{TOURNAMENT_NAME}#", $tournament->getName(), $content); + + self::sendMail($user->getEmail(), "Équipe rejointe TFJM² $YEAR", $content); + } + + public static function sendAddOrganizerMail(NewOrganizer $new_orga) + { + global $YEAR; + + $content = self::getTemplate("add_organizer"); + $content = preg_replace("#{FIRST_NAME}#", $new_orga->first_name, $content); + $content = preg_replace("#{SURNAME}#", $new_orga->surname, $content); + $content = preg_replace("#{TOKEN}#", $new_orga->token, $content); + + self::sendMail($new_orga->email, "Ajout d'un organisateur – TFJM² $YEAR", $content); + } + + public static function sendAddOrganizerForTournamentMail(User $organizer, Tournament $tournament) + { + global $YEAR; + + $content = self::getTemplate("add_organizer_for_tournament"); + $content = preg_replace("#{FIRST_NAME}#", $organizer->getFirstName(), $content); + $content = preg_replace("#{SURNAME}#", $organizer->getSurname(), $content); + $content = preg_replace("#{TOURNAMENT_NAME}#", $tournament->getName(), $content); + + self::sendMail($organizer->getEmail(), "Ajout d'un organisateur pour le tournoi " . $tournament->getName() . " – TFJM² $YEAR", $content); + } + + public static function requestPaymentValidation(User $user, Team $team, Tournament $tournament, Payment $payment) + { + global $YEAR, $URL_BASE; + + $content = self::getTemplate("request_payment_validation"); + $content = preg_replace("#{USER_FIRST_NAME}#", $user->getFirstName(), $content); + $content = preg_replace("#{USER_SURNAME}#", $user->getSurname(), $content); + $content = preg_replace("#{USER_ID}#", $user->getId(), $content); + $content = preg_replace("#{TEAM_NAME}#", $team->getName(), $content); + $content = preg_replace("#{TRIGRAM}#", $team->getTrigram(), $content); + $content = preg_replace("#{TOURNAMENT_NAME}#", $tournament->getName(), $content); + $content = preg_replace("#{AMOUNT}#", $payment->getAmount(), $content); + $content = preg_replace("#{PAYMENT_METHOD}#", PaymentMethod::getTranslatedName($payment->getMethod()), $content); + if ($payment->getMethod() == PaymentMethod::SCHOLARSHIP) + $content = preg_replace("#{PAYMENT_INFOS}#", "getTransactionInfos() . "\">Voir la notification de bourse", $content); + else + $content = preg_replace("#{PAYMENT_INFOS}#", $payment->getTransactionInfos(), $content); + + self::broadcastToAdmins("Demande de validation de paiement pour le tournoi " . $tournament->getName() . " – TFJM² $YEAR", $content); + } + + public static function sendRequestValidationMail(Team $team, Tournament $tournament) + { + global $YEAR; + + $content = self::getTemplate("request_validation"); + $content = preg_replace("#{TEAM_NAME}#", $team->getName(), $content); + $content = preg_replace("#{TRIGRAM}#", $team->getTrigram(), $content); + $content = preg_replace("#{TOURNAMENT}#", $tournament->getName(), $content); + $content = preg_replace("#{ACCESS_CODE}#", $team->getAccessCode(), $content); + + self::brodcastToOrgas($tournament, "Demande de validation – TFJM² $YEAR", $content); + } + + public static function sendValidateTeam($team, $message) + { + global $YEAR; + + $content = self::getTemplate("validate_team"); + if (strlen($message) > 0) + $message = " L'équipe d'organisation vous transmet le message suivant :\n\n" . $message; + $message = preg_replace("#\n#", "
\n", $message); + $content = preg_replace("#{MESSAGE}#", $message, $content); + + self::broadcastToTeam($team, "Équipe validée – TFJM² $YEAR", $content); + } + + public static function sendUnvalidateTeam($team, $message) + { + global $YEAR; + + $content = self::getTemplate("unvalidate_team"); + if (strlen($message) > 0) + $message = " L'équipe d'organisation vous transmet le message suivant :\n\n" . $message; + $message = preg_replace("#\n#", "
\n", $message); + $content = preg_replace("#{MESSAGE}#", $message, $content); + + self::broadcastToTeam($team, "Équipe non validée – Correspondances des Jeunes Mathématicien·ne·s $YEAR", $content); + } + + public static function sendValidatePayment(User $user, Team $team, Tournament $tournament, Payment $payment, $message) + { + global $YEAR, $URL_BASE; + + $content = self::getTemplate($payment->getValidationStatus() == ValidationStatus::VALIDATED ? "validate_payment" : "unvalidate_payment"); + $content = preg_replace("#{FIRST_NAME}#", $user->getFirstName(), $content); + $content = preg_replace("#{SURNAME}#", $user->getSurname(), $content); + $content = preg_replace("#{TEAM_NAME}#", $team->getName(), $content); + $content = preg_replace("#{TRIGRAM}#", $team->getTrigram(), $content); + $content = preg_replace("#{TOURNAMENT_NAME}#", $tournament->getName(), $content); + $content = preg_replace("#{AMOUNT}#", $payment->getAmount(), $content); + $content = preg_replace("#{PAYMENT_METHOD}#", PaymentMethod::getTranslatedName($payment->getMethod()), $content); + if ($payment->getMethod() == PaymentMethod::SCHOLARSHIP) + $content = preg_replace("#{PAYMENT_INFOS}#", "getTransactionInfos() . "\">Voir la notification de bourse", $content); + else + $content = preg_replace("#{PAYMENT_INFOS}#", $payment->getTransactionInfos(), $content); + if (isset($message) && strlen($message) > 0) { + $content = preg_replace("#{MESSAGE}#", "L'équipe d'organisation vous transmet les informations suivantes :

" . $message . "
", $content); + } + + self::sendMail($user->getEmail(), "Paiement pour le tournoi " . $tournament->getName() . " – TFJM² $YEAR", $content); + } +} diff --git a/server_files/services/mail_templates/add_organizer.html b/server_files/services/mail_templates/add_organizer.html new file mode 100644 index 0000000..56ed2c5 --- /dev/null +++ b/server_files/services/mail_templates/add_organizer.html @@ -0,0 +1,21 @@ + + + + + Organisateur du TFJM² + + +Bonjour {FIRST_NAME} {SURNAME},
+
+Vous recevez ce message (envoyé automatiquement) car vous êtes organisateur d'un des tournois du TFJM2.

+Un compte organisateur vous a été créé par l'un des administrateurs. Un mot de passe aléatoire vous a été attribué, mais que vous +devez changer pour des raisons de sécurité sur le lien suivant : +{URL_BASE}/connexion/reinitialiser_mdp/{TOKEN}
+
+Une fois le mot de passe changé, vous pourrez vous connecter sur la plateforme.
+
+Merci beaucoup pour votre aide !
+
+Le comité national d'organisation du TFJM2 + + \ No newline at end of file diff --git a/server_files/services/mail_templates/add_organizer_for_tournament.html b/server_files/services/mail_templates/add_organizer_for_tournament.html new file mode 100644 index 0000000..ee83644 --- /dev/null +++ b/server_files/services/mail_templates/add_organizer_for_tournament.html @@ -0,0 +1,18 @@ + + + + + + Organisateur du tournoi de {TOURNAMENT_NAME} – TFJM² + + +Bonjour {FIRST_NAME} {SURNAME},
+
+Vous venez d'être promu organisateur du tournoi {TOURNAMENT_NAME} du TFJM2 {YEAR}.
+Ce message vous a été envoyé automatiquement. En cas de problème, merci de répondre à ce message. +
+Cordialement,
+
+Le comité national d'organisation du TFJM2 + + \ No newline at end of file diff --git a/server_files/services/mail_templates/add_team.html b/server_files/services/mail_templates/add_team.html new file mode 100644 index 0000000..ffd2b50 --- /dev/null +++ b/server_files/services/mail_templates/add_team.html @@ -0,0 +1,16 @@ + + + + + Nouvelle équipe TFJM² {YEAR} + + +Bonjour {FIRST_NAME} {SURNAME},
+
+Vous venez de créer l'équipe « {TEAM_NAME} » ({TRIGRAM}) pour le TFJM2 de {TOURNAMENT_NAME} et nous vous en remercions.
+Afin de permettre aux autres membres de votre équipe de vous rejoindre, veuillez leur transmettre le code d'accès : +{ACCESS_CODE}
+
+Le comité national d'organisation du TFJM2 + + \ No newline at end of file diff --git a/server_files/services/mail_templates/change_email_address.html b/server_files/services/mail_templates/change_email_address.html new file mode 100644 index 0000000..0adf015 --- /dev/null +++ b/server_files/services/mail_templates/change_email_address.html @@ -0,0 +1,16 @@ + + + + + + Changement d'adresse e-mail – TFJM² + + +Bonjour {FIRST_NAME} {SURNAME},
+
+Vous venez de changer votre adresse e-mail. Veuillez désormais la confirmer en cliquant ici : {URL_BASE}/confirmer_mail/{TOKEN}
+
+Le comité national d'organisation du TFJM2 + + \ No newline at end of file diff --git a/server_files/services/mail_templates/change_password.html b/server_files/services/mail_templates/change_password.html new file mode 100644 index 0000000..91d2cf1 --- /dev/null +++ b/server_files/services/mail_templates/change_password.html @@ -0,0 +1,18 @@ + + + + + Mot de passe changé – TFJM² + + +Bonjour {FIRST_NAME} {SURNAME},
+
+Nous vous informons que votre mot de passe vient d'être modifié. Si vous n'êtes pas à l'origine de cette manipulation, +veuillez immédiatement vérifier vos accès à votre boîte mail et changer votre mot de passe sur la plateforme +d'inscription.
+
+Cordialement,
+
+Le comité national d'organisation du TFJM2 + + \ No newline at end of file diff --git a/server_files/services/mail_templates/confirm_email.html b/server_files/services/mail_templates/confirm_email.html new file mode 100644 index 0000000..ba75174 --- /dev/null +++ b/server_files/services/mail_templates/confirm_email.html @@ -0,0 +1,18 @@ + + + + + + Inscription au TFJM² {YEAR} + + +Bonjour {FIRST_NAME} {SURNAME},
+
+Vous êtes inscrit au TFJM2 {YEAR} et nous vous en remercions.
+Pour valider votre adresse e-mail, veuillez cliquer sur le lien : {URL_BASE}/confirmer_mail/{TOKEN}
+
+Cordialement,
+
+Le comité national d'organisation du TFJM2 + + \ No newline at end of file diff --git a/server_files/services/mail_templates/forgotten_password.html b/server_files/services/mail_templates/forgotten_password.html new file mode 100644 index 0000000..18c187d --- /dev/null +++ b/server_files/services/mail_templates/forgotten_password.html @@ -0,0 +1,20 @@ + + + + + + Mot de passe oublié – TFJM² + + +Bonjour,
+
+Vous avez indiqué avoir oublié votre mot de passe. Veuillez cliquer ici pour le réinitialiser : {URL_BASE}/connexion/reinitialiser_mdp/{TOKEN}
+
+Si vous n'êtes pas à l'origine de cette manipulation, vous pouvez ignorer ce message.
+
+Cordialement,
+
+Le comité national d'organisation du TFJM2 + + \ No newline at end of file diff --git a/server_files/services/mail_templates/join_team.html b/server_files/services/mail_templates/join_team.html new file mode 100644 index 0000000..3e51307 --- /dev/null +++ b/server_files/services/mail_templates/join_team.html @@ -0,0 +1,17 @@ + + + + + Équipe rejointe – TFJM² {YEAR} + + +Bonjour {FIRST_NAME} {SURNAME},
+
+Vous venez de rejoindre l'équipe « {TEAM_NAME} » ({TRIGRAM}) pour le TFJM² de {TOURNAMENT_NAME} et nous vous en +remercions.
+
+Cordialement,
+
+Le comité national d'organisation du TFJM2 + + \ No newline at end of file diff --git a/server_files/services/mail_templates/register.html b/server_files/services/mail_templates/register.html new file mode 100644 index 0000000..0334c01 --- /dev/null +++ b/server_files/services/mail_templates/register.html @@ -0,0 +1,16 @@ + + + + + + Inscription au TFJM² {YEAR} + + +Bonjour {FIRST_NAME} {SURNAME},
+
+Vous venez de vous inscrire au TFJM2 {YEAR} et nous vous en remercions.
+Pour valider votre adresse e-mail, veuillez cliquer sur le lien : {URL_BASE}/confirmer_mail/{TOKEN}
+
+Le comité national d'organisation du TFJM2 + + \ No newline at end of file diff --git a/server_files/services/mail_templates/request_payment_validation.html b/server_files/services/mail_templates/request_payment_validation.html new file mode 100644 index 0000000..8c23f21 --- /dev/null +++ b/server_files/services/mail_templates/request_payment_validation.html @@ -0,0 +1,26 @@ + + + + + + Demande de validation de paiement pour le TFJM² {YEAR} + + +Bonjour {FIRST_NAME} {SURNAME},
+
+{USER_FIRST_NAME} {USER_SURNAME} de l'équipe {TEAM_NAME} ({TRIGRAM}) annonce avoir réglé sa participation pour le tournoi {TOURNAMENT_NAME}. +Les informations suivantes ont été communiquées :

+Équipe : {TEAM_NAME} ({TRIGRAM})
+Tournoi : {TOURNAMENT_NAME}
+Moyen de paiement : {PAYMENT_METHOD}
+Montant : {AMOUNT} €
+Informations sur le paiement : {PAYMENT_INFOS}
+
+Vous pouvez désormais vérifier ces informations, puis valider (ou non) le paiement sur +la page associée à ce participant. +
+Cordialement, +
+Le comité national d'organisation du TFJM2 + + \ No newline at end of file diff --git a/server_files/services/mail_templates/request_validation.html b/server_files/services/mail_templates/request_validation.html new file mode 100644 index 0000000..203d616 --- /dev/null +++ b/server_files/services/mail_templates/request_validation.html @@ -0,0 +1,19 @@ + + + + + + Demande de validation - TFJM² + + +Bonjour {FIRST_NAME} {SURNAME},
+
+L'équipe « {TEAM_NAME} » ({TRIGRAM}) vient de demander à valider son équipe pour participer au tournoi {TOURNAMENT} du +TFJM². Vous pouvez décider d'accepter ou de refuser l'équipe en vous rendant sur la page de l'équipe : +{URL_BASE}/equipe/{TRIGRAM}
+
+Cordialement,
+
+Le comité national d'organisation du TFJM2 + + \ No newline at end of file diff --git a/server_files/services/mail_templates/unvalidate_payment.html b/server_files/services/mail_templates/unvalidate_payment.html new file mode 100644 index 0000000..c6e99ff --- /dev/null +++ b/server_files/services/mail_templates/unvalidate_payment.html @@ -0,0 +1,24 @@ + + + + + + Non-validation du paiement pour le TFJM² {YEAR} + + +Bonjour {FIRST_NAME} {SURNAME},
+
+Votre paiement pour le TFJM² {YEAR} a malheureusement été rejeté. Pour rappel, vous aviez fourni ces informations :

+Équipe : {TEAM_NAME} ({TRIGRAM})
+Tournoi : {TOURNAMENT_NAME}
+Moyen de paiement : {PAYMENT_METHOD}
+Montant : {AMOUNT} €
+Informations sur le paiement : {PAYMENT_INFOS}
+
+{MESSAGE} +
+Cordialement, +
+Le comité national d'organisation du TFJM2 + + \ No newline at end of file diff --git a/server_files/services/mail_templates/unvalidate_team.html b/server_files/services/mail_templates/unvalidate_team.html new file mode 100644 index 0000000..d9c5588 --- /dev/null +++ b/server_files/services/mail_templates/unvalidate_team.html @@ -0,0 +1,19 @@ + + + + + Équipe non validée – TFJM² {YEAR} + + +Bonjour {FIRST_NAME} {SURNAME},
+
+Maleureusement, votre équipe « {TEAM_NAME} » ({TRIGRAM}) n'a pas été validée. Veuillez vérifier que vos autorisations sont correctes. +{MESSAGE}
+
+N'hésitez pas à nous contacter à l'adresse contact@tfjm.org pour plus d'informations. +
+Cordialement,
+
+Le comité national d'organisation du TFJM2 + + \ No newline at end of file diff --git a/server_files/services/mail_templates/validate_payment.html b/server_files/services/mail_templates/validate_payment.html new file mode 100644 index 0000000..afe94ba --- /dev/null +++ b/server_files/services/mail_templates/validate_payment.html @@ -0,0 +1,24 @@ + + + + + + Validation du paiement pour le TFJM² {YEAR} + + +Bonjour {FIRST_NAME} {SURNAME},
+
+Votre paiement pour le TFJM² {YEAR} a bien été validé. Pour rappel, vous aviez fourni ces informations :

+Équipe : {TEAM_NAME} ({TRIGRAM})
+Tournoi : {TOURNAMENT_NAME}
+Moyen de paiement : {PAYMENT_METHOD}
+Montant : {AMOUNT} €
+Informations sur le paiement : {PAYMENT_INFOS}
+
+{MESSAGE} +
+Cordialement, +
+Le comité national d'organisation du TFJM2 + + \ No newline at end of file diff --git a/server_files/services/mail_templates/validate_team.html b/server_files/services/mail_templates/validate_team.html new file mode 100644 index 0000000..0967488 --- /dev/null +++ b/server_files/services/mail_templates/validate_team.html @@ -0,0 +1,18 @@ + + + + + Équipe validée – TFJM² {YEAR} + + +Bonjour {FIRST_NAME} {SURNAME},
+
+Félicitations ! Votre équipe « {TEAM_NAME} » ({TRIGRAM}) est désormais validée ! Vous êtes désormais apte à travailler sur +vos problèmes et publier vos solutions sur la plateforme. +{MESSAGE}
+
+Cordialement,
+
+Le comité national d'organisation du TFJM2 + + \ No newline at end of file diff --git a/server_files/utils.php b/server_files/utils.php new file mode 100644 index 0000000..2bc4ce5 --- /dev/null +++ b/server_files/utils.php @@ -0,0 +1,32 @@ + + +
+

Ajouter une équipe

+
+ + +
+ Votre équipe a bien été créée ! Voici le code d'accès à transmettre aux autres membres de votre équipe : + access_code ?> +
+ +
+ Vous êtes déjà dans une équipe. +
+ + +
+
+
+ + +
+ +
+ + +
+
+ +
+ + +
+ +
+ +
+
+ + + diff --git a/server_files/views/ajouter_organisateur.php b/server_files/views/ajouter_organisateur.php new file mode 100644 index 0000000..9db8a91 --- /dev/null +++ b/server_files/views/ajouter_organisateur.php @@ -0,0 +1,51 @@ + + +
+

Ajouter un organisateur

+
+ + +
+ Organisateur ajouté avec succès ! Ses identifiants ont été transmis par mail. +
+ + +
+
+
+ + +
+ +
+ + +
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+ +
+ +
+
+ + diff --git a/server_files/views/ajouter_tournoi.php b/server_files/views/ajouter_tournoi.php new file mode 100644 index 0000000..2570da3 --- /dev/null +++ b/server_files/views/ajouter_tournoi.php @@ -0,0 +1,128 @@ + + +
+

Ajouter un tournoi

+
+ + +
+ Tournoi de name ?> ajouté avec succès ! +
+ + +
+
+
+ + +
+ +
+ + +
+
+ +
+
+ + +
+
+ +
+
+ + +
+ +
+ + +
+
+ +
+
+ + +
+
+ + +
+
+ +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ +
+
+ + + +
+
+ + + +
+
+ +
+
+ + +
+
+ + +

+ +
+ +
+
+ + \ No newline at end of file diff --git a/server_files/views/connexion.php b/server_files/views/connexion.php new file mode 100644 index 0000000..f59f4ac --- /dev/null +++ b/server_files/views/connexion.php @@ -0,0 +1,65 @@ +Le mail de récupération de mot de passe a bien été envoyé."; + elseif (isset($reset_password) && isset($_POST["password"])) + echo "
Le mot de passe a bien été changé. Vous pouvez désormais vous connecter.
"; + elseif (isset($_GET["confirmation-mail"])) + echo "
Le mail a bien été renvoyé.
"; + else if (isset($logging_in_user)) { + echo "
Connexion réussie !
"; + require_once "footer.php"; + } else if (isset($_SESSION["user_id"])) { + echo "
Vous êtes déjà connecté !
"; + require_once "footer.php"; + } +} + +if (isset($_GET["mdp_oublie"])) { ?> +
+

Réinitialisation du mot de passe

+ + + +
+user != null && ($has_error || !isset($_POST["password"]))) { ?> +
+

Connexion

+ "/> +
+ + +
+
+ + +
+ +
+ + +
+

Connexion

+
+
+ + +
+
+ + +
+ +
+
+ + Mot de passe oublié ? +
+ + + diff --git a/server_files/views/equipe.php b/server_files/views/equipe.php new file mode 100644 index 0000000..6744110 --- /dev/null +++ b/server_files/views/equipe.php @@ -0,0 +1,161 @@ + + +
+

Informations sur l'équipe

+
+ +
+ Nom de l'équipe : getName() ?> +
+
+ Trigramme : getTrigram() ?> +
+ +
+ getValidationStatus() != ValidationStatus::VALIDATED) { ?> + +
+ +
+ + Tournoi : getName() ?>"> + getTournamentId() == 0 ? "Pas de tournoi choisi" : $tournament->getName() ?> + + +
+ +
getValidationStatus() == ValidationStatus::WAITING ? "warning" : "danger") ?>"> + Validation de l'équipe + : getValidationStatus()) ?> +
+
+ getEncadrants()[$i - 1] == NULL) + continue; + $encadrant = User::fromId($team->getEncadrants()[$i - 1]); + $id = $encadrant->getId(); + echo "Encadrant : getFirstName() . " " . $encadrant->getSurname() . "\">" . $encadrant->getFirstName() . " " . $encadrant->getSurname() . "
"; + } + for ($i = 1; $i <= 6; ++$i) { + if ($team->getParticipants()[$i - 1] == NULL) + continue; + $participant = User::fromId($team->getParticipants()[$i - 1]); + $id = $participant->getId(); + echo "Participant $i : getFirstName() . " " . $participant->getSurname() . "\">" . $participant->getFirstName() . " " . $participant->getSurname() . "
"; + } + if ($team->isSelectedForFinal()) { + $final_name = $FINAL->getName(); + echo "Équipe sélectionnée pour la finale nationale."; + } + ?> +
+ +
+ ">Envoyer un mail à toute l'équipe +
+ + + +
+
+
+ + +
+ +
+ + +
+
+ +
+ + +
+ +
+ +
+
+ +getValidationStatus() != ValidationStatus::VALIDATED) { ?> +
+ + + +
+ +

Documents

+ + + +
+ +
+ +isSelectedForFinal()) { ?> +
+

Documents pour la finale

+ +
+ +
+ + +getValidationStatus() == ValidationStatus::WAITING) { ?> +
+
+ + +
+ +
+
+ + +
+
+
+ isSelectedForFinal() && $team->getValidationStatus() == ValidationStatus::VALIDATED) { ?> +
+
+ +
+getValidationStatus() == ValidationStatus::NOT_READY && $_SESSION["role"] == Role::ADMIN) { ?> +
+
+ +
+ + + \ No newline at end of file diff --git a/server_files/views/footer.php b/server_files/views/footer.php new file mode 100644 index 0000000..c84f917 --- /dev/null +++ b/server_files/views/footer.php @@ -0,0 +1,18 @@ +
+
+ + + + + + diff --git a/server_files/views/header.php b/server_files/views/header.php new file mode 100644 index 0000000..f503e23 --- /dev/null +++ b/server_files/views/header.php @@ -0,0 +1,163 @@ + + + + + + + + + Site d'inscription pour le TFJM² <?= $YEAR ?> + + + + + + + + + + + + + + + + +
+ +
+ + +
+ +
+
+ + getValidationStatus() == ValidationStatus::NOT_READY) { ?> +
+ Votre équipe n'est pas validée. Rendez-vous sur la page Mon équipe pour demander à + valider votre équipe. Si vous aviez déjà effectué cette procédure par le passé, sachez qu'en raison du + changement de format de l'édition 2020 du TFJM2, toutes les validations ont été retirées, et + vous devez à nouveau demander à valider votre équipe. Plus d'informations sur la page d'accueil. +
+ + + +
+ Erreur : +
+ + +
+
+

+ Bienvenue sur le site d'inscription au 𝕋𝔽𝕁𝕄2 ! +

+

+ Le Tournoi Français des Jeunes Mathématiciens et Mathématiciennes +

+
+
+
+
+

+ Tu souhaites participer au tournoi ? +
+ Ton équipe est déjà formée ? +

+
+ +
+ +
+
Attentions aux échéances
+

+ Chaque tournoi a une date limite pour les inscriptions et une date limite pour + déposer vos solutions. En savoir plus +

+
+ +
+
Modification du règlement
+

+ Depuis l'année dernière, l'équipe doit envoyer par mail à contact@tfjm.org les informations suivantes: +

    +
  • Comment l’équipe s’est-elle formée ?
  • +
  • + Comment l’équipe va-t-elle travailler (où peut-elle se rencontrer, à quelle fréquence, rencontres + avec l’encadrant•e) ? +
  • +
+ + Cette lettre permettra aux organisateurs•trices de vérifier que l’équipe dispose des conditions nécessaires + à une participation sérieuse. Sont dispensées les équipes dont la moitié ou plus des membres sont scolarisés + dans le même établissement. Le comité National d’Organisation se réserve le droit d’accepter ou non + l’inscription des équipes concernées par cette lettre. +

+
+ +
+ +
+
Comment ça marche ?
+

+ Pour participer à l'un des tournois régionaux, il suffit de créer un compte sur la rubrique + Inscription. Il vous faudra une adresse email pour ce faire. Un mail de confirmation sera envoyé + à cette adresse. Il vous fournira un nom d'utilisateur et un mot de passe que vous allez devoir changer + par la suite. +

+

+ Vous pouvez accéder à votre compte via la rubrique Connexion. Une fois connecté, vous pourrez : +

+
    +
  • rentrer des informations sur les membres de votre équipe, tant participants qu'encadrants ;
  • +
  • + enregistrer et télécharger des versions préliminaires de vos solutions (seulement la dernière + version enregistrée avant la date limite sera prise en compte pour le tournoi). +
  • +
+

+ Une fois que vous aurez fourni toutes les informations demandées dans la rubrique Mon Équipe, + votre inscription pourra être validée par les organisateurs locaux. +

+ +
+ Attention! Votre équipe ne sera considérée comme admissible à participer au tournoi que + lorsque cette première étape aura été franchie. +
+ +
+ Pensez donc à former une équipe complète (minimum 4 participants et 1 encadrant) le plus tôt possible + pour avoir plus de chances de participer, compte tenu du nombre des places disponibles dans chaque + tournoi (qui sera dûment affiché sur la rubrique Liste des Tournois). Les équipes restantes + seront placées en liste d'attente. +
+

+ Pour les équipes dont l'inscription aura été validée, des documents à télécharger, remplir et signer + deviendront disponibles sur votre compte. Vous allez devoir ensuite les scanner et les télécharger vers + le site pour compléter votre inscription. +

+
+ Attention Les équipes qui ne respecteront pas les délais pour rendre ces documents + risquent d'être disqualifiées et de laisser leur place aux équipes placées en liste d'attente. +
+
+ + +
+ Ce site est récent et il est encore possible que certaines pages ne fonctionnent + pas correctement. +
+ Si vous remarquez des bugs, merci de les signaler à l'adresse + contact@tfjm.org. +
+ +
\ No newline at end of file diff --git a/server_files/views/index.php b/server_files/views/index.php new file mode 100644 index 0000000..7c8e0b0 --- /dev/null +++ b/server_files/views/index.php @@ -0,0 +1,28 @@ + +
+ + + +
+ +
+ +
+
+ +
+ + Modifier la page + + + +
+

getFirstName() . " " . $user->getSurname() ?>

+
+ + +
+ La personne a bien été exclue de l'équipe ! +
+ +
+ La personne a bien rejoint l'équipe ! +
+ +
+ La paiement a bien été validé / rejeté ! Un mail a été transmis au participant. +
+ + + +
+ Rôle : getRole()) ?> +
+ +getRole() == Role::PARTICIPANT || $user->getRole() == Role::ENCADRANT) { ?> +
+ Équipe + : getTrigram() . "\">" + . $team->getName() . " (" . $team->getTrigram() . ")" ?> + +
+
+
+ + +
+
+
+ +
+
+ getValidationStatus() == ValidationStatus::NOT_READY) { ?> +
+ + Exclure de l'équipe +
+ +
+ + +getRole() == Role::PARTICIPANT || $user->getRole() == Role::ENCADRANT) { +?> +
+ Date de naissance : getBirthDate()) ?>
+
+ +
+ Genre : getGender() == "M" ? "Masculin" : "Féminin" ?>
+
+ +
+ Adresse : getAddress() . ", " . $user->getPostalCode() . " " . $user->getCity() . ($user->getCountry() == "France" ? "" : ", " . $user->getCountry()) ?>
+
+ + +
+ Adresse e-mail : getEmail() ?>
+
+ +
+ Numéro de téléphone : getPhoneNumber() ?>
+
+ +getRole() == Role::PARTICIPANT) { ?> +
+ Lycée : getSchool() ?>
+ Classe : getClass()) ?> +
+ +
+ Nom du responsable légal : getResponsibleName() ?> +
+ +
+ Numéro de téléphone du responsable légal : getResponsiblePhone() ?> +
+ +
+ Adresse e-mail du responsable légal : getResponsibleEmail() ?> +
+ + getRole() == Role::PARTICIPANT && $user->getTeamId() > 0) { ?> +
+ Récapitulatif du paiement :

+ + getValidationStatus() == ValidationStatus::NOT_READY) { ?> +
+ Cette personne n'a pas encore payé sa participation. +
+ + Tournoi : getName() ?>
+ Montant : getAmount() ?> €
+ Moyen de paiement : getMethod()) ?>
+ getMethod() == PaymentMethod::SCHOLARSHIP) { ?> + Notification de bourse : Télécharger

+ + Informations sur le paiement : getTransactionInfos() ?>

+ getValidationStatus() == ValidationStatus::WAITING) { ?> +
+ Le paiement n'a pas encore été validé. + +
+ + +
+ + +
+ + + +
+
+ +
+ Le paiement a été validé. +
+ + +
+ +
+ En raison du changement de format du TFJM² 2020, le tournoi est devenu gratuit. Il n'y a plus d'informations de + paiement à donner. +
+ +getDescription() != "") { ?> +
+ Description : getDescription() ?> +
+getRole() == Role::ADMIN || $user->getRole() == Role::ORGANIZER) { + foreach ($user->getOrganizedTournaments() as $tournament) { + echo "
Organise le tournoi getName(). "\">" . $tournament->getName() . "
"; + } +} +elseif (($user->getRole() == Role::PARTICIPANT || $user->getRole() == Role::ENCADRANT) && $user->getTeamId() !== NULL) { ?> + +

Documents

+ isSelectedForFinal()) { ?> +
+

Documents pour la finale

+ getRole() != Role::ADMIN && $team == null) { ?> +
+ +
+ +
+ +
+
+ getSurname() ?>"/> +
+ + +
+

Formulaire d'inscription

+
+ + +
+ Vous êtes bien inscrit ! Merci désormais de confirmer votre boîte mail pour valider votre adresse. Pensez à vérifier + vos courriers indésirables. +
+ +
+ Vous êtes déjà connecté ! +
+ + +
+
+
+ + +
+
+ +
+
+ + +
+ +
+ + +
+
+ +
+
+ + +
+
+ + +
+
+ +
+
+ + +
+
+ + +
+
+ +
+
+ +
+
+ /> + +
+
+ /> + +
+
+
+ + +
+
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + " required/> +
+
+
+
+ + +
+
+ + +
+
+ +
+
+ + + +
+
+ + + + +
+
+ + + + +
+ +
+ +
+ + + +
+ +
+ +
+
+ + + + + + \ No newline at end of file diff --git a/server_files/views/mon_compte.php b/server_files/views/mon_compte.php new file mode 100644 index 0000000..a086c7f --- /dev/null +++ b/server_files/views/mon_compte.php @@ -0,0 +1,266 @@ + + +
+

Mon compte

+
+ + +
+ Le fichier a été correctement envoyé ! +
+ + + +
+ Votre compte a bien été mis à jour ! +
+ getEmail() != $my_account->email) { ?> +
+ Votre adresse mail a bien été changée. Veuillez vérifier votre boîte mail pour valider votre nouvelle + adresse, vous en aurez besoin pour vous reconnecter. +
+ + + +
+ +
+
+ + +
+ +
+ + +
+
+ +
+
+ + +
+
+ + +
+
+ + getRole() == Role::PARTICIPANT || $user->getRole() == Role::ENCADRANT) { ?> + +
+
+ +
+
+ getGender() == "M" ? "checked" : "" ?> /> + +
+
+ getGender() == "F" ? "checked" : "" ?> /> + +
+
+
+ + +
+
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + + + getRole() == Role::PARTICIPANT) { ?> + +
+
+ + +
+
+ + +
+
+ +
+
+ + + +
+
+ + + + +
+
+ + + + +
+ +
+ + + +
+ + + +
+ + + +
+ +
+
+ +
+ +
+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+ +
+
+ +getRole() == Role::PARTICIPANT || $user->getRole() == Role::ENCADRANT)) { + $not_validated = $_SESSION["team"]->getValidationStatus() == ValidationStatus::NOT_READY; + ?> +
+
+

Mes documents

+
+ +
+ Ces documents peuvent être modifiés tant que l'équipe n'est pas validée. Les fichiers doivent peser au maximum 2 Mo et doivent + être au format PDF. +
+ +
+ En raison du changement de format du TFJM² 2020, il n'y a plus de document nécessaire à envoyer. Seule la lettre de motivation + pourra être considérée, même si son envoi n'est plus obligatoire. Merci de ne pas prêter attention à la partie qui suit. +
+ +
+ Modèle de fiche sanitaire : Télécharger
+ getBirthDate() > strval($YEAR - 18) . substr($tournament->getStartDate(), 4)) { ?> + Modèle d'autorisation parentale : Télécharger + - Modèle vierge
+ + Modèle d'autorisation de droit à l'image : Télécharger + - Modèle vierge +
+ + + +
+ Les fichiers doivent être au format PDF, PNG ou JPEG et peser moins de 2 Mo. +
+ +
+ +
+
+ + +
+
+ +
+
+ + +
+
+ +
+ +
+
+ + + + \ No newline at end of file diff --git a/server_files/views/mon_equipe.php b/server_files/views/mon_equipe.php new file mode 100644 index 0000000..b86b5d7 --- /dev/null +++ b/server_files/views/mon_equipe.php @@ -0,0 +1,184 @@ + + +
+

Mon équipe

+
+ +
+ Nom de l'équipe : getName() ?> +
+
+ Trigramme : getTrigram() ?> +
+
+ Tournoi : + getName() . "\">" . $tournament->getName() . "" ?> +
+
+ getEncadrants()[$i - 1] == NULL) + continue; + $encadrant = User::fromId($team->getEncadrants()[$i - 1]); + $id = $encadrant->getId(); + echo "Encadrant $i : getFirstName() . " " . $encadrant->getSurname() . "\">" . $encadrant->getFirstName() . " " . $encadrant->getSurname() . "
"; + } + for ($i = 1; $i <= 6; ++$i) { + if ($team->getParticipants()[$i - 1] == NULL) + continue; + $participant = User::fromId($team->getParticipants()[$i - 1]); + $id = $participant->getId(); + echo "Participant $i : getFirstName() . " " . $participant->getSurname() . "\">" . $participant->getFirstName() . " " . $participant->getSurname() . "
"; + } + ?> +
+ +
+ Code d'accès : getAccessCode() ?> +
+ +isSelectedForFinal()) { + $final_name = $FINAL->getName(); + echo "
Équipe sélectionnée pour la finale nationale.
"; +} ?> + + + +
+
+
+ + +
+ +
+ + +
+
+ +
+ + +
+ +
+ +
+
+ + + + getValidationStatus() == ValidationStatus::NOT_READY) { ?> + + + + + + getValidationStatus() == ValidationStatus::NOT_READY) { ?> +
+ +
+ +
+ + +
+
+ + +
+ Attention ! Une fois votre équipe validée, vous ne pourrez plus modifier le nom + de l'équipe, le trigramme ou la composition de l'équipe. +
+ +
+ +
+
+ Pour demander à valider votre équipe, vous devez avoir au moins un encadrant, quatre participants + et soumis une autorisation de droit à l'image, une fiche sanitaire et une autorisation + parentale (si besoin) par participant, ainsi qu'une lettre de motivation à transmettre aux organisateurs. + Les encadrants doivent également fournir une autorisation de droit à l'image. +
+ +
+
+ En raison du changement de format du TFJM² 2020, il n'y a plus de document obligatoire à envoyer. Les autorisations + précédemment envoyées ont été détruites. Seules les lettres de motivation ont été conservées, mais leur envoi + n'est plus obligatoire. +
+ getValidationStatus() == ValidationStatus::WAITING) { ?> +
+ Votre équipe est en attente de validation. +
+ + +
+ +

Documents de l'équipe

+ isSelectedForFinal()) { ?> +
+ +

Documents de l'équipe pour la finale

+ + + + + +getValidationStatus() == ValidationStatus::VALIDATED) { ?> +
+

Solutions à opposer/rapporter

+
+ Modèle vierge de note de synthèse (PDF -- TEX) +
+ +
+ Les solutions du tour 1 seront disponibles sur cette page peu après le tirage. +
+ getSolutionsDate2()) { ?> +
+ Les solutions du tour 2 pourront être téléchargées sur cette page à partir du getSolutionsDate2(), true) ?>. +
+getFileId(); + $problem = $sol->getProblem(); + $t = Team::fromId($sol->getTeamId()); + $trigram = $t->getTrigram(); + echo "
getSolutionsDate2() ? "danger" : "info") . "\">Problème $problem " + . " de l'équipe $trigram " . ($source == DestType::OPPOSANT ? "opposé" : "rapporté") . ", tour $round : Télécharger
\n"; + } + ?> + + + + \ No newline at end of file diff --git a/server_files/views/organisateurs.php b/server_files/views/organisateurs.php new file mode 100644 index 0000000..4e5ebea --- /dev/null +++ b/server_files/views/organisateurs.php @@ -0,0 +1,76 @@ + + +
+

Liste des organisateurs

+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Nom + + Prénom + + Adresse e-mail + + Est administrateur +
+ getSurname() ?>"> + getSurname() ?> + + + getSurname() ?>"> + getFirstName() ?> + + + + getEmail() ?> + + + getRole() == Role::ADMIN ? "oui" : "non" ?> +
+ Nom + + Prénom + + Adresse e-mail + + Est administrateur +
+ + + +
+

Paiement

+
+ +getValidationStatus() == ValidationStatus::NOT_READY) { ?> +
+ Le prix du tournoi est de getPrice() ?> €. Vous pouvez par carte bancaire via + la plateforme dédiée, + et indiquer sur cette page les informations de paiement qui nous permettront de le retrouver. + Si ce n'est pas possible, vous pouvez également procéder à un virement sur le compte :

+ IBAN : FR76 1027 8065 0000 0206 4290 127
+ BIC : CMCIFR2A

+ en précisant bien en référence du virement la mention TFJMpu suivie des nom et prénom de l'élève.

+ Si aucune de ces procédures n’est possible pour vous, envoyez un mail à contact@tfjm.org + pour que nous trouvions une solution à vos difficultés. +
+ +
+
+ + + + + + + +
+
+ + +getValidationStatus() == ValidationStatus::WAITING) { ?> +
+ Votre paiement est en attente de validation. +
+ +
+ Votre paiement a bien été validé. +
+ + +
+ Récapitulatif du paiement :

+ + Tournoi : getName() ?>
+ Montant : getAmount() ?> €
+ Moyen de paiement : getMethod()) ?>
+ getMethod() == PaymentMethod::SCHOLARSHIP) { ?> + Notification de bourse : Télécharger
+ + Informations sur le paiement : getTransactionInfos() ?>
+ +
+ + + +
+

+
+ +
+ Cette page recense tous les utilisateurs inscrits. +
+ +
+ subject=TFJM² " target="_blank">Envoyer un mail à toutes les personnes inscrites +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ Nom + + Rôle + + Inscrit le +
+ getFirstName() . " " . $user->getSurname() ?>"> + getFirstName() . " " . $user->getSurname() ?> + + getRole()) ?>getInscriptionDate(), true) ?>
+ Nom + + Rôle + + Inscrit le +
+ + + +
+

Rejoindre une équipe

+
+ + +
+ Vous avez bien rejoint l'équipe getName() ?> ! +
+ + + 0) { ?> +
+ Vous êtes déjà inscrit dans une équipe. Vous pouvez toutefois encadrer plusieurs équipes. +
+ + +
+
+
+ + +
+
+ +
+ +
+
+ + + + \ No newline at end of file diff --git a/server_files/views/solutions.php b/server_files/views/solutions.php new file mode 100644 index 0000000..a567353 --- /dev/null +++ b/server_files/views/solutions.php @@ -0,0 +1,62 @@ + +
+ Le fichier a été correctement envoyé ! +
+ + +getSolutionsDate()) { ?> +
+ +
+
+ + +
+ +
+ + +
+
+ + +
+ + +
+ +

Solutions soumises :

+ +getFileId(); + $problem = $sol->getProblem(); + $version = $sol->getVersion(); + echo "
Problème $problem (Version $version) : Télécharger
\n"; +} + +if ($team->isSelectedForFinal()) { ?> +
+ +

Solutions soumises pour la finale :

+ getFileId(); + $problem = $sol->getProblem(); + $version = $sol->getVersion(); + echo "
Problème $problem (Version $version) : Télécharger
\n"; + } +} + +require_once "footer.php"; diff --git a/server_files/views/solutions_orga.php b/server_files/views/solutions_orga.php new file mode 100644 index 0000000..aa7595d --- /dev/null +++ b/server_files/views/solutions_orga.php @@ -0,0 +1,30 @@ + + +
+

Solutions

+
+ +Tournoi de " . $tournament->getName() . "\n"; + $sols = $tournament->getAllSolutions(); + /** @var Solution $sol */ + foreach ($sols as $sol) { + $file_id = $sol->getFileId(); + $problem = $sol->getProblem(); + $version = $sol->getVersion(); + $team = Team::fromId($sol->getTeamId()); + $team_name = $team->getName(); + $team_trigram = $team->getTrigram(); + echo "
Problème n°$problem de l'équipe $team_name ($team_trigram), version $version : Télécharger
"; + } + + echo "
\n"; + echo "getId() . "\" />\n"; + echo "\n"; + echo "
\n"; +} + +require_once "server_files/views/footer.php"; \ No newline at end of file diff --git a/server_files/views/syntheses.php b/server_files/views/syntheses.php new file mode 100644 index 0000000..3b746a3 --- /dev/null +++ b/server_files/views/syntheses.php @@ -0,0 +1,80 @@ +getSolutionsDate()) { + echo "

Il est trop tôt pour se préoccuper des notes de synthèse, attendez le tirage des poules.

"; + require_once "server_files/views/footer.php"; +} + +if (isset($save_synthesis) && !$has_error) { ?> +
+ Le fichier a été correctement envoyé ! +
+ + +getSynthesesDate2()) { + if (date("Y-m-d H:i:s") < $tournament->getSynthesesDate()) { + ?> +
+ Attention : la date butoir de soumission des notes de synthèse pour le tour 1 est passée. Les prochaines notes de synthèses compteront pour le second tour. +
+ +
+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+
+ + +
+ + +
+ +

Notes de synthèse soumises :

+ +getFileId(); + $dest = $synthesis->getDest(); + $round = $synthesis->getRound(); + $version = $synthesis->getVersion(); + echo "
Note de synthèse " . ($dest == DestType::OPPOSANT ? "de l'opposant" : "du rapporteur") . ", tour $round (version $version) : Télécharger
"; +} + +if ($team->isSelectedForFinal()) { ?> +
+ +

Notes de synthèse soumises pour la finale :

+ getFileId(); + $dest = $synthesis->getDest(); + $round = $synthesis->getRound(); + $version = $synthesis->getVersion(); + echo "
Note de synthèse " . ($dest == DestType::OPPOSANT ? "de l'opposant" : "du rapporteur") . ", tour $round (version $version) : Télécharger
"; + } +} + +require_once "footer.php"; \ No newline at end of file diff --git a/server_files/views/syntheses_orga.php b/server_files/views/syntheses_orga.php new file mode 100644 index 0000000..9106b65 --- /dev/null +++ b/server_files/views/syntheses_orga.php @@ -0,0 +1,33 @@ + + +
+

Notes de synthèse

+
+ +Tournoi de " . $tournament->getName() . "\n"; + $syntheses = $tournament->getAllSyntheses(); + /** @var Synthesis $synthesis */ + foreach ($syntheses as $synthesis) { + $file_id = $synthesis->getFileId(); + $dest = $synthesis->getDest(); + $round = $synthesis->getRound(); + $version = $synthesis->getVersion(); + $team = Team::fromId($synthesis->getTeamId()); + $team_name = $team->getName(); + $team_trigram = $team->getTrigram(); + echo "
Note de synthèse de l'équipe $team_name ($team_trigram) pour " . ($dest == DestType::OPPOSANT ? "l'opposant" : "le rapporteur") + . ", tour $round, version $version : Télécharger
"; + } + + echo "
\n"; + echo "getId() . "\" />\n"; + echo "\n"; + echo "
\n"; +} + +require_once "server_files/views/footer.php"; diff --git a/server_files/views/tournoi.php b/server_files/views/tournoi.php new file mode 100644 index 0000000..9b54849 --- /dev/null +++ b/server_files/views/tournoi.php @@ -0,0 +1,241 @@ + + +
+

Tournoi de getName() ?>

+
+ + + +
+ Organisateur= 2 ? 's' : '' ?> : + getId(); + $orga_name = $orga->getFirstName() . " " . $orga->getSurname(); + if ($_SESSION["role"] == Role::ORGANIZER || $_SESSION["role"] == Role::ADMIN) + $s .= "$orga_name"; + else + $s .= $orga_name; + $s .= ", "; + } + echo substr($s, 0, -2); + ?> +
+
+ Nombre d'équipes maximal : getSize() ?> +
+
+ Lieu : getPlace() ?> +
+ +
+ Dates : Du getStartDate()) ?> au getEndDate()) ?> +
+
+ Clôture des inscriptions : getInscriptionDate(), true) ?> +
+
+ Date limite d'envoi des solutions : getSolutionsDate(), true) ?> +
+
+ Date limite d'envoi des notes de synthèse - tour 1 : getSynthesesDate(), true) ?> +
+
+ Date à partir de laquelle les solutions du tour 2 sont disponibles : getSolutionsDate2(), true) ?> +
+
+ Date limite d'envoi des notes de synthèse - tour 2 : getSynthesesDate2(), true) ?> +
+
+ Description : getDescription() ?> +
+isFinal()) + echo "
\n\tCe tournoi est la finale nationale du TFJM² 2020.\n
\n"; +?> + +organize($_SESSION["user_id"]))) { ?> +
+ &subject=TFJM² " target="_blank">Envoyer un mail à toutes les personnes inscrites au tournoi
+ &subject=TFJM² " target="_blank">Envoyer un mail à toutes les personnes inscrites au tournoi dans une équipe validée +
+ + + + + + +
+ +

Équipes inscrites à ce tournoi :

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Équipe + + Trigramme + + Date d'inscription + + État de validation de l'inscription +
+ organize($_SESSION["user_id"])))) + echo "getTrigram() . "\">" . $team->getName(). ""; + else + echo $team->getName(); + ?> + getTrigram() ?>getInscriptionDate()) ?>getValidationStatus()) ?>
+ Équipe + + Trigramme + + Date d'inscription + + État de validation de l'inscription +
+ + +
+
+ + +
+ +
+ + +
+ + +
+
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+
+ + +
+ +
+ + +
+
+ +
+
+ + + +
+ +
+ + + +
+ +
+ + + +
+
+ +
+
+ + + +
+ +
+ + + +
+
+ +
+
+ + +
+
+ + +
+ + + + diff --git a/server_files/views/tournois.php b/server_files/views/tournois.php new file mode 100644 index 0000000..5c7526d --- /dev/null +++ b/server_files/views/tournois.php @@ -0,0 +1,52 @@ + + +
+

Liste des tournois

+
+ + +
+ subject=TFJM² " target="_blank">Envoyer un mail à toutes les personnes inscrites au tournoi
+ subject=TFJM² " target="_blank">Envoyer un mail à toutes les personnes inscrites au tournoi dans une équipe validée +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NomDatesInscription avant leDate de rendu des solutionsPlaces disponibles
+ getName() ?> + Du getStartDate()) ?> au getEndDate()) ?>getInscriptionDate()) ?>getSolutionsDate()) ?>getSize() ?>
NomDatesInscription avant leDate de rendu des solutionsPlaces disponibles
+ + diff --git a/setup/create_database.sql b/setup/create_database.sql new file mode 100644 index 0000000..bc1eb1f --- /dev/null +++ b/setup/create_database.sql @@ -0,0 +1,275 @@ +-- phpMyAdmin SQL Dump +-- version 4.7.5 +-- https://www.phpmyadmin.net/ +-- +-- Host: db +-- Erstellungszeit: 18. Feb 2020 um 14:32 +-- Server-Version: 5.7.20 +-- PHP-Version: 7.1.9 + +SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; +SET AUTOCOMMIT = 0; +START TRANSACTION; +SET time_zone = "+02: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 */; + +-- +-- Datenbank: `inscription_tfjm` +-- +CREATE DATABASE IF NOT EXISTS `inscription_tfjm` DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci; +USE `inscription_tfjm`; + +-- -------------------------------------------------------- + +-- +-- Tabellenstruktur für Tabelle `documents` +-- + +CREATE TABLE `documents` ( + `file_id` varchar(64) NOT NULL, + `user` int(11) NOT NULL, + `team` int(11) NOT NULL, + `tournament` int(11) NOT NULL, + `type` varchar(64) NOT NULL, + `uploaded_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Tabellenstruktur für Tabelle `organizers` +-- + +CREATE TABLE `organizers` ( + `id` int(11) NOT NULL, + `organizer` int(11) NOT NULL, + `tournament` int(11) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Tabellenstruktur für Tabelle `payments` +-- + +CREATE TABLE `payments` ( + `id` int(11) NOT NULL, + `user` int(11) NOT NULL, + `tournament` int(11) NOT NULL, + `amount` tinyint(4) NOT NULL, + `method` enum('CREDIT_CARD','BANK_CHECK','BANK_TRANSFER','CASH','SCHOLARSHIP','NOT_PAID') COLLATE utf8_unicode_ci NOT NULL, + `transaction_infos` text COLLATE utf8_unicode_ci NOT NULL, + `validation_status` enum('NOT_READY','WAITING','VALIDATED','') COLLATE utf8_unicode_ci NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- Tabellenstruktur für Tabelle `solutions` +-- + +CREATE TABLE `solutions` ( + `file_id` varchar(64) NOT NULL, + `team` int(11) NOT NULL, + `tournament` int(11) NOT NULL, + `problem` int(11) NOT NULL, + `uploaded_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Tabellenstruktur für Tabelle `syntheses` +-- + +CREATE TABLE `syntheses` ( + `file_id` varchar(64) NOT NULL, + `team` int(11) NOT NULL, + `tournament` int(11) NOT NULL, + `dest` varchar(64) NOT NULL, + `uploaded_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Tabellenstruktur für Tabelle `teams` +-- + +CREATE TABLE `teams` ( + `id` int(11) NOT NULL, + `name` varchar(64) NOT NULL, + `trigram` varchar(3) NOT NULL, + `tournament` int(8) NOT NULL, + `encadrant_1` int(8) DEFAULT NULL, + `encadrant_2` int(8) DEFAULT NULL, + `encadrant_3` int(11) DEFAULT NULL, + `participant_1` int(8) DEFAULT NULL, + `participant_2` int(8) DEFAULT NULL, + `participant_3` int(8) DEFAULT NULL, + `participant_4` int(8) DEFAULT NULL, + `participant_5` int(8) DEFAULT NULL, + `participant_6` int(8) DEFAULT NULL, + `inscription_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `validation_status` enum('NOT_READY','WAITING','VALIDATED','') NOT NULL, + `final_selection` tinyint(1) NOT NULL DEFAULT '0', + `access_code` varchar(6) NOT NULL, + `year` int(4) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Tabellenstruktur für Tabelle `tournaments` +-- + +CREATE TABLE `tournaments` ( + `id` int(8) NOT NULL, + `name` varchar(64) NOT NULL, + `size` int(1) NOT NULL, + `place` varchar(255) NOT NULL, + `price` int(4) NOT NULL, + `description` varchar(255) NOT NULL, + `date_start` date NOT NULL, + `date_end` date NOT NULL, + `date_inscription` datetime NOT NULL, + `date_solutions` datetime NOT NULL, + `date_syntheses` datetime NOT NULL, + `final` tinyint(1) NOT NULL DEFAULT '0', + `year` int(4) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Tabellenstruktur für Tabelle `users` +-- + +CREATE TABLE `users` ( + `id` int(8) NOT NULL, + `email` varchar(255) NOT NULL, + `pwd_hash` varchar(64) NOT NULL, + `surname` varchar(255) NOT NULL, + `first_name` varchar(255) NOT NULL, + `birth_date` date DEFAULT NULL, + `gender` char(1) DEFAULT NULL, + `address` varchar(255) DEFAULT NULL, + `postal_code` int(5) DEFAULT NULL, + `city` varchar(255) DEFAULT NULL, + `country` varchar(255) DEFAULT 'France', + `phone_number` varchar(20) DEFAULT NULL, + `school` varchar(255) DEFAULT NULL, + `class` enum('SECONDE','PREMIERE','TERMINALE','ADULT') DEFAULT NULL, + `responsible_name` varchar(255) DEFAULT NULL, + `responsible_phone` varchar(20) DEFAULT NULL, + `responsible_email` varchar(255) DEFAULT NULL, + `description` varchar(255) DEFAULT NULL, + `role` enum('PARTICIPANT','ENCADRANT','ORGANIZER','ADMIN') NOT NULL, + `team_id` int(8) DEFAULT NULL, + `year` int(4) NOT NULL DEFAULT '2020', + `confirm_email` varchar(64) DEFAULT NULL COMMENT 'Jeton de confirmation d''e-mail', + `forgotten_password` varchar(64) DEFAULT NULL COMMENT 'Jeton de récupération de mot de passe', + `inscription_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Indizes der exportierten Tabellen +-- + +-- +-- Indizes für die Tabelle `documents` +-- +ALTER TABLE `documents` + ADD PRIMARY KEY (`file_id`); + +-- +-- Indizes für die Tabelle `organizers` +-- +ALTER TABLE `organizers` + ADD PRIMARY KEY (`id`), + ADD UNIQUE KEY `organizer` (`organizer`,`tournament`); + +-- +-- Indizes für die Tabelle `payments` +-- +ALTER TABLE `payments` + ADD PRIMARY KEY (`id`), + ADD UNIQUE KEY `user` (`user`); + +-- +-- Indizes für die Tabelle `solutions` +-- +ALTER TABLE `solutions` + ADD PRIMARY KEY (`file_id`); + +-- +-- Indizes für die Tabelle `syntheses` +-- +ALTER TABLE `syntheses` + ADD PRIMARY KEY (`file_id`); + +-- +-- Indizes für die Tabelle `teams` +-- +ALTER TABLE `teams` + ADD PRIMARY KEY (`id`), + ADD UNIQUE KEY `name/year` (`name`,`year`), + ADD UNIQUE KEY `trigram/year` (`trigram`,`year`); + +-- +-- Indizes für die Tabelle `tournaments` +-- +ALTER TABLE `tournaments` + ADD PRIMARY KEY (`id`), + ADD UNIQUE KEY `Name/year` (`name`,`year`) USING BTREE; + +-- +-- Indizes für die Tabelle `users` +-- +ALTER TABLE `users` + ADD PRIMARY KEY (`id`), + ADD UNIQUE KEY `email/year` (`email`,`year`) USING BTREE; + +-- +-- AUTO_INCREMENT für exportierte Tabellen +-- + +-- +-- AUTO_INCREMENT für Tabelle `organizers` +-- +ALTER TABLE `organizers` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=40; + +-- +-- AUTO_INCREMENT für Tabelle `payments` +-- +ALTER TABLE `payments` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=111; + +-- +-- AUTO_INCREMENT für Tabelle `teams` +-- +ALTER TABLE `teams` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=61; + +-- +-- AUTO_INCREMENT für Tabelle `tournaments` +-- +ALTER TABLE `tournaments` + MODIFY `id` int(8) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=12; + +-- +-- AUTO_INCREMENT für Tabelle `users` +-- +ALTER TABLE `users` + MODIFY `id` int(8) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=370; +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 */; diff --git a/setup/msmtprc b/setup/msmtprc new file mode 100644 index 0000000..3a3cc60 --- /dev/null +++ b/setup/msmtprc @@ -0,0 +1,18 @@ +defaults +auth on +tls on +tls_starttls off +tls_trust_file /etc/ssl/certs/ca-certificates.crt +syslog on +logfile /var/log/msmtp.log + +account tfjm +host ssl0.ovh.net +auth on +port 465 +from contact@tfjm.org +user contact@tfjm.org +passwordeval "echo $TFJM_MAIL_PASSWORD" + +# Set a default account +account default : tfjm