Skip to content

Commit

Permalink
https://github.com/danieleteti/delphimvcframework/issues/330
Browse files Browse the repository at this point in the history
  • Loading branch information
danieleteti committed Apr 13, 2020
1 parent 640ffef commit 26b8208
Show file tree
Hide file tree
Showing 9 changed files with 102 additions and 13 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,8 @@ end;

- Fixed! [issue312](https://github.com/danieleteti/delphimvcframework/issues/312)

- Fixed! [issue330](https://github.com/danieleteti/delphimvcframework/issues/330)

- Fixed! [issue333](https://github.com/danieleteti/delphimvcframework/issues/333)

- Fixed! [issue334](https://github.com/danieleteti/delphimvcframework/issues/334)
Expand Down
4 changes: 2 additions & 2 deletions samples/serversideviews_mustache/WebSiteControllerU.pas
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,10 @@ procedure TWebSiteController.Index;

procedure TWebSiteController.NewPerson;
var
lDAL: IPeopleDAL;
LDAL: IPeopleDAL;
lDevices: TDeviceList;
begin
lDAL := TServicesFactory.GetPeopleDAL;
LDAL := TServicesFactory.GetPeopleDAL;
lDevices := LDAL.GetDevicesList;
try
ViewData['deviceslist'] := lDevices;
Expand Down
34 changes: 26 additions & 8 deletions sources/MVCFramework.View.Renderers.Mustache.pas
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
interface

uses
MVCFramework, System.Generics.Collections, System.SysUtils,
MVCFramework.Commons, System.IOUtils, System.Classes;
MVCFramework, System.SysUtils,
MVCFramework.Commons, System.IOUtils, System.Classes, Data.DB;

type
{ This class implements the mustache view engine for server side views }
Expand All @@ -49,10 +49,11 @@ implementation
SynCommons,
MVCFramework.Serializer.Defaults,
MVCFramework.Serializer.Intf,
MVCFramework.DuckTyping;
MVCFramework.DuckTyping, System.Generics.Collections;

{$WARNINGS OFF}


procedure TMVCMustacheViewEngine.Execute(const ViewName: string; const OutputStream: TStream);
var
lViewFileName: string;
Expand All @@ -65,6 +66,7 @@ procedure TMVCMustacheViewEngine.Execute(const ViewName: string; const OutputStr
if not FileExists(lViewFileName) then
raise EMVCFrameworkViewException.CreateFmt('View [%s] not found', [ViewName]);
lViewTemplate := StringToUTF8(TFile.ReadAllText(lViewFileName, TEncoding.UTF8));
{ don't free this instance! There is a garbagecollector in SynCommons }
lViewEngine := TSynMustache.Parse(lViewTemplate);
lSW := TStreamWriter.Create(OutputStream);
try
Expand All @@ -76,23 +78,27 @@ procedure TMVCMustacheViewEngine.Execute(const ViewName: string; const OutputStr

{$WARNINGS ON}


procedure TMVCMustacheViewEngine.PrepareModels;
var
lFirst: Boolean;
lList: IMVCList;
DataObj: TPair<string, TObject>;
lDSPair: TPair<string, TDataSet>;
lSJSON: string;
lJSON: string;
lSer: IMVCSerializer;
begin
if (FJSONModel <> '{}') and (not FJSONModel.IsEmpty) then
Exit;
FJSONModel := '{}';

lSer := GetDefaultSerializer;
lSJSON := '{';
lFirst := True;

if Assigned(ViewModel) then
begin
lSer := GetDefaultSerializer;
lSJSON := '{';
lFirst := True;
for DataObj in ViewModel do
begin
lList := TDuckTypedList.Wrap(DataObj.Value);
Expand All @@ -105,9 +111,21 @@ procedure TMVCMustacheViewEngine.PrepareModels;
lSJSON := lSJSON + '"' + DataObj.Key + '":' + lJSON;
lFirst := False;
end;
lSJSON := lSJSON + '}';
FJSONModel := lSJSON;
end;

if Assigned(ViewDataSets) then
begin
for lDSPair in ViewDataSets do
begin
lJSON := lSer.SerializeDataSet(lDSPair.Value);
if not lFirst then
lSJSON := lSJSON + ',';
lSJSON := lSJSON + '"' + lDSPair.Key + '":' + lJSON;
lFirst := False;
end;
end;
lSJSON := lSJSON + '}';
FJSONModel := lSJSON;
end;

end.
27 changes: 27 additions & 0 deletions unittests/general/Several/LiveServerTestU.pas
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,11 @@ TServerTest = class(TBaseServerTest)
// test web server
[Test]
procedure TestDirectoryTraversal1;

// test server side views
[Test]
procedure TestViewDataViewDataSet;

end;

[TestFixture]
Expand Down Expand Up @@ -1603,6 +1608,28 @@ procedure TServerTest.TestTypedTGuid1;
Assert.areEqual('{161BEA56-480B-40A8-AF0E-7FDF6B08E121} modified from server', res.BodyAsString);
end;

procedure TServerTest.TestViewDataViewDataSet;
var
lRes: IRESTResponse;
begin
lRes := RESTClient.Accept(TMVCMediaType.TEXT_PLAIN).doGET('/website/list', []);
var lLines := lRes.BodyAsString.Split([sLineBreak]);
var lCount: Integer := 1001;
for var lLine in lLines do
begin
var lLinePieces := lLine.Split(['|']);
if Length(lLinePieces) = 1 then
begin
lCount := 1001;
Continue;
end;
Assert.AreEqual(9, Length(lLinePieces));
Assert.AreEqual(lCount, lLinePieces[0].ToInteger);
Inc(lCount);
end;
Assert.areEqual(HTTP_STATUS.OK, lRes.ResponseCode);
end;

procedure TServerTest.TestWrongJSONBody;
var
lRes: IRESTResponse;
Expand Down
27 changes: 25 additions & 2 deletions unittests/general/TestServer/TestServerControllerU.pas
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,12 @@ TTestServerController = class(TMVCController)
[MVCHTTPMethod([httpGET])]
[MVCPath('/($projectid)/pictures/($imageuuid)')]
procedure GetImage;

{ templates }
[MVCHTTPMethod([httpGET])]
[MVCPath('/website/list')]
procedure Tmpl_ListOfDataUsingDatasets;

end;

[MVCPath('/private')]
Expand Down Expand Up @@ -274,7 +280,7 @@ implementation
MVCFramework.Serializer.Defaults,
MVCFramework.DuckTyping,
System.IOUtils,
System.Classes;
System.Classes, FireDAC.Comp.Client;

{ TTestServerController }

Expand Down Expand Up @@ -469,7 +475,7 @@ procedure TTestServerController.TestGetImagePng;
begin
ContentType := TMVCMediaType.IMAGE_PNG;
lFName := TPath.Combine(TPath.GetDirectoryName(ParamStr(0)), '..\..') + '\sample.png';
//Render(TFile.OpenRead('..\..\sample.png'));
// Render(TFile.OpenRead('..\..\sample.png'));
Render(TFile.OpenRead(lFName));
end;

Expand Down Expand Up @@ -740,6 +746,23 @@ procedure TTestServerController.TestTypedActionTTime1(value: TTime);
Render(TimeToISOTime(value) + ' modified from server');
end;

procedure TTestServerController.Tmpl_ListOfDataUsingDatasets;
var
lDS: TFDMemTable;
begin
lDS := TFDMemTable.Create(nil);
try
var lFName: string := TPath.Combine(TPath.GetDirectoryName(ParamStr(0)), '..\..') + '\customers.json';
lDS.LoadFromFile(lFName);
ViewDataset['customers'] := lDS;
ViewData['customers2'] := lDS;
LoadView(['dataset_list']);
RenderResponseStream;
finally
lDS.Free;
end;
end;

{ TTestPrivateServerController }

procedure TTestPrivateServerController.OnlyRole1;
Expand Down
4 changes: 4 additions & 0 deletions unittests/general/TestServer/WebModuleUnit.dfm
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,8 @@ object MainWebModule: TMainWebModule
Actions = <>
Height = 230
Width = 415
object FDStanStorageJSONLink1: TFDStanStorageJSONLink
Left = 192
Top = 96
end
end
8 changes: 7 additions & 1 deletion unittests/general/TestServer/WebModuleUnit.pas
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,14 @@ interface
MVCFramework
{$IFDEF MSWINDOWS}
,
MVCFramework.Serializer.JsonDataObjects.OptionalCustomTypes
MVCFramework.Serializer.JsonDataObjects.OptionalCustomTypes,
FireDAC.Stan.StorageJSON
{$ENDIF}
;

type
TMainWebModule = class(TWebModule)
FDStanStorageJSONLink1: TFDStanStorageJSONLink;
procedure WebModuleCreate(Sender: TObject);
private
MVCEngine: TMVCEngine;
Expand All @@ -62,6 +64,7 @@ implementation
TestServerControllerPrivateU,
AuthHandlersU,
TestServerControllerJSONRPCU,
MVCFramework.View.Renderers.Mustache,
MVCFramework.Middleware.Compression;

procedure TMainWebModule.WebModuleCreate(Sender: TObject);
Expand All @@ -73,6 +76,8 @@ procedure TMainWebModule.WebModuleCreate(Sender: TObject);
Config[TMVCConfigKey.SessionTimeout] := '0'; // setting cookie
Config[TMVCConfigKey.PathPrefix] := '';
Config[TMVCConfigKey.DocumentRoot] := '..\..\www';
Config[TMVCConfigKey.ViewPath] := '..\..\templates';
Config[TMVCConfigKey.DefaultViewFileExtension] := 'html';
end, nil);
MVCEngine.AddController(TTestServerController)
.AddController(TTestPrivateServerController)
Expand All @@ -96,6 +101,7 @@ procedure TMainWebModule.WebModuleCreate(Sender: TObject);
.AddMiddleware(TMVCBasicAuthenticationMiddleware.Create(TBasicAuthHandler.Create))
.AddMiddleware(TMVCCustomAuthenticationMiddleware.Create(TCustomAuthHandler.Create, '/system/users/logged'))
.AddMiddleware(TMVCCompressionMiddleware.Create);
MVCEngine.SetViewEngine(TMVCMustacheViewEngine);
{$IFDEF MSWINDOWS}
RegisterOptionalCustomTypesSerializers(MVCEngine.Serializers[TMVCMediaType.APPLICATION_JSON]);
{$ENDIF}
Expand Down
1 change: 1 addition & 0 deletions unittests/general/TestServer/customers.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"FDBS":{"Version":15,"Manager":{"UpdatesRegistry":true,"TableList":[{"class":"Table","Name":"FDMemTable1","SourceName":"Table","TabID":0,"EnforceConstraints":false,"MinimumCapacity":50,"CheckNotNull":false,"ColumnList":[{"class":"Column","Name":"CUST_NO","SourceName":"CUST_NO","SourceID":1,"DataType":"Int32","Searchable":true,"Base":true,"OInUpdate":true,"OInWhere":true,"OInKey":true,"OriginColName":"CUST_NO"},{"class":"Column","Name":"CUSTOMER","SourceName":"CUSTOMER","SourceID":2,"DataType":"AnsiString","Size":25,"Searchable":true,"Base":true,"OInUpdate":true,"OInWhere":true,"OriginColName":"CUSTOMER","SourceSize":25},{"class":"Column","Name":"CONTACT_FIRST","SourceName":"CONTACT_FIRST","SourceID":3,"DataType":"AnsiString","Size":15,"Searchable":true,"AllowNull":true,"Base":true,"OAllowNull":true,"OInUpdate":true,"OInWhere":true,"OriginColName":"CONTACT_FIRST","SourceSize":15},{"class":"Column","Name":"CONTACT_LAST","SourceName":"CONTACT_LAST","SourceID":4,"DataType":"AnsiString","Size":20,"Searchable":true,"AllowNull":true,"Base":true,"OAllowNull":true,"OInUpdate":true,"OInWhere":true,"OriginColName":"CONTACT_LAST","SourceSize":20},{"class":"Column","Name":"PHONE_NO","SourceName":"PHONE_NO","SourceID":5,"DataType":"AnsiString","Size":20,"Searchable":true,"AllowNull":true,"Base":true,"OAllowNull":true,"OInUpdate":true,"OInWhere":true,"OriginColName":"PHONE_NO","SourceSize":20},{"class":"Column","Name":"ADDRESS_LINE1","SourceName":"ADDRESS_LINE1","SourceID":6,"DataType":"AnsiString","Size":30,"Searchable":true,"AllowNull":true,"Base":true,"OAllowNull":true,"OInUpdate":true,"OInWhere":true,"OriginColName":"ADDRESS_LINE1","SourceSize":30},{"class":"Column","Name":"ADDRESS_LINE2","SourceName":"ADDRESS_LINE2","SourceID":7,"DataType":"AnsiString","Size":30,"Searchable":true,"AllowNull":true,"Base":true,"OAllowNull":true,"OInUpdate":true,"OInWhere":true,"OriginColName":"ADDRESS_LINE2","SourceSize":30},{"class":"Column","Name":"CITY","SourceName":"CITY","SourceID":8,"DataType":"AnsiString","Size":25,"Searchable":true,"AllowNull":true,"Base":true,"OAllowNull":true,"OInUpdate":true,"OInWhere":true,"OriginColName":"CITY","SourceSize":25},{"class":"Column","Name":"STATE_PROVINCE","SourceName":"STATE_PROVINCE","SourceID":9,"DataType":"AnsiString","Size":15,"Searchable":true,"AllowNull":true,"Base":true,"OAllowNull":true,"OInUpdate":true,"OInWhere":true,"OriginColName":"STATE_PROVINCE","SourceSize":15},{"class":"Column","Name":"COUNTRY","SourceName":"COUNTRY","SourceID":10,"DataType":"AnsiString","Size":15,"Searchable":true,"AllowNull":true,"Base":true,"OAllowNull":true,"OInUpdate":true,"OInWhere":true,"OriginColName":"COUNTRY","SourceSize":15},{"class":"Column","Name":"POSTAL_CODE","SourceName":"POSTAL_CODE","SourceID":11,"DataType":"AnsiString","Size":12,"Searchable":true,"AllowNull":true,"Base":true,"OAllowNull":true,"OInUpdate":true,"OInWhere":true,"OriginColName":"POSTAL_CODE","SourceSize":12},{"class":"Column","Name":"ON_HOLD","SourceName":"ON_HOLD","SourceID":12,"DataType":"AnsiString","Size":1,"Searchable":true,"AllowNull":true,"FixedLen":true,"Base":true,"OAllowNull":true,"OInUpdate":true,"OInWhere":true,"OriginColName":"ON_HOLD","SourceSize":1}],"ConstraintList":[],"ViewList":[],"RowList":[{"RowID":0,"Original":{"CUST_NO":1001,"CUSTOMER":"Signature Design","CONTACT_FIRST":"Dale J.","CONTACT_LAST":"Little","PHONE_NO":"(619) 530-2710","ADDRESS_LINE1":"15500 Pacific Heights Blvd.","CITY":"San Diego","STATE_PROVINCE":"CA","COUNTRY":"USA","POSTAL_CODE":"92121"}},{"RowID":1,"Original":{"CUST_NO":1002,"CUSTOMER":"Dallas Technologies","CONTACT_FIRST":"Glen","CONTACT_LAST":"Brown","PHONE_NO":"(214) 960-2233","ADDRESS_LINE1":"P. O. Box 47000","CITY":"Dallas","STATE_PROVINCE":"TX","COUNTRY":"USA","POSTAL_CODE":"75205","ON_HOLD":"*"}},{"RowID":2,"Original":{"CUST_NO":1003,"CUSTOMER":"Buttle, Griffith and Co.","CONTACT_FIRST":"James","CONTACT_LAST":"Buttle","PHONE_NO":"(617) 488-1864","ADDRESS_LINE1":"2300 Newbury Street","ADDRESS_LINE2":"Suite 101","CITY":"Boston","STATE_PROVINCE":"MA","COUNTRY":"USA","POSTAL_CODE":"02115"}},{"RowID":3,"Original":{"CUST_NO":1004,"CUSTOMER":"Central Bank","CONTACT_FIRST":"Elizabeth","CONTACT_LAST":"Brocket","PHONE_NO":"61 211 99 88","ADDRESS_LINE1":"66 Lloyd Street","CITY":"Manchester","COUNTRY":"England","POSTAL_CODE":"M2 3LA"}},{"RowID":4,"Original":{"CUST_NO":1005,"CUSTOMER":"DT Systems, LTD.","CONTACT_FIRST":"Tai","CONTACT_LAST":"Wu","PHONE_NO":"(852) 850 43 98","ADDRESS_LINE1":"400 Connaught Road","CITY":"Central Hong Kong","COUNTRY":"Hong Kong"}},{"RowID":5,"Original":{"CUST_NO":1006,"CUSTOMER":"DataServe International","CONTACT_FIRST":"Tomas","CONTACT_LAST":"Bright","PHONE_NO":"(613) 229 3323","ADDRESS_LINE1":"2000 Carling Avenue","ADDRESS_LINE2":"Suite 150","CITY":"Ottawa","STATE_PROVINCE":"ON","COUNTRY":"Canada","POSTAL_CODE":"K1V 9G1"}},{"RowID":6,"Original":{"CUST_NO":1007,"CUSTOMER":"Mrs. Beauvais","CONTACT_LAST":"Mrs. Beauvais","ADDRESS_LINE1":"P.O. Box 22743","CITY":"Pebble Beach","STATE_PROVINCE":"CA","COUNTRY":"USA","POSTAL_CODE":"93953"}},{"RowID":7,"Original":{"CUST_NO":1008,"CUSTOMER":"Anini Vacation Rentals","CONTACT_FIRST":"Leilani","CONTACT_LAST":"Briggs","PHONE_NO":"(808) 835-7605","ADDRESS_LINE1":"3320 Lawai Road","CITY":"Lihue","STATE_PROVINCE":"HI","COUNTRY":"USA","POSTAL_CODE":"96766"}},{"RowID":8,"Original":{"CUST_NO":1009,"CUSTOMER":"Max","CONTACT_FIRST":"Max","PHONE_NO":"22 01 23","ADDRESS_LINE1":"1 Emerald Cove","CITY":"Turtle Island","COUNTRY":"Fiji","ON_HOLD":"*"}},{"RowID":9,"Original":{"CUST_NO":1010,"CUSTOMER":"MPM Corporation","CONTACT_FIRST":"Miwako","CONTACT_LAST":"Miyamoto","PHONE_NO":"3 880 77 19","ADDRESS_LINE1":"2-64-7 Sasazuka","CITY":"Tokyo","COUNTRY":"Japan","POSTAL_CODE":"150"}},{"RowID":10,"Original":{"CUST_NO":1011,"CUSTOMER":"Dynamic Intelligence Corp","CONTACT_FIRST":"Victor","CONTACT_LAST":"Granges","PHONE_NO":"01 221 16 50","ADDRESS_LINE1":"Florhofgasse 10","CITY":"Zurich","COUNTRY":"Switzerland","POSTAL_CODE":"8005"}},{"RowID":11,"Original":{"CUST_NO":1012,"CUSTOMER":"3D-Pad Corp.","CONTACT_FIRST":"Michelle","CONTACT_LAST":"Roche","PHONE_NO":"1 43 60 61","ADDRESS_LINE1":"22 Place de la Concorde","CITY":"Paris","COUNTRY":"France","POSTAL_CODE":"75008"}},{"RowID":12,"Original":{"CUST_NO":1013,"CUSTOMER":"Lorenzi Export, Ltd.","CONTACT_FIRST":"Andreas","CONTACT_LAST":"Lorenzi","PHONE_NO":"02 404 6284","ADDRESS_LINE1":"Via Eugenia, 15","CITY":"Milan","COUNTRY":"Italy","POSTAL_CODE":"20124"}},{"RowID":13,"Original":{"CUST_NO":1014,"CUSTOMER":"Dyno Consulting","CONTACT_FIRST":"Greta","CONTACT_LAST":"Hessels","PHONE_NO":"02 500 5940","ADDRESS_LINE1":"Rue Royale 350","CITY":"Brussels","COUNTRY":"Belgium","POSTAL_CODE":"1210"}},{"RowID":14,"Original":{"CUST_NO":1015,"CUSTOMER":"GeoTech Inc.","CONTACT_FIRST":"K.M.","CONTACT_LAST":"Neppelenbroek","PHONE_NO":"(070) 44 91 18","ADDRESS_LINE1":"P.0.Box 702","CITY":"Den Haag","COUNTRY":"Netherlands","POSTAL_CODE":"2514"}}]}],"RelationList":[],"UpdatesJournal":{"SavePoint":15,"Changes":[]}}}}
8 changes: 8 additions & 0 deletions unittests/general/TestServer/templates/dataset_list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{{#customers}}
{{CUST_NO}}|{{CUSTOMER}}|{{CONTACT_FIRST}}|{{CONTACT_LAST}}|{{PHONE_NO}}|{{ADDRESS_LINE1}}|{{CITY}}|{{COUNTRY}}|{{POSTAL_CODE}}
{{/customers}}
---
{{#customers2}}
{{CUST_NO}}|{{CUSTOMER}}|{{CONTACT_FIRST}}|{{CONTACT_LAST}}|{{PHONE_NO}}|{{ADDRESS_LINE1}}|{{CITY}}|{{COUNTRY}}|{{POSTAL_CODE}}
{{/customers2}}

0 comments on commit 26b8208

Please sign in to comment.