From 8026f3c3bd9222cdc72402e855e64e109c46b03e Mon Sep 17 00:00:00 2001
From: Andrew Dolgov <noreply@fakecake.org>
Date: Thu, 25 Feb 2021 09:34:03 +0300
Subject: [PATCH] initial (wip) for new prefs: add missing

---
 classes/prefs.php | 251 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 251 insertions(+)
 create mode 100644 classes/prefs.php

diff --git a/classes/prefs.php b/classes/prefs.php
new file mode 100644
index 000000000..9855c67d7
--- /dev/null
+++ b/classes/prefs.php
@@ -0,0 +1,251 @@
+<?php
+class Prefs {
+	// (this is the database-backed version of Config.php)
+
+	const PURGE_OLD_DAYS = "PURGE_OLD_DAYS";
+	const DEFAULT_UPDATE_INTERVAL = "DEFAULT_UPDATE_INTERVAL";
+	const DEFAULT_ARTICLE_LIMIT = "DEFAULT_ARTICLE_LIMIT";
+	const ALLOW_DUPLICATE_POSTS = "ALLOW_DUPLICATE_POSTS";
+	const ENABLE_FEED_CATS = "ENABLE_FEED_CATS";
+	const SHOW_CONTENT_PREVIEW = "SHOW_CONTENT_PREVIEW";
+	const SHORT_DATE_FORMAT = "SHORT_DATE_FORMAT";
+	const LONG_DATE_FORMAT = "LONG_DATE_FORMAT";
+	const COMBINED_DISPLAY_MODE = "COMBINED_DISPLAY_MODE";
+	const HIDE_READ_FEEDS = "HIDE_READ_FEEDS";
+	const ON_CATCHUP_SHOW_NEXT_FEED = "ON_CATCHUP_SHOW_NEXT_FEED";
+	const FEEDS_SORT_BY_UNREAD = "FEEDS_SORT_BY_UNREAD";
+	const REVERSE_HEADLINES = "REVERSE_HEADLINES";
+	const DIGEST_ENABLE = "DIGEST_ENABLE";
+	const CONFIRM_FEED_CATCHUP = "CONFIRM_FEED_CATCHUP";
+	const CDM_AUTO_CATCHUP = "CDM_AUTO_CATCHUP";
+	const _DEFAULT_VIEW_MODE = "_DEFAULT_VIEW_MODE";
+	const _DEFAULT_VIEW_LIMIT = "_DEFAULT_VIEW_LIMIT";
+	//const _PREFS_ACTIVE_TAB = "_PREFS_ACTIVE_TAB";
+	const STRIP_UNSAFE_TAGS = "STRIP_UNSAFE_TAGS";
+	const BLACKLISTED_TAGS = "BLACKLISTED_TAGS";
+	const FRESH_ARTICLE_MAX_AGE = "FRESH_ARTICLE_MAX_AGE";
+	const DIGEST_CATCHUP = "DIGEST_CATCHUP";
+	const CDM_EXPANDED = "CDM_EXPANDED";
+	const PURGE_UNREAD_ARTICLES = "PURGE_UNREAD_ARTICLES";
+	const HIDE_READ_SHOWS_SPECIAL = "HIDE_READ_SHOWS_SPECIAL";
+	const VFEED_GROUP_BY_FEED = "VFEED_GROUP_BY_FEED";
+	const STRIP_IMAGES = "STRIP_IMAGES";
+	const _DEFAULT_VIEW_ORDER_BY = "_DEFAULT_VIEW_ORDER_BY";
+	const ENABLE_API_ACCESS = "ENABLE_API_ACCESS";
+	//const _COLLAPSED_SPECIAL = "_COLLAPSED_SPECIAL";
+	//const _COLLAPSED_LABELS = "_COLLAPSED_LABELS";
+	//const _COLLAPSED_UNCAT = "_COLLAPSED_UNCAT";
+	//const _COLLAPSED_FEEDLIST = "_COLLAPSED_FEEDLIST";
+	//const _MOBILE_ENABLE_CATS = "_MOBILE_ENABLE_CATS";
+	//const _MOBILE_SHOW_IMAGES = "_MOBILE_SHOW_IMAGES";
+	//const _MOBILE_HIDE_READ = "_MOBILE_HIDE_READ";
+	//const _MOBILE_SORT_FEEDS_UNREAD = "_MOBILE_SORT_FEEDS_UNREAD";
+	//const _MOBILE_BROWSE_CATS = "_MOBILE_BROWSE_CATS";
+	//const _THEME_ID = "_THEME_ID";
+	const USER_TIMEZONE = "USER_TIMEZONE";
+	const USER_STYLESHEET = "USER_STYLESHEET";
+	const SORT_HEADLINES_BY_FEED_DATE = "SORT_HEADLINES_BY_FEED_DATE";
+	const SSL_CERT_SERIAL = "SSL_CERT_SERIAL";
+	const DIGEST_PREFERRED_TIME = "DIGEST_PREFERRED_TIME";
+	//const _PREFS_SHOW_EMPTY_CATS = "_PREFS_SHOW_EMPTY_CATS";
+	const _DEFAULT_INCLUDE_CHILDREN = "_DEFAULT_INCLUDE_CHILDREN";
+	//const AUTO_ASSIGN_LABELS = "AUTO_ASSIGN_LABELS";
+	const _ENABLED_PLUGINS = "_ENABLED_PLUGINS";
+	const _MOBILE_REVERSE_HEADLINES = "_MOBILE_REVERSE_HEADLINES";
+	const USER_CSS_THEME = "USER_CSS_THEME";
+	const USER_LANGUAGE = "USER_LANGUAGE";
+	const DEFAULT_SEARCH_LANGUAGE = "DEFAULT_SEARCH_LANGUAGE";
+	const _PREFS_MIGRATED = "_PREFS_MIGRATED";
+
+	private const _DEFAULTS = [
+		Prefs::PURGE_OLD_DAYS => [ 60, Config::T_INT ],
+		Prefs::DEFAULT_UPDATE_INTERVAL => [ 30, Config::T_INT ],
+		Prefs::DEFAULT_ARTICLE_LIMIT => [ 30, Config::T_INT ],
+		Prefs::ALLOW_DUPLICATE_POSTS => [ false, Config::T_BOOL ],
+		Prefs::ENABLE_FEED_CATS => [ true, Config::T_BOOL ],
+		Prefs::SHOW_CONTENT_PREVIEW => [ true, Config::T_BOOL ],
+		Prefs::SHORT_DATE_FORMAT => [ "M d, G:i", Config::T_STRING ],
+		Prefs::LONG_DATE_FORMAT => [ "D, M d Y - G:i", Config::T_STRING ],
+		Prefs::COMBINED_DISPLAY_MODE => [ true, Config::T_BOOL ],
+		Prefs::HIDE_READ_FEEDS => [ false, Config::T_BOOL ],
+		Prefs::ON_CATCHUP_SHOW_NEXT_FEED => [ false, Config::T_BOOL ],
+		Prefs::FEEDS_SORT_BY_UNREAD => [ false, Config::T_BOOL ],
+		Prefs::REVERSE_HEADLINES => [ false, Config::T_BOOL ],
+		Prefs::DIGEST_ENABLE => [ false, Config::T_BOOL ],
+		Prefs::CONFIRM_FEED_CATCHUP => [ true, Config::T_BOOL ],
+		Prefs::CDM_AUTO_CATCHUP => [ false, Config::T_BOOL ],
+		Prefs::_DEFAULT_VIEW_MODE => [ "adaptive", Config::T_BOOL ],
+		Prefs::_DEFAULT_VIEW_LIMIT => [ 30, Config::T_INT ],
+		//Prefs::_PREFS_ACTIVE_TAB => [ "", Config::T_STRING ],
+		Prefs::STRIP_UNSAFE_TAGS => [ true, Config::T_BOOL ],
+		Prefs::BLACKLISTED_TAGS => [ 'main, generic, misc, uncategorized, blog, blogroll, general, news', Config::T_STRING ],
+		Prefs::FRESH_ARTICLE_MAX_AGE => [ 24, Config::T_INT ],
+		Prefs::DIGEST_CATCHUP => [ false, Config::T_BOOL ],
+		Prefs::CDM_EXPANDED => [ true, Config::T_BOOL ],
+		Prefs::PURGE_UNREAD_ARTICLES => [ true, Config::T_BOOL ],
+		Prefs::HIDE_READ_SHOWS_SPECIAL => [ true, Config::T_BOOL ],
+		Prefs::VFEED_GROUP_BY_FEED => [ false, Config::T_BOOL ],
+		Prefs::STRIP_IMAGES => [ false, Config::T_BOOL ],
+		Prefs::_DEFAULT_VIEW_ORDER_BY => [ "default", Config::T_STRING ],
+		Prefs::ENABLE_API_ACCESS => [ false, Config::T_BOOL ],
+		//Prefs::_COLLAPSED_SPECIAL => [ false, Config::T_BOOL ],
+		//Prefs::_COLLAPSED_LABELS => [ false, Config::T_BOOL ],
+		//Prefs::_COLLAPSED_UNCAT => [ false, Config::T_BOOL ],
+		//Prefs::_COLLAPSED_FEEDLIST => [ false, Config::T_BOOL ],
+		//Prefs::_MOBILE_ENABLE_CATS => [ false, Config::T_BOOL ],
+		//Prefs::_MOBILE_SHOW_IMAGES => [ false, Config::T_BOOL ],
+		//Prefs::_MOBILE_HIDE_READ => [ false, Config::T_BOOL ],
+		//Prefs::_MOBILE_SORT_FEEDS_UNREAD => [ false, Config::T_BOOL ],
+		//Prefs::_MOBILE_BROWSE_CATS => [ true, Config::T_BOOL ],
+		//Prefs::_THEME_ID => [ 0, Config::T_BOOL ],
+		Prefs::USER_TIMEZONE => [ "Automatic", Config::T_STRING ],
+		Prefs::USER_STYLESHEET => [ "", Config::T_STRING ],
+		Prefs::SORT_HEADLINES_BY_FEED_DATE => [ false, Config::T_BOOL ],
+		Prefs::SSL_CERT_SERIAL => [ "", Config::T_STRING ],
+		Prefs::DIGEST_PREFERRED_TIME => [ "00:00", Config::T_STRING ],
+		//Prefs::_PREFS_SHOW_EMPTY_CATS => [ false, Config::T_BOOL ],
+		Prefs::_DEFAULT_INCLUDE_CHILDREN => [ false, Config::T_BOOL ],
+		//Prefs::AUTO_ASSIGN_LABELS => [ false, Config::T_BOOL ],
+		Prefs::_ENABLED_PLUGINS => [ "", Config::T_STRING ],
+		Prefs::_MOBILE_REVERSE_HEADLINES => [ false, Config::T_BOOL ],
+		Prefs::USER_CSS_THEME => [ "" , Config::T_STRING ],
+		Prefs::USER_LANGUAGE => [ "" , Config::T_STRING ],
+		Prefs::DEFAULT_SEARCH_LANGUAGE => [ "" , Config::T_STRING ],
+		Prefs::_PREFS_MIGRATED => [ false, Config::T_BOOL ],
+	];
+
+	private const _PROFILE_BLACKLIST = [
+		Prefs::ALLOW_DUPLICATE_POSTS,
+		Prefs::PURGE_OLD_DAYS,
+		Prefs::PURGE_UNREAD_ARTICLES,
+		Prefs::DIGEST_ENABLE,
+		Prefs::DIGEST_CATCHUP,
+		Prefs::BLACKLISTED_TAGS,
+		Prefs::ENABLE_API_ACCESS,
+		//Prefs::UPDATE_POST_ON_CHECKSUM_CHANGE,
+		Prefs::DEFAULT_UPDATE_INTERVAL,
+		Prefs::USER_TIMEZONE,
+		Prefs::SORT_HEADLINES_BY_FEED_DATE,
+		Prefs::SSL_CERT_SERIAL,
+		Prefs::DIGEST_PREFERRED_TIME
+	];
+
+	private static $instance;
+	private $cache = [];
+
+	/** @var PDO */
+	private $pdo;
+
+	public static function get_instance() {
+		if (self::$instance == null)
+			self::$instance = new self();
+
+		return self::$instance;
+	}
+
+	function __construct() {
+		$this->pdo = Db::pdo();
+
+		/*$ref = new ReflectionClass(get_class($this));
+
+		foreach ($ref->getConstants() as $const => $cvalue) {
+			if (isset($this::_DEFAULTS[$const])) {
+				list ($defval, $deftype) = $this::_DEFAULTS[$const];
+
+				$this->cache[$cvalue] = [ Config::cast_to($defval, $deftype), $deftype ];
+			}
+		}*/
+	}
+
+	private function _get($pref_name, int $owner_uid, int $profile_id = null) {
+		if (isset(self::_DEFAULTS[$pref_name])) {
+			if (!$profile_id || in_array($pref_name, self::_PROFILE_BLACKLIST)) $profile_id = null;
+
+			$sth = $this->pdo->prepare("SELECT value FROM ttrss_user_prefs2
+							WHERE pref_name = :name AND owner_uid = :uid AND
+							(profile = :profile OR (:profile IS NULL AND profile IS NULL))");
+
+			$sth->execute(["uid" => $owner_uid, "profile" => $profile_id, "name" => $pref_name ]);
+
+			list ($def_val, $type_hint) = self::_DEFAULTS[$pref_name];
+
+			if ($row = $sth->fetch(PDO::FETCH_ASSOC)) {
+				return Config::cast_to($row["value"], $type_hint);
+			} else {
+				return $def_val;
+			}
+		}
+
+		return null;
+	}
+
+	private function _set($pref_name, $value, int $owner_uid, int $profile_id = null) {
+		if (!$profile_id) $profile_id = null;
+
+		if ($profile_id && in_array($pref_name, self::_PROFILE_BLACKLIST))
+			return false;
+
+		if (isset(self::_DEFAULTS[$pref_name])) {
+			$sth = $this->pdo->prepare("SELECT COUNT(pref_name) AS count FROM ttrss_user_prefs2
+			WHERE pref_name = :name AND owner_uid = :uid AND
+			(profile = :profile OR (:profile IS NULL AND profile IS NULL))");
+
+			$sth->execute(["uid" => $owner_uid, "profile" => $profile_id, "name" => $pref_name ]);
+
+			if ($row = $sth->fetch()) {
+				if ($row["count"] == 0) {
+					$sth = $this->pdo->prepare("INSERT INTO ttrss_user_prefs2
+						(pref_name, value, owner_uid, profile)
+						VALUES
+						(:name, :value, :uid, :profile)");
+
+					return $sth->execute(["uid" => $owner_uid, "profile" => $profile_id, "name" => $pref_name, "value" => $value ]);
+
+				} else {
+					$sth = $this->pdo->prepare("UPDATE ttrss_user_prefs2
+						SET value = :value
+						WHERE pref_name = :name AND owner_uid = :uid AND
+							(profile = :profile OR (:profile IS NULL AND profile IS NULL))");
+
+					return $sth->execute(["uid" => $owner_uid, "profile" => $profile_id, "name" => $pref_name, "value" => $value ]);
+				}
+			}
+		}
+
+		return false;
+	}
+
+	function migrate(int $owner_uid, int $profile_id = null) {
+		if (!$profile_id) $profile_id = null;
+
+		if (!$this->_get(Prefs::_PREFS_MIGRATED, $owner_uid, $profile_id)) {
+
+			$sth = $this->pdo->prepare("SELECT pref_name, value FROM ttrss_user_prefs
+				WHERE owner_uid = :uid AND
+					(profile = :profile OR (:profile IS NULL AND profile IS NULL))");
+			$sth->execute(["uid" => $owner_uid, "profile" => $profile_id]);
+
+			while ($row = $sth->fetch(PDO::FETCH_ASSOC)) {
+				if (isset(self::_DEFAULTS[$row["pref_name"]])) {
+					list ($def_val, $type_hint) = self::_DEFAULTS[$row["pref_name"]];
+
+					$user_val = Config::cast_to($row["value"], $type_hint);
+
+					if ($user_val != $def_val) {
+						$this->_set($row["pref_name"], $user_val, $owner_uid, $profile_id);
+					}
+				}
+			}
+
+			$this->_set(Prefs::_PREFS_MIGRATED, "1", $owner_uid, $profile_id);
+		}
+
+		die;
+	}
+
+	static function initialize($owner_uid, int $profile_id = null) {
+		$instance = self::get_instance();
+
+		$instance->migrate($owner_uid, $profile_id);
+	}
+}
-- 
GitLab