diff --git a/core/_bootstrap.php b/core/_bootstrap.php
index 6467f4d8..b48efbce 100644
--- a/core/_bootstrap.php
+++ b/core/_bootstrap.php
@@ -68,7 +68,13 @@ unset($themelet);
$page = class_exists("CustomPage") ? new CustomPage() : new Page();
$_tracer->end();
-$_tracer->begin("Loading extensions/event listeners");
+$_tracer->log_start("Loading user information");
+$user = _get_user();
+$user_config = new DatabaseConfig($database, "user_config","user_id", $user->id);
+$_tracer->log_endok();
+
+// hook up event handlers
+$_tracer->begin("Loading event listeners");
_load_event_listeners();
$_tracer->end();
diff --git a/core/config.php b/core/config.php
index c9fb225b..6b1ac6fa 100644
--- a/core/config.php
+++ b/core/config.php
@@ -20,6 +20,11 @@ interface Config
*/
public function set_int(string $name, ?string $value): void;
+ /**
+ * Set a configuration option to a new value, regardless of what the value is at the moment.
+ */
+ public function set_float(string $name, ?string $value): void;
+
/**
* Set a configuration option to a new value, regardless of what the value is at the moment.
*/
@@ -48,6 +53,16 @@ interface Config
*/
public function set_default_int(string $name, int $value): void;
+ /**
+ * Set a configuration option to a new value, if there is no value currently.
+ *
+ * Extensions should generally call these from their InitExtEvent handlers.
+ * This has the advantage that the values will show up in the "advanced" setup
+ * page where they can be modified, while calling get_* with a "default"
+ * parameter won't show up.
+ */
+ public function set_default_float(string $name, float $value): void;
+
/**
* Set a configuration option to a new value, if there is no value currently.
*
@@ -85,6 +100,11 @@ interface Config
*/
public function get_int(string $name, ?int $default=null): ?int;
+ /**
+ * Pick a value out of the table by name, cast to the appropriate data type.
+ */
+ public function get_float(string $name, ?float $default=null): ?float;
+
/**
* Pick a value out of the table by name, cast to the appropriate data type.
*/
@@ -119,6 +139,12 @@ abstract class BaseConfig implements Config
$this->save($name);
}
+ public function set_float(string $name, ?string $value): void
+ {
+ $this->values[$name] = $value;
+ $this->save($name);
+ }
+
public function set_string(string $name, ?string $value): void
{
$this->values[$name] = $value;
@@ -131,9 +157,13 @@ abstract class BaseConfig implements Config
$this->save($name);
}
- public function set_array(string $name, array $value): void
+ public function set_array(string $name, ?array $value): void
{
- $this->values[$name] = implode(",", $value);
+ if($value!=null) {
+ $this->values[$name] = implode(",", $value);
+ } else {
+ $this->values[$name] = null;
+ }
$this->save($name);
}
@@ -279,19 +309,41 @@ class DatabaseConfig extends BaseConfig
/** @var Database */
private $database = null;
- public function __construct(Database $database)
+ private $table_name;
+ private $sub_column;
+ private $sub_value;
+
+ public function __construct(Database $database, string $table_name = "config",
+ string $sub_column = null, string $sub_value = null)
{
$this->database = $database;
+ $this->table_name = $table_name;
+ $this->sub_value = $sub_value;
+ $this->sub_column = $sub_column;
- $cached = $this->database->cache->get("config");
+ $cache_name = "config";
+ if(!empty($sub_value)) {
+ $cache_name .= "_".$sub_value;
+ }
+
+ $cached = $this->database->cache->get($cache_name);
if ($cached) {
$this->values = $cached;
} else {
$this->values = [];
- foreach ($this->database->get_all("SELECT name, value FROM config") as $row) {
+
+ $query = "SELECT name, value FROM {$this->table_name}";
+ $args = [];
+
+ if(!empty($sub_column)&&!empty($sub_value)) {
+ $query .= " WHERE $sub_column = :sub_value";
+ $args["sub_value"] = $sub_value;
+ }
+
+ foreach ($this->database->get_all($query, $args ) as $row) {
$this->values[$row["name"]] = $row["value"];
}
- $this->database->cache->set("config", $this->values);
+ $this->database->cache->set($cache_name, $this->values);
}
}
@@ -303,8 +355,23 @@ class DatabaseConfig extends BaseConfig
$this->save($name);
}
} else {
- $this->database->Execute("DELETE FROM config WHERE name = :name", ["name"=>$name]);
- $this->database->Execute("INSERT INTO config VALUES (:name, :value)", ["name"=>$name, "value"=>$this->values[$name]]);
+ $query = "DELETE FROM {$this->table_name} WHERE name = :name";
+ $args = ["name"=>$name];
+ $cols = ["name","value"];
+ $params = [":name",":value"];
+ if(!empty($this->sub_column)&&!empty($this->sub_value)) {
+ $query .= " AND $this->sub_column = :sub_value";
+ $args["sub_value"] = $this->sub_value;
+ $cols[] = $this->sub_column;
+ $params[] = ":sub_value";
+ }
+
+ $this->database->Execute($query, $args);
+
+ $args["value"] =$this->values[$name];
+ $this->database->Execute(
+ "INSERT INTO {$this->table_name} (".join(",",$cols).") VALUES (".join(",",$params).")",
+ $args);
}
// rather than deleting and having some other request(s) do a thundering
// herd of race-conditioned updates, just save the updated version once here
diff --git a/ext/upgrade/main.php b/ext/upgrade/main.php
index dd51e26d..63be82ad 100644
--- a/ext/upgrade/main.php
+++ b/ext/upgrade/main.php
@@ -6,7 +6,6 @@ class Upgrade extends Extension
{
global $config, $database;
-
if ($config->get_bool("in_upgrade")) {
return;
}
@@ -157,8 +156,6 @@ class Upgrade extends Extension
}
// SQLite doesn't support altering existing columns? This seems like a problem?
-
-
log_info("upgrade", "Database at version 16");
$config->set_bool("in_upgrade", false);
}
@@ -217,7 +214,24 @@ class Upgrade extends Extension
$config->set_bool("in_upgrade", false);
}
+ if ($config->get_int("db_version") < 18) {
+ $config->set_bool("in_upgrade", true);
+ $config->set_int("db_version", 18);
+ log_info("upgrade", "Adding user config table");
+
+ $database->create_table("user_config", "
+ user_id INTEGER NOT NULL,
+ name VARCHAR(128) NOT NULL,
+ value TEXT,
+ PRIMARY KEY (user_id, name),
+ FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
+ ");
+ $database->execute("CREATE INDEX user_config_user_id_idx ON user_config(user_id)");
+
+ log_info("upgrade", "Database at version 18");
+ $config->set_bool("in_upgrade", false);
+ }
}
diff --git a/ext/user/events.php b/ext/user/events.php
index 1fa04ccb..fae10b73 100644
--- a/ext/user/events.php
+++ b/ext/user/events.php
@@ -82,4 +82,3 @@ class UserDeletionEvent extends Event
$this->id = $id;
}
}
-
diff --git a/ext/user/main.php b/ext/user/main.php
index a65dbc28..91147c28 100644
--- a/ext/user/main.php
+++ b/ext/user/main.php
@@ -188,6 +188,17 @@ class UserPage extends Extension
ksort($event->stats);
$this->theme->display_user_page($event->display_user, $event->stats);
+
+ if (!$user->is_anonymous()) {
+ if ($user->id == $event->display_user->id || $user->can("edit_user_info")) {
+ $uobe = new UserOptionsBuildingEvent();
+ send_event($uobe);
+
+ $page->add_block(new Block("Options", $this->theme->build_options($event->display_user, $uobe), "main", 60));
+ }
+ }
+
+
if ($user->id == $event->display_user->id) {
$ubbe = new UserBlockBuildingEvent();
send_event($ubbe);
diff --git a/ext/user/theme.php b/ext/user/theme.php
index dab26e8c..a1650db4 100644
--- a/ext/user/theme.php
+++ b/ext/user/theme.php
@@ -243,14 +243,9 @@ class UserPageTheme extends Themelet
$page->add_block(new NavBlock());
$page->add_block(new Block("Stats", join("
", $stats), "main", 10));
- if (!$user->is_anonymous()) {
- if ($user->id == $duser->id || $user->can("edit_user_info")) {
- $page->add_block(new Block("Options", $this->build_options($duser), "main", 60));
- }
- }
}
- protected function build_options(User $duser)
+ public function build_options(User $duser, UserOptionsBuildingEvent $event)
{
global $config, $user;
$html = "";
@@ -266,7 +261,7 @@ class UserPageTheme extends Themelet
".make_form(make_link("user_admin/change_email"))."