Browse Source

Creating campain

isundil 10 years ago
parent
commit
9e90c471f0

+ 5 - 0
pub/css/app.css

@@ -2,3 +2,8 @@ body { background: #DCDCFF; color: #000033; }
 .navbar-inverse { background-color: #000033; }
 .navbar-inverse .navbar-brand { color: #DCDCFF; }
 #page { margin-top: 85px; }
+.table>tbody>tr>td, .table>tbody>tr>th, .table>tfoot>tr>td, .table>tfoot>tr>th, .table>thead>tr>td, .table>thead>tr>th { border-color: #909090; }
+#page .userlist #cname-before { border-bottom-left-radius: 0; }
+#page .userlist #cname { border-bottom-right-radius: 0; }
+#page .userlist #cemail-before { border-top-left-radius: 0; }
+#page .userlist #cemail { border-top-right-radius: 0; }

+ 42 - 0
src/classes/Constraint.Entity.php

@@ -0,0 +1,42 @@
+<?php
+
+require_once(__DIR__."/Entity.class.php");
+
+class ConstraintEntity extends \Entity
+{
+	private $name;
+
+	public function __construct($data)
+	{
+		parent::__construct();
+		$this->userA = $data["userA"];
+		$this->userB = $data["userB"];
+	}
+
+	public function getUserA() { return $this->userA; }
+	public function getUserB() { return $this->userB; }
+
+	/**
+	 * Create entity
+	 * @var int $cId Campain id
+	 * @var string $email
+	 * @var string $name
+	 * @return Boolean
+	**/
+	public static function create($cId, $userA, $userB)
+	{
+		$query = self::getPdo()->prepare("INSERT INTO `users` (`campain`, `userA`, `userB`) VALUES(?, ?, ?)");
+		return ($query->execute(array($cId, $userA, $userB)));
+	}
+
+	public static function getForCampain($cId)
+	{
+		$cId = (int) $cId;
+		$q = self::getPdo()->query("SELECT * FROM `userConstraints` WHERE `campain`={$cId}");
+		$result = array();
+		foreach ($q as $i)
+			$result[] = new self($i);
+		return $result;
+	}
+}
+

+ 18 - 0
src/classes/Entity.class.php

@@ -0,0 +1,18 @@
+<?php
+
+require_once(__DIR__.'/../config.php');
+
+abstract class Entity {
+	private static $_dbo = null;
+
+	public function __construct() {
+		self::getPdo();
+	}
+
+	protected static function getPdo() {
+		if (self::$_dbo == null)
+			self::$_dbo = new PDO("mysql:host=localhost;dbname=".DB_NAME, DB_USER, DB_PASS);
+		return self::$_dbo;
+	}
+}
+

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

@@ -1,16 +1,60 @@
 <?php
 
-class SecretEntity
+require_once(__DIR__."/Entity.class.php");
+require_once(__DIR__."/User.Entity.php");
+require_once(__DIR__."/Constraint.Entity.php");
+require_once(__DIR__."/hash.class.php");
+
+class SecretEntity extends \Entity
 {
+	private $name;
+	private $description;
+	private $admin;
+	private $id;
+
+	public function __construct($data)
+	{
+		parent::__construct();
+		$this->name = $data["name"];
+		$this->description = $data["description"];
+		$this->admin = $data["admin"];
+		$this->id = $data["id"];
+	}
+
+	public function getName() { return $this->name; }
+	public function getAdmin() { return $this->admin; }
+	public function getDescr() { return $this->description; }
+	public function getId() { return hash::encode($this->id); }
+	public function getUsers() { return UserEntity::getForCampain($this->id); }
+	public function getConstraints() { return ConstraintEntity::getForCampain($this->id); }
+
 	/**
 	 * Create entity
 	 * @var string $admin
 	 * @var string $name
 	 * @var string $description
-	 * @return string|null string id or null on error
+	 * @return string|false string id or false on error
 	**/
 	public static function create($admin, $name, $description)
 	{
+		$name = empty($name) ? NULL : $name;
+		$description = empty($description) ? NULL : $description;
+		$query = self::getPdo()->prepare("INSERT INTO `campain` (`admin`, `description`, `name`) VALUES(?, ?, ?)");
+		if (!($query->execute(array($admin, $description, $name))))
+			return false;
+		$id = self::getPdo()->lastInsertId();
+		return hash::encode($id);
+	}
+
+	public static function fromId($id)
+	{
+		$rId = (int) hash::decode($id);
+		if ($rId <= 0)
+			return false;
+		$query = self::getPdo()->query("SELECT * FROM `campain` WHERE `id`={$rId}");
+		foreach ($query as $i)
+			return new self($i);
+		return false;
 	}
 }
 

+ 59 - 0
src/classes/User.Entity.php

@@ -0,0 +1,59 @@
+<?php
+
+require_once(__DIR__."/Entity.class.php");
+require_once(__DIR__."/Secret.Entity.php");
+require_once(__DIR__."/hash.class.php");
+
+class UserEntity extends \Entity
+{
+	private $name;
+	private $email;
+
+	public function __construct($data)
+	{
+		parent::__construct();
+		$this->name = $data["name"];
+		$this->email = $data["email"];
+	}
+
+	public function getName() { return $this->name; }
+	public function getEmail() { return $this->email; }
+
+	public function getOpturEmail()
+	{
+		$email = explode('@', $this->getEmail());
+		if (count($email) != 2)
+			return $this->getEmail();
+		return $email[0];
+	}
+
+	public function getDisplay()
+	{
+		return $this->name != null ? $this->name : $this->getOpturEmail();
+	}
+
+	/**
+	 * Create entity
+	 * @var int $cId Campain id
+	 * @var string $email
+	 * @var string $name
+	 * @return Boolean
+	**/
+	public static function create($cId, $email, $name)
+	{
+		$name = empty($name) ? NULL : $name;
+		$query = self::getPdo()->prepare("INSERT INTO `users` (`campain`, `email`, `name`) VALUES(?, ?, ?)");
+		return ($query->execute(array($cId, $email, $name)));
+	}
+
+	public static function getForCampain($cId)
+	{
+		$cId = (int) $cId;
+		$q = self::getPdo()->query("SELECT * FROM `users` WHERE `campain`={$cId}");
+		$result = array();
+		foreach ($q as $i)
+			$result[] = new self($i);
+		return $result;
+	}
+}
+

+ 24 - 0
src/classes/hash.class.php

@@ -0,0 +1,24 @@
+<?php
+
+require_once(__DIR__."/../lib/HashGenerator.php");
+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);
+		return $hashids->encode($id);
+	}
+
+	public static function decode($hash)
+	{
+		$hashids = new Hashids\Hashids(self::$salt, 8);
+		foreach ($hashids->decode($hash) as $i)
+			return $i;
+		return -1;
+	}
+}
+

+ 1 - 1
src/config.php

@@ -1,7 +1,7 @@
 <?php
 
 define("DB_USER", "secretsanta");
-define("DB_PASS", "password");
+define("DB_PASS", "Vh2SNDdapMPCquqU");
 define("DB_NAME", "secretsanta");
 
 

+ 8 - 2
src/create.php

@@ -16,9 +16,15 @@ class CreateController extends Controller
 	public function managePost()
 	{
 		$cadmin = $_POST['cadmin'];
-		$name = empty($_POST['cname']) ? '' : $_POST['cname'];
-		$desc = empty($_POST['cdescr']) ? '' : $_POST['cdescr'];
+		$name = empty($_POST['cname']) ? NULL : $_POST['cname'];
+		$desc = empty($_POST['cdescr']) ? NULL : $_POST['cdescr'];
 		$id = SecretEntity::create($cadmin, $name, $desc);
+		if ($id !== false)
+		{
+			header("HTTP/1.0 302 Found");
+			header("Location: /".$id);
+			die;
+		}
 	}
 }
 

+ 46 - 1
src/hash.php

@@ -1 +1,46 @@
-<?php var_dump($request); ?>
+<?php
+
+require_once(dirname(__FILE__) . '/classes/Controller.php');
+require_once(__DIR__.'/classes/Secret.Entity.php');
+
+class CreateController extends Controller
+{
+	private $campain = null;
+	private $users = array();
+	private $constraints = array();
+
+	public function __construct($request)
+	{
+		parent::__construct();
+		$this->campain = SecretEntity::fromId($request);
+		$this->users = $this->campain->getUsers();
+		$this->constraints = $this->campain->getConstraints();
+		if ($this->campain === false)
+		{
+			$this->render("404");
+			die;
+		}
+		if (!empty($_POST))
+			$this->managePost();
+		$this->render('hash');
+	}
+
+	public function getCampain() { return $this->campain; }
+	public function getUsers() { return $this->users; }
+
+	public function hasConstraint($userA, $userB)
+	{
+		foreach ($this->constraints as $i)
+			if (($i->getUserA() == $userA->getEmail() && $i->getUserB() == $userB->getEmail()) ||
+				($i->getUserA() == $userB->getEmail() && $i->getUserB() == $userA->getEmail()))
+				return true;
+		return false;
+	}
+
+	public function managePost()
+	{
+	}
+}
+
+return new CreateController($request);
+

+ 57 - 0
src/lib/HashGenerator.php

@@ -0,0 +1,57 @@
+<?php
+
+/*
+	
+	Hashids
+	http://hashids.org/php
+	(c) 2013 Ivan Akimov
+	
+	https://github.com/ivanakimov/hashids.php
+	hashids may be freely distributed under the MIT license.
+	
+*/
+
+namespace Hashids;
+
+/**
+ * HashGenerator is a contract for generating hashes
+ */
+interface HashGenerator {
+	
+	/**
+	 * Encodes a variable number of parameters to generate a hash
+	 * 
+	 * @param mixed ...
+	 * 
+	 * @return string the generated hash
+	 */
+	public function encode();
+	
+	/**
+	 * Decodes a hash to the original parameter values
+	 * 
+	 * @param string $hash the hash to decode
+	 * 
+	 * @return array
+	 */
+	public function decode($hash);
+	
+	/**
+	 * Encodes hexadecimal values to generate a hash
+	 * 
+	 * @param string $str hexadecimal string
+	 * 
+	 * @return string the generated hash
+	 */
+	public function encode_hex($str);
+	
+	/**
+	 * Decodes hexadecimal hash
+	 * 
+	 * @param string $hash
+	 * 
+	 * @return string hexadecimal string
+	 */
+	public function decode_hex($hash);
+	
+}

+ 356 - 0
src/lib/Hashids.php

@@ -0,0 +1,356 @@
+<?php
+
+/*
+	
+	Hashids
+	http://hashids.org/php
+	(c) 2013 Ivan Akimov
+	
+	https://github.com/ivanakimov/hashids.php
+	hashids may be freely distributed under the MIT license.
+	
+*/
+
+namespace Hashids;
+
+class Hashids implements HashGenerator {
+	
+	const VERSION = '1.0.5';
+	
+	/* internal settings */
+	
+	const MIN_ALPHABET_LENGTH = 16;
+	const SEP_DIV = 3.5;
+	const GUARD_DIV = 12;
+	
+	/* error messages */
+	
+	const E_ALPHABET_LENGTH = 'alphabet must contain at least %d unique characters';
+	const E_ALPHABET_SPACE = 'alphabet cannot contain spaces';
+	
+	/* set at constructor */
+	
+	private $_alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
+	private $_seps = 'cfhistuCFHISTU';
+	private $_min_hash_length = 0;
+	private $_math_functions = array();
+	private $_max_int_value = 1000000000;
+	
+	public function __construct($salt = '', $min_hash_length = 0, $alphabet = '') {
+		
+		/* if either math precision library is present, raise $this->_max_int_value */
+		
+		if (function_exists('gmp_add')) {
+			$this->_math_functions['add'] = 'gmp_add';
+			$this->_math_functions['div'] = 'gmp_div';
+			$this->_math_functions['str'] = 'gmp_strval';
+		} else if (function_exists('bcadd')) {
+			$this->_math_functions['add'] = 'bcadd';
+			$this->_math_functions['div'] = 'bcdiv';
+			$this->_math_functions['str'] = 'strval';
+		}
+		
+		$this->_lower_max_int_value = $this->_max_int_value;
+		if ($this->_math_functions) {
+			$this->_max_int_value = PHP_INT_MAX;
+		}
+		
+		/* handle parameters */
+		
+		$this->_salt = $salt;
+		
+		if ((int)$min_hash_length > 0) {
+			$this->_min_hash_length = (int)$min_hash_length;
+		}
+		
+		if ($alphabet) {
+			$this->_alphabet = implode('', array_unique(str_split($alphabet)));
+		}
+		
+		if (strlen($this->_alphabet) < self::MIN_ALPHABET_LENGTH) {
+			throw new \Exception(sprintf(self::E_ALPHABET_LENGTH, self::MIN_ALPHABET_LENGTH));
+		}
+		
+		if (is_int(strpos($this->_alphabet, ' '))) {
+			throw new \Exception(self::E_ALPHABET_SPACE);
+		}
+		
+		$alphabet_array = str_split($this->_alphabet);
+		$seps_array = str_split($this->_seps);
+		
+		$this->_seps = implode('', array_intersect($alphabet_array, $seps_array));
+		$this->_alphabet = implode('', array_diff($alphabet_array, $seps_array));
+		$this->_seps = $this->_consistent_shuffle($this->_seps, $this->_salt);
+		
+		if (!$this->_seps || (strlen($this->_alphabet) / strlen($this->_seps)) > self::SEP_DIV) {
+			
+			$seps_length = (int)ceil(strlen($this->_alphabet) / self::SEP_DIV);
+			
+			if ($seps_length == 1) {
+				$seps_length++;
+			}
+			
+			if ($seps_length > strlen($this->_seps)) {
+				
+				$diff = $seps_length - strlen($this->_seps);
+				$this->_seps .= substr($this->_alphabet, 0, $diff);
+				$this->_alphabet = substr($this->_alphabet, $diff);
+				
+			} else {
+				$this->_seps = substr($this->_seps, 0, $seps_length);
+			}
+			
+		}
+		
+		$this->_alphabet = $this->_consistent_shuffle($this->_alphabet, $this->_salt);
+		$guard_count = (int)ceil(strlen($this->_alphabet) / self::GUARD_DIV);
+		
+		if (strlen($this->_alphabet) < 3) {
+			$this->_guards = substr($this->_seps, 0, $guard_count);
+			$this->_seps = substr($this->_seps, $guard_count);
+		} else {
+			$this->_guards = substr($this->_alphabet, 0, $guard_count);
+			$this->_alphabet = substr($this->_alphabet, $guard_count);
+		}
+		
+	}
+	
+	public function encode() {
+		
+		$ret = '';
+		$numbers = func_get_args();
+		
+		if (func_num_args() == 1 && is_array(func_get_arg(0))) {
+			$numbers = $numbers[0];
+		}
+		
+		if (!$numbers) {
+			return $ret;
+		}
+		
+		foreach ($numbers as $number) {
+			
+			$is_number = ctype_digit((string)$number);
+			
+			if (!$is_number || $number < 0 || $number > $this->_max_int_value) {
+				return $ret;
+			}
+			
+		}
+		
+		return $this->_encode($numbers);
+		
+	}
+	
+	public function decode($hash) {
+		
+		$ret = array();
+		
+		if (!is_string($hash) || !($hash = trim($hash))) {
+			return $ret;
+		}
+		
+		return $this->_decode($hash, $this->_alphabet);
+		
+	}
+	
+	public function encode_hex($str) {
+		
+		if (!ctype_xdigit((string)$str)) {
+			return '';
+		}
+		
+		$numbers = trim(chunk_split($str, 12, ' '));
+		$numbers = explode(' ', $numbers);
+		
+		foreach ($numbers as $i => $number) {
+			$numbers[$i] = hexdec('1' . $number);
+		}
+		
+		return call_user_func_array(array($this, 'encode'), $numbers);
+		
+	}
+	
+	public function decode_hex($hash) {
+		
+		$ret = "";
+		$numbers = $this->decode($hash);
+		
+		foreach ($numbers as $i => $number) {
+			$ret .= substr(dechex($number), 1);
+		}
+		
+		return $ret;
+		
+	}
+	
+	public function get_max_int_value() {
+		return $this->_max_int_value;
+	}
+	
+	private function _encode(array $numbers) {
+		
+		$alphabet = $this->_alphabet;
+		$numbers_size = sizeof($numbers);
+		$numbers_hash_int = 0;
+		
+		foreach ($numbers as $i => $number) {
+			$numbers_hash_int += ($number % ($i + 100));
+		}
+		
+		$lottery = $ret = $alphabet[$numbers_hash_int % strlen($alphabet)];
+		foreach ($numbers as $i => $number) {
+			
+			$alphabet = $this->_consistent_shuffle($alphabet, substr($lottery . $this->_salt . $alphabet, 0, strlen($alphabet)));
+			$ret .= $last = $this->_hash($number, $alphabet);
+			
+			if ($i + 1 < $numbers_size) {
+				$number %= (ord($last) + $i);
+				$seps_index = $number % strlen($this->_seps);
+				$ret .= $this->_seps[$seps_index];
+			}
+			
+		}
+		
+		if (strlen($ret) < $this->_min_hash_length) {
+			
+			$guard_index = ($numbers_hash_int + ord($ret[0])) % strlen($this->_guards);
+			
+			$guard = $this->_guards[$guard_index];
+			$ret = $guard . $ret;
+			
+			if (strlen($ret) < $this->_min_hash_length) {
+				
+				$guard_index = ($numbers_hash_int + ord($ret[2])) % strlen($this->_guards);
+				$guard = $this->_guards[$guard_index];
+				
+				$ret .= $guard;
+				
+			}
+			
+		}
+		
+		$half_length = (int)(strlen($alphabet) / 2);
+		while (strlen($ret) < $this->_min_hash_length) {
+			
+			$alphabet = $this->_consistent_shuffle($alphabet, $alphabet);
+			$ret = substr($alphabet, $half_length) . $ret . substr($alphabet, 0, $half_length);
+			
+			$excess = strlen($ret) - $this->_min_hash_length;
+			if ($excess > 0) {
+				$ret = substr($ret, $excess / 2, $this->_min_hash_length);
+			}
+			
+		}
+		
+		return $ret;
+		
+	}
+	
+	private function _decode($hash, $alphabet) {
+		
+		$ret = array();
+		
+		$hash_breakdown = str_replace(str_split($this->_guards), ' ', $hash);
+		$hash_array = explode(' ', $hash_breakdown);
+		
+		$i = 0;
+		if (sizeof($hash_array) == 3 || sizeof($hash_array) == 2) {
+			$i = 1;
+		}
+		
+		$hash_breakdown = $hash_array[$i];
+		if (isset($hash_breakdown[0])) {
+			
+			$lottery = $hash_breakdown[0];
+			$hash_breakdown = substr($hash_breakdown, 1);
+			
+			$hash_breakdown = str_replace(str_split($this->_seps), ' ', $hash_breakdown);
+			$hash_array = explode(' ', $hash_breakdown);
+			
+			foreach ($hash_array as $sub_hash) {
+				$alphabet = $this->_consistent_shuffle($alphabet, substr($lottery . $this->_salt . $alphabet, 0, strlen($alphabet)));
+				$ret[] = (int)$this->_unhash($sub_hash, $alphabet);
+			}
+			
+			if ($this->_encode($ret) != $hash) {
+				$ret = array();
+			}
+			
+		}
+		
+		return $ret;
+		
+	}
+	
+	private function _consistent_shuffle($alphabet, $salt) {
+		
+		$salt_length = strlen($salt);
+		if (!$salt_length) {
+			return $alphabet;
+		}
+		
+		for ($i = strlen($alphabet) - 1, $v = 0, $p = 0; $i > 0; $i--, $v++) {
+			
+			$v %= $salt_length;
+			$p += $int = ord($salt[$v]);
+			$j = ($int + $v + $p) % $i;
+			
+			$temp = $alphabet[$j];
+			$alphabet[$j] = $alphabet[$i];
+			$alphabet[$i] = $temp;
+			
+		}
+		
+		return $alphabet;
+		
+	}
+	
+	private function _hash($input, $alphabet) {
+		
+		$hash = '';
+		$alphabet_length = strlen($alphabet);
+		
+		do {
+			
+			$hash = $alphabet[$input % $alphabet_length] . $hash;
+			if ($input > $this->_lower_max_int_value && $this->_math_functions) {
+				$input = $this->_math_functions['str']($this->_math_functions['div']($input, $alphabet_length));
+			} else {
+				$input = (int)($input / $alphabet_length);
+			}
+			
+		} while ($input);
+		
+		return $hash;
+		
+	}
+	
+	private function _unhash($input, $alphabet) {
+		
+		$number = 0;
+		$input_length = strlen($input);
+
+		if ($input_length && $alphabet) {
+			
+			$alphabet_length = strlen($alphabet);
+			$input_chars = str_split($input);
+			
+			foreach ($input_chars as $i => $char) {
+				
+				$pos = strpos($alphabet, $char);
+				if ($this->_math_functions) {
+					$number = $this->_math_functions['str']($this->_math_functions['add']($number, $pos * pow($alphabet_length, ($input_length - $i - 1))));
+				} else {
+					$number += $pos * pow($alphabet_length, ($input_length - $i - 1));
+				}
+				
+			}
+			
+		}
+		
+		return $number;
+		
+	}
+	
+}

+ 1 - 0
src/views/404.php

@@ -1,2 +1,3 @@
 <?php require(dirname(__FILE__).'/header.inc.php'); ?>
+Oops 404
 <?php require(dirname(__FILE__).'/footer.inc.php'); ?>

+ 1 - 1
src/views/create.php

@@ -14,7 +14,7 @@ Merci de remplir les champs ci-dessous :
 		<label for="campain-description">Description 
 			<em>Une description de l'&eacute;v&eacute;nement <small>(optionnel)</small></em>
 		</label>
-		<textarea name="cdescription" id="campain-description" class="form-control"></textarea>
+		<textarea name="cdescr" id="campain-description" class="form-control"></textarea>
 	</div>
 	<div class="form-group">
 		<label for="campain-email">Adresse email 

+ 48 - 0
src/views/hash.php

@@ -1,2 +1,50 @@
 <?php require(dirname(__FILE__).'/header.inc.php'); ?>
+<form method="POST" action="#" class="userlist">
+	<table class="table">
+		<thead>
+			<tr>
+				<th>Utilisateur</th>
+				<?php foreach ($this->getUsers() as $i): ?>
+				<th class="text-center"><?php echo $i->getDisplay(); ?>
+				<?php endforeach; ?>
+			</tr>
+		</thead>
+		<tbody>
+			<?php
+			foreach ($this->getUsers() as $i):
+			$pass = false;
+			?>
+			<tr>
+				<td><?php echo $i->getDisplay(); ?></td>
+				<?php foreach ($this->getUsers() as $j): ?>
+				<td class="text-center"><?php
+				if ($i->getEmail() == $j->getEmail())
+					$pass = true;
+				else if (!$pass)
+				{
+					?><input type="checkbox" name="<?php echo md5($i->getEmail()).'-'.md5($j->getEmail()); ?>" <?php
+					if (!$this->hasConstraint($i, $j))
+						echo " checked";
+					echo '/>';
+				}
+				echo '</td>';
+				endforeach; ?>
+			</tr>
+			<?php endforeach; ?>
+			<tr>
+				<td>
+					<div class="form-group">
+						<label for="cname">Ajouter un participant : </label>
+						<div class="input-group"><span class="input-group-addon glyphicon glyphicon-user" id="cname-before"></span><input id="cname" type="text" placeholder="nom *" class="form-control" name="cname" /></div>
+						<div class="input-group"><span class="input-group-addon glyphicon glyphicon-envelope" id="cemail-before"></span><input type="email" placeholder="email" class="form-control" id="cemail" name="cemail" /></div>
+					</div>
+				</td>
+				<?php for ($i=0; $i < count($this->getUsers()); $i++): ?>
+				<td></td>
+				<?php endfor; ?>
+			</tr>
+		</tbody>
+	</table>
+	<input type="submit" class="btn btn-default" value="Valider" />
+</form>
 <?php require(dirname(__FILE__).'/footer.inc.php'); ?>