4require_once 
"./Services/Object/classes/class.ilObjectGUI.php";
 
    6require_once 
'Modules/Test/classes/class.ilObjTest.php';
 
    7require_once 
'Modules/TestQuestionPool/classes/class.ilAssQuestionProcessLocker.php';
 
   26    public function __construct($a_data, $a_id = 0, $a_call_by_reference = 
true, $a_prepare_output = 
true)
 
   31        parent::__construct($a_data, $a_id, $a_call_by_reference, 
false);
 
   33        if (!
$rbacsystem->checkAccess(
'read', $this->object->getRefId())) {
 
   34            $this->
ilias->raiseError($this->lng->txt(
"msg_no_perm_read_assf"), $this->ilias->error_obj->WARNING);
 
   37        $this->lng->loadLanguageModule(
'assessment');
 
   48        $next_class = $this->ctrl->getNextClass($this);
 
   49        $cmd = $this->ctrl->getCmd();
 
   52        switch ($next_class) {
 
   53            case 'ilpermissiongui':
 
   54                $ilTabs->activateTab(
'perm_settings');
 
   55                include_once(
"Services/AccessControl/classes/class.ilPermissionGUI.php");
 
   57                $ret =&$this->ctrl->forwardCommand($perm_gui);
 
   60            case 'ilsettingstemplategui':
 
   64            case 'ilglobalunitconfigurationgui':
 
   65                if (!$rbacsystem->checkAccess(
'write', $this->object->getRefId())) {
 
   66                    $this->
ilias->raiseError($this->lng->txt(
'permission_denied'), $this->ilias->error_obj->WARNING);
 
   69                $ilTabs->setTabActive(
'units');
 
   71                require_once 
'Modules/TestQuestionPool/classes/class.ilGlobalUnitConfigurationGUI.php';
 
   72                require_once 
'Modules/TestQuestionPool/classes/class.ilUnitConfigurationRepository.php';
 
   76                $this->ctrl->forwardCommand($gui);
 
   80                if ($cmd == 
"" || $cmd == 
"view") {
 
  101        $newObj = parent::saveObject();
 
  108        $this->ctrl->redirect($this);
 
  119        $ilTabs->setTabActive(
'settings');
 
  121        if (
$form === 
null) {
 
  122            $form = $this->buildSettingsForm();
 
  125        $this->tpl->setVariable(
"ADM_CONTENT", 
$form->getHTML());
 
  128    private function buildSettingsForm()
 
  135        include_once 
"./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
 
  136        include_once(
"./Services/Form/classes/class.ilPropertyFormGUI.php");
 
  138        $form->setFormAction($this->ctrl->getFormAction($this));
 
  139        $form->setTableWidth(
"100%");
 
  140        $form->setId(
"settings");
 
  143        $header->setTitle($this->lng->txt(
'settings'));
 
  147        $chb = 
new ilCheckboxInputGUI($this->lng->txt(
'ass_process_lock'), 
'ass_process_lock');
 
  149        $chb->setInfo($this->lng->txt(
'ass_process_lock_desc'));
 
  150        $form->addItem($chb);
 
  151        $rg = 
new ilRadioGroupInputGUI($this->lng->txt(
'ass_process_lock_mode'), 
'ass_process_lock_mode');
 
  152        $rg->setRequired(
true);
 
  154        $opt->setInfo($this->lng->txt(
'ass_process_lock_mode_file_desc'));
 
  155        $rg->addOption($opt);
 
  157        $opt->setInfo($this->lng->txt(
'ass_process_lock_mode_db_desc'));
 
  158        $rg->addOption($opt);
 
  160            $rg->setValue($this->object->getAssessmentProcessLockMode());
 
  162        $chb->addSubItem($rg);
 
  164        $assessmentSetting = 
new ilSetting(
'assessment');
 
  165        $imap_line_color   = array_key_exists(
'imap_line_color', 
$_GET) ? 
$_GET[
'imap_line_color'] : $assessmentSetting->get(
'imap_line_color');
 
  166        if (strlen($imap_line_color) == 0) {
 
  167            $imap_line_color = 
'FF0000';
 
  170        $linepicker = 
new ilColorPickerInputGUI($this->lng->txt(
'assessment_imap_line_color'), 
'imap_line_color');
 
  171        $linepicker->setValue($imap_line_color);
 
  172        $form->addItem($linepicker);
 
  174        $user_criteria = array_key_exists(
'user_criteria', 
$_GET) ? 
$_GET[
'user_criteria'] : $assessmentSetting->get(
'user_criteria');
 
  175        $userCriteria  = 
new ilSelectInputGUI($this->lng->txt(
'user_criteria'), 
'user_criteria');
 
  176        $userCriteria->setInfo($this->lng->txt(
'user_criteria_desc'));
 
  177        $userCriteria->setRequired(
true);
 
  179        $fields     = array(
'usr_id', 
'login', 
'email', 
'matriculation', 
'ext_account');
 
  180        $usr_fields = array();
 
  181        foreach ($fields as $field) {
 
  182            $usr_fields[$field] = $field;
 
  184        $userCriteria->setOptions($usr_fields);
 
  185        $userCriteria->setValue($user_criteria);
 
  186        $form->addItem($userCriteria);
 
  189            $this->lng->txt(
'tst_skill_triggerings_num_req_answers'),
 
  192        $numRequiredAnswers->setInfo($this->lng->txt(
'tst_skill_triggerings_num_req_answers_desc'));
 
  193        $numRequiredAnswers->setSize(4);
 
  194        $numRequiredAnswers->allowDecimals(
false);
 
  195        $numRequiredAnswers->setMinValue(1);
 
  196        $numRequiredAnswers->setMinvalueShouldBeGreater(
false);
 
  197        $numRequiredAnswers->setValue($this->object->getSkillTriggeringNumAnswersBarrier());
 
  198        $form->addItem($numRequiredAnswers);
 
  200        $ceeqwh = 
new ilCheckboxInputGUI($this->lng->txt(
'export_essay_qst_with_html'), 
'export_essay_qst_with_html');
 
  201        $ceeqwh->setChecked($this->object->getExportEssayQuestionsWithHtml());
 
  202        $ceeqwh->setInfo($this->lng->txt(
'export_essay_qst_with_html_desc'));
 
  203        $form->addItem($ceeqwh);
 
  207        $header->setTitle($this->lng->txt(
"assf_questiontypes"));
 
  211        $allowed = 
new ilCheckboxGroupInputGUI($this->lng->txt(
'assf_allowed_questiontypes'), 
"chb_allowed_questiontypes");
 
  214        $allowedtypes = array();
 
  215        foreach ($questiontypes as $qt) {
 
  216            if (!in_array($qt[
'question_type_id'], $forbidden_types)) {
 
  217                array_push($allowedtypes, $qt[
'question_type_id']);
 
  220        $allowed->setValue($allowedtypes);
 
  221        foreach ($questiontypes as $type_name => $qtype) {
 
  222            $allowed->addOption(
new ilCheckboxOption($type_name, $qtype[
"question_type_id"]));
 
  224        $allowed->setInfo($this->lng->txt(
'assf_allowed_questiontypes_desc'));
 
  225        $form->addItem($allowed);
 
  228        $manual = 
new ilCheckboxGroupInputGUI($this->lng->txt(
'assessment_log_manual_scoring_activate'), 
"chb_manual_scoring");
 
  230        $manual->setValue($manscoring);
 
  231        foreach ($questiontypes as $type_name => $qtype) {
 
  232            $manual->addOption(
new ilCheckboxOption($type_name, $qtype[
"question_type_id"]));
 
  234        $manual->setInfo($this->lng->txt(
'assessment_log_manual_scoring_desc'));
 
  235        $form->addItem($manual);
 
  238        $scoring_activation = 
new ilCheckboxInputGUI($this->lng->txt(
'assessment_scoring_adjust'), 
'chb_scoring_adjust');
 
  239        $scoring_activation->setChecked($this->object->getScoringAdjustmentEnabled());
 
  240        $scoring_activation->setInfo($this->lng->txt(
'assessment_scoring_adjust_desc'));
 
  241        $form->addItem($scoring_activation);
 
  244        $scoring = 
new ilCheckboxGroupInputGUI($this->lng->txt(
'assessment_log_scoring_adjustment_activate'), 
"chb_scoring_adjustment");
 
  245        $scoring_active = $this->
object->getScoringAdjustableQuestions();
 
  246        $scoring->setValue($scoring_active);
 
  247        foreach ($this->object->fetchScoringAdjustableTypes($questiontypes) as $type_name => $qtype) {
 
  248            $scoring->addOption(
new ilCheckboxOption($type_name, $qtype[
"question_type_id"]));
 
  250        $scoring->setInfo($this->lng->txt(
'assessment_log_scoring_adjustment_desc'));
 
  251        $form->addItem($scoring);
 
  253        if ($ilAccess->checkAccess(
"write", 
"", $this->object->getRefId())) {
 
  254            $form->addCommandButton(
"saveSettings", $this->lng->txt(
"save"));
 
  266        if (!$ilAccess->checkAccess(
"write", 
"", $this->object->getRefId())) {
 
  267            $this->ctrl->redirect($this, 
'settings');
 
  270        $form = $this->buildSettingsForm();
 
  271        if (!
$form->checkInput()) {
 
  272            $form->setValuesByPost();
 
  276        $this->
object->setSkillTriggeringNumAnswersBarrier((
int) 
$_POST[
'num_req_answers']);
 
  277        $this->
object->setExportEssayQuestionsWithHtml((
int) $_POST[
"export_essay_qst_with_html"] == 1);
 
  278        $this->
object->_setManualScoring($_POST[
"chb_manual_scoring"]);
 
  279        include_once 
"./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
 
  281        $forbidden_types = array();
 
  282        foreach ($questiontypes as 
$name => 
$row) {
 
  283            if (!in_array(
$row[
"question_type_id"], 
$_POST[
"chb_allowed_questiontypes"])) {
 
  284                array_push($forbidden_types, 
$row[
"question_type_id"]);
 
  287        $this->
object->_setForbiddenQuestionTypes($forbidden_types);
 
  289        $this->
object->setScoringAdjustmentEnabled($_POST[
'chb_scoring_adjust']);
 
  290        $scoring_types = array();
 
  291        foreach ($questiontypes as 
$name => 
$row) {
 
  292            if (in_array(
$row[
"question_type_id"], (array) 
$_POST[
"chb_scoring_adjustment"])) {
 
  293                array_push($scoring_types, 
$row[
"question_type_id"]);
 
  296        $this->
object->setScoringAdjustableQuestions($scoring_types);
 
  298        if (!
$_POST[
'ass_process_lock']) {
 
  301            $this->
object->setAssessmentProcessLockMode($_POST[
'ass_process_lock_mode']);
 
  304        $assessmentSetting = 
new ilSetting(
'assessment');
 
  305        $assessmentSetting->set(
'use_javascript', 
'1');
 
  306        if (strlen(
$_POST[
'imap_line_color']) == 6) {
 
  313        $this->ctrl->redirect($this, 
'settings');
 
  324        $form->setValuesByPost();
 
  325        $this->logsObject(
$form);
 
  334        if (!
$form->checkInput()) {
 
  335            $form->setValuesByPost();
 
  336            $this->logsObject(
$form);
 
  347                $this->lng->txt(
"assessment_log_datetime"),
 
  348                $this->lng->txt(
"user"),
 
  349                $this->lng->txt(
"assessment_log_text"),
 
  350                $this->lng->txt(
"question")
 
  352        include_once 
"./Modules/Test/classes/class.ilObjTest.php";
 
  353        include_once 
"./Modules/TestQuestionPool/classes/class.assQuestion.php";
 
  358        foreach ($log_output as 
$key => 
$log) {
 
  359            if (!array_key_exists(
$log[
"user_fi"], 
$users)) {
 
  363            if (
$log[
"question_fi"] || 
$log[
"original_fi"]) {
 
  365                if (strlen(
$title) == 0) {
 
  368                $title = $this->lng->txt(
"assessment_log_question") . 
": " . 
$title;
 
  373            array_push($csvrow, trim(
$users[
$log[
"user_fi"]][
"title"] . 
" " . 
$users[
$log[
"user_fi"]][
"firstname"] . 
" " . 
$users[
$log[
"user_fi"]][
"lastname"]));
 
  374            array_push($csvrow, trim(
$log[
"logtext"]));
 
  375            array_push($csvrow, 
$title);
 
  379        foreach ($csv as 
$row) {
 
  380            $csvoutput .= join(
$row, $separator) . 
"\n";
 
  390        require_once 
'Services/Form/classes/class.ilPropertyFormGUI.php';
 
  392        $form->setPreventDoubleSubmission(
false);
 
  393        $form->setFormAction($this->ctrl->getFormAction($this));
 
  394        $form->setTableWidth(
"100%");
 
  395        $form->setId(
"logs");
 
  398        $header->setTitle($this->lng->txt(
"assessment_log"));
 
  403        $from->setShowTime(
true);
 
  404        $from->setRequired(
true);
 
  409        $until->setShowTime(
true);
 
  410        $until->setRequired(
true);
 
  411        $form->addItem($until);
 
  413        require_once 
'Modules/Test/classes/class.ilObjTest.php';
 
  414        require_once 
'Modules/TestQuestionPool/classes/class.assQuestion.php';
 
  418        $fortest = 
new ilSelectInputGUI($this->lng->txt(
'assessment_log_for_test'), 
"sel_test");
 
  419        $fortest->setRequired(
true);
 
  420        $sorted_options = array();
 
  421        foreach ($available_tests as 
$key => $value) {
 
  422            $sorted_options[] = array(
 
  423                'title' => 
ilUtil::prepareFormOutput($value) . 
" [" . $this->object->getNrOfLogEntries(
$key) . 
" " . $this->lng->txt(
"assessment_log_log_entries") . 
"]",
 
  428        $options = array(
'' => $this->lng->txt(
'please_choose'));
 
  429        foreach ($sorted_options as $option) {
 
  430            $options[$option[
'key']] = $option[
'title'];
 
  433        $form->addItem($fortest);
 
  435        $form->addCommandButton(
'showLog', $this->lng->txt(
'show'));
 
  436        $form->addCommandButton(
'exportLog', $this->lng->txt(
'export'));
 
  451        $ilTabs->activateTab(
'logs');
 
  463            if (isset(
$_GET[
'sel_test'])) {
 
  464                $p_test = $values[
'sel_test'] = (int) 
$_GET[
'sel_test'];
 
  467            if (isset(
$_GET[
'log_from'])) {
 
  468                $fromdate = (int) 
$_GET[
'log_from'];
 
  470                $fromdate = mktime(0, 0, 0, 1, 1, 
date(
'Y'));
 
  473            if (isset(
$_GET[
'log_until'])) {
 
  474                $untildate = (int) 
$_GET[
'log_until'];
 
  482            $form->setValuesByArray($values);
 
  484            $fromdate_input  = 
$form->getItemByPostVar(
'log_from')->getDate();
 
  485            $untildate_input = 
$form->getItemByPostVar(
'log_until')->getDate();
 
  487                $p_test  = 
$form->getInput(
'sel_test');
 
  494        $this->ctrl->setParameter($this, 
'sel_test', (
int) $p_test);
 
  495        $this->ctrl->setParameter($this, 
'log_until', (
int) $untildate);
 
  496        $this->ctrl->setParameter($this, 
'log_from', (
int) $fromdate);
 
  501            require_once 
"Services/Link/classes/class.ilLink.php";
 
  502            include_once 
"./Modules/Test/classes/tables/class.ilAssessmentFolderLogTableGUI.php";
 
  507            array_walk($log_output, 
function (&
$row) use ($self) {
 
  508                if (is_numeric(
$row[
'ref_id']) && 
$row[
'ref_id'] > 0) {
 
  510                    $row[
'location_txt']  = $self->lng->txt(
"perma_link");
 
  514            $table_gui->setData($log_output);
 
  515            $template->setVariable(
'LOG', $table_gui->getHTML());
 
  517        $this->tpl->setVariable(
"ADM_CONTENT", 
$template->get());
 
  525        if (is_array(
$_POST[
"chb_test"]) && (count(
$_POST[
"chb_test"]))) {
 
  526            $this->
object->deleteLogEntries(
$_POST[
"chb_test"]);
 
  539        global $ilAccess, $ilTabs;
 
  541        $ilTabs->activateTab(
'logs');
 
  543        $a_write_access = ($ilAccess->checkAccess(
"write", 
"", $this->object->getRefId())) ? 
true : 
false;
 
  545        include_once 
"./Modules/Test/classes/tables/class.ilAssessmentFolderLogAdministrationTableGUI.php";
 
  547        include_once 
"./Modules/Test/classes/class.ilObjTest.php";
 
  548        require_once 
"./Services/Link/classes/class.ilLink.php";
 
  553            array_push(
$data, array(
 
  555                "nr"            => $this->object->getNrOfLogEntries(
$obj_id),
 
  558                "location_txt"  => $this->lng->txt(
"perma_link")
 
  561        $table_gui->setData(
$data);
 
  562        $this->tpl->setVariable(
'ADM_CONTENT', $table_gui->getHTML());
 
  575        $ilTabs->addSubTabTarget(
 
  577            $this->ctrl->getLinkTarget($this, 
"showLogSettings"),
 
  578            array(
"saveLogSettings", 
"showLogSettings"),
 
  583        $ilTabs->addSubTabTarget(
 
  585            $this->ctrl->getLinkTarget($this, 
"logs"),
 
  586            array(
"logs", 
"showLog", 
"exportLog"),
 
  591        $ilTabs->addSubTabTarget(
 
  593            $this->ctrl->getLinkTarget($this, 
"logAdmin"),
 
  594            array(
"logAdmin", 
"deleteLog"),
 
  609        switch ($this->ctrl->getCmd()) {
 
  610            case "saveLogSettings":
 
  611            case "showLogSettings":
 
  621        if ($rbacsystem->checkAccess(
"visible,read", $this->object->getRefId())) {
 
  622            $this->tabs_gui->addTarget(
 
  624                $this->ctrl->getLinkTarget($this, 
"settings"),
 
  625                array(
"settings",
"",
"view"),
 
  630            $this->tabs_gui->addTarget(
 
  632                $this->ctrl->getLinkTarget($this, 
"showLogSettings"),
 
  633                array(
'saveLogSettings', 
'showLogSettings', 
"logs",
"showLog", 
"exportLog", 
"logAdmin", 
"deleteLog"),
 
  638            $this->tabs_gui->addTab(
 
  640                $lng->txt(
"adm_settings_templates"),
 
  641                $this->ctrl->getLinkTargetByClass(
"ilsettingstemplategui", 
"")
 
  645        if (
$rbacsystem->checkAccess(
"write", $this->object->getRefId())) {
 
  646            $this->tabs_gui->addTarget(
'units', $this->ctrl->getLinkTargetByClass(
'ilGlobalUnitConfigurationGUI', 
''), 
'', 
'ilglobalunitconfigurationgui');
 
  649        if (
$rbacsystem->checkAccess(
'edit_permission', $this->object->getRefId())) {
 
  650            $this->tabs_gui->addTarget(
 
  652                $this->ctrl->getLinkTargetByClass(array(get_class($this),
'ilpermissiongui'), 
"perm"),
 
  653                array(
"perm",
"info",
"owner"),
 
  664        $this->tabs_gui->activateTab(
'logs');
 
  667            $form = $this->getLogSettingsForm();
 
  668            $form->setValuesByArray(array(
 
  674        $this->tpl->setContent(
$form->getHTML());
 
  680    protected function saveLogSettingsObject()
 
  687        if (!$ilAccess->checkAccess(
'write', 
'', $this->object->getRefId())) {
 
  688            $this->
ilias->raiseError($this->lng->txt(
"permission_denied"), $this->ilias->error_obj->WARNING);
 
  691        $form = $this->getLogSettingsForm();
 
  692        if (
$form->checkInput()) {
 
  693            $this->
object->_enableAssessmentLogging((
int) 
$form->getInput(
'chb_assessment_logging'));
 
  694            $this->
object->_setLogLanguage(
$form->getInput(
'reporting_language'));
 
  695            $this->
object->update();
 
  699        $form->setValuesByPost();
 
  706    protected function getLogSettingsForm()
 
  713        require_once 
'Services/Form/classes/class.ilPropertyFormGUI.php';
 
  715        $form->setFormAction($this->ctrl->getFormAction($this, 
'saveLogSettings'));
 
  716        $form->setTitle($this->lng->txt(
'assessment_log_logging'));
 
  719        $logging->setValue(1);
 
  720        $logging->setOptionTitle($this->lng->txt(
'activate_assessment_logging'));
 
  721        $form->addItem($logging);
 
  723        $reporting = 
new ilSelectInputGUI($this->lng->txt(
'assessment_settings_reporting_language'), 
'reporting_language');
 
  724        $languages = $this->lng->getInstalledLanguages();
 
  725        $this->lng->loadLanguageModule(
'meta');
 
  727        foreach ($languages as 
$lang) {
 
  731        $form->addItem($reporting);
 
  733        if ($ilAccess->checkAccess(
'write', 
'', $this->object->getRefId())) {
 
  734            $form->addCommandButton(
'saveLogSettings', $this->lng->txt(
'save'));
 
  744        $ilTabs->setTabActive(
'templates');
 
  746        require_once 
'Services/Administration/classes/class.ilSettingsTemplateGUI.php';
 
  749        $this->ctrl->forwardCommand($gui);
 
  759        require_once 
'Modules/Test/classes/class.ilTestSettingsTemplateConfig.php';
 
date( 'd-M-Y', $objPHPExcel->getProperties() ->getCreated())
if(!isset( $_REQUEST[ 'ReturnTo'])) if(!isset($_REQUEST['AuthId'])) $options
An exception for terminatinating execution or to throw for unit testing.
static _getQuestionTitle($question_id)
Returns the question title of a question with a given id.
This class represents an option in a checkbox group.
@classDescription Date and time handling
Class ilGlobalUnitConfigurationGUI.
static _getLink($a_ref_id, $a_type='', $a_params=array(), $append="")
Class ilObjAssessmentFolderGUI.
__construct($a_data, $a_id=0, $a_call_by_reference=true, $a_prepare_output=true)
Constructor.
settingsObject(ilPropertyFormGUI $form=null)
display assessment folder settings form
logAdminObject()
Administration output for assessment log files.
getAdminTabs()
administration tabs show only permissions and trash folder
saveSettingsObject()
Save Assessment settings.
deleteLogObject()
Deletes the log entries for one or more tests.
forwardToSettingsTemplateGUI()
showLogSettingsObject(ilPropertyFormGUI $form=null)
exportLogObject()
Called when the a log should be exported.
showLogObject()
Called when the a log should be shown.
static getSettingsTemplateConfig()
saveObject()
save object @access public
const ASS_PROC_LOCK_MODE_FILE
static _getLogLanguage()
retrieve the log language for assessment logging
static _getManualScoring()
Retrieve the manual scoring settings.
const ASS_PROC_LOCK_MODE_NONE
static getLog($ts_from, $ts_to, $test_id, $test_only=false)
Retrieve assessment log datasets from the database.
static _getForbiddenQuestionTypes()
Returns the forbidden questiontypes for ILIAS.
static getValidAssessmentProcessLockModes()
static _enabledAssessmentLogging()
check wether assessment logging is enabled or not
const ASS_PROC_LOCK_MODE_DB
static _getQuestionTypes($all_tags=false, $fixOrder=false)
static _getAvailableTests($use_object_id=false)
Returns the available tests for the active user.
static _lookupName($a_user_id)
lookup user name
Class ilObjectGUI Basic methods of all Output classes.
prepareOutput($a_show_subobjects=true)
prepare output
executeCommand()
execute command
static _lookupObjectId($a_ref_id)
lookup object id
New PermissionGUI (extends from old ilPermission2GUI) RBAC related output.
This class represents an option in a radio group.
special template class to simplify handling of ITX/PEAR
Class ilUnitConfigurationRepository.
static sortArray( $array, $a_array_sortby, $a_array_sortorder=0, $a_numeric=false, $a_keep_keys=false)
sortArray
static sendSuccess($a_info="", $a_keep=false)
Send Success Message to Screen.
static deliverData($a_data, $a_filename, $mime="application/octet-stream", $charset="")
deliver data for download via browser.
static stripSlashes($a_str, $a_strip_html=true, $a_allow="")
strip slashes if magic qoutes is enabled
static sendInfo($a_info="", $a_keep=false)
Send Info Message to Screen.
static & processCSVRow(&$row, $quoteAll=false, $separator=";", $outUTF8=false, $compatibleWithMSExcel=true)
Convertes an array for CSV usage.
static prepareFormOutput($a_str, $a_strip=false)
prepares string output for html forms @access public
redirection script todo: (a better solution should control the processing via a xml file)
if(isset($_POST['submit'])) $form