From 42d7435f22effb30d4d51dd7f7e11bc25fd436e4 Mon Sep 17 00:00:00 2001 From: Charles Severance Date: Thu, 16 Jul 2015 00:14:57 -0400 Subject: [PATCH] SAK-29328 - Move towards a placement view in the tool model --- .../org/sakaiproject/lti/api/LTIService.java | 11 ++++++++++- .../java/org/sakaiproject/lti2/LTI2Service.java | 3 +++ .../src/bundle/ltiservice.properties | 9 ++++++--- .../sakaiproject/blti/tool/LTIAdminTool.java | 15 +++++++++++++-- .../java/org/imsglobal/lti2/ContentItem.java | 17 ++++++++++++++--- .../src/java/org/imsglobal/lti2/ToolProxy.java | 1 + 6 files changed, 47 insertions(+), 9 deletions(-) diff --git a/basiclti/basiclti-api/src/java/org/sakaiproject/lti/api/LTIService.java b/basiclti/basiclti-api/src/java/org/sakaiproject/lti/api/LTIService.java index ecd8ee5fe630..bf39fd8d4d61 100644 --- a/basiclti/basiclti-api/src/java/org/sakaiproject/lti/api/LTIService.java +++ b/basiclti/basiclti-api/src/java/org/sakaiproject/lti/api/LTIService.java @@ -720,7 +720,12 @@ public interface LTIService { "allowroster:checkbox:label=bl_allowroster", "allowsettings:checkbox:label=bl_allowsettings", "allowlori:checkbox:label=bl_allowlori", - "allowcontentitem:checkbox:label=bl_allowcontentitem", + // Hide these from end users until they are working in the various Sakai tools + "pl_header:header:fields=pl_linkselection,pl_fileimport,pl_contenteditor,pl_assessmentselection", + "pl_linkselection:checkbox:label=bl_pl_linkselection", + "pl_fileimport:checkbox:label=bl_pl_fileimport:role=admin", + "pl_contenteditor:checkbox:label=bl_pl_contenteditor:role=admin", + "pl_assessmentselection:checkbox:label=bl_pl_assessmentselection:role=admin", "newpage:radio:label=bl_newpage:choices=off,on,content", "debug:radio:label=bl_debug:choices=off,on,content", // LTI 1.x user-entered custom @@ -849,5 +854,9 @@ public interface LTIService { // A subset of a tool_proxy with only a single resource_handler static final String LTI_TOOL_PROXY_BINDING = "tool_proxy_binding"; // End of BLTI-230 - LTI 2.0 + static final String LTI_PL_LINKSELECTION = "pl_linkselection"; + static final String LTI_PL_FILEIMPORT = "pl_fileimport"; + static final String LTI_PL_CONTENTEDITOR = "pl_contenteditor"; + static final String LTI_PL_ASSESSMENTSELECTION = "pl_assessmentselection"; } diff --git a/basiclti/basiclti-blis/src/java/org/sakaiproject/lti2/LTI2Service.java b/basiclti/basiclti-blis/src/java/org/sakaiproject/lti2/LTI2Service.java index 1a50d6229538..4934f34b3ab7 100644 --- a/basiclti/basiclti-blis/src/java/org/sakaiproject/lti2/LTI2Service.java +++ b/basiclti/basiclti-blis/src/java/org/sakaiproject/lti2/LTI2Service.java @@ -42,6 +42,7 @@ import org.imsglobal.lti2.LTI2Constants; import org.imsglobal.lti2.LTI2Util; import org.imsglobal.lti2.ToolProxy; +import org.imsglobal.lti2.ContentItem; import org.imsglobal.lti2.objects.Service_offered; import org.imsglobal.lti2.objects.StandardServices; import org.imsglobal.lti2.objects.ToolConsumer; @@ -223,6 +224,8 @@ protected ToolConsumer getToolConsumerProfile(Map deploy, String ToolConsumer consumer = new ToolConsumer(profile_id+"", resourceUrl, cnf); consumer.allowSplitSecret(); consumer.allowHmac256(); + consumer.addCapability(ContentItem.getCapability(ContentItem.TYPE_LTILINK)); + consumer.addCapability(ContentItem.getCapability(ContentItem.TYPE_FILEITEM)); if (foorm.getLong(deploy.get(LTIService.LTI_SENDEMAILADDR)) > 0 ) { consumer.allowEmail(); diff --git a/basiclti/basiclti-impl/src/bundle/ltiservice.properties b/basiclti/basiclti-impl/src/bundle/ltiservice.properties index 3cc4f5b338e0..689cfd2ff7bb 100644 --- a/basiclti/basiclti-impl/src/bundle/ltiservice.properties +++ b/basiclti/basiclti-impl/src/bundle/ltiservice.properties @@ -68,9 +68,12 @@ bl_allowroster=Provide Roster to External Tool bl_allowsettings=Allow External Tool to store setting data bl_allowlori=Allow External Tool to access Lessons API bl_allowcontentitem=Allow External Tool to configure itself (the tool must support the IMS Content-Item message) -bl_allowlinkselection=Allow External Tool to Send Links -bl_allowassessmentselection=Allow External Tool to be an assessment -bl_allowcoursenavigation=Allow External Tool to be in course navigation +pl_header=Indicate the following types of Content Item Selection launches this tool can handle. Not all tools can handle Content Item Selection launches. If you enable a tool which is not capable of responding to a particular request, it will likely fail when you try to use it. +bl_pl_coursenavigation=Allow the tool to be launched as a link (this is typically true for most tools) +bl_pl_linkselection=Allow external tool to configure itself (the tool must support the IMS Content-Item message) +bl_pl_fileimport=Allow the tool to provide a file to be imported into a tool like Lessons +bl_pl_contenteditor=Allow the tool to be used from the rich content editor to select content +bl_pl_assessmentselection=Allow the tool to be one of the assessment types bl_allowcustom=Allow additional custom parameters bl_custom=Custom Parameters (key=value on separate lines) bl_splash=Splash Screen (If this is non-blank it is shown before the tool is launched) diff --git a/basiclti/basiclti-tool/src/java/org/sakaiproject/blti/tool/LTIAdminTool.java b/basiclti/basiclti-tool/src/java/org/sakaiproject/blti/tool/LTIAdminTool.java index 9bca4c86ab0b..0b2695f2606d 100644 --- a/basiclti/basiclti-tool/src/java/org/sakaiproject/blti/tool/LTIAdminTool.java +++ b/basiclti/basiclti-tool/src/java/org/sakaiproject/blti/tool/LTIAdminTool.java @@ -38,6 +38,7 @@ import org.imsglobal.basiclti.BasicLTIConstants; import org.imsglobal.lti2.LTI2Config; import org.imsglobal.lti2.LTI2Constants; +import org.imsglobal.lti2.LTI2Messages; import org.imsglobal.lti2.LTI2Util; import org.imsglobal.lti2.ToolProxy; import org.imsglobal.lti2.ContentItem; @@ -1019,6 +1020,16 @@ public String prepareValidate(Map deploy, List addAlert(state,rb.getString("deploy.parse.error")+" tool_proxy_binding"); return "lti_error"; } + + if ( toolProxyBinding.enabledCapability(LTI2Messages.BASIC_LTI_LAUNCH_REQUEST, + ContentItem.getCapability(ContentItem.TYPE_LTILINK) ) ) { + newTool.put(LTIService.LTI_PL_LINKSELECTION, new Integer(1)); + } + + if ( toolProxyBinding.enabledCapability(LTI2Messages.BASIC_LTI_LAUNCH_REQUEST, + ContentItem.getCapability(ContentItem.TYPE_FILEITEM) ) ) { + newTool.put(LTIService.LTI_PL_FILEIMPORT, new Integer(1)); + } newTool.put(LTIService.LTI_TOOL_PROXY_BINDING, tool_proxy_binding); String fa_icon = toolProxyBinding.getIconPath("FontAwesome"); @@ -1676,13 +1687,13 @@ public String buildContentConfigPanelContext(VelocityPortlet portlet, Context co } // Check if we are supposed to let the tool configure itself - Long allowContentItem = foorm.getLong(tool.get(LTIService.LTI_ALLOWCONTENTITEM)); + Long allowLinkSelection = foorm.getLong(tool.get(LTIService.LTI_PL_LINKSELECTION)); context.put("isAdmin",new Boolean(ltiService.isAdmin()) ); context.put("doAction", BUTTON + "doContentPut"); if ( ! returnUrl.startsWith("about:blank") ) context.put("cancelUrl", returnUrl); context.put("returnUrl", returnUrl); - if ( allowContentItem > 0 ) context.put("contentLaunch", contentLaunch); + if ( allowLinkSelection > 0 ) context.put("contentLaunch", contentLaunch); context.put(LTIService.LTI_TOOL_ID,toolKey); context.put("tool_description", tool.get(LTIService.LTI_DESCRIPTION)); context.put("tool_title", tool.get(LTIService.LTI_TITLE)); diff --git a/basiclti/basiclti-util/src/java/org/imsglobal/lti2/ContentItem.java b/basiclti/basiclti-util/src/java/org/imsglobal/lti2/ContentItem.java index de0331db9e22..c3b023f0d0db 100644 --- a/basiclti/basiclti-util/src/java/org/imsglobal/lti2/ContentItem.java +++ b/basiclti/basiclti-util/src/java/org/imsglobal/lti2/ContentItem.java @@ -77,10 +77,13 @@ public class ContentItem { public static final String ACCEPT_MEDIA_TYPES = "accept_media_types"; public static String MEDIA_LTILINK = "application/vnd.ims.lti.v1.ltilink"; - public static String MEDIA_CC = "application/vnd.ims.lti.v1.ltilink"; - - public static String TYPE_LTILINK = "LtiLink"; + // http://www.ietf.org/mail-archive/web/ietf-types/current/msg00754.html + public static final String MEDIA_CC = "application/imsccml+xml"; + public static final String TYPE_LTILINK = "LtiLink"; + public static final String TYPE_CONTENTITEM = "ContentItem"; + public static final String TYPE_FILEITEM = "FileItem"; + public static final String TYPE_IMPORTITEM = "ImportItem"; HttpServletRequest servletRequest = null; @@ -246,6 +249,14 @@ public String getErrorMessage() return errorMessage; } + /** + * Get an LTI 2.x Capability String + */ + public static String getCapability(String type) + { + return "ContentItem." + type; + } + /** * Build up a ContentItem launch URL from a base url, return url and extra data */ diff --git a/basiclti/basiclti-util/src/java/org/imsglobal/lti2/ToolProxy.java b/basiclti/basiclti-util/src/java/org/imsglobal/lti2/ToolProxy.java index 023e32ee9fa8..4f0865bf6c6e 100644 --- a/basiclti/basiclti-util/src/java/org/imsglobal/lti2/ToolProxy.java +++ b/basiclti/basiclti-util/src/java/org/imsglobal/lti2/ToolProxy.java @@ -153,6 +153,7 @@ public boolean enabledCapability(JSONObject resourceHandler, String messageType, { JSONObject message = getMessageOfType(resourceHandler, messageType); JSONArray enabled_capability = getArray(message, LTI2Constants.ENABLED_CAPABILITY); + if ( enabled_capability == null ) return false; return enabled_capability.contains(capability); }