Boktips4

Språk

Englishsuomisvenska
Fel uppstod under bearbetning av mallen.
The following has evaluated to null or missing:
==> crdPageUrl  [in template "118468#118507#284013" at line 349, column 46]

----
Tip: If the failing expression is known to be legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
----

----
FTL stack trace ("~" means nesting-related):
	- Failed at: ${crdPageUrl}  [in template "118468#118507#284013" at line 349, column 44]
	- Reached through: #assign crdPageFullUrl = "${crdPageUr...  [in template "118468#118507#284013" at line 349, column 17]
----
1<#-- STAFF PICKS TEMPLATE --> 
2<#--Settings needed for local REST API call --> 
3<#assign portalSiteID = "" /><#-- Portal side id needed to query records --> 
4<#assign agencyID = "" /><#-- Agency ID needed for cover fetching. Can be obtained e.g. from SOLR --> 
5<#assign agencyMemberID = "" /> 
6<#assign agencyName = "" /><#-- Needed for cover fetching --> 
7<#assign portNumber = "16520" /><#-- Needed for all API calls --> 
8<#assign queryLimit = 8 /><#-- Limits how many records are shown at maximum in list view --> 
9<#assign portalUrl = "" /> 
10<#assign portalUrlSecure = "" /><#-- Used for fetching covers and get rid of mixed content warning --> 
11<#assign csAddress = "http://arena-central" /> <#-- used to be arena-central:16517 --> 
12<#assign lsAddress = "http://arena-local:16520" /> 
13<#assign friendlyUrl = "" /> 
14<#assign sitePrefix = "/web/arena" /> 
15 
16<#-- If friendlyUrl is not set, get it from the organization --> 
17<#if friendlyUrl == "" > 
18    <#assign groupLocalService = serviceLocator.findService("com.liferay.portal.kernel.service.GroupLocalService")/> 
19    <#assign group = groupLocalService.getGroup(groupId)/> 
20    <#assign friendlyUrl = group.getFriendlyURL() /> 
21    <#assign sitePrefix = "/web${friendlyUrl}" /> 
22</#if> 
23 
24<#-- Get server and page URLs --> 
25<#assign serviceContext = staticUtil["com.liferay.portal.kernel.service.ServiceContextThreadLocal"].getServiceContext() /> 
26<#assign themeDisplay = serviceContext.getThemeDisplay() /> 
27<#assign portalUrl = themeDisplay.getPortalURL() /> 
28<#assign portalUrlSecure = portalUrl /> 
29<#if portalUrlSecure?index_of("https") == -1> 
30    <#assign portalUrlSecure = portalUrl?replace("http", "https") /> 
31</#if> 
32<#if portalUrl?index_of("https") != -1> 
33    <#assign portalUrl = portalUrl?replace("https", "http") /> 
34</#if> 
35 
36<#assign virtualURL = portalUrlSecure?replace("https://","") /> 
37 
38<#assign fullPageUrl = portalUrl + themeDisplay.getURLCurrent() /> 
39<#assign urlMatcher = themeDisplay.getURLCurrent()?matches("^(/[a-z]{2}(_[A-Z]{2})?)?/web/[^/]+")> 
40<#list urlMatcher as algFriendlyUrl> 
41    <#assign crdPageUrl = portalUrlSecure + algFriendlyUrl + "/results"/> 
42    <#assign searchPageUrl = portalUrlSecure + algFriendlyUrl + "/search"/> 
43</#list> 
44 
45<#-- General variables needed in multiple macros --> 
46<#assign journalArticleResourceService = serviceLocator.findService("com.liferay.journal.service.JournalArticleResourceLocalService") /> 
47<#assign articleResourcePK = journalArticleResourceService.getArticleResourcePrimKey(groupId, .vars['reserved-article-id'].data)?number /> 
48<#assign journalArticleService = serviceLocator.findService("com.liferay.journal.service.JournalArticleLocalService") /> 
49<#assign journalArticle = journalArticleService.getArticle(groupId, .vars['reserved-article-id'].data) /> 
50 
51<#--Makes a query to the REST API and requests records. This function should be used to call the API within this template. 
52Returns the result as a simpleHash object --> 
53<#function queryAPI query limit> 
54    <#assign fullRequestUrl = "${lsAddress}/local-rest/api/v1/portalsites/${portalSiteID}/records?query=${httpUtilUnsafe.encodeURL(query)}&count=${limit}&isShowExtended=false&sortDirection=Descending&sortField=Relevance&agencyMemberId=${agencyMemberID}&decorationNames=Ratings"/> 
55    <#assign response = httpUtilUnsafe.URLtoString(fullRequestUrl) /> 
56    <#assign result = jsonFactoryUtil.looseDeserialize(response) /> 
57    <#return result /> 
58</#function> 
59 
60<#-- Makes a query to Central REST API to get portal site settings --> 
61<#function getPortalSiteSettingsFromCentralService> 
62    <#assign requestUrlPortalSites = "${csAddress}/central-rest/api/v1/configs/portalsites?vhost=${httpUtilUnsafe.encodeURL(virtualURL)}&friendlyUrl=${httpUtilUnsafe.encodeURL(friendlyUrl)}" /> 
63    <#assign response = httpUtilUnsafe.URLtoString(requestUrlPortalSites) /> 
64    <#assign result = jsonFactoryUtil.looseDeserialize(response) /> 
65    <#return result /> 
66</#function> 
67 
68<#-- Makes a query to Central REST API to get Member settings to extract Agency ID from --> 
69<#function getAgencySettingsFromCentralService> 
70    <#assign requestUrlMemberAgencies = "${csAddress}/central-rest/api/v1/configs/agencymembers/${agencyMemberID}" /> 
71    <#assign response = httpUtilUnsafe.URLtoString(requestUrlMemberAgencies) /> 
72    <#assign result = jsonFactoryUtil.looseDeserialize(response) /> 
73    <#return result /> 
74</#function> 
75 
76<#function getServerSettingsFromCentralService> 
77    <#assign portalSites = "" /> 
78    <#assign returnValue = "OK" /> 
79    <#assign portalSites = "" /> 
80    <#assign memberData = "" /> 
81    <#assign favoriteAgencyName = "" /> 
82    <#attempt> 
83        <#assign portalSites = getPortalSiteSettingsFromCentralService() /> 
84        <#if portalSites.id??> 
85            <#assign portalSiteID = portalSites.id?string /> 
86            <#assign favoriteAgencyName = portalSites.mainGroup.properties["Favourite Agency Member"] /> 
87        <#else> 
88            <#assign requestUrlPortalSites = "${csAddress}/central-rest/api/v1/configs/portalsites?vhost=${httpUtilUnsafe.encodeURL(virtualURL)}&friendlyUrl=${httpUtilUnsafe.encodeURL(friendlyUrl)}" /> 
89            <#assign response = httpUtilUnsafe.URLtoString(requestUrlPortalSites) /> 
90        </#if> 
91        <#if favoriteAgencyName != ""> 
92        <#-- Go through portalSites.agencyMemberSummaries to find the one with matching favoriteAgencyName --> 
93            <#list portalSites.agencyMemberSummaries as summary> 
94                <#if summary.name == favoriteAgencyName> 
95                    <#assign agencyMemberID = summary.id?string /> 
96                </#if> 
97            </#list> 
98        </#if> 
99        <#recover> 
100            <#assign returnValue =  "Portal Sites failed" /> 
101    </#attempt> 
102    <#if agencyMemberID != "" && returnValue == "OK"> 
103        <#attempt> 
104            <#assign memberData = getAgencySettingsFromCentralService() /> 
105            <#if memberData.agency??> 
106                <#assign agencyID = memberData.agency.id /> 
107                <#assign agencyName = memberData.agency.name /> 
108            </#if> 
109            <#recover> 
110                <#assign returnValue =  "Agency member data failed" /> 
111        </#attempt> 
112    </#if> 
113 
114    <#return returnValue /> 
115</#function> 
116 
117<#macro debugServerInfo> 
118    <div class="serverInfo hidden debug informative"> 
119        <p class="idsForRestAPI"> 
120            <strong>Portal Site ID:</strong> ${portalSiteID}<br /> 
121            <strong>Agency ID:</strong> ${agencyID}<br /> 
122            <strong>Agency name:</strong> ${agencyName}<br /> 
123            <strong>Member ID:</strong> ${agencyMemberID} 
124 
125        </p> 
126        <p class="serverURL"> 
127            <strong>Portal site URL:</strong> ${portalUrl}<br /> 
128            <strong>Portal site URL Secure:</strong> ${portalUrlSecure}<br /> 
129            <strong>Virtual URL:</strong> ${virtualURL}<br /> 
130            <strong>Friendly URL:</strong> ${friendlyUrl} 
131        </p> 
132    </div> 
133</#macro> 
134 
135<#-- Outputs a hidden debug tag with information. --> 
136<#macro debugthis title message link isinformative> 
137    <#assign cssClass = "hidden debug" /> 
138    <#if isinformative> 
139        <#assign cssClass = "hidden debug informative" /> 
140    </#if> 
141    <div class="${cssClass}"> 
142        <h4>Debug - ${title}</h4> 
143        <#if link == ""> 
144            <p>${message}</p> 
145        <#else> 
146            <p><a href="${link}">${message}</a></p> 
147        </#if> 
148    </div> 
149</#macro> 
150 
151<#macro showTags> 
152    <#assign tagsService = serviceLocator.findService("com.liferay.asset.kernel.service.AssetTagLocalService") /> 
153    <#assign tagsAsset = tagsService.getTags("com.liferay.journal.model.JournalArticle", articleResourcePK) /> 
154 
155<#-- Services for tag links --> 
156    <#assign layoutUid = journalArticle.getLayoutUuid() /> 
157 
158    <h3><@liferay.language key="staffpicks.detail.header.tags" /></h3> 
159    <@debugthis title="tags" message="Tag links don't work yet." isinformative=true link="" /> 
160    <@debugthis title="tags" message=layoutUid isinformative=true link="" /> 
161    <ul class="staffpick-article-tags"> 
162        <#list tagsAsset as tag> 
163            <#assign tagNameLink = tag.getName() /> 
164            <li class="staffpick-article-tagentry"><a class="staffpicks-article-tag-link" href="${sitePrefix}/-/tag/${tagNameLink}">${tagNameLink}</a></li> 
165        </#list> 
166    </ul> 
167</#macro> 
168 
169<#macro showArticleAuthor> 
170    <#if articleAuthor?? && articleAuthor.getData() != ""> 
171        <p class="staffpick-article-author-name"> 
172            <@liferay.language_format key="staffpicks.detail.articleauthor" arguments=[articleAuthor.getData()] /> 
173            <#--${languageUtil.format(locale, "staffpicks.detail.articleauthor", [articleAuthor.getData()])}--> 
174        </p> 
175    </#if> 
176</#macro> 
177 
178<#macro showDate dateString> 
179    <#assign localization = languageUtil.get(locale,"staffpicks.detail.dateformat") /> 
180    <#assign timeString = "MMM d yyyy" /> 
181    <#if localization != "staffpicks.detail.dateformat"> 
182        <#assign timeString = localization /> 
183    </#if> 
184    <#assign originalLocale = locale /> 
185    <#setting locale = localeUtil.getDefault() /> 
186    <#assign time = dateString?datetime("EEE, dd MMM yyyy hh:mm:ss ZZZZ") /> 
187    <#setting locale = originalLocale /> 
188    ${time?string[timeString]} 
189</#macro> 
190 
191<#macro showRecord recordInfo> 
192<#-- Arena 4 CRD link --> 
193    <#assign crdPageFullUrl = "${crdPageUrl}?p_p_id=crDetailWicket_WAR_arenaportlet&p_p_lifecycle=1&p_p_state=normal&p_r_p_arena_urn%3Aarena_search_item_id=${recordInfo.id}&p_r_p_arena_urn%3Aarena_agency_name=${agencyName}" /> 
194 
195    <li class="similar-record record-${recordInfo.id}"> 
196        <@debugthis title="Record" message="ID: ${recordInfo.id}" link="" isinformative=true /> 
197        <a class="similar-record-link" href="${crdPageFullUrl}"> 
198            <img class="similar-record-cover" src="${portalUrlSecure}/local-rest/api/v1/portalsites/${portalSiteID}/agencies/${agencyID}/records/${httpUtilUnsafe.encodeURL(recordInfo.id)}/cover" alt="" /> 
199            <span class="similar-record-title">${recordInfo.fields.title}</span> 
200            <#if recordInfo.fields.authors?? && recordInfo.fields.authors?size gt 0 && recordInfo.fields.authors[0]??> 
201            <span class="similar-record-author">${recordInfo.fields.authors[0].name} 
202                </#if> 
203        </a> 
204        <#if recordInfo.rating??> 
205            <@showRatings rating=recordInfo.rating recordtitle=recordInfo.fields.title /> 
206        </#if> 
207    </li> 
208</#macro> 
209 
210<#macro showRatings rating recordtitle> 
211    <#assign ratingFive = (rating/2) /> 
212    <#assign ratingLimit = 5 /> 
213    <div class="staffpicks-rating"> 
214        <#assign ratingFiveString = ratingFive?string.number /> 
215        <span class="sr-only"><@liferay.language_format key="staffpicks.detail.rating" arguments=[recordtitle, ratingFiveString, ratingLimit]/></span> 
216        <#list 1..ratingLimit as x> 
217            <#if (x-0.5) == ratingFive> 
218                <span class="arena-rating rating-half-full"><i class="icon-star-half-full"></i></span> 
219            <#elseif x <= ratingFive> 
220                <span class="arena-rating rating-full"><i class="icon-star"></i></span> 
221            <#else> 
222                <span class="arena-rating rating-empty"><i class="icon-star-empty"></i></span> 
223            </#if> 
224        </#list> 
225    </div> 
226</#macro> 
227 
228<#macro showSimilarRecords result> 
229    <h3><@liferay.language key="staffpicks.detail.header.similartitles" /></h3> 
230    <#assign searchString = "" /> 
231    <#attempt> 
232        <#if result.fields.subjects?size gt 0> 
233            <#assign searchString = searchString + "(" /> 
234            <#list result.fields.subjects as subject> 
235                <#assign searchString = searchString + "subject:\"${subject}\"" /> 
236                <#if subject_index < result.fields.subjects?size-1> 
237                    <#assign searchString = searchString + " OR " /> 
238                </#if> 
239            </#list> 
240            <#assign searchString = searchString +") AND (" /> 
241        <#else> 
242            <#assign searchString = searchString +"(" /> 
243        </#if> 
244        <#recover> 
245    </#attempt> 
246    <#attempt> 
247        <#if result.fields.languages?size gt 0> 
248            <#list result.fields.languages as language> 
249                <#assign searchString = searchString + "language:\"${language}\"" /> 
250                <#if language_index < result.fields.languages?size-1> 
251                    <#assign searchString = searchString + " OR " /> 
252                </#if> 
253            </#list> 
254        </#if> 
255        <#recover> 
256    </#attempt> 
257    <#attempt> 
258        <#assign searchString = searchString +") AND " /> 
259        <#assign searchString = searchString+"mediaclass:\"${result.fields.mediaClass}\" AND " /> 
260        <#assign searchString = searchString +"NOT uberkey:\"${result.uberkey}\"" /> 
261        <#recover> 
262    </#attempt> 
263 
264    <#assign similarBooks = ""> 
265 
266    <#attempt> 
267        <#assign similarBooks = queryAPI(searchString, queryLimit) /> 
268        <ul class="staffpick-similar-records"> 
269            <#list similarBooks.records as record> 
270                <@showRecord recordInfo = record /> 
271            </#list> 
272        </ul> 
273        <#recover> 
274            <@debugthis title="Similar records" message="Similar records not looked for because an error happened in API call or processing it." isinformative=false link="" /> 
275    </#attempt> 
276    <@debugthis title="Similar records search string" message=searchString isinformative=true link="" /> 
277    <#assign fullRequestUrl = '${lsAddress}/local-rest/api/v1/portalsites/${portalSiteID}/records?query=${searchString}&count=${queryLimit}&isShowExtended=false&sortDirection=Descending&sortField=Relevance&agencyMemberId=${agencyMemberID}'/> 
278    <@debugthis title="Similar records search URL" message="Similar records query" isinformative=true link=fullRequestUrl /> 
279</#macro> 
280 
281<#-- Prints a debug button that toggles the visibility of elements with debug CSS class --> 
282<#macro toggleDebug> 
283    <script type="text/javascript"> 
284        function toggleDebugMessages() { 
285            YUI().use("node",function(Y) { 
286                Y.all(".debug").each(function() { 
287                    this.toggleClass("hidden"); 
288                }); 
289            }); 
290        }; 
291    </script> 
292    <a href="javascript:void(0);" onclick="toggleDebugMessages()" class="btn btn-info toggle-debug-button"><i class="icon-eye-open"></i> Debug</a> 
293</#macro> 
294 
295<link rel="stylesheet" type="text/css" href="//cdn.axiell.com/arena/staffpicks/staffpicks.css"> 
296<div class="staffpick-article"> 
297    <#assign status = "OK" /> 
298    <#assign status = getServerSettingsFromCentralService() /> 
299 
300    <@debugServerInfo /> 
301 
302    <#if status != "OK"> 
303        <@debugthis isinformative=false title="Central Service Settings failed" message="Failed with ${status}" link=""/> 
304    </#if> 
305 
306    <div class="back-button-container"> 
307        <a class="staffpick-back-link" href="javascript:void(0);" onclick="window.history.back();"><@liferay.language key="back" /></a> 
308    </div> 
309    <style>.portlet-asset-categories-navigation, .staff-picks-introduction { display: none; }</style> 
310    <#assign searchQuery = "" /> 
311    <#assign result = "" /> 
312    <#assign recordInfo = "" /> 
313    <#if recordId?? && recordId.getData() != ""> 
314        <#if recordId.getData()?index_of("id:") == -1> 
315            <#assign searchQuery = 'id:"${recordId.getData()}"' /> 
316        <#else> 
317            <#assign searchQuery = recordId.getData() /> 
318        </#if> 
319        <#attempt> 
320            <#assign result = queryAPI(searchQuery, 1) /> 
321            <#assign recordInfo = result.records[0] /> 
322 
323            <#recover> 
324                <#assign recordInfo = { 
325                "fields" : { 
326                "title" :  "${.vars['reserved-article-title'].data}" 
327
328                } /> 
329                <#assign fullRequestUrl = "${lsAddress}/local-rest/api/v1/portalsites/${portalSiteID}/records?query=${httpUtilUnsafe.encodeURL(searchQuery,true)}&count=1&isShowExtended=false&sortDirection=Descending&sortField=Relevance&agencyMemberId=${agencyMemberID}"/> 
330                <@debugthis isinformative=false title="API call failed with this url" message=fullRequestUrl link=fullRequestUrl /> 
331 
332        </#attempt> 
333    <#else> 
334        <#assign recordInfo = { 
335        "fields" : { 
336        "title" :  "${.vars['reserved-article-title'].data}" 
337
338        } /> 
339    </#if> 
340 
341 
342 
343 
344    <div class="row"> 
345        <div class="col-xs-12 col-sm-4 col-lg-3 cover-column"> 
346 
347            <#if recordInfo.id??> 
348            <#--Arena 4 CRD link --> 
349                <#assign crdPageFullUrl = "${crdPageUrl}?p_p_id=crDetailWicket_WAR_arenaportlet&p_p_lifecycle=1&p_p_state=normal&p_r_p_arena_urn%3Aarena_search_item_id=${recordInfo.id}&p_r_p_arena_urn%3Aarena_agency_name=${agencyName}" /> 
350 
351                <a class="record-link" href="${crdPageFullUrl}"> 
352                    <#assign assetService = serviceLocator.findService("com.liferay.asset.kernel.service.AssetEntryLocalService") /> 
353                    <#assign thumbnailPath = "" /> 
354                    <#attempt> 
355                        <#assign serviceContext = staticUtil["com.liferay.portal.kernel.service.ServiceContextThreadLocal"].getServiceContext()> 
356                        <#assign themeDisplay = serviceContext.getThemeDisplay() /> 
357                        <#assign thumbnailPath = journalArticle.getArticleImageURL(themeDisplay) /> 
358                        <#recover> 
359                    </#attempt> 
360                    <#if journalArticle.getSmallImage() && thumbnailPath != ""> 
361                        <img class="cover-image cover-overwrite" alt="" src="${thumbnailPath}" /> 
362                    <#else> 
363                        <img class="cover-image" alt="" src="${portalUrlSecure}/local-rest/api/v1/portalsites/${portalSiteID}/agencies/${agencyID}/records/${httpUtilUnsafe.encodeURL(recordInfo.id)}/cover" /> 
364                    </#if> 
365                    <span class="alg-button alg-button--inverted gotoCRDButton"><@liferay.language key="staffpicks.detail.viewbook" /></span> 
366                </a> 
367            </#if> 
368            <@toggleDebug /> 
369        </div> 
370        <div class="col-xs-12 col-sm-8 col-lg-9 staffpick-detail"> 
371            <div class="staffpick-article-title"> 
372                <h2>${recordInfo.fields.title}</h2> 
373            </div> 
374            <#-- Special debug which cannot be in a regular macro --> 
375            <#if recordInfo.id??> 
376                <@debugthis title="Record Id - API" message="Record ID from API: ${recordInfo.id}" isinformative=true link="" /> 
377            </#if> 
378            <@debugthis title="Record Id - Query" message="Record ID from Query: ${recordId.getData()}" isinformative=true link="" /> 
379            <#if recordInfo.id?? && (recordInfo.id != recordId.getData() )> 
380                <@debugthis title="Record id missmatch" message="Query ID and API ID do not match!" isinformative=false link="" /> 
381            </#if> 
382 
383            <#if recordInfo.fields?? && recordInfo.fields.authors?? && recordInfo.fields.authors?size gt 0 && recordInfo.fields.authors[0]??> 
384                <div class="staffpick-article-author"> 
385                    <a class="staffpick-article-author-link" href="${searchPageUrl}?p_p_id=searchResult_WAR_arenaportlet&p_p_lifecycle=1&p_p_state=normal&p_r_p_arena_urn%3Aarena_facet_queries=&p_r_p_arena_urn%3Aarena_search_query=${recordInfo.fields.authors[0].name}&p_r_p_arena_urn%3Aarena_search_type=solr&p_r_p_arena_urn%3Aarena_sort_advice=field%3DRelevance%26direction%3DDescending"> 
386                        <@liferay.language_format key="staffpicks.detail.author" arguments=[recordInfo.fields.authors[0].name] /> 
387                    </a> 
388                </div> 
389            </#if> 
390            <div class="staffpick-article-text"> 
391                ${articleText.getData()} 
392            </div> 
393            <div class="staffpick-article-recommendedby-date row"> 
394                <div class="staffpick-article-recommeded-by col-xs-12 col-sm-7"> 
395                    <@showArticleAuthor /> 
396                </div> 
397                <div class="staffpick-article-date col-xs-12 col-sm-5"> 
398                    <@showDate dateString=.vars['reserved-article-create-date'].data /> 
399                </div> 
400            </div> 
401        </div> 
402    </div> 
403    <#--<div class="row tags-container"> 
404        <div class="col-xs-12"> 
405            <@showTags /> 
406        </div> 
407    </div>--> 
408    <div class="row similar-records-container"> 
409        <div class="col-xs-12"> 
410            <@showSimilarRecords result=recordInfo /> 
411        </div> 
412    </div> 
413</div>