diff --git a/CHANGELOG.md b/CHANGELOG.md
index c3634d76..6cd9755f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,38 @@
The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/).
+## [v0.21.4] - 10.07.2024
+- implement JS changes for material design too
+- bug fix for default session code regex
+- default to exporting items when exporting run JSONs
+- all newly created surveys have a default field "iteration" which is simply an auto-increment number from 1 to number of responses to survey
+
+## [v0.21.3] - 21.06.2024
+- autoset timezone for timezone inputs
+- make user id/session code length flexible/configurable
+- webshim number inputs to make the regional number formatting configurable
+
+## [v0.21.2] - 02.06.2024
+- bug fix (minify changed JS correctly)
+
+## [v0.21.1] - 01.06.2024
+- simplify integration with labjs et al by
+ - not changing file names on upload
+ - allowing larger amounts of data to be stored in text fields
+ - allowing uploadable file types to be configurable
+- add Reply-To option for email accounts
+- allow default email accounts to be configured in settings.php, Reply-To defaults to admin email address
+- allow superadmins to manually set admin account email addresses as verified
+
+
+## [v0.21.0] - 07.03.2024
+- make it easier to dockerise formr
+- track bower_components to make it easier to collaborate on changes in CSS/JS
+- improve cookie handling, so that formr works similarly, whether you use study-specific subdomains or not.
+
+## [v0.20.7] - 02.05.2023
+
+
## [v0.20.7] - 02.05.2023
### Fixed
* Adding SMTP accounts that do not support password
diff --git a/application/Model/SurveyStudy.php b/application/Model/SurveyStudy.php
index 002df2c3..c58bc3c9 100644
--- a/application/Model/SurveyStudy.php
+++ b/application/Model/SurveyStudy.php
@@ -605,6 +605,7 @@ private function getResultsTableSyntax($columns) {
CREATE TABLE `{$this->results_table}` (
`session_id` INT UNSIGNED NOT NULL ,
`study_id` INT UNSIGNED NOT NULL ,
+ `iteration` INT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE,
`created` DATETIME NULL DEFAULT NULL ,
`modified` DATETIME NULL DEFAULT NULL ,
`ended` DATETIME NULL DEFAULT NULL ,
@@ -704,10 +705,7 @@ public function getResults($items = null, $filter = null, array $paginate = null
);
*/
} else {
- $columns = array('survey_run_sessions.session', "`{$results_table}`.`created`", "`{$results_table}`.`modified`", "`{$results_table}`.`ended`, `survey_unit_sessions`.`expired`");
- }
- foreach ($items as $item) {
- $columns[] = "{$results_table}.{$item}";
+ $columns = array('survey_run_sessions.session', "`{$results_table}`.*");
}
$select = $this->db->select($columns)
@@ -957,7 +955,7 @@ public function deleteResults($run_id = null) {
return true;
} elseif ($run_id !== null) {
//@todo implement deleting results only for a particular run
- $this->error[] = 'Deleting run specific results for a survey is not yet implemented';
+ $this->errors[] = 'Deleting run specific results for a survey is not yet implemented';
return false;
} elseif ($this->backupResults()) {
$delete = $this->db->query("TRUNCATE TABLE `{$this->results_table}`");
diff --git a/application/Model/UnitSession.php b/application/Model/UnitSession.php
index a67a124e..cb8e1511 100644
--- a/application/Model/UnitSession.php
+++ b/application/Model/UnitSession.php
@@ -723,9 +723,17 @@ protected function getRunDataNeeded($q, $token_add = null) {
$items = $this->db->select('name')->from('survey_items')
->where(['study_id' => $study_id])
->where("type NOT IN ('mc_heading', 'note', 'submit', 'block', 'note_iframe')")
+ ->where("name != 'iteration'")
->fetchAll();
$variable_names_in_table[$table_name] = array("created", "modified", "ended"); // should avoid modified, sucks for caching
+ $res_table = $results_tables[$table_name];
+ $has_iter = $this->db->prepare("DESCRIBE `$res_table` `iteration`");
+ $has_iter->execute();
+ if($has_iter->fetch(PDO::FETCH_ASSOC) !== false) {
+ $variable_names_in_table[$table_name][] = "iteration";
+ }
+
foreach ($items as $res) {
$variable_names_in_table[$table_name][] = $res['name']; // search set for user defined tables
}
diff --git a/application/Site.php b/application/Site.php
index be64238e..0b04639c 100644
--- a/application/Site.php
+++ b/application/Site.php
@@ -171,7 +171,7 @@ public function expire_session($expiry) {
public function loginUser($user) {
// came here with a login link
$code_rule = Config::get("user_code_regular_expression");
- pr($_GET['code']);die;
+
if (isset($_GET['run_name']) && isset($_GET['code']) && preg_match($code_rule, $_GET['code'])) {
$login_code = $_GET['code'];
// this user came here with a session code that he wasn't using before.
diff --git a/application/Spreadsheet/SpreadsheetReader.php b/application/Spreadsheet/SpreadsheetReader.php
index 17e27be3..b9574b05 100644
--- a/application/Spreadsheet/SpreadsheetReader.php
+++ b/application/Spreadsheet/SpreadsheetReader.php
@@ -747,7 +747,7 @@ private function readSurveySheet(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $
$this->errors[] = __("The variable name '%s' is invalid. It has to be between 1 and 64 characters. It needs to start with a letter and can only contain the characters from a to Z, 0 to 9 and the underscore.", $cellValue);
}
- if (in_array($cellValue, array('session_id', 'created', 'modified', 'ended', 'id', 'study_id'))) {
+ if (in_array($cellValue, array('session_id', 'created', 'modified', 'ended', 'id', 'study_id', 'iteration'))) {
$this->errors[] = __("Row %s: variable name '%s' is not permitted.", $rowNumber, $cellValue);
}
diff --git a/config-dist/settings.php b/config-dist/settings.php
index 90d28641..85cbf795 100644
--- a/config-dist/settings.php
+++ b/config-dist/settings.php
@@ -84,7 +84,7 @@
$settings['display_errors'] = 0;
$settings['error_to_stderr'] = 0;
-$settings['user_code_regular_expression'] = "/^[A-Za-z0-9+]{64}$/";
+$settings['user_code_regular_expression'] = "/^[A-Za-z0-9+-_~]{64}$/";
// Session expiration related settings
// (for unregistered users. in seconds (defaults to a year))
diff --git a/setup.php b/setup.php
index 82fa04ae..51c71bb0 100644
--- a/setup.php
+++ b/setup.php
@@ -1,6 +1,6 @@