public void doEdit(RenderRequest request, RenderResponse response) throws PortletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); String title = getTitleString(request); if (title != null) response.setTitle(title); Context context = new VelocityContext(); context.put("tlang", rb); context.put("validator", validator); sendAlert(request, context); PortletURL url = response.createActionURL(); context.put("actionUrl", url.toString()); context.put("doCancel", "sakai.cancel"); context.put("doUpdate", "sakai.update"); // get current site Placement placement = ToolManager.getCurrentPlacement(); String siteId = ""; // find the right LTIContent object for this page String source = placement.getPlacementConfig().getProperty(SOURCE); Long key = getContentIdFromSource(source); if (key == null) { out.println(rb.getString("get.info.notconfig")); M_log.warn("Cannot find content id placement=" + placement.getId() + " source=" + source); return; } Map<String, Object> content = m_ltiService.getContent(key); if (content == null) { out.println(rb.getString("get.info.notconfig")); M_log.warn("Cannot find content item placement=" + placement.getId() + " key=" + key); return; } // attach the ltiToolId to each model attribute, so that we could have the tool configuration // page for multiple tools String foundLtiToolId = content.get(m_ltiService.LTI_TOOL_ID).toString(); Map<String, Object> tool = m_ltiService.getTool(Long.valueOf(foundLtiToolId)); if (tool == null) { out.println(rb.getString("get.info.notconfig")); M_log.warn("Cannot find tool placement=" + placement.getId() + " key=" + foundLtiToolId); return; } String[] contentToolModel = m_ltiService.getContentModel(Long.valueOf(foundLtiToolId)); String formInput = m_ltiService.formInput(content, contentToolModel); context.put("formInput", formInput); vHelper.doTemplate(vengine, "/vm/edit.vm", context, out); }
public void processActionEdit(ActionRequest request, ActionResponse response) throws PortletException, IOException { // TODO: Check Role // Stay in EDIT mode unless we are successful response.setPortletMode(PortletMode.EDIT); Placement placement = ToolManager.getCurrentPlacement(); // get the site toolConfiguration, if this is part of a site. ToolConfiguration toolConfig = SiteService.findTool(placement.getId()); String id = request.getParameter(LTIService.LTI_ID); String toolId = request.getParameter(LTIService.LTI_TOOL_ID); Properties reqProps = new Properties(); Enumeration names = request.getParameterNames(); while (names.hasMoreElements()) { String name = (String) names.nextElement(); reqProps.setProperty(name, request.getParameter(name)); } Object retval = m_ltiService.updateContent(Long.parseLong(id), reqProps); placement.save(); response.setPortletMode(PortletMode.VIEW); }
protected void processSetting( HttpServletRequest request, HttpServletResponse response, String lti_message_type, Site site, String siteId, String placement_id, Properties pitch, String user_id, Map<String, Object> theMap) throws java.io.IOException { String setting = null; // Check for permission in placement String allowSetting = pitch.getProperty(LTIService.LTI_ALLOWSETTINGS); if (!"on".equals(allowSetting)) { doError( request, response, theMap, "outcomes.invalid", "lti_message_type=" + lti_message_type, null); return; } SakaiBLTIUtil.pushAdvisor(); boolean success = false; try { if ("basic-lti-loadsetting".equals(lti_message_type)) { setting = pitch.getProperty(LTIService.LTI_SETTINGS_EXT); // Remove this after the DB conversion for SAK-25621 is completed // It is harmless until LTI 2.0 starts to get heavy use. if (setting == null) { setting = pitch.getProperty(LTIService.LTI_SETTINGS); } if (setting != null) { theMap.put("/message_response/setting/value", setting); } success = true; } else { if (SakaiBLTIUtil.isPlacement(placement_id)) { ToolConfiguration placement = SiteService.findTool(placement_id); if ("basic-lti-savesetting".equals(lti_message_type)) { setting = request.getParameter("setting"); if (setting == null) { M_log.warn("No setting parameter"); doError(request, response, theMap, "setting.empty", "", null); } else { if (setting.length() > 8096) setting = setting.substring(0, 8096); placement.getPlacementConfig().setProperty("toolsetting", setting); } } else if ("basic-lti-deletesetting".equals(lti_message_type)) { placement.getPlacementConfig().remove("toolsetting"); } try { placement.save(); success = true; } catch (Exception e) { doError(request, response, theMap, "setting.save.fail", "", e); } } else { Map<String, Object> content = null; String contentStr = pitch.getProperty("contentKey"); Long contentKey = foorm.getLongKey(contentStr); if (contentKey >= 0) content = ltiService.getContentDao(contentKey, siteId); if (content != null) { if ("basic-lti-savesetting".equals(lti_message_type)) { setting = request.getParameter("setting"); if (setting == null) { M_log.warn("No setting parameter"); doError(request, response, theMap, "setting.empty", "", null); } else { if (setting.length() > 8096) setting = setting.substring(0, 8096); content.put(LTIService.LTI_SETTINGS_EXT, setting); success = true; } } else if ("basic-lti-deletesetting".equals(lti_message_type)) { content.put(LTIService.LTI_SETTINGS_EXT, null); success = true; } if (success) { Object result = ltiService.updateContentDao(contentKey, content, siteId); if (result instanceof String) { M_log.warn("Setting update failed: " + result); doError(request, response, theMap, "setting.fail", "", null); success = false; } } } } } } catch (Exception e) { doError(request, response, theMap, "setting.fail", "", e); } finally { SakaiBLTIUtil.popAdvisor(); } if (!success) return; theMap.put("/message_response/statusinfo/codemajor", "Success"); theMap.put("/message_response/statusinfo/severity", "Status"); theMap.put("/message_response/statusinfo/codeminor", "fullsuccess"); String theXml = XMLMap.getXML(theMap, true); PrintWriter out = response.getWriter(); out.println(theXml); }
// Render the portlet - this is not supposed to change the state of the portlet // Render may be called many times so if it changes the state - that is tacky // Render will be called when someone presses "refresh" or when another portlet // onthe same page is handed an Action. public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException { response.setContentType("text/html"); // System.out.println("==== doView called ===="); // Grab that underlying request to get a GET parameter ServletRequest req = (ServletRequest) ThreadLocalManager.get(CURRENT_HTTP_REQUEST); String popupDone = req.getParameter("sakai.popup"); PrintWriter out = response.getWriter(); Placement placement = ToolManager.getCurrentPlacement(); response.setTitle(placement.getTitle()); String source = placement.getPlacementConfig().getProperty(SOURCE); if (source == null) source = ""; String height = placement.getPlacementConfig().getProperty(HEIGHT); if (height == null) height = "1200px"; boolean maximize = "true".equals(placement.getPlacementConfig().getProperty(MAXIMIZE)); boolean popup = false; // Comes from content item boolean oldPopup = "true".equals(placement.getPlacementConfig().getProperty(POPUP)); // Retrieve the corresponding content item and tool to check the launch Map<String, Object> content = null; Map<String, Object> tool = null; Long key = getContentIdFromSource(source); if (key == null) { out.println(rb.getString("get.info.notconfig")); M_log.warn("Cannot find content id placement=" + placement.getId() + " source=" + source); return; } try { content = m_ltiService.getContent(key); // If we are supposed to popup (per the content), do so and optionally // copy the calue into the placement to communicate with the portal popup = getLongNull(content.get("newpage")) == 1; if (oldPopup != popup) { placement.getPlacementConfig().setProperty(POPUP, popup ? "true" : "false"); placement.save(); } String launch = (String) content.get("launch"); Long tool_id = getLongNull(content.get("tool_id")); if (launch == null && tool_id != null) { tool = m_ltiService.getTool(tool_id); launch = (String) tool.get("launch"); } // Force http:// to pop-up if we are https:// String serverUrl = ServerConfigurationService.getServerUrl(); if (request.isSecure() || (serverUrl != null && serverUrl.startsWith("https://"))) { if (launch != null && launch.startsWith("http://")) popup = true; } } catch (Exception e) { out.println(rb.getString("get.info.notconfig")); e.printStackTrace(); return; } if (source != null && source.trim().length() > 0) { Context context = new VelocityContext(); context.put("tlang", rb); context.put("validator", validator); context.put("source", source); context.put("height", height); sendAlert(request, context); context.put("popupdone", Boolean.valueOf(popupDone != null)); context.put("popup", Boolean.valueOf(popup)); context.put("maximize", Boolean.valueOf(maximize)); vHelper.doTemplate(vengine, "/vm/main.vm", context, out); } else { out.println(rb.getString("get.info.notconfig")); } // System.out.println("==== doView complete ===="); }
/* (non-Javadoc) * @see impl.LTIExportService#export(java.io.OutputStream, org.sakaiproject.lti.api.LTIExportService.ExportType, java.lang.String) */ public void export(OutputStream out, String siteId, ExportType exportType, String filterId) { String search = null; // check if we need to filter the tools by tool_id if (StringUtils.isNotEmpty(filterId)) { search = "tool_id:" + filterId; } List<Map<String, Object>> contents = ltiService.getContentsDao(search, null, 0, 0, siteId, isAdmin(siteId)); LTIExporter exporter = null; switch (exportType) { case CSV: exporter = new ExporterCSV(); break; case EXCEL: exporter = new ExporterExcel(); break; } if (exporter != null) { DateFormat dateFormatter = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, rb.getLocale()); String attribution_name = serverConfigurationService.getString(LTIService.LTI_SITE_ATTRIBUTION_PROPERTY_NAME); if (StringUtils.isNotEmpty(attribution_name)) { // check if given property is a translation key String aux = rb.getString(attribution_name); if (StringUtils.isNotEmpty(aux)) attribution_name = aux; } boolean isAdmin = isAdmin(siteId); // set header row exporter.newLine(); exporter.addCell(rb.getString("export.title")); exporter.addCell(rb.getString("export.url")); if (isAdmin) { exporter.addCell(rb.getString("export.siteid")); exporter.addCell(rb.getString("export.sitetitle")); } exporter.addCell(rb.getString("export.createdat")); if (isAdmin) { exporter.addCell(rb.getString("export.sitecontactname")); exporter.addCell(rb.getString("export.sitecontactemail")); if (StringUtils.isNotEmpty(attribution_name)) { exporter.addCell(attribution_name); } } // values rows for (Map<String, Object> content : contents) { exporter.newLine(); exporter.addCell((String) content.get("title")); String url = (String) content.get("launch"); if (StringUtils.isEmpty(url)) { try { url = (String) (ltiService .getToolDao( new Long(content.get(LTIService.LTI_TOOL_ID).toString()), siteId) .get("launch")); } catch (Exception e) { url = "-"; } } exporter.addCell(url); if (isAdmin) { exporter.addCell((String) content.get("SITE_ID")); exporter.addCell((String) content.get("SITE_TITLE")); } try { exporter.addCell(dateFormatter.format(content.get("created_at"))); } catch (Exception e) { exporter.addCell("-"); } if (isAdmin) { exporter.addCell((String) content.get("SITE_CONTACT_NAME")); exporter.addCell((String) content.get("SITE_CONTACT_EMAIL")); if (StringUtils.isNotEmpty(attribution_name)) { exporter.addCell((String) content.get("ATTRIBUTION")); } } } exporter.write(out); } else { M_log.error("Error exporting : no exporter found for " + exportType); } }
private void syncSiteMembershipsOnceThenSchedule( Map payload, Site site, boolean isTrustedConsumer, boolean isEmailTrustedConsumer) throws LTIException { if (isTrustedConsumer) return; M_log.debug("synchSiteMembershipsOnceThenSchedule"); if (!ServerConfigurationService.getBoolean(SakaiBLTIUtil.INCOMING_ROSTER_ENABLED, false)) { M_log.info("LTI Memberships synchronization disabled."); return; } final String membershipsUrl = (String) payload.get("ext_ims_lis_memberships_url"); if (!BasicLTIUtil.isNotBlank(membershipsUrl)) { M_log.info("LTI Memberships extension is not supported."); return; } if (M_log.isDebugEnabled()) M_log.debug("Memberships URL: " + membershipsUrl); final String membershipsId = (String) payload.get("ext_ims_lis_memberships_id"); if (!BasicLTIUtil.isNotBlank(membershipsId)) { M_log.info("No memberships id supplied. Memberships will NOT be synchronized."); return; } final String siteId = site.getId(); // If this site has already been scheduled, then we do nothing. if (ltiService.getMembershipsJob(siteId) != null) { if (M_log.isDebugEnabled()) { M_log.debug( "Site '" + siteId + "' already scheduled for memberships sync. Doing nothing ..."); } return; } final String oauth_consumer_key = (String) payload.get(OAuth.OAUTH_CONSUMER_KEY); // This is non standard. Moodle's core LTI plugin does not currently do memberships and // a fix for this has been proposed at https://tracker.moodle.org/browse/MDL-41724. I don't // think this will ever become core and the first time memberships will appear in core lti // is with LTI2. At that point this code will be replaced with standard LTI2 JSON type stuff. String lms = (String) payload.get("ext_lms"); final String callbackType = (BasicLTIUtil.isNotBlank(lms) && lms.equals("moodle-2")) ? "ext-moodle-2" : (String) payload.get(BasicLTIConstants.LTI_VERSION); (new Thread( new Runnable() { public void run() { long then = 0L; if (M_log.isDebugEnabled()) { M_log.debug("Starting memberships sync."); then = (new Date()).getTime(); } siteMembershipsSynchroniser.synchroniseSiteMemberships( siteId, membershipsId, membershipsUrl, oauth_consumer_key, isEmailTrustedConsumer, callbackType); if (M_log.isDebugEnabled()) { long now = (new Date()).getTime(); M_log.debug( "Memberships sync finished. It took " + ((now - then) / 1000) + " seconds."); } } }, "org.sakaiproject.blti.ProviderServlet.MembershipsSync")) .start(); ltiService.insertMembershipsJob( siteId, membershipsId, membershipsUrl, oauth_consumer_key, callbackType); }