/admin/class_modul_votings_admin.php
After having done both, the installer and the definition of the beans, the admin-view is the next step to work on.
class class_modul_votings_admin extends class_admin implements interface_admin {
public function __construct() {
$arrModul["name"] = "modul_votings";
$arrModul["author"] = "sidler @ mulchprod.de";
$arrModul["moduleId"] = _votings_modul_id_;
$arrModul["table"] = _dbprefix_."votings_voting";
$arrModul["table2"] = _dbprefix_."votings_answer";
$arrModul["modul"] = "votings";
parent::__construct($arrModul);
}
As already known, the constructor defines the usual meta-data. Not all of them are optional, e.g. they are needed to load the matching language-files. So make sure to maintain them the best you can.
public function action($strAction = "") {
$strReturn = "";
if($strAction == "")
$strAction = "list";
try {
if($strAction == "list")
$strReturn = $this->actionList();
else if($strAction == "newVoting")
$strReturn = $this->actionNewVoting("new");
else if($strAction == "editVoting")
$strReturn = $this->actionNewVoting("edit");
else if($strAction == "saveVoting") {
if($this->validateForm()) {
$strReturn = $this->actionSaveVoting();
if($strReturn == "")
$this->adminReload(getLinkAdminHref($this->arrModule["modul"]));
}
else {
if($this->getParam("mode") == "new")
$strReturn = $this->actionNewVoting("new");
else
$strReturn = $this->actionNewVoting("edit");
}
}
else if($strAction == "deleteVoting") {
$strReturn = $this->actionDeleteVoting();
if($strReturn == "")
$this->adminReload(getLinkAdminHref($this->arrModule["modul"]));
}
[ ... ]action parts for the answers [ ... ]
}
catch (class_exception $objException) {
$objException->processException();
$strReturn = "An internal error occured: ".$objException->getMessage();
}
$this->strOutput = $strReturn;
}
The action()-block controls the behavior of the class and calls the single methods, depending on the action requested. The action() method is called by the framework, passing the action to perform. If no action was passed, the class can decide what action to perform by default. In this case, the action “list” is considered as the default action, providing a list-view of the votings available (actionList()).
public function getOutputContent() {
return $this->strOutput;
}
The result of the execution is not returned via the return-value of the action() method, instead it's requested via the method getOutputContent() later on.
public function getOutputModuleNavi() {
$arrReturn = array();
$arrReturn[] = array("right", getLinkAdmin("right", "change", "&changemodule=".$this->arrModule["modul"], $this->getText("module_permissions"), "", "", true, "adminnavi"));
$arrReturn[] = array("", "");
$arrReturn[] = array("view", getLinkAdmin($this->arrModule["modul"], "list", "", $this->getText("module_list"), "", "", true, "adminnavi"));
$arrReturn[] = array("", "");
$arrReturn[] = array("edit", getLinkAdmin($this->arrModule["modul"], "newVoting", "", $this->getText("module_create"), "", "", true, "adminnavi"));
return $arrReturn;
}
The structure of the module-navigation (the navigation on the left side when using the standard-skin) is set up by the method getOutputModuleNavi(). Its return-value is a two-dimensional array, each entry being another array. It contains the name of the required permission and the link related to the permission. The framework checks whether the user has the sufficient permissions to display the link automatically and hides the link otherwise.
To build logical groups in the navigation, an array of empty values can be inserted to add a separator: $arrReturn[] = array("", "");
See in addition http://apidocs.kajona.de/v3.3.0/modul_system/class_admin.html#getOutputModuleNavi
protected function getRequiredFields() {
$strAction = $this->getAction();
$arrReturn = array();
if($strAction == "saveVoting") {
$arrReturn["voting_title"] = "string";
}
if($strAction == "saveAnswer") {
$arrReturn["answer_title"] = "string";
}
return $arrReturn;
}
The method getRequiredFields() can be used to validate the forms submitted by the user. If information is provided, the validation is done by the framework automatically. To use the validation, Kajona has to know what fields to validate at what action. In the example above, it'd be the field “voting_title” at action “saveVoting” and “answer_title” at “saveAnswer”. So, the method returns the fields to validate depending on the current action whereas the returned array is built up of entries schemed “field => data-type”.
The validation is triggered by calling $this->validateForm() in the action method.
The erroneous fields can be loaded, already formatted, and printed at a different location by calling $this->objToolkit->getValidationErrors($this).
See in addition
- http://apidocs.kajona.de/v3.3.0/modul_system/class_admin.html#getRequiredFields
- http://apidocs.kajona.de/v3.3.0/modul_system/class_admin.html#getValidationErrors
- http://apidocs.kajona.de/v3.3.0/modul_system/class_toolkit_admin.html#getValidationErrors
Now following is the rather long block of the actionList() method. It creates the table-based view of the votings. This method is one of the best places to get to know how to work with the toolkit, besides the form-generation mentioned in a later section.
private function actionList() {
$strReturn = "";
if($this->objRights->rightView($this->getModuleSystemid($this->arrModule["modul"]))) {
$strVotings = "";
$arrVotings = class_modul_votings_voting::getVotings();
$intI = 0;
It starts by verifying the permissions at module-level. If granted, the list of available votings is requested from the voting-bean. Afterwards, those votings are processed sequentially.
foreach($arrVotings as $objOneVoting) {
if($this->objRights->rightView($objOneVoting->getSystemid())) {
$strAction = "";
if($this->objRights->rightEdit($objOneVoting->getSystemid())) {
$strAction .= $this->objToolkit->listButton(getLinkAdmin($this->arrModule["modul"], "editVoting", "&systemid=".$objOneVoting->getSystemid(), "", $this->getText("voting_edit"), "icon_pencil.gif"));
$strAction .= $this->objToolkit->listButton(getLinkAdmin($this->arrModule["modul"], "listAnswers", "&systemid=".$objOneVoting->getSystemid(), "", $this->getText("voting_listAnswers"), "icon_book.gif"));
}
For every voting, the loop checks the permissions of the current user. Only if the user is allowed to view the voting, execution proceeds. Before printing the voting, all possible actions are collected, in this case the actions to edit (“editVoting”) and to list the associated answers (“listAnswers”) are built – again depending on the permissions. The button is rendered by the toolkits' method listButton(), build using additional util-functions.
See in addition
- http://apidocs.kajona.de/v3.3.0/modul_system/class_toolkit_admin.html#listButton
- http://apidocs.kajona.de/v3.3.0/modul_system/class_toolkit_admin.html#listDeleteButton
- http://apidocs.kajona.de/v3.3.0/modul_system/class_toolkit_admin.html#listStatusButton
- http://apidocs.kajona.de/v3.3.0/modul_system/_system---functions.php.html#functiongetLinkAdmin
if($this->objRights->rightDelete($objOneVoting->getSystemid()))
$strAction .= $this->objToolkit->listDeleteButton(
$objOneVoting->getStrTitle(), $this->getText("voting_delete_question"),
getLinkAdminHref($this->arrModule["modul"], "deleteVoting", "&systemid=".$objOneVoting->getSystemid()."&voting_delete_final=1&peClose=".$this->getParam("pe"))
);
if($this->objRights->rightEdit($objOneVoting->getSystemid()))
$strAction .= $this->objToolkit->listStatusButton($objOneVoting->getSystemid());
if($this->objRights->rightRight($objOneVoting->getSystemid()))
$strAction .= $this->objToolkit->listButton(getLinkAdmin("right", "change", "&systemid=".$objOneVoting->getSystemid(), "", $this->getText("voting_permissions"), getRightsImageAdminName($objOneVoting->getSystemid())));
$strVotings .= $this->objToolkit->listRow2Image(getImageAdmin("icon_question.gif"), uniStrTrim($objOneVoting->getStrTitle(), 80), $strAction, $intI++);
The row for each voting is added by calling listRow2Image() - a row containing an image and two content-elements; the name of the voting and the actions.
}
}
if($this->objRights->rightEdit($this->getModuleSystemid($this->arrModule["modul"])))
$strVotings .= $this->objToolkit->listRow2Image("", "", getLinkAdmin($this->arrModule["modul"], "newVoting", "", $this->getText("module_create"), $this->getText("module_create"), "icon_blank.gif"), $intI++);
A row to create a new voting completes the list.
if(uniStrlen($strVotings) != 0)
$strVotings = $this->objToolkit->listHeader().$strVotings.$this->objToolkit->listFooter();
if(count($arrVotings) == 0)
$strVotings.= $this->getText("list_empty");
$strReturn .= $strVotings;
}
else
$strReturn = $this->getText("error_permissions");
return $strReturn;
}
To create a new voting or edit an already existing one, the action() method calls actionNewVoting() parametrized with the requested edit-type.
private function actionNewVoting($strMode = "new") {
$strReturn = "";
if($strMode == "new") {
//Form to create new votings
if($this->objRights->rightEdit($this->getModuleSystemid($this->arrModule["modul"]))) {
$strReturn .= $this->objToolkit->getValidationErrors($this);
$strReturn .= $this->objToolkit->formHeader(getLinkAdminHref($this->arrModule["modul"], "saveVoting"));
$strReturn .= $this->objToolkit->formInputTextArea("voting_title", $this->getText("voting_title"), $this->getParam("voting_title"));
$strReturn .= $this->objToolkit->formDateSingle("voting_start", $this->getText("voting_start"), new class_date());
$strReturn .= $this->objToolkit->formDateSingle("voting_end", $this->getText("voting_end"), null);
$strReturn .= $this->objToolkit->formInputHidden("systemid", "");
$strReturn .= $this->objToolkit->formInputHidden("mode", "new");
$strReturn .= $this->objToolkit->formInputHidden("peClose", $this->getParam("pe"));
$strReturn .= $this->objToolkit->formInputSubmit($this->getText("button_save"));
$strReturn .= $this->objToolkit->formClose();
$strReturn .= $this->objToolkit->setBrowserFocus("votings_title");
}
else
$strReturn .= $this->getText("error_permissions");
}
When creating a new voting, the permissions are checked on module-level, the form is created with empty fields. The element-name “voting_title” matches the value used in getRequiredFields(), providing the automated validation. Errors are printed by calling $this->objToolkit->getValidationErrors() at the head of the page.
elseif ($strMode == "edit") {
//Rights
if($this->objRights->rightEdit($this->getSystemid())) {
$objVoting = new class_modul_votings_voting($this->getSystemid());
$strReturn .= $this->objToolkit->getValidationErrors($this);
$strReturn .= $this->objToolkit->formHeader(getLinkAdminHref($this->arrModule["modul"], "saveVoting"));
$strReturn .= $this->objToolkit->formInputTextArea("voting_title", $this->getText("voting_title"), $objVoting->getStrTitle());
$strReturn .= $this->objToolkit->formDateSingle("voting_start", $this->getText("voting_start"), $objVoting->getLongDateStart() != 0 ? new class_date($objVoting->getLongDateStart()) : null);
$strReturn .= $this->objToolkit->formDateSingle("voting_end", $this->getText("voting_end"), $objVoting->getLongDateEnd() != 0 ? new class_date($objVoting->getLongDateEnd()) : null);
$strReturn .= $this->objToolkit->formInputHidden("systemid", $this->getSystemid());
$strReturn .= $this->objToolkit->formInputHidden("mode", "edit");
$strReturn .= $this->objToolkit->formInputHidden("peClose", $this->getParam("pe"));
$strReturn .= $this->objToolkit->formInputSubmit($this->getText("button_save"));
$strReturn .= $this->objToolkit->formClose();
$strReturn .= $this->objToolkit->setBrowserFocus("votings_title");
}
else
$strReturn .= $this->getText("error_permissions");
}
return $strReturn;
}
When editing an existing voting, the permissions are checked right in context of the voting, the fields are populated with the values of the voting.
The form is created completely by toolkit-functionality.
private function actionSaveVoting() {
$strReturn = "";
$objVoting = null;
if($this->getParam("mode") == "new" && $this->objRights->rightEdit($this->getModuleSystemid($this->arrModule["modul"]))) {
$objVoting = new class_modul_votings_voting();
}
elseif($this->getParam("mode") == "edit" && $this->objRights->rightEdit($this->getSystemid())) {
$objVoting = new class_modul_votings_voting($this->getSystemid());
}
if($objVoting != null) {
$objVoting->setStrTitle($this->getParam("voting_title"));
//parse passed dates
$objStartDate = new class_date("0");
$objStartDate->generateDateFromParams("voting_start", $this->getAllParams());
$objEndDate = new class_date("0");
$objEndDate->generateDateFromParams("voting_end", $this->getAllParams());
$objVoting->setLongDateStart($objStartDate->getLongTimestamp());
$objVoting->setLongDateEnd($objEndDate->getLongTimestamp());
if(!$objVoting->updateObjectToDb( $this->getModuleSystemid($this->arrModule["modul"])))
throw new class_exception("Error updating object to db", class_exception::$level_ERROR);
}
else
$strReturn .= $this->getText("error_permissions");
return $strReturn;
}
The only difference between new and existing objects is done during initialization of the voting in order to save it. The processing of the date-values is done by the class_date transparently just by calling generateDateFromParams().
When saving the object you don't have to take care whether the object is a new or an existing one, this is done by the framework.
See in addition
- http://apidocs.kajona.de/v3.3.0/modul_system/class_date.html
- http://apidocs.kajona.de/v3.3.0/modul_system/class_date.html#generateDateFromParams
- http://apidocs.kajona.de/v3.3.0/modul_system/class_model.html#updateObjectToDb
private function actionDeleteVoting() {
$strReturn = "";
if($this->objRights->rightDelete($this->getSystemid())) {
if($this->getParam("voting_delete_final") == "") {
$objFaq = new class_modul_votings_voting($this->getSystemid());
$strName = $objFaq->getStrTitle();
$strReturn .= $this->objToolkit->warningBox($strName
."<br /><a href=\"".http://www.kajona.de/index.php."?admin=1&module=".$this->arrModule["modul"]."&action=deleteVoting&systemid="
.$this->getSystemid().($this->getParam("pe") == "" ? "" : "&peClose=".$this->getParam("pe"))."&voting_delete_final=1\">"
.$this->getText("voting_delete_question"));
}
elseif($this->getParam("voting_delete_final") == "1") {
$objVoting = new class_modul_votings_voting($this->getSystemid());
if(!$objVoting->deleteVoting())
throw new class_exception("Error deleting object from db", class_exception::$level_ERROR);
}
}
else
$strReturn .= $this->getText("error_permissions");
return $strReturn;
}
The method actionDeleteVoting() is called as soon as a voting should be deleted. The first part creates a confirmation dialog shown in the portal-editor. When deleting a voting via the backend, the dialog was generated in actionList() before, so there's no need to show another warning-message – the second part is executed directly. The voting is deleted by calling the matching method on the voting bean.
[ ... Answer-Functions ... ]
}
The methods to manage the answers are nearly the same and don't have to be analyzed again.
The only relevant difference is when saving an answer:
if(!$objAnswer->updateObjectToDb( $this->getParam("votingid") ) )
The parameter when calling updateObjectToDb() is the id of the related voting. By passing this id, the framework creates the relation between voting and answer automatically in the background.



