Эх сурвалжийг харах

Sending e-mail + admin panel

isundil 10 жил өмнө
parent
commit
05a208fb71

+ 3 - 0
pub/js/app.js

@@ -0,0 +1,3 @@
+$(".spoiler-trigger").click(function() {
+	$(this).parent().parent().next().collapse('toggle');
+});

+ 7 - 3
src/classes/CRM.php

@@ -2,9 +2,11 @@
 
 class CRM
 {
-	public static function sendInitEmail($dest, $name, $id)
+	public static function sendInitEmail($dest, $name, $id, $id_admin)
 	{
-		$result = print_r(array("dest" => $dest, "name" => $name, "id" => $id), true);
+		ob_start();
+		include('src/mails/init.php');
+		$result = ob_get_clean();
 		mail($dest, "[Secret santa] - Création de votre campagne", $result, "Content-Type: text/HTML");
 	}
 
@@ -20,7 +22,9 @@ class CRM
 		}
 		if ($from == null || $to == null)
 			return;
-		$result = print_r(array("from" => $from->getName(), "receiver" => $to->getName(), "camp" => array("name" => $campain->getName(), "description" => $campain->getDescr())), true);
+		ob_start();
+		include('src/mails/result.php');
+		$result = ob_get_clean();
 		mail($sender, "[Secret santa] - Résultat du tirage au sort", $result, "Content-Type: text/HTML");
 	}
 }

+ 2 - 1
src/classes/Secret.Entity.php

@@ -30,6 +30,7 @@ class SecretEntity extends \Entity
 	public function getUsers() { return UserEntity::getForCampain($this->id); }
 	public function getConstraints() { return ConstraintEntity::getForCampain($this->id); }
 	public function isFinished() { return $this->result !== null; }
+	public function getResult() { return $this->result; }
 
 	public function addUser($email, $name)
 	{
@@ -51,7 +52,7 @@ class SecretEntity extends \Entity
 		if (!($query->execute(array($admin, $description, $name))))
 			return false;
 		$id = self::getPdo()->lastInsertId();
-		return hash::encode($id);
+		return array(hash::encode($id), hash::encode_long($id));
 	}
 
 	public function setResult($result)

+ 1 - 1
src/classes/User.Entity.php

@@ -29,7 +29,7 @@ class UserEntity extends \Entity
 
 	public function getDisplay()
 	{
-		return $this->name != null ? $this->name : $this->getOpturEmail();
+		return htmlentities($this->name != null ? $this->name : $this->getOpturEmail());
 	}
 
 	/**

+ 16 - 3
src/classes/hash.class.php

@@ -5,20 +5,33 @@ require_once(__DIR__."/../lib/Hashids.php");
 
 class hash
 {
-	private static $salt = "_secretsanta_hash_8fb6f14e85be8141";
 
 	public static function encode($id)
 	{
-		$hashids = new Hashids\Hashids(self::$salt, 8);
+		$hashids = new Hashids\Hashids(SALT_S, 8);
+		return $hashids->encode($id);
+	}
+
+	public static function encode_long($id)
+	{
+		$hashids = new Hashids\Hashids(SALT_L, 12);
 		return $hashids->encode($id);
 	}
 
 	public static function decode($hash)
 	{
-		$hashids = new Hashids\Hashids(self::$salt, 8);
+		$hashlen = strlen($hash);
+		if ($hashlen != 8 && $hashlen != 12)
+			return -1;
+		$hashids = new Hashids\Hashids($hashlen == 8 ? SALT_S : SALT_L, $hashlen);
 		foreach ($hashids->decode($hash) as $i)
 			return $i;
 		return -1;
 	}
+
+	public static function isLong($hash)
+	{
+		return strlen($hash) == 12;
+	}
 }
 

+ 3 - 0
src/config.php

@@ -4,4 +4,7 @@ define("DB_USER", "secretsanta");
 define("DB_PASS", "Vh2SNDdapMPCquqU");
 define("DB_NAME", "secretsanta");
 
+define("SALT_S", "_secretsanta_hash_8fb6f14e85be8141");
+define("SALT_L", "_secretsanta_hash_4eb797109080f3db");
+
 

+ 3 - 3
src/create.php

@@ -19,12 +19,12 @@ class CreateController extends Controller
 		$cadmin = $_POST['cadmin'];
 		$name = empty($_POST['cname']) ? NULL : $_POST['cname'];
 		$desc = empty($_POST['cdescr']) ? NULL : $_POST['cdescr'];
-		$id = SecretEntity::create($cadmin, $name, $desc);
-		CRM::sendInitEmail($cadmin, $name, $id);
+		list($id, $id_admin) = SecretEntity::create($cadmin, $name, $desc);
+		CRM::sendInitEmail($cadmin, $name, $id, $id_admin);
 		if ($id !== false)
 		{
 			header("HTTP/1.0 302 Found");
-			header("Location: /".$id);
+			header("Location: /".$id_admin);
 			die;
 		}
 	}

+ 51 - 3
src/hash.php

@@ -4,11 +4,19 @@ require_once(dirname(__FILE__) . '/classes/Controller.php');
 require_once(dirname(__FILE__) . '/classes/SecretRandomizer.class.php');
 require_once(__DIR__.'/classes/Secret.Entity.php');
 
+class UserError extends Exception { }
+class RandomError extends Exception { }
+
 class CreateController extends Controller
 {
 	private $campain = null;
 	private $users = array();
 	private $constraints = array();
+	private $adminPanel = false;
+	private $publink = null;
+
+	private $randomError = false;
+	private $userError = false;
 
 	public function __construct($request)
 	{
@@ -19,15 +27,44 @@ class CreateController extends Controller
 			$this->render("404");
 			die;
 		}
+		$this->publink = $_SERVER['REQUEST_SCHEME']
+			.'://'
+			.$_SERVER['HTTP_HOST']
+			.$GLOBALS['baseUri']
+			.$this->getCampain()->getId();
+		$this->adminPanel = hash::isLong($request);
 		$this->users = $this->campain->getUsers();
 		$this->constraints = $this->campain->getConstraints();
 		if (!empty($_POST) && !$this->campain->isFinished())
-			$this->managePost();
+		{
+			try
+			{
+				$this->managePost();
+			}
+			catch (RandomError $e)
+			{
+				$this->randomError = true;
+			}
+			catch (UserError $e)
+			{
+				$this->userError = true;
+			}
+			if (!$this->randomError && !$this->userError)
+			{
+				header("HTTP/1.0 302 Found");
+				header("Location: ".$_SERVER['HTTP_REQUEST']);
+				die();
+			}
+		}
 		$this->render('hash');
 	}
 
 	public function getCampain() { return $this->campain; }
 	public function getUsers() { return $this->users; }
+	public function isAdmin() { return $this->adminPanel; }
+	public function getPublink() { return $this->publink; }
+	public function hasError() { return $this->randomError; }
+	public function hasUsererror() { return $this->userError; }
 
 	public function hasConstraint($userA, $userB)
 	{
@@ -38,15 +75,24 @@ class CreateController extends Controller
 		return false;
 	}
 
+	/**
+	 * @return Boolean false on random fail
+	**/
 	public function managePost()
 	{
 		if (!empty($_POST['launch']))
 		{
+			if (!$this->adminPanel)
+				return true;
+			if (count($this->users) < 2)
+				throw new RandomError();
 			$s = new SecretRandomizer($this->campain, $this->users, $this->constraints);
 			$result = $s->getResult();
+			if ($result->getResult() == null)
+				throw new RandomError();
 			$result->sendMails();
 			$this->campain->setResult($result->getResult());
-			return;
+			return true;
 		}
 		$this->campain->removeConstraints();
 		$groups = array();
@@ -62,9 +108,11 @@ class CreateController extends Controller
 		$this->constraints = $this->campain->getConstraints();
 		if (!empty($_POST['cemail']))
 		{
-			$this->campain->addUser($_POST['cemail'], $_POST['cname']);
+			if (!($this->campain->addUser($_POST['cemail'], $_POST['cname'])))
+				throw new UserError();
 			$this->users = $this->campain->getUsers();
 		}
+		return true;
 	}
 }
 

+ 7 - 0
src/mails/footer.inc.php

@@ -0,0 +1,7 @@
+			</div>
+			<div style="margin: auto; max-width: 600px; padding: 15px; padding: 1em;">
+				<p>Secretsanta est une application libre de droits. Vous pouvez suivre les &eacute;volutions du projet <a href="http://git.knacki.info/isundil/secretsanta">sur l'interface gogs du projet</a>.</p>
+			</div>
+		</div>
+	</body>
+</html>

+ 4 - 0
src/mails/header.inc.php

@@ -0,0 +1,4 @@
+<html>
+	<body style="background-color: #DCDCFF; margin: 0; padding: 0;" bgcolor="#DCDCFF">
+		<div style="margin: 0; padding: 0; background-color: #DCDCFF; width: 100%; height: 100%;">
+			<div style="margin: auto; max-width: 600px; padding: 15px; padding: 1em; background: white;">

+ 13 - 0
src/mails/init.php

@@ -0,0 +1,13 @@
+<?php
+require(dirname(__FILE__).'/header.inc.php');
+?><p>Vous avez cr&eacute;&eacute; une campagne secret santa, voici les informations utiles: <br/></p>
+	<ul>
+		<li>Lien d'administration: <a href="<?php echo $_SERVER['REQUEST_SCHEME'], '://', $_SERVER['HTTP_HOST'], $GLOBALS['baseUri'], $id_admin; ?>"><?php echo $_SERVER['REQUEST_SCHEME'], '://', $_SERVER['HTTP_HOST'], $GLOBALS['baseUri'], $id_admin; ?></a></li>
+		<p>Ce lien vous permettra d'effectuer le tirage au sort. Vous devez le conserver.</p>
+		<li>Lien public: <a href="<?php echo $_SERVER['REQUEST_SCHEME'], '://', $_SERVER['HTTP_HOST'], $GLOBALS['baseUri'], $id; ?>"><?php echo $_SERVER['REQUEST_SCHEME'], '://', $_SERVER['HTTP_HOST'], $GLOBALS['baseUri'], $id; ?></a></li>
+		<p>Ce lien est &agrave; transmettre aux participants pour qu'ils puissent s'inscrire.</p>
+	</ul>
+	<p>Une fois que tous les participants seront inscrits, vous pourrez cliquer sur "Confirmer et envoyer les e-mails" dans votre interface d'administration pour effectuer le tirage au sort.</p>
+<?php
+require(dirname(__FILE__).'/footer.inc.php');
+?>

+ 10 - 0
src/mails/result.php

@@ -0,0 +1,10 @@
+<?php
+require(dirname(__FILE__).'/header.inc.php');
+?>
+<p>Bonjour,<br/><br/>
+Les r&eacute;sultats du tirage au sort <?php if (!empty($campain->getName())): ?>pour <?php echo htmlentities($campain->getName()), ' '; endif; ?>sont disponibles !<br/>
+Vous avez &eacute;t&eacute; d&eacute;sign&eacute; pour faire un cadeau &agrave; <strong><?php if (!empty($to->getName())) { echo htmlentities($to->getName()); ?></strong> (<?php } echo htmlentities($to->getEmail()); if (!empty($to->getName())) echo ')'; ?><br/><br/>
+<?php if (!empty($campain->getDescr())) echo htmlentities($campain->getDescr()); ?>
+<?php
+require(dirname(__FILE__).'/footer.inc.php');
+?>

+ 1 - 1
src/views/create.php

@@ -22,6 +22,6 @@ Merci de remplir les champs ci-dessous :
 		</label>
 		<input type="text" name="cadmin" id="campain-email" class="form-control" placeholder="Adresse email" required />
 	</div>
-	<input type="submit" class="btn btn-default" />
+	<input type="submit" class="btn btn-default" value="Créer la campagne" />
 </form>
 <?php require(dirname(__FILE__).'/footer.inc.php'); ?>

+ 1 - 0
src/views/footer.inc.php

@@ -1,5 +1,6 @@
 	</div>
     <script src="pub/js/jquery-1.11.3.min.js"></script>
     <script src="pub/js/bootstrap.min.js"></script>
+    <script src="pub/js/app.js"></script>
   </body>
 </html>

+ 73 - 7
src/views/hash.php

@@ -1,9 +1,43 @@
 <?php require(dirname(__FILE__).'/header.inc.php'); ?>
+<?php if ($this->getCampain()->getDescr()) { ?>
+<div class="panel panel-default">
+	<?php if ($this->getCampain()->getName()) { ?>
+	<div class="panel-heading">
+		<h2><?php echo htmlentities($this->getCampain()->getName()); ?></h2>
+	</div>
+	<?php } ?>
+	<div class="panel-body">
+		<?php echo htmlentities($this->getCampain()->getDescr()); ?>
+	</div>
+</div>
+<?php } elseif ($this->getCampain()->getName()) { ?>
+<h2><?php echo htmlentities($this->getCampain()->getName()); ?></h2>
+<?php } ?>
+<?php if ($this->isAdmin()) { ?>
+<div class="panel panel-default"><div class="panel-heading">Lien public:</div>
+<div class="panel-body"><div class="highlight"><code><a href="<?php echo $this->getPublink(); ?>" target="_blank">
+<?php echo $this->getPublink(); ?>
+</a></code></div></div></div>
+<?php if ($this->haserror() && count($this->getusers()) >= 2) { ?>
+<div class="alert alert-danger">
+les contraintes entre les utilisateurs ne permettent pas de r&eacute;soudre le tirage au sort.
+</div>
+<?php } /* / randomizer error */ else if ($this->haserror()) { ?>
+<div class="alert alert-danger">
+Il n'y a pas suffisament de participants pour effectuer le tirage au sort.
+</div>
+<?php } /* / User count error */ } /* ! admin : public link */ ?>
+<?php if ($this->hasUsererror()) { ?>
+<div class="alert alert-danger">
+L'utilisateur est d&eacute;j&agrave; enregistr&eacute; pour le tirage.
+</div>
+<?php } /* / user exists error */ ?>
+<div class="panel panel-default"><div class="panel-body">
 <form method="POST" action="#" class="userlist">
 	<table class="table">
 		<thead>
 			<tr>
-				<th>Utilisateur</th>
+				<th>Utilisateurs</th>
 				<?php foreach ($this->getUsers() as $i): ?>
 				<th class="text-center"><?php echo $i->getDisplay(); ?>
 				<?php endforeach; ?>
@@ -52,10 +86,42 @@
 	<input type="submit" class="btn btn-default" value="Valider" />
 	<?php endif; ?>
 </form>
-<?php if (!$this->getCampain()->isFinished()): ?>
-<form method="POST">
-	<input type="hidden" name="launch" value="1" />
-	<input type="submit" class="btn btn-default" value="Confirmer et envoyer les e-mails" />
-</form>
-<?php endif; ?>
+</div></div>
+<?php if (!$this->getCampain()->isFinished() && $this->isAdmin()): ?>
+<div class="panel panel-default"><div class="panel-body">
+	<p>Quand toutes les personnes auront été inscrites au tirage au sort, vous pourrez cliquer sur le bouton ci-dessous pour effectuer le tirage au sort et envoyer les e-mails aux participants.</p>
+	<form method="POST">
+		<input type="hidden" name="launch" value="1" />
+		<input type="submit" class="btn btn-default" value="Confirmer et envoyer les e-mails" />
+	</form>
+</div></div>
+<?php elseif ($this->isAdmin()): ?>
+<div class="panel panel-default">
+	<div class="panel-heading">
+		R&eacute;sultat du tirage:
+		<div class="pull-right">
+			<button type="button" class="btn btn-default btn-xs spoiler-trigger" data-toggle="collapse">Voir les r&eacute;sultats</button>
+		</div>
+	</div>
+	<div class="panel-collapse collapse out"><div class="panel-body">
+		<table class="table table-stripped">
+			<thead>
+				<tr>
+					<th>L'utilisateur</th>
+					<th>offre &agrave;</th>
+				</tr>
+			</thead>
+			<tbody>
+				<?php $userCount = count($this->getCampain()->getResult());
+				for ($i =0; $i < $userCount; $i++): ?>
+				<tr>
+					<td><?php echo htmlentities($this->getCampain()->getResult()[$i]); ?></td>
+					<td><?php echo htmlEntities($this->getCampain()->getResult()[($i +1) % $userCount]); ?></td>
+				</tr>
+				<?php endfor; ?>
+			</tbody>
+		</table>
+	</div></div>
+</div>
+<?php endif; /* !admin */ ?>
 <?php require(dirname(__FILE__).'/footer.inc.php'); ?>