+ added more unit tests

+ topic property is now correctly rendered in the message json when read
+ updated dmvcframework
+ added (an hugly) icon
This commit is contained in:
Daniele Teti 2021-10-07 10:10:25 +02:00
parent 8d44ac5e05
commit cda0651182
3 changed files with 83 additions and 46 deletions

View File

@ -2748,39 +2748,42 @@ var
begin begin
lUnitOfWork := TMVCUnitOfWork<T>.Create; lUnitOfWork := TMVCUnitOfWork<T>.Create;
lUnitOfWork.RegisterDelete(CurrentList); lUnitOfWork.RegisterDelete(CurrentList);
lPKType := NewList[i].GetPrimaryKeyFieldType; if NewList.Count > 0 then
for i := 0 to NewList.Count - 1 do
begin begin
if NewList[i].PKIsNull then lPKType := NewList[0].GetPrimaryKeyFieldType;
for i := 0 to NewList.Count - 1 do
begin begin
lUnitOfWork.RegisterInsert(NewList[i]); if NewList[i].PKIsNull then
continue; begin
end; lUnitOfWork.RegisterInsert(NewList[i]);
continue;
end;
case lPKType of case lPKType of
ftString: ftString:
begin begin
lNeedsToBeUpdated := TMVCUnitOfWork<T>.KeyExistsString(CurrentList, lNeedsToBeUpdated := TMVCUnitOfWork<T>.KeyExistsString(CurrentList,
NewList[i].GetPK.AsString, lFoundAtIndex); NewList[i].GetPK.AsString, lFoundAtIndex);
end; end;
ftInteger: ftInteger:
begin begin
lNeedsToBeUpdated := TMVCUnitOfWork<T>.KeyExistsInt(CurrentList, lNeedsToBeUpdated := TMVCUnitOfWork<T>.KeyExistsInt(CurrentList,
NewList[i].GetPK.AsInteger, lFoundAtIndex); NewList[i].GetPK.AsInteger, lFoundAtIndex);
end; end;
ftLargeInt: ftLargeInt:
begin begin
lNeedsToBeUpdated := TMVCUnitOfWork<T>.KeyExistsInt64(CurrentList, lNeedsToBeUpdated := TMVCUnitOfWork<T>.KeyExistsInt64(CurrentList,
NewList[i].GetPK.AsInt64, lFoundAtIndex); NewList[i].GetPK.AsInt64, lFoundAtIndex);
end; end;
else else
raise EMVCActiveRecord.Create('Invalid primary key type'); raise EMVCActiveRecord.Create('Invalid primary key type');
end; end;
if lNeedsToBeUpdated then if lNeedsToBeUpdated then
lUnitOfWork.RegisterUpdate(NewList[i]) lUnitOfWork.RegisterUpdate(NewList[i])
else else
lUnitOfWork.RegisterInsert(NewList[i]); lUnitOfWork.RegisterInsert(NewList[i]);
end;
end; end;
Result := lUnitOfWork as IMVCMultiExecutor<T>; Result := lUnitOfWork as IMVCMultiExecutor<T>;
end; end;
@ -3148,7 +3151,7 @@ end;
procedure TMVCUnitOfWork<T>.Apply(const ItemApplyAction: TMVCItemApplyAction<T>); procedure TMVCUnitOfWork<T>.Apply(const ItemApplyAction: TMVCItemApplyAction<T>);
var var
i: UInt32; i: Integer;
lHandled: Boolean; lHandled: Boolean;
begin begin
for i := 0 to fListToInsert.Count - 1 do for i := 0 to fListToInsert.Count - 1 do
@ -3166,7 +3169,7 @@ begin
DoItemApplyAction(fListToUpdate[i], eaUpdate, ItemApplyAction, lHandled); DoItemApplyAction(fListToUpdate[i], eaUpdate, ItemApplyAction, lHandled);
if not lHandled then if not lHandled then
begin begin
fListToUpdate[i].Update; fListToUpdate[i].Update(True);
end; end;
end; end;
for i := 0 to fListToDelete.Count - 1 do for i := 0 to fListToDelete.Count - 1 do
@ -3175,7 +3178,7 @@ begin
DoItemApplyAction(fListToDelete[i], eaDelete, ItemApplyAction, lHandled); DoItemApplyAction(fListToDelete[i], eaDelete, ItemApplyAction, lHandled);
if not lHandled then if not lHandled then
begin begin
fListToDelete[i].Delete; fListToDelete[i].Delete(True);
end; end;
end; end;
end; end;
@ -3246,7 +3249,7 @@ begin
Result := false; Result := false;
for i := 0 to NewList.Count - 1 do for i := 0 to NewList.Count - 1 do
begin begin
if NewList[i].GetPK.AsInt64 = KeyValue then if (not NewList[i].PKIsNull) and (NewList[i].GetPK.AsInt64 = KeyValue) then
begin begin
Index := i; Index := i;
Exit(True); Exit(True);

View File

@ -80,9 +80,9 @@ var
lItem: string; lItem: string;
lRespCompressionType: TMVCCompressionType; lRespCompressionType: TMVCCompressionType;
lTmpItem: string; lTmpItem: string;
{$IF not Defined(ALEXANDRIAORBETTER)} {.$IF not Defined(ALEXANDRIAORBETTER)}
lZStream: TZCompressionStream; lZStream: TZCompressionStream;
{$ENDIF} {.$ENDIF}
begin begin
if IsLibrary then if IsLibrary then
begin begin
@ -107,16 +107,16 @@ begin
lTmpItem := lItem.Trim; lTmpItem := lItem.Trim;
if lTmpItem = 'gzip' then if lTmpItem = 'gzip' then
begin begin
{$IF Defined(ALEXANDRIAORBETTER)} {.$IF Defined(ALEXANDRIAORBETTER)}
{ {
There is a bug in 11 Alexandria with TZCompressionStream, so the gzip compression There is a bug in 11 Alexandria with TZCompressionStream, so the gzip compression
is not available until the fix. is not available until the fix.
The issue has been created on https://quality.embarcadero.com/browse/RSP-35516 The issue has been created on https://quality.embarcadero.com/browse/RSP-35516
} }
{$ELSE} {.$ELSE}
lRespCompressionType := TMVCCompressionType.ctGZIP; lRespCompressionType := TMVCCompressionType.ctGZIP;
break; break;
{$ENDIF} {.$ENDIF}
end end
else if lTmpItem = 'deflate' then else if lTmpItem = 'deflate' then
begin begin
@ -133,21 +133,31 @@ begin
// begin // begin
lMemStream := TMemoryStream.Create; lMemStream := TMemoryStream.Create;
try try
{$IF Defined(ALEXANDRIAORBETTER)} {.$IF Defined(ALEXANDRIAORBETTER)}
ZCompressStream(lContentStream, lMemStream); //ZCompressStream(lContentStream, lMemStream);
// use it only for deflate, ZCompressStream (Delphi 11.0) cannot // use it only for deflate, ZCompressStream (Delphi 11.0) cannot
// create gzip compliant streams // create gzip compliant streams
{$ELSE} {.$ELSE}
lZStream := TZCompressionStream.Create(lMemStream, lZStream := TZCompressionStream.Create(lMemStream,
TZCompressionLevel.zcDefault, MVC_COMPRESSION_ZLIB_WINDOW_BITS TZCompressionLevel.zcDefault, MVC_COMPRESSION_ZLIB_WINDOW_BITS
[lRespCompressionType]); [lRespCompressionType]);
try try
lContentStream.Position := 0; lContentStream.Position := 0;
lZStream.CopyFrom(lContentStream, 0) // WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
// WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
// WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
// There is a bug in 11 Alexandria with TZCompressionStream, this bug
// raises an exception here and the debugger catches it, but it its "normal" behavior.
// The gzip stream is correctly created. Please, vote for its resolution.
// https://quality.embarcadero.com/browse/RSP-35516
// WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
// WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
// WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
lZStream.CopyFrom(lContentStream, 0);
finally finally
lZStream.Free; lZStream.Free;
end; end;
{$ENDIF} {.$ENDIF}
except except
lMemStream.Free; lMemStream.Free;
raise; raise;

View File

@ -319,6 +319,8 @@ type
public public
constructor Create(const AParamName: string); overload; constructor Create(const AParamName: string); overload;
constructor Create(const AParamName: string; const DefaultAsString: string); overload; constructor Create(const AParamName: string; const DefaultAsString: string); overload;
constructor Create(const AParamName: string; const DefaultAsInteger: Int64); overload;
constructor Create(const AParamName: string; const DefaultAsBoolean: Boolean); overload;
property ParamName: string read FParamName; property ParamName: string read FParamName;
property DefaultValueAsString: string read FDefaultValueAsString; property DefaultValueAsString: string read FDefaultValueAsString;
property CanBeUsedADefaultValue: Boolean read FCanBeUsedADefaultValue; property CanBeUsedADefaultValue: Boolean read FCanBeUsedADefaultValue;
@ -525,8 +527,8 @@ type
FIsSessionStarted: Boolean; FIsSessionStarted: Boolean;
FSessionMustBeClose: Boolean; FSessionMustBeClose: Boolean;
FLoggedUser: TUser; FLoggedUser: TUser;
FData: TDictionary<string, string>;
FWebSession: TWebSession; FWebSession: TWebSession;
FData: TMVCStringDictionary;
function GetWebSession: TWebSession; function GetWebSession: TWebSession;
function GetLoggedUser: TUser; function GetLoggedUser: TUser;
function GetParamsTable: TMVCRequestParamsTable; function GetParamsTable: TMVCRequestParamsTable;
@ -538,6 +540,7 @@ type
function SendSessionCookie(const AContext: TWebContext): string; function SendSessionCookie(const AContext: TWebContext): string;
function AddSessionToTheSessionList(const ASessionType, ASessionId: string; function AddSessionToTheSessionList(const ASessionType, ASessionId: string;
const ASessionTimeout: Integer): TWebSession; const ASessionTimeout: Integer): TWebSession;
function GetData: TMVCStringDictionary;
public public
constructor Create(const ARequest: TWebRequest; const AResponse: TWebResponse; constructor Create(const ARequest: TWebRequest; const AResponse: TWebResponse;
const AConfig: TMVCConfig; const ASerializers: TDictionary<string, IMVCSerializer>); const AConfig: TMVCConfig; const ASerializers: TDictionary<string, IMVCSerializer>);
@ -557,7 +560,7 @@ type
property Response: TMVCWebResponse read FResponse; property Response: TMVCWebResponse read FResponse;
property Session: TWebSession read GetWebSession; property Session: TWebSession read GetWebSession;
property Config: TMVCConfig read FConfig; property Config: TMVCConfig read FConfig;
property Data: TDictionary<string, string> read FData; property Data: TMVCStringDictionary read GetData;
property ParamsTable: TMVCRequestParamsTable read GetParamsTable write SetParamsTable; property ParamsTable: TMVCRequestParamsTable read GetParamsTable write SetParamsTable;
end; end;
@ -1151,6 +1154,18 @@ begin
FCanBeUsedADefaultValue := False; FCanBeUsedADefaultValue := False;
end; end;
constructor MVCInjectableParamAttribute.Create(const AParamName: string;
const DefaultAsInteger: Int64);
begin
Create(AParamName, DefaultAsInteger.ToString);
end;
constructor MVCInjectableParamAttribute.Create(const AParamName: string;
const DefaultAsBoolean: Boolean);
begin
Create(AParamName, iif(DefaultAsBoolean,'true','false'));
end;
{ MVCProducesAttribute } { MVCProducesAttribute }
constructor MVCProducesAttribute.Create(const AValue, ACharset: string); constructor MVCProducesAttribute.Create(const AValue, ACharset: string);
@ -1918,7 +1933,7 @@ begin
FResponse := TMVCWebResponse.Create(AResponse); FResponse := TMVCWebResponse.Create(AResponse);
FConfig := AConfig; FConfig := AConfig;
FSerializers := ASerializers; FSerializers := ASerializers;
FData := TDictionary<string, string>.Create; FData := nil;
FLoggedUser := nil; FLoggedUser := nil;
end; end;
@ -1949,6 +1964,15 @@ begin
FResponse.Flush; FResponse.Flush;
end; end;
function TWebContext.GetData: TMVCStringDictionary;
begin
if fData = nil then
begin
fData := TMVCStringDictionary.Create;
end;
Result := fData;
end;
function TWebContext.GetHostingFrameworkType: TMVCHostingFrameworkType; function TWebContext.GetHostingFrameworkType: TMVCHostingFrameworkType;
begin begin
{$IFDEF WEBAPACHEHTTP} {$IFDEF WEBAPACHEHTTP}