diff --git a/application/config/config-defaults.php b/application/config/config-defaults.php index 3f7b4facdf7..1fe5ed92145 100644 --- a/application/config/config-defaults.php +++ b/application/config/config-defaults.php @@ -94,7 +94,9 @@ $config['memory_limit'] = '256'; // This sets how much memory LimeSurvey can access in megabytes. 256 MB is the minimum recommended - if you are using PDF functions up to 512 MB may be needed $config['showpopups'] = 1; // Show popup messages if mandatory or conditional questions have not been answered correctly. -// 1=Show popup message, 0=Show message on page instead. +// 1 = Show popup message (default) +// 0 = Show message on page instead; +// -1 = Do not show the message at all (in this case, users will still see the question-specific tips indicating which questions must be answered). $config['maxemails'] = 50; // The maximum number of emails to send in one go (this is to prevent your mail server or script from timeouting when sending mass mail) diff --git a/application/controllers/admin/themes.php b/application/controllers/admin/themes.php index bdb320164c6..e33e3704700 100755 --- a/application/controllers/admin/themes.php +++ b/application/controllers/admin/themes.php @@ -75,7 +75,6 @@ public function templatezip($templatename) } } - /** * Exports a deprecated template * @@ -89,10 +88,39 @@ public function deprecatedtemplatezip($templatename) $templatename = sanitize_dirname($templatename); $usertemplaterootdir = Yii::app()->getConfig("uploaddir").DIRECTORY_SEPARATOR."templates"; $templatePath = $usertemplaterootdir.DIRECTORY_SEPARATOR.$templatename; + $this->folderzip($templatename, $templatePath); + } + /** + * Exports a broken theme + * + * @access public + * @param string $templatename + * @return void + */ + public function brokentemplatezip($templatename) + { + //$oEditedTemplate = Template::model()->getTemplateConfiguration($templatename); + $templatename = sanitize_dirname($templatename); + $templatePath = Yii::app()->getConfig("userthemerootdir").DIRECTORY_SEPARATOR.$templatename; + $this->folderzip($templatename, $templatePath); + } + + /** + * Exports a theme folder + * NOTE: This function must remain private !!! it doesn't sanitize the $templatePath + * This should be done by the proxy function (eg: deprecatedtemplatezip(), brokentemplatezip() ) + * + * @access public + * @param string $templatename + * @return void + */ + private function folderzip($templatename, $templatePath) + { if (!Permission::model()->hasGlobalPermission('templates','export')){ - die('No permission'); + Yii::app()->setFlashMessage(gT("We are sorry but you don't have permissions to do this."), 'error'); + $this->getController()->redirect(array("admin/themeoptions")); } $tempdir = Yii::app()->getConfig('tempdir'); @@ -116,8 +144,8 @@ public function deprecatedtemplatezip($templatename) // Delete the temporary file unlink($zipfile); } - } + } /** * Retrieves a temporary template file from disk @@ -616,10 +644,28 @@ public function delete($templatename) } else { Yii::app()->setFlashMessage(gT("We are sorry but you don't have permissions to do this."), 'error'); } + + // Redirect with default templatename, editfile and screenname $this->getController()->redirect(array("admin/themeoptions")); } + public function deleteBrokenTheme($templatename) + { + // First we check that the theme is really broken + $aBrokenThemes = Template::getBrokenThemes(); + $templatename = sanitize_dirname($templatename); + if (array_key_exists($templatename, $aBrokenThemes)) { + if (rmdirr(Yii::app()->getConfig('userthemerootdir')."/".$templatename)){ + Yii::app()->setFlashMessage(sprintf(gT("Theme '%s' was successfully deleted."), $templatename)); + } + }else{ + Yii::app()->setFlashMessage(gT("Not a broken theme!"), 'error'); + } + + $this->getController()->redirect(array("admin/themeoptions")); + } + /** * Function responsible to save the changes made in CodemMirror editor. * @@ -1185,7 +1231,7 @@ protected function _initialise($templatename, $screenname, $editfile, $showsumma $thissurvey['include_content'] = $sContentFile; - + try { $myoutput = Yii::app()->twigRenderer->renderTemplateForTemplateEditor( $sLayoutFile, diff --git a/application/helpers/SurveyRuntimeHelper.php b/application/helpers/SurveyRuntimeHelper.php index 93f3e2ceff6..25b0fca82d4 100644 --- a/application/helpers/SurveyRuntimeHelper.php +++ b/application/helpers/SurveyRuntimeHelper.php @@ -391,8 +391,8 @@ public function run($surveyid, $args) $bShowpopups = Yii::app()->getConfig('showpopups'); $aErrorHtmlMessage = $this->getErrorHtmlMessage(); - $this->aSurveyInfo['errorHtml']['show'] = !empty($aErrorHtmlMessage); - $this->aSurveyInfo['errorHtml']['hiddenClass'] = $bShowpopups ? "ls-js-hidden " : ""; + $this->aSurveyInfo['errorHtml']['show'] = !empty($aErrorHtmlMessage) && $bShowpopups==0; + $this->aSurveyInfo['errorHtml']['hiddenClass'] = $bShowpopups==1 ? "ls-js-hidden " : ""; $this->aSurveyInfo['errorHtml']['messages'] = $aErrorHtmlMessage; $_gseq = -1; @@ -1420,7 +1420,7 @@ private function getErrorHtmlMessage() } // Question(s) with not valid answer(s) - if ($this->aStepInfo['valid'] && $this->okToShowErrors) { + if (!$this->aStepInfo['valid'] && $this->okToShowErrors) { $aErrorsMandatory[] = gT("One or more questions have not been answered in a valid manner. You cannot proceed until these answers are valid."); } diff --git a/application/models/Assessment.php b/application/models/Assessment.php index 778c0465546..0d3d6e175c1 100644 --- a/application/models/Assessment.php +++ b/application/models/Assessment.php @@ -92,30 +92,31 @@ public function getButtons() { $buttons = "
"; $raw_button_template = "" - . ""; - - if (Permission::model()->hasGlobalPermission('assessments', 'update')) { - $editData = array( - 'action_assessments_editModal', - 'text-danger', - gT("Edit this assessment rule"), - 'edit' - ); - $deleteData = array( - 'action_assessments_deleteModal', - 'text-danger', - gT("Delete this assessment rule"), - 'trash text-danger' - ); - + $editData = array( + 'action_assessments_editModal', + 'text-info', + gT("Edit this assessment rule"), + 'edit', + gT("Edit") + ); + $deleteData = array( + 'action_assessments_deleteModal', + 'text-danger', + gT("Delete this assessment rule"), + 'trash text-danger', + gT("Delete") + ); + if (Permission::model()->hasSurveyPermission($this->sid,'assessments', 'delete')) { $buttons .= vsprintf($raw_button_template, $deleteData); + } + if (Permission::model()->hasSurveyPermission($this->sid,'assessments', 'update')) { $buttons .= vsprintf($raw_button_template, $editData); } - $buttons .= '
'; - + return $buttons; } diff --git a/application/models/Template.php b/application/models/Template.php index ccd941d1017..428d23ab31e 100755 --- a/application/models/Template.php +++ b/application/models/Template.php @@ -221,7 +221,7 @@ public function checkTemplateExtends() if (empty($oRTemplate)) { // Why? it blocks the user at login screen.... - // It should return false and show a nice warning message. + // It should return false and show a nice warning message. /*throw new Exception( sprintf( @@ -677,6 +677,32 @@ static public function getDeprecatedTemplates() return $aTemplateList; } + /** + * Retrieves a list of broken themes + */ + public static function getBrokenThemes($sFolder=null) + { + $aBrokenTemplateList = array(); + $sFolder = (empty($sFolder))?Yii::app()->getConfig("userthemerootdir"):$sFolder; + + if ($sFolder && $handle = opendir($sFolder)) { + while (false !== ($sFileName = readdir($handle))) { + if (!is_file("$sFolder/$sFileName") && $sFileName != "." && $sFileName != ".." && $sFileName != ".svn" && $sFileName != 'generalfiles' ) { + + try { + $oTheme = Template::getTemplateConfiguration($sFileName, null, null, true); // Get the manifest; + }catch (Exception $e) { + $aBrokenTemplateList[$sFileName] = $e; + } + } + } + closedir($handle); + } + ksort($aBrokenTemplateList); + return $aBrokenTemplateList; + } + + /** * Returns the static model of the specified AR class. * Please note that you should have this exact method in all your CActiveRecord descendants! diff --git a/application/models/TemplateConfig.php b/application/models/TemplateConfig.php index 3cc20aa3bf3..05196258734 100644 --- a/application/models/TemplateConfig.php +++ b/application/models/TemplateConfig.php @@ -112,7 +112,7 @@ public function getTemplateURL() /** * Get the template for a given file. It checks if a file exist in the current template or in one of its mother templates * Can return a 302 redirect (this is not really a throw … - * + * * @param string $sFile the file to look for (must contain relative path, unless it's a view file) * @param TemplateConfig $oRTemplate template from which the recurrence should start * @param boolean $force file to be in template or mother template @@ -730,7 +730,7 @@ public function getClassAndAttributes() $aClassAndAttributes['attr']['clearalllinks'] = $aClassAndAttributes['attr']['clearalllink'] = ' '; // Clearall Buttons $aClassAndAttributes['class']['clearallwrapper'] = $aClassAndAttributes['class']['clearallconfirm'] = ""; // No need, adding it if need something after - $aClassAndAttributes['class']['clearalllabel'] = "ls-js-hidden"; + $aClassAndAttributes['class']['clearalllabel'] = "ls-js-hidden"; $aClassAndAttributes['attr']['clearallconfirm'] = 'value="confirm" name="confirm-clearall" type="checkbox"'; $aClassAndAttributes['attr']['clearallbutton'] = 'type="submit" value="clearall" name="move" data-confirmedby="confirm-clearall"'; $aClassAndAttributes['class']['clearallbutton'] = "ls-clearaction ls-clearall"; // Not needed, keep it (and adding to twig to be most compatible in future) diff --git a/application/views/admin/conditions/conditionshead_view.php b/application/views/admin/conditions/conditionshead_view.php index e2349a91f24..cbba22654ee 100644 --- a/application/views/admin/conditions/conditionshead_view.php +++ b/application/views/admin/conditions/conditionshead_view.php @@ -24,13 +24,13 @@ class='btn btn-warning pull-right condition-header-button' class="btn btn-default pull-right condition-header-button" data-toggle='modal' data-target='#confirmation-modal' - data-message='' + data-message='' data-onclick='(function() { document.getElementById("toplevelsubaction").value="renumberscenarios"; document.getElementById("deleteallconditions").submit();})' onclick='return false;' >   - + diff --git a/application/views/admin/themeoptions/index.php b/application/views/admin/themeoptions/index.php index 4336e8c7ac7..aeab45bbfa2 100644 --- a/application/views/admin/themeoptions/index.php +++ b/application/views/admin/themeoptions/index.php @@ -35,6 +35,7 @@ renderPartial('themeoptions/surveythememenu',['canImport'=>$canImport,'importErrorMessage'=>$importErrorMessage]); ?> renderPartial('themeoptions/surveythemelist', array( 'oSurveyTheme'=> $oSurveyTheme )); ?> + templatesWithNoDb) > 0 ):?>

@@ -69,6 +70,63 @@
+ + 0 ):?> + + + +
+
+ +
+ + + + + + + + + $oBrokenTheme):?> + + + + + + + + +
getMessage(); ?>
+ + + hasGlobalPermission('templates','export') && function_exists("zip_open")):?> + + + + + + + + hasGlobalPermission('templates','delete')):?> + ", "_top")'> + + + + + +
+ +
+ +
+
+ + + + + 0 ):?> diff --git a/assets/packages/template-core/template-core.js b/assets/packages/template-core/template-core.js index 0be2d1a8820..83ad33d4532 100644 --- a/assets/packages/template-core/template-core.js +++ b/assets/packages/template-core/template-core.js @@ -21,9 +21,11 @@ var TemplateCoreClass = function () { }, /* alertSurveyDialog @see application/core/package/limesurvey */ alertSurveyDialog: function (text, title) { - $("#bootstrap-alert-box-modal .modal-header .modal-title").text(title || ""); - $("#bootstrap-alert-box-modal .modal-body").html("

" + text + "

" || ""); - $("#bootstrap-alert-box-modal").modal('show'); + if (LSvar.showpopup===1) { + $("#bootstrap-alert-box-modal .modal-header .modal-title").text(title || ""); + $("#bootstrap-alert-box-modal .modal-body").html("

" + text + "

" || ""); + $("#bootstrap-alert-box-modal").modal('show'); + } }, /* confirmSurveyDialog @see application/core/package/limesurvey */ confirmSurveyDialog: function (text, title, submits) {