private void init(final UserRequest ureq) { startButton = LinkFactory.createButton("start", myContent, this); // fetch disclaimer file String sDisclaimer = (String) modConfig.get(IQEditController.CONFIG_KEY_DISCLAIMER); if (sDisclaimer != null) { VFSContainer baseContainer = userCourseEnv.getCourseEnvironment().getCourseFolderContainer(); final int lastSlash = sDisclaimer.lastIndexOf('/'); if (lastSlash != -1) { baseContainer = (VFSContainer) baseContainer.resolve(sDisclaimer.substring(0, lastSlash)); sDisclaimer = sDisclaimer.substring(lastSlash); // first check if disclaimer exists on filesystem if (baseContainer == null || baseContainer.resolve(sDisclaimer) == null) { showWarning("disclaimer.file.invalid", sDisclaimer); } else { // screenreader do not like iframes, display inline if (getWindowControl().getWindowBackOffice().getWindowManager().isForScreenReader()) { final HtmlStaticPageComponent disclaimerComp = new HtmlStaticPageComponent("disc", baseContainer); myContent.put("disc", disclaimerComp); disclaimerComp.setCurrentURI(sDisclaimer); myContent.contextPut("hasDisc", Boolean.TRUE); } else { iFrameCtr = new IFrameDisplayController(ureq, getWindowControl(), baseContainer); listenTo(iFrameCtr); // dispose automatically myContent.put("disc", iFrameCtr.getInitialComponent()); iFrameCtr.setCurrentURI(sDisclaimer); myContent.contextPut("hasDisc", Boolean.TRUE); } } } } // push title and learning objectives, only visible on intro page myContent.contextPut("menuTitle", courseNode.getShortTitle()); myContent.contextPut("displayTitle", courseNode.getLongTitle()); // Adding learning objectives final String learningObj = courseNode.getLearningObjectives(); if (learningObj != null) { final Component learningObjectives = ObjectivesHelper.createLearningObjectivesComponent(learningObj, ureq); myContent.put("learningObjectives", learningObjectives); myContent.contextPut("hasObjectives", learningObj); // dummy value, just an exists operator } if (type.equals(AssessmentInstance.QMD_ENTRY_TYPE_ASSESS)) { checkChats(ureq); singleUserEventCenter.registerFor(this, getIdentity(), chatEventOres); } }
public void buildDocument() { final File unzippedRoot = fileresourceManager.unzipFileResource(resourceable); // with VFS FIXME:pb:c: remove casts to LocalFileImpl and LocalFolderImpl if no longer needed. final VFSContainer vfsUnzippedRoot = new LocalFolderImpl(unzippedRoot); final VFSItem vfsQTI = vfsUnzippedRoot.resolve("qti.xml"); // getDocument(..) ensures that InputStream is closed in every case. document = QTIHelper.getDocument((LocalFileImpl) vfsQTI); }
/** * @param ureq * @param te */ public void switchToPage(final UserRequest ureq, final TreeEvent te) { // all treeevents receiced here are event clicked only // if (!te.getCommand().equals(TreeEvent.COMMAND_TREENODE_CLICKED)) throw // new AssertException("error"); // switch to the new page final String nodeId = te.getNodeId(); final TreeNode tn = ctm.getNodeById(nodeId); final String identifierRes = (String) tn.getUserObject(); // security check if (identifierRes.indexOf("../") != -1) { throw new AssertException( "a non-normalized url encountered in a manifest item:" + identifierRes); } // Check if path ends with .html, .htm or .xhtml. We do this by searching for "htm" // and accept positions of this string at length-3 or length-4 // Check also for XML resources that use XSLT for rendering if (identifierRes.toLowerCase().lastIndexOf(FILE_SUFFIX_HTM) >= (identifierRes.length() - 4) || identifierRes.toLowerCase().endsWith(FILE_SUFFIX_XML)) { // display html files inline or in an iframe if (cpContentCtr != null) { cpContentCtr.setCurrentURI(identifierRes); } if (cpComponent != null) { cpComponent.setCurrentURI(identifierRes); } } else { // Also display pdf and other files in the iframe if it has been // initialized. Delegates displaying to the browser (and its plugins). if (cpContentCtr != null) { cpContentCtr.setCurrentURI(identifierRes); } else { // if an entry in a manifest points e.g. to a pdf file and the iframe // controller has not been initialized display it non-inline final VFSItem currentItem = rootContainer.resolve(identifierRes); MediaResource mr; if (currentItem == null || !(currentItem instanceof VFSLeaf)) { mr = new NotFoundMediaResource(identifierRes); } else { mr = new VFSMediaResource((VFSLeaf) currentItem); } ureq.getDispatchResult().setResultingMediaResource(mr); // Prevent 'don't reload' warning cpTree.setDirty(false); } } ThreadLocalUserActivityLogger.log( CourseLoggingAction.CP_GET_FILE, getClass(), LoggingResourceable.wrapCpNode(identifierRes)); }
/** * @param ureq * @param cpRoot * @param showMenu * @param activateFirstPage */ CPDisplayController( final UserRequest ureq, final WindowControl wControl, final VFSContainer rootContainer, final boolean showMenu, final boolean activateFirstPage, final String initialUri, final OLATResourceable ores) { super(ureq, wControl); this.rootContainer = rootContainer; // wrapper velocity container for page content this.myContent = createVelocityContainer("cpDisplay"); // the cp component, added to the velocity if (!ureq.getUserSession().getRoles().isGuestOnly()) { final SearchServiceUIFactory searchServiceUIFactory = (SearchServiceUIFactory) CoreSpringFactory.getBean(SearchServiceUIFactory.class); searchCtrl = searchServiceUIFactory.createInputController(ureq, wControl, DisplayOption.BUTTON, null); myContent.put("search_input", searchCtrl.getInitialComponent()); } // TODO:gs:a // may add an additional config for disabling, enabling IFrame style or not in CP mode // but always disable IFrame display when in screenreader mode (no matter whether style gets // ugly) if (getWindowControl().getWindowBackOffice().getWindowManager().isForScreenReader()) { cpComponent = new HtmlStaticPageComponent("", rootContainer); cpComponent.addListener(this); myContent.put("cpContent", cpComponent); } else { cpContentCtr = new IFrameDisplayController(ureq, getWindowControl(), rootContainer, null, ores); cpContentCtr.setAllowDownload(true); listenTo(cpContentCtr); myContent.put("cpContent", cpContentCtr.getInitialComponent()); } // even if we do not show the menu, we need to build parse the manifest and // find the first node to display at startup final VFSItem mani = rootContainer.resolve("imsmanifest.xml"); if (mani == null || !(mani instanceof VFSLeaf)) { throw new OLATRuntimeException( "error.manifest.missing", null, this.getClass().getPackage().getName(), "CP " + rootContainer + " has no imsmanifest", null); } // initialize tree model in any case ctm = new CPManifestTreeModel((VFSLeaf) mani); if (showMenu) { // the menu is only initialized when needed. cpTree = new MenuTree("cpDisplayTree"); cpTree.setTreeModel(ctm); cpTree.addListener(this); } LoggingResourceable nodeInfo = null; if (activateFirstPage) { // set content to first accessible child or root node if no children // available TreeNode node = ctm.getRootNode(); if (node == null) { throw new OLATRuntimeException( CPDisplayController.class, "root node of content packaging was null, file:" + rootContainer, null); } while (node != null && !node.isAccessible()) { if (node.getChildCount() > 0) { node = (TreeNode) node.getChildAt(0); } else { node = null; } } if (node != null) { // node.isAccessible final String nodeUri = (String) node.getUserObject(); if (cpContentCtr != null) { cpContentCtr.setCurrentURI(nodeUri); } if (cpComponent != null) { cpComponent.setCurrentURI(nodeUri); } if (showMenu) { cpTree.setSelectedNodeId(node.getIdent()); } // activate the selected node in the menu (skips the root node that is // empty anyway and saves one user click) selNodeId = node.getIdent(); nodeInfo = LoggingResourceable.wrapCpNode(nodeUri); } } else if (initialUri != null) { // set page if (cpContentCtr != null) { cpContentCtr.setCurrentURI(initialUri); } if (cpComponent != null) { cpComponent.setCurrentURI(initialUri); } // update menu final TreeNode newNode = ctm.lookupTreeNodeByHref(initialUri); if (newNode != null) { // user clicked on a link which is listed in the // toc if (cpTree != null) { cpTree.setSelectedNodeId(newNode.getIdent()); } else { selNodeId = newNode.getIdent(); } } nodeInfo = LoggingResourceable.wrapCpNode(initialUri); } // Note: the ores has a typename of ICourse - see // CPCourseNode.createNodeRunConstructorResult // which has the following line: // OresHelper.createOLATResourceableInstance(ICourse.class, // userCourseEnv.getCourseEnvironment().getCourseResourceableId()); // therefore we use OresHelper.calculateTypeName(ICourse.class) here if (ores != null && nodeInfo != null && !OresHelper.calculateTypeName(ICourse.class).equals(ores.getResourceableTypeName())) { addLoggingResourceable(LoggingResourceable.wrap(ores, OlatResourceableType.cp)); ThreadLocalUserActivityLogger.log( LearningResourceLoggingAction.LEARNING_RESOURCE_OPEN, getClass(), nodeInfo); } putInitialPanel(myContent); }
/** * @param ureq * @param wControl * @param rootDir The VFS root directory from which the linkable files should be read * @param uploadRelPath The relative path within the rootDir where uploaded files should be put * into. If NULL, the root Dir is used * @param suffixes Array of allowed file types * @param fileName the path of the file currently edited (in order to compute the correct relative * paths for links), e.g. bla/blu.html or index.html */ public FileLinkChooserController( UserRequest ureq, WindowControl wControl, VFSContainer rootDir, String uploadRelPath, String[] suffixes, String fileName) { super(ureq, wControl); this.fileName = fileName; this.suffixes = suffixes; this.rootDir = rootDir; this.mainVC = createVelocityContainer("filechooser"); // file uploads are relative to the currently edited file String[] dirs = this.fileName.split("/"); VFSContainer fileUploadBase = rootDir; for (String subPath : dirs) { // try to resolve the given file path in the root container VFSItem subFolder = fileUploadBase.resolve(subPath); if (subFolder != null) { if (subFolder instanceof VFSContainer) { // a higher level found, use this one unless a better one is found fileUploadBase = (VFSContainer) subFolder; } else { // it is not a container - leaf reached break; } } else { // resolving was not possible??? stop here break; } } // create directory filter combined with suffix filter String[] dirFilters = {"_courseelementdata"}; VFSItemFilter customFilter = null; VFSItemFilter dirFilter = new VFSItemExcludePrefixFilter(dirFilters); if (suffixes != null) { VFSItemFileTypeFilter typeFilter = new VFSItemFileTypeFilter(suffixes); typeFilter.setCompositeFilter(dirFilter); customFilter = typeFilter; } else { customFilter = dirFilter; } // hide file chooser title, we have our own title fileChooserController = FileChooserUIFactory.createFileChooserControllerWithoutTitle( ureq, getWindowControl(), rootDir, customFilter, true); listenTo(fileChooserController); mainVC.put("stTree", fileChooserController.getInitialComponent()); // convert file endings to mime types as needed by file upload controller Set<String> mimeTypes = null; if (suffixes != null) { mimeTypes = new HashSet<String>(); for (String suffix : suffixes) { String mimeType = WebappHelper.getMimeType("dummy." + suffix); if (mimeType != null) { if (!mimeTypes.contains(mimeType)) mimeTypes.add(mimeType); } } } uploadCtr = new FileUploadController( wControl, fileUploadBase, ureq, (int) FolderConfig.getLimitULKB(), Quota.UNLIMITED, mimeTypes, true); listenTo(uploadCtr); // set specific upload path uploadCtr.setUploadRelPath(uploadRelPath); mainVC.put("uploader", uploadCtr.getInitialComponent()); putInitialPanel(mainVC); }