diff --git a/classes/feeds.php b/classes/feeds.php
index 4e6fdbaf801d74c9faeb0eefdada3022a612c05f..43c8bf584542df4bd6ba9e6e7895501f193f2059 100755
--- a/classes/feeds.php
+++ b/classes/feeds.php
@@ -608,7 +608,7 @@ class Feeds extends Handler_Protected {
 			print "<fieldset>";
 			print "<label class='inline'>" . __("Language:") . "</label>";
 			print \Controls\select_tag("search_language", get_pref('DEFAULT_SEARCH_LANGUAGE'), Pref_Feeds::get_ts_languages(),
-				"title=\"".__('Used for word stemming')."\"");
+										["title" => __('Used for word stemming')]);
 			print "</fieldset>";
 		}
 
diff --git a/classes/pref/feeds.php b/classes/pref/feeds.php
index 636f2d69bb7983391ce10e2a08690e38be8061a5..ce2d321bdc662c552ab33ba97ec80b3bdc1ae133 100755
--- a/classes/pref/feeds.php
+++ b/classes/pref/feeds.php
@@ -644,8 +644,10 @@ class Pref_Feeds extends Handler_Protected {
 				$local_purge_intervals = [ T_nsprintf('%d day', '%d days', $purge_interval, $purge_interval) ];
 			}
 
-			print \Controls\select_hash("purge_interval", $purge_interval, $local_purge_intervals,
-				((FORCE_ARTICLE_PURGE == 0) ? "" : 'disabled="1"'));
+			print \Controls\select_hash("purge_interval",
+										$purge_interval,
+										$local_purge_intervals,
+										(FORCE_ARTICLE_PURGE == 0) ? [] : ["disabled" => 1]);
 
 			print "</fieldset>";
 
@@ -815,8 +817,6 @@ class Pref_Feeds extends Handler_Protected {
 
 		print_notice("Enable the options you wish to apply using checkboxes on the right:");
 
-		print "<p>";
-
 		print \Controls\hidden_tag("ids", "$feed_ids");
 		print \Controls\hidden_tag("op", "pref-feeds");
 		print \Controls\hidden_tag("method", "batchEditSave");
@@ -846,8 +846,7 @@ class Pref_Feeds extends Handler_Protected {
 			print "<fieldset>";
 
 			print "<label>" . __('Language:') . "</label> ";
-			print \Controls\select_tag("feed_language", "", $this::get_ts_languages(),
-				'disabled="1"');
+			print \Controls\select_tag("feed_language", "", $this::get_ts_languages(), ["disabled"=> 1]);
 
 			$this->batch_edit_cbox("feed_language");
 
@@ -868,7 +867,7 @@ class Pref_Feeds extends Handler_Protected {
 		$local_update_intervals = $update_intervals;
 		$local_update_intervals[0] .= sprintf(" (%s)", $update_intervals[get_pref("DEFAULT_UPDATE_INTERVAL")]);
 
-		print \Controls\select_hash("update_interval", "", $local_update_intervals, 'disabled="1"');
+		print \Controls\select_hash("update_interval", "", $local_update_intervals, ["disabled" => 1]);
 
 		$this->batch_edit_cbox("update_interval");
 
@@ -890,7 +889,7 @@ class Pref_Feeds extends Handler_Protected {
 			else
 				$local_purge_intervals[0] .= " " . sprintf("(%s)", __("Disabled"));
 
-			print \Controls\select_hash("purge_interval", "", $local_purge_intervals, 'disabled="1"');
+			print \Controls\select_hash("purge_interval", "", $local_purge_intervals, ["disabled" => 1]);
 
 			$this->batch_edit_cbox("purge_interval");
 
diff --git a/classes/pref/filters.php b/classes/pref/filters.php
index caefb1ea7d3e02a76327881975db13d44570470a..e9c58cc3e3694f417d00186c47beb52be2b05d09 100755
--- a/classes/pref/filters.php
+++ b/classes/pref/filters.php
@@ -894,7 +894,7 @@ class Pref_Filters extends Handler_Protected {
 			dojoType='fox.form.Select'");*/
 
 		print \Controls\select_labels("action_param_label", $action_param,
-			"style=\"$label_param_hidden\"",
+			["style" => $label_param_hidden],
 			"filterDlg_actionParamLabel");
 
 		$filter_actions = PluginHost::getInstance()->get_filter_actions();
@@ -909,16 +909,16 @@ class Pref_Filters extends Handler_Protected {
 		}
 
 		if (count($filter_action_hash) == 0) {
-			$filter_plugin_disabled = "disabled";
+			$filter_plugin_disabled = ["disabled" => "1"];
 
 			$filter_action_hash["no-data"] = __("No actions available");
 
 		} else {
-			$filter_plugin_disabled = "";
+			$filter_plugin_disabled = [];
 		}
 
 		print \Controls\select_hash("action_param_plugin", $action_param, $filter_action_hash,
-			"style=\"$plugin_param_hidden\" $filter_plugin_disabled",
+			array_merge(["style" => $plugin_param_hidden], $filter_plugin_disabled),
 			"filterDlg_actionParamPlugin");
 
 		print "</span>";
diff --git a/classes/pref/prefs.php b/classes/pref/prefs.php
index d8491995d20893ed517447a66829f8891cf1b294..3bc8a9a9ca7b490107e836b14c261371be0a1397 100644
--- a/classes/pref/prefs.php
+++ b/classes/pref/prefs.php
@@ -664,13 +664,13 @@ class Pref_Prefs extends Handler_Protected {
 
 					if ($pref_name == "USER_LANGUAGE") {
 						print \Controls\select_hash($pref_name, $value, get_translations(),
-							"style='width : 220px; margin : 0px'");
+							["style" => 'width : 220px; margin : 0px']);
 
 					} else if ($pref_name == "USER_TIMEZONE") {
 
 						$timezones = explode("\n", file_get_contents("lib/timezones.txt"));
 
-						print \Controls\select_tag($pref_name, $value, $timezones, 'dojoType="dijit.form.FilteringSelect"');
+						print \Controls\select_tag($pref_name, $value, $timezones, ["dojoType" => "dijit.form.FilteringSelect"]);
 
 					} else if ($pref_name == "BLACKLISTED_TAGS") { # TODO: other possible <textarea> prefs go here
 
diff --git a/classes/pref/system.php b/classes/pref/system.php
index d3b73336436c9f129e00af49ed39e7a3d7b69e72..a4a072ea9abcaffa41f9f9702ee245c3bd535b83 100644
--- a/classes/pref/system.php
+++ b/classes/pref/system.php
@@ -95,7 +95,7 @@ class Pref_System extends Handler_Administrative {
 							E_USER_ERROR => __("Errors"),
 							E_USER_WARNING => __("Warnings"),
 							E_USER_NOTICE => __("Everything")
-						], 'onchange="Helpers.EventLog.refresh()"', "severity") ?>
+						], ["onchange"=> "Helpers.EventLog.refresh()"], "severity") ?>
 				</div>
 			</div>
 
diff --git a/include/controls.php b/include/controls.php
index b351a9449b4c682a6d205e004e918c2fda9f0991..78ff7557213b74895fcf1a0aafa4eff1a554a8d6 100755
--- a/include/controls.php
+++ b/include/controls.php
@@ -1,19 +1,30 @@
 <?php
    namespace Controls;
 
-   function button_tag(string $value, string $type, $attributes = "") {
-      return "<button dojoType=\"dijit.form.Button\" $attributes type=\"$type\">".htmlspecialchars($value)."</button>";
+   function attributes_to_string(array $attributes) {
+      $rv = "";
+
+      foreach ($attributes as $k => $v) {
+         $rv .= "$k=\"" . htmlspecialchars($v) . "\"";
+      }
+
+      return $rv;
+   }
+
+   function button_tag(string $value, string $type, array $attributes = []) {
+      return "<button dojoType=\"dijit.form.Button\" ".attributes_to_string($attributes)." type=\"$type\">".htmlspecialchars($value)."</button>";
    }
 
-   function submit_tag(string $value, $attributes = "") {
-      return button_tag($value, "submit", "class=\"alt-primary\" $attributes");
+   function submit_tag(string $value, array $attributes = []) {
+      return button_tag($value, "submit", array_merge(["class" => "alt-primary"], $attributes));
    }
 
-   function select_tag(string $name, $value, array $values, string $attributes = "", string $id = "") {
-      $dojo_type = strpos($attributes, "dojoType") === false ? "dojoType='fox.form.Select'" : "";
+   function select_tag(string $name, $value, array $values, array $attributes = [], string $id = "") {
+      $attributes_str = attributes_to_string($attributes);
+      $dojo_type = strpos($attributes_str, "dojoType") === false ? "dojoType='fox.form.Select'" : "";
 
       $rv = "<select $dojo_type name=\"".htmlspecialchars($name)."\"
-         id=\"".htmlspecialchars($id)."\" name=\"".htmlspecialchars($name)."\" $attributes>";
+         id=\"".htmlspecialchars($id)."\" name=\"".htmlspecialchars($name)."\" $attributes_str>";
 
       foreach ($values as $v) {
          $is_sel = ($v == $value) ? "selected=\"selected\"" : "";
@@ -26,7 +37,7 @@
       return $rv;
    }
 
-   function select_labels(string $name, string $value, string $attributes = "", string $id = "") {
+   function select_labels(string $name, string $value, array $attributes = [], string $id = "") {
       $pdo = \Db::pdo();
 
       $sth = $pdo->prepare("SELECT caption FROM ttrss_labels2
@@ -42,11 +53,12 @@
       return select_tag($name, $value, $values, $attributes, $id);
    }
 
-   function select_hash(string $name, $value, array $values, string $attributes = "", string $id = "") {
-      $dojo_type = strpos($attributes, "dojoType") === false ? "dojoType='fox.form.Select'" : "";
+   function select_hash(string $name, $value, array $values, array $attributes = [], string $id = "") {
+      $attributes_str = attributes_to_string($attributes);
+      $dojo_type = strpos($attributes_str, "dojoType") === false ? "dojoType='fox.form.Select'" : "";
 
       $rv = "<select $dojo_type name=\"".htmlspecialchars($name)."\"
-         id=\"".htmlspecialchars($id)."\" name=\"".htmlspecialchars($name)."\" $attributes>";
+         id=\"".htmlspecialchars($id)."\" name=\"".htmlspecialchars($name)."\" $attributes_str>";
 
       foreach ($values as $k => $v) {
          $is_sel = ($k == $value) ? "selected=\"selected\"" : "";
@@ -59,20 +71,21 @@
       return $rv;
    }
 
-   function hidden_tag(string $name, string $value) {
+   function hidden_tag(string $name, string $value, array $attributes = []) {
       return "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\"
-         name=\"".htmlspecialchars($name)."\" value=\"".htmlspecialchars($value)."\">";
+               ".attributes_to_string($attributes)." name=\"".htmlspecialchars($name)."\"
+               value=\"".htmlspecialchars($value)."\">";
    }
 
-   function checkbox_tag(string $name, bool $checked = false, string $value = "", string $attributes = "", string $id = "") {
+   function checkbox_tag(string $name, bool $checked = false, string $value = "", array $attributes = [], string $id = "") {
       $is_checked = $checked ? "checked" : "";
       $value_str = $value ? "value=\"".htmlspecialchars($value)."\"" : "";
 
       return "<input dojoType='dijit.form.CheckBox' name=\"".htmlspecialchars($name)."\"
-                  $value_str $is_checked $attributes id=\"".htmlspecialchars($id)."\">";
+                  $value_str $is_checked ".attributes_to_string($attributes)." id=\"".htmlspecialchars($id)."\">";
    }
 
-   function select_feeds_cats(string $name, int $default_id = null, string $attributes = "",
+   function select_feeds_cats(string $name, int $default_id = null, array $attributes = [],
                   bool $include_all_cats = true, string $root_id = null, int $nest_level = 0, string $id = "") {
 
       $ret = "";
@@ -81,7 +94,7 @@
          $ret .= "<select name=\"".htmlspecialchars($name)."\"
                         id=\"".htmlspecialchars($id)."\"
                         default=\"".((string)$default_id)."\"
-                        dojoType=\"fox.form.Select\" $attributes>";
+                        dojoType=\"fox.form.Select\" ".attributes_to_string($attributes).">";
       }
 
       $pdo = \Db::pdo();
diff --git a/include/login_form.php b/include/login_form.php
index e4eb52a51baf165ae6a762a648873e1048ffb916..c3660bced3588bdbf7c12bac2d9733390b9f5f88 100755
--- a/include/login_form.php
+++ b/include/login_form.php
@@ -142,7 +142,8 @@
 				<label> </label>
 
 				<label id="bw_limit_label">
-					<?= \Controls\checkbox_tag("safe_mode", false, "", "onchange='UtilityApp.bwLimitChange(this)'", 'bw_limit') ?>
+					<?= \Controls\checkbox_tag("bw_limit", false, "",
+									["onchange" => 'UtilityApp.bwLimitChange(this)'], 'bw_limit') ?>
 					<?= __("Use less traffic") ?></label>
 			</fieldset>
 
diff --git a/plugins/mail/init.php b/plugins/mail/init.php
index ffd0397e00169b38e237c851df2a75f8658f3d15..c054196df59e31a41a0d54b59fddd8c9a8b4c7ee 100644
--- a/plugins/mail/init.php
+++ b/plugins/mail/init.php
@@ -160,7 +160,8 @@ class Mail extends Plugin {
 				style=\"width : 30em;\"
 				name=\"destination\" id=\"emailArticleDlg_destination\">"; */
 
-		print \Controls\select_tag("destination", "", $addresslist, 'style="width: 30em" dojoType="dijit.form.ComboBox"');
+		print \Controls\select_tag("destination", "", $addresslist,
+									["style" => "width: 30em", "dojoType" => "dijit.form.ComboBox"]);
 
 /*		print "<div class=\"autocomplete\" id=\"emailArticleDlg_dst_choices\"
 	style=\"z-index: 30; display : none\"></div>"; */