1212use Psr \Http \Message \ServerRequestInterface as Request ;
1313use Throwable ;
1414use WebSocket \Client ;
15+ use pietercolpaert \hardf \TriGWriter ;
16+ use pietercolpaert \hardf \TriGParser ;
1517
1618class Server
1719{
@@ -195,7 +197,7 @@ private function handle(string $method, string $path, $contents, $request): Resp
195197 break ;
196198 case "text/n3 " :
197199 $ response = $ this ->handleN3Update ($ response , $ path , $ contents );
198- break ;
200+ break ;
199201 default :
200202 $ response ->getBody ()->write (self ::ERROR_UNHANDLED_PATCH_CONTENT_TYPE );
201203 $ response = $ response ->withStatus (400 );
@@ -361,12 +363,86 @@ private function handleSparqlUpdate(Response $response, string $path, $contents)
361363 return $ response ;
362364 }
363365
366+ private function normalizeN3 ($ contents ) {
367+ $ parser = new TriGParser (["format " => "n3 " ]);
368+ $ triples = $ parser ->parse ($ contents );
369+ $ parsedGraph = [];
370+ foreach ($ triples as $ key => $ value ) {
371+ $ graph = $ value ['graph ' ];
372+ $ subject = $ value ['subject ' ];
373+ $ predicate = $ value ['predicate ' ];
374+ $ object = $ value ['object ' ];
375+
376+ if ($ graph == '' ) {
377+ $ graph = ':root ' ;
378+ }
379+ if ($ graph != ':root ' ) {
380+ $ value ['graph ' ] = '' ;
381+ $ parsedGraph [$ graph ] = $ value ;
382+ } else {
383+ if (!isset ($ parsedGraph [$ graph ])) {
384+ $ parsedGraph [$ graph ] = [];
385+ }
386+ if (!isset ($ parsedGraph [$ graph ][$ subject ])) {
387+ $ parsedGraph [$ graph ][$ subject ] = [];
388+ }
389+ if (!isset ($ parsedGraph [$ graph ][$ subject ][$ predicate ])) {
390+ $ parsedGraph [$ graph ][$ subject ][$ predicate ] = [];
391+ }
392+ $ parsedGraph [$ graph ][$ subject ][$ predicate ][] = $ object ;
393+ }
394+ }
395+ return $ parsedGraph ;
396+ }
397+
398+ private function n3Convert ($ contents ) {
399+ $ parsedGraph = $ this ->normalizeN3 ($ contents );
400+ $ inserts = [];
401+ foreach ($ parsedGraph [':root ' ] as $ subject ) {
402+ if (
403+ isset ($ subject ['http://www.w3.org/1999/02/22-rdf-syntax-ns#type ' ]) &&
404+ (in_array ('http://www.w3.org/ns/solid/terms#InsertDeletePatch ' , $ subject ['http://www.w3.org/1999/02/22-rdf-syntax-ns#type ' ])) &&
405+ isset ($ subject ['http://www.w3.org/ns/solid/terms#inserts ' ])
406+ ) {
407+ foreach ($ subject ['http://www.w3.org/ns/solid/terms#inserts ' ] as $ target ) {
408+ $ inserts [] = $ parsedGraph [$ target ];
409+ }
410+ }
411+ }
412+
413+ $ deletes = [];
414+ foreach ($ parsedGraph [':root ' ] as $ subject ) {
415+ if (
416+ isset ($ subject ['http://www.w3.org/1999/02/22-rdf-syntax-ns#type ' ]) &&
417+ (in_array ('http://www.w3.org/ns/solid/terms#InsertDeletePatch ' , $ subject ['http://www.w3.org/1999/02/22-rdf-syntax-ns#type ' ])) &&
418+ isset ($ subject ['http://www.w3.org/ns/solid/terms#deletes ' ])
419+ ) {
420+ foreach ($ subject ['http://www.w3.org/ns/solid/terms#deletes ' ] as $ target ) {
421+ $ deletes [] = $ parsedGraph [$ target ];
422+ }
423+ }
424+ }
425+
426+ $ writer = new TriGWriter (["format " => "turtle " ]);
427+ $ writer ->addTriples ($ inserts );
428+ $ insertTurtle = $ writer ->end ();
429+
430+ $ writer = new TriGWriter (["format " => "turtle " ]);
431+ $ writer ->addTriples ($ deletes );
432+ $ deleteTurtle = $ writer ->end ();
433+
434+ return array (
435+ "insert " => $ insertTurtle ?? "" ,
436+ "delete " => $ deleteTurtle ?? ""
437+ );
438+ }
439+
364440 private function handleN3Update (Response $ response , string $ path , $ contents ): Response
365441 {
366442 $ filesystem = $ this ->filesystem ;
367443 $ graph = $ this ->getGraph ();
368444 $ n3Graph = $ this ->getGraph ();
369-
445+
370446 if ($ filesystem ->has ($ path ) === false ) {
371447 $ data = '' ;
372448 } else {
@@ -380,39 +456,33 @@ private function handleN3Update(Response $response, string $path, $contents): Re
380456 $ graph ->parse ($ data , "turtle " );
381457 // FIXME: Adding this base will allow us to parse <> entries; , $this->baseUrl . $this->basePath . $path), but that breaks the build.
382458 // FIXME: Use enums from namespace Pdsinterop\Rdf\Enum\Format instead of 'turtle'?
459+ $ instructions = $ this ->n3Convert ($ contents );
383460
384- $ n3Graph ->parse ($ contents , "ntriples " );
385- $ matching = $ n3Graph ->resourcesMatching ('http://www.w3.org/ns/solid/terms#InsertDeletePatch ' );
386- foreach ($ matching as $ match ) {
387- $ inserts = $ match ->all ('<http://www.w3.org/ns/solid/terms#inserts> ' );
388- $ deletes = $ match ->all ('<http://www.w3.org/ns/solid/terms#deletes> ' );
389- // FIXME: do we need to so patches as well?
390- // $patches = $match->all('<http://www.w3.org/ns/solid/terms#patches>');
391-
392- foreach ($ inserts as $ triples ) {
393- $ graph ->parse ($ triples , "turtle " );
394- }
395- foreach ($ deletes as $ triples ) {
396- $ deleteGraph = $ this ->getGraph ();
397- // @CHECKME: Does the Graph Parse here also need an URI?
398- $ deleteGraph ->parse ($ triples , "ntriples " );
399- $ resources = $ deleteGraph ->resources ();
400- foreach ($ resources as $ resource ) {
401- $ properties = $ resource ->propertyUris ();
402- foreach ($ properties as $ property ) {
403- $ values = $ resource ->all ($ property );
404- if (!count ($ values )) {
405- $ graph ->delete ($ resource , $ property );
406- } else {
407- foreach ($ values as $ value ) {
408- $ count = $ graph ->delete ($ resource , $ property , $ value );
409- if ($ count === 0 ) {
410- throw new Exception ("Could not delete a value " , 500 );
411- }
412- }
413- }
414- }
415- }
461+ // error_log("INSERT");
462+ // error_log($instructions['insert']);
463+ $ graph ->parse ($ instructions ['insert ' ]);
464+
465+ $ deleteGraph = $ this ->getGraph ();
466+ // error_log("DELETE");
467+ // error_log($instructions['delete']);
468+
469+ // @CHECKME: Does the Graph Parse here also need an URI?
470+ $ deleteGraph ->parse ($ instructions ['delete ' ], "turtle " );
471+ $ resources = $ deleteGraph ->resources ();
472+ foreach ($ resources as $ resource ) {
473+ $ properties = $ resource ->propertyUris ();
474+ foreach ($ properties as $ property ) {
475+ $ values = $ resource ->all ($ property );
476+ if (!count ($ values )) {
477+ $ graph ->delete ($ resource , $ property );
478+ } else {
479+ foreach ($ values as $ value ) {
480+ $ count = $ graph ->delete ($ resource , $ property , $ value );
481+ if ($ count === 0 ) {
482+ throw new Exception ("Could not delete a value " , 500 );
483+ }
484+ }
485+ }
416486 }
417487 // FIXME: Is there a 'patches'? What does it look like and how do we handle it?
418488 }
0 commit comments