bcom/clazz/Membre2.class.php

721 lines
21 KiB
PHP
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
class Membre {
const DEFAULT_BANNER = "pictures/bande.png";
protected $ID = NULL;
protected $IDLoaded = FALSE;
protected $pseudo = NULL;
protected $pseudoLoaded = FALSE;
protected $hashedPassword = NULL;
protected $hashedPasswordLoaded = FALSE;
protected $adminLevel = NULL;
protected $adminLevelLoaded = FALSE;
protected $dateCreation = NULL;
protected $dateCreationLoaded = FALSE;
protected $requiredBanner = NULL;
protected $requiredBannerLoaded = FALSE;
protected $personnalMessage;
protected $personnalMessageLoaded = FALSE;
protected $count = NULL;
protected $where;
protected $whereArgs;
protected const ATTRIBUTES = array('ID','pseudo','hashedPassword','dateCreation','adminLevel','data');
protected function __construct($where,$whereArgs = array()) {
$this->where = $where;
$this->whereArgs = $whereArgs;
}
public static function me(){
if(!isset($_SESSION['session_id']))
return NO_SESSION_ID;
return new Membre('WHERE ID=?');
}
public static function getFromAttributes($restrictions){
$whereCommands = array();
$restrictionValues = array();
foreach ($restrictions as $restriction){
$whereCommand = NULL;
$attribute = $restriction[0];
$json = FALSE;
$operator = NULL;
$value = NULL;
try {
switch ($attribute){
case 'ID':
if($restriction[2][0] !== '0'){
echo 'Error : the type "'.$restriction[2][0].'" is not allowed for the attribute '.$attribute;
exit;
}
$value = intval($restriction[2][1]);
$operator = Utility::getIntegerSqlOperator($restriction[1]);
break;
case 'pseudo':
if($restriction[2][0] !== '"'){
echo 'Error : the type "'.$restriction[2][0].'" is not allowed for the attribute '.$attribute;
exit;
}
$value = '"'.strval($restriction[2][1]).'"';
$operator = Utility::getStringSqlOperator($restriction[1]);
break;
case 'hashedPseudo':
if($restriction[2][0] !== '"'){
echo 'Error : the type "'.$restriction[2][0].'" is not allowed for the attribute '.$attribute;
exit;
}
$value = '"'.strval($restriction[2][1]).'"';
$operator = Utility::getStringSqlOperator($restriction[1]);
break;
case 'adminLevel':
if($restriction[2][0] !== '0'){
echo 'Error : the type "'.$restriction[2][0].'" is not allowed for the attribute '.$attribute;
exit;
}
$value = intval($restriction[2][1]);
$operator = Utility::getIntegerSqlOperator($restriction[1]);
break;
case 'dateCreation':
if($restriction[2][0] !== '"'){//TODO add type date
echo 'Error : the type "'.$restriction[2][0].'" is not allowed for the attribute '.$attribute;
exit;
}
$value = '"'.$restriction[2][1].'"';
$operator = Utility::getDateSqlOperator($restriction[1]);
break;
case 'requiredBanner'://FIXME jsonMysqlProblem
$json=TRUE;
if($restriction[2][0] !== '"'){
echo 'Error : the type "'.$restriction[2][0].'" is not allowed for the attribute '.$attribute;
exit;
}
$value = '"'.strval($restriction[2][1]).'"';
$operator = Utility::getStringSqlOperator($restriction[1]);
break;
case 'personnalMessage':
$json=TRUE;
if($restriction[2][0] !== '"'){
echo 'Error : the type "'.$restriction[2][0].'" is not allowed for the attribute '.$attribute;
exit;
}
$value = '"'.strval($restriction[2][1]).'"';
$operator = Utility::getStringSqlOperator($restriction[1]);
break;
default:
echo 'Undefined attribute "'.$attribute.'" for the class Membre';
exit;
}
}catch(InvalidOperatorException $e){
echo $e->getMessage().' when reading attribute "'.$attribute.'"';
exit;
}
$restrictionValues[] = $value;
if($json){
$whereCommand = '((data->"$.'.$attribute.'" IS NOT NULL) AND (data->"$.'.$attribute.'" '.$operator.' ? ))';
}else{
$whereCommand = $attribute . ' ' . $operator . ' ' . $value;
}
$whereCommands[] = $whereCommand;
}
$wherePart = "";
if(count($whereCommands) >0)
$wherePart = 'WHERE '.implode(' AND ',$whereCommands);
$command = 'SELECT * FROM membres '.$wherePart;
$req = $GLOBALS['bdd']->prepare($command);
$req->execute($restrictionValues);
//echo $command.'</br>';
if($req->errorInfo()[0] != 0)
echo 'Erreur SQL, veuillez verifier les selecteurs';
$out = array();
while($rep = $req->fetch())
$out[] = new Membre($rep['ID']);
//Choose return value
switch(count($out)){
case 0:
return NULL;
case 1:
return $out[0];
default:
return $out;
}
}
public static function with($conditions){//[ { 'adminLevel' , '>=' , 24 } , { requiredBanner , '/home/banner.png' } , { email } ]
$wheres = array();
$whereAttributes = array();
foreach($conditions as $condition){
//TODO support custom conditions (OR, NAND)
//TODO test !is_array()
switch(count($condition)){
case 0:
throw new MalformedConditionException($conditions,'Une condition ne peut pas être NULL , voyons ...'));
break;
case 1:
assert(in_array($condition[0],Membre::ATTRIBUTES),new MalformedConditionException($conditions,'$condition[0] n\'est pas un attribut de la classe membre !'));
$wheres[] = $condition[0] . ' NOT NULL';
break;
case 2:
assert(in_array($condition[0],Membre::ATTRIBUTES),new MalformedConditionException($conditions,'$condition[0] n\'est pas un attribut de la classe membre !'));
$wheres[] = $condition[0] . ' = ?';
$whereAttributes[] = $condition[1];
break;
case 3:
assert(in_array($condition[0],Membre::ATTRIBUTES),new MalformedConditionException($conditions,'$condition[0] n\'est pas un attribut de la classe membre !'));
$operator = Utility::getSqlOperator($condition[2]);
assert($operator !== NULL,new MalformedConditionException($conditions,'$condition[2] n\'est pas un opérateur valide !'));
$wheres[] = $condition[0] . ' ' . $operator . ' ?';
$whereAttributes[] = $condition[1];
break;
default:
throw new MalformedConditionException($conditions,'Cette version du site ne comprends pas encore les conditions avec plus de trois paramètres (' . json_encode($condition); . ')');
}
}
$where = implode(' AND ',$wheres);
return new Membre($where,$whereAttributes);
}
public static function withPseudo($pseudo){
return new Membre('WHERE pseudo=?',array($pseudo));
}
public static function withAdminLevel($level){
return new Membre('WHERE adminLevel=?',array($level));
}
public static function withAdminLevelGreaterThan($level){
return new Membre('WHERE adminLevel>?',array($level));
}
public static function withAdminLevelLowerThan($level){
return new Membre('WHERE adminLevel<?',array($level));
}
public static function withDateCreation($date){
return new Membre('WHERE dateCreation=?',array($pseudo));
}
public static function withDateCreationLaterThan($date){
return new Membre('WHERE dateCreation>?',array($pseudo));
}
public static function withDateCreationEarlierThan($date){
return new Membre('WHERE dateCreation<?',array($pseudo));
}
public function checkPassword($password) {
return password_verify ($password, $this->getHashedPassword() );
}
public function __toString(){
return 'Membre with "' . $where . '" args:{' . $whereArgs . '}';
}
/**
@returns
Si le Membre est unique et que le dernier paramètre est faux (valeur par défaut)
@return [ 'ID' => 12 , 'pseudo' => "Mysaa" ]
Si le Membre est plurier ou si le dernier paramètre est vrai
@return [ { 'ID' => 12 , 'pseudo' => "Mysaa" } , { 'ID' => 11 , 'pseudo' => "Zlopeg" } ]
**/
public function get(){
$objects = func_get_args();
assert(count($objects) < 1, new BadMethodCallException('La methode get requiert au moins un argument'));
$array = end($objects);
if(gettype($array) !== 'boolean')
$array=FALSE;
else
array_pop($objects);
assert(count($objectsCount) < 1, new BadMethodCallException('La methode get requiert au moins un nom de paramètre à retourner !'));
$toAsk = array();
$toGive = array();
foreach($objects as $object){
assert(!is_string($object), new InvalidArgumentException('"$object" n\'est pas une chaine de caractère ... ça devrait'))
assert(in_array($object,Membre::ATTRIBUTES),new InvalidArgumentException('$object n\'est pas un attribut de la classe membre !'));
if($this->{$object . 'Loaded'})
array_push($toGive,$object);
else
array_push($toAsk,$object);
}
$result = array();
if(count($toAsk)>0){
$req = $GLOBALS['bdd']->prepare('SELECT ' . implode(',',$toAsk) . 'FROM membres WHERE ' . $this->where);
$req->execute($this->whereArgs);
$sqlResult = $req->fetchAll(PDO::FETCH_COLUMN | PDO::FETCH_GROUP);
foreach($toAsk as $item){
if(!isset($this->count))$this->count = count($item);
$this->$item = $sqlResult[$item];
$this->{$item . 'Loaded'} = TRUE;
$result[$item] = $sqlResult[$item];
}
}
foreach($toGive as $item)
$result[$item] = $this->$item;
/* RETURN */
if(count($result) === 0)
return $array?array():NULL;
$return = array()
if(!$array AND $this->count === 1)
foreach($result as $item => $values)$return[$key] = $values[0];
else
foreach($result as $key=>$res)
for($i=0;$i<$this->count;$i++)
$return[$i][$key] = $res[$i]
return $return;
}
public function count(){
if($this->count)return $this->count;
$req = $GLOBALS['bdd']->prepare('SELECT COUNT(*) AS count FROM membres WHERE ' . $this->where);
$req->execute($this->whereArgs);
return $req->fetch()['count'];
}
public function __call($funcName,$params){
if(preg_match('^get',$funcName)){// TODO Support multi get ("getPseudoAndAdminLevel")
$attributeName = lcfirst(substr($funcName,3))
assert(in_array($attributeName,Membre::ATTRIBUTES), new BadMethodCallException('$attributeName n\'est pas un attribut de la classe membre !'));
$return = call_user_func_array(array($this,'get'),array($attributeName));
return (count($return)===1)?$return[0]:$return;
}
}
public function get(){
$objects = func_get_args();
assert(count($objects) < 2, new BadMethodCallException('La methode set requiert au moins deux argument'));
$objectsCount = count($objects);
assert($objectsCount % 2 === 0, new BadMethodCallException('La methode set requiert un nombre pair d\'arguments'));
foreach($objects as $object){
assert(!is_string($object), new InvalidArgumentException('"$object" n\'est pas une chaine de caractère ... ça devrait'))
assert(in_array($object,Membre::ATTRIBUTES),new InvalidArgumentException('$object n\'est pas un attribut de la classe membre !'));
if($this->{$object . 'Loaded'})//FIXME to complete get -> set
array_push($toGive,$object);
else
array_push($toAsk,$object);
}
$result = array();
if(count($toAsk)>0){
$req = $GLOBALS['bdd']->prepare('SELECT ' . implode(',',$toAsk) . 'FROM membres WHERE ' . $this->where);
$req->execute($this->whereArgs);
$sqlResult = $req->fetchAll(PDO::FETCH_COLUMN | PDO::FETCH_GROUP);
foreach($toAsk as $item){
if(!isset($this->count))$this->count = count($item);
$this->$item = $sqlResult[$item];
$this->{$item . 'Loaded'} = TRUE;
$result[$item] = $sqlResult[$item];
}
}
foreach($toGive as $item)
$result[$item] = $this->$item;
/* RETURN */
if(count($result) === 0)
return $array?array():NULL;
$return = array()
if(!$array AND $this->count === 1)
foreach($result as $item => $values)$return[$key] = $values[0];
else
foreach($result as $key=>$res)
for($i=0;$i<$this->count;$i++)
$return[$i][$key] = $res[$i]
return $return;
}
private function decodeData($data) {
$jsonData = json_decode ( $data ,TRUE);
// Set the data's required_banner if it is defined , otherwise sets the DEFAULT_BANNER
$this->requiredBanner = $jsonData ['requiredBanner'] ?? self::DEFAULT_BANNER;
$this->personnalMessage = $jsonData ['personnalMessage'] ?? NULL;
}
//Getters
public function getID(){
return $this->ID;
}
public function getPseudo(){
return $this->pseudo;
}
public function getAdminLevel() {
return $this->adminLevel;
}
public function getDateCreation(){
return $this->dateCreation;
}
public function getRequiredBanner() {
return $this->requiredBanner;
}
public function getPersonnalMessage(){
return $this->personnalMessage;
}
//Useful getters
public function isAdminLevelLowerThan($max){
return $this->adminLevel<$max;
}
public function isAdminLevelGreaterThan($min){
return $this->adminLevel>$min;
}
public function isAdminLevelLowerOrEqualThan($max){
return $this->adminLevel<$max;
}
public function isAdminLevelGreaterOrEqualThan($min){
return $this->adminLevel>$max;
}
public function hasPersonnalMessage() {
return isset ( $this->personnalMessage );
}
public function showPersonnalMessage() {
$msg = $this->personnalMessage;
$this->setPersonnalMessage = NULL;
return $msg;
}
//Setters
public function changePassword($newPassword){
if(strlen($newPassword)>255)
return Membre::PASSWORD_TOO_LONG;
$req = $GLOBALS['bdd']->prepare('UPDATE membres SET hashedPassword=? WHERE ID=?');
$req->execute(array(password_hash ( $newPassword, PASSWORD_DEFAULT ),$this->ID));
return Membre::PASSWORD_CHANGED;
}
public function setAttribute($attribute,$value,$valueType){
$json=FALSE;
switch ($attribute){
case 'ID':
if($valueType !== '0'){
echo 'Error : the type "'.$valueType.'" is not allowed for the attribute '.$attribute;
exit;
}
$value = intval($value);
break;
case 'pseudo':
if($valueType !== '"'){
echo 'Error : the type "'.$valueType.'" is not allowed for the attribute '.$attribute;
exit;
}
$value = '"'.strval($value).'"';
break;
case 'hashedPseudo':
if($valueType !== '"'){
echo 'Error : the type "'.$valueType.'" is not allowed for the attribute '.$attribute;
exit;
}
$value = '"'.strval($value).'"';
break;
case 'adminLevel':
if($valueType !== '0'){
echo 'Error : the type "'.$valueType.'" is not allowed for the attribute '.$attribute;
exit;
}
$value = intval($value);
break;
case 'dateCreation':
if($valueType !== '"'){
echo 'Error : the type "'.$valueType.'" is not allowed for the attribute '.$attribute;
exit;
}
$value = '"'.$value.'"';
break;
case 'requiredBanner'://FIXME jsonMysqlProblem
$json=TRUE;
if($valueType !== '"'){
echo 'Error : the type "'.$valueType.'" is not allowed for the attribute '.$attribute;
exit;
}
$value = '"'.strval($value).'"';
break;
case 'personnalMessage':
$json=TRUE;
if($valueType !== '"'){
echo 'Error : the type "'.$valueType.'" is not allowed for the attribute '.$attribute;
exit;
}
$value = '"'.strval($value).'"';
break;
default:
echo 'Undefined attribute "'.$attribute.'" for the class Membre';
exit;
}
$restrictionValues[] = $value;
if($json){
//TODO Set command for json
}else{
$command = 'UPDATE membres SET ' . $attribute . '=' . $value . ' WHERE ID=' . $this->ID;
}
echo $command.'</br>';
$req = $GLOBALS['bdd']->prepare($command);
$req->execute(array());
if($req->errorInfo()[0] != 0){
echo 'Eine MYSQL Exception hat geworft. Einschuldigung';
exit;
}
}
/**
*
* @return Objects which matchs the specified restrictions
*/
public static function getFromAttributes($restrictions){
$whereCommands = array();
$restrictionValues = array();
foreach ($restrictions as $restriction){
$whereCommand = NULL;
$attribute = $restriction[0];
$json = FALSE;
$operator = NULL;
$value = NULL;
try {
switch ($attribute){
case 'ID':
if($restriction[2][0] !== '0'){
echo 'Error : the type "'.$restriction[2][0].'" is not allowed for the attribute '.$attribute;
exit;
}
$value = intval($restriction[2][1]);
$operator = Utility::getIntegerSqlOperator($restriction[1]);
break;
case 'pseudo':
if($restriction[2][0] !== '"'){
echo 'Error : the type "'.$restriction[2][0].'" is not allowed for the attribute '.$attribute;
exit;
}
$value = '"'.strval($restriction[2][1]).'"';
$operator = Utility::getStringSqlOperator($restriction[1]);
break;
case 'hashedPseudo':
if($restriction[2][0] !== '"'){
echo 'Error : the type "'.$restriction[2][0].'" is not allowed for the attribute '.$attribute;
exit;
}
$value = '"'.strval($restriction[2][1]).'"';
$operator = Utility::getStringSqlOperator($restriction[1]);
break;
case 'adminLevel':
if($restriction[2][0] !== '0'){
echo 'Error : the type "'.$restriction[2][0].'" is not allowed for the attribute '.$attribute;
exit;
}
$value = intval($restriction[2][1]);
$operator = Utility::getIntegerSqlOperator($restriction[1]);
break;
case 'dateCreation':
if($restriction[2][0] !== '"'){//TODO add type date
echo 'Error : the type "'.$restriction[2][0].'" is not allowed for the attribute '.$attribute;
exit;
}
$value = '"'.$restriction[2][1].'"';
$operator = Utility::getDateSqlOperator($restriction[1]);
break;
case 'requiredBanner'://FIXME jsonMysqlProblem
$json=TRUE;
if($restriction[2][0] !== '"'){
echo 'Error : the type "'.$restriction[2][0].'" is not allowed for the attribute '.$attribute;
exit;
}
$value = '"'.strval($restriction[2][1]).'"';
$operator = Utility::getStringSqlOperator($restriction[1]);
break;
case 'personnalMessage':
$json=TRUE;
if($restriction[2][0] !== '"'){
echo 'Error : the type "'.$restriction[2][0].'" is not allowed for the attribute '.$attribute;
exit;
}
$value = '"'.strval($restriction[2][1]).'"';
$operator = Utility::getStringSqlOperator($restriction[1]);
break;
default:
echo 'Undefined attribute "'.$attribute.'" for the class Membre';
exit;
}
}catch(InvalidOperatorException $e){
echo $e->getMessage().' when reading attribute "'.$attribute.'"';
exit;
}
$restrictionValues[] = $value;
if($json){
$whereCommand = '((data->"$.'.$attribute.'" IS NOT NULL) AND (data->"$.'.$attribute.'" '.$operator.' ? ))';
}else{
$whereCommand = $attribute . ' ' . $operator . ' ' . $value;
}
$whereCommands[] = $whereCommand;
}
$wherePart = "";
if(count($whereCommands) >0)
$wherePart = 'WHERE '.implode(' AND ',$whereCommands);
$command = 'SELECT * FROM membres '.$wherePart;
$req = $GLOBALS['bdd']->prepare($command);
$req->execute($restrictionValues);
//echo $command.'</br>';
if($req->errorInfo()[0] != 0)
echo 'Erreur SQL, veuillez verifier les selecteurs';
$out = array();
while($rep = $req->fetch())
$out[] = new Membre($rep['ID']);
//Choose return value
switch(count($out)){
case 0:
return NULL;
case 1:
return $out[0];
default:
return $out;
}
}
public static function getFromPseudo($pseudo){
return Membre::getFromAttributes(array(['pseudo','=',['"',$pseudo]]));
}
public static function getFromAdminLevel($level){
return Membre::getFromAttributes(array(['adminLevel','=',['0',$level]]));
}
public static function getFromDateCreation($date){
return Membre::getFromAttributes(array(['dateCreation','=',['0',$date]]));
}
public static function getCreatedLaterThan($date){
return Membre::getFromAttributes(array(['dateCreation','>',['"',$date]]));
}
public static function getCreatedEarlierThan($date){
return Membre::getFromAttributes(array(['dateCreation','<',['"',$date]]));
}
public static function getAdminGreaterThan($min){
return Membre::getFromAttributes(array(['adminLevel','>',['0',$min]]));
}
public static function getAdminLowerThan($max){
return Membre::getFromAttributes(array(['adminLevel','<',['0',$max]]));
}
//Membre creator
public static function registerPerson($pseudo, $mdp) {
if (Membre::getFromPseudo($pseudo))
return Membre::USED_USERNAME;
$req = $GLOBALS ['bdd']->prepare ('INSERT INTO membres(pseudo,mdp,date_creation) VALUES (?,?,NOW())');
$req->execute (array($pseudo,password_hash( $mdp, PASSWORD_DEFAULT)));
return Membre::PERSON_REGISTERED;
}
//Operateurs
public function __is_identical($copain){
return $this->getID() == $copain->getID();
}
//Outputs texts
const NO_SESSION_ID = 0;
//changePassword
const PASSWORD_TOO_LONG = 'Le mot de passe est trop long ! (Max : 255 caract&egrave;res)';
const PASSWORD_CHANGED = 'Le mot de passe a bien &eacute;t&eacute; chang&eacute;';
//registerPerson
const USED_USERNAME = 'Le pseudonyme est d&eacute;j&agrave; utilis&eacute;';
const PERSON_REGISTERED = 'Le membre a bien &eacute;t&eacute; inscrit !';
}