An alternative to UBB.threads
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

252 lines
8.2 KiB

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Web.Core;
using Web.Core.DB;
using Web.Core.DB.conditions;
using FLocal.Common.actions;
namespace FLocal.Common.dataobjects {
public class Restriction : SqlObject<Restriction> {
public class TableSpec : ISqlObjectTableSpec {
public const string TABLE = "Restrictions";
public const string FIELD_ID = "Id";
public const string FIELD_USERID = "UserId";
public const string FIELD_BOARDID = "BoardId";
public const string FIELD_DATA = "Data";
public static readonly TableSpec instance = new TableSpec();
public string name { get { return TABLE; } }
public string idName { get { return FIELD_ID; } }
public void refreshSqlObject(int id) {
Refresh(id);
var restriction = Restriction.LoadById(id);
byUser_Recalculate(restriction.userId);
byBoard_Recalculate(restriction.boardId);
lock(restrictionId_cache) {
if(!restrictionId_cache.ContainsKey(restriction.userId)) restrictionId_cache[restriction.userId] = new Dictionary<int, int?>();
restrictionId_cache[restriction.userId][restriction.boardId] = restriction.id;
}
}
}
protected override ISqlObjectTableSpec table { get { return TableSpec.instance; } }
private int _userId;
public int userId {
get {
this.LoadIfNotLoaded();
return this._userId;
}
}
public User user {
get {
return User.LoadById(this.userId);
}
}
private int _boardId;
public int boardId {
get {
this.LoadIfNotLoaded();
return this._boardId;
}
}
public Board board {
get {
return Board.LoadById(this.boardId);
}
}
private Dictionary<int, DateTime> _data;
public Dictionary<int, DateTime> data {
get {
this.LoadIfNotLoaded();
return this._data;
}
}
protected override void doFromHash(Dictionary<string, string> data) {
this._userId = int.Parse(data[TableSpec.FIELD_USERID]);
this._boardId = int.Parse(data[TableSpec.FIELD_BOARDID]);
this._data = (
from part in data[TableSpec.FIELD_DATA].Split(new char[] {';'}, StringSplitOptions.RemoveEmptyEntries)
let subparts = part.Split(new char[] {':'}, 2)
select new KeyValuePair<int, DateTime>(
int.Parse(subparts[0]),
new DateTime(long.Parse(subparts[1]))
)
).ToDictionary();
}
public XElement exportToXml(UserContext context) {
return new XElement("restriction",
this.user.exportToXmlForViewing(context),
this.board.exportToXmlSimple(context, Board.SubboardsOptions.None),
new XElement("layers",
from kvp in this.data
select PostLayer.LoadById(kvp.Key).exportToXml(
context,
new XElement("restrictionExpires", kvp.Value.ToXml())
)
)
);
}
private static readonly Dictionary<int, Dictionary<int, int?>> restrictionId_cache = new Dictionary<int,Dictionary<int, int?>>();
public static Restriction GetRestriction(User user, Board board) {
if(!restrictionId_cache.ContainsKey(user.id) || !restrictionId_cache[user.id].ContainsKey(board.id)) {
lock(restrictionId_cache) {
if(!restrictionId_cache.ContainsKey(user.id) || !restrictionId_cache[user.id].ContainsKey(board.id)) {
if(!restrictionId_cache.ContainsKey(user.id)) restrictionId_cache[user.id] = new Dictionary<int, int?>();
List<string> ids = Config.instance.mainConnection.LoadIdsByConditions(
TableSpec.instance,
new ComplexCondition(
ConditionsJoinType.AND,
new ComparisonCondition(
TableSpec.instance.getColumnSpec(TableSpec.FIELD_USERID),
ComparisonType.EQUAL,
user.id.ToString()
),
new ComparisonCondition(
TableSpec.instance.getColumnSpec(TableSpec.FIELD_BOARDID),
ComparisonType.EQUAL,
board.id.ToString()
)
),
Diapasone.unlimited
);
if(ids.Count < 1) {
restrictionId_cache[user.id][board.id] = null;
} else {
restrictionId_cache[user.id][board.id] = Restriction.LoadById(int.Parse(ids.Single())).id;
}
}
}
}
if(restrictionId_cache[user.id][board.id].HasValue) {
return Restriction.LoadById(restrictionId_cache[user.id][board.id].Value);
} else {
return null;
}
}
public static Dictionary<int, DateTime> GetRestrictionData(User user, Board board) {
Restriction restriction = GetRestriction(user, board);
if(restriction != null) {
return restriction.data;
} else {
return new Dictionary<int,DateTime>();
}
}
private static readonly Dictionary<int, IEnumerable<int>> byBoard_cache = new Dictionary<int, IEnumerable<int>>();
private static void byBoard_Recalculate(int boardId) {
lock(byBoard_cache) {
byBoard_cache[boardId] =
from stringId in Config.instance.mainConnection.LoadIdsByConditions(
TableSpec.instance,
new ComparisonCondition(
TableSpec.instance.getColumnSpec(TableSpec.FIELD_BOARDID),
ComparisonType.EQUAL,
boardId.ToString()
),
Diapasone.unlimited
)
select Restriction.LoadById(int.Parse(stringId)).id;
}
}
public static IEnumerable<User> GetRestrictedUsers(Board board) {
if(!byBoard_cache.ContainsKey(board.id)) {
byBoard_Recalculate(board.id);
}
return from id in byBoard_cache[board.id] select Restriction.LoadById(id).user;
}
private static readonly Dictionary<int, IEnumerable<int>> byUser_cache = new Dictionary<int,IEnumerable<int>>();
private static void byUser_Recalculate(int userId) {
lock(byUser_cache) {
byUser_cache[userId] =
from stringId in Config.instance.mainConnection.LoadIdsByConditions(
TableSpec.instance,
new ComparisonCondition(
TableSpec.instance.getColumnSpec(TableSpec.FIELD_USERID),
ComparisonType.EQUAL,
userId.ToString()
),
Diapasone.unlimited
)
select Restriction.LoadById(int.Parse(stringId)).id;
}
}
public static IEnumerable<Restriction> GetRestrictions(User user) {
if(!byUser_cache.ContainsKey(user.id)) {
byUser_Recalculate(user.id);
}
return from id in byUser_cache[user.id] select Restriction.LoadById(id);
}
public static void RecalculateRestrictions(Board board, User user) {
List<Punishment> punishments = (from punishment in Punishment.getEffectivePunishments(user, board) where punishment.punishmentType.weight > 0 orderby punishment.expires descending select punishment).ToList();
Dictionary<int, DateTime> layer2expirationDate = new Dictionary<int,DateTime>();
foreach(var layer in PostLayer.allLayers) {
if(!layer.maxPunishments.HasValue) continue;
bool restricted = false;
int accumulated = 0;
DateTime? expirationDate = null;
foreach(var punishment in punishments) {
accumulated += punishment.punishmentType.weight;
if(accumulated >= layer.maxPunishments.Value) {
expirationDate = punishment.expires;
restricted = true;
break;
}
}
if(restricted) {
layer2expirationDate[layer.id] = expirationDate.Value;
}
}
string data = (from kvp in layer2expirationDate select string.Format("{0}:{1}", kvp.Key, kvp.Value.Ticks)).Join(";");
ChangeSetUtil.ApplyChanges(
new InsertOrUpdateChange(
TableSpec.instance,
new Dictionary<string,AbstractFieldValue> {
{ TableSpec.FIELD_BOARDID, new ScalarFieldValue(board.id.ToString()) },
{ TableSpec.FIELD_USERID, new ScalarFieldValue(user.id.ToString()) },
{ TableSpec.FIELD_DATA, new ScalarFieldValue(data) },
},
new Dictionary<string,AbstractFieldValue> {
{ TableSpec.FIELD_DATA, new ScalarFieldValue(data) },
},
new ComplexCondition(
ConditionsJoinType.AND,
new ComparisonCondition(
TableSpec.instance.getColumnSpec(TableSpec.FIELD_BOARDID),
ComparisonType.EQUAL,
board.id.ToString()
),
new ComparisonCondition(
TableSpec.instance.getColumnSpec(TableSpec.FIELD_USERID),
ComparisonType.EQUAL,
user.id.ToString()
)
)
)
);
}
}
}