Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow for different authors in the URL, closes #316 #333

Merged
merged 13 commits into from
Nov 28, 2019
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 @@ -315,7 +333,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 @@ -1496,18 +1514,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 @@ -1523,7 +1548,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 @@ -1555,7 +1583,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 @@ -1598,15 +1626,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 @@ -1693,7 +1721,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 @@ -1718,7 +1748,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 @@ -152,12 +152,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 @@ -381,8 +381,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 @@ -402,7 +404,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 @@ -423,7 +425,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 @@ -478,7 +480,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