From ae9b69b68c2694f688c9b7f1505252628811c98f Mon Sep 17 00:00:00 2001 From: oliver Date: Fri, 30 Oct 2015 22:45:05 +0100 Subject: [PATCH] add additional pages and handle introduction page as ?system? page --- agents/intermediate/PagesAgent.inc | 38 ++++ configs/AppConfig.inc | 6 +- controllers/IntroductionController.inc | 58 ++++++ controllers/MenuController.inc | 12 ++ controllers/PagesController.inc | 237 +++++++++++++++++++++++++ db/create.sql | 29 ++- models/PagesModel.inc | 232 ++++++++++++++++++++++++ views/html/introduction/edit.tpl | 18 ++ views/html/introduction/index.tpl | 60 +++---- views/html/menu/index.tpl | 18 +- views/html/pages/create.tpl | 47 +++++ views/html/pages/delete.tpl | 13 ++ views/html/pages/edit.tpl | 56 ++++++ views/html/pages/index.tpl | 20 +++ views/html/pages/page.tpl | 12 ++ 15 files changed, 812 insertions(+), 44 deletions(-) create mode 100644 agents/intermediate/PagesAgent.inc create mode 100644 controllers/PagesController.inc create mode 100644 models/PagesModel.inc create mode 100644 views/html/introduction/edit.tpl create mode 100644 views/html/pages/create.tpl create mode 100644 views/html/pages/delete.tpl create mode 100644 views/html/pages/edit.tpl create mode 100644 views/html/pages/index.tpl create mode 100644 views/html/pages/page.tpl diff --git a/agents/intermediate/PagesAgent.inc b/agents/intermediate/PagesAgent.inc new file mode 100644 index 00000000..3af3036f --- /dev/null +++ b/agents/intermediate/PagesAgent.inc @@ -0,0 +1,38 @@ + + * @copyright 2014 Heinrich-Heine-Universität Düsseldorf + * @license http://www.gnu.org/licenses/gpl.html + * @link https://bitbucket.org/coderkun/the-legend-of-z + */ + + namespace hhu\z\agents\intermediate; + + + /** + * Agent to manage additional pages. + * + * @author Oliver Hanraths + */ + class PagesAgent extends \nre\agents\IntermediateAgent + { + + + + + /** + * Action: index. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function index(\nre\core\Request $request, \nre\core\Response $response) + { + } + + } + +?> diff --git a/configs/AppConfig.inc b/configs/AppConfig.inc index 21ca643a..910f2d7c 100644 --- a/configs/AppConfig.inc +++ b/configs/AppConfig.inc @@ -313,6 +313,8 @@ array('^library/([^/]+)/([^/]+)/(edit|delete|manage)/?$', 'library/$3/$1/$2', true), array('^map/([^/]+)/?$', 'map/index/$1', true), array('^map/([^/]+)/(edit)/?$', 'map/$2/$1', true), + array('^pages/([^/]+)/(edit|delete)$', 'pages/$2/$1', true), + array('^pages/(?!(create|edit|delete))/?', 'pages/page/$1', true), array('^media/(.*)$', 'media/$1?layout=binary', false), array('^uploads/(.*)$', 'uploads/$1?layout=binary', false) ); @@ -364,7 +366,9 @@ array('^library/topic/([^/]+)/([^/]+)/?$', 'library/$1/$2', true), array('^library/(edit|delete|manage)/([^/]+)/([^/]+)/?$', 'library/$2/$3/$1', true), array('^map/index/(.*)$', 'map/$1', true), - array('^map/(edit)/(.*)$', 'map/$2/$1', true) + array('^map/(edit)/(.*)$', 'map/$2/$1', true), + array('^pages/page/(.*+)$', 'pages/$1', true), + array('^pages/(edit|delete)/([^/]+)$', 'pages/$2/$1', true) ); diff --git a/controllers/IntroductionController.inc b/controllers/IntroductionController.inc index 97d34978..106edb60 100644 --- a/controllers/IntroductionController.inc +++ b/controllers/IntroductionController.inc @@ -19,6 +19,12 @@ */ class IntroductionController extends \hhu\z\controllers\IntermediateController { + /** + * Required models + * + * @var array + */ + public $models = array('pages'); @@ -28,8 +34,60 @@ */ public function index() { + // Get introduction text + $page = $this->Pages->getPageByUrl(\hhu\z\models\PagesModel::PAGEURL_INTRODUCTION); + $text = (!is_null($page)) ? $page['text'] : null; + + // Pass data to view $this->set('userId', $this->Auth->getUserId()); + $this->set('text', $text); + } + + + /** + * Action: edit. + */ + public function edit() + { + // Get page + $page = $this->Pages->getPageByUrl(\hhu\z\models\PagesModel::PAGEURL_INTRODUCTION); + + // Values + $text = (!is_null($page)) ? $page['text'] : null; + + // Check request method + if($this->request->getRequestMethod() == 'POST') + { + if(!is_null($this->request->getPostParam('edit'))) + { + // Get values + $text = $this->request->getPostParam('text'); + + // Create page if necessary + if(is_null($page)) { + $pageId = $this->Pages->createPage( + $this->Auth->getUserId(), + \hhu\z\models\PagesModel::PAGEURL_INTRODUCTION + ); + $page = $this->Pages->getPageById($pageId); + } + + // Save text + $this->Pages->editPage( + $page['id'], + $page['title'], + $text + ); + } + + // Redirect + $this->redirect($this->linker->link(array('index'), 1)); + } + + + // Pass data to view + $this->set('text', $text); } } diff --git a/controllers/MenuController.inc b/controllers/MenuController.inc index 353d5fc6..26854b16 100644 --- a/controllers/MenuController.inc +++ b/controllers/MenuController.inc @@ -19,6 +19,12 @@ */ class MenuController extends \hhu\z\Controller { + /** + * Required models + * + * @var array + */ + public $models = array('pages'); @@ -45,6 +51,12 @@ */ public function index() { + // Get additional pages + $pages = $this->Pages->getPages(); + + + // Pass data to view + $this->set('pages', $pages); } } diff --git a/controllers/PagesController.inc b/controllers/PagesController.inc new file mode 100644 index 00000000..eb6b2cdd --- /dev/null +++ b/controllers/PagesController.inc @@ -0,0 +1,237 @@ + + * @copyright 2014 Heinrich-Heine-Universität Düsseldorf + * @license http://www.gnu.org/licenses/gpl.html + * @link https://bitbucket.org/coderkun/the-legend-of-z + */ + + namespace hhu\z\controllers; + + + /** + * Controller of the PagesAgent to manage additional pages. + * + * @author Oliver Hanraths + */ + class PagesController extends \hhu\z\controllers\IntermediateController + { + /** + * Required components + * + * @var array + */ + public $components = array('validation'); + /** + * Required models + * + * @var array + */ + public $models = array('pages'); + /** + * User permissions + * + * @var array + */ + public $permissions = array( + 'index' => array('admin') + /* + 'create' => array('admin', 'moderator'), + 'edit' => array('admin', 'moderator'), + 'delete' => array('admin') + */ + ); + + + + + /** + * Action: index. + * + * List all registered pages. + */ + public function index() + { + // Get registered pages + $pages = $this->Pages->getPages(); + + + // Pass data to view + $this->set('pages', $pages); + } + + + /** + * Action: page. + * + * Show a page. + * + * @throws \nre\exceptions\IdNotFoundException + * @param string $pageUrl URL of page to show + */ + public function page($pageUrl) + { + // Get page + $page = $this->Pages->getPageByUrl($pageUrl); + + + // Pass data to view + $this->set('page', $page); + } + + + /** + * Action: create. + * + * Create a new page. + */ + public function create() + { + // Values + $title = ''; + $fields = array('title'); + $validation = array(); + + // Create new page + if($this->request->getRequestMethod() == 'POST' && !is_null($this->request->getPostParam('create'))) + { + // Get params and validate them + $validation = $this->Validation->validateParams($this->request->getPostParams(), $fields); + $title = $this->request->getPostParam('title'); + if($this->Pages->titleExists($title)) { + $validation = $this->Validation->addValidationResult($validation, 'title', 'exist', true); + } + + // Create + if($validation === true) + { + $pageId = $this->Pages->createPage( + $this->Auth->getUserId(), + $title + ); + + // Redirect to page + $page = $this->Pages->getPageById($pageId); + $this->redirect($this->linker->link(array('page', $page['url']), 1)); + } + } + + // Get validation settings + $validationSettings = array(); + foreach($fields as &$field) { + $validationSettings[$field] = \nre\configs\AppConfig::$validation[$field]; + } + + + // Pass data to view + $this->set('title', $title); + $this->set('validation', $validation); + $this->set('validationSettings', $validationSettings); + } + + + /** + * Action: edit. + * + * Edit page. + * + * @throws \nre\exceptions\IdNotFoundException + * @param string $pageUrl URL of page to edit + */ + public function edit($pageUrl) + { + // Get page + $page = $this->Pages->getPageByUrl($pageUrl); + + // Values + $title = $page['title']; + $text = $page['text']; + $fields = array('title'); + $validation = array(); + + // Edit content + if($this->request->getRequestMethod() == 'POST' && !is_null($this->request->getPostParam('save'))) + { + // Get params and validate them + $validation = $this->Validation->validateParams($this->request->getPostParams(), $fields); + $title = $this->request->getPostParam('title'); + if($this->Pages->titleExists($title, $page['id'])) { + $validation = $this->Validation->addValidationResult($validation, 'title', 'exist', true); + } + $text = $this->request->getPostParam('text'); + var_dump($text); + + // Edit + if($validation === true) + { + $this->Pages->editPage( + $page['id'], + $title, + $text + ); + + // Redirect to entry + $this->redirect($this->linker->link(array('page', $page['url']), 1)); + } + } + + // Get validation settings + $validationSettings = array(); + foreach($fields as &$field) { + $validationSettings[$field] = \nre\configs\AppConfig::$validation[$field]; + } + + + // Pass data to view + $this->set('page', $page); + $this->set('title', $title); + $this->set('text', $text); + $this->set('validation', $validation); + $this->set('validationSettings', $validationSettings); + } + + + /** + * Action: delete. + * + * Delete a page. + * + * @throws \nre\exceptions\IdNotFoundException + * @param string $pageUrl URL of page to delete + */ + public function delete($pageUrl) + { + // Get page + $page = $this->Pages->getPageByUrl($pageUrl); + + // Check request method + if($this->request->getRequestMethod() == 'POST') + { + // Check confirmation + if(!is_null($this->request->getPostParam('delete'))) + { + // Delete page + $this->Pages->deletePage($page); + + // Redirect to overview + $this->redirect($this->linker->link(null, 1)); + } + + // Redirect to entry + $this->redirect($this->linker->link(array('page', $page['url']), 1)); + } + + + // Set titile + $this->addTitleLocalized('Delete page'); + + // Show confirmation + $this->set('page', $page); + } + + } + +?> diff --git a/db/create.sql b/db/create.sql index fd9f11ec..a1fe59a8 100644 --- a/db/create.sql +++ b/db/create.sql @@ -1,8 +1,8 @@ --- MySQL dump 10.15 Distrib 10.0.21-MariaDB, for Linux (x86_64) +-- MySQL dump 10.15 Distrib 10.0.22-MariaDB, for Linux (x86_64) -- -- Host: localhost Database: z -- ------------------------------------------------------ --- Server version 10.0.21-MariaDB-log +-- Server version 10.0.22-MariaDB-log /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; @@ -805,6 +805,29 @@ CREATE TABLE `media` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; +-- +-- Table structure for table `pages` +-- + +DROP TABLE IF EXISTS `pages`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `pages` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `created_user_id` int(11) NOT NULL, + `pos` int(11) NOT NULL, + `title` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL, + `url` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL, + `text` text COLLATE utf8mb4_unicode_ci NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `url` (`url`), + UNIQUE KEY `pos` (`pos`), + KEY `created_user_id` (`created_user_id`), + CONSTRAINT `pages_ibfk_1` FOREIGN KEY (`created_user_id`) REFERENCES `users` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + -- -- Table structure for table `questgroups` -- @@ -2294,4 +2317,4 @@ DELIMITER ; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2015-08-21 9:38:24 +-- Dump completed on 2015-10-30 22:27:53 diff --git a/models/PagesModel.inc b/models/PagesModel.inc new file mode 100644 index 00000000..e1453748 --- /dev/null +++ b/models/PagesModel.inc @@ -0,0 +1,232 @@ + + * @copyright 2014 Heinrich-Heine-Universität Düsseldorf + * @license http://www.gnu.org/licenses/gpl.html + * @link https://bitbucket.org/coderkun/the-legend-of-z + */ + + namespace hhu\z\models; + + + /** + * Model to interact with Pages-table. + * + * @author Oliver Hanraths + */ + class PagesModel extends \hhu\z\Model + { + /** + * URL for system page: Introduction + */ + const PAGEURL_INTRODUCTION = 'introduction'; + + + + + /** + * Construct a new PagesModel. + */ + public function __construct() + { + parent::__construct(); + } + + + + + /** + * Get all registered pages (without system pages). + * + * @return array List of registered pages + */ + public function getPages() { + // Get pages + $data = $this->db->query( + 'SELECT id, pos, url, title, text '. + 'FROM pages '. + 'ORDER BY pos' + ); + + // Remove system pages + $pages = array(); + foreach($data as $page) { + if($page['url'] != self::PAGEURL_INTRODUCTION) { + $pages[] = $page; + } + } + + + // Return pages + return $pages; + } + + + /** + * Get a page by its ID. + * + * @param string $pageid ID of page to get + * @return array Page data + */ + public function getPageById($pageId) + { + $data = $this->db->query( + 'SELECT id, url, title, pos, text '. + 'FROM pages '. + 'WHERE id = ?', + 'i', + $pageId + ); + if(!empty($data)) { + return $data[0]; + } + + + return null; + } + + + /** + * Get a page by its URL. + * + * @param string $pageUrl URL of page to get + * @return array Page data + */ + public function getPageByUrl($pageUrl) + { + $data = $this->db->query( + 'SELECT id, url, title, pos, text '. + 'FROM pages '. + 'WHERE url = ?', + 's', + $pageUrl + ); + if(!empty($data)) { + return $data[0]; + } + + + return null; + } + + + /** + * Check if a page title already exists. + * + * @param string $title Page title to check + * @param int $pageId Do not check this ID (for editing) + * @return boolean Whether title exists or not + */ + public function titleExists($title, $pageId=null) + { + $data = $this->db->query( + 'SELECT id '. + 'FROM pages '. + 'WHERE title = ? OR url = ?', + 'ss', + $title, + self::createLinkParam($title) + ); + + + return (!empty($data) && (is_null($pageId) || $pageId != $data[0]['id'])); + } + + + /** + * Create a new page. + * + * @param int $userId ID of creating user + * @param string $title Title of page to create + * @return int ID of the newly created page + */ + public function createPage($userId, $title) + { + // Create content + $this->db->query( + 'INSERT INTO pages '. + '(created_user_id, pos, title, url) '. + 'SELECT ?, IFNULL(MAX(pos),0)+1, ?, ? '. + 'FROM pages', + 'iss', + $userId, + $title, + self::createLinkParam($title) + ); + + + return $this->db->getInsertId(); + } + + + /** + * Edit data of a page. + * + * @param int $pageId ID of page to edit + * @param string $title New page title + * @param string $text New page text + */ + public function editPage($pageId, $title, $text) + { + $this->db->query( + 'UPDATE pages '. + 'SET title = ?, url = ?, text = ? '. + 'WHERE id = ?', + 'sssi', + $title, + self::createLinkParam($title), + $text, + $pageId + ); + } + + + /** + * Delete page. + * + * @param array $page Page to delete + */ + public function deletePage($page) + { + $this->db->setAutocommit(false); + try { + // Delete page + $this->db->query('DELETE FROM pages WHERE id = ?', 'i', $page['id']); + + // Correct position + $this->db->query( + 'UPDATE pages '. + 'SET pos = pos-1 '. + 'WHERE pos > ?', + 'i', + $page['pos'] + ); + } + catch(\nre\exceptions\DatamodelException $e) { + $this->db->rollback(); + $this->db->setAutocommit(true); + throw $e; + } + $this->db->setAutocommit(true); + } + + + + + /* + * Mask parameters to be used in an URL. + * + * @param string $param1 First parameter + * @return string Masked parameters as string + */ + private static function createLinkParam($param) + { + return \nre\core\Linker::createLinkParam(mb_strtolower($param)); + } + + } + +?> diff --git a/views/html/introduction/edit.tpl b/views/html/introduction/edit.tpl new file mode 100644 index 00000000..3afc1b97 --- /dev/null +++ b/views/html/introduction/edit.tpl @@ -0,0 +1,18 @@ +
+ +
+ +

+
+
+ + +
+ + +
+ diff --git a/views/html/introduction/index.tpl b/views/html/introduction/index.tpl index c44708c9..263c34a8 100644 --- a/views/html/introduction/index.tpl +++ b/views/html/introduction/index.tpl @@ -4,47 +4,33 @@
-

-

+

+ + +

+

+ + +

+ + + +

-

-

Bereits im Sommersemester 2013 wurde das Projekt „Die Legende von Zyren“ unterstützt durch den Lehrförderungsfond der Heinrich-Heine-Universität Düsseldorf ins Leben gerufen, um die Inhalte der Vorlesung „Wissensrepräsentation“ den Studierenden des Faches Informationswissenschaft mit Hilfe von Spielelementen und -modellen zu vermitteln. Die innovative Lernumgebung besteht aus einem virtuellen Textadventure, dass über eine webbasierte Plattform zugänglich ist und realen Spielen in einer Präsenzveranstaltung, in denen die Studierenden unmittelbar in das Abenteuer eintauchen und in Teams spielerisch gegeneinander antreten.

-

Auf der Plattform spielt sich jeder der Studierenden mit seinem virtuellen Avatar durch das Reich von Zyren und erlernt und vertieft auf spielerische Weise die Inhalte der Vorlesung „Wissensrepräsentation“, die in Form von Herausforderungen oder Rätseln in das Abenteuer eingebunden wurden und über den Fortlauf und den Erfolg des Spiels entscheiden.

-

In der zusätzlichen Präsenzveranstaltung tauchen die Studierenden direkt in das Abenteuer ein und die vertiefen die Inhalte spielerisch. Hier schließen sich die Studierenden in Teams (Gilden) zusammen, müssen eigenverantwortlich Lerninhalte erarbeiten, Probleme lösen und in speziellen Gildenaufgaben gegen andere Teams antreten, um ihr kollaborativ erarbeitetes Wissen auf die Probe zu stellen.

-

Für jede erfolgreiche absolvierte Herausforderung auf der Plattform oder in der Übung erhalten die Studierenden Erfahrungspunkte und Belohnungen.

-

Um das Konzept auch anderen Fachbereichen und Lehrveranstaltungen zugänglich zu machen, wurde im Frühjahr 2014 das Projekt Questlab (Arbeitstitel „The Legend of Z“) gestartet um das Konzept zu generalisieren. Lehrende können die Plattform nun nutzen um eigene Aufgaben (Quests) zu kreieren und hochzuladen und sie optional in eine Geschichte einzubinden, die sie selbst gestalten können. Zudem wurde das Responsive Design überarbeitet und bietet nun optimalen Zugriff auf die Plattform über alle mobilen Endgeräte.

+ +t($text)?> + -

Die Legende von Zyren in der Presse

- - -

Das Team

-

Projektleitung:

-
    -
  • Kathrin Knautz
  • -
-

Entwicklung und Evaluation des Prototypens:

-
    -
  • Lisa Orszullok
  • -
  • Simone Soubusta
  • -
  • Julia Göretz
  • -
  • Anja Wintermeyer
  • -
-

Entwicklung „Questlab“:

-
    -
  • Oliver Hanraths
  • -
  • Daniel Miskovic
  • -
+
+

Questlab', + 'GPL' +)?>.

diff --git a/views/html/menu/index.tpl b/views/html/menu/index.tpl index 9785edaf..86e658bd 100644 --- a/views/html/menu/index.tpl +++ b/views/html/menu/index.tpl @@ -1,7 +1,19 @@
  • - 0) : ?>
  • -
  • - 0) : ?> + 0) : ?> +
  • + + +
  • + + 0) : ?> + + + +
  • + + +
  • +
  • diff --git a/views/html/pages/create.tpl b/views/html/pages/create.tpl new file mode 100644 index 00000000..d424286f --- /dev/null +++ b/views/html/pages/create.tpl @@ -0,0 +1,47 @@ +
    + +
    + + +

    + +
      + &$settings) : ?> +
    • +
        + $value) : ?> +
      • + getMessage(); + break; + } ?> +
      • + +
      +
    • + +
    + +
    +
    + + />
    +
    + +
    diff --git a/views/html/pages/delete.tpl b/views/html/pages/delete.tpl new file mode 100644 index 00000000..28a54d7f --- /dev/null +++ b/views/html/pages/delete.tpl @@ -0,0 +1,13 @@ +
    + +
    + + +

    + +
    + + +
    diff --git a/views/html/pages/edit.tpl b/views/html/pages/edit.tpl new file mode 100644 index 00000000..3f37eb40 --- /dev/null +++ b/views/html/pages/edit.tpl @@ -0,0 +1,56 @@ +
    + +
    + + +

    + +
      + &$settings) : ?> +
    • +
        + $value) : ?> +
      • + getMessage(); + break; + } ?> +
      • + +
      +
    • + +
    + +
    +
    + + />
    +
    +
    + + +
    + +
    + diff --git a/views/html/pages/index.tpl b/views/html/pages/index.tpl new file mode 100644 index 00000000..a863be01 --- /dev/null +++ b/views/html/pages/index.tpl @@ -0,0 +1,20 @@ +
    + +
    + +

    +
      + +
    • + + + +
    • + +
    • +
      + + +
      +
    • +
    diff --git a/views/html/pages/page.tpl b/views/html/pages/page.tpl new file mode 100644 index 00000000..db02e5a8 --- /dev/null +++ b/views/html/pages/page.tpl @@ -0,0 +1,12 @@ +
    + +
    + + + + +

    +t($page['text'])?>