Skip to content

Commit

Permalink
allow for different authors in the URL, closes #316 (#333)
Browse files Browse the repository at this point in the history
* fix breadcrumbs and URL rewritings for multiple authors #316

* fix breadcrumb for authors without key #316

* fix csLink for multiple authors/senders #316

* improve jsonld output for multiple authors #316

and the landing page

* update expected results

* keep author/sender context for links #316

in the context box (of letter single view) and in the correspondence/leter list view

* fix breadcrumb

* small fix

* check explicitly for sequences

* update expected results

* only output context when there's more than a senderID

* update expected results
  • Loading branch information
peterstadler authored and jakosch committed Nov 28, 2019
1 parent 5e17944 commit 47b3008
Show file tree
Hide file tree
Showing 203 changed files with 5,171 additions and 4,698 deletions.
78 changes: 54 additions & 24 deletions modules/app.xqm
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,32 @@ import module namespace wega-util-shared="http://xquery.weber-gesamtausgabe.de/m
: @return xs:string
:)
declare function app:createUrlForDoc($doc as document-node()?, $lang as xs:string) as xs:string? {
let $path := controller:path-to-resource($doc, $lang)
let $path := controller:path-to-resource($doc, $lang)[1]
return
if($doc and $path) then core:link-to-current-app($path || '.html')
else ()
};

(:~
: Creates link to doc
: This 3-arity function version will honour the current (author) context by returning
: a link depending on the author ID. If the provided context does not match the requested
: document, the canonical link will be returned.
:
: @author Peter Stadler
: @param $doc document node
: @param $lang the current language (de|en)
: @param $context the current (author) context, e.g. 'A002068'
: @return xs:string
:)
declare function app:createUrlForDocInContext($doc as document-node()?, $lang as xs:string, $contextID as xs:string) as xs:string? {
let $path := controller:path-to-resource($doc, $lang)
return
if($doc and count($path[contains(., $contextID)]) = 1) then core:link-to-current-app($path[contains(., $contextID)] || '.html')
else if($doc and count($path) gt 0) then core:link-to-current-app($path[1] || '.html')
else ()
};

(:~
: Creates an xhtml:a link to a WeGA document
:
Expand Down Expand Up @@ -182,15 +202,14 @@ declare function app:set-line-wrap($node as node(), $model as map(*)) as element
declare
%templates:default("lang", "en")
function app:breadcrumb-person($node as node(), $model as map(*), $lang as xs:string) as element(a) {
let $authorElem := query:get-author-element($model?doc)[1]
let $authorID :=
if(config:is-person($model('docID'))) then $model('docID')
else if($model?docType='diaries') then 'A002068'
else $authorElem/(@key, @dbkey)
let $authorID := tokenize($model?('exist:path'), '/')[3]
let $anonymusID := config:get-option('anonymusID')
let $authorElem :=
if ($authorID = $anonymusID) then query:get-author-element($model?doc)[(count(@key | @dbkey) = 0) or ((@key, @dbkey) = $anonymusID)]
else query:get-author-element($model?doc)[(@key, @dbkey) = $authorID]
let $href :=
if ($authorID = config:get-option('anonymusID')) then ()
else if($authorID) then app:createUrlForDoc(core:doc($authorID), $lang)
else ()
if ($authorID = $anonymusID) then ()
else app:createUrlForDoc(core:doc($authorID), $lang)
let $elem :=
if($href) then QName('http://www.w3.org/1999/xhtml', 'a')
else QName('http://www.w3.org/1999/xhtml', 'span')
Expand All @@ -206,11 +225,10 @@ declare
declare
%templates:default("lang", "en")
function app:breadcrumb-docType($node as node(), $model as map(*), $lang as xs:string) as element(a) {
let $authorID := query:get-authorID($model('doc'))
let $href := core:link-to-current-app(functx:substring-before-last(controller:path-to-resource($model('doc'), $lang), '/'))
let $display-name := replace(functx:substring-after-last($href, '/'), '_', ' ')
let $href := core:link-to-current-app(functx:substring-before-last($model('$exist:path'), '/'))
let $display-name := replace(xmldb:decode(functx:substring-after-last($href, '/')), '_', ' ')
let $elem :=
if($href and not($authorID = config:get-option('anonymusID'))) then QName('http://www.w3.org/1999/xhtml', 'a')
if($href and not(contains($href, config:get-option('anonymusID')))) then QName('http://www.w3.org/1999/xhtml', 'a')
else QName('http://www.w3.org/1999/xhtml', 'span')
return
element {$elem} {
Expand Down Expand Up @@ -252,7 +270,7 @@ declare
declare
%templates:default("lang", "en")
function app:breadcrumb-var($node as node(), $model as map(*), $lang as xs:string) as element() {
let $pathTokens := tokenize(request:get-attribute('$exist:path'), '/')
let $pathTokens := tokenize($model?('$exist:path'), '/')
return
element {node-name($node)} {
$node/@*,
Expand Down Expand Up @@ -327,7 +345,7 @@ declare
case 'gnd-beacon' return if($model('gnd')) then 'beacon.html' else ()
default return ()
let $ajax-url :=
if(config:get-doctype-by-id($model('docID')) and $ajax-resource) then core:link-to-current-app(controller:path-to-resource($model('doc'), $lang) || '/' || $ajax-resource)
if(config:get-doctype-by-id($model('docID')) and $ajax-resource) then core:link-to-current-app(controller:path-to-resource($model('doc'), $lang)[1] || '/' || $ajax-resource)
else if(gl:spec($model?specID, $model?schemaID) and $ajax-resource) then core:link-to-current-app(replace($model('exist:path'), '\.[xhtml]+$', '') || '/' || $ajax-resource)
else ()
return
Expand Down Expand Up @@ -1508,18 +1526,25 @@ declare
};


(:~
: Add context information to the current model map
: NB: If no context information is found, an empty sequence will be returned
: effectively removing the HTML subtree under $node from the output.
:)
declare
%templates:wrap
function app:context($node as node(), $model as map(*)) as map(*)? {
let $senderID := tokenize($model?('exist:path'), '/')[3]
let $context :=
switch($model?docType)
case 'letters' return map:merge((
query:context-relatedItems($model?doc),
query:correspContext($model?doc)
query:correspContext($model?doc, $senderID)
))
default return query:context-relatedItems($model?doc)
return
if(wega-util-shared:has-content($context)) then $context
if(wega-util-shared:has-content($context))
then map:merge(($context, map:entry('senderID', $senderID)))
else ()
};

Expand All @@ -1535,7 +1560,10 @@ declare
default return core:logToFile('error', 'app:print-letter-context(): wrong value for parameter "fromTo": "' || $model('letter-norm-entry')('fromTo') || '"')
let $normDate := query:get-normalized-date($letter)
return (
app:createDocLink($letter, $normDate, $lang, ()),
element a {
attribute href {app:createUrlForDocInContext($letter, $lang, $model?senderID)},
$normDate
},
": ",
lower-case(lang:get-language-string($model('letter-norm-entry')('fromTo'), $lang)),
" ",
Expand Down Expand Up @@ -1567,7 +1595,7 @@ declare
%templates:default("lang", "en")
function app:csLink($node as node(), $model as map(*), $lang as xs:string) as element(div) {
let $doc := $model('doc')
let $correspondent-1-key := query:get-authorID($doc)
let $correspondent-1-key := tokenize($model?('exist:path'), '/')[3]
let $correspondent-1-gnd := query:get-gnd($correspondent-1-key)
let $correspondent-2-key := ($doc//tei:correspAction[@type = 'received']//@key[parent::tei:persName or parent::name or parent::tei:orgName])[1]
let $correspondent-2-gnd := query:get-gnd($correspondent-2-key)
Expand Down Expand Up @@ -1610,15 +1638,15 @@ declare
: @return element html:p
:)
declare %private function app:get-news-foot($doc as document-node(), $lang as xs:string) as element(p)? {
let $authorID := query:get-authorID($doc)
let $authorElem := query:get-author-element($doc)
let $dateFormat :=
if ($lang = 'de') then '[FNn], [D]. [MNn] [Y]'
else '[FNn], [MNn] [D], [Y]'
return
if($authorID) then
if(count($authorElem) gt 0) then
element p {
attribute class {'authorDate'},
app:printCorrespondentName(query:get-author-element($doc), $lang, 'fs'),
app:printCorrespondentName($authorElem, $lang, 'fs'),
concat(', ', date:format-date(xs:date($doc//tei:publicationStmt/tei:date/xs:dateTime(@when)), $dateFormat, $lang))
}
else()
Expand Down Expand Up @@ -1705,7 +1733,9 @@ declare
map {
'doc' : $model('result-page-entry'),
'docID' : $model('result-page-entry')/root()/*/data(@xml:id),
'docURL' : app:createUrlForDoc($model('result-page-entry'), $lang),
'docURL' :
if(config:is-person($model?parent-docID)) then app:createUrlForDocInContext($model?result-page-entry, $lang, $model?parent-docID)
else app:createUrlForDoc($model('result-page-entry'), $lang),
'docType' : config:get-doctype-by-id($model('result-page-entry')/root()/*/data(@xml:id)),
'relators' : query:relators($model('result-page-entry')),
'biblioType' : $model('result-page-entry')/tei:biblStruct/data(@type),
Expand All @@ -1730,7 +1760,7 @@ declare
return
element {name($node)} {
$node/@*[not(name(.) = 'href')],
if($node[self::xhtml:a]) then attribute href {app:createUrlForDoc($model('doc'), $lang) || (if(map:contains($model, 'query-string-org')) then ('?q=' || $model?query-string-org) else ())}
if($node[self::xhtml:a]) then attribute href {$model?docURL || (if(map:contains($model, 'query-string-org')) then ('?q=' || $model?query-string-org) else ())}
else (),
if($title instance of xs:string or $title instance of text() or count($title) gt 1) then $title
else $title/node()
Expand Down
16 changes: 9 additions & 7 deletions modules/controller.xqm
Original file line number Diff line number Diff line change
Expand Up @@ -200,12 +200,12 @@ declare function controller:dispatch($exist-vars as map(*)) as element(exist:dis
map:entry('media-type', $media-type)
))
let $doc := core:doc($docID)
let $path := controller:encode-path-segments-for-uri(controller:path-to-resource($doc, $exist-vars('lang')))
let $path := controller:path-to-resource($doc, $exist-vars('lang')) ! controller:encode-path-segments-for-uri(.)
(: let $log := util:log-system-out($exist-vars('exist:path')):)
(: let $log := util:log-system-out($path):)
return
if($media-type and $exist-vars('exist:path') eq $path || '.' || $media-type) then controller:forward-document($updated-exist-vars)
else if($media-type and $path) then controller:redirect-absolute('/' || $path || '.' || $media-type)
if($media-type and $exist-vars('exist:path') = ($path ! (. || '.' || $media-type))) then controller:forward-document($updated-exist-vars)
else if($media-type and count($path) gt 0) then controller:redirect-absolute('/' || $path[1] || '.' || $media-type)
(: last else case: document does not exist :)
else controller:error(map:put($updated-exist-vars, 'error-message', 'resource not found'), 404)
};
Expand Down Expand Up @@ -421,8 +421,10 @@ declare function controller:encode-path-segments-for-uri($uri-string as xs:strin
: Warning:
: * No URL encoding here, see controller:encode-path-segments-for-uri()
: * resulting paths do not include exist:prefix, see core:link-to-current-app()
:
: @return a sequence of valid (external) paths for a document, based on the authors and docType
~:)
declare function controller:path-to-resource($doc as document-node()?, $lang as xs:string) as xs:string? {
declare function controller:path-to-resource($doc as document-node()?, $lang as xs:string) as xs:string* {
let $docID := $doc/*/@xml:id
let $docType := config:get-doctype-by-id($docID) (: Die originale Darstellung der doctypes, also 'persons', 'letters' etc:)
let $displayName := (: Die Darstellung als URL, also 'Korrespondenz', 'Tagebücher' etc. :)
Expand All @@ -442,7 +444,7 @@ declare function controller:path-to-resource($doc as document-node()?, $lang as
if($docType = ('persons', 'orgs', 'places')) then str:join-path-elements(('/', $lang, $docID))
else if($docType = 'var') then str:join-path-elements(('/', $lang, lang:get-language-string('project', $lang), $docID))
else if($docType = 'addenda') then str:join-path-elements(('/', $lang, lang:get-language-string('project', $lang), lang:get-language-string('volContents', $lang), $docID))
else if($authorID and $displayName) then str:join-path-elements(('/', $lang, $authorID, $displayName, $docID))
else if(count($authorID) gt 0 and $displayName) then $authorID ! str:join-path-elements(('/', $lang, ., $displayName, $docID))
else core:logToFile('error', 'controller:path-to-resource(): could not create path for ' || $docID)
};

Expand All @@ -463,7 +465,7 @@ declare function controller:docType-url-for-author($author as document-node(), $
case 'letters' return 'correspondence'
default return $docType
return
core:link-to-current-app(str:join-path-elements((controller:path-to-resource($author, $lang), $docType-path-segment || '.html')))
core:link-to-current-app(str:join-path-elements((controller:path-to-resource($author, $lang)[1], $docType-path-segment || '.html')))
};

(:
Expand Down Expand Up @@ -518,7 +520,7 @@ declare function controller:redirect-by-gnd($exist-vars as map(*)) as element(ex
let $doc := query:doc-by-gnd(controller:basename($exist-vars('exist:resource')))[last()]
let $media-type := controller:media-type($exist-vars)
return
if(exists($doc) and $media-type) then controller:redirect-absolute(controller:path-to-resource($doc, $exist-vars('lang')) || '.' || $media-type)
if(exists($doc) and $media-type) then controller:redirect-absolute(controller:path-to-resource($doc, $exist-vars('lang'))[1] || '.' || $media-type)
else controller:error($exist-vars, 404)
};

Expand Down
36 changes: 25 additions & 11 deletions modules/lod.xqm
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ declare function lod:jsonld($model as map(*), $lang as xs:string) as map(*) {
let $schema.org-type := lod:schema.org-type($model)
let $identifier := lod:DC.identifier($model)
let $url :=
if($model?doc) then core:permalink(controller:path-to-resource($model?doc, $lang))
(: multiple URLs are generated when the document features multiple authors :)
if($model?doc) then controller:path-to-resource($model?doc, $lang) ! core:permalink(.)
else $identifier
let $jsonld-common := map {
'@id': $identifier,
Expand All @@ -97,14 +98,24 @@ declare function lod:jsonld($model as map(*), $lang as xs:string) as map(*) {
(:array {
distinct-values(($model?doc//tei:text//tei:*[@key] | $model?doc/tei:ab//tei:*[@key])/@key) ! lod:jsonld-entity(<tei:rs key="{.}"/>, $lang)
}:)
let $image :=
if($model?docID = 'home') then core:permalink('resources/img/logo_weber.png')
let $homepageSpecials :=
if($model?docID = 'home') then map {
'image': core:permalink('resources/img/logo_weber.png'),
'logo': core:permalink('resources/favicons/mstile-150x150.png'),
"potentialAction": array {
map {
"@type": "SearchAction",
"target": core:permalink('de/Suche?q={search_term_string}'),
"query-input": "required name=search_term_string"
}
}
}
else ()
return
map:merge((
$jsonld-common, (: always included :)

if($image) then map { 'image': $image } else (), (: include image if available :)
$homepageSpecials, (: specials for the landing page :)

if($schema.org-type = ('CreativeWork', 'Article', 'NewsArticle')) then map:merge((
$jsonld-common,
Expand All @@ -126,13 +137,16 @@ declare function lod:jsonld($model as map(*), $lang as xs:string) as map(*) {
: Helper function for setting a schema.org type
:)
declare %private function lod:schema.org-type($model as map(*)) as xs:string {
switch(config:get-doctype-by-id($model?docID))
case 'news' return 'NewsArticle'
case 'persons' return 'Person'
case 'orgs' return 'Organization'
case 'places' return 'Place'
case 'addenda' case 'thematicCommentary' return 'Article'
default return 'CreativeWork'
if($model?docID = 'home')
then 'WebSite'
else
switch(config:get-doctype-by-id($model?docID))
case 'news' return 'NewsArticle'
case 'persons' return 'Person'
case 'orgs' return 'Organization'
case 'places' return 'Place'
case 'addenda' case 'thematicCommentary' return 'Article'
default return 'CreativeWork'
};

(:~
Expand Down
20 changes: 14 additions & 6 deletions modules/query.xqm
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@ declare function query:title($key as xs:string) as xs:string {
: @param $item the id of the TEI document (or the document node itself) to grab the author from
: @return xs:string the WeGA ID
:)
declare function query:get-authorID($doc as document-node()?) as xs:string {
let $author-element := query:get-author-element($doc)[1]
declare function query:get-authorID($doc as document-node()?) as xs:string* {
let $author-element := query:get-author-element($doc)
let $id := $author-element/@key | $author-element/@dbkey
return
if(exists($doc) and $id) then string($id)
if(exists($doc) and count($id) gt 0) then $id ! string(.)
else if(exists($doc)) then config:get-option('anonymusID')
else ''
else ()
};

(:~
Expand Down Expand Up @@ -368,10 +368,18 @@ declare function query:contributors($doc as document-node()?) as xs:string* {

(:~
: Query the letter context, i.e. preceding and following letters
:
: @param $doc the TEI document with correspondence information provided in tei:correspDesc
: @param $senderID optional sender ID for co-authorship letters. If none is provided, the first sender in $doc will be taken.
: @return a map object with objects representing 'context-letter-absolute-prev', 'context-letter-absolute-next',
: 'context-letter-korrespondenzstelle-prev', and 'context-letter-korrespondenzstelle-next', e.g. { 'context-letter-absolute-prev': { 'fromTo': 'to', 'doc': document-node() } }
~:)
declare function query:correspContext($doc as document-node()) as map(*)? {
declare function query:correspContext($doc as document-node(), $senderID as xs:string?) as map(*)? {
let $docID := $doc/tei:TEI/data(@xml:id)
let $authorID := $doc//tei:fileDesc/tei:titleStmt/tei:author[1]/@key (:$doc//tei:sender/tei:persName[1]/@key:)
let $authorID :=
if($doc//tei:correspAction[@type='sent']/tei:*[self::tei:persName or self::tei:orgName or self::tei:name][@key=$senderID])
then $senderID
else ($doc//tei:correspAction[@type='sent']/tei:*[self::tei:persName or self::tei:orgName or self::tei:name])[1]/@key
let $addresseeID := ($doc//tei:correspAction[@type='received']/tei:*[self::tei:persName or self::tei:orgName or self::tei:name])[1]/@key
let $authorColl :=
if($authorID) then core:getOrCreateColl('letters', $authorID, true())
Expand Down
Loading

0 comments on commit 47b3008

Please sign in to comment.