implement permissions for Questgroups, Quests and Sidequests
This commit is contained in:
parent
b6ea1fafae
commit
42a7e9303c
8 changed files with 355 additions and 19 deletions
|
|
@ -65,10 +65,28 @@
|
|||
// Get Questgrouphierarchy
|
||||
$questgroupshierarchy = $this->Questgroupshierarchy->getHierarchyById($questgroup['questgroupshierarchy_id']);
|
||||
|
||||
// Get Character
|
||||
$character = $this->Characters->getCharacterForUserAndSeminary($this->Auth->getUserId(), $seminary['id']);
|
||||
|
||||
// Check permission
|
||||
$previousQuestgroup = $this->Questgroups->getPreviousQuestgroup($questgroup['id']);
|
||||
if(!is_null($previousQuestgroup)) {
|
||||
if(!$this->Questgroups->hasCharacterSolvedQuestgroup($previousQuestgroup['id'], $character['id'])) {
|
||||
throw new \nre\exceptions\AccessDeniedException();
|
||||
}
|
||||
}
|
||||
|
||||
// Get child Questgroupshierarchy
|
||||
$childQuestgroupshierarchy = $this->Questgroupshierarchy->getChildQuestgroupshierarchy($questgroupshierarchy['id']);
|
||||
foreach($childQuestgroupshierarchy as &$hierarchy) {
|
||||
foreach($childQuestgroupshierarchy as &$hierarchy)
|
||||
{
|
||||
// Get Questgroups
|
||||
$hierarchy['questgroups'] = $this->Questgroups->getQuestgroupsForHierarchy($hierarchy['id'], $questgroup['id']);
|
||||
|
||||
// Check permission of Questgroups
|
||||
for($i=1; $i<count($hierarchy['questgroups']); $i++) {
|
||||
$hierarchy['questgroups'][$i]['access'] = $this->Questgroups->hasCharacterSolvedQuestgroup($hierarchy['questgroups'][$i-1]['id'], $character['id']);
|
||||
}
|
||||
}
|
||||
|
||||
// Get texts
|
||||
|
|
@ -79,10 +97,15 @@
|
|||
if(count($childQuestgroupshierarchy) == 0)
|
||||
{
|
||||
$quests = $this->Quests->getQuestsForQuestgroup($questgroup['id']);
|
||||
|
||||
// Attach sidequests
|
||||
foreach($quests as &$quest) {
|
||||
$quest['sidequests'] = $this->Quests->getSidequestsForQuest($quest['id']);
|
||||
for($i=0; $i<count($quests); $i++)
|
||||
{
|
||||
// Check permission
|
||||
if($i > 0) {
|
||||
$quests[$i]['access'] = $this->Quests->hasCharacterSolvedQuest($quests[$i-1]['id'], $character['id']);
|
||||
}
|
||||
|
||||
// Attach sidequests
|
||||
$quests[$i]['sidequests'] = $this->Quests->getSidequestsForQuest($quests[$i]['id']);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public $models = array('seminaries', 'questgroups', 'quests', 'questtexts', 'media', 'questtypes');
|
||||
public $models = array('seminaries', 'questgroups', 'quests', 'questtexts', 'media', 'questtypes', 'questgroupshierarchy');
|
||||
/**
|
||||
* User permissions
|
||||
*
|
||||
|
|
@ -68,6 +68,35 @@
|
|||
// Get Quest
|
||||
$quest = $this->Quests->getQuestByUrl($seminary['id'], $questgroup['id'], $questUrl);
|
||||
|
||||
// Get Character
|
||||
$character = $this->Characters->getCharacterForUserAndSeminary($this->Auth->getUserId(), $seminary['id']);
|
||||
|
||||
// Check permissions
|
||||
$previousQuests = $this->Quests->getPreviousQuests($quest['id']);
|
||||
if(count($previousQuests) == 0)
|
||||
{
|
||||
// Previous Questgroup
|
||||
$previousQuestgroup = $this->Questgroups->getPreviousQuestgroup($questgroup['id']);
|
||||
if(!$this->Questgroups->hasCharacterSolvedQuestgroup($previousQuestgroup['id'], $character['id'])) {
|
||||
throw new \nre\exceptions\AccessDeniedException();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Previous Quests
|
||||
$solved = false;
|
||||
foreach($previousQuests as &$previousQuest)
|
||||
{
|
||||
if($this->Quests->hasCharacterSolvedQuest($previousQuest['id'], $character['id'])) {
|
||||
$solved = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!$solved) {
|
||||
throw new \nre\exceptions\AccessDeniedException();
|
||||
}
|
||||
}
|
||||
|
||||
// Get Questtext
|
||||
$questtext = null;
|
||||
if(is_null($questtexttypeUrl)) {
|
||||
|
|
@ -111,7 +140,7 @@
|
|||
|
||||
// Task
|
||||
$task = null;
|
||||
if($questtext['type'] == 'Prolog')
|
||||
if($questtexttypeUrl == 'Prolog')
|
||||
{
|
||||
// Questtype
|
||||
$questtype = $this->Questtypes->getQuesttypeById($quest['questtype_id']);
|
||||
|
|
@ -120,10 +149,20 @@
|
|||
$task = $this->runAndRenderTask($questtype['classname']);
|
||||
}
|
||||
|
||||
// Next Quest
|
||||
// Next Quest/Questgroup
|
||||
$nextQuests = null;
|
||||
if($questtexttypeUrl == 'Epilog') {
|
||||
$nextQuestgroup = null;
|
||||
if($questtexttypeUrl == 'Epilog')
|
||||
{
|
||||
// Next Quest
|
||||
$nextQuests = $this->Quests->getNextQuests($quest['id']);
|
||||
|
||||
// Next Questgroup
|
||||
if(empty($nextQuests))
|
||||
{
|
||||
$nextQuestgroup = $this->Questgroups->getNextQuestgroup($questgroup['id']);
|
||||
$nextQuestgroup['hierarchy'] = $this->Questgroupshierarchy->getHierarchyById($nextQuestgroup['questgroupshierarchy_id']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -135,6 +174,7 @@
|
|||
$this->set('queststatus', $questStatus);
|
||||
$this->set('queststatustext', $questStatusText);
|
||||
$this->set('nextquests', $nextQuests);
|
||||
$this->set('nextquestgroup', $nextQuestgroup);
|
||||
$this->set('task', $task);
|
||||
$this->set('media', $questmedia);
|
||||
}
|
||||
|
|
@ -167,6 +207,38 @@
|
|||
// Get Sidequest
|
||||
$sidequest = $this->Quests->getSidequestByUrl($seminary['id'], $questgroup['id'], $quest['id'], $sidequestUrl);
|
||||
|
||||
// Get Character
|
||||
$character = $this->Characters->getCharacterForUserAndSeminary($this->Auth->getUserId(), $seminary['id']);
|
||||
|
||||
// Check permission
|
||||
$previousQuests = $this->Quests->getPreviousQuests($quest['id']);
|
||||
if(count($previousQuests) == 0)
|
||||
{
|
||||
// Previous Questgroup
|
||||
$previousQuestgroup = $this->Questgroups->getPreviousQuestgroup($questgroup['id']);
|
||||
if(!$this->Questgroups->hasCharacterSolvedQuestgroup($previousQuestgroup['id'], $character['id'])) {
|
||||
throw new \nre\exceptions\AccessDeniedException();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Previous Quests
|
||||
if(count($previousQuests) > 0)
|
||||
{
|
||||
$solved = false;
|
||||
foreach($previousQuests as &$previousQuest)
|
||||
{
|
||||
if($this->Quests->hasCharacterSolvedQuest($previousQuest['id'], $character['id'])) {
|
||||
$solved = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!$solved) {
|
||||
throw new \nre\exceptions\AccessDeniedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get Questtext
|
||||
$questtext = $this->Questtexts->getQuesttextForSidequest($sidequest['id']);
|
||||
|
||||
|
|
@ -215,7 +287,7 @@
|
|||
|
||||
// Task
|
||||
$task = null;
|
||||
if(!is_null($sidequesttext) && $sidequesttext['type'] == 'Prolog')
|
||||
if($sidequesttexttypeUrl == 'Prolog')
|
||||
{
|
||||
// Questtype
|
||||
$questtype = $this->Questtypes->getQuesttypeById($sidequest['questtype_id']);
|
||||
|
|
|
|||
|
|
@ -90,10 +90,20 @@
|
|||
// Created user
|
||||
$seminary['creator'] = $this->Users->getUserById($seminary['created_user_id']);
|
||||
|
||||
// Get Character
|
||||
$character = $this->Characters->getCharacterForUserAndSeminary($this->Auth->getUserId(), $seminary['id']);
|
||||
|
||||
// Questgrouphierarchy and Questgroups
|
||||
$questgroupshierarchy = $this->Questgroupshierarchy->getHierarchyForSeminary($seminary['id']);
|
||||
foreach($questgroupshierarchy as &$hierarchy) {
|
||||
foreach($questgroupshierarchy as &$hierarchy)
|
||||
{
|
||||
// Get Questgroups
|
||||
$hierarchy['questgroups'] = $this->Questgroups->getQuestgroupsForHierarchy($hierarchy['id']);
|
||||
|
||||
// Check permission of Questgroups
|
||||
for($i=1; $i<count($hierarchy['questgroups']); $i++) {
|
||||
$hierarchy['questgroups'][$i]['access'] = $this->Questgroups->hasCharacterSolvedQuestgroup($hierarchy['questgroups'][$i-1]['id'], $character['id']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,12 @@
|
|||
*/
|
||||
class QuestgroupsModel extends \hhu\z\Model
|
||||
{
|
||||
/**
|
||||
* Required models
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $models = array('questgroupshierarchy', 'quests');
|
||||
|
||||
|
||||
|
||||
|
|
@ -138,6 +144,164 @@
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the next Questgroup.
|
||||
*
|
||||
* Determine the next Questgroup. If there is no next Questgroup
|
||||
* on the same level as the given Quest then the followed-up
|
||||
* Questgroup from a higher hierarchy level is returned.
|
||||
*
|
||||
* @param int $questgroupId ID of Questgroup to get next Questgroup of
|
||||
* @return array Questgroup data
|
||||
*/
|
||||
public function getNextQuestgroup($questgroupId)
|
||||
{
|
||||
$currentQuestgroup = $this->getQuestgroupById($questgroupId);
|
||||
$nextQuestgroup = $this->_getNextQuestgroup($currentQuestgroup['parent_questgroup_id'], $currentQuestgroup['pos']);
|
||||
while(is_null($nextQuestgroup) && !is_null($currentQuestgroup['parent_questgroup_id']))
|
||||
{
|
||||
$currentQuestgroup = $this->getQuestgroupById($currentQuestgroup['parent_questgroup_id']);
|
||||
$nextQuestgroup = $this->_getNextQuestgroup($currentQuestgroup['parent_questgroup_id'], $currentQuestgroup['pos']);
|
||||
}
|
||||
|
||||
|
||||
return $nextQuestgroup;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the previous Questgroup.
|
||||
*
|
||||
* Determine the previous Questgroup. If there is no previous
|
||||
* Questgroup on the same level as the given Quest then the
|
||||
* followed-up Questgroup from a higher hierarchy level is
|
||||
* returned.
|
||||
*
|
||||
* @param int $questgroupId ID of Questgroup to get previous Questgroup of
|
||||
* @return array Questgroup data
|
||||
*/
|
||||
public function getPreviousQuestgroup($questgroupId)
|
||||
{
|
||||
$currentQuestgroup = $this->getQuestgroupById($questgroupId);
|
||||
$previousQuestgroup = $this->_getPreviousQuestgroup($currentQuestgroup['parent_questgroup_id'], $currentQuestgroup['pos']);
|
||||
while(is_null($previousQuestgroup) && !is_null($currentQuestgroup['parent_questgroup_id']))
|
||||
{
|
||||
$currentQuestgroup = $this->getQuestgroupById($currentQuestgroup['parent_questgroup_id']);
|
||||
$previousQuestgroup = $this->_getPreviousQuestgroup($currentQuestgroup['parent_questgroup_id'], $currentQuestgroup['pos']);
|
||||
}
|
||||
|
||||
|
||||
return $previousQuestgroup;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if the given Character has solved the Quests form
|
||||
* this Questgroup.
|
||||
*
|
||||
* @param int $questgroupId ID of Questgroup to check
|
||||
* @param int $characterId ID of Character to check
|
||||
* @result boolean Whether Character has solved the Questgroup or not
|
||||
*/
|
||||
public function hasCharacterSolvedQuestgroup($questgroupId, $characterId)
|
||||
{
|
||||
$currentQuestgroup = $this->getQuestgroupById($questgroupId);
|
||||
$childQuestgroupshierarchy = $this->Questgroupshierarchy->getChildQuestgroupshierarchy($currentQuestgroup['questgroupshierarchy_id']);
|
||||
$lastChildQuestgroupshierarchy = array_pop($childQuestgroupshierarchy);
|
||||
while(!is_null($lastChildQuestgroupshierarchy))
|
||||
{
|
||||
$questgroups = $this->getQuestgroupsForHierarchy($lastChildQuestgroupshierarchy['id'], $currentQuestgroup['id']);
|
||||
$currentQuestgroup = array_pop($questgroups);
|
||||
$childQuestgroupshierarchy = $this->Questgroupshierarchy->getChildQuestgroupshierarchy($currentQuestgroup['questgroupshierarchy_id']);
|
||||
$lastChildQuestgroupshierarchy = array_pop($childQuestgroupshierarchy);
|
||||
}
|
||||
|
||||
$quests = $this->Quests->getQuestsForQuestgroup($currentQuestgroup['id']);
|
||||
$lastQuest = array_pop($quests);
|
||||
|
||||
|
||||
return $this->Quests->hasCharacterSolvedQuest($lastQuest['id'], $characterId);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the next (direct) Questgroup.
|
||||
*
|
||||
* @param int $parentQuestgroupId ID of parent Questgroup to get next Questgroup of
|
||||
* @param int $questgroupPos Position of Questgroup to get next Questgroup of
|
||||
* @return array Data of next Questgroup or NULL
|
||||
*/
|
||||
private function _getNextQuestgroup($parentQuestgroupId, $questgroupPos)
|
||||
{
|
||||
if(!is_null($parentQuestgroupId))
|
||||
{
|
||||
$data = $this->db->query(
|
||||
'SELECT * '.
|
||||
'FROM questgroups '.
|
||||
'WHERE parent_questgroup_id = ? AND pos = ? + 1',
|
||||
'ii',
|
||||
$parentQuestgroupId, $questgroupPos
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$data = $this->db->query(
|
||||
'SELECT * '.
|
||||
'FROM questgroups '.
|
||||
'WHERE parent_questgroup_id IS NULL AND pos = ? + 1',
|
||||
'i',
|
||||
$questgroupPos
|
||||
);
|
||||
}
|
||||
if(empty($data)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
return $data[0];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the previous (direct) Questgroup.
|
||||
*
|
||||
* @param int $parentQuestgroupId ID of parent Questgroup to get previous Questgroup of
|
||||
* @param int $questgroupPos Position of Questgroup to get previous Questgroup of
|
||||
* @return array Data of previous Questgroup or NULL
|
||||
*/
|
||||
private function _getPreviousQuestgroup($parentQuestgroupId, $questgroupPos)
|
||||
{
|
||||
if(!is_null($parentQuestgroupId))
|
||||
{
|
||||
$data = $this->db->query(
|
||||
'SELECT * '.
|
||||
'FROM questgroups '.
|
||||
'WHERE parent_questgroup_id = ? AND pos = ? - 1',
|
||||
'ii',
|
||||
$parentQuestgroupId, $questgroupPos
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$data = $this->db->query(
|
||||
'SELECT * '.
|
||||
'FROM questgroups '.
|
||||
'WHERE parent_questgroup_id IS NULL AND pos = ? - 1',
|
||||
'i',
|
||||
$questgroupPos
|
||||
);
|
||||
}
|
||||
if(empty($data)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
return $data[0];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@
|
|||
$seminaryId
|
||||
);
|
||||
if(empty($data)) {
|
||||
throw new \nre\exceptions\IdNotFoundException();
|
||||
throw new \nre\exceptions\IdNotFoundException($sidequestUrl);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -175,6 +175,27 @@
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get Quests that the given Quests follows-up to.
|
||||
*
|
||||
* @param int $questId ID of Quest to get previous Quests of
|
||||
* @return array Quests data
|
||||
*/
|
||||
public function getPreviousQuests($questId)
|
||||
{
|
||||
return $this->db->query(
|
||||
'SELECT quests.id, quests.title, quests.url, questgroups.title AS questgroup_title, questgroups.url AS questgroup_url '.
|
||||
'FROM quests_previousquests '.
|
||||
'LEFT JOIN quests ON quests.id = quests_previousquests.previous_quest_id '.
|
||||
'LEFT JOIN questgroups ON questgroups.id = quests.questgroup_id '.
|
||||
'LEFT JOIN questgroupshierarchy ON questgroupshierarchy.id = questgroups.questgroupshierarchy_id '.
|
||||
'WHERE quests_previousquests.quest_id = ?',
|
||||
'i',
|
||||
$questId
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Mark a Quest as solved for a Character.
|
||||
*
|
||||
|
|
@ -216,6 +237,29 @@
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if the given Character has solved the given Quest.
|
||||
*
|
||||
* @param int $questId ID of Quest to check
|
||||
* @param int $characterId ID of Character to check
|
||||
* @result boolean Whether Character has solved the Quest or not
|
||||
*/
|
||||
public function hasCharacterSolvedQuest($questId, $characterId)
|
||||
{
|
||||
$count = $this->db->query(
|
||||
'SELECT count(id) AS c '.
|
||||
'FROM quests_characters '.
|
||||
'WHERE quest_id = ? AND character_id = ? AND status = 0',
|
||||
'ii',
|
||||
$questId,
|
||||
$characterId
|
||||
);
|
||||
|
||||
|
||||
return (!empty($count) && intval($count[0]['c']) > 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<h1><?=_('Seminaries')?></h2>
|
||||
<h2><?=$seminary['title']?></h3>
|
||||
<h1><?=_('Seminaries')?></h1>
|
||||
<h2><?=$seminary['title']?></h2>
|
||||
|
||||
<?=$questgroupshierarchypath?>
|
||||
<?=$questgroupspicture?>
|
||||
|
|
@ -14,7 +14,14 @@
|
|||
<h3><?=$hierarchy['title_plural']?></h3>
|
||||
<ul>
|
||||
<?php foreach($hierarchy['questgroups'] as &$group) : ?>
|
||||
<li><?=$hierarchy['title_singular']?> <?=$group['pos']?>: <a href="<?=$linker->link(array('questgroups','questgroup',$seminary['url'],$group['url']))?>"><?=$group['title']?></a></li>
|
||||
<li>
|
||||
<?=$hierarchy['title_singular']?> <?=$group['pos']?>:
|
||||
<?php if(!array_key_exists('access', $group) || $group['access']) : ?>
|
||||
<a href="<?=$linker->link(array('questgroups','questgroup',$seminary['url'],$group['url']))?>"><?=$group['title']?></a>
|
||||
<?php else : ?>
|
||||
<?=_('locked')?>
|
||||
<?php endif ?>
|
||||
</li>
|
||||
<?php endforeach?>
|
||||
</ul>
|
||||
<?php endif ?>
|
||||
|
|
@ -25,6 +32,7 @@
|
|||
<ul>
|
||||
<?php foreach($quests as &$quest) : ?>
|
||||
<li>
|
||||
<?php if(!array_key_exists('access', $quest) || $quest['access']) : ?>
|
||||
<a href="<?=$linker->link(array('quests','quest',$seminary['url'],$questgroup['url'],$quest['url']))?>"><?=$quest['title']?></a>
|
||||
<br />
|
||||
<?=_('containing optional Quests')?>:
|
||||
|
|
@ -35,6 +43,9 @@
|
|||
<?php endforeach ?>
|
||||
</ul>
|
||||
<?php endif ?>
|
||||
<?php else : ?>
|
||||
<?=_('Locked')?>
|
||||
<?php endif ?>
|
||||
</li>
|
||||
<?php endforeach ?>
|
||||
</ul>
|
||||
|
|
|
|||
|
|
@ -48,14 +48,20 @@
|
|||
</section>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if(!is_null($nextquests)) : ?>
|
||||
<?php if(!is_null($nextquests) || !is_null($nextquestgroup)) : ?>
|
||||
<section>
|
||||
<h1><?=_('Next Quests')?></h1>
|
||||
<h1><?=_('Go on') ?></h1>
|
||||
<?php if(count($nextquests) > 0) : ?>
|
||||
<ul>
|
||||
<?php foreach($nextquests as &$nextquest) : ?>
|
||||
<li><a href="<?=$linker->link(array($nextquest['questgroup_url'],$nextquest['url']),3)?>"><?=$nextquest['title']?></a></li>
|
||||
<li><?=_('Quest')?>: <a href="<?=$linker->link(array($nextquest['questgroup_url'],$nextquest['url']),3)?>"><?=$nextquest['title']?></a></li>
|
||||
<?php endforeach ?>
|
||||
</ul>
|
||||
<?php elseif(!is_null($nextquestgroup)) : ?>
|
||||
<a href="<?=$linker->link(array('questgroups','questgroup',$seminary['url'],$nextquestgroup['url']))?>"><?=$nextquestgroup['hierarchy']['title_singular']?> <?=$nextquestgroup['pos']?>: <?=$nextquestgroup['title']?></a>
|
||||
<?php else : ?>
|
||||
Spiel vorbei
|
||||
<?php endif ?>
|
||||
</section>
|
||||
<?php endif ?>
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,13 @@
|
|||
<h3><?=$hierarchy['title_plural']?></h3>
|
||||
<ul>
|
||||
<?php foreach($hierarchy['questgroups'] as &$group) : ?>
|
||||
<li><?=$hierarchy['title_singular']?> <?=$group['pos']?>: <a href="<?=$linker->link(array('questgroups','questgroup',$seminary['url'],$group['url']))?>"><?=$group['title']?></a></li>
|
||||
<li>
|
||||
<?=$hierarchy['title_singular']?> <?=$group['pos']?>:
|
||||
<?php if(!array_key_exists('access', $group) || $group['access']) : ?>
|
||||
<a href="<?=$linker->link(array('questgroups','questgroup',$seminary['url'],$group['url']))?>"><?=$group['title']?></a></li>
|
||||
<?php else : ?>
|
||||
<?=_('locked')?>
|
||||
<?php endif ?>
|
||||
<?php endforeach?>
|
||||
</ul>
|
||||
<?php endforeach ?>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue