commit df14dfafc3eded4ff5c7ed1c21bf7633334a5b50 Author: oliver Date: Sat Apr 9 13:44:37 2016 +0200 hide map for Character groups Quest Stations when there are no stations diff --git a/.hgignore b/.hgignore new file mode 100644 index 00000000..94d6c873 --- /dev/null +++ b/.hgignore @@ -0,0 +1,10 @@ +syntax: regexp +^logs/* +^media/* +^tmp/* +^uploads/* +^seminarymedia/* +^seminaryuploads/* +^www/analytics/config/config.ini.php* +^www/analytics/temp/* +^app/lib/phpqrcode/cache/* diff --git a/.htaccess b/.htaccess new file mode 100644 index 00000000..258afda9 --- /dev/null +++ b/.htaccess @@ -0,0 +1,50 @@ +Options -Indexes -MultiViews + +ErrorDocument 403 /www/error403.html +ErrorDocument 404 /www/error404.html +ErrorDocument 500 /www/error500.html + + + + + Require all granted + + + Require all denied + + + + Require all denied + + + + Require all denied + + + + + Allow From All + + + Order Deny,Allow + Deny From All + + + + Order Deny,Allow + Deny From All + + + + Order Deny,Allow + Deny From All + + + + + + RewriteEngine On + + RewriteBase / + RewriteRule ^(.*)$ www/$1 [L] + diff --git a/agents/BottomlevelAgent.inc b/agents/BottomlevelAgent.inc new file mode 100644 index 00000000..648c1fb7 --- /dev/null +++ b/agents/BottomlevelAgent.inc @@ -0,0 +1,25 @@ + + * @copyright 2013 coderkun (http://www.coderkun.de) + * @license http://www.gnu.org/licenses/gpl.html + * @link http://www.coderkun.de/projects/nre + */ + + namespace nre\agents; + + + /** + * The BottomlevelAgent is the standard Agent and can have indefinite + * SubAgents. + * + * @author coderkun + */ + abstract class BottomlevelAgent extends \nre\core\Agent + { + } + +?> diff --git a/agents/IntermediateAgent.inc b/agents/IntermediateAgent.inc new file mode 100644 index 00000000..4828cfbb --- /dev/null +++ b/agents/IntermediateAgent.inc @@ -0,0 +1,49 @@ + + * @copyright 2013 coderkun (http://www.coderkun.de) + * @license http://www.gnu.org/licenses/gpl.html + * @link http://www.coderkun.de/projects/nre + */ + + namespace nre\agents; + + + /** + * The IntermediateAgent assumes the task of a module. There is only one + * IntermediateAgent per request. + * + * @author coderkun + */ + abstract class IntermediateAgent extends \nre\core\Agent + { + + + + + /** + * Get the layout if it was explicitly defined. + * + * @param string $agentName Agent name + * @return string Layout of the IntermediateAgent + */ + public static function getLayout($agentName) + { + // Determine classname + $className = Autoloader::concatClassNames($agentName, 'Agent'); + + // Check property + if(isset($className::$layout)) { + return $className::$layout; + } + + + return null; + } + + } + +?> diff --git a/agents/ToplevelAgent.inc b/agents/ToplevelAgent.inc new file mode 100644 index 00000000..0c4e64ea --- /dev/null +++ b/agents/ToplevelAgent.inc @@ -0,0 +1,395 @@ + + * @copyright 2013 coderkun (http://www.coderkun.de) + * @license http://www.gnu.org/licenses/gpl.html + * @link http://www.coderkun.de/projects/nre + */ + + namespace nre\agents; + + + /** + * The ToplevelAgent assumes the task of a FrontController. There is + * only one per request. + * + * @author coderkun + */ + class ToplevelAgent extends \nre\core\Agent + { + /** + * Stage: Load + * + * @var string + */ + const STAGE_LOAD = 'load'; + /** + * Stage: Run + * + * @var string + */ + const STAGE_RUN = 'run'; + + /** + * Current request + * + * @var \nre\core\Request + */ + private $request; + /** + * Current response + * + * @var \nre\core\Response + */ + private $response; + /** + * Layout instace + * + * @var \nre\core\Layout + */ + private $layout = null; + /** + * IntermediateAgent instance + * + * @var IntermediateAgent + */ + private $intermediateAgent = null; + + + + + /** + * Construct a ToplevelAgent. + * + * @throws \nre\exceptions\ServiceUnavailableException + * @throws \nre\exceptions\DatamodelException + * @throws \nre\exceptions\DriverNotValidException + * @throws \nre\exceptions\DriverNotFoundException + * @throws \nre\exceptions\ViewNotFoundException + * @throws \nre\exceptions\ModelNotValidException + * @throws \nre\exceptions\ModelNotFoundException + * @throws \nre\exceptions\ControllerNotValidException + * @throws \nre\exceptions\ControllerNotFoundException + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + * @param \nre\core\Logger $log Log-system + */ + protected function __construct(\nre\core\Request $request, \nre\core\Response $response, \nre\core\Logger $log=null) + { + // Store values + $this->request = $request; + $this->response = $response; + + + // Create response + $response = clone $response; + $response->clearParams(1); + $response->addParams( + null, + \nre\configs\CoreConfig::$defaults['action'] + ); + + // Call parent constructor + parent::__construct($request, $response, $log, true); + + + // Load IntermediateAgent + $this->loadIntermediateAgent(); + } + + + + + /** + * Run the Controller of this Agent and its SubAgents. + * + * @throws \nre\exceptions\ServiceUnavailableException + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + * @return \Exception Last occurred exception of SubAgents + */ + public function run(\nre\core\Request $request, \nre\core\Response $response) + { + try { + return $this->_run($request, $response); + } + catch(\nre\exceptions\AccessDeniedException $e) { + $this->error($e, \nre\core\WebUtils::HTTP_FORBIDDEN, self::STAGE_RUN); + } + catch(\nre\exceptions\ParamsNotValidException $e) { + $this->error($e, \nre\core\WebUtils::HTTP_NOT_FOUND, self::STAGE_RUN); + } + catch(\nre\exceptions\IdNotFoundException $e) { + $this->error($e, \nre\core\WebUtils::HTTP_NOT_FOUND, self::STAGE_RUN); + } + catch(\nre\exceptions\DatamodelException $e) { + $this->error($e, \nre\core\WebUtils::HTTP_SERVICE_UNAVAILABLE, self::STAGE_RUN); + } + catch(\nre\exceptions\ActionNotFoundException $e) { + $this->error($e, \nre\core\WebUtils::HTTP_NOT_FOUND, self::STAGE_RUN); + } + } + + + /** + * Generate output of the Controller of this Agent and its + * SubAgents. + * + * @param array $data View data + * @return string Generated output + */ + public function render($data=array()) + { + // Render IntermediateAgent + $data = array(); + $data['intermediate'] = $this->intermediateAgent->render(); + + + // Render ToplevelAgent + return parent::render($data); + } + + + /** + * Return the IntermediateAgent. + * + * @return \nre\agents\IntermediateAgent IntermediateAgent + */ + public function getIntermediateAgent() + { + return $this->intermediateAgent; + } + + + + + /** + * Load a SubAgent and add it. + * + * @throws \nre\exceptions\ServiceUnavailableException + * @throws \nre\exceptions\FatalDatamodelException + * @throws \nre\exceptions\AgentNotFoundException + * @throws \nre\exceptions\AgentNotValidException + * @param string $agentName Name of the Agent to load + * @param mixed … Additional parameters for the agent + */ + protected function addSubAgent($agentName) + { + try { + call_user_func_array( + array( + $this, + '_addSubAgent' + ), + func_get_args() + ); + } + catch(\nre\exceptions\DatamodelException $e) { + throw new \nre\exceptions\FatalDatamodelException($e->getDatamodelMessage(), $e->getDatamodelErrorNumber()); + } + } + + + + + /** + * Load IntermediateAgent defined by the current request. + * + * @throws \nre\exceptions\ServiceUnavailableException + */ + private function loadIntermediateAgent() + { + try { + $this->_loadIntermediateAgent(); + } + catch(\nre\exceptions\ViewNotFoundException $e) { + $this->error($e, \nre\core\WebUtils::HTTP_NOT_FOUND); + } + catch(\nre\exceptions\DatamodelException $e) { + $this->error($e, \nre\core\WebUtils::HTTP_SERVICE_UNAVAILABLE); + } + catch(\nre\exceptions\DriverNotValidException $e) { + $this->error($e, \nre\core\WebUtils::HTTP_SERVICE_UNAVAILABLE); + } + catch(\nre\exceptions\DriverNotFoundException $e) { + $this->error($e, \nre\core\WebUtils::HTTP_SERVICE_UNAVAILABLE); + } + catch(\nre\exceptions\ModelNotValidException $e) { + $this->error($e, \nre\core\WebUtils::HTTP_SERVICE_UNAVAILABLE); + } + catch(\nre\exceptions\ModelNotFoundException $e) { + $this->error($e, \nre\core\WebUtils::HTTP_SERVICE_UNAVAILABLE); + } + catch(\nre\exceptions\ControllerNotValidException $e) { + $this->error($e, \nre\core\WebUtils::HTTP_SERVICE_UNAVAILABLE); + } + catch(\nre\exceptions\ControllerNotFoundException $e) { + $this->error($e, \nre\core\WebUtils::HTTP_NOT_FOUND); + } + catch(\nre\exceptions\AgentNotValidException $e) { + $this->error($e, \nre\core\WebUtils::HTTP_SERVICE_UNAVAILABLE); + } + catch(\nre\exceptions\AgentNotFoundException $e) { + $this->error($e, \nre\core\WebUtils::HTTP_NOT_FOUND); + } + } + + + /** + * Load IntermediateAgent defined by the current request. + * + * @throws \nre\exceptions\ServiceUnavailableException + */ + private function _loadIntermediateAgent() + { + // Determine IntermediateAgent + $agentName = $this->response->getParam(1); + if(is_null($agentName)) { + $agentName = $this->request->getParam(1, 'intermediate'); + $this->response->addParam($agentName); + } + + // Load IntermediateAgent + IntermediateAgent::load($agentName); + + + // Determine Action + $action = $this->response->getParam(2); + if(is_null($action)) { + $action = $this->request->getParam(2, 'action'); + $this->response->addParam($action); + } + + // Construct IntermediateAgent + $this->intermediateAgent = \nre\agents\IntermediateAgent::factory( + $agentName, + $this->request, + $this->response, + $this->log + ); + } + + + /** + * Run the Controller of this Agent and its SubAgents. + * + * @throws \nre\exceptions\AccessDeniedException + * @throws \nre\exceptions\IdNotFoundException + * @throws \nre\exceptions\ServiceUnavailableException + * @throws \nre\exceptions\DatamodelException + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + * @return \Exception Last occurred exception of SubAgents + */ + private function _run(\nre\core\Request $request, \nre\core\Response $response) + { + // Run IntermediateAgent + $this->runIntermediateAgent(); + + + // TODO Request instead of response? + $response = clone $response; + $response->clearParams(2); + $response->addParam(\nre\configs\CoreConfig::$defaults['action']); + + + // Run ToplevelAgent + return parent::run($request, $response); + } + + + /** + * Run IntermediateAgent. + * + * @throws \nre\exceptions\AccessDeniedException + * @throws \nre\exceptions\ParamsNotValidException + * @throws \nre\exceptions\IdNotFoundException + * @throws \nre\exceptions\ServiceUnavailableException + * @throws \nre\exceptions\DatamodelException + */ + private function runIntermediateAgent() + { + $this->intermediateAgent->run( + $this->request, + $this->response + ); + } + + + /** + * Handle an error that occurred during + * loading/cnostructing/running of the IntermediateAgent. + * + * @throws \nre\exceptions\ServiceUnavailableException + * @param \Exception $exception Occurred exception + * @param int $httpStatusCode HTTP-statuscode + * @param string $stage Stage of execution + */ + private function error($exception, $httpStatusCode, $stage=self::STAGE_LOAD) + { + // Log error + $this->log($exception, \nre\core\Logger::LOGMODE_AUTO); + + + try { + // Define ErrorAgent + $this->response->clearParams(1); + $this->response->addParams( + \nre\configs\AppConfig::$defaults['intermediate-error'], + \nre\configs\CoreConfig::$defaults['action'], + $httpStatusCode + ); + + // Load ErrorAgent + $this->_loadIntermediateAgent(); + + // Run ErrorAgent + if($stage == self::STAGE_RUN) { + $this->_run($this->request, $this->response); + } + } + catch(\nre\exceptions\ActionNotFoundException $e) { + throw new \nre\exceptions\ServiceUnavailableException($e); + } + catch(\nre\exceptions\DatamodelException $e) { + throw new \nre\exceptions\ServiceUnavailableException($e); + } + catch(\nre\exceptions\DriverNotValidException $e) { + throw new \nre\exceptions\ServiceUnavailableException($e); + } + catch(\nre\exceptions\DriverNotFoundException $e) { + throw new \nre\exceptions\ServiceUnavailableException($e); + } + catch(\nre\exceptions\ModelNotValidException $e) { + throw new \nre\exceptions\ServiceUnavailableException($e); + } + catch(\nre\exceptions\ModelNotFoundException $e) { + throw new \nre\exceptions\ServiceUnavailableException($e); + } + catch(\nre\exceptions\ViewNotFoundException $e) { + throw new \nre\exceptions\ServiceUnavailableException($e); + } + catch(\nre\exceptions\ControllerNotValidException $e) { + throw new \nre\exceptions\ServiceUnavailableException($e); + } + catch(\nre\exceptions\ControllerNotFoundException $e) { + throw new \nre\exceptions\ServiceUnavailableException($e); + } + catch(\nre\exceptions\AgentNotValidException $e) { + throw new \nre\exceptions\ServiceUnavailableException($e); + } + catch(\nre\exceptions\AgentNotFoundException $e) { + throw new \nre\exceptions\ServiceUnavailableException($e); + } + catch(Exception $e) { + throw new \nre\exceptions\ServiceUnavailableException($e); + } + } + + + } + +?> diff --git a/agents/bottomlevel/MailreceiverAgent.inc b/agents/bottomlevel/MailreceiverAgent.inc new file mode 100644 index 00000000..2321e34a --- /dev/null +++ b/agents/bottomlevel/MailreceiverAgent.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\bottomlevel; + + + /** + * Agent to generate a mail receiver salutation. + * + * @author Oliver Hanraths + */ + class MailreceiverAgent extends \nre\agents\BottomlevelAgent + { + + + + + /** + * 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/agents/bottomlevel/MenuAgent.inc b/agents/bottomlevel/MenuAgent.inc new file mode 100644 index 00000000..724cce6e --- /dev/null +++ b/agents/bottomlevel/MenuAgent.inc @@ -0,0 +1,40 @@ + + * @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\bottomlevel; + + + /** + * Agent to display a menu. + * + * @author Oliver Hanraths + */ + class MenuAgent extends \nre\agents\BottomlevelAgent + { + + + + + /** + * 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) + { + // Add Seminary menu + $this->addSubAgent('Seminarymenu'); + } + + } + +?> diff --git a/agents/bottomlevel/MoodpicAgent.inc b/agents/bottomlevel/MoodpicAgent.inc new file mode 100644 index 00000000..0257d9db --- /dev/null +++ b/agents/bottomlevel/MoodpicAgent.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\bottomlevel; + + + /** + * Agent to display a Moodpic. + * + * @author Oliver Hanraths + */ + class MoodpicAgent extends \nre\agents\BottomlevelAgent + { + + + + + /** + * 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/agents/bottomlevel/QuestgroupshierarchypathAgent.inc b/agents/bottomlevel/QuestgroupshierarchypathAgent.inc new file mode 100644 index 00000000..43dba806 --- /dev/null +++ b/agents/bottomlevel/QuestgroupshierarchypathAgent.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\bottomlevel; + + + /** + * Agent to display the Questgroups hierarchy path. + * + * @author Oliver Hanraths + */ + class QuestgroupshierarchypathAgent extends \nre\agents\BottomlevelAgent + { + + + + + /** + * 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/agents/bottomlevel/SeminarybarAgent.inc b/agents/bottomlevel/SeminarybarAgent.inc new file mode 100644 index 00000000..62a30ccd --- /dev/null +++ b/agents/bottomlevel/SeminarybarAgent.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\bottomlevel; + + + /** + * Agent to display a sidebar with Seminary related information. + * + * @author Oliver Hanraths + */ + class SeminarybarAgent extends \nre\agents\BottomlevelAgent + { + + + + + /** + * 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/agents/bottomlevel/SeminarymenuAgent.inc b/agents/bottomlevel/SeminarymenuAgent.inc new file mode 100644 index 00000000..9367cf7d --- /dev/null +++ b/agents/bottomlevel/SeminarymenuAgent.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\bottomlevel; + + + /** + * Agent to display a menu with Seminary related links. + * + * @author Oliver Hanraths + */ + class SeminarymenuAgent extends \nre\agents\BottomlevelAgent + { + + + + + /** + * 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/agents/bottomlevel/UserrolesAgent.inc b/agents/bottomlevel/UserrolesAgent.inc new file mode 100644 index 00000000..791846cd --- /dev/null +++ b/agents/bottomlevel/UserrolesAgent.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\bottomlevel; + + + /** + * Agent to display and manage userroles. + * + * @author Oliver Hanraths + */ + class UserrolesAgent extends \nre\agents\BottomlevelAgent + { + + + + + /** + * Action: user. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function user(\nre\core\Request $request, \nre\core\Response $response) + { + } + + } + +?> diff --git a/agents/intermediate/AchievementsAgent.inc b/agents/intermediate/AchievementsAgent.inc new file mode 100644 index 00000000..39f97abb --- /dev/null +++ b/agents/intermediate/AchievementsAgent.inc @@ -0,0 +1,105 @@ + + * @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 list Achievements. + * + * @author Oliver Hanraths + */ + class AchievementsAgent 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) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: create. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function create(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: edit. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function edit(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: manage. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function manage(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: conditions. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function conditions(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3)); + } + + + /** + * Action: delete. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function delete(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + } + +?> diff --git a/agents/intermediate/CharactergroupsAgent.inc b/agents/intermediate/CharactergroupsAgent.inc new file mode 100644 index 00000000..30164865 --- /dev/null +++ b/agents/intermediate/CharactergroupsAgent.inc @@ -0,0 +1,157 @@ + + * @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 display Character groups. + * + * @author Oliver Hanraths + */ + class CharactergroupsAgent 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) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: groupsgroup. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function groupsgroup(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: creategroupsgroups. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function creategroupsgroup(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: editgroupsgroup. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function editgroupsgroup(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: deletegroupsgroup. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function deletegroupsgroup(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: group. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function group(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: creategroup. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function creategroup(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: managegroup. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function managegroup(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: editgroup. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function editgroup(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: deletegroup. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function deletegroup(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + } + +?> diff --git a/agents/intermediate/CharactergroupsachievementsAgent.inc b/agents/intermediate/CharactergroupsachievementsAgent.inc new file mode 100644 index 00000000..d247ff7f --- /dev/null +++ b/agents/intermediate/CharactergroupsachievementsAgent.inc @@ -0,0 +1,92 @@ + + * @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 list Charactergroups Achievements. + * + * @author Oliver Hanraths + */ + class CharactergroupsachievementsAgent extends \nre\agents\IntermediateAgent + { + + + + + /** + * Action: achievement. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function achievement(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: create. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function create(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: edit. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function edit(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: manage. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function manage(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: delete. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function delete(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + } + +?> diff --git a/agents/intermediate/CharactergroupsquestsAgent.inc b/agents/intermediate/CharactergroupsquestsAgent.inc new file mode 100644 index 00000000..1d4d8c50 --- /dev/null +++ b/agents/intermediate/CharactergroupsquestsAgent.inc @@ -0,0 +1,105 @@ + + * @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 display Character groups Quests. + * + * @author Oliver Hanraths + */ + class CharactergroupsquestsAgent 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) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), 'charactergroups'); + } + + + /** + * Action: quest. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function quest(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), 'charactergroups'); + } + + + /** + * Action: create. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function create(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), 'charactergroups'); + } + + + /** + * Action: manage. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function manage(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), 'charactergroups'); + } + + + /** + * Action: edit. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function edit(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), 'charactergroups'); + } + + + /** + * Action: delete. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function delete(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), 'charactergroups'); + } + + } + +?> diff --git a/agents/intermediate/CharactergroupsqueststationsAgent.inc b/agents/intermediate/CharactergroupsqueststationsAgent.inc new file mode 100644 index 00000000..9de435b3 --- /dev/null +++ b/agents/intermediate/CharactergroupsqueststationsAgent.inc @@ -0,0 +1,103 @@ + + * @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 display Character groups Quest stations. + * + * @author Oliver Hanraths + */ + class CharactergroupsqueststationsAgent 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) + { + } + + + /** + * Action: station. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function station(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), 'charactergroups'); + } + + + /** + * Action: create. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function create(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), 'charactergroups'); + } + + + /** + * Action: edit. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function edit(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), 'charactergroups'); + } + + + /** + * Action: edittask. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function edittask(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), 'charactergroups'); + } + + + /** + * Action: delete. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function delete(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), 'charactergroups'); + } + + } + +?> diff --git a/agents/intermediate/CharactersAgent.inc b/agents/intermediate/CharactersAgent.inc new file mode 100644 index 00000000..1ba9bf4e --- /dev/null +++ b/agents/intermediate/CharactersAgent.inc @@ -0,0 +1,105 @@ + + * @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 list registered Characters and their data. + * + * @author Oliver Hanraths + */ + class CharactersAgent 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) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3)); + } + + + /** + * Action: character. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function character(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3)); + } + + + /** + * Action: register. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function register(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3)); + } + + + /** + * Action: manage. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function manage(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3)); + } + + + /** + * Action: edit. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function edit(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3)); + } + + + /** + * Action: delete. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function delete(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3)); + } + + } + +?> diff --git a/agents/intermediate/CharactertitlesAgent.inc b/agents/intermediate/CharactertitlesAgent.inc new file mode 100644 index 00000000..cd68a5d8 --- /dev/null +++ b/agents/intermediate/CharactertitlesAgent.inc @@ -0,0 +1,79 @@ + + * @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 handle Character titles of a Seminary. + * + * @author Oliver Hanraths + */ + class CharactertitlesAgent 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) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: create. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function create(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: edit. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function edit(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: delete. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function delete(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + } + +?> diff --git a/agents/intermediate/CharactertypesAgent.inc b/agents/intermediate/CharactertypesAgent.inc new file mode 100644 index 00000000..61083255 --- /dev/null +++ b/agents/intermediate/CharactertypesAgent.inc @@ -0,0 +1,79 @@ + + * @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 handle Charactertyes of a Seminary. + * + * @author Oliver Hanraths + */ + class CharactertypesAgent 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) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: create. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function create(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: edit. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function edit(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: delete. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function delete(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + } + +?> diff --git a/agents/intermediate/ErrorAgent.inc b/agents/intermediate/ErrorAgent.inc new file mode 100644 index 00000000..94b170a8 --- /dev/null +++ b/agents/intermediate/ErrorAgent.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 show an error page. + * + * @author Oliver Hanraths + */ + class ErrorAgent 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/agents/intermediate/IntroductionAgent.inc b/agents/intermediate/IntroductionAgent.inc new file mode 100644 index 00000000..1b5ebd8b --- /dev/null +++ b/agents/intermediate/IntroductionAgent.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 show an introduction page. + * + * @author Oliver Hanraths + */ + class IntroductionAgent 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/agents/intermediate/LibraryAgent.inc b/agents/intermediate/LibraryAgent.inc new file mode 100644 index 00000000..ec6d703a --- /dev/null +++ b/agents/intermediate/LibraryAgent.inc @@ -0,0 +1,105 @@ + + * @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 list Quest topics. + * + * @author Oliver Hanraths + */ + class LibraryAgent 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) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: create. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function create(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: topic. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function topic(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: manage. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function manage(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: edit. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function edit(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: delete. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function delete(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + } + +?> diff --git a/agents/intermediate/MailAgent.inc b/agents/intermediate/MailAgent.inc new file mode 100644 index 00000000..f221f3fb --- /dev/null +++ b/agents/intermediate/MailAgent.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 generate a mail-message. + * + * @author Oliver Hanraths + */ + class MailAgent 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/agents/intermediate/MapAgent.inc b/agents/intermediate/MapAgent.inc new file mode 100644 index 00000000..d0e9cbdc --- /dev/null +++ b/agents/intermediate/MapAgent.inc @@ -0,0 +1,53 @@ + + * @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 display a map. + * + * @author Oliver Hanraths + */ + class MapAgent 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) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: edit. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function edit(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + } + +?> diff --git a/agents/intermediate/MediaAgent.inc b/agents/intermediate/MediaAgent.inc new file mode 100644 index 00000000..89e773b2 --- /dev/null +++ b/agents/intermediate/MediaAgent.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 process and show media. + * + * @author Oliver Hanraths + */ + class MediaAgent 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/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/agents/intermediate/QrAgent.inc b/agents/intermediate/QrAgent.inc new file mode 100644 index 00000000..89314a46 --- /dev/null +++ b/agents/intermediate/QrAgent.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 redirect to a page from a (short) QR-code link. + * + * @author Oliver Hanraths + */ + class QrAgent 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/agents/intermediate/QrcodesAgent.inc b/agents/intermediate/QrcodesAgent.inc new file mode 100644 index 00000000..45a15782 --- /dev/null +++ b/agents/intermediate/QrcodesAgent.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 generate and show QR-codes. + * + * @author Oliver Hanraths + */ + class QrcodesAgent 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/agents/intermediate/QuestgroupsAgent.inc b/agents/intermediate/QuestgroupsAgent.inc new file mode 100644 index 00000000..e30e2a55 --- /dev/null +++ b/agents/intermediate/QuestgroupsAgent.inc @@ -0,0 +1,136 @@ + + * @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 display Questgroups. + * + * @author Oliver Hanraths + */ + class QuestgroupsAgent extends \nre\agents\IntermediateAgent + { + + + + + /** + * Action: questgroup. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function questgroup(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'questgroup', $request->getParam(3), $request->getParam(4)); + + // Add Questgroups hierarchy path + $this->addSubAgent('Questgroupshierarchypath', 'index', $request->getParam(3), $request->getParam(4)); + } + + + /** + * Action: create. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function create(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3)); + } + + + /** + * Action: edit. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function edit(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'questgroup', $request->getParam(3), $request->getParam(4)); + + // Add Questgroups hierarchy path + $this->addSubAgent('Questgroupshierarchypath', 'index', $request->getParam(3), $request->getParam(4)); + } + + + /** + * Action: edittexts. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function edittexts(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'questgroup', $request->getParam(3), $request->getParam(4)); + + // Add Questgroups hierarchy path + $this->addSubAgent('Questgroupshierarchypath', 'index', $request->getParam(3), $request->getParam(4)); + } + + + /** + * Action: moveup. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function moveup(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'questgroup', $request->getParam(3), $request->getParam(4)); + + // Add Questgroups hierarchy path + $this->addSubAgent('Questgroupshierarchypath', 'index', $request->getParam(3), $request->getParam(4)); + } + + + /** + * Action: movedown. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function movedown(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'questgroup', $request->getParam(3), $request->getParam(4)); + + // Add Questgroups hierarchy path + $this->addSubAgent('Questgroupshierarchypath', 'index', $request->getParam(3), $request->getParam(4)); + } + + + /** + * Action: delete. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function delete(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'questgroup', $request->getParam(3), $request->getParam(4)); + + // Add Questgroups hierarchy path + $this->addSubAgent('Questgroupshierarchypath', 'index', $request->getParam(3), $request->getParam(4)); + } + + } + +?> diff --git a/agents/intermediate/QuestgroupshierarchyAgent.inc b/agents/intermediate/QuestgroupshierarchyAgent.inc new file mode 100644 index 00000000..7ede785a --- /dev/null +++ b/agents/intermediate/QuestgroupshierarchyAgent.inc @@ -0,0 +1,24 @@ + + * @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 Questgroupshierarchy. + * + * @author Oliver Hanraths + */ + class QuestgroupshierarchyAgent extends \nre\agents\IntermediateAgent + { + } + +?> diff --git a/agents/intermediate/QuestsAgent.inc b/agents/intermediate/QuestsAgent.inc new file mode 100644 index 00000000..9e1950ed --- /dev/null +++ b/agents/intermediate/QuestsAgent.inc @@ -0,0 +1,168 @@ + + * @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 display Quests. + * + * @author Oliver Hanraths + */ + class QuestsAgent 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) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3)); + } + + + /** + * Action: quest. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function quest(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'questgroup', $request->getParam(3), $request->getParam(4)); + + // Add Questgroups hierarchy path + $this->addSubAgent('Questgroupshierarchypath', 'index', $request->getParam(3), $request->getParam(4), true); + } + + + /** + * Action: submissions. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function submissions(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'questgroup', $request->getParam(3), $request->getParam(4)); + + // Add Questgroups hierarchy path + $this->addSubAgent('Questgroupshierarchypath', 'index', $request->getParam(3), $request->getParam(4), true); + } + + + /** + * Action: submission. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function submission(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'questgroup', $request->getParam(3), $request->getParam(4)); + + // Add Questgroups hierarchy path + $this->addSubAgent('Questgroupshierarchypath', 'index', $request->getParam(3), $request->getParam(4), true); + } + + + /** + * Action: create. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function create(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'questgroup', $request->getParam(3), $request->getParam(4)); + + // Add Questgroups hierarchy path + $this->addSubAgent('Questgroupshierarchypath', 'index', $request->getParam(3), $request->getParam(4), true); + } + + + /** + * Action: edit. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function edit(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'questgroup', $request->getParam(3), $request->getParam(4)); + + // Add Questgroups hierarchy path + $this->addSubAgent('Questgroupshierarchypath', 'index', $request->getParam(3), $request->getParam(4), true); + } + + + /** + * Action: edittask. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function edittask(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'questgroup', $request->getParam(3), $request->getParam(4)); + + // Add Questgroups hierarchy path + $this->addSubAgent('Questgroupshierarchypath', 'index', $request->getParam(3), $request->getParam(4), true); + } + + + /** + * Action: edittexts. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function edittexts(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'questgroup', $request->getParam(3), $request->getParam(4)); + + // Add Questgroups hierarchy path + $this->addSubAgent('Questgroupshierarchypath', 'index', $request->getParam(3), $request->getParam(4), true); + } + + + /** + * Action: delete. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function delete(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'questgroup', $request->getParam(3), $request->getParam(4)); + + // Add Questgroups hierarchy path + $this->addSubAgent('Questgroupshierarchypath', 'index', $request->getParam(3), $request->getParam(4), true); + } + + } + +?> diff --git a/agents/intermediate/SeminariesAgent.inc b/agents/intermediate/SeminariesAgent.inc new file mode 100644 index 00000000..aecb054b --- /dev/null +++ b/agents/intermediate/SeminariesAgent.inc @@ -0,0 +1,105 @@ + + * @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 list registered seminaries. + * + * @author Oliver Hanraths + */ + class SeminariesAgent 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) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'index'); + } + + + /** + * Action: seminary. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function seminary(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3)); + } + + + /** + * Action: create. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function create(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'index'); + } + + + /** + * Action: edit. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function edit(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: copy. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function copy(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + + /** + * Action: delete. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function delete(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3), $request->getParam(1)); + } + + } + +?> diff --git a/agents/intermediate/UploadsAgent.inc b/agents/intermediate/UploadsAgent.inc new file mode 100644 index 00000000..ff492f82 --- /dev/null +++ b/agents/intermediate/UploadsAgent.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 process and show user uploads. + * + * @author Oliver Hanraths + */ + class UploadsAgent 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/agents/intermediate/UsersAgent.inc b/agents/intermediate/UsersAgent.inc new file mode 100644 index 00000000..c99d870e --- /dev/null +++ b/agents/intermediate/UsersAgent.inc @@ -0,0 +1,50 @@ + + * @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 list registered users and their data. + * + * @author Oliver Hanraths + */ + class UsersAgent 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) + { + } + + + /** + * Action: user. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function user(\nre\core\Request $request, \nre\core\Response $response) + { + $this->addSubAgent('Userroles', 'user'); + } + + } + +?> diff --git a/agents/intermediate/XplevelsAgent.inc b/agents/intermediate/XplevelsAgent.inc new file mode 100644 index 00000000..e810d4e8 --- /dev/null +++ b/agents/intermediate/XplevelsAgent.inc @@ -0,0 +1,40 @@ + + * @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 handle XP-levels of a Seminary. + * + * @author Oliver Hanraths + */ + class XplevelsAgent extends \nre\agents\IntermediateAgent + { + + + + + /** + * Action: index. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function manage(\nre\core\Request $request, \nre\core\Response $response) + { + // Add Moodpic + $this->addSubAgent('Moodpic', 'seminary', $request->getParam(3)); + } + + } + +?> diff --git a/agents/toplevel/AjaxAgent.inc b/agents/toplevel/AjaxAgent.inc new file mode 100644 index 00000000..4b56cf98 --- /dev/null +++ b/agents/toplevel/AjaxAgent.inc @@ -0,0 +1,80 @@ + + * @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\toplevel; + + + /** + * Agent to return a JSON-string used by AJAX. + * + * @author Oliver Hanraths + */ + class AjaxAgent extends \hhu\z\agents\ToplevelAgent + { + + + + + /** + * Construct a new AjaxAgent. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + * @param \nre\core\Logger $log Logger instance + */ + protected function __construct(\nre\core\Request $request, \nre\core\Response $response, \nre\core\Logger $log=null) + { + parent::__construct($request, $response, $log); + + + $this->setLanguage($request); + } + + + /** + * 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) + { + } + + + + + /** + * Set requested language. + * + * @param \nre\core\Request $request Current request + */ + private function setLanguage(\nre\core\Request $request) + { + // Set domain + $domain = \nre\configs\AppConfig::$app['genericname']; + + // Get language + $locale = $request->getGetParam('lang', 'language'); + if(is_null($locale)) { + return; + } + + // Load translation + putenv("LC_ALL=$locale"); + setlocale(LC_ALL, $locale); + bindtextdomain($domain, ROOT.DS.\nre\configs\AppConfig::$dirs['locale']); + textdomain($domain); + } + + } + +?> diff --git a/agents/toplevel/BinaryAgent.inc b/agents/toplevel/BinaryAgent.inc new file mode 100644 index 00000000..6130a1c0 --- /dev/null +++ b/agents/toplevel/BinaryAgent.inc @@ -0,0 +1,51 @@ + + * @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\toplevel; + + + /** + * Agent to display binary data (e. g. images). + * + * @author Oliver Hanraths + */ + class BinaryAgent extends \hhu\z\agents\ToplevelAgent + { + + + + + /** + * Construct a new BinaryAgent. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + * @param \nre\core\Logger $log Logger instance + */ + protected function __construct(\nre\core\Request $request, \nre\core\Response $response, \nre\core\Logger $log=null) + { + parent::__construct($request, $response, $log); + } + + + /** + * 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/agents/toplevel/FaultAgent.inc b/agents/toplevel/FaultAgent.inc new file mode 100644 index 00000000..dc4b101b --- /dev/null +++ b/agents/toplevel/FaultAgent.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\toplevel; + + + /** + * Agent to display a toplevel error page. + * + * @author Oliver Hanraths + */ + class FaultAgent extends \nre\agents\ToplevelAgent + { + + + + + /** + * 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/agents/toplevel/HtmlAgent.inc b/agents/toplevel/HtmlAgent.inc new file mode 100644 index 00000000..6a8e4ac5 --- /dev/null +++ b/agents/toplevel/HtmlAgent.inc @@ -0,0 +1,155 @@ + + * @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\toplevel; + + + /** + * Agent to display a HTML-page. + * + * @author Oliver Hanraths + */ + class HtmlAgent extends \hhu\z\agents\ToplevelAgent + { + + + + + /** + * Construct a new HtmlAgent. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + * @param \nre\core\Logger $log Logger instance + */ + protected function __construct(\nre\core\Request $request, \nre\core\Response $response, \nre\core\Logger $log=null) + { + parent::__construct($request, $response, $log); + + + $this->setLanguage($request); + } + + + /** + * 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) + { + // Add menu + $this->addSubAgent('Menu'); + + // Add Seminary sidebar + $this->addSubAgent('Seminarybar'); + } + + + + + /** + * Set requested language. + * + * @param \nre\core\Request $request Current request + */ + private function setLanguage(\nre\core\Request $request) + { + // Set domain + $domain = \nre\configs\AppConfig::$app['genericname']; + + // Get language + $locale = $this->determineLanguage($request); + + // Set Locale and Load translation + if(!is_null($locale)) + { + putenv("LC_ALL=$locale"); + setlocale(LC_ALL, $locale); + \Locale::setDefault($locale); + + bindtextdomain($domain, ROOT.DS.\nre\configs\AppConfig::$dirs['locale']); + textdomain($domain); + } + } + + + /** + * Determine which language is either requested directly or by browser + * setting. + * + * @param \nre\core\Request $request Current request + * @return string Requested language or default one + */ + private function determineLanguage(\nre\core\Request $request) + { + // Get supported languages + $supportedLanguages = \nre\configs\AppConfig::$app['languages']; + if(empty($supportedLanguages)) { + return null; + } + + // Get requested language + $language = $request->getGetParam('lang', 'language'); + if(!is_null($language) && array_key_exists($language, $supportedLanguages)) { + return $supportedLanguages[$language]; + } + + // Negotiate language + return $this->negotiateLanguage($supportedLanguages, $request->getBrowserLanguages()); + } + + + /** + * Negotiate which language the browser wants most out of the supported + * languages. + * + * @param array $supportedLanguages List of supported languages + * @param array $browserLanguages List of browser languages + * @return string Negotiated language or default one + */ + private function negotiateLanguage($supportedLanguages, $browserLanguages) + { + if(!is_null($browserLanguages)) + { + // Create array with languages and their ratings + $parsedLanguages = array(); + $languages = explode(',', $browserLanguages); + foreach($languages as &$language) + { + if(($pos = strpos($language, ';q=')) !== false) { + $parsedLanguages[substr($language, 1, min(2, $pos-1))] = floatval(substr($language, $pos+3)); + } + else { + $parsedLanguages[$language] = 1.0; + } + } + + // Sort languages by their ratings + arsort($parsedLanguages); + + // Get highest supported language + foreach($parsedLanguages as $language => $rating) { + if(array_key_exists($language, $supportedLanguages)) { + return $supportedLanguages[$language]; + } + } + } + + + // Return default language + return $supportedLanguages[array_keys($supportedLanguages)[0]]; + } + + } + +?> diff --git a/agents/toplevel/HtmlmailAgent.inc b/agents/toplevel/HtmlmailAgent.inc new file mode 100644 index 00000000..c0d9cad5 --- /dev/null +++ b/agents/toplevel/HtmlmailAgent.inc @@ -0,0 +1,52 @@ + + * @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\toplevel; + + + /** + * Agent for generating a HTML-mail message. + * + * @author Oliver Hanraths + */ + class HtmlmailAgent extends \hhu\z\agents\ToplevelAgent + { + + + + + /** + * Construct a new HtmlmailAgent. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + * @param \nre\core\Logger $log Logger instance + */ + protected function __construct(\nre\core\Request $request, \nre\core\Response $response, \nre\core\Logger $log=null) + { + parent::__construct($request, $response, $log); + } + + + /** + * 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) + { + $this->addSubagent('mailreceiver', 'index', $request->getParam(3)); + } + + } + +?> diff --git a/agents/toplevel/TextmailAgent.inc b/agents/toplevel/TextmailAgent.inc new file mode 100644 index 00000000..85c20d13 --- /dev/null +++ b/agents/toplevel/TextmailAgent.inc @@ -0,0 +1,53 @@ + + * @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\toplevel; + + /** + * Agent for generating a simple text-mail message. + * + * @author Oliver Hanraths + */ + class TextmailAgent extends \hhu\z\agents\ToplevelAgent + { + + + + + /** + * Construct a new TextmailAgent. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + * @param \nre\core\Logger $log Logger instance + */ + protected function __construct(\nre\core\Request $request, \nre\core\Response $response, \nre\core\Logger $log=null) + { + parent::__construct($request, $response, $log); + } + + + + + /** + * 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) + { + $this->addSubagent('mailreceiver', 'index', $request->getParam(3)); + } + + } + +?> diff --git a/apis/WebApi.inc b/apis/WebApi.inc new file mode 100644 index 00000000..eafde955 --- /dev/null +++ b/apis/WebApi.inc @@ -0,0 +1,250 @@ + + * @copyright 2013 coderkun (http://www.coderkun.de) + * @license http://www.gnu.org/licenses/gpl.html + * @link http://www.coderkun.de/projects/nre + */ + + namespace nre\apis; + + + /** + * WebApi-implementation. + * + * This class runs and renders an web-applictaion. + * + * @author coderkun + */ + class WebApi extends \nre\core\Api + { + + + + + /** + * Construct a new WebApi. + */ + public function __construct() + { + parent::__construct( + new \nre\requests\WebRequest(), + new \nre\responses\WebResponse() + ); + + // Add routes + $this->addRoutes(); + + // Disable screen logging for AJAX requests + if($this->request->getParam(0, 'toplevel') == 'ajax') { + $this->log->disableAutoLogToScreen(); + } + } + + + + + /** + * Run application. + * + * This method runs the application and handles all errors. + */ + public function run() + { + try { + $exception = parent::run(); + + if(!is_null($exception)) { + $this->errorService($exception); + } + } + catch(\nre\exceptions\ServiceUnavailableException $e) { + $this->errorService($e); + } + catch(\nre\exceptions\ActionNotFoundException $e) { + $this->error($e, \nre\core\WebUtils::HTTP_NOT_FOUND); + } + catch(\nre\exceptions\FatalDatamodelException $e) { + $this->errorService($e); + } + catch(\nre\exceptions\DatamodelException $e) { + $this->error($e, \nre\core\WebUtils::HTTP_SERVICE_UNAVAILABLE); + } + catch(\nre\exceptions\DriverNotValidException $e) { + $this->error($e, \nre\core\WebUtils::HTTP_SERVICE_UNAVAILABLE); + } + catch(\nre\exceptions\DriverNotFoundException $e) { + $this->error($e, \nre\core\WebUtils::HTTP_SERVICE_UNAVAILABLE); + } + catch(\nre\exceptions\ModelNotValidException $e) { + $this->error($e, \nre\core\WebUtils::HTTP_SERVICE_UNAVAILABLE); + } + catch(\nre\exceptions\ModelNotFoundException $e) { + $this->error($e, \nre\core\WebUtils::HTTP_SERVICE_UNAVAILABLE); + } + catch(\nre\exceptions\ViewNotFoundException $e) { + $this->error($e, \nre\core\WebUtils::HTTP_NOT_FOUND); + } + catch(\nre\exceptions\ControllerNotValidException $e) { + $this->error($e, \nre\core\WebUtils::HTTP_SERVICE_UNAVAILABLE); + } + catch(\nre\exceptions\ControllerNotFoundException $e) { + $this->error($e, \nre\core\WebUtils::HTTP_NOT_FOUND); + } + catch(\nre\exceptions\AgentNoaatValidException $e) { + $this->error($e, \nre\core\WebUtils::HTTP_SERVICE_UNAVAILABLE); + } + catch(\nre\exceptions\AgentNotFoundException $e) { + $this->error($e, \nre\core\WebUtils::HTTP_NOT_FOUND); + } + catch(\nre\exceptions\ClassNotValidException $e) { + $this->errorService($e); + } + catch(\nre\exceptions\ClassNotFoundException $e) { + $this->errorService($e); + } + } + + + /** + * Render output. + */ + public function render() + { + // Generate output + parent::render(); + + + // Set HTTP-header + $this->response->header(); + + // Show output + echo $this->response->getOutput(); + } + + + + + /** + * Add routes (normal and reverse) defined in the AppConfig. + */ + private function addRoutes() + { + // Normal routes + if(property_exists('\nre\configs\AppConfig', 'routes')) { + foreach(\nre\configs\AppConfig::$routes as &$route) { + $this->request->addRoute($route[0], $route[1], $route[2]); + } + } + + // Reverse routes + if(property_exists('\nre\configs\AppConfig', 'reverseRoutes')) { + foreach(\nre\configs\AppConfig::$reverseRoutes as &$route) { + $this->request->addReverseRoute($route[0], $route[1], $route[2]); + } + } + + // Revalidate request + $this->request->revalidate(); + } + + + /** + * Handle an error that orrcurred during the + * loading/constructing/running of the ToplevelAgent. + * + * @param \Exception $exception Occurred exception + * @param int $httpStatusCode HTTP-statuscode + */ + private function error(\nre\core\Exception $exception, $httpStatusCode) + { + // Log error message + $this->log($exception, \nre\core\Logger::LOGMODE_AUTO); + + try { + // Set agent for handling errors + $this->response->clearParams(); + $this->response->addParams( + \nre\configs\AppConfig::$defaults['toplevel-error'], + \nre\configs\AppConfig::$defaults['intermediate-error'], + \nre\configs\CoreConfig::$defaults['action'], + $httpStatusCode + ); + + // Run this agent + parent::run(); + } + catch(\nre\exceptions\ServiceUnavailableException $e) { + $this->errorService($e); + } + catch(\nre\exceptions\ActionNotFoundException $e) { + $this->errorService($e); + } + catch(\nre\exceptions\DatamodelException $e) { + $this->errorService($e); + } + catch(\nre\exceptions\DriverNotValidException $e) { + $this->errorService($e); + } + catch(\nre\exceptions\DriverNotFoundException $e) { + $this->errorService($e); + } + catch(\nre\exceptions\ModelNotValidException $e) { + $this->errorService($e); + } + catch(\nre\exceptions\ModelNotFoundException $e) { + $this->errorService($e); + } + catch(\nre\exceptions\ViewNotFoundException $e) { + $this->errorService($e); + } + catch(\nre\exceptions\ControllerNotValidException $e) { + $this->errorService($e); + } + catch(\nre\exceptions\ControllerNotFoundException $e) { + $this->errorService($e); + } + catch(\nre\exceptions\AgentNotValidException $e) { + $this->errorService($e); + } + catch(\nre\exceptions\AgentNotFoundException $e) { + $this->errorService($e); + } + catch(Exception $e) { + $this->errorService($e); + } + } + + + /** + * Handle a error which cannot be handles by the system (and + * HTTP 503). + * + * @param \Exception $exception Occurred exception + */ + private function errorService($exception) + { + // Log error message + $this->log($exception, \nre\core\Logger::LOGMODE_AUTO); + + // Set HTTP-rtatuscode + $this->response->addHeader(\nre\core\WebUtils::getHttpHeader(503)); + + + // Read and print static error file + $fileName = ROOT.DS.\nre\configs\CoreConfig::getClassDir('views').DS.\nre\configs\CoreConfig::$defaults['errorFile'].\nre\configs\CoreConfig::getFileExt('views'); + ob_start(); + include($fileName); + $this->response->setOutput(ob_get_clean()); + + + // Prevent further execution + $this->response->setExit(); + } + + } + +?> diff --git a/app/Controller.inc b/app/Controller.inc new file mode 100644 index 00000000..eaf4dc32 --- /dev/null +++ b/app/Controller.inc @@ -0,0 +1,134 @@ + + * @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; + + + /** + * Abstract class for implementing an application Controller. + * + * @author Oliver Hanraths + */ + abstract class Controller extends \nre\core\Controller + { + /** + * Required components + * + * @var array + */ + public $components = array('auth'); + + /** + * Logger instance + * + * @var \nre\core\Logger + */ + protected $log = null; + /** + * Linker instance + * + * @var \nre\core\Linker + */ + protected $linker = null; + + + + + /** + * Construct a new application Controller. + * + * @throws \nre\exceptions\DriverNotFoundException + * @throws \nre\exceptions\DriverNotValidException + * @throws \nre\exceptions\ModelNotValidException + * @throws \nre\exceptions\ModelNotFoundException + * @throws \nre\exceptions\ViewNotFoundException + * @param string $layoutName Name of the current Layout + * @param string $action Current Action + * @param \nre\core\Agent $agent Corresponding Agent + */ + public function __construct($layoutName, $action, $agent) + { + parent::__construct($layoutName, $action, $agent); + + // Create logger + $this->log = new \nre\core\Logger(); + } + + + + /** + * Prefilter that is executed before running the Controller. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function preFilter(\nre\core\Request $request, \nre\core\Response $response) + { + parent::preFilter($request, $response); + + // Create linker + $this->linker = new \nre\core\Linker($request); + $this->set('linker', $this->linker); + + // Create text formatter + $this->set('t', new \hhu\z\TextFormatter($this->linker)); + + // Create date and time and number formatter + $this->set('dateFormatter', new \IntlDateFormatter( + //\nre\core\Config::getDefault('locale'), + \Locale::getDefault(), + \IntlDateFormatter::MEDIUM, + \IntlDateFormatter::NONE, + NULL + )); + $this->set('timeFormatter', new \IntlDateFormatter( + //\nre\core\Config::getDefault('locale'), + \Locale::getDefault(), + \IntlDateFormatter::NONE, + \IntlDateFormatter::SHORT, + NULL + )); + $this->set('numberFormatter', new \NumberFormatter( + //\nre\core\Config::getDefault('locale'), + \Locale::getDefault(), + \NumberFormatter::DEFAULT_STYLE + )); + } + + + /** + * Postfilter that is executed after running the Controller. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function postFilter(\nre\core\Request $request, \nre\core\Response $response) + { + parent::postFilter($request, $response); + } + + + + + /** + * Log an error. + * + * @param string $message Error message to log + * @param int $logMode Log mode (optional) + */ + protected function log($message, $logMode=\nre\core\Logger::LOGMODE_AUTO) + { + $this->log->log($message, $logMode); + } + + } + +?> diff --git a/app/Model.inc b/app/Model.inc new file mode 100644 index 00000000..9acc0835 --- /dev/null +++ b/app/Model.inc @@ -0,0 +1,42 @@ + + * @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; + + + /** + * Abstract class for implementing an application Model. + * + * @author Oliver Hanraths + */ + class Model extends \nre\models\DatabaseModel + { + + + + + /** + * Construct a new application Model. + * + * @throws \nre\exceptions\DatamodelException + * @throws \nre\exceptions\DriverNotFoundException + * @throws \nre\exceptions\DriverNotValidException + * @throws \nre\exceptions\ModelNotValidException + * @throws \nre\exceptions\ModelNotFoundException + */ + public function __construct() + { + parent::__construct('mysqli', \nre\configs\AppConfig::$database); + } + + } + +?> diff --git a/app/TextFormatter.inc b/app/TextFormatter.inc new file mode 100644 index 00000000..c7c6bd67 --- /dev/null +++ b/app/TextFormatter.inc @@ -0,0 +1,213 @@ + + * @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; + + + /** + * Class to format text with different syntax tags. + * + * @author Oliver Hanraths + */ + class TextFormatter + { + /** + * Linker to create links. + * + * @var \nre\core\Linker + */ + private $linker; + /** + * Media-Model to retrieve media data + * + * @static + * @var \nre\core\Model + */ + private static $Media = null; + + + + + /** + * Create a new text formatter. + * + * @param \nre\core\Linker $linker Linker to create links with + */ + public function __construct(\nre\core\Linker $linker) + { + $this->linker = $linker; + } + + + + + /** + * Format a string. + * + * @param string $string String to format + * @return string Formatted string + */ + public function t($string) + { + // Use Textile + \hhu\z\lib\Textile::load(); + $textileParser = new \Netcarver\Textile\Parser('html5'); + $string = $textileParser->textileRestricted($string, false, false); + + // Add link targets + $string = $this->tLinks($string); + + // Handle custom formatting + $string = $this->tCustom($string); + + // Handle Seminarymedia + $string = $this->tSeminarymedia($string); + + + // Return processed string + return $string; + } + + + + + /** + * Load the Media-Model if it is not loaded + * + * @return boolean Whether the Media-Model has been loaded or not + */ + private function loadMediaModel() + { + // Do not load Model if it has already been loaded + if(!is_null(self::$Media)) { + return true; + } + + try { + // Load class + Model::load('media'); + + // Construct Model + self::$Media = Model::factory('media'); + } + catch(\Exception $e) { + } + + + // Return whether Media-Model has been loaded or not + return !is_null(self::$Media); + } + + + /** + * Add “target” attribute to anchors (links). + * + * @param string $string String to format + * @return string Formatted string + */ + private function tLinks($string) + { + if(!class_exists('\DOMDocument')) { + return $string; + } + try { + $dom = new \DOMDocument('1.0'); + $dom->loadHTML(''.$string.''); + foreach($dom->getElementsByTagName('a') as $link) { + $link->setAttribute('target', '_blank'); + } + $body = $dom->getElementsByTagName('body')->item(0); + $string = $dom->saveHTML($body); + + return trim(substr($string, 6, strlen($string) - 13)); + } + catch(\Exception $e) { + return $string; + } + } + + + /** + * Handle custom formatting syntax. + * + * @Deprecated + * @param string $string String to format + * @return string Formatted string + */ + private function tCustom($string) + { + // Important text + $string = str_replace('[strong]', '', $string); + $string = str_replace('[/strong]', '', $string); + + // Create tables + $string = preg_replace('/(\[table\])\s+/u', '$1', $string); + $string = preg_replace('/\s*(\[tr\])\s*/u', '$1', $string); + $string = preg_replace('%\s+(\[/table\])%u', '$1', $string); + $string = preg_replace('%\s*(\[/tr\])\s*%u', '$1', $string); + $string = str_replace('[table]', '

', $string); + $string = str_replace('[/table]', '

', $string); + $string = str_replace('[tr]', '', $string); + $string = str_replace('[/tr]', '', $string); + $string = str_replace('[th]', '', $string); + $string = str_replace('[/th]', '', $string); + $string = str_replace('[td]', '', $string); + $string = str_replace('[/td]', '', $string); + + + // Return new string + return $string; + } + + + /** + * Handle including Seminarymedia. + * + * @param string $string String to format + * @return string Formatted string + */ + private function tSeminarymedia($string) + { + $seminarymedia = array(); + preg_match_all('/\[seminarymedia:(\d+)\]/iu', $string, $matches); //, PREG_SET_ORDER | PREG_OFFSET_CAPTURE); + $seminarymediaIds = array_unique($matches[1]); + foreach($seminarymediaIds as &$seminarymediaId) + { + $replacement = null; + if(!is_null(\hhu\z\controllers\SeminaryController::$seminary) && $this->loadMediaModel()) + { + try { + $medium = self::$Media->getSeminaryMediaById($seminarymediaId); + $replacement = sprintf( + '%s', + $this->linker->link(array('media','seminary', \hhu\z\controllers\SeminaryController::$seminary['url'],$medium['url'])), + $medium['description'] + ); + } + catch(\nre\exceptions\IdNotFoundException $e) { + } + } + + $seminarymedia[$seminarymediaId] = $replacement; + } + foreach($seminarymedia as $seminarymediaId => $replacement) { + $string = str_replace("[seminarymedia:$seminarymediaId]", $replacement, $string); + } + + + // Return new string + return $string; + } + + + } + +?> diff --git a/app/Utils.inc b/app/Utils.inc new file mode 100644 index 00000000..0aae181b --- /dev/null +++ b/app/Utils.inc @@ -0,0 +1,239 @@ + + * @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; + + + /** + * Class for implementing utility methods. + * + * @author Oliver Hanraths + */ + class Utils + { + /** + * String length for hashes + * + * @var int + */ + const HASH_LENGTH = 10; + + + + + /** + * Mask HTML-chars for save output. + * + * @static + * @param string $string String to be masked + * @return string Masked string + */ + public static function t($string) + { + return nl2br(htmlspecialchars($string)); + } + + + /** + * ‚htmlspecialchars‘ with support for UTF-8. + * + * @static + * @param string $string String to be masked + * @return string Masked string + */ + public static function htmlspecialchars_utf8($string) + { + return htmlspecialchars($string, ENT_COMPAT, 'UTF-8'); + } + + + /** + * Cut a string to the given length but only word boundaries. + * + * @static + * @param string $string String to cut + * @param int $length Length to cut string + * @param int $scope Maximum length to cut string regardless word boundaries + * @return string Cutted string + */ + public static function shortenString($string, $length, $scope) + { + // Determine length + $length = min($length, strlen($string)); + + // Look for word boundary + if(($pos = strpos($string, ' ', $length)) !== false) + { + // Check if boundary is outside of scope + if($pos > $length + $scope) { + $pos = strrpos(substr($string, 0, $pos), ' '); + } + } + else { + $pos = strlen($string); + } + + + // Cut string and return it + return substr($string, 0, $pos); + } + + + /** + * Send an e‑mail. + * + * @throws \hhu\z\exceptions\MailingException + * @param mixed $to One (string) or many (array) receivers + * @param string $messageAction Message Action + * @param boolean $html Whether mail should be formatted as HTML or not + * @param array $params Parameters to pass + * @param \nre\core\Linker $linker Linker instance + */ + public static function sendMail($to, $messageAction, $html=false, $params=null, $linker=null) + { + // Check configuration + if( + empty(\nre\configs\AppConfig::$mail['host']) || + empty(\nre\configs\AppConfig::$mail['port']) || + empty(\nre\configs\AppConfig::$mail['username']) + ) { + return; + } + + // Load classes + \hhu\z\lib\PHPMailerAutoload::load(); + \hhu\z\lib\PHPMailer::load(); + \hhu\z\lib\SMTP::load(); + + // Create mailer + $mail = new \PHPMailer(); + + // Configure mailer + $mail->isSMTP(); + $mail->Host = \nre\configs\AppConfig::$mail['host']; + $mail->Port = \nre\configs\AppConfig::$mail['port']; + $mail->SMTPAuth = true; + $mail->Username = \nre\configs\AppConfig::$mail['username']; + $mail->Password = \nre\configs\AppConfig::$mail['password']; + $mail->SMTPSecure = \nre\configs\AppConfig::$mail['secure']; + + // Set properties + $mail->CharSet = 'UTF-8'; + $mail->From = \nre\configs\AppConfig::$app['mailsender']; + $mail->FromName = \nre\configs\AppConfig::$app['name']; + if(!is_array($to)) { + $to = array($to); + } + foreach($to as &$receiver) { + $mail->addAddress($receiver); + } + if($html) { + $mail->isHTML(true); + } + + // Create message + try { + // Create MailApi + $mailApi = new \hhu\z\apis\MailApi(); + if(!is_null($linker)) { + $mailApi->setLinker($linker); + } + $mailApi->setMessage($messageAction); + $mailApi->setParams($params); + if($html) { + $mailApi->setHTML(); + } + + // Render message + $exception = $mailApi->run(); + if(!is_null($exception)) { + return $exception; + } + $mail->Subject = $mailApi->getSubject(); + $mail->Body = $mailApi->render(); + + // Try to render alternativ plaintext message + if($html) + { + $mailApi->setHTML(false); + + // Render message + $exception = $mailApi->run(); + if(is_null($exception)) + { + try { + $mail->AltBody = $mailApi->render(); + } + catch(\nre\core\Exception $e) { + // No alternative plaintext available + } + } + } + } + catch(\nre\core\Exception $e) { + throw new \hhu\z\exceptions\MailingException($e->getMessage()); + } + + + // Return status + if(!$mail->send()) { + throw new \hhu\z\exceptions\MailingException($mail->ErrorInfo); + } + } + + + /** + * Detect Mimetype of a file. + * + * @param string $filename Name of file to detect Mimetype of + * @param string $defaultMimetype Default Mimetype to use + * @return string Detected Mimetype of file + */ + public static function getMimetype($filename, $defaultMimetype=null) + { + $mimetype = (!is_null($defaultMimetype)) ? $defaultMimetype : 'application/octet-stream'; + // Use Fileinfo + if(class_exists('\finfo')) + { + $finfo = new \finfo(FILEINFO_MIME_TYPE); + if(!is_null($finfo)) { + $mimetype = $finfo->file($filename); + } + } + // Use deprecated mime_content_type() + elseif(function_exists('mime_content_type')) { + $mimetype = mime_content_type($filename); + } + + + return $mimetype; + } + + + /** + * Create a random hash string. + * + * @param int Length of string + * @return string String with random characters + */ + public static function createRandomHash($length=self::HASH_LENGTH) + { + // Length of URL + $length = max(0, min(32, $length)); + + + // Create and return random string + return substr(md5(microtime()), rand(0, 32-$length), $length); + } + + } + +?> diff --git a/app/agents/QuesttypeAgent.inc b/app/agents/QuesttypeAgent.inc new file mode 100644 index 00000000..f13d6786 --- /dev/null +++ b/app/agents/QuesttypeAgent.inc @@ -0,0 +1,268 @@ + + * @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; + + + /** + * Abstract class for implementing a QuesttypeAgent. + * + * @author Oliver Hanraths + */ + abstract class QuesttypeAgent extends \nre\agents\BottomlevelAgent + { + /** + * Current request + * + * @var \nre\core\Request + */ + private $request; + /** + * Current response + * + * @var \nre\core\Response + */ + private $response; + + + + + /** + * Load a QuesttypeAgent. + * + * @static + * @throws \hhu\z\exceptions\QuesttypeAgentNotFoundException + * @throws \hhu\z\exceptions\QuesttypeAgentNotValidException + * @param string $questtypeName Name of the QuesttypeAgent to load + */ + public static function load($questtypeName) + { + // Determine full classname + $className = self::getClassName($questtypeName); + + try { + // Load class + static::loadClass($questtypeName, $className); + + // Validate class + static::checkClass($className, get_class()); + } + catch(\nre\exceptions\ClassNotValidException $e) { + throw new \hhu\z\exceptions\QuesttypeAgentNotValidException($e->getClassName()); + } + catch(\nre\exceptions\ClassNotFoundException $e) { + throw new \hhu\z\exceptions\QuesttypeAgentNotFoundException($e->getClassName()); + } + } + + + /** + * Instantiate a QuesttypeAgent (Factory Pattern). + * + * @static + * @throws \nre\exceptions\DatamodelException + * @throws \nre\exceptions\DriverNotValidException + * @throws \nre\exceptions\DriverNotFoundException + * @throws \nre\exceptions\ViewNotFoundException + * @throws \hhu\z\exceptions\QuesttypeModelNotValidException + * @throws \hhu\z\exceptions\QuesttypeModelNotFoundException + * @throws \hhu\z\exceptions\QuesttypeControllerNotValidException + * @throws \hhu\z\exceptions\QuesttypeControllerNotFoundException + * @param string $questtypeName Name of the QuesttypeAgent to instantiate + * @param Request $request Current request + * @param Response $response Current respone + * @param Logger $log Log-system + */ + public static function factory($questtypeName, \nre\core\Request $request, \nre\core\Response $response, \nre\core\Logger $log=null) + { + // Determine full classname + $className = self::getClassName($questtypeName); + + // Construct and return Questmodule + return new $className($request, $response, $log); + } + + + /** + * Determine the Agent-classname for the given Questtype-name. + * + * @static + * @param string $questtypeName Questtype-name to get Agent-classname of + * @param string $agentType Agent type of given Agent name + * @return string Classname for the Questtype-name + */ + private static function getClassName($questtypeName, $agentType=null) + { + $className = \nre\core\ClassLoader::concatClassNames($questtypeName, \nre\core\ClassLoader::stripClassType(\nre\core\ClassLoader::stripNamespace(get_class())), 'agent'); + + + return \nre\configs\AppConfig::$app['namespace']."questtypes\\$className"; + } + + + /** + * Load the class of a QuesttypeAgent. + * + * @static + * @throws \nre\exceptions\ClassNotFoundException + * @param string $questtypeName Name of the QuesttypeAgent to load + * @param string $fullClassName Name of the class to load + */ + private static function loadClass($questtypeName, $fullClassName) + { + // Determine folder to look in + $className = explode('\\', $fullClassName); + $className = array_pop($className); + + // Determine filename + $fileName = ROOT.DS.\nre\configs\AppConfig::$dirs['questtypes'].DS.strtolower($questtypeName).DS.$className.\nre\configs\CoreConfig::getFileExt('includes'); + + // Check file + if(!file_exists($fileName)) + { + throw new \nre\exceptions\ClassNotFoundException( + $fullClassName + ); + } + + // Include file + include_once($fileName); + } + + + /** + * Check inheritance of the QuesttypeAgent-class. + * + * @static + * @throws \nre\exceptions\ClassNotValidException + * @param string $className Name of the class to check + * @param string $parentClassName Name of the parent class + */ + public static function checkClass($className, $parentClassName) + { + // Check if class is subclass of parent class + if(!is_subclass_of($className, $parentClassName)) { + throw new \nre\exceptions\ClassNotValidException( + $className + ); + } + } + + + + + /** + * Construct a new QuesttypeAgent. + * + * @throws \nre\exceptions\DatamodelException + * @throws \nre\exceptions\DriverNotValidException + * @throws \nre\exceptions\DriverNotFoundException + * @throws \nre\exceptions\ViewNotFoundException + * @throws \nre\exceptions\ModelNotValidException + * @throws \nre\exceptions\ModelNotFoundException + * @throws \hhu\z\exceptions\QuesttypeModelNotValidException + * @throws \hhu\z\exceptions\QuesttypeModelNotFoundException + * @throws \hhu\z\exceptions\QuesttypeControllerNotValidException + * @throws \hhu\z\exceptions\QuesttypeControllerNotFoundException + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + * @param \nre\core\Logger $log Log-system + */ + protected function __construct(\nre\core\Request $request, \nre\core\Response $response, \nre\core\Logger $log=null) + { + // Store values + $this->request = $request; + $this->response = $response; + + + // Call parent constructor + parent::__construct($request, $response, $log); + } + + + + + /** + * Save the answers of a Character for a Quest. + * + * @param array $seminary Current Seminary data + * @param array $questgroup Current Questgroup data + * @param array $quest Current Quest data + * @param array $character Current Character data + * @param array $answers Character answers for the Quest + */ + public function saveAnswersOfCharacter($seminary, $questgroup, $quest, $character, $answers) + { + $this->controller->saveAnswersOfCharacter($seminary, $questgroup, $quest, $character, $answers); + } + + + /** + * Check if answers of a Character for a Quest match the correct ones. + * + * @param array $seminary Current Seminary data + * @param array $questgroup Current Questgroup data + * @param array $quest Current Quest data + * @param array $character Current Character data + * @param array $answers Character answers for the Quest + */ + public function matchAnswersOfCharacter($seminary, $questgroup, $quest, $character, $answers) + { + return $this->controller->matchAnswersOfCharacter($seminary, $questgroup, $quest, $character, $answers); + } + + + + + /** + * Load the Controller of this Agent. + * + * @throws \nre\exceptions\DatamodelException + * @throws \nre\exceptions\DriverNotValidException + * @throws \nre\exceptions\DriverNotFoundException + * @throws \nre\exceptions\ViewNotFoundException + * @throws \nre\exceptions\ModelNotValidException + * @throws \nre\exceptions\ModelNotFoundException + * @throws \hhu\z\exceptions\QuesttypeModelNotValidException + * @throws \hhu\z\exceptions\QuesttypeModelNotFoundException + * @throws \hhu\z\exceptions\QuesttypeControllerNotValidException + * @throws \hhu\z\exceptions\QuesttypeControllerNotFoundException + */ + protected function loadController() + { + // Determine Controller name + $controllerName = \nre\core\ClassLoader::stripClassType(\nre\core\ClassLoader::getClassName(get_class($this))); + + // Determine ToplevelAgent + $toplevelAgentName = $this->response->getParam(0); + if(is_null($toplevelAgentName)) { + $toplevelAgentName = $this->request->getParam(0, 'toplevel'); + $this->response->addParam($toplevelAgentName); + } + + // Determine Action + $action = $this->response->getParam(2); + if(is_null($action)) { + $action = $this->request->getParam(2, 'action'); + $this->response->addParam($action); + } + + + // Load Controller + \hhu\z\controllers\QuesttypeController::load($controllerName); + + // Construct Controller + $this->controller = \hhu\z\controllers\QuesttypeController::factory($controllerName, $toplevelAgentName, $action, $this); + } + + } + +?> diff --git a/app/agents/StationtypeAgent.inc b/app/agents/StationtypeAgent.inc new file mode 100644 index 00000000..5598afb5 --- /dev/null +++ b/app/agents/StationtypeAgent.inc @@ -0,0 +1,298 @@ + + * @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; + + + /** + * Abstract class for implementing a StationtypeAgent. + * + * @author Oliver Hanraths + */ + abstract class StationtypeAgent extends \nre\agents\BottomlevelAgent + { + /** + * Current request + * + * @var \nre\core\Request + */ + private $request; + /** + * Current response + * + * @var \nre\core\Response + */ + private $response; + + + + + /** + * Load a StationtypeAgent. + * + * @static + * @throws \hhu\z\exceptions\StationtypeAgentNotFoundException + * @throws \hhu\z\exceptions\StationtypeAgentNotValidException + * @param string $stationtypeName Name of the StationtypeAgent to load + */ + public static function load($stationtypeName) + { + // Determine full classname + $className = self::getClassName($stationtypeName); + + try { + // Load class + static::loadClass($stationtypeName, $className); + + // Validate class + static::checkClass($className, get_class()); + } + catch(\nre\exceptions\ClassNotValidException $e) { + throw new \hhu\z\exceptions\StationtypeAgentNotValidException($e->getClassName()); + } + catch(\nre\exceptions\ClassNotFoundException $e) { + throw new \hhu\z\exceptions\StationtypeAgentNotFoundException($e->getClassName()); + } + } + + + /** + * Instantiate a StationtypeAgent (Factory Pattern). + * + * @static + * @throws \nre\exceptions\DatamodelException + * @throws \nre\exceptions\DriverNotValidException + * @throws \nre\exceptions\DriverNotFoundException + * @throws \nre\exceptions\ViewNotFoundException + * @throws \hhu\z\exceptions\StationtypeModelNotValidException + * @throws \hhu\z\exceptions\StationtypeModelNotFoundException + * @throws \hhu\z\exceptions\StationtypeControllerNotValidException + * @throws \hhu\z\exceptions\StationtypeControllerNotFoundException + * @param string $stationtypeName Name of the StationtypeAgent to instantiate + * @param Request $request Current request + * @param Response $response Current respone + * @param Logger $log Log-system + */ + public static function factory($stationtypeName, \nre\core\Request $request, \nre\core\Response $response, \nre\core\Logger $log=null) + { + // Determine full classname + $className = self::getClassName($stationtypeName); + + // Construct and return Stationmodule + return new $className($request, $response, $log); + } + + + /** + * Determine the Agent-classname for the given Stationtype-name. + * + * @static + * @param string $stationtypeName Stationtype-name to get Agent-classname of + * @param string $agentType Agent type of given Agent name + * @return string Classname for the Stationtype-name + */ + private static function getClassName($stationtypeName, $agentType=null) + { + $className = \nre\core\ClassLoader::concatClassNames( + $stationtypeName, + \nre\core\ClassLoader::stripClassType(\nre\core\ClassLoader::stripNamespace(get_class())), + 'agent' + ); + + + return \nre\configs\AppConfig::$app['namespace']."stationtypes\\$className"; + } + + + /** + * Load the class of a StationtypeAgent. + * + * @static + * @throws \nre\exceptions\ClassNotFoundException + * @param string $stationtypeName Name of the StationtypeAgent to load + * @param string $fullClassName Name of the class to load + */ + private static function loadClass($stationtypeName, $fullClassName) + { + // Determine folder to look in + $className = explode('\\', $fullClassName); + $className = array_pop($className); + + // Determine filename + $fileName = ROOT.DS. + \nre\configs\AppConfig::$dirs['stationtypes'].DS. + strtolower($stationtypeName).DS.$className.\nre\configs\CoreConfig::getFileExt('includes'); + + // Check file + if(!file_exists($fileName)) + { + throw new \nre\exceptions\ClassNotFoundException( + $fullClassName + ); + } + + // Include file + include_once($fileName); + } + + + /** + * Check inheritance of the StationtypeAgent-class. + * + * @static + * @throws \nre\exceptions\ClassNotValidException + * @param string $className Name of the class to check + * @param string $parentClassName Name of the parent class + */ + public static function checkClass($className, $parentClassName) + { + // Check if class is subclass of parent class + if(!is_subclass_of($className, $parentClassName)) { + throw new \nre\exceptions\ClassNotValidException( + $className + ); + } + } + + + + + /** + * Construct a new StationtypeAgent. + * + * @throws \nre\exceptions\DatamodelException + * @throws \nre\exceptions\DriverNotValidException + * @throws \nre\exceptions\DriverNotFoundException + * @throws \nre\exceptions\ViewNotFoundException + * @throws \nre\exceptions\ModelNotValidException + * @throws \nre\exceptions\ModelNotFoundException + * @throws \hhu\z\exceptions\StationtypeModelNotValidException + * @throws \hhu\z\exceptions\StationtypeModelNotFoundException + * @throws \hhu\z\exceptions\StationtypeControllerNotValidException + * @throws \hhu\z\exceptions\StationtypeControllerNotFoundException + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + * @param \nre\core\Logger $log Log-system + */ + protected function __construct(\nre\core\Request $request, \nre\core\Response $response, \nre\core\Logger $log=null) + { + // Store values + $this->request = $request; + $this->response = $response; + + + // Call parent constructor + parent::__construct($request, $response, $log); + } + + + + + /** + * Save the answer of a Character group for a Station. + * + * @param array $seminary Current Seminary data + * @param array $questgroup Current Questgroup data + * @param array $quest Current Quest data + * @param array $station Current Station data + * @param array $group Current Character data + * @param array $answers Character answers for the Quest + */ + public function saveAnswer($seminary, $groupsgroup, $quest, $station, $group, $answer) + { + $this->controller->saveAnswer( + $seminary, + $groupsgroup, + $quest, + $station, + $group, + $answer + ); + } + + + /** + * Check if the answer of a Character group for a Station matches the + * correct one. + * + * @param array $seminary Current Seminary data + * @param array $questgroup Current Questgroup data + * @param array $quest Current Quest data + * @param array $station Current Station data + * @param array $group Current Character group data + * @param array $answers Character answers for the Quest + */ + public function matchAnswer($seminary, $groupsgroup, $quest, $station, $group, $answer) + { + return $this->controller->matchAnswer( + $seminary, + $groupsgroup, + $quest, + $station, + $group, + $answer + ); + } + + + + + /** + * Load the Controller of this Agent. + * + * @throws \nre\exceptions\DatamodelException + * @throws \nre\exceptions\DriverNotValidException + * @throws \nre\exceptions\DriverNotFoundException + * @throws \nre\exceptions\ViewNotFoundException + * @throws \nre\exceptions\ModelNotValidException + * @throws \nre\exceptions\ModelNotFoundException + * @throws \hhu\z\exceptions\StationxuesttypeModelNotValidException + * @throws \hhu\z\exceptions\StationtypeModelNotFoundException + * @throws \hhu\z\exceptions\StationtypeControllerNotValidException + * @throws \hhu\z\exceptions\StationtypeControllerNotFoundException + */ + protected function loadController() + { + // Determine Controller name + $controllerName = \nre\core\ClassLoader::stripClassType( + \nre\core\ClassLoader::getClassName(get_class($this)) + ); + + // Determine ToplevelAgent + $toplevelAgentName = $this->response->getParam(0); + if(is_null($toplevelAgentName)) { + $toplevelAgentName = $this->request->getParam(0, 'toplevel'); + $this->response->addParam($toplevelAgentName); + } + + // Determine Action + $action = $this->response->getParam(2); + if(is_null($action)) { + $action = $this->request->getParam(2, 'action'); + $this->response->addParam($action); + } + + + // Load Controller + \hhu\z\controllers\StationtypeController::load($controllerName); + + // Construct Controller + $this->controller = \hhu\z\controllers\StationtypeController::factory( + $controllerName, + $toplevelAgentName, + $action, + $this + ); + } + + } + +?> diff --git a/app/agents/ToplevelAgent.inc b/app/agents/ToplevelAgent.inc new file mode 100644 index 00000000..10a72d85 --- /dev/null +++ b/app/agents/ToplevelAgent.inc @@ -0,0 +1,43 @@ + + * @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; + + + /** + * Abstract class for implementing an application Controller. + * + * @author Oliver Hanraths + */ + abstract class ToplevelAgent extends \nre\agents\ToplevelAgent + { + + + + + /** + * Construct a new ToplevlAgent + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + * @param \nre\core\Logger $log Logger instance + */ + protected function __construct(\nre\core\Request $request, \nre\core\Response $response, \nre\core\Logger $log=null) + { + parent::__construct($request, $response, $log); + + + // Set timezone + date_default_timezone_set(\nre\configs\AppConfig::$app['timeZone']); + } + } + +?> diff --git a/app/apis/MailApi.inc b/app/apis/MailApi.inc new file mode 100644 index 00000000..bc8dbd1c --- /dev/null +++ b/app/apis/MailApi.inc @@ -0,0 +1,202 @@ + + * @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\apis; + + + /** + * MailApi-implementation. + * + * This class runs and renders e‑mail text and subject. + * + * @author Oliver Hanraths + */ + class MailApi extends \nre\core\Api + { + + + + + /** + * Construct a new MailApi. + */ + public function __construct() + { + parent::__construct( + new \hhu\z\requests\MailRequest(), + new \hhu\z\responses\MailResponse() + ); + + // Set ToplevelAgent + $this->request->addParam(\nre\configs\AppConfig::$defaults['toplevel-mail']); + $this->request->addParam(\nre\configs\AppConfig::$defaults['intermediate-mail']); + } + + + + + /** + * Set linker instance for creating links. + * + * @param \nre\core\Linker $linker Linker instance for creating links + */ + public function setLinker(\nre\core\Linker $linker) + { + $this->request->setLinker($linker); + } + + + /** + * Use a ToplevelAgent for HTML-mail + * + * @param bool $html Whether to use HTML or not + */ + public function setHTML($html=true) + { + // Save params + $params = $this->request->getParams(1); + + // Set ToplevelAgent + $this->request->clearParams(); + if($html) { + $this->request->addParam(\nre\configs\AppConfig::$defaults['toplevel-htmlmail']); + } + else { + $this->request->addParam(\nre\configs\AppConfig::$defaults['toplevel-mail']); + } + + // Restore params + if(!empty($params)) { + $this->addParams($params); + } + } + + + /** + * Set the Action for the message to render. + * + * @param string $messageAgent Agent to handle the message + */ + public function setMessage($messageAgent) + { + // Save params + $params = $this->request->getParams(3); + + // Set messageAgent + $this->request->clearParams(2); + $this->request->addParam($messageAgent); + + // Restore params + if(!empty($params)) { + $this->addParams($params); + } + } + + + /** + * Set additional params to pass to the Action. + * + * @param array $params Additional params to set + */ + public function setParams($params) + { + // Add placeholder params + for($i=3; $irequest->getParams()); $i++) { + $this->request->addParam(null); + } + + // Set params + call_user_func_array( + array( + $this->request, + 'addParams' + ), + $params + ); + } + + + /** + * Return the subject set by the Controller. + * + * @return string Subject set by Controller + */ + public function getSubject() + { + return $this->response->getSubject(); + } + + + /** + * Run mailtext generation. + * + * This method runs the generation of mailtext. + * + * @return \Exception Occured exception or null + */ + public function run() + { + // Set response + $this->response->clearParams(); + foreach($this->request->getParams() as $param) { + $this->response->addParam($param); + } + + // Run + try { + $exception = parent::run(); + + + return $exception; + } + catch(\nre\Exception $e) { + return $e; + } + } + + + /** + * Render output. + * + * @return string Rendered output + */ + public function render() + { + // Generate output + parent::render(); + + + // Return output + return $this->response->getOutput(); + } + + + + + /** + * Add multiple request params. + * + * @param array $params Request params to add + */ + private function addParams($params) + { + call_user_func_array( + array( + $this->request, + 'addParams' + ), + $params + ); + } + + } + +?> diff --git a/app/controllers/IntermediateController.inc b/app/controllers/IntermediateController.inc new file mode 100644 index 00000000..923bc1b3 --- /dev/null +++ b/app/controllers/IntermediateController.inc @@ -0,0 +1,197 @@ + + * @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; + + + /** + * Abstract class for implementing a Controller of an IntermediateAgent. + * + * @author Oliver Hanraths + */ + abstract class IntermediateController extends \hhu\z\Controller + { + /** + * Required models + * + * @var array + */ + public $models = array('users', 'userroles', 'seminaries', 'characters'); + /** + * Current user + * + * @var array + */ + public static $user = null; + /** + * Title information + * + * @var array + */ + private $title = array(); + + + + + /** + * Construct a new IntermediateController. + * + * @throws \nre\exceptions\DriverNotFoundException + * @throws \nre\exceptions\DriverNotValidException + * @throws \nre\exceptions\ModelNotValidException + * @throws \nre\exceptions\ModelNotFoundException + * @throws \nre\exceptions\ViewNotFoundException + * @param string $layoutName Name of the current Layout + * @param string $action Current Action + * @param \nre\core\Agent $agent Corresponding Agent + */ + public function __construct($layoutName, $action, $agent) + { + parent::__construct($layoutName, $action, $agent); + } + + + + /** + * Prefilter that is executed before running the Controller. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function preFilter(\nre\core\Request $request, \nre\core\Response $response) + { + parent::preFilter($request, $response); + + // Get userdata + try { + self::$user = $this->Users->getUserById($this->Auth->getUserId()); + self::$user['roles'] = array_map(function($r) { return $r['name']; }, $this->Userroles->getUserrolesForUserById(self::$user['id'])); + } + catch(\nre\exceptions\IdNotFoundException $e) { + } + + // Check permissions + $this->checkPermission($request, $response); + + // Set userdata + $this->set('loggedUser', self::$user); + } + + + /** + * Postfilter that is executed after running the Controller. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function postFilter(\nre\core\Request $request, \nre\core\Response $response) + { + parent::postFilter($request, $response); + } + + + /** + * Return current title information. + * + * @return string Title information + */ + public function getTitle() + { + return $this->title; + } + + + + + /** + * Add a piece of information to the current title. + * + * @param string $title Title information + */ + protected function addTitle($title) + { + $this->title[] = $title; + } + + + /** + * Add a piece of information to the current title and localize + * it. + * + * @param string $title Title information + */ + protected function addTitleLocalized($title) + { + $title = gettext($title); + + $args = func_get_args(); + if(count($args) > 0) { + $title = call_user_func_array( + 'sprintf', + array_merge( + array($title), + array_slice($args, 1) + ) + ); + } + + + $this->title[] = $title; + } + + + + + /** + * Check user permissions. + * + * @throws \nre\exceptions\AccessDeniedException + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + private function checkPermission(\nre\core\Request $request, \nre\core\Response $response) + { + // Determine user + $userRoles = array('guest'); + if(!is_null(self::$user)) { + $userRoles = self::$user['roles']; + } + + + // Do not check error pages + if($response->getParam(0, 'toplevel') == \nre\core\Config::getDefault('toplevel-error')) { + return; + } + if($response->getParam(1, 'intermediate') == \nre\core\Config::getDefault('intermediate-error')) { + return; + } + + // Determine permissions of Intermediate Controller for current action + $controller = $this->agent->controller; + $action = $this->request->getParam(2, 'action'); + if(!property_exists($controller, 'permissions')) { + return; // Allow if nothing is specified + } + if(!array_key_exists($action, $controller->permissions)) { + return; // Allow if Action is not specified + } + $permissions = $controller->permissions[$action]; + + + // Check permissions + if(count(array_intersect($userRoles, $permissions)) == 0) { + throw new \nre\exceptions\AccessDeniedException(); + } + } + + } + +?> diff --git a/app/controllers/QuesttypeController.inc b/app/controllers/QuesttypeController.inc new file mode 100644 index 00000000..50eaac2d --- /dev/null +++ b/app/controllers/QuesttypeController.inc @@ -0,0 +1,320 @@ + + * @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; + + + /** + * Abstract class for implementing a QuesttypeController. + * + * @author Oliver Hanraths + */ + abstract class QuesttypeController extends \hhu\z\Controller + { + /** + * Required models + * + * @var array + */ + public $models = array('seminaries', 'questgroups', 'quests', 'characters'); + + + + + /** + * Save the answers of a Character for a Quest. + * + * @param array $seminary Current Seminary data + * @param array $questgroup Current Questgroup data + * @param array $quest Current Quest data + * @param array $character Current Character data + * @param array $answers Character answers for the Quest + */ + public abstract function saveAnswersOfCharacter($seminary, $questgroup, $quest, $character, $answers); + + + /** + * Save additional data for the answers of a Character for a Quest. + * + * @param array $seminary Current Seminary data + * @param array $questgroup Current Questgroup data + * @param array $quest Current Quest data + * @param array $character Current Character data + * @param array $data Additional (POST-) data + */ + public abstract function saveDataForCharacterAnswers($seminary, $questgroup, $quest, $character, $data); + + + /** + * Check if answers of a Character for a Quest match the correct ones. + * + * @param array $seminary Current Seminary data + * @param array $questgroup Current Questgroup data + * @param array $quest Current Quest data + * @param array $character Current Character data + * @param array $answers Character answers for the Quest + * @return boolean True/false for a right/wrong answer or null for moderator evaluation + */ + public abstract function matchAnswersOfCharacter($seminary, $questgroup, $quest, $character, $answers); + + + /** + * Action: quest. + * + * Show the task of a Quest. + * + * @param array $seminary Current Seminary data + * @param array $questgroup Current Questgroup data + * @param array $quest Current Quest data + * @param array $character Current Character data + * @param \Exception $exception Character submission exception + */ + public abstract function quest($seminary, $questgroup, $quest, $character, $exception); + + + /** + * Action: submission. + * + * Show the submission of a Character for a Quest. + * + * @param array $seminary Current Seminary data + * @param array $questgroup Current Questgroup data + * @param array $quest Current Quest data + * @param array $character Current Character data + */ + public abstract function submission($seminary, $questgroup, $quest, $character); + + + /** + * Action: edittask. + * + * Edit the task of a Quest. + * + * @param array $seminary Current Seminary data + * @param array $questgroup Current Questgroup data + * @param array $quest Current Quest data + */ + public abstract function edittask($seminary, $questgroup, $quest); + + + + + /** + * Load a QuesttypeController. + * + * @static + * @throws \hhu\z\exceptions\QuesttypeControllerNotFoundException + * @throws \hhu\z\exceptions\QuesttypeControllerNotValidException + * @param string $controllerName Name of the QuesttypeController to load + */ + public static function load($controllerName) + { + // Determine full classname + $className = self::getClassName($controllerName); + + try { + // Load class + static::loadClass($controllerName, $className); + + // Validate class + static::checkClass($className, get_class()); + } + catch(\nre\exceptions\ClassNotValidException $e) { + throw new \hhu\z\exceptions\QuesttypeControllerNotValidException($e->getClassName()); + } + catch(\nre\exceptions\ClassNotFoundException $e) { + throw new \hhu\z\exceptions\QuesttypeControllerNotFoundException($e->getClassName()); + } + } + + + /** + * Instantiate a QuesttypeController (Factory Pattern). + * + * @static + * @throws \nre\exceptions\DatamodelException + * @throws \nre\exceptions\DriverNotFoundException + * @throws \nre\exceptions\DriverNotValidException + * @throws \nre\exceptions\ModelNotValidException + * @throws \nre\exceptions\ModelNotFoundException + * @throws \nre\exceptions\ViewNotFoundException + * @throws \hhu\z\exceptions\QuesttypeModelNotValidException + * @throws \hhu\z\exceptions\QuesttypeModelNotFoundException + * @param string $controllerName Name of the QuesttypeController to instantiate + * @param string $layoutName Name of the current Layout + * @param string $action Current Action + * @param \nre\core\Agent $agent Corresponding Agent + */ + public static function factory($controllerName, $layoutName, $action, $agent) + { + // Determine full classname + $className = self::getClassName($controllerName); + + // Construct and return Controller + return new $className($layoutName, $action, $agent); + } + + + /** + * Determine the Controller-classname for the given Questtype-name. + * + * @static + * @param string $questtypeName Questtype-name to get Controller-classname of + * @return string Classname for the Questtype-name + */ + private static function getClassName($questtypeName) + { + $className = \nre\core\ClassLoader::concatClassNames($questtypeName, \nre\core\ClassLoader::stripClassType(\nre\core\ClassLoader::stripNamespace(get_class())), 'controller'); + + + return \nre\configs\AppConfig::$app['namespace']."questtypes\\$className"; + } + + + /** + * Load the class of a QuesttypeController + * + * @static + * @throws \nre\exceptions\ClassNotFoundException + * @param string $questtypeName Name of the QuesttypeController to load + * @param string $fullClassName Name of the class to load + */ + private static function loadClass($questtypeName, $fullClassName) + { + // Determine folder to look in + $className = explode('\\', $fullClassName); + $className = array_pop($className); + + // Determine filename + $fileName = ROOT.DS.\nre\configs\AppConfig::$dirs['questtypes'].DS.strtolower($questtypeName).DS.$className.\nre\configs\CoreConfig::getFileExt('includes'); + + // Check file + if(!file_exists($fileName)) + { + throw new \nre\exceptions\ClassNotFoundException( + $fullClassName + ); + } + + // Include file + include_once($fileName); + } + + + /** + * Check inheritance of the QuesttypeController-class. + * + * @static + * @throws \nre\exceptions\ClassNotValidException + * @param string $className Name of the class to check + * @param string $parentClassName Name of the parent class + */ + public static function checkClass($className, $parentClassName) + { + // Check if class is subclass of parent class + if(!is_subclass_of($className, $parentClassName)) { + throw new \nre\exceptions\ClassNotValidException( + $className + ); + } + } + + + + + /** + * Construct a new application Controller. + * + * @throws \nre\exceptions\DriverNotFoundException + * @throws \nre\exceptions\DriverNotValidException + * @throws \nre\exceptions\ModelNotValidException + * @throws \nre\exceptions\ModelNotFoundException + * @throws \nre\exceptions\ViewNotFoundException + * @throws \hhu\z\exceptions\QuesttypeModelNotValidException + * @throws \hhu\z\exceptions\QuesttypeModelNotFoundException + * @param string $layoutName Name of the current Layout + * @param string $action Current Action + * @param Agent $agent Corresponding Agent + */ + public function __construct($layoutName, $action, $agent) + { + parent::__construct($layoutName, $action, $agent); + } + + + + + /** + * Load the Models of this Controller. + * + * @throws \nre\exceptions\DatamodelException + * @throws \nre\exceptions\DriverNotFoundException + * @throws \nre\exceptions\DriverNotValidException + * @throws \nre\exceptions\ModelNotValidException + * @throws \nre\exceptions\ModelNotFoundException + * @throws \hhu\z\exceptions\QuesttypeModelNotValidException + * @throws \hhu\z\exceptions\QuesttypeModelNotFoundException + */ + protected function loadModels() + { + // Load default models + parent::loadModels(); + + // Load QuesttypeModel + $this->loadModel(); + } + + + /** + * Load the Model of the Questtype. + * + * @throws \hhu\z\exceptions\QuesttypeModelNotValidException + * @throws \hhu\z\exceptions\QuesttypeModelNotFoundException + */ + private function loadModel() + { + // Determine Model + $model = \nre\core\ClassLoader::stripClassType(\nre\core\ClassLoader::stripClassType(\nre\core\ClassLoader::stripNamespace(get_class($this)))); + + // Load class + \hhu\z\models\QuesttypeModel::load($model); + + // Construct Model + $modelName = ucfirst(strtolower($model)); + $this->$modelName = \hhu\z\models\QuesttypeModel::factory($model); + } + + + /** + * Load the View of this QuesttypeController. + * + * @throws \nre\exceptions\ViewNotFoundException + * @param string $layoutName Name of the current Layout + * @param string $action Current Action + */ + protected function loadView($layoutName, $action) + { + // Check Layout name + if(is_null($layoutName)) { + return; + } + + // Determine controller name + $controllerName = \nre\core\ClassLoader::stripClassType(\nre\core\ClassLoader::getClassName(get_class($this))); + + + // Load view + $this->view = \hhu\z\views\QuesttypeView::loadAndFactory($layoutName, $controllerName, $action); + } + + } + +?> diff --git a/app/controllers/SeminaryController.inc b/app/controllers/SeminaryController.inc new file mode 100644 index 00000000..37036f3c --- /dev/null +++ b/app/controllers/SeminaryController.inc @@ -0,0 +1,202 @@ + + * @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; + + + /** + * Abstract class for implementing a Controller for a Seminary and its + * concepts. + * + * @author Oliver Hanraths + */ + abstract class SeminaryController extends \hhu\z\controllers\IntermediateController + { + /** + * Required components + * + * @var array + */ + public $components = array('achievement', 'auth', 'notification'); + /** + * Required models + * + * @var array + */ + public $models = array('seminaries', 'characters', 'characterroles', 'xplevels', 'avatars', 'achievements', 'charactertitles'); + /** + * Current Seminary + * + * var array + */ + public static $seminary = null; + /** + * Character of current user and Seminary + * + * @var array + */ + public static $character = null; + + + + + /** + * Construct a new Seminary Controller. + * + * @throws \nre\exceptions\DriverNotFoundException + * @throws \nre\exceptions\DriverNotValidException + * @throws \nre\exceptions\ModelNotValidException + * @throws \nre\exceptions\ModelNotFoundException + * @throws \nre\exceptions\ViewNotFoundException + * @param string $layoutName Name of the current Layout + * @param string $action Current Action + * @param \nre\core\Agent $agent Corresponding Agent + */ + public function __construct($layoutName, $action, $agent) + { + parent::__construct($layoutName, $action, $agent); + } + + + + /** + * Prefilter that is executed before running the Controller. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function preFilter(\nre\core\Request $request, \nre\core\Response $response) + { + parent::preFilter($request, $response); + + // Get Seminary and Character data + try { + self::$seminary = $this->Seminaries->getSeminaryByUrl($this->request->getParam(3)); + if(!is_null(self::$user)) + { + self::$character = $this->Characters->getCharacterForUserAndSeminary(self::$user['id'], self::$seminary['id']); + self::$character['characterroles'] = array_map(function($r) { return $r['name']; }, $this->Characterroles->getCharacterrolesForCharacterById(self::$character['id'])); + try { + self::$character['xplevel'] = $this->Xplevels->getXPLevelById(self::$character['xplevel_id']); + self::$character['avatar'] = $this->Avatars->getAvatarByTypeAndLevel(self::$seminary['id'], self::$character['charactertype_url'], self::$character['xplevel']['level']); + } + catch(\nre\exceptions\IdNotFoundException $e) { + // No Avatar available + } + if(!is_null(self::$character['charactertitle_id']) && !is_null(self::$character['gender'])) + { + $title = $this->Charactertitles->getTitleById(self::$character['charactertitle_id']); + self::$character['title'] = $title[(self::$character['gender']) ? 'title_male' : 'title_female']; + } + } + } + catch(\nre\exceptions\IdNotFoundException $e) { + } + + // Check permissions + $this->checkPermission($request, $response); + + // Check achievements + $this->checkAchievements($request, 'date'); + $this->checkAchievements($request, 'achievement'); + + // Set Seminary and Character data + $this->set('loggedSeminary', self::$seminary); + $this->set('loggedCharacter', self::$character); + } + + + /** + * Postfilter that is executed after running the Controller. + * + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + public function postFilter(\nre\core\Request $request, \nre\core\Response $response) + { + parent::postFilter($request, $response); + } + + + + /** + * Check user permissions. + * + * @throws AccessDeniedException + * @param \nre\core\Request $request Current request + * @param \nre\core\Response $response Current response + */ + private function checkPermission(\nre\core\Request $request, \nre\core\Response $response) + { + // Do not check index page + if(is_null($request->getParam(3))) { + return; + } + + + // Determine permissions for current action + $action = $this->request->getParam(2, 'action'); + if(!property_exists($this, 'seminaryPermissions')) { + return; // Allow if nothing is specified + } + if(!array_key_exists($action, $this->seminaryPermissions)) { + return; // Allow if Action is not specified + } + $permissions = $this->seminaryPermissions[$action]; + + + // Check permissions + if(is_null(self::$character) || !array_key_exists('characterroles', self::$character) || count(array_intersect(self::$character['characterroles'], $permissions)) == 0) { + throw new \nre\exceptions\AccessDeniedException(); + } + } + + + /** + * Check for newly achieved Achievements. + * + * @param \nre\core\Request $request Current request + * @param array $checkConditions Conditions to check + */ + protected function checkAchievements(\nre\core\Request $request, $checkConditions=null) + { + // Do not check MediaController + if($request->getParam(0, 'toplevel') != \nre\configs\AppConfig::$defaults['toplevel']) { + return; + } + + // Check if Character is present + if(is_null(self::$character)) { + return; + } + + // Check Achievements + $achievements = $this->Achievement->checkAchievements( + self::$seminary['id'], + self::$character['id'], + $checkConditions + ); + + // Add notifications + foreach($achievements as &$achievement) + { + $this->Notification->addNotification( + \hhu\z\controllers\components\NotificationComponent::TYPE_ACHIEVEMENT, + $achievement['title'], + $this->linker->link(array('achievements', 'index', self::$seminary['url']), 0, true, null, true, $achievement['url']), + (!is_null($achievement['achieved_achievementsmedia_id']) ? $this->linker->link(array('media','achievement',self::$seminary['url'],$achievement['url'])) : null) + ); + } + } + + } + +?> diff --git a/app/controllers/StationtypeController.inc b/app/controllers/StationtypeController.inc new file mode 100644 index 00000000..fbf48ba4 --- /dev/null +++ b/app/controllers/StationtypeController.inc @@ -0,0 +1,320 @@ + + * @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; + + + /** + * Abstract class for implementing a StationtypeController. + * + * @author Oliver Hanraths + */ + abstract class StationtypeController extends \hhu\z\Controller + { + /** + * Required models + * + * @var array + */ + public $models = array('seminaries'); + + + + + + /** + * Save the answer of a Character group for a Station. + * + * @param array $seminary Current Seminary data + * @param array $groupsgroup Current Groups group data + * @param array $quest Current Quest data + * @param array $station Current Station data + * @param array $charactergroup Current Character group data + * @param array $answer Character group answer for the Station + */ + public abstract function saveAnswer($seminary, $groupsgroup, $quest, $station, $charactergroup, $answer); + + + /** + * Check if answer of a Character group for a Station matches the correct one. + * + * @param array $seminary Current Seminary data + * @param array $groupsgroup Current Groups group data + * @param array $quest Current Quest data + * @param array $station Current Station data + * @param array $charactergroup Current Character group data + * @param array $answer Character group answer for the Station + * @return boolean True/false for a right/wrong answer + */ + public abstract function matchAnswer($seminary, $groupsgroup, $quest, $station, $charactergroup, $answer); + + + /** + * Action: quest. + * + * Show the task of a Station. + * + * @param array $seminary Current Seminary data + * @param array $groupsgroup Current Groups group data + * @param array $quest Current Quest data + * @param array $station Current Station data + * @param array $charactergroup Current Character group data + */ + public abstract function quest($seminary, $groupsgroup, $quest, $station, $charactergroup); + + + /** + * Action: edittask. + * + * Edit the task of a Station. + * + * @param array $seminary Current Seminary data + * @param array $groupsgroup Current Groups group data + * @param array $quest Current Quest data + * @param array $station Current Station data + */ + public abstract function edittask($seminary, $groupsgroup, $quest, $station); + + + + + /** + * Load a StationtypeController. + * + * @static + * @throws \hhu\z\exceptions\StationtypeControllerNotFoundException + * @throws \hhu\z\exceptions\StationtypeControllerNotValidException + * @param string $controllerName Name of the StationtypeController to load + */ + public static function load($controllerName) + { + // Determine full classname + $className = self::getClassName($controllerName); + + try { + // Load class + static::loadClass($controllerName, $className); + + // Validate class + static::checkClass($className, get_class()); + } + catch(\nre\exceptions\ClassNotValidException $e) { + throw new \hhu\z\exceptions\StationtypeControllerNotValidException($e->getClassName()); + } + catch(\nre\exceptions\ClassNotFoundException $e) { + throw new \hhu\z\exceptions\StationtypeControllerNotFoundException($e->getClassName()); + } + } + + + /** + * Instantiate a StationtypeController (Factory Pattern). + * + * @static + * @throws \nre\exceptions\DatamodelException + * @throws \nre\exceptions\DriverNotFoundException + * @throws \nre\exceptions\DriverNotValidException + * @throws \nre\exceptions\ModelNotValidException + * @throws \nre\exceptions\ModelNotFoundException + * @throws \nre\exceptions\ViewNotFoundException + * @throws \hhu\z\exceptions\StationtypeModelNotValidException + * @throws \hhu\z\exceptions\StationtypeModelNotFoundException + * @param string $controllerName Name of the StationtypeController to instantiate + * @param string $layoutName Name of the current Layout + * @param string $action Current Action + * @param \nre\core\Agent $agent Corresponding Agent + */ + public static function factory($controllerName, $layoutName, $action, $agent) + { + // Determine full classname + $className = self::getClassName($controllerName); + + // Construct and return Controller + return new $className($layoutName, $action, $agent); + } + + + /** + * Determine the Controller-classname for the given Stationtype-name. + * + * @static + * @param string $stationtypeName Stationtype-name to get Controller-classname of + * @return string Classname for the Stationtype-name + */ + private static function getClassName($stationtypeName) + { + $className = \nre\core\ClassLoader::concatClassNames( + $stationtypeName, + \nre\core\ClassLoader::stripClassType(\nre\core\ClassLoader::stripNamespace(get_class())), + 'controller' + ); + + + return \nre\configs\AppConfig::$app['namespace']."stationtypes\\$className"; + } + + + /** + * Load the class of a StationtypeController + * + * @static + * @throws \nre\exceptions\ClassNotFoundException + * @param string $stationtypeName Name of the StationtypeController to load + * @param string $fullClassName Name of the class to load + */ + private static function loadClass($stationtypeName, $fullClassName) + { + // Determine folder to look in + $className = explode('\\', $fullClassName); + $className = array_pop($className); + + // Determine filename + $fileName = ROOT.DS. + \nre\configs\AppConfig::$dirs['stationtypes'].DS. + strtolower($stationtypeName).DS. + $className.\nre\configs\CoreConfig::getFileExt('includes'); + + // Check file + if(!file_exists($fileName)) + { + throw new \nre\exceptions\ClassNotFoundException( + $fullClassName + ); + } + + // Include file + include_once($fileName); + } + + + /** + * Check inheritance of the StationtypeController-class. + * + * @static + * @throws \nre\exceptions\ClassNotValidException + * @param string $className Name of the class to check + * @param string $parentClassName Name of the parent class + */ + public static function checkClass($className, $parentClassName) + { + // Check if class is subclass of parent class + if(!is_subclass_of($className, $parentClassName)) { + throw new \nre\exceptions\ClassNotValidException( + $className + ); + } + } + + + + + /** + * Construct a new application Controller. + * + * @throws \nre\exceptions\DriverNotFoundException + * @throws \nre\exceptions\DriverNotValidException + * @throws \nre\exceptions\ModelNotValidException + * @throws \nre\exceptions\ModelNotFoundException + * @throws \nre\exceptions\ViewNotFoundException + * @throws \hhu\z\exceptions\StationtypeModelNotValidException + * @throws \hhu\z\exceptions\StationtypeModelNotFoundException + * @param string $layoutName Name of the current Layout + * @param string $action Current Action + * @param Agent $agent Corresponding Agent + */ + public function __construct($layoutName, $action, $agent) + { + parent::__construct($layoutName, $action, $agent); + } + + + + + /** + * Load the Models of this Controller. + * + * @throws \nre\exceptions\DatamodelException + * @throws \nre\exceptions\DriverNotFoundException + * @throws \nre\exceptions\DriverNotValidException + * @throws \nre\exceptions\ModelNotValidException + * @throws \nre\exceptions\ModelNotFoundException + * @throws \hhu\z\exceptions\StationtypeModelNotValidException + * @throws \hhu\z\exceptions\StationtypeModelNotFoundException + */ + protected function loadModels() + { + // Load default models + parent::loadModels(); + + // Load StationtypeModel + $this->loadModel(); + } + + + /** + * Load the Model of the Stationtype. + * + * @throws \hhu\z\exceptions\StationtypeModelNotValidException + * @throws \hhu\z\exceptions\StationtypeModelNotFoundException + */ + private function loadModel() + { + // Determine Model + $model = \nre\core\ClassLoader::stripClassType( + \nre\core\ClassLoader::stripClassType( + \nre\core\ClassLoader::stripNamespace( + get_class($this) + ) + ) + ); + + // Load class + \hhu\z\models\StationtypeModel::load($model); + + // Construct Model + $modelName = ucfirst(strtolower($model)); + $this->$modelName = \hhu\z\models\StationtypeModel::factory($model); + } + + + /** + * Load the View of this StationtypeController. + * + * @throws \nre\exceptions\ViewNotFoundException + * @param string $layoutName Name of the current Layout + * @param string $action Current Action + */ + protected function loadView($layoutName, $action) + { + // Check Layout name + if(is_null($layoutName)) { + return; + } + + // Determine controller name + $controllerName = \nre\core\ClassLoader::stripClassType( + \nre\core\ClassLoader::getClassName( + get_class($this) + ) + ); + + + // Load view + $this->view = \hhu\z\views\StationtypeView::loadAndFactory( + $layoutName, + $controllerName, + $action + ); + } + + } + +?> diff --git a/app/exceptions/FileCopyException.inc b/app/exceptions/FileCopyException.inc new file mode 100644 index 00000000..485428ff --- /dev/null +++ b/app/exceptions/FileCopyException.inc @@ -0,0 +1,79 @@ + + * @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\exceptions; + + + /** + * Exception: File copy went wrong + * + * @author Oliver Hanraths + */ + class FileCopyException extends \nre\core\Exception + { + /** + * Error code + * + * @var int + */ + const CODE = 204; + /** + * Error message + * + * @var string + */ + const MESSAGE = 'File copy went wrong'; + + /** + * Nested error + * + * @var array + */ + private $nestedError; + + + + + /** + * Construct a new exception. + * + * @param array $nestedError Nested error + * @param string $message Error message + * @param int $code Error code + */ + function __construct($nestedError, $message=self::MESSAGE, $code=self::CODE) + { + parent::__construct( + $message, + $code, + $nestedError['message'] + ); + + // Store values + $this->nestedError = $nestedError; + } + + + + + /** + * Get nested error. + * + * @return Nested error + */ + public function getNestedError() + { + return $this->nestedError; + } + + } + +?> diff --git a/app/exceptions/FileUploadException.inc b/app/exceptions/FileUploadException.inc new file mode 100644 index 00000000..340bd61a --- /dev/null +++ b/app/exceptions/FileUploadException.inc @@ -0,0 +1,79 @@ + + * @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\exceptions; + + + /** + * Exception: File upload went wrong + * + * @author Oliver Hanraths + */ + class FileUploadException extends \nre\core\Exception + { + /** + * Error code + * + * @var int + */ + const CODE = 203; + /** + * Error message + * + * @var string + */ + const MESSAGE = 'File upload went wrong'; + + /** + * Nested message + * + * @var string + */ + private $nestedMessage; + + + + + /** + * Construct a new exception. + * + * @param string $nestedMessage Nested message + * @param string $message Error message + * @param int $code Error code + */ + function __construct($nestedMessage=null, $message=self::MESSAGE, $code=self::CODE) + { + parent::__construct( + $message, + $code, + $nestedMessage + ); + + // Store values + $this->nestedMessage = $nestedMessage; + } + + + + + /** + * Get nested message. + * + * @return Nested message + */ + public function getNestedMessage() + { + return $this->nestedMessage; + } + + } + +?> diff --git a/app/exceptions/MailingException.inc b/app/exceptions/MailingException.inc new file mode 100644 index 00000000..a6ff9736 --- /dev/null +++ b/app/exceptions/MailingException.inc @@ -0,0 +1,79 @@ + + * @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\exceptions; + + + /** + * Exception during sending of an e‑mail. + * + * @author Oliver Hanraths + */ + class MailingException extends \nre\core\Exception + { + /** + * Error code + * + * @var int + */ + const CODE = 300; + /** + * Error message + * + * @var string + */ + const MESSAGE = 'Error sending e‑mail'; + + /** + * Nested error message + * + * @var string + */ + private $error; + + + + + /** + * Construct a new exception. + * + * @param int $error Nested error message + * @param string $message Error message + * @param int $code Error code + */ + function __construct($error, $message=self::MESSAGE, $code=self::CODE) + { + parent::__construct( + $message, + $code, + $error + ); + + // Store values + $this->error = $error; + } + + + + + /** + * Get nested error message. + * + * @return string Nested error message + */ + public function getError() + { + return $this->error; + } + + } + +?> diff --git a/app/exceptions/MaxFilesizeException.inc b/app/exceptions/MaxFilesizeException.inc new file mode 100644 index 00000000..0de53993 --- /dev/null +++ b/app/exceptions/MaxFilesizeException.inc @@ -0,0 +1,54 @@ + + * @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\exceptions; + + + /** + * Exception: File exceeds size maximum. + * + * @author Oliver Hanraths + */ + class MaxFilesizeException extends \nre\core\Exception + { + /** + * Error code + * + * @var int + */ + const CODE = 202; + /** + * Error message + * + * @var string + */ + const MESSAGE = 'File exceeds size maximum'; + + + + + /** + * Construct a new exception. + * + * @param string $message Error message + * @param int $code Error code + */ + function __construct($message=self::MESSAGE, $code=self::CODE) + { + parent::__construct( + $message, + $code + ); + } + + } + +?> diff --git a/app/exceptions/QuesttypeAgentNotFoundException.inc b/app/exceptions/QuesttypeAgentNotFoundException.inc new file mode 100644 index 00000000..b2b9dcb4 --- /dev/null +++ b/app/exceptions/QuesttypeAgentNotFoundException.inc @@ -0,0 +1,79 @@ + + * @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\exceptions; + + + /** + * Exception: QuesttypeAgent not found. + * + * @author Oliver Hanraths + */ + class QuesttypeAgentNotFoundException extends \nre\core\Exception + { + /** + * Error code + * + * @var int + */ + const CODE = 101; + /** + * Error message + * + * @var string + */ + const MESSAGE = 'QuesttypeAgent not found'; + + /** + * Name of the class that was not found + * + * @var string + */ + private $questtypeName; + + + + + /** + * Construct a new exception. + * + * @param string $questtypeName Name of the QuesttypeAgent that was not found + * @param string $message Error message + * @param int $code Error code + */ + function __construct($questtypeName, $message=self::MESSAGE, $code=self::CODE) + { + parent::__construct( + $message, + $code, + $questtypeName + ); + + // Store values + $this->questtypeName = $questtypeName; + } + + + + + /** + * Get the name of the QuesttypeAgent that was not found. + * + * @return string Name of the QuesttypeAgent that was not found + */ + public function getClassName() + { + return $this->questtypeName; + } + + } + +?> diff --git a/app/exceptions/QuesttypeAgentNotValidException.inc b/app/exceptions/QuesttypeAgentNotValidException.inc new file mode 100644 index 00000000..6e499919 --- /dev/null +++ b/app/exceptions/QuesttypeAgentNotValidException.inc @@ -0,0 +1,79 @@ + + * @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\exceptions; + + + /** + * Exception: QuesttypeAgent not valid. + * + * @author Oliver Hanraths + */ + class QuesttypeAgentNotValidException extends \nre\core\Exception + { + /** + * Error code + * + * @var int + */ + const CODE = 102; + /** + * Error message + * + * @var string + */ + const MESSAGE = 'QuesttypeAgent not valid'; + + /** + * Name of the invalid class + * + * @var string + */ + private $questtypeName; + + + + + /** + * Construct a new exception. + * + * @param string $questtypeName Name of the invalid QuesttypeAgent + * @param string $message Error message + * @param int $code Error code + */ + function __construct($questtypeName, $message=self::MESSAGE, $code=self::CODE) + { + parent::__construct( + $message, + $code, + $questtypeName + ); + + // Store value + $this->questtypeName = $questtypeName; + } + + + + + /** + * Get the name of the invalid QuesttypeAgent. + * + * @return string Name of the invalid QuesttypeAgent + */ + public function getClassName() + { + return $this->questtypeName; + } + + } + +?> diff --git a/app/exceptions/QuesttypeControllerNotFoundException.inc b/app/exceptions/QuesttypeControllerNotFoundException.inc new file mode 100644 index 00000000..3787ebac --- /dev/null +++ b/app/exceptions/QuesttypeControllerNotFoundException.inc @@ -0,0 +1,79 @@ + + * @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\exceptions; + + + /** + * Exception: QuesttypeController not found. + * + * @author Oliver Hanraths + */ + class QuesttypeControllerNotFoundException extends \nre\core\Exception + { + /** + * Error code + * + * @var int + */ + const CODE = 103; + /** + * Error message + * + * @var string + */ + const MESSAGE = 'QuesttypeController not found'; + + /** + * Name of the class that was not found + * + * @var string + */ + private $questtypeName; + + + + + /** + * Construct a new exception. + * + * @param string $questtypeName Name of the QuesttypeController that was not found + * @param string $message Error message + * @param int $code Error code + */ + function __construct($questtypeName, $message=self::MESSAGE, $code=self::CODE) + { + parent::__construct( + $message, + $code, + $questtypeName + ); + + // Store values + $this->questtypeName = $questtypeName; + } + + + + + /** + * Get the name of the QuesttypeController that was not found. + * + * @return string Name of the QuesttypeController that was not found + */ + public function getClassName() + { + return $this->questtypeName; + } + + } + +?> diff --git a/app/exceptions/QuesttypeControllerNotValidException.inc b/app/exceptions/QuesttypeControllerNotValidException.inc new file mode 100644 index 00000000..3b0ef93d --- /dev/null +++ b/app/exceptions/QuesttypeControllerNotValidException.inc @@ -0,0 +1,79 @@ + + * @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\exceptions; + + + /** + * Exception: QuesttypeController not valid. + * + * @author Oliver Hanraths + */ + class QuesttypeControllerNotValidException extends \nre\core\Exception + { + /** + * Error code + * + * @var int + */ + const CODE = 104; + /** + * Error message + * + * @var string + */ + const MESSAGE = 'QuesttypeController not valid'; + + /** + * Name of the invalid class + * + * @var string + */ + private $questtypeName; + + + + + /** + * Construct a new exception. + * + * @param string $questtypeName Name of the invalid QuesttypeController + * @param string $message Error message + * @param int $code Error code + */ + function __construct($questtypeName, $message=self::MESSAGE, $code=self::CODE) + { + parent::__construct( + $message, + $code, + $questtypeName + ); + + // Store value + $this->questtypeName = $questtypeName; + } + + + + + /** + * Get the name of the invalid QuesttypeController. + * + * @return string Name of the invalid QuesttypeController + */ + public function getClassName() + { + return $this->questtypeName; + } + + } + +?> diff --git a/app/exceptions/QuesttypeModelNotFoundException.inc b/app/exceptions/QuesttypeModelNotFoundException.inc new file mode 100644 index 00000000..363013d6 --- /dev/null +++ b/app/exceptions/QuesttypeModelNotFoundException.inc @@ -0,0 +1,79 @@ + + * @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\exceptions; + + + /** + * Exception: QuesttypeModel not found. + * + * @author Oliver Hanraths + */ + class QuesttypeModelNotFoundException extends \nre\core\Exception + { + /** + * Error code + * + * @var int + */ + const CODE = 105; + /** + * Error message + * + * @var string + */ + const MESSAGE = 'QuesttypeModel not found'; + + /** + * Name of the class that was not found + * + * @var string + */ + private $questtypeName; + + + + + /** + * Construct a new exception. + * + * @param string $questtypeName Name of the QuesttypeModel that was not found + * @param string $message Error message + * @param int $code Error code + */ + function __construct($questtypeName, $message=self::MESSAGE, $code=self::CODE) + { + parent::__construct( + $message, + $code, + $questtypeName + ); + + // Store values + $this->questtypeName = $questtypeName; + } + + + + + /** + * Get the name of the QuesttypeModel that was not found. + * + * @return string Name of the QuesttypeModel that was not found + */ + public function getClassName() + { + return $this->questtypeName; + } + + } + +?> diff --git a/app/exceptions/QuesttypeModelNotValidException.inc b/app/exceptions/QuesttypeModelNotValidException.inc new file mode 100644 index 00000000..31a5248d --- /dev/null +++ b/app/exceptions/QuesttypeModelNotValidException.inc @@ -0,0 +1,79 @@ + + * @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\exceptions; + + + /** + * Exception: QuesttypeModel not valid. + * + * @author Oliver Hanraths + */ + class QuesttypeModelNotValidException extends \nre\core\Exception + { + /** + * Error code + * + * @var int + */ + const CODE = 106; + /** + * Error message + * + * @var string + */ + const MESSAGE = 'QuesttypeModel not valid'; + + /** + * Name of the invalid class + * + * @var string + */ + private $questtypeName; + + + + + /** + * Construct a new exception. + * + * @param string $questtypeName Name of the invalid QuesttypeModel + * @param string $message Error message + * @param int $code Error code + */ + function __construct($questtypeName, $message=self::MESSAGE, $code=self::CODE) + { + parent::__construct( + $message, + $code, + $questtypeName + ); + + // Store value + $this->questtypeName = $questtypeName; + } + + + + + /** + * Get the name of the invalid QuesttypeModel. + * + * @return string Name of the invalid QuesttypeModel + */ + public function getClassName() + { + return $this->questtypeName; + } + + } + +?> diff --git a/app/exceptions/StationtypeAgentNotFoundException.inc b/app/exceptions/StationtypeAgentNotFoundException.inc new file mode 100644 index 00000000..90347b40 --- /dev/null +++ b/app/exceptions/StationtypeAgentNotFoundException.inc @@ -0,0 +1,79 @@ + + * @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\exceptions; + + + /** + * Exception: StationtypeAgent not found. + * + * @author Oliver Hanraths + */ + class StationtypeAgentNotFoundException extends \nre\core\Exception + { + /** + * Error code + * + * @var int + */ + const CODE = 401; + /** + * Error message + * + * @var string + */ + const MESSAGE = 'StationtypeAgent not found'; + + /** + * Name of the class that was not found + * + * @var string + */ + private $stationtypeName; + + + + + /** + * Construct a new exception. + * + * @param string $stationtypeName Name of the StationtypeAgent that was not found + * @param string $message Error message + * @param int $code Error code + */ + function __construct($stationtypeName, $message=self::MESSAGE, $code=self::CODE) + { + parent::__construct( + $message, + $code, + $stationtypeName + ); + + // Store values + $this->stationtypeName = $stationtypeName; + } + + + + + /** + * Get the name of the StationtypeAgent that was not found. + * + * @return string Name of the StationtypeAgent that was not found + */ + public function getClassName() + { + return $this->stationtypeName; + } + + } + +?> diff --git a/app/exceptions/StationtypeAgentNotValidException.inc b/app/exceptions/StationtypeAgentNotValidException.inc new file mode 100644 index 00000000..26ed5f96 --- /dev/null +++ b/app/exceptions/StationtypeAgentNotValidException.inc @@ -0,0 +1,79 @@ + + * @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\exceptions; + + + /** + * Exception: StationtypeAgent not valid. + * + * @author Oliver Hanraths + */ + class StationtypeAgentNotValidException extends \nre\core\Exception + { + /** + * Error code + * + * @var int + */ + const CODE = 402; + /** + * Error message + * + * @var string + */ + const MESSAGE = 'StationtypeAgent not valid'; + + /** + * Name of the invalid class + * + * @var string + */ + private $stationtypeName; + + + + + /** + * Construct a new exception. + * + * @param string $stationtypeName Name of the invalid StationtypeAgent + * @param string $message Error message + * @param int $code Error code + */ + function __construct($stationtypeName, $message=self::MESSAGE, $code=self::CODE) + { + parent::__construct( + $message, + $code, + $stationtypeName + ); + + // Store value + $this->stationtypeName = $stationtypeName; + } + + + + + /** + * Get the name of the invalid StationtypeAgent. + * + * @return string Name of the invalid StationtypeAgent + */ + public function getClassName() + { + return $this->stationtypeName; + } + + } + +?> diff --git a/app/exceptions/StationtypeControllerNotFoundException.inc b/app/exceptions/StationtypeControllerNotFoundException.inc new file mode 100644 index 00000000..063fc9c9 --- /dev/null +++ b/app/exceptions/StationtypeControllerNotFoundException.inc @@ -0,0 +1,79 @@ + + * @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\exceptions; + + + /** + * Exception: StationtypeController not found. + * + * @author Oliver Hanraths + */ + class StationtypeControllerNotFoundException extends \nre\core\Exception + { + /** + * Error code + * + * @var int + */ + const CODE = 403; + /** + * Error message + * + * @var string + */ + const MESSAGE = 'StationtypeController not found'; + + /** + * Name of the class that was not found + * + * @var string + */ + private $stationtypeName; + + + + + /** + * Construct a new exception. + * + * @param string $stationtypeName Name of the StationtypeController that was not found + * @param string $message Error message + * @param int $code Error code + */ + function __construct($stationtypeName, $message=self::MESSAGE, $code=self::CODE) + { + parent::__construct( + $message, + $code, + $stationtypeName + ); + + // Store values + $this->stationtypeName = $stationtypeName; + } + + + + + /** + * Get the name of the StationtypeController that was not found. + * + * @return string Name of the StationtypeController that was not found + */ + public function getClassName() + { + return $this->stationtypeName; + } + + } + +?> diff --git a/app/exceptions/StationtypeControllerNotValidException.inc b/app/exceptions/StationtypeControllerNotValidException.inc new file mode 100644 index 00000000..7bba0e1f --- /dev/null +++ b/app/exceptions/StationtypeControllerNotValidException.inc @@ -0,0 +1,79 @@ + + * @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\exceptions; + + + /** + * Exception: StationtypeController not valid. + * + * @author Oliver Hanraths + */ + class StationtypeControllerNotValidException extends \nre\core\Exception + { + /** + * Error code + * + * @var int + */ + const CODE = 404; + /** + * Error message + * + * @var string + */ + const MESSAGE = 'StationtypeController not valid'; + + /** + * Name of the invalid class + * + * @var string + */ + private $stationtypeName; + + + + + /** + * Construct a new exception. + * + * @param string $stationtypeName Name of the invalid StationtypeController + * @param string $message Error message + * @param int $code Error code + */ + function __construct($stationtypeName, $message=self::MESSAGE, $code=self::CODE) + { + parent::__construct( + $message, + $code, + $stationtypeName + ); + + // Store value + $this->stationtypeName = $stationtypeName; + } + + + + + /** + * Get the name of the invalid StationtypeController. + * + * @return string Name of the invalid StationtypeController + */ + public function getClassName() + { + return $this->stationtypeName; + } + + } + +?> diff --git a/app/exceptions/StationtypeModelNotFoundException.inc b/app/exceptions/StationtypeModelNotFoundException.inc new file mode 100644 index 00000000..5c032e77 --- /dev/null +++ b/app/exceptions/StationtypeModelNotFoundException.inc @@ -0,0 +1,79 @@ + + * @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\exceptions; + + + /** + * Exception: StationtypeModel not found. + * + * @author Oliver Hanraths + */ + class StationtypeModelNotFoundException extends \nre\core\Exception + { + /** + * Error code + * + * @var int + */ + const CODE = 405; + /** + * Error message + * + * @var string + */ + const MESSAGE = 'StationtypeModel not found'; + + /** + * Name of the class that was not found + * + * @var string + */ + private $stationtypeName; + + + + + /** + * Construct a new exception. + * + * @param string $stationtypeName Name of the StationtypeModel that was not found + * @param string $message Error message + * @param int $code Error code + */ + function __construct($stationtypeName, $message=self::MESSAGE, $code=self::CODE) + { + parent::__construct( + $message, + $code, + $stationtypeName + ); + + // Store values + $this->stationtypeName = $stationtypeName; + } + + + + + /** + * Get the name of the StationtypeModel that was not found. + * + * @return string Name of the StationtypeModel that was not found + */ + public function getClassName() + { + return $this->stationtypeName; + } + + } + +?> diff --git a/app/exceptions/StationtypeModelNotValidException.inc b/app/exceptions/StationtypeModelNotValidException.inc new file mode 100644 index 00000000..e9fcd728 --- /dev/null +++ b/app/exceptions/StationtypeModelNotValidException.inc @@ -0,0 +1,79 @@ + + * @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\exceptions; + + + /** + * Exception: StationxuesttypeModel not valid. + * + * @author Oliver Hanraths + */ + class StationtypeModelNotValidException extends \nre\core\Exception + { + /** + * Error code + * + * @var int + */ + const CODE = 406; + /** + * Error message + * + * @var string + */ + const MESSAGE = 'StationtypeModel not valid'; + + /** + * Name of the invalid class + * + * @var string + */ + private $stationtypeName; + + + + + /** + * Construct a new exception. + * + * @param string $stationtypeName Name of the invalid StationtypeModel + * @param string $message Error message + * @param int $code Error code + */ + function __construct($stationtypeName, $message=self::MESSAGE, $code=self::CODE) + { + parent::__construct( + $message, + $code, + $stationtypeName + ); + + // Store value + $this->stationtypeName = $stationtypeName; + } + + + + + /** + * Get the name of the invalid StationtypeModel. + * + * @return string Name of the invalid StationtypeModel + */ + public function getClassName() + { + return $this->stationtypeName; + } + + } + +?> diff --git a/app/exceptions/SubmissionNotValidException.inc b/app/exceptions/SubmissionNotValidException.inc new file mode 100644 index 00000000..21cbee55 --- /dev/null +++ b/app/exceptions/SubmissionNotValidException.inc @@ -0,0 +1,79 @@ + + * @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\exceptions; + + + /** + * Exception: Character submission not valid. + * + * @author Oliver Hanraths + */ + class SubmissionNotValidException extends \nre\core\Exception + { + /** + * Error code + * + * @var int + */ + const CODE = 200; + /** + * Error message + * + * @var string + */ + const MESSAGE = 'Character submission not valid'; + + /** + * Nested exception + * + * @var Exception + */ + private $nestedException; + + + + + /** + * Construct a new exception. + * + * @param string $nestedException Nested exception + * @param string $message Error message + * @param int $code Error code + */ + function __construct($nestedException, $message=self::MESSAGE, $code=self::CODE) + { + parent::__construct( + $message, + $code, + $nestedException + ); + + // Store value + $this->nestedException = $nestedException; + } + + + + + /** + * Get Nested exception. + * + * @return string Nested exception + */ + public function getNestedException() + { + return $this->nestedException; + } + + } + +?> diff --git a/app/exceptions/WrongFiletypeException.inc b/app/exceptions/WrongFiletypeException.inc new file mode 100644 index 00000000..8a734dc0 --- /dev/null +++ b/app/exceptions/WrongFiletypeException.inc @@ -0,0 +1,79 @@ + + * @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\exceptions; + + + /** + * Exception: File has wrong filetype. + * + * @author Oliver Hanraths + */ + class WrongFiletypeException extends \nre\core\Exception + { + /** + * Error code + * + * @var int + */ + const CODE = 201; + /** + * Error message + * + * @var string + */ + const MESSAGE = 'File has wrong type “%s”'; + + /** + * Type of file + * + * @var string + */ + private $type; + + + + + /** + * Construct a new exception. + * + * @param string $type Type of file + * @param string $message Error message + * @param int $code Error code + */ + function __construct($type, $message=self::MESSAGE, $code=self::CODE) + { + parent::__construct( + $message, + $code, + $type + ); + + // Store values + $this->type = $type; + } + + + + + /** + * Get type of file. + * + * @return Type of file + */ + public function getType() + { + return $this->type; + } + + } + +?> diff --git a/app/lib/Netcarver/Textile/DataBag.php b/app/lib/Netcarver/Textile/DataBag.php new file mode 100644 index 00000000..0a1d9401 --- /dev/null +++ b/app/lib/Netcarver/Textile/DataBag.php @@ -0,0 +1,99 @@ + + * use Netcarver\Textile\DataBag; + * $plant = new DataBag(array('key' => 'value')); + * $plant->flower('rose')->color('red'); + * + */ + +class DataBag +{ + /** + * The data array stored in the bag. + * + * @var array + */ + + protected $data; + + /** + * Constructor. + * + * @param array|null $data The initial data array stored in the bag + */ + + public function __construct(array $data = null) + { + $this->data = (array) $data; + } + + /** + * Adds a value to the bag. + * + * Empty values are rejected, unless the + * second argument is set TRUE. + * + * + * use Netcarver\Textile\DataBag; + * $plant = new DataBag(array('key' => 'value')); + * $plant->flower('rose')->color('red')->emptyValue(false, true); + * + * + * @param string $name The name + * @param array $params Arguments + * @return DataBag + */ + + public function __call($name, array $params) + { + if (!empty($params[1]) || !empty($params[0])) { + $this->data[$name] = $params[0]; + } + + return $this; + } +} diff --git a/app/lib/Netcarver/Textile/Parser.php b/app/lib/Netcarver/Textile/Parser.php new file mode 100644 index 00000000..4c150ec3 --- /dev/null +++ b/app/lib/Netcarver/Textile/Parser.php @@ -0,0 +1,4042 @@ + + * All rights reserved. + * + * Thanks to Carlo Zottmann for refactoring + * Textile's procedural code into a class framework + * + * Additions and fixes Copyright (c) 2006 Alex Shiels https://twitter.com/tellyworth + * Additions and fixes Copyright (c) 2010 Stef Dawson http://stefdawson.com/ + * Additions and fixes Copyright (c) 2010-13 Netcarver https://github.com/netcarver + * Additions and fixes Copyright (c) 2011 Jeff Soo http://ipsedixit.net/ + * Additions and fixes Copyright (c) 2012 Robert Wetzlmayr http://wetzlmayr.com/ + * Additions and fixes Copyright (c) 2012-13 Jukka Svahn http://rahforum.biz/ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name Textile nor the names of its contributors may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* +Textile usage examples. + +Block modifier syntax: + + Header: h(1-6). + Paragraphs beginning with 'hn. ' (where n is 1-6) are wrapped in header tags. + Example: h1. Header... ->

Header...

+ + Paragraph: p. (also applied by default) + Example: p. Text ->

Text

+ + Blockquote: bq. + Example: bq. Block quotation... ->
Block quotation...
+ + Blockquote with citation: bq.:http://citation.url + Example: bq.:http://textism.com/ Text... + ->
Text...
+ + Footnote: fn(1-100). + Example: fn1. Footnote... ->

Footnote...

+ + Numeric list: #, ## + Consecutive paragraphs beginning with # are wrapped in ordered list tags. + Example:
  1. ordered list
+ + Bulleted list: *, ** + Consecutive paragraphs beginning with * are wrapped in unordered list tags. + Example:
  • unordered list
+ + Definition list: + Terms ;, ;; + Definitions :, :: + Consecutive paragraphs beginning with ; or : are wrapped in definition list tags. + Example:
term
definition
+ + Redcloth-style Definition list: + - Term1 := Definition1 + - Term2 := Extended + definition =: + +Phrase modifier syntax: + + _emphasis_ -> emphasis + __italic__ -> italic + *strong* -> strong + **bold** -> bold + ??citation?? -> citation + -deleted text- -> deleted + +inserted text+ -> inserted + ^superscript^ -> superscript + ~subscript~ -> subscript + @code@ -> computer code + %(bob)span% -> span + + ==notextile== -> leave text alone (do not format) + + "linktext":url -> linktext +"linktext(title)":url -> linktext + "$":url -> url + "$(title)":url -> url + + !imageurl! -> + !imageurl(alt text)! -> alt text + !imageurl!:linkurl -> + +ABC(Always Be Closing) -> ABC + +Linked Notes: + + Allows the generation of an automated list of notes with links. + + Linked notes are composed of three parts, a set of named _definitions_, a set of + _references_ to those definitions and one or more _placeholders_ indicating where + the consolidated list of notes is to be placed in your document. + + Definitions: + + Each note definition must occur in its own paragraph and should look like this... + + note#mynotelabel. Your definition text here. + + You are free to use whatever label you wish after the # as long as it is made up + of letters, numbers, colon(:) or dash(-). + + References: + + Each note reference is marked in your text like this[#mynotelabel] and + it will be replaced with a superscript reference that links into the list of + note definitions. + + List placeholder(s): + + The note list can go anywhere in your document. You have to indicate where + like this: + + notelist. + + notelist can take attributes (class#id) like this: notelist(class#id). + + By default, the note list will show each definition in the order that they + are referenced in the text by the _references_. It will show each definition with + a full list of backlinks to each reference. If you do not want this, you can choose + to override the backlinks like this... + + notelist(class#id)!. Produces a list with no backlinks. + notelist(class#id)^. Produces a list with only the first backlink. + + Should you wish to have a specific definition display backlinks differently to this + then you can override the backlink method by appending a link override to the + _definition_ you wish to customise. + + note#label. Uses the citelist's setting for backlinks. + note#label!. Causes that definition to have no backlinks. + note#label^. Causes that definition to have one backlink (to the first ref.) + note#label*. Causes that definition to have all backlinks. + + Any unreferenced notes will be left out of the list unless you explicitly state + you want them by adding a '+'. Like this... + + notelist(class#id)!+. Giving a list of all notes without any backlinks. + + You can mix and match the list backlink control and unreferenced links controls + but the backlink control (if any) must go first. Like so: notelist^+. , not + like this: notelist+^. + + Example... + Scientists say[#lavader] the moon is small. + + note#other. An unreferenced note. + + note#lavader(myliclass). "Proof":http://example.com of a small moon. + + notelist(myclass#myid)+. + + Would output (the actual IDs used would be randomised)... + +

Scientists say1 the moon is small.

+ +
    +
  1. a + Proof of a small moon.
  2. +
  3. An unreferenced note.
  4. +
+ + The 'a b c' backlink characters can be altered too. + For example if you wanted the notes to have numeric backlinks starting from 1: + + notelist:1. + +Table syntax: + + Simple tables: + + |a|simple|table|row| + |And|Another|table|row| + |With an||empty|cell| + + |=. My table caption goes here + |_. A|_. table|_. header|_.row| + |A|simple|table|row| + + Note: Table captions *must* be the first line of the table else treated as a center-aligned cell. + + Tables with attributes: + + table{border:1px solid black}. My table summary here + {background:#ddd;color:red}. |{}| | | | + + To specify thead / tfoot / tbody groups, add one of these on its own line + above the row(s) you wish to wrap (you may specify attributes before the dot): + + |^. # thead + |-. # tbody + |~. # tfoot + + Column groups: + + |:\3. 100| + + Becomes: + + + You can omit either or both of the \N or width values. You may also + add cells after the colgroup definition to specify col elements with + span, width, or standard Textile attributes: + + |:. 50|(firstcol). |\2. 250||300| + + Becomes: + + + + + + + + (Note that, per the HTML specification, you should not add span + to the colgroup if specifying col elements.) + +Applying Attributes: + + Most anywhere Textile code is used, attributes such as arbitrary css style, + css classes, and ids can be applied. The syntax is fairly consistent. + + The following characters quickly alter the alignment of block elements: + + < -> left align ex. p<. left-aligned para + > -> right align h3>. right-aligned header 3 + = -> centred h4=. centred header 4 + <> -> justified p<>. justified paragraph + + These will change vertical alignment in table cells: + + ^ -> top ex. |^. top-aligned table cell| + - -> middle |-. middle aligned| + ~ -> bottom |~. bottom aligned cell| + + Plain (parentheses) inserted between block syntax and the closing dot-space + indicate classes and ids: + + p(hector). paragraph ->

paragraph

+ + p(#fluid). paragraph ->

paragraph

+ + (classes and ids can be combined) + p(hector#fluid). paragraph ->

paragraph

+ + Curly {brackets} insert arbitrary css style + + p{line-height:18px}. paragraph ->

paragraph

+ + h3{color:red}. header 3 ->

header 3

+ + Square [brackets] insert language attributes + + p[no]. paragraph ->

paragraph

+ + %[fr]phrase% -> phrase + + Usually Textile block element syntax requires a dot and space before the block + begins, but since lists don't, they can be styled just using braces + + #{color:blue} one ->
    + # big
  1. one
  2. + # list
  3. big
  4. +
  5. list
  6. +
+ + Using the span tag to style a phrase + + It goes like this, %{color:red}the fourth the fifth% + -> It goes like this, the fourth the fifth + +Ordered list start and continuation: + + You can control the start attribute of an ordered list like so; + + #5 Item 5 + # Item 6 + + You can resume numbering list items after some intervening anonymous block like so... + + #_ Item 7 + # Item 8 +*/ + +/** + * Textile parser. + * + * The Parser class takes Textile input and + * converts it to well formatted HTML. This is + * the library's main class, hosting the parsing + * functionality and exposing a simple + * public interface for you to use. + * + * The most basic use case would involve initialising + * a instance of the class and calling the textileThis + * method, parsing the given Textile input in unrestricted + * mode. + * + * + * $parser = new \Netcarver\Textile\Parser(); + * echo $parser->textileThis('h1. Hello World!'); + * + * + * @see Parser::__construct() + * @see Parser::textileThis() + * @see Parser::textileRestricted() + */ + +class Parser +{ + /** + * Version number. + * + * @var string + */ + + protected $ver = '3.5.5'; + + /** + * Regular expression snippets. + * + * @var array + */ + + protected $regex_snippets; + + /** + * Pattern for horizontal align. + * + * @var string + */ + + protected $hlgn = "(?:\<(?!>)|<>|>|<|(?|\<\>|\=|[()]+(?! ))"; + + /** + * Pattern for vertical align. + * + * @var string + */ + + protected $vlgn = "[\-^~]"; + + /** + * Pattern for HTML classes and IDs. + * + * Does not allow classes/ids/languages/styles to span across + * newlines if used in a dotall regular expression. + * + * @var string + */ + + protected $clas = "(?:\([^)\n]+\))"; + + /** + * Pattern for language attribute. + * + * @var string + */ + + protected $lnge = "(?:\[[^]\n]+\])"; + + /** + * Pattern for style attribute. + * + * @var string + */ + + protected $styl = "(?:\{[^}\n]+\})"; + + /** + * Regular expression pattern for column spans in tables. + * + * @var string + */ + + protected $cspn = "(?:\\\\[0-9]+)"; + + /** + * Regular expression for row spans in tables. + * + * @var string + */ + + protected $rspn = "(?:\/[0-9]+)"; + + /** + * Regular expression for horizontal or vertical alignment. + * + * @var string + */ + + protected $a; + + /** + * Regular expression for column or row spans in tables. + * + * @var string + */ + + protected $s; + + /** + * Pattern that matches a class, style, language and horizontal alignment attributes. + * + * @var string + */ + + protected $c; + + /** + * Pattern that matches class, style and language attributes. + * + * Will allows all 16 possible permutations of class, style and language attributes. + * , c, cl, cs, cls, csl, l, lc, ls, lcs, lsc, s, sc, sl, scl or slc + * + * @var string + */ + protected $cls; + + /** + * Whitelisted block tags. + * + * @var array + */ + + protected $blocktag_whitelist = array(); + + /** + * Pattern for punctation. + * + * @var string + */ + + protected $pnct = '[\!"#\$%&\'()\*\+,\-\./:;<=>\?@\[\\\]\^_`{\|}\~]'; + + /** + * Pattern for URL. + * + * @var string + */ + + protected $urlch; + + /** + * Matched marker symbols. + * + * @var string + */ + + protected $syms = '¤§µ¶†‡•∗∴◊♠♣♥♦'; + + /** + * HTML rel attribute used for links. + * + * @var string + */ + + protected $rel; + + /** + * Array of footnotes + * + * @var array + */ + protected $fn; + + /** + * Shelved content. + * + * Stores fragments of the source text that have been parsed + * and require no more processing. + * + * @var array + */ + + protected $shelf = array(); + + /** + * Restricted mode. + * + * @var bool + */ + + protected $restricted = false; + + /** + * Disallow images. + * + * @var bool + */ + + protected $noimage = false; + + /** + * Lite mode. + * + * @var bool + */ + + protected $lite = false; + + /** + * Accepted link protocols. + * + * @var array + */ + + protected $url_schemes = array(); + + /** + * Restricted link protocols. + * + * @var array + */ + + protected $restricted_url_schemes = array( + 'http', + 'https', + 'ftp', + 'mailto', + ); + + /** + * Unrestricted link protocols. + * + * @var array + */ + + protected $unrestricted_url_schemes = array( + 'http', + 'https', + 'ftp', + 'mailto', + 'file', + 'tel', + 'callto', + 'sftp', + ); + + /** + * Span tags. + * + * @var array + */ + + protected $span_tags = array( + '*' => 'strong', + '**' => 'b', + '??' => 'cite', + '_' => 'em', + '__' => 'i', + '-' => 'del', + '%' => 'span', + '+' => 'ins', + '~' => 'sub', + '^' => 'sup', + ); + + /** + * Patterns for finding glyphs. + * + * An array of regex patterns used to find text features + * such as apostrophes, fractions and em-dashes. Each + * entry in this array must have a corresponding entry in + * the $glyph_replace array. + * + * @var null|array + * @see Parser::$glyph_replace + */ + + protected $glyph_search = null; + + /** + * Glyph replacements. + * + * An array of replacements used to insert typographic glyphs + * into the text. Each entry must have a corresponding entry in + * the $glyph_search array and may refer to values captured in + * the corresponding search regex. + * + * @var null|array + * @see Parser::$glyph_search + */ + + protected $glyph_replace = null; + + /** + * Indicates whether glyph substitution is required. + * + * Dirty flag, set by setSymbol(), indicating the parser needs to + * rebuild the glyph substitutions before the next parse. + * + * @var bool + * @see Parser::setSymbol() + */ + + protected $rebuild_glyphs = true; + + /** + * Relative image path. + * + * @var string + */ + + protected $relativeImagePrefix = ''; + + /** + * Maximum nesting level for inline elements. + * + * @var int + */ + + protected $max_span_depth = 5; + + /** + * Server document root. + * + * @var string + */ + + protected $doc_root; + + /** + * Target document type. + * + * @var string + */ + + protected $doctype; + + /** + * Substitution symbols. + * + * Basic symbols used in textile glyph replacements. To override these, call + * setSymbol method before calling textileThis or textileRestricted. + * + * @var array + * @see Parser::setSymbol() + */ + + protected $symbols = array( + 'quote_single_open' => '‘', + 'quote_single_close' => '’', + 'quote_double_open' => '“', + 'quote_double_close' => '”', + 'apostrophe' => '’', + 'prime' => '′', + 'prime_double' => '″', + 'ellipsis' => '…', + 'emdash' => '—', + 'endash' => '–', + 'dimension' => '×', + 'trademark' => '™', + 'registered' => '®', + 'copyright' => '©', + 'half' => '½', + 'quarter' => '¼', + 'threequarters' => '¾', + 'degrees' => '°', + 'plusminus' => '±', + 'fn_ref_pattern' => '{marker}', + 'fn_foot_pattern' => '{marker}', + 'nl_ref_pattern' => '{marker}', + ); + + /** + * Dimensionless images flag. + * + * @var bool + */ + + protected $dimensionless_images = false; + + /** + * Directory separator. + * + * @var string + */ + + protected $ds = '/'; + + /** + * Whether mbstring extension is installed. + * + * @var bool + */ + + protected $mb; + + /** + * Multi-byte conversion map. + * + * @var array + */ + + protected $cmap = array(0x0080, 0xffff, 0, 0xffff); + + /** + * Stores note index. + * + * @var int + */ + + protected $note_index = 1; + + /** + * Stores unreferenced notes. + * + * @var array + */ + + protected $unreferencedNotes = array(); + + /** + * Stores note lists. + * + * @var array + */ + + protected $notelist_cache = array(); + + /** + * Stores notes. + * + * @var array + */ + + protected $notes = array(); + + /** + * Stores URL references. + * + * @var array + */ + + protected $urlrefs = array(); + + /** + * Stores span depth. + * + * @var int + */ + + protected $span_depth = 0; + + /** + * Unique ID used for reference tokens. + * + * @var string + */ + + protected $uid; + + /** + * Token reference index. + * + * @var int + */ + + protected $refIndex = 1; + + /** + * Stores references values. + * + * @var array + */ + + protected $refCache = array(); + + /** + * Matched open and closed quotes. + * + * @var array + */ + + protected $quotes = array( + '"' => '"', + "'" => "'", + '(' => ')', + '{' => '}', + '[' => ']', + '«' => '»', + '»' => '«', + '‹' => '›', + '›' => '‹', + '„' => '“', + '‚' => '‘', + '‘' => '’', + '”' => '“', + ); + + /** + * Regular expression that matches starting quotes. + * + * @var string + */ + + protected $quote_starts; + + /** + * Ordered list starts. + * + * @var array + */ + + protected $olstarts = array(); + + /** + * Link prefix. + * + * @var string + */ + + protected $linkPrefix; + + /** + * Link index. + * + * @var int + */ + + protected $linkIndex = 1; + + /** + * Constructor. + * + * The constructor allows setting options that affect the + * class instance as a whole, such as the output doctype. + * To instruct the parser to return HTML5 markup instead of + * XHTML, set $doctype argument to 'html5'. + * + * + * $parser = new \Netcarver\Textile\Parser('html5'); + * echo $parser->textileThis('HTML(HyperText Markup Language)"); + * + * + * @param string $doctype The output document type, either 'xhtml' or 'html5' + * @throws \InvalidArgumentException + * @api + */ + + public function __construct($doctype = 'xhtml') + { + $doctypes = array( + 'xhtml', + 'html5', + ); + + if (!in_array($doctype, $doctypes, true)) { + throw new \InvalidArgumentException('Invalid doctype given.'); + } else { + $this->doctype = $doctype; + } + + $uid = uniqid(rand()); + $this->uid = 'textileRef:'.$uid.':'; + $this->linkPrefix = $uid.'-'; + $this->a = "(?:$this->hlgn|$this->vlgn)*"; + $this->s = "(?:$this->cspn|$this->rspn)*"; + $this->c = "(?:$this->clas|$this->styl|$this->lnge|$this->hlgn)*"; + + $this->cls = '(?:'. + "$this->clas(?:". + "$this->lnge(?:$this->styl)?|$this->styl(?:$this->lnge)?". + ')?|'. + "$this->lnge(?:". + "$this->clas(?:$this->styl)?|$this->styl(?:$this->clas)?". + ')?|'. + "$this->styl(?:". + "$this->clas(?:$this->lnge)?|$this->lnge(?:$this->clas)?". + ')?'. + ')?'; + + if ($this->isUnicodePcreSupported()) { + $this->regex_snippets = array( + 'acr' => '\p{Lu}\p{Nd}', + 'abr' => '\p{Lu}', + 'nab' => '\p{Ll}', + 'wrd' => '(?:\p{L}|\p{M}|\p{N}|\p{Pc})', + 'mod' => 'u', // Make sure to mark the unicode patterns as such, Some servers seem to need this. + 'cur' => '\p{Sc}', + 'digit' => '\p{N}', + 'space' => '(?:\p{Zs}|\h|\v)', + 'char' => '(?:[^\p{Zs}\h\v])', + ); + } else { + $this->regex_snippets = array( + 'acr' => 'A-Z0-9', + 'abr' => 'A-Z', + 'nab' => 'a-z', + 'wrd' => '\w', + 'mod' => '', + 'cur' => '', + 'digit' => '\d', + 'space' => '(?:\s|\h|\v)', + 'char' => '\S', + ); + } + extract($this->regex_snippets); + $this->urlch = '['.$wrd.'"$\-_.+!*\'(),";\/?:@=&%#{}|\\^~\[\]`]'; + $this->quote_starts = implode('|', array_map('preg_quote', array_keys($this->quotes))); + + if (defined('DIRECTORY_SEPARATOR')) { + $this->ds = constant('DIRECTORY_SEPARATOR'); + } + + if (php_sapi_name() === 'cli') { + $this->doc_root = getcwd(); + } elseif (!empty($_SERVER['DOCUMENT_ROOT'])) { + $this->doc_root = $_SERVER['DOCUMENT_ROOT']; + } elseif (!empty($_SERVER['PATH_TRANSLATED'])) { + $this->doc_root = $_SERVER['PATH_TRANSLATED']; + } + + $this->doc_root = rtrim($this->doc_root, $this->ds).$this->ds; + } + + /** + * Defines a substitution symbol. + * + * Call this you need to redefine a substitution symbol to + * be used when parsing a Textile document. + * + * @param string $name Name of the symbol to assign a new value to. + * @param string $value New value for the symbol. + * @return Parser + * @api + */ + + public function setSymbol($name, $value) + { + $this->symbols[$name] = $value; + $this->rebuild_glyphs = true; + return $this; + } + + /** + * Gets a symbol definitions. + * + * This method can be used to get a symbol definition, or an + * array containing the full symbol table. + * + * @param string|null $name The name of the symbol, or NULL if requesting the symbol table + * @return array|string The symbol table or the requested symbol + * @throws \InvalidArgumentException + * @api + */ + + public function getSymbol($name = null) + { + if ($name !== null) { + if (isset($this->symbols[$name])) { + return $this->symbols[$name]; + } + + throw new \InvalidArgumentException('The specified name does not match any symbols.'); + } + + return $this->symbols; + } + + /** + * Sets base image directory path. + * + * This is used when Textile is supplied with a relative image path. + * Allows client systems to have PHP-Textile convert relative image paths to + * absolute or prefixed paths. This method is used to set that base path, + * usually a absolute HTTP address pointing to a directory. + * + * + * $parser = new \Netcarver\Textile\Parser(); + * $parser->setRelativeImagePrefix('http://static.example.com/'); + * + * + * @param string $prefix The string to prefix all relative image paths with + * @return Parser + * @api + */ + + public function setRelativeImagePrefix($prefix = '') + { + $this->relativeImagePrefix = $prefix; + return $this; + } + + /** + * Toggles image dimension attributes. + * + * If $dimensionless is set to TRUE, image width and height attributes + * will not be included in rendered image tags. Normally, Textile will add + * dimensions height images that specify a relative path, as long + * as the image file can be accessed. + * + * + * $parser = new \Netcarver\Textile\Parser(); + * echo $parser->setDimensionlessImages(false)->textileThis('Hello World!'); + * + * + * @param bool $dimensionless TRUE to disable image dimensions, FALSE to enable + * @return Parser + * @api + */ + + public function setDimensionlessImages($dimensionless = true) + { + $this->dimensionless_images = (bool) $dimensionless; + return $this; + } + + /** + * Whether images will get dimensions or not. + * + * This method will return the state of + * the state of the $dimensionless_images property. + * + * + * $parser = new \Netcarver\Textile\Parser(); + * if ($parser->getDimensionlessImages() === true) + * { + * echo 'Images do not get dimensions.'; + * } + * + * + * @return bool TRUE if images will not get dimensions, FALSE otherwise + * @api + */ + + public function getDimensionlessImages() + { + return (bool) $this->dimensionless_images; + } + + /** + * Gets Textile version number. + * + * + * $parser = new \Netcarver\Textile\Parser(); + * echo $parser->getVersion(); + * + * + * @return string Version + * @api + */ + + public function getVersion() + { + return $this->ver; + } + + /** + * Encodes the given text. + * + * + * $parser = new \Netcarver\Textile\Parser(); + * $parser->textileEncode('Some content to encode.'); + * + * + * @param string $text The text to be encoded + * @return string The encoded text + * @api + */ + + public function textileEncode($text) + { + $text = preg_replace("/&(?![#a-z0-9]+;)/i", "x%x%", $text); + $text = str_replace("x%x%", "&", $text); + return $text; + } + + /** + * Parses the given Textile input in un-restricted mode. + * + * This method should be used to parse any trusted Textile + * input, such as articles created by well-known + * authorised users. + * + * This method allows users to mix raw HTML and Textile. + * If you want to parse untrusted input, see the + * textileRestricted method instead. Using this less + * restrictive method on untrusted input, like comments + * and forum posts, will lead to XSS issues, as users + * will be able to use any HTML code, JavaScript links + * and Textile attributes in their input. + * + * + * $parser = new \Netcarver\Textile\Parser(); + * echo $parser->textileThis('h1. Hello World!'); + * + * + * @param string $text The Textile input to parse + * @param bool $lite Switch to lite mode + * @param bool $encode Encode input and return + * @param bool $noimage Disables images + * @param bool $strict This argument is ignored + * @param string $rel Relationship attribute applied to generated links + * @return string Parsed $text + * @see Parser::textileRestricted() + * @api + */ + + public function textileThis($text, $lite = false, $encode = false, $noimage = false, $strict = false, $rel = '') + { + $this->prepare($lite, $noimage, $rel); + $this->url_schemes = $this->unrestricted_url_schemes; + + if ($encode) { + trigger_error( + 'Use of the $encode argument is discouraged. Use Parser::textileEncode() instead.', + E_USER_DEPRECATED + ); + return $this->textileEncode($text); + } + + return $this->textileCommon($text, $lite); + } + + /** + * Parses the given Textile input in restricted mode. + * + * This method should be used for any untrusted user input, + * including comments or forum posts. + * + * This method escapes any raw HTML input, ignores unsafe + * attributes, links only whitelisted URL schemes + * and by default also prevents the use of images and + * extra Textile formatting, accepting only paragraphs + * and blockquotes as valid block tags. + * + * + * $parser = new \Netcarver\Textile\Parser(); + * echo $parser->textileRestricted('h1. Hello World!'); + * + * + * @param string $text The Textile input to parse + * @param bool $lite Controls lite mode, allowing extra formatting + * @param bool $noimage Allow images + * @param string $rel Relationship attribute applied to generated links + * @return string Parsed $text + * @see Parser::textileThis() + * @api + */ + + public function textileRestricted($text, $lite = true, $noimage = true, $rel = 'nofollow') + { + $this->prepare($lite, $noimage, $rel); + $this->url_schemes = $this->restricted_url_schemes; + $this->restricted = true; + + // Escape any raw html + $text = $this->encodeHTML($text, 0); + + return $this->textileCommon($text, $lite); + } + + /** + * Parses Textile syntax. + * + * This method performs common parse actions. + * + * @param string $text The input to parses + * @param bool $lite Controls lite mode + * @return string Parsed input + */ + + protected function textileCommon($text, $lite) + { + $text = $this->cleanWhiteSpace($text); + $text = $this->cleanUniqueTokens($text); + + if ($lite) { + $this->blocktag_whitelist = array('bq', 'p'); + $text = $this->blocks($text."\n\n"); + } else { + $this->blocktag_whitelist = array( + 'bq', + 'p', + 'bc', + 'notextile', + 'pre', + 'h[1-6]', + 'fn'.$this->regex_snippets['digit'].'+', + '###', + ); + $text = $this->blocks($text); + $text = $this->placeNoteLists($text); + } + + $text = $this->retrieve($text); + $text = $this->replaceGlyphs($text); + $text = $this->retrieveTags($text); + $text = $this->retrieveURLs($text); + + $text = str_replace("
", "
\n", $text); + + return $text; + } + + /** + * Prepares the glyph patterns from the symbol table. + * + * @see Parser::setSymbol() + * @see Parser::getSymbol() + */ + + protected function prepGlyphs() + { + if ($this->rebuild_glyphs === false) { + return; + } + + extract($this->symbols, EXTR_PREFIX_ALL, 'txt'); + extract($this->regex_snippets); + $pnc = '[[:punct:]]'; + + if ($cur) { + $cur = '(?:['.$cur.']'.$space.'*)?'; + } + + $this->glyph_search = array(); + $this->glyph_replace = array(); + + // Dimension sign + $this->glyph_search[] = '/([0-9]+[\])]?[\'"]? ?)[xX]( ?[\[(]?)(?=[+-]?'.$cur.'[0-9]*\.?[0-9]+)/'.$mod; + $this->glyph_replace[] = '$1'.$txt_dimension.'$2'; + + // Apostrophe + $this->glyph_search[] = '/('.$wrd.'|\))\'('.$wrd.')/'.$mod; + $this->glyph_replace[] = '$1'.$txt_apostrophe.'$2'; + + // Back in '88/the '90s but not in his '90s', '1', '1.' '10m' or '5.png' + $this->glyph_search[] = '/('.$space.')\'(\d+'.$wrd.'?)\b(?![.]?['.$wrd.']*?\')/'.$mod; + $this->glyph_replace[] = '$1'.$txt_apostrophe.'$2'; + + // Single open following open bracket + $this->glyph_search[] = "/([([{])'(?=\S)/".$mod; + $this->glyph_replace[] = '$1'.$txt_quote_single_open; + + // Single closing + $this->glyph_search[] = '/(\S)\'(?='.$space.'|'.$pnc.'|<|$)/'.$mod; + $this->glyph_replace[] = '$1'.$txt_quote_single_close; + + // Default single opening + $this->glyph_search[] = "/'/"; + $this->glyph_replace[] = $txt_quote_single_open; + + // Double open following an open bracket. Allows things like Hello ["(Mum) & dad"] + $this->glyph_search[] = '/([([{])"(?=\S)/'.$mod; + $this->glyph_replace[] = '$1'.$txt_quote_double_open; + + // Double closing + $this->glyph_search[] = '/(\S)"(?='.$space.'|'.$pnc.'|<|$)/'.$mod; + $this->glyph_replace[] = '$1'.$txt_quote_double_close; + + // Default double opening + $this->glyph_search[] = '/"/'; + $this->glyph_replace[] = $txt_quote_double_open; + + // 3+ uppercase acronym + $this->glyph_search[] = '/\b(['.$abr.']['.$acr.']{2,})\b(?:[(]([^)]*)[)])/'.$mod; + + if ($this->doctype === 'html5') { + $this->glyph_replace[] = '$1'; + } else { + $this->glyph_replace[] = '$1'; + } + + // 3+ uppercase + $this->glyph_search[] = '/('.$space.'|^|[>(;-])(['.$abr.']{3,})'. + '(['.$nab.']*)(?='.$space.'|'.$pnc.'|<|$)(?=[^">]*?(<|$))/'.$mod; + $this->glyph_replace[] = '$1'.$this->uid.':glyph:$2$3'; + + // Ellipsis + $this->glyph_search[] = '/([^.]?)\.{3}/'; + $this->glyph_replace[] = '$1'.$txt_ellipsis; + + // em dash + $this->glyph_search[] = '/--/'; + $this->glyph_replace[] = $txt_emdash; + + // en dash + $this->glyph_search[] = '/ - /'; + $this->glyph_replace[] = ' '.$txt_endash.' '; + + // Trademark + $this->glyph_search[] = '/(\b ?|'.$space.'|^)[([]TM[])]/i'.$mod; + $this->glyph_replace[] = '$1'.$txt_trademark; + + // Registered + $this->glyph_search[] = '/(\b ?|'.$space.'|^)[([]R[])]/i'.$mod; + $this->glyph_replace[] = '$1'.$txt_registered; + + // Copyright + $this->glyph_search[] = '/(\b ?|'.$space.'|^)[([]C[])]/i'.$mod; + $this->glyph_replace[] = '$1'.$txt_copyright; + + // 1/4 + $this->glyph_search[] = '/[([]1\/4[])]/'; + $this->glyph_replace[] = $txt_quarter; + + // 1/2 + $this->glyph_search[] = '/[([]1\/2[])]/'; + $this->glyph_replace[] = $txt_half; + + // 3/4 + $this->glyph_search[] = '/[([]3\/4[])]/'; + $this->glyph_replace[] = $txt_threequarters; + + // Degrees -- that's a small 'oh' + $this->glyph_search[] = '/[([]o[])]/'; + $this->glyph_replace[] = $txt_degrees; + + // Plus minus + $this->glyph_search[] = '/[([]\+\/-[])]/'; + $this->glyph_replace[] = $txt_plusminus; + + // No need to rebuild next run unless a symbol is redefined + $this->rebuild_glyphs = false; + } + + /** + * Sets the maximum allowd link index. + * + * @return int + * @since 3.5.5 + */ + + protected function getMaxLinkIndex() + { + return 1000000; + } + + /** + * Prepares the parser for parsing. + * + * This method prepares the transient internal state of + * Textile parser in preparation for parsing a new document. + * + * @param bool $lite Controls lite mode + * @param bool $noimage Disallow images + * @param string $rel A relationship attribute applied to links + */ + + protected function prepare($lite, $noimage, $rel) + { + if ($this->linkIndex >= $this->getMaxLinkIndex()) { + $this->linkPrefix .= '-'; + $this->linkIndex = 1; + } + + $this->unreferencedNotes = array(); + $this->notelist_cache = array(); + $this->notes = array(); + $this->urlrefs = array(); + $this->shelf = array(); + $this->fn = array(); + $this->span_depth = 0; + $this->refIndex = 1; + $this->refCache = array(); + $this->note_index = 1; + $this->rel = $rel; + $this->lite = $lite; + $this->noimage = $noimage; + $this->prepGlyphs(); + } + + /** + * Cleans a HTML attribute value. + * + * This method checks for presence of URL encoding in the value. + * If the number encoded characters exceeds the thereshold, + * the input is discarded. Otherwise the encoded + * instances are decoded. + * + * This method also strips any ", ' and = characters + * from the given value. This method does not guarantee + * valid HTML or full sanitization. + * + * @param string $in The input string + * @return string Cleaned string + */ + + protected function cleanAttribs($in) + { + $tmp = $in; + $before = -1; + $after = 0; + $max = 3; + $i = 0; + + while (($after != $before) && ($i < $max)) { + $before = strlen($tmp); + $tmp = rawurldecode($tmp); + $after = strlen($tmp); + $i++; + } + + if ($i === $max) { + // If we hit the max allowed decodes, assume the input is tainted and consume it. + $out = ''; + } else { + $out = str_replace(array('"', "'", '='), '', $tmp); + } + + return $out; + } + + /** + * Constructs a HTML tag from an object. + * + * This is a helper method that creates a new + * instance of \Netcarver\Textile\Tag. + * + * @param string $name The HTML element name + * @param array $atts HTML attributes applied to the tag + * @param bool $selfclosing Determines if the tag should be selfclosing + * @return Tag + */ + + protected function newTag($name, $atts, $selfclosing = true) + { + return new Tag($name, $atts, $selfclosing); + } + + /** + * Parses Textile attributes. + * + * @param string $in The Textile attribute string to be parsed + * @param string $element Focus the routine to interpret the attributes as applying to a specific HTML tag + * @param bool $include_id If FALSE, IDs are not included in the attribute list + * @param string $autoclass An additional classes applied to the output + * @return string HTML attribute list + * @see Parser::parseAttribsToArray() + */ + + protected function parseAttribs($in, $element = '', $include_id = true, $autoclass = '') + { + $o = $this->parseAttribsToArray($in, $element, $include_id, $autoclass); + + return $this->formatAttributeString($o); + } + + /** + * Converts an array of named attribute => value mappings to a string. + * + * @param array $attribute_array + * @return string + */ + + protected function formatAttributeString(array $attribute_array) + { + $out = ''; + + if (count($attribute_array)) { + foreach ($attribute_array as $k => $v) { + $out .= " $k=\"$v\""; + } + } + + return $out; + } + + /** + * Parses Textile attributes into an array. + * + * @param string $in The Textile attribute string to be parsed + * @param string $element Focus the routine to interpret the attributes as applying to a specific HTML tag + * @param bool $include_id If FALSE, IDs are not included in the attribute list + * @param string $autoclass An additional classes applied to the output + * @return array HTML attributes as key => value mappings + * @see Parser::parseAttribs() + */ + + protected function parseAttribsToArray($in, $element = '', $include_id = true, $autoclass = '') + { + $style = ''; + $class = ''; + $lang = ''; + $colspan = ''; + $rowspan = ''; + $span = ''; + $width = ''; + $id = ''; + $atts = ''; + $align = ''; + + $matched = $in; + if ($element == 'td') { + if (preg_match("/\\\\([0-9]+)/", $matched, $csp)) { + $colspan = $csp[1]; + } + + if (preg_match("/\/([0-9]+)/", $matched, $rsp)) { + $rowspan = $rsp[1]; + } + } + + if ($element == 'td' or $element == 'tr') { + if (preg_match("/($this->vlgn)/", $matched, $vert)) { + $style[] = "vertical-align:" . $this->vAlign($vert[1]); + } + } + + if (preg_match("/\{([^}]*)\}/", $matched, $sty)) { + if ($sty[1] = $this->cleanAttribs($sty[1])) { + $style[] = rtrim($sty[1], ';'); + } + $matched = str_replace($sty[0], '', $matched); + } + + if (preg_match("/\[([^]]+)\]/U", $matched, $lng)) { + // Consume entire lang block -- valid or invalid. + $matched = str_replace($lng[0], '', $matched); + if (preg_match("/\[([a-zA-Z]{2}(?:[\-\_][a-zA-Z]{2})?)\]/U", $lng[0], $lng)) { + $lang = $lng[1]; + } + } + + if (preg_match("/\(([^()]+)\)/U", $matched, $cls)) { + + $class_regex = "/^([-a-zA-Z 0-9_\.]*)$/"; + + // Consume entire class block -- valid or invalid. + $matched = str_replace($cls[0], '', $matched); + + // Only allow a restricted subset of the CSS standard characters for classes/ids. + // No encoding markers allowed. + if (preg_match("/\(([-a-zA-Z 0-9_\.\:\#]+)\)/U", $cls[0], $cls)) { + $hashpos = strpos($cls[1], '#'); + // If a textile class block attribute was found with a '#' in it + // split it into the css class and css id... + if (false !== $hashpos) { + if (preg_match("/#([-a-zA-Z0-9_\.\:]*)$/", substr($cls[1], $hashpos), $ids)) { + $id = $ids[1]; + } + + if (preg_match($class_regex, substr($cls[1], 0, $hashpos), $ids)) { + $class = $ids[1]; + } + } else { + if (preg_match($class_regex, $cls[1], $ids)) { + $class = $ids[1]; + } + } + } + } + + if (preg_match("/([(]+)/", $matched, $pl)) { + $style[] = "padding-left:" . strlen($pl[1]) . "em"; + $matched = str_replace($pl[0], '', $matched); + } + + if (preg_match("/([)]+)/", $matched, $pr)) { + $style[] = "padding-right:" . strlen($pr[1]) . "em"; + $matched = str_replace($pr[0], '', $matched); + } + + if (preg_match("/($this->hlgn)/", $matched, $horiz)) { + $style[] = "text-align:" . $this->hAlign($horiz[1]); + } + + if ($element == 'col') { + if (preg_match("/(?:\\\\([0-9]+))?{$this->regex_snippets['space']}*([0-9]+)?/", $matched, $csp)) { + $span = isset($csp[1]) ? $csp[1] : ''; + $width = isset($csp[2]) ? $csp[2] : ''; + } + } + + if ($this->restricted) { + $o = array(); + $class = trim($autoclass); + if ($class) { + $o['class'] = $this->cleanAttribs($class); + } + + if ($lang) { + $o['lang'] = $this->cleanAttribs($lang); + } + + ksort($o); + return $o; + } else { + $class = trim($class . ' ' . $autoclass); + } + + $o = array(); + if ($class) { + $o['class'] = $this->cleanAttribs($class); + } + + if ($colspan) { + $o['colspan'] = $this->cleanAttribs($colspan); + } + + if ($id && $include_id) { + $o['id'] = $this->cleanAttribs($id); + } + + if ($lang) { + $o['lang'] = $this->cleanAttribs($lang); + } + + if ($rowspan) { + $o['rowspan'] = $this->cleanAttribs($rowspan); + } + + if ($span) { + $o['span'] = $this->cleanAttribs($span); + } + + if ($style) { + $so = ''; + $tmps = array(); + foreach ($style as $s) { + $parts = explode(';', $s); + foreach ($parts as $p) { + if ($p = trim(trim($p), ":")) { + $tmps[] = $p; + } + } + } + + sort($tmps); + foreach ($tmps as $p) { + if (!empty($p)) { + $so .= $p.';'; + } + } + $style = trim(str_replace(array("\n", ';;'), array('', ';'), $so)); + + $o['style'] = $style; + } + + if ($width) { + $o['width'] = $this->cleanAttribs($width); + } + + ksort($o); + return $o; + } + + /** + * Checks whether the text is not enclosed by a block tag. + * + * @param string $text The input string + * @return bool TRUE if the text is not enclosed + */ + + protected function hasRawText($text) + { + $r = preg_replace( + '@<(p|hr|br|img|blockquote|div|form|table|ul|ol|dl|pre|h[1-6])[^>]*?'.chr(62).'.*]*?>@si', + '', + trim($text) + ); + $r = trim(preg_replace('@<(br|hr|img)[^>]*?/?>@i', '', trim($r))); + return '' != $r; + } + + /** + * Parses textile table structures into HTML. + * + * @param string $text The textile input + * @return string The parsed text + */ + + protected function tables($text) + { + $text = $text . "\n\n"; + return preg_replace_callback( + "/^(?:table(?P_?{$this->s}{$this->a}{$this->cls})\.". + "(?P.*)?\n)?^(?P{$this->a}{$this->cls}\.? ?\|.*\|){$this->regex_snippets['space']}*\n\n/smU", + array(&$this, "fTable"), + $text + ); + } + + /** + * Constructs a HTML table from a textile table structure. + * + * This method is used by Parser::tables() to process + * found table structures. + * + * @param array $matches + * @return string HTML table + * @see Parser::tables() + */ + + protected function fTable($matches) + { + $tatts = $this->parseAttribs($matches['tatts'], 'table'); + $space = $this->regex_snippets['space']; + + $sum = trim($matches['summary']) + ? ' summary="'.htmlspecialchars(trim($matches['summary']), ENT_QUOTES, 'UTF-8').'"' + : ''; + $cap = ''; + $colgrp = ''; + $last_rgrp = ''; + $c_row = 1; + + foreach (preg_split("/\|{$space}*?$/m", $matches['rows'], -1, PREG_SPLIT_NO_EMPTY) as $row) { + + $row = ltrim($row); + + // Caption -- can only occur on row 1, otherwise treat '|=. foo |...' + // as a normal center-aligned cell. + if (($c_row <= 1) && preg_match( + "/^\|\=(?P$this->s$this->a$this->cls)\. (?P[^\n]*)(?P.*)/s", + ltrim($row), + $cmtch + )) { + $capts = $this->parseAttribs($cmtch['capts']); + $cap = "\t".trim($cmtch['cap'])."\n"; + $row = ltrim($cmtch['row']); + if (empty($row)) { + continue; + } + } + + $c_row += 1; + + // Colgroup + if (preg_match("/^\|:(?P$this->s$this->a$this->cls\. .*)/m", ltrim($row), $gmtch)) { + // Is this colgroup def missing a closing pipe? If so, there + // will be a newline in the middle of $row somewhere. + $nl = strpos($row, "\n"); + $idx = 0; + + foreach (explode('|', str_replace('.', '', $gmtch['cols'])) as $col) { + $gatts = $this->parseAttribs(trim($col), 'col'); + $colgrp .= "\t" : $gatts." />")."\n"; + $idx++; + } + + $colgrp .= "\t\n"; + + if ($nl === false) { + continue; + } else { + // Recover from our missing pipe and process the rest of the line. + $row = ltrim(substr($row, $nl)); + } + } + + // Row group + $rgrpatts = $rgrp = ''; + + if (preg_match( + "/(:?^\|(?P$this->vlgn)(?P$this->s$this->a$this->cls)\.{$space}*$\n)?^(?P.*)/sm", + ltrim($row), + $grpmatch + )) { + if (isset($grpmatch['part'])) { + if ($grpmatch['part'] === '^') { + $rgrp = 'head'; + } elseif ($grpmatch['part'] === '~') { + $rgrp = 'foot'; + } elseif ($grpmatch['part'] === '-') { + $rgrp = 'body'; + } + } + + if (isset($grpmatch['part'])) { + $rgrpatts = $this->parseAttribs($grpmatch['rgrpatts']); + } + + if (isset($grpmatch['row'])) { + $row = $grpmatch['row']; + } + } + + if (preg_match("/^(?P$this->a$this->cls\. )(?P.*)/m", ltrim($row), $rmtch)) { + $ratts = $this->parseAttribs($rmtch['ratts'], 'tr'); + $row = $rmtch['row']; + } else { + $ratts = ''; + } + + $cells = array(); + $cellctr = 0; + + foreach (explode("|", $row) as $cell) { + $ctyp = "d"; + + if (preg_match("/^_(?=[{$this->regex_snippets['space']}[:punct:]])/", $cell)) { + $ctyp = "h"; + } + + if (preg_match("/^(?P_?$this->s$this->a$this->cls\. )(?P.*)/s", $cell, $cmtch)) { + $catts = $this->parseAttribs($cmtch['catts'], 'td'); + $cell = $cmtch['cell']; + } else { + $catts = ''; + } + + if (!$this->lite) { + $a = array(); + + if (preg_match('/(?'.$this->regex_snippets['space'].'*)(?P.*)/s', $cell, $a)) { + $cell = $this->redclothLists($a['cell']); + $cell = $this->textileLists($cell); + $cell = $a['space'] . $cell; + } + } + + if ($cellctr > 0) { + // Ignore first 'cell': it precedes the opening pipe + $cells[] = $this->doTagBr("t$ctyp", "\t\t\t$cell"); + } + + $cellctr++; + } + + $grp = ''; + + if ($rgrp && $last_rgrp) { + $grp .= "\t\n"; + } + + if ($rgrp) { + $grp .= "\t\n"; + } + + $last_rgrp = ($rgrp) ? $rgrp : $last_rgrp; + $rows[] = $grp."\t\t\n" . join("\n", $cells) . ($cells ? "\n" : "") . "\t\t"; + unset($cells, $catts); + } + + $rows = join("\n", $rows) . "\n"; + $close = ''; + + if ($last_rgrp) { + $close = "\t\n"; + } + + return "\n".$cap.$colgrp.$rows.$close."\n\n"; + } + + /** + * Parses RedCloth-style definition lists into HTML. + * + * @param string $text The textile input + * @return string The parsed text + */ + + protected function redclothLists($text) + { + return preg_replace_callback( + "/^([-]+$this->cls[ .].*:=.*)$(?![^-])/smU", + array(&$this, "fRedclothList"), + $text + ); + } + + /** + * Constructs a HTML definition list from a RedCloth-style definition structure. + * + * This method is used by Parser::redclothLists() to process + * found definition list structures. + * + * @param array $m + * @return string HTML definition list + * @see Parser::redclothLists() + */ + + protected function fRedclothList($m) + { + $in = $m[0]; + $out = array(); + $text = preg_split('/\n(?=[-])/m', $in); + foreach ($text as $nr => $line) { + $m = array(); + if (preg_match("/^[-]+(?P$this->cls)\.? (?P.*)$/s", $line, $m)) { + $content = trim($m['content']); + $atts = $this->parseAttribs($m['atts']); + + if (!preg_match( + "/^(.*?){$this->regex_snippets['space']}*:=(.*?)". + "{$this->regex_snippets['space']}*(=:|:=)?". + "{$this->regex_snippets['space']}*$/s", + $content, + $xm + )) { + $xm = array( $content, $content, '' ); + } + + list(, $term, $def,) = $xm; + $term = trim($term); + $def = trim($def, ' '); + + if (empty($out)) { + if (''==$def) { + $out[] = ""; + } else { + $out[] = '
'; + } + } + + if ('' != $term) { + $pos = strpos($def, "\n"); + $def = str_replace("\n", "
", trim($def)); + if (0 === $pos) { + $def = '

' . $def . '

'; + } + $term = str_replace("\n", "
", $term); + + $term = $this->graf($term); + $def = $this->graf($def); + + $out[] = "\t$term"; + + if ($def) { + $out[] = "\t
$def
"; + } + } + } + } + $out[] = '
'; + return implode("\n", $out); + } + + /** + * Parses Textile list structures into HTML. + * + * Searches for ordered, un-ordered and definition lists in the + * textile input and generates HTML lists for them. + * + * @param string $text The input + * @return string The parsed text + */ + + protected function textileLists($text) + { + return preg_replace_callback( + "/^((?:[*;:]+|[*;:#]*#(?:_|\d+)?)$this->cls[ .].*)$(?![^#*;:])/smU", + array(&$this, "fTextileList"), + $text + ); + } + + /** + * Constructs a HTML list from a Textile list structure. + * + * This method is used by Parser::textileLists() to process + * found list structures. + * + * @param array $m + * @return string HTML list + * @see Parser::textileLists() + */ + + protected function fTextileList($m) + { + $text = preg_split('/\n(?=[*#;:])/m', $m[0]); + $pt = ''; + foreach ($text as $nr => $line) { + $nextline = isset($text[$nr+1]) ? $text[$nr+1] : false; + if (preg_match("/^(?P[#*;:]+)(?P_|\d+)?(?P$this->cls)[ .](?P.*)$/s", $line, $m)) { + $tl = $m['tl']; + $st = $m['st']; + $atts = $m['atts']; + $content = trim($m['content']); + $nl = ''; + $ltype = $this->liType($tl); + $litem = (strpos($tl, ';') !== false) ? 'dt' : ((strpos($tl, ':') !== false) ? 'dd' : 'li'); + $showitem = (strlen($content) > 0); + + if ('o' === $ltype) { + // Handle list continuation/start attribute on ordered lists. + if (!isset($this->olstarts[$tl])) { + $this->olstarts[$tl] = 1; + } + + if (strlen($tl) > strlen($pt)) { + // First line of this level of ol -- has a start attribute? + if ('' == $st) { + // No => reset count to 1. + $this->olstarts[$tl] = 1; + } elseif ('_' !== $st) { + // Yes, and numeric => reset to given. + // TRICKY: the '_' continuation marker just means + // output the count so don't need to do anything + // here. + $this->olstarts[$tl] = (int) $st; + } + } + + if ((strlen($tl) > strlen($pt)) && '' !== $st) { + // Output the start attribute if needed. + $st = ' start="' . $this->olstarts[$tl] . '"'; + } + + if ($showitem) { + // TRICKY: Only increment the count for list items; + // not when a list definition line is encountered. + $this->olstarts[$tl] += 1; + } + } + + if (preg_match("/^(?P[#*;:]+)(_|[\d]+)?($this->cls)[ .].*/", $nextline, $nm)) { + $nl = $nm['nextlistitem']; + } + + if ((strpos($pt, ';') !== false) && (strpos($tl, ':') !== false)) { + // We're already in a
so flag not to start another + $lists[$tl] = 2; + } + + $tabs = str_repeat("\t", strlen($tl)-1); + $atts = $this->parseAttribs($atts); + if (!isset($lists[$tl])) { + $lists[$tl] = 1; + $line = "$tabs<" . $ltype . "l$atts$st>" . (($showitem) ? "\n$tabs\t<$litem>" . $content : ''); + } else { + $line = ($showitem) ? "$tabs\t<$litem$atts>" . $content : ''; + } + + if ((strlen($nl) <= strlen($tl))) { + $line .= (($showitem) ? "" : ''); + } + + foreach (array_reverse($lists) as $k => $v) { + if (strlen($k) > strlen($nl)) { + $line .= ($v==2) ? '' : "\n$tabsliType($k) . "l>"; + if ((strlen($k) > 1) && ($v != 2)) { + $line .= ""; + } + unset($lists[$k]); + } + } + $pt = $tl; // Remember the current Textile tag + } + + $out[] = $line; + } + + $out = implode("\n", $out); + return $this->doTagBr($litem, $out); + } + + /** + * Determines the list type from the Textile input symbol. + * + * @param string $in Textile input containing the possible list marker + * @return string Either 'd', 'o', 'u' + */ + + protected function liType($in) + { + $m = array(); + $type = 'd'; + if (preg_match('/^(?P[#*]+)/', $in, $m)) { + $type = ('#' === substr($m['type'], -1)) ? 'o' : 'u'; + } + return $type; + } + + /** + * Adds br tags within the specified container tag. + * + * @param string $tag The tag + * @param string $in The input + * @return string + */ + + protected function doTagBr($tag, $in) + { + return preg_replace_callback( + '@<(?P'.preg_quote($tag).')(?P[^>]*?)>(?P.*)(?P)@s', + array(&$this, 'fBr'), + $in + ); + } + + /** + * Adds br tags to paragraphs and headings. + * + * @param string $in The input + * @return string + */ + + protected function doPBr($in) + { + return preg_replace_callback( + '@<(?Pp|h[1-6])(?P[^>]*?)>(?P.*)(?P)@s', + array(&$this, 'fPBr'), + $in + ); + } + + /** + * Less restrictive version of fBr method. + * + * Used only in paragraphs and headings where the next row may + * start with a smiley or perhaps something like '#8 bolt...' + * or '*** stars...'. + * + * @param string $m The input + * @return string + */ + + protected function fPBr($m) + { + // Replaces
\n instances that are not followed by white-space, + // or at end, with single LF. + $content = preg_replace( + "~{$this->regex_snippets['space']}*\n(?![{$this->regex_snippets['space']}|])~i", + "\n", + $m['content'] + ); + // Replaces those LFs that aren't followed by white-space, or at end, with
. + $content = preg_replace("/\n(?![\s|])/", '
', $content); + return '<'.$m['tag'].$m['atts'].'>'.$content.$m['closetag']; + } + + /** + * Formats line breaks. + * + * @param string $m The input + * @return string + */ + + protected function fBr($m) + { + $content = preg_replace("@(.+)(?|
|||)\n(?![#*;:\s|])@", '$1
', $m['content']); + return '<'.$m['tag'].$m['atts'].'>'.$content.$m['closetag']; + } + + /** + * Splits the given input into blocks. + * + * Blocks are separated by double line-break boundaries, and processed + * the blocks one by one. + * + * @param string $text Textile source text + * @return string Input text with blocks processed + */ + + protected function blocks($text) + { + $regex = '/^(?P'.join('|', $this->blocktag_whitelist).')'. + '(?P'.$this->a.$this->cls.')\.(?P\.?)(?::(?P\S+))? (?P.*)$/Ss'. + $this->regex_snippets['mod']; + + $textblocks = preg_split('/(\n{2,})/', $text, null, PREG_SPLIT_DELIM_CAPTURE); + + $eatWhitespace = false; + $whitespace = ''; + $ext = ''; + $out = array(); + + foreach ($textblocks as $block) { + + // Line is just whitespace, keep it for the next block. + if (trim($block) === '') { + if ($eatWhitespace === false) { + $whitespace .= $block; + } + continue; + } + + if (!$ext) { + $tag = 'p'; + $atts = ''; + $cite = ''; + $graf = ''; + $eat = false; + } + + $eatWhitespace = false; + $anonymous_block = !preg_match($regex, $block, $m); + + if (!$anonymous_block) { + // Last block was extended, so close it + if ($ext) { + $out[count($out)-1] .= $c1; + } + + // Extract the new block's parts + extract($m); + list($o1, $o2, $content, $c2, $c1, $eat) = $this->fBlock($m); + + // Leave off c1 if this block is extended, we'll close it at the start of the next block + $block = $o1.$o2.$content.$c2; + if (!$ext) { + $block .= $c1; + } + } else { + if ($ext || strpos($block, ' ') !== 0) { + list($o1, $o2, $content, $c2, $c1, $eat) = $this->fBlock(array( + 0, + $tag, + $atts, + $ext, + $cite, + $block, + )); + + // Skip $o1/$c1 because this is part of a continuing extended block + if ($tag == 'p' && !$this->hasRawText($content)) { + $block = $content; + } else { + $block = $o2.$content.$c2; + } + } else { + $block = $this->graf($block); + } + } + + $block = $this->doPBr($block); + $block = $whitespace. str_replace('
', '
', $block); + + if ($ext && $anonymous_block) { + $out[count($out)-1] .= $block; + } elseif (!$eat) { + $out[] = $block; + } + + if ($eat) { + $eatWhitespace = true; + } else { + $whitespace = ''; + } + + } + + if ($ext) { + $out[count($out)-1] .= $c1; + } + + return join('', $out); + } + + /** + * Formats the given block. + * + * Adds block tags and formats the text content inside + * the block. + * + * @param string $m The block content to format + * @return array + */ + + protected function fBlock($m) + { + list(, $tag, $att, $ext, $cite, $content) = $m; + $atts = $this->parseAttribs($att); + $space = $this->regex_snippets['space']; + + $o1 = ''; + $o2 = ''; + $c2 = ''; + $c1 = ''; + $eat = false; + + if ($tag === 'p') { + // Is this an anonymous block with a note definition? + $notedef = preg_replace_callback( + "/ + ^note\# # start of note def marker + (?P