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.'
'; 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($pseudo)); } public static function withDateCreationEarlierThan($date){ return new Membre('WHERE dateCreationgetHashedPassword() ); } 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.'
'; $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.'
'; 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ères)'; const PASSWORD_CHANGED = 'Le mot de passe a bien été changé'; //registerPerson const USED_USERNAME = 'Le pseudonyme est déjà utilisé'; const PERSON_REGISTERED = 'Le membre a bien été inscrit !'; }