- changes in layout of the achievementgroup cards

- accomplished/next achievement(s) now in collappsibel
  - record reporting button now hidden in collapsible
  - cards list groups that are unlocked from the group
This commit is contained in:
marko
2020-11-29 18:06:30 +01:00
parent de24498f77
commit ac7d81b136
4 changed files with 237 additions and 83 deletions

View File

@@ -91,12 +91,12 @@ function processPostData($db, $post, $redirectLocation = "."){
$u['vorname']." ".$u['name']." got ".$post['value']." in ".$g->getName(), $u['vorname']." ".$u['name']." got ".$post['value']." in ".$g->getName(),
"[machs] Rekord eingetragen" "[machs] Rekord eingetragen"
); );
//setRecord( setRecord(
//$db, $db,
//$post['userId'], $post['userId'],
//$post['achievementGroupId'], $post['achievementGroupId'],
//$post['value'] $post['value']
//); );
} }
if($post['action']=="reportRecord"){ if($post['action']=="reportRecord"){
# $u = getUserData($db, $post['userId']); # $u = getUserData($db, $post['userId']);

View File

@@ -13,7 +13,9 @@ class achievementGroup{
private $unlockingAchievementId; private $unlockingAchievementId;
// an image for the group // an image for the group
private $imageUrl; private $imageUrl;
// flag, if the group can has records
private $canHaveRecords;
// achievements, that belong to this group // achievements, that belong to this group
private $achievements; private $achievements;
@@ -49,7 +51,8 @@ SQL;
$r['id'], $r['id'],
$r['name'], $r['name'],
$r['unlockingAchievementId'], $r['unlockingAchievementId'],
$r['imageUrl'] $r['imageUrl'],
$r['canHaveRecords']
); );
$groups[$gid]->getAchievements(['force'=>true]); $groups[$gid]->getAchievements(['force'=>true]);
} }
@@ -61,6 +64,7 @@ SQL;
function getName(){return $this->name;} function getName(){return $this->name;}
function getUnlockingAchievementId(){return $this->unlockingAchievementId;} function getUnlockingAchievementId(){return $this->unlockingAchievementId;}
function getImageUrl(){return $this->imageUrl;} function getImageUrl(){return $this->imageUrl;}
function canHaveRecords(){return $this->canHaveRecords;}
/// returns list of achievements /// returns list of achievements
/// - returns the previously loaded achievements /// - returns the previously loaded achievements
@@ -91,41 +95,87 @@ SQL;
$result[0]['id'], $result[0]['id'],
$result[0]['name'], $result[0]['name'],
$result[0]['unlockingAchievementId'], $result[0]['unlockingAchievementId'],
$result[0]['imageUrl'] $result[0]['imageUrl'],
$result[0]['canHaveRecords']
); );
$this->getAchievements(['force'=>true]); $this->getAchievements(['force'=>true]);
} }
/// Set the member data of the group /// Set the member data of the group
function setAchievementGroupData($id, $name, $unlockingAchievementId=null, $imageUrl=null){ function setAchievementGroupData($id, $name, $unlockingAchievementId=null, $imageUrl=null, $canHaveRecords=null){
$this->id = (int)$id; $this->id = (int)$id;
$this->name = $name; $this->name = $name;
$this->unlockingAchievementId = ($unlockingAchievementId == null ? null : (int)$unlockingAchievementId); $this->unlockingAchievementId = ($unlockingAchievementId == null ? null : (int)$unlockingAchievementId);
$this->imageUrl = $imageUrl; $this->imageUrl = $imageUrl;
$this->canHaveRecords = (bool)$canHaveRecords;
# echo("bool(".$canHaveRecords.")=".$this->canHaveRecords."\n");
# var_dump($canHaveRecords, $this->canHaveRecords);
} }
/// gets all achievements of that user in that group reachedd /// get the next achievement, the user has to accomplish in that group
function getUsersNextAchievement($userId){
$groupsAchievements = $this->getAchievements();
if(count($this->getAchievements()) < 1)
return null;
$usersAchievementsIds = collectKeysValues(
$this->getUsersAchievements($userId),
'achievementId'
);
$usersNextAchievement = null;
foreach($groupsAchievements as $ga){
if(!in_array($ga['id'], $usersAchievementsIds)){
if($usersNextAchievement == null){
$usersNextAchievement = $ga;
continue;
}
if( $usersNextAchievement['level'] > $ga['level'] ){
$usersNextAchievement = $ga;
};
}
}
return $usersNextAchievement;
}
/// get all achievements, that unlock something
static function getUnlockingAchievements(){
// get all achievements
}
/// gets all achievements a user reached in that group as Array
function getUsersAchievements($userId, $options=[]){ function getUsersAchievements($userId, $options=[]){
$getAll = $options['getAll']??false; $getAll = $options['getAll']??false; // ignore restriction to this group
$query = "";
$query.= "SELECT * FROM `cwsvjudo`.`achievements<=>user` "; $query = <<<SQL
$query.= "WHERE `userId` = :userId"; SELECT *, `cwsvjudo`.`achievements`.`name` AS `achievementName` FROM `cwsvjudo`.`achievements<=>user`
if(!$getAll) JOIN `cwsvjudo`.`achievements`
$query.=" AND `achievementId` = :achievementId"; ON `cwsvjudo`.`achievements<=>user`.`achievementId` = `cwsvjudo`.`achievements`.`id`
$query.= ";"; JOIN `cwsvjudo`.`machs_achievementGroups`
$params[':userId'] = array('value'=>$userId, 'data_type'=>PDO::PARAM_INT); ON `cwsvjudo`.`achievements`.`achievementGroupId` = `cwsvjudo`.`machs_achievementGroups`.`id`
if(!$getAll) WHERE `cwsvjudo`.`achievements<=>user`.`userid` = :userId
$params[':achievementId'] = array('value'=>$this->getId(), 'data_type'=>PDO::PARAM_INT); SQL;
$result = dbQuery($this->getDbConnection(), $query, $params); if(!$getAll){
return $result; $query.=" AND `cwsvjudo`.`machs_achievementGroups`.`id` = :achievementGroupId ";
} $query.="ORDER BY `cwsvjudo`.`achievements`.`level` DESC";
}
$query.=";";
$params[':userId'] = array('value'=>$userId, 'data_type'=>PDO::PARAM_INT);
if(!$getAll)
$params[':achievementGroupId'] = array('value'=>$this->getId(), 'data_type'=>PDO::PARAM_INT);
$result = dbQuery($this->getDbConnection(), $query, $params);
# var_dump($query);
# var_dump($result);
return $result;
}
/// returns the materialize card html code of the Achievementgroup /// returns the materialize card html code of the Achievementgroup
/// ///
/// @param $uId id of the user the achievements should be /// @param $uId id of the user the achievements should be
function asHtmlCard($uId, $options=[]){ function asHtmlCard($uId, $options=[]){
// Setting standard options
$noForm = $options['noForm']??true; // for deactivating the give achievement form $noForm = $options['noForm']??true; // for deactivating the give achievement form
$retHtml = ""; $retHtml = "";
$userData = record::getUserData($uId); $userData = record::getUserData($uId);
$usersAchievements = $this->getUsersAchievements( $uId, ['getAll'=>true] ); $usersAchievements = $this->getUsersAchievements( $uId, ['getAll'=>true] );
$usersAchievementIds=[null]; $usersAchievementIds=[null];
@@ -135,15 +185,17 @@ return $result;
// If the user hasn't have the needed Achievement // If the user hasn't have the needed Achievement
if(!in_array($this->getUnlockingAchievementId(), $usersAchievementIds)) if(!in_array($this->getUnlockingAchievementId(), $usersAchievementIds))
return ""; return "";
$records = record::getGroupsRecords( $records = record::getGroupsRecords(
$this->getId(), $this->getId(),
record::birthday2ageClass($userData[0]['gebDatum']) record::birthday2ageClass($userData[0]['gebDatum'])
); );
$achievements = $this->getAchievements(); $achievements = $this->getAchievements();
$retHtml .= "<div class=\"col s12 m6 l4 xl3\">"; $retHtml .= "<div class=\"col s12 m6 l4 xl3\">";/// @todo gehört eigentlich nicht mit zur karte
$retHtml .= "<div class=\"card\">"; $retHtml .= "<div class=\"card\">";
// image + title
if($this->imageUrl != null){ if($this->imageUrl != null){
$retHtml .= "<div class=\"card-image\"><img src=\"".$this->imageUrl."\">"; $retHtml .= "<div class=\"card-image\"><img src=\"".$this->imageUrl."\">";
$retHtml .= "<span class=\"card-title\">".$this->name."</span>"; $retHtml .= "<span class=\"card-title\">".$this->name."</span>";
@@ -152,50 +204,59 @@ return $result;
else else
$retHtml .= "<span style=\"padding-left: 1vw;\" class=\"card-title\">".$this->name."</span>"; $retHtml .= "<span style=\"padding-left: 1vw;\" class=\"card-title\">".$this->name."</span>";
// content
$retHtml .= "<div class=\"card-content\">"; $retHtml .= "<div class=\"card-content\">";
$retHtml .= "<ul class=\collapsible\">"; // - das nächste achievement
foreach($achievements as $a){ // - als collapsible (list): des users erreichte achievements
if(in_array((int)$a['id'], $usersAchievementIds)){
$retHtml .= "<li>&#10003; ".$a['name'].": ".$a['description']; $usersAchievements = $this->getUsersAchievements($uId);
$retHtml .= "</li>"; $usersNextAchievement = $this->getUsersNextAchievement($uId);
} $retHtml .= "<div style=\"font-size:1.5rem; font-weight:200%\">Nächstes Achievement</div>";
else{ $retHtml .= "<ul class=\"collapsible\"><li>";
$retHtml .= "<li style=\"color:gray\">".$a['name'].": ".$a['description']; $retHtml .= "<div class=\"collapsible-header\" >";
break; if(count($usersAchievements)>0)
} $retHtml .= "&#xfe40; ";
$retHtml .= $usersNextAchievement['name'].": ".$usersNextAchievement['description']."</div>";
if(count($usersAchievements)>0){
$retHtml .= "<ul class=\"collapsible-body\" style=\"color:gray\">";
foreach($this->getUsersAchievements($uId) as $a)
$retHtml .= "<li >&#10003; ".$a['achievementName'].": ".$a['description']."</li>";
$retHtml .= "</ul>";// end body
} }
$retHtml .= "</li></ul>";// end collapsible
// show the current record // show the current record
if($this->canHaveRecords()){
if( validateDate($userData[0]['gebDatum'])){ $retHtml .= "<div style=\"font-size:1.5rem; font-weight:200%\">Aktueller Rekord</div>";
$retHtml.=record::arrayRecord2htmlCard($records[0], $userData[0], $this->getId(), "li");
}
else{
$retHtml.="<div>Rekorde können erst angezeigt werden, wenn das <a href=./setUserData.php>Geburtsdatum korrekt gesetzt</a> wurde!</div>";
}
$retHtml .= "</ul>";
$retHtml .= "</div>";// end card-content
$retHtml .= "<div class=\"card-action\">";
if(!$noForm){
if( canUserGetAchievementToday( $this->getDbConnection(), $uId) or isUserAdmin($this->getDbConnection(), $_SESSION['user']['userId']) ){
$retHtml .= "<form action=\".\" method=\"POST\">";
$retHtml .= "<input name=\"action\" value=\"giveUserAnAchievement\" type=\"hidden\" />";
$retHtml .= "<input name=\"redirectLocation\" value=\"./#achievementList-".$uId."\" type=\"hidden\" />";
$retHtml .= "<input name=\"userId\" value=\"".$uId."\" type=\"hidden\" />";
$retHtml .= "<input name=\"achievementId\" value=\"".$a['id']."\" type=\"hidden\" />";
$retHtml .= "<input name=\"submit\" type=\"submit\" value=\"".$a['name']." geben\">";
// $retHtml .= "<button class=\"btn\" name=\"submit\" type=\"submit\" >Achievement ".$a['name']." geben</button>";
$retHtml .= "</form>";
}
if( validateDate($userData[0]['gebDatum'])){ if( validateDate($userData[0]['gebDatum'])){
$retHtml.=record::arrayRecord2htmlCardAction($records[0], $userData[0], $this->getId(), "li"); $retHtml.=record::arrayRecord2collapsible($records[0], $userData[0], $this->getId(), $noForm);
} }
else{ else{
$retHtml.="<div>Rekorde können erst angezeigt werden, wenn das <a href=./setUserData.php>Geburtsdatum korrekt gesetzt</a> wurde!</div>"; $retHtml.="<div>Rekorde können erst angezeigt werden, wenn das <a href=./setUserData.php>Geburtsdatum korrekt gesetzt</a> wurde!</div>";
} }
} }
$retHtml .= "</div>";
$retHtml .= $this->listUnlockableGroups();
$retHtml .= "</div>";// end card-content
if(!$noForm){
$retHtml .= "<div class=\"card-action\">";
$retHtml .= "<form action=\".\" method=\"POST\">";
$retHtml .= "<input name=\"action\" value=\"giveUserAnAchievement\" type=\"hidden\" />";
$retHtml .= "<input name=\"redirectLocation\" value=\"./#achievementList-".$uId."\" type=\"hidden\" />";
$retHtml .= "<input name=\"userId\" value=\"".$uId."\" type=\"hidden\" />";
$retHtml .= "<input name=\"achievementId\" value=\"".$usersNextAchievement['id']."\" type=\"hidden\" />";
if( canUserGetAchievementToday( $this->getDbConnection(), $uId) or isUserAdmin($this->getDbConnection(), $_SESSION['user']['userId']) ){
$retHtml .= "<button style=\"width:100%\" class=\"btn\" name=\"submit\" type=\"submit\" >Achievement ".$usersNextAchievement['name']." geben</button>";
}
else{
$retHtml .= "<button disabled style=\"width:100%\" class=\"btn\" name=\"submit\" type=\"submit\" >Heute wurde schon ein Achievement erreicht!</button>";
}
$retHtml .= "</form>";
$retHtml .= "</div>";// end card-action
}
$retHtml .= "</div>";// end card $retHtml .= "</div>";// end card
$retHtml .= "</div>";// end col $retHtml .= "</div>";// end col
return $retHtml; return $retHtml;
@@ -214,6 +275,7 @@ return $result;
$html .= "</form>"; $html .= "</form>";
return $html; return $html;
} }
/// create html code for a for to edit an achievementGroup /// create html code for a for to edit an achievementGroup
function htmlEditAchievementGroupForm(){ function htmlEditAchievementGroupForm(){
$html = ""; $html = "";
@@ -259,15 +321,25 @@ return $result;
/// auto generate the achievements for this group /// auto generate the achievements for this group
/// @todo only for empty groups? /// @todo only for empty groups?
function autoAddAchievements($messageTemplate, $from, $to, $step){ function autoAddAchievements($messageTemplate, $from, $to, $step){
if(!empty($this->getAchievements())){ if(count($this->getAchievements()) > 0){
echo("Won't auto-add Achievements to non-empty AchievementGroup!"); echo("Won't auto-add Achievements to non-empty AchievementGroup!");
var_dump($this->getAchievements());
return; return;
} }
$level = 1; $level = 1;
for ($value = (int)$from; $value <= (int)$to; $value+=(int)$step) { if($step > 0){
$name = $this->getName()." ".intToRomanRepresentation($level++); for ($value = (int)$from; $value <= (int)$to; $value+=(int)$step) {
$description = str_replace("%value%", (string)$value, $messageTemplate); $name = $this->getName()." ".intToRomanRepresentation($level++);
$this->addAchievement($name, $description, $level); $description = str_replace("%value%", (string)$value, $messageTemplate);
$this->addAchievement($name, $description, $level);
}
}
else{
for ($value = (int)$from; $value >= (int)$to; $value+=(int)$step) {
$name = $this->getName()." ".intToRomanRepresentation($level++);
$description = str_replace("%value%", (string)$value, $messageTemplate);
$this->addAchievement($name, $description, $level);
}
} }
} }
@@ -283,6 +355,42 @@ return $result;
null null
); );
} }
function usersAchievementList($uId){
$usersAchievements = $this->getUsersAchievements($userId);
$retHtml .= "<ul class=\"collapsible\">";
$retHtml .= "<li>";
$body = "<ul class=\"collapsible-body\">";
foreach($achievements as $a){
if(in_array((int)$a['id'], $usersAchievementIds)){
$body .= "<li >&#10003; ".$a['name'].": ".$a['description'];
$body .= "</li>";
}
else{
$body .= "</ul>";
break;
}
}
$header = "<div class=\"collapsible-header\" style=\"color:gray\">".$a['name'].": ".$a['description']."</div>";
$retHtml .= $header.$body;
$retHtml .= "</li>";
$retHtml .= "</ul>";// end collapsible
}
function listUnlockableGroups(){
$achievementGroups = achievementGroup::getAllAchievementGroups();
$achievements = [];
foreach($this->getAchievements() as $a)
$achievements[(int)$a['id']] = $a;
$retHtml ="<div>";
foreach($achievementGroups as $g){
if(array_key_exists( $g->getUnlockingAchievementId(), $achievements)){
$retHtml .= "<div>Mit Level ".intToRomanRepresentation($achievements[(int)$g->getUnlockingAchievementId()]['level'])." wird ".$g->getName()." freigeschaltet!</div>";
}
}
$retHtml .= "</div>";
return $retHtml;
}
} }
/// convert an int number to roman representation /// convert an int number to roman representation
@@ -302,4 +410,12 @@ function intToRomanRepresentation($number){
} }
return $returnValue; return $returnValue;
} }
/// in an array of arrays collect all values with specific key
function collectKeysValues($array, $key){
$values = [];
foreach($array as $a)
$values[]=$a[$key];
return $values;
}
?> ?>

View File

@@ -7,6 +7,7 @@
<?php <?php
if(isUserAdmin($dbConnection, $_SESSION['user']['userId'])){ if(isUserAdmin($dbConnection, $_SESSION['user']['userId'])){
echo("<li><a href=\"./achievementBuilder.php\">achievementBuilder</a></li>"); echo("<li><a href=\"./achievementBuilder.php\">achievementBuilder</a></li>");
echo("<li><a href=\"./playground.php\">playground</a></li>");
} }
?> ?>
</ul> </ul>

View File

@@ -55,9 +55,11 @@ SQL;
// - a value // - a value
// - an age class // - an age class
public static function getGroupsRecords($groupId, $ageClass=null){ public static function getGroupsRecords($groupId, $ageClass=null){
$query = "SELECT *, `cwsvjudo`.`machs_records`.`id` as `recordId` FROM `cwsvjudo`.`machs_records` "; $query = "SELECT *, `cwsvjudo`.`machs_records`.`id` as `recordId`, `cwsvjudo`.`wkParticipo_Users`.`name` as `userName` FROM `cwsvjudo`.`machs_records` ";
$query.= " JOIN `cwsvjudo`.`wkParticipo_Users` "; $query.= " JOIN `cwsvjudo`.`wkParticipo_Users` ";
$query.= " ON `cwsvjudo`.`machs_records`.`userId` = `cwsvjudo`.`wkParticipo_Users`.`id` "; $query.= " ON `cwsvjudo`.`machs_records`.`userId` = `cwsvjudo`.`wkParticipo_Users`.`id` ";
$query.= " JOIN `cwsvjudo`.`machs_achievementGroups` ";
$query.= " ON `cwsvjudo`.`machs_achievementGroups`.`id` = `cwsvjudo`.`machs_records`.`achievementGroupId` ";
$query.= " WHERE `cwsvjudo`.`machs_records`.`achievementGroupId` = :groupId "; $query.= " WHERE `cwsvjudo`.`machs_records`.`achievementGroupId` = :groupId ";
$params =[ $params =[
'groupId'=>[ 'value'=>$groupId, 'data_type'=>PDO::PARAM_INT ] 'groupId'=>[ 'value'=>$groupId, 'data_type'=>PDO::PARAM_INT ]
@@ -80,8 +82,7 @@ SQL;
} }
public static function arrayRecord2htmlCardAction($r, $u, $gid){ public static function arrayRecord2htmlCardAction($r, $u, $gid){
// $retHtml.= "<div class=\"card-action\">"; $retHtml.= "<a style=\"width:100%;\" class=\"waves-effect waves-light btn modal-trigger\" href=\"#reportRecord-user-".$u['id']."-group-".$gid."\">Rekord melden</a>";
$retHtml.= "<a class=\"waves-effect waves-light btn modal-trigger\" href=\"#reportRecord-user-".$u['id']."-group-".$gid."\">Rekord melden</a>";
$retHtml.= "<div id=\"reportRecord-user-".$u['id']."-group-".$gid."\" class=\"modal\">"; $retHtml.= "<div id=\"reportRecord-user-".$u['id']."-group-".$gid."\" class=\"modal\">";
$retHtml.= "<div class=\"modal-content\">"; $retHtml.= "<div class=\"modal-content\">";
$retHtml.= "Rekorde stellen in jeder Achievementgruppe und Altersklasse die Bestleistung unter allen Judoka dar. Rekorde können unabhänging vom eigenen, aktuellen Achievementstand aufgestellt werden."; $retHtml.= "Rekorde stellen in jeder Achievementgruppe und Altersklasse die Bestleistung unter allen Judoka dar. Rekorde können unabhänging vom eigenen, aktuellen Achievementstand aufgestellt werden.";
@@ -106,7 +107,7 @@ SQL;
$retHtml.= "<input id=\"submit\" style=\"width:100%\" name=\"submit\" type=\"submit\" value=\"Rekord eintragen\">"; $retHtml.= "<input id=\"submit\" style=\"width:100%\" name=\"submit\" type=\"submit\" value=\"Rekord eintragen\">";
} }
else{ else{
$retHtml.= "<input disabled=\"true\" id=\"submit\" style=\"width:100%\" name=\"submit\" type=\"submit\" value=\"Rekord melden\">"; $retHtml.= "<input id=\"submit\" style=\"width:100%\" name=\"submit\" type=\"submit\" value=\"Rekord melden\">";
} }
$retHtml.= "</form>"; $retHtml.= "</form>";
$retHtml.= "</div>"; $retHtml.= "</div>";
@@ -118,27 +119,63 @@ SQL;
return $retHtml; return $retHtml;
} }
/// @param $r record joined with it's holder as associative error /// @param $r record joined with it's holder as associative array
/// @param $u user for whom the record is shown /// @param $u user for whom the record is shown
public static function arrayRecord2htmlCard($r, $u, $gid, $frameTag="div"){ public static function arrayRecord2collapsible($r, $u, $gid, $noForm=true){
$retHtml = "<".$frameTag." class=\"card\">"; $currentRecord = "";
$retHtml.= "<div class=\"card-content\">";
$retHtml.= "<span class=\"card-title\">Zu schlagender Rekord</span>";
if(empty($r)){ if(empty($r)){
$retHtml.= "Noch kein Rekord für die Altersklasse U".record::birthday2ageClass($u['gebDatum']); $currentRecord.= "Noch kein Rekord für die Altersklasse U".record::birthday2ageClass($u['gebDatum']);
} }
else{ else{
$retHtml.= $r['vorname']." ".$r['name']." mit ".$r['value']." in der U".$r['ageClass']; $currentRecord.= $r['vorname']." ".$r['userName']." mit ".$r['value']." in der U".$r['ageClass'];
} }
$retHtml.= "</div>";
$recordRequest = record::arrayRecord2htmlCardAction($r, $u, $gid, $noForm);
$retHtml.= "</".$frameTag.">";
return $retHtml; return <<<COLLAPSIBLE
<ul class="collapsible">
<li>
<div class="collapsible-header">&#xfe40; $currentRecord</div>
<div class="collapsible-body"><span>$recordRequest</span></div>
</li>
</ul>
COLLAPSIBLE;
} }
/// @param $r record joined with it's holder as associative array
/// @param $u user for whom the record is shown
public static function arrayRecord2htmlCard($r, $u, $gid, $noForm=true, $frameTag="div"){
$group = new achievementGroup;
$group->loadAchievementGroupFromDb($gid);
$retHtml.= "";
var_dump($group->canHaveRecords());
if($group->canHaveRecords()){
$retHtml = "<".$frameTag." class=\"card\">";
$retHtml.= "<div class=\"card-content\">";
$retHtml.= "<span class=\"card-title\">Zu schlagender Rekord</span>";
if(empty($r)){
$retHtml.= "Noch kein Rekord für die Altersklasse U".record::birthday2ageClass($u['gebDatum']);
}
else{
// $retHtml.=record::arrayRecord2collapsible($records[0], $userData[0], $this->getId(), $noForm);
$retHtml.=record::arrayRecord2collapsible($r, $u, $gid, $noForm);
//$retHtml.= $r['vorname']." ".$r['name']." mit ".$r['value']." in der U".$r['ageClass'];
}
$retHtml.= "</div>";//end card-content
// if(!$noForm){
// $retHtml.= record::arrayRecord2htmlCardAction($r, $u, $gid, $noForm);
// }
$retHtml.= "</".$frameTag.">";
}
return $retHtml;
}
public static function birthday2ageClass($birthdateString){ public static function birthday2ageClass($birthdateString){
$birthDate = DateTime::createFromFormat("Y-m-d", $birthdateString); $birthDate = DateTime::createFromFormat("Y-m-d", $birthdateString);
$birthYear= (int)$birthDate->format("Y"); $birthYear= (int)$birthDate->format("Y");