diff --git a/core/config.php b/core/config.php index c88c0dbae..4d130c577 100644 --- a/core/config.php +++ b/core/config.php @@ -323,4 +323,17 @@ protected function save(string $name): void abstract class ConfigGroup { + public static function get_group_for_entry_by_name(string $name): ?ConfigGroup + { + foreach (get_subclasses_of(ConfigGroup::class) as $class) { + $config = new $class(); + assert(is_a($config, ConfigGroup::class)); + foreach ((new \ReflectionClass($class))->getConstants() as $const => $value) { + if ($value === $name) { + return $config; + } + } + } + return null; + } } diff --git a/core/tests/ConfigTest.php b/core/tests/ConfigTest.php new file mode 100644 index 000000000..95188a849 --- /dev/null +++ b/core/tests/ConfigTest.php @@ -0,0 +1,17 @@ +assertNotNull($conf); + $this->assertEquals(CommentConfig::LIMIT, $conf::class); + } +} diff --git a/ext/blotter/config.php b/ext/blotter/config.php new file mode 100644 index 000000000..47179e437 --- /dev/null +++ b/ext/blotter/config.php @@ -0,0 +1,13 @@ +set_default_int("blotter_recent", 5); - $config->set_default_string("blotter_color", "FF0000"); - $config->set_default_string("blotter_position", "subheading"); + $config->set_default_int(BlotterConfig::RECENT, 5); + $config->set_default_string(BlotterConfig::COLOR, "FF0000"); + $config->set_default_string(BlotterConfig::POSITION, "subheading"); } public function onDatabaseUpgrade(DatabaseUpgradeEvent $event): void { global $database; - if ($this->get_version("blotter_version") < 1) { + if ($this->get_version(BlotterConfig::VERSION) < 1) { $database->create_table("blotter", " id SCORE_AIPK, entry_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP, @@ -34,11 +34,11 @@ public function onDatabaseUpgrade(DatabaseUpgradeEvent $event): void ["text" => "Installed the blotter extension!", "important" => true] ); log_info("blotter", "Installed tables for blotter extension."); - $this->set_version("blotter_version", 2); + $this->set_version(BlotterConfig::VERSION, 2); } - if ($this->get_version("blotter_version") < 2) { + if ($this->get_version(BlotterConfig::VERSION) < 2) { $database->standardise_boolean("blotter", "important"); - $this->set_version("blotter_version", 2); + $this->set_version(BlotterConfig::VERSION, 2); } } @@ -110,7 +110,7 @@ private function display_blotter(): void global $database, $config; $entries = $database->get_all( 'SELECT * FROM blotter ORDER BY id DESC LIMIT :limit', - ["limit" => $config->get_int("blotter_recent", 5)] + ["limit" => $config->get_int(BlotterConfig::RECENT, 5)] ); $this->theme->display_blotter($entries); } diff --git a/ext/blotter/theme.php b/ext/blotter/theme.php index 6ef228794..8bd62caa2 100644 --- a/ext/blotter/theme.php +++ b/ext/blotter/theme.php @@ -41,7 +41,7 @@ public function display_blotter(array $entries): void { global $page, $config; $html = $this->get_html_for_blotter($entries); - $position = $config->get_string("blotter_position", "subheading"); + $position = $config->get_string(BlotterConfig::POSITION, "subheading"); $page->add_block(new Block(null, rawHTML($html), $position, 20)); } @@ -127,7 +127,7 @@ private function get_html_for_blotter_page(array $entries): string * This one displays a list of all blotter entries. */ global $config; - $i_color = $config->get_string("blotter_color", "#FF0000"); + $i_color = $config->get_string(BlotterConfig::COLOR, "#FF0000"); $html = "
";
 
         $num_entries = count($entries);
@@ -158,8 +158,8 @@ private function get_html_for_blotter_page(array $entries): string
     private function get_html_for_blotter(array $entries): string
     {
         global $config;
-        $i_color = $config->get_string("blotter_color", "#FF0000");
-        $position = $config->get_string("blotter_position", "subheading");
+        $i_color = $config->get_string(BlotterConfig::COLOR, "#FF0000");
+        $position = $config->get_string(BlotterConfig::POSITION, "subheading");
         $entries_list = "";
         foreach ($entries as $entry) {
             /**
diff --git a/ext/comment/config.php b/ext/comment/config.php
new file mode 100644
index 000000000..e9e6525d5
--- /dev/null
+++ b/ext/comment/config.php
@@ -0,0 +1,17 @@
+set_default_int('comment_window', 5);
-        $config->set_default_int('comment_limit', 10);
-        $config->set_default_int('comment_list_count', 10);
-        $config->set_default_int('comment_count', 5);
-        $config->set_default_bool('comment_captcha', false);
+        $config->set_default_int(CommentConfig::WINDOW, 5);
+        $config->set_default_int(CommentConfig::LIMIT, 10);
+        $config->set_default_int(CommentConfig::LIST_COUNT, 10);
+        $config->set_default_int(CommentConfig::COUNT, 5);
+        $config->set_default_bool(CommentConfig::CAPTCHA, false);
     }
 
     public function onDatabaseUpgrade(DatabaseUpgradeEvent $event): void
     {
         global $database;
-        if ($this->get_version("ext_comments_version") < 3) {
+        if ($this->get_version(CommentConfig::VERSION) < 3) {
             // shortcut to latest
-            if ($this->get_version("ext_comments_version") < 1) {
+            if ($this->get_version(CommentConfig::VERSION) < 1) {
                 $database->create_table("comments", "
 					id SCORE_AIPK,
 					image_id INTEGER NOT NULL,
@@ -151,11 +150,11 @@ public function onDatabaseUpgrade(DatabaseUpgradeEvent $event): void
                 $database->execute("CREATE INDEX comments_image_id_idx ON comments(image_id)", []);
                 $database->execute("CREATE INDEX comments_owner_id_idx ON comments(owner_id)", []);
                 $database->execute("CREATE INDEX comments_posted_idx ON comments(posted)", []);
-                $this->set_version("ext_comments_version", 3);
+                $this->set_version(CommentConfig::VERSION, 3);
             }
 
             // the whole history
-            if ($this->get_version("ext_comments_version") < 1) {
+            if ($this->get_version(CommentConfig::VERSION) < 1) {
                 $database->create_table("comments", "
 					id SCORE_AIPK,
 					image_id INTEGER NOT NULL,
@@ -165,17 +164,17 @@ public function onDatabaseUpgrade(DatabaseUpgradeEvent $event): void
 					comment TEXT NOT NULL
 				");
                 $database->execute("CREATE INDEX comments_image_id_idx ON comments(image_id)", []);
-                $this->set_version("ext_comments_version", 1);
+                $this->set_version(CommentConfig::VERSION, 1);
             }
 
-            if ($this->get_version("ext_comments_version") == 1) {
+            if ($this->get_version(CommentConfig::VERSION) == 1) {
                 $database->execute("CREATE INDEX comments_owner_ip ON comments(owner_ip)");
                 $database->execute("CREATE INDEX comments_posted ON comments(posted)");
-                $this->set_version("ext_comments_version", 2);
+                $this->set_version(CommentConfig::VERSION, 2);
             }
 
-            if ($this->get_version("ext_comments_version") == 2) {
-                $this->set_version("ext_comments_version", 3);
+            if ($this->get_version(CommentConfig::VERSION) == 2) {
+                $this->set_version(CommentConfig::VERSION, 3);
                 $database->execute("ALTER TABLE comments ADD FOREIGN KEY (image_id) REFERENCES images(id) ON DELETE CASCADE");
                 $database->execute("ALTER TABLE comments ADD FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE RESTRICT");
             }
@@ -310,7 +309,7 @@ public function onAdminBuilding(AdminBuildingEvent $event): void
     public function onPostListBuilding(PostListBuildingEvent $event): void
     {
         global $cache, $config;
-        $cc = $config->get_int("comment_count");
+        $cc = $config->get_int(CommentConfig::COUNT);
         if ($cc > 0) {
             $recent = cache_get_or_set("recent_comments", fn () => $this->get_recent_comments($cc), 60);
             if (count($recent) > 0) {
@@ -477,8 +476,8 @@ private function is_comment_limit_hit(): bool
             return false;
         }
 
-        $window = $config->get_int('comment_window');
-        $max = $config->get_int('comment_limit');
+        $window = $config->get_int(CommentConfig::WINDOW);
+        $max = $config->get_int(CommentConfig::LIMIT);
 
         if ($database->get_driver_id() == DatabaseDriverID::MYSQL) {
             $window_sql = "interval $window minute";
@@ -511,7 +510,7 @@ public static function get_hash(): string
     private function is_spam_akismet(string $text): bool
     {
         global $config, $user;
-        $key = $config->get_string('comment_wordpress_key');
+        $key = $config->get_string(CommentConfig::WORDPRESS_KEY);
         if (!is_null($key) && strlen($key) > 0) {
             $comment = [
                 'author'       => $user->name,
@@ -608,7 +607,7 @@ private function comment_checks(int $image_id, User $user, string $comment): voi
         }
 
         // rate-limited external service checks last
-        elseif ($config->get_bool('comment_captcha') && !captcha_check()) {
+        elseif ($config->get_bool(CommentConfig::CAPTCHA) && !captcha_check()) {
             throw new CommentPostingException("Error in captcha");
         } elseif ($user->is_anonymous() && $this->is_spam_akismet($comment)) {
             throw new CommentPostingException("Akismet thinks that your comment is spam. Try rewriting the comment, or logging in.");
diff --git a/ext/comment/test.php b/ext/comment/test.php
index 9d7e9fdbd..5d30675b9 100644
--- a/ext/comment/test.php
+++ b/ext/comment/test.php
@@ -10,14 +10,14 @@ public function setUp(): void
     {
         global $config;
         parent::setUp();
-        $config->set_int("comment_limit", 100);
+        $config->set_int(CommentConfig::LIMIT, 100);
         $this->log_out();
     }
 
     public function tearDown(): void
     {
         global $config;
-        $config->set_int("comment_limit", 10);
+        $config->set_int(CommentConfig::LIMIT, 10);
         parent::tearDown();
     }
 
diff --git a/ext/comment/theme.php b/ext/comment/theme.php
index 6c42b4b3d..d4677cdc8 100644
--- a/ext/comment/theme.php
+++ b/ext/comment/theme.php
@@ -41,8 +41,8 @@ public function display_comment_list(array $images, int $page_number, int $total
         // parts for each image
         $position = 10;
 
-        $comment_limit = $config->get_int("comment_list_count", 10);
-        $comment_captcha = $config->get_bool('comment_captcha');
+        $comment_limit = $config->get_int(CommentConfig::LIST_COUNT, 10);
+        $comment_captcha = $config->get_bool(CommentConfig::CAPTCHA);
 
         foreach ($images as $pair) {
             $image = $pair[0];
@@ -222,7 +222,7 @@ protected function comment_to_html(Comment $comment, bool $trim = false): string
                 }
                 #if($user->can(UserAbilities::VIEW_IP)) {
                 #$style = " style='color: ".$this->get_anon_colour($comment->poster_ip).";'";
-                if ($user->can(Permissions::VIEW_IP) || $config->get_bool("comment_samefags_public", false)) {
+                if ($user->can(Permissions::VIEW_IP) || $config->get_bool(CommentConfig::SHOW_REPEAT_ANONS, false)) {
                     if ($this->anon_map[$comment->poster_ip] != $this->anon_id) {
                         $anoncode2 = '('.$this->anon_map[$comment->poster_ip].')';
                     }
diff --git a/ext/setup/style.css b/ext/setup/style.css
index a20a2ea8f..63a0d123d 100644
--- a/ext/setup/style.css
+++ b/ext/setup/style.css
@@ -16,6 +16,10 @@
 	resize: vertical;
 }
 
+.advanced_settings INPUT {
+	width: 100%;
+}
+
 #Setupmain {
 	box-shadow: none;
 }
@@ -35,4 +39,4 @@
 	margin-top: 1em;
 	padding: 1em;
 	width: 100%;
-}
\ No newline at end of file
+}
diff --git a/ext/setup/theme.php b/ext/setup/theme.php
index c7d26ee19..fb8fe79d9 100644
--- a/ext/setup/theme.php
+++ b/ext/setup/theme.php
@@ -6,6 +6,15 @@
 
 use MicroHTML\HTMLElement;
 
+use function MicroHTML\INPUT;
+use function MicroHTML\TABLE;
+use function MicroHTML\TBODY;
+use function MicroHTML\TD;
+use function MicroHTML\TEXTAREA;
+use function MicroHTML\TFOOT;
+use function MicroHTML\TH;
+use function MicroHTML\THEAD;
+use function MicroHTML\TR;
 use function MicroHTML\rawHTML;
 
 class SetupTheme extends Themelet
@@ -51,39 +60,57 @@ public function display_page(Page $page, SetupPanel $panel): void
      */
     public function display_advanced(Page $page, array $options): void
     {
-        $h_rows = "";
+        $rows = TBODY();
         ksort($options);
         foreach ($options as $name => $value) {
+            $ext = ConfigGroup::get_group_for_entry_by_name($name);
+            if ($ext) {
+                $ext_name = \Safe\preg_replace("#Shimmie2.(.*)Config#", '$1', $ext::class);
+            } else {
+                $ext_name = "";
+            }
+
             if (is_null($value)) {
                 $value = '';
             }
 
-            $h_name = html_escape($name);
-            $h_value = html_escape((string)$value);
-
-            $h_box = "";
+            $valbox = TD();
             if (is_string($value) && str_contains($value, "\n")) {
-                $h_box .= "";
+                $valbox->appendChild(TEXTAREA(
+                    ['name' => "_config_$name", 'cols' => 50, 'rows' => 4],
+                    $value,
+                ));
             } else {
-                $h_box .= "";
+                $valbox->appendChild(INPUT(
+                    ['type' => 'text', 'name' => "_config_$name", 'value' => $value],
+                ));
             }
-            $h_box .= "";
-            $h_rows .= "$h_name$h_box";
+            $valbox->appendChild(INPUT(
+                ['type' => 'hidden', 'name' => '_type_' . $name, 'value' => 'string'],
+            ));
+
+            $rows->appendChild(TR(TD($ext_name), TD($name), $valbox));
         }
 
-        $table = "
-			".make_form(make_link("setup/save"))."
-				
-					
-					$h_rows
-					
-				
NameValue
- - "; + $table = SHM_SIMPLE_FORM( + "setup/save", + TABLE( + ['id' => 'settings', 'class' => 'zebra advanced_settings'], + THEAD(TR( + TH(['width' => '20%'], 'Group'), + TH(['width' => '20%'], 'Name'), + TH('Value'), + )), + $rows, + TFOOT(TR( + TD(["colspan" => 3], INPUT(['type' => 'submit', 'value' => 'Save Settings'])) + )), + ) + ); $page->set_title("Shimmie Setup"); $page->add_block(new Block("Navigation", $this->build_navigation(), "left", 0)); - $page->add_block(new Block("Setup", rawHTML($table))); + $page->add_block(new Block("Setup", $table)); } protected function build_navigation(): HTMLElement diff --git a/ext/user/main.php b/ext/user/main.php index 78c1504c3..d42ab3e7c 100644 --- a/ext/user/main.php +++ b/ext/user/main.php @@ -99,7 +99,7 @@ public static function login(string $username, string $password): LoginResult ); } catch (UserNotFound $ex) { return new LoginResult( - User::by_id($config->get_int("anon_id", 0)), + User::by_id($config->get_int(UserPageConfig::ANON_ID, 0)), null, "No user found" ); @@ -119,7 +119,7 @@ public static function create_user(string $username, string $password1, string $ ); } catch (UserCreationException $ex) { return new LoginResult( - User::by_id($config->get_int("anon_id", 0)), + User::by_id($config->get_int(UserPageConfig::ANON_ID, 0)), null, $ex->getMessage() ); @@ -135,14 +135,14 @@ class UserPage extends Extension public function onInitExt(InitExtEvent $event): void { global $config; - $config->set_default_bool("login_signup_enabled", true); - $config->set_default_int("login_memory", 365); - $config->set_default_string("avatar_host", "none"); - $config->set_default_int("avatar_gravatar_size", 80); - $config->set_default_string("avatar_gravatar_default", ""); - $config->set_default_string("avatar_gravatar_rating", "g"); - $config->set_default_bool("login_tac_bbcode", true); - $config->set_default_bool("user_email_required", false); + $config->set_default_bool(UserPageConfig::SIGNUP_ENABLED, true); + $config->set_default_int(UserPageConfig::LOGIN_MEMORY, 365); + $config->set_default_string(UserPageConfig::AVATAR_HOST, "none"); + $config->set_default_int(UserPageConfig::AVATAR_GRAVATAR_SIZE, 80); + $config->set_default_string(UserPageConfig::AVATAR_GRAVATAR_DEFAULT, ""); + $config->set_default_string(UserPageConfig::AVATAR_GRAVATAR_RATING, "g"); + $config->set_default_bool(UserPageConfig::LOGIN_TAC_BBCODE, true); + $config->set_default_bool(UserPageConfig::USER_EMAIL_REQUIRED, false); } public function onUserLogin(UserLoginEvent $event): void @@ -174,7 +174,7 @@ public function onPageRequest(PageRequestEvent $event): void } if ($event->page_matches("user_admin/create", method: "GET", permission: Permissions::CREATE_USER)) { global $config, $page, $user; - if (!$config->get_bool("login_signup_enabled")) { + if (!$config->get_bool(UserPageConfig::SIGNUP_ENABLED)) { $this->theme->display_signups_disabled($page); return; } @@ -182,7 +182,7 @@ public function onPageRequest(PageRequestEvent $event): void } if ($event->page_matches("user_admin/create", method: "POST", authed: false, permission: Permissions::CREATE_USER)) { global $config, $page, $user; - if (!$config->get_bool("login_signup_enabled")) { + if (!$config->get_bool(UserPageConfig::SIGNUP_ENABLED)) { $this->theme->display_signups_disabled($page); return; } @@ -312,7 +312,7 @@ public function onPageRequest(PageRequestEvent $event): void if ($event->page_matches("user/{name}")) { $display_user = User::by_name($event->get_arg('name')); - if ($display_user->id == $config->get_int("anon_id")) { + if ($display_user->id == $config->get_int(UserPageConfig::ANON_ID)) { throw new UserNotFound("No such user"); } $e = send_event(new UserPageBuildingEvent($display_user)); @@ -346,7 +346,7 @@ public function onUserPageBuilding(UserPageBuildingEvent $event): void if ($av) { $event->add_part($av, 0); } elseif ( - ($config->get_string("avatar_host") == "gravatar") && + ($config->get_string(UserPageConfig::AVATAR_HOST) == "gravatar") && ($user->id == $duser->id) ) { $event->add_part( @@ -414,8 +414,8 @@ public function onSetupBuilding(SetupBuildingEvent $event): void $sb = $event->panel->create_new_block("User Options"); $sb->start_table(); $sb->add_bool_option(UserConfig::ENABLE_API_KEYS, "Enable user API keys", true); - $sb->add_bool_option("login_signup_enabled", "Allow new signups", true); - $sb->add_bool_option("user_email_required", "Require email address", true); + $sb->add_bool_option(UserPageConfig::SIGNUP_ENABLED, "Allow new signups", true); + $sb->add_bool_option(UserPageConfig::USER_EMAIL_REQUIRED, "Require email address", true); $sb->add_longtext_option("login_tac", "Terms & Conditions", true); $sb->add_choice_option( "user_loginshowprofile", @@ -426,9 +426,9 @@ public function onSetupBuilding(SetupBuildingEvent $event): void "On log in/out", true ); - $sb->add_choice_option("avatar_host", $hosts, "Avatars", true); + $sb->add_choice_option(UserPageConfig::AVATAR_HOST, $hosts, "Avatars", true); - if ($config->get_string("avatar_host") == "gravatar") { + if ($config->get_string(UserPageConfig::AVATAR_HOST) == "gravatar") { $sb->start_table_row(); $sb->start_table_cell(2); $sb->add_label("
Gravatar Options
"); @@ -436,7 +436,7 @@ public function onSetupBuilding(SetupBuildingEvent $event): void $sb->end_table_row(); $sb->add_choice_option( - "avatar_gravatar_type", + UserPageConfig::AVATAR_GRAVATAR_TYPE, [ 'Default' => 'default', 'Wavatar' => 'wavatar', @@ -447,7 +447,7 @@ public function onSetupBuilding(SetupBuildingEvent $event): void true ); $sb->add_choice_option( - "avatar_gravatar_rating", + UserPageConfig::AVATAR_GRAVATAR_RATING, ['G' => 'g', 'PG' => 'pg', 'R' => 'r', 'X' => 'x'], "Rating", true @@ -502,7 +502,7 @@ public function onUserCreation(UserCreationEvent $event): void if (!$user->can(Permissions::CREATE_USER)) { throw new UserCreationException("Account creation is currently disabled"); } - if (!$config->get_bool("login_signup_enabled") && !$user->can(Permissions::CREATE_OTHER_USER)) { + if (!$config->get_bool(UserPageConfig::SIGNUP_ENABLED) && !$user->can(Permissions::CREATE_OTHER_USER)) { throw new UserCreationException("Account creation is currently disabled"); } if (strlen($name) < 1) { @@ -530,7 +530,7 @@ public function onUserCreation(UserCreationEvent $event): void // Users who can create other users (ie, admins) are exempt // from the email requirement !$user->can(Permissions::CREATE_OTHER_USER) && - ($config->get_bool("user_email_required") && empty($event->email)) + ($config->get_bool(UserPageConfig::USER_EMAIL_REQUIRED) && empty($event->email)) ) { throw new UserCreationException("Email address is required"); } @@ -630,11 +630,11 @@ private function page_login(string $name, string $pass): void private function page_logout(): void { global $page, $config; - $page->add_cookie("session", "", time() + 60 * 60 * 24 * $config->get_int('login_memory'), "/"); + $page->add_cookie("session", "", time() + 60 * 60 * 24 * $config->get_int(UserPageConfig::LOGIN_MEMORY), "/"); if (Extension::is_enabled(SpeedHaxInfo::KEY) && $config->get_bool(SpeedHaxConfig::PURGE_COOKIE)) { # to keep as few versions of content as possible, # make cookies all-or-nothing - $page->add_cookie("user", "", time() + 60 * 60 * 24 * $config->get_int('login_memory'), "/"); + $page->add_cookie("user", "", time() + 60 * 60 * 24 * $config->get_int(UserPageConfig::LOGIN_MEMORY), "/"); } log_info("user", "Logged out"); $page->set_mode(PageMode::REDIRECT); @@ -760,7 +760,7 @@ private function delete_user(Page $page, int $uid, bool $with_images = false, bo } else { $database->execute( "UPDATE images SET owner_id = :new_owner_id WHERE owner_id = :old_owner_id", - ["new_owner_id" => $config->get_int('anon_id'), "old_owner_id" => $uid] + ["new_owner_id" => $config->get_int(UserPageConfig::ANON_ID), "old_owner_id" => $uid] ); } diff --git a/ext/user/theme.php b/ext/user/theme.php index 21bc473ab..d2dccc0d6 100644 --- a/ext/user/theme.php +++ b/ext/user/theme.php @@ -61,14 +61,14 @@ public function display_user_block(Page $page, User $user, array $parts): void public function display_signup_page(Page $page): void { global $config, $user; - $tac = $config->get_string("login_tac", ""); + $tac = $config->get_string(UserPageConfig::LOGIN_TAC, ""); - if ($config->get_bool("login_tac_bbcode")) { + if ($config->get_bool(UserPageConfig::LOGIN_TAC_BBCODE)) { $tac = format_text($tac); } $email_required = ( - $config->get_bool("user_email_required") && + $config->get_bool(UserPageConfig::USER_EMAIL_REQUIRED) && !$user->can(Permissions::CREATE_OTHER_USER) ); @@ -190,7 +190,7 @@ public function create_login_block(): HTMLElement $html = emptyHTML(); $html->appendChild($form); - if ($config->get_bool("login_signup_enabled") && $user->can(Permissions::CREATE_USER)) { + if ($config->get_bool(UserPageConfig::SIGNUP_ENABLED) && $user->can(Permissions::CREATE_USER)) { $html->appendChild(SMALL(A(["href" => make_link("user_admin/create")], "Create Account"))); }