def testExport(self): # Delete the output dir outdir = TempDirPath() G.application = Application() G.application.loadConfiguration() G.application.preLaunch() # Load a package package = Package.load('testing/testPackage2.elp') # Do the export style_dir = G.application.config.stylesDir / package.style exporter = WebsiteExport(G.application.config, style_dir, outdir) exporter.export(package) # Check that it all exists now assert outdir.isdir() assert (outdir / 'index.html').isfile() # Check that the style sheets have been copied for filename in style_dir.files(): assert ((outdir / filename.basename()).exists(), 'Style file "%s" not copied' % (outdir / filename.basename())) # Check that each node in the package has had a page made pagenodes = Set([p.node for p in exporter.pages]) othernodes = Set(self._getNodes([], package.root)) assert pagenodes == othernodes for page in exporter.pages: self._testPage(page, outdir)
def export(self, package): """ Export SCORM package """ outputDir = TempDirPath() styleFiles = [self.styleDir/'..'/'base.css'] styleFiles += [self.styleDir/'..'/'popup_bg.gif'] styleFiles += self.styleDir.files("*.css") if "nav.css" in styleFiles: styleFiles.remove("nav.css") styleFiles += self.styleDir.files("*.jpg") styleFiles += self.styleDir.files("*.gif") styleFiles += self.styleDir.files("*.png") styleFiles += self.styleDir.files("*.js") styleFiles += self.styleDir.files("*.html") self.styleDir.copylist(styleFiles, outputDir) package.resourceDir.copyfiles(outputDir) self.pages = [ IMSPage("index", 1, package.root) ] self.generatePages(package.root, 2) uniquifyNames(self.pages) for page in self.pages: page.save(outputDir) manifest = Manifest(self.config, outputDir, package, self.pages) manifest.save() self.scriptsDir.copylist(('libot_drag.js', 'common.js'), outputDir) self.schemasDir.copylist(('imscp_v1p1.xsd', 'imsmd_v1p2p2.xsd', 'ims_xml.xsd'), outputDir) self.templatesDir.copylist(('videoContainer.swf', 'magnifier.swf', 'xspf_player.swf'),outputDir) (self.templatesDir/'fdl.html').copyfile(outputDir/'fdl.html') self.filename.safeSave(self.doZip, _('EXPORT FAILED!\nLast succesful export is %s.'), outputDir) outputDir.rmtree()
def exportZip(self, package): """ Export web site Cleans up the previous packages pages and performs the export """ outputDir = TempDirPath() self.copyFiles(package, outputDir) if (self.stylesDir/"websitepage.py").exists(): global WebsitePage module = imp.load_source("websitepage", self.stylesDir/"websitepage.py") WebsitePage = module.WebsitePage self.pages = [ WebsitePage("index", 1, package.root) ] self.generatePages(package.root, 1) uniquifyNames(self.pages) prevPage = None thisPage = self.pages[0] for nextPage in self.pages[1:]: thisPage.save(outputDir, prevPage, nextPage, self.pages) prevPage = thisPage thisPage = nextPage thisPage.save(outputDir, prevPage, None, self.pages) zipped = ZipFile(self.filename, "w") for scormFile in outputDir.files(): zipped.write(scormFile, scormFile.basename().encode('utf8'), ZIP_DEFLATED) zipped.close() outputDir.rmtree()
def testExport(self): # Delete the output dir outdir = TempDirPath() # Load a package package = Package.load('testPackage.elp') # Do the export exporter = WebsiteExport('../exe/webui/style/default', outdir, '../exe/webui/images', '../exe/webui/scripts', '../exe/webui/templates') exporter.export(package) # Check that it all exists now assert outdir.isdir() assert (outdir / 'index.html').isfile() # Check that the style sheets have been copied for filename in Path('../exe/webui/style/default').files(): assert ((outdir / filename.basename()).exists(), 'Style file "%s" not copied' % (outdir / filename.basename())) # Check that each node in the package has had a page made pagenodes = Set([p.node for p in exporter.pages]) othernodes = Set(self._getNodes([], package.root)) assert pagenodes == othernodes for page in exporter.pages: self._testPage(page, outdir)
def __init__(self, name): """ Initialize """ log.debug(u"init " + repr(name)) self._nextIdeviceId = 0 self._nextNodeId = 0 # For looking up nodes by ids self._nodeIdDict = {} self._levelNames = self.defaultLevelNames[:] self.name = name self._title = u'' self._backgroundImg = u'' self.backgroundImgTile = False # Empty if never saved/loaded self.filename = u'' self.root = Node(self, None, _(u"Home")) self.currentNode = self.root self.style = u"default" self.isChanged = False self.idevices = [] self.dublinCore = DublinCore() self.scolinks = False self.license = "None" self.footer = "" # Temporary directory to hold resources in self.resourceDir = TempDirPath() self.resources = {} # Checksum-[_Resource(),..]
def exportZip(self, package): """ Export web site Cleans up the previous packages pages and performs the export """ outputDir = TempDirPath() # Import the Website Page class. If the style has it's own page class # use that, else use the default one. if (self.stylesDir/"websitepage.py").exists(): global WebsitePage module = imp.load_source("websitepage", self.stylesDir/"websitepage.py") WebsitePage = module.WebsitePage self.pages = [ WebsitePage("index", 1, package.root) ] self.generatePages(package.root, 1) uniquifyNames(self.pages) prevPage = None thisPage = self.pages[0] for nextPage in self.pages[1:]: thisPage.save(outputDir, prevPage, nextPage, self.pages) prevPage = thisPage thisPage = nextPage thisPage.save(outputDir, prevPage, None, self.pages) self.copyFiles(package, outputDir) # Zip up the website package self.filename.safeSave(self.doZip, _('EXPORT FAILED!\nLast succesful export is %s.'), outputDir) # Clean up the temporary dir outputDir.rmtree()
def export(self, package): """ Export SCORM package """ outputDir = TempDirPath() styleFiles = [self.styleDir/'..'/'base.css'] styleFiles += [self.styleDir/'..'/'popup_bg.gif'] styleFiles += self.styleDir.files("*.css") if "nav.css" in styleFiles: styleFiles.remove("nav.css") styleFiles += self.styleDir.files("*.jpg") styleFiles += self.styleDir.files("*.gif") styleFiles += self.styleDir.files("*.png") styleFiles += self.styleDir.files("*.js") styleFiles += self.styleDir.files("*.html") self.styleDir.copylist(styleFiles, outputDir) package.resourceDir.copyfiles(outputDir) self.pages = [ ScormPage("index", 1, package.root) ] self.generatePages(package.root, 2) uniquifyNames(self.pages) for page in self.pages: page.save(outputDir) if not self.hasForum: for idevice in page.node.idevices: if hasattr(idevice, "isForum"): if idevice.forum.lms.lms == "moodle": self.hasForum = True break manifest = Manifest(self.config, outputDir, package, self.pages, self.scormType) manifest.save("imsmanifest.xml") if self.hasForum: manifest.save("discussionforum.xml") self.scriptsDir.copylist(('APIWrapper.js', 'imscp_rootv1p1p2.xsd', 'imsmd_rootv1p2p1.xsd', 'ims_xml.xsd', 'adlcp_rootv1p2.xsd', 'SCOFunctions.js', 'libot_drag.js', 'common.js'), outputDir) self.templatesDir.copylist(('videoContainer.swf', 'magnifier.swf', 'xspf_player.swf'),outputDir) (self.templatesDir/'fdl.html').copyfile(outputDir/'fdl.html') zipped = ZipFile(self.filename, "w") for scormFile in outputDir.files(): zipped.write(scormFile, scormFile.basename().encode('utf8'), ZIP_DEFLATED) zipped.close() outputDir.rmtree()
def __init__(self, name): """ Initialize """ log.debug(u"init " + repr(name)) self._nextIdeviceId = 0 self._nextNodeId = 0 self._nodeIdDict = {} self._levelNames = self.defaultLevelNames[:] self.name = name self._title = u'' self._backgroundImg = u'' self.backgroundImgTile = False self.filename = u'' self.root = Node(self, None, _(u"Home")) self.currentNode = self.root self.style = u"default" self.isChanged = False self.idevices = [] self.dublinCore = DublinCore() self.scolinks = False self.license = "None" self.footer = "" self.resourceDir = TempDirPath() self.resources = {} # Checksum-[_Resource(),..]
def __init__(self, name): """ Initialize """ log.debug(u"init " + repr(name)) self._nextIdeviceId = 0 self._nextNodeId = 0 # For looking up nodes by ids self._nodeIdDict = {} self._levelNames = self.defaultLevelNames[:] self.name = name self._title = u"" self._backgroundImg = u"" self.backgroundImgTile = False # Empty if never saved/loaded self.filename = u"" self.root = Node(self, None, _(u"Home")) self.currentNode = self.root self.style = u"default" self.isChanged = False self.idevices = [] self.dublinCore = DublinCore() self.scolinks = False self.license = "None" self.footer = "" # Temporary directory to hold resources in self.resourceDir = TempDirPath() self.resources = {} # Checksum-[_Resource(),..]
def testExport(self): outdir = TempDirPath() package = Package.load('testPackage.elp') exporter = WebsiteExport('../exe/webui/style/default', outdir, '../exe/webui/images', '../exe/webui/scripts', '../exe/webui/templates') exporter.export(package) assert outdir.isdir() assert (outdir / 'index.html').isfile() for filename in Path('../exe/webui/style/default').files(): assert ((outdir / filename.basename()).exists(), 'Style file "%s" not copied' % (outdir / filename.basename())) pagenodes = Set([p.node for p in exporter.pages]) othernodes = Set(self._getNodes([], package.root)) assert pagenodes == othernodes for page in exporter.pages: self._testPage(page, outdir)
def export(self, package): """ Export SCORM package """ outputDir = TempDirPath() styleFiles = [self.styleDir/'..'/'base.css'] styleFiles += [self.styleDir/'..'/'popup_bg.gif'] styleFiles += self.styleDir.files("*.css") if "nav.css" in styleFiles: styleFiles.remove("nav.css") styleFiles += self.styleDir.files("*.jpg") styleFiles += self.styleDir.files("*.gif") styleFiles += self.styleDir.files("*.png") styleFiles += self.styleDir.files("*.js") styleFiles += self.styleDir.files("*.html") self.styleDir.copylist(styleFiles, outputDir) package.resourceDir.copyfiles(outputDir) self.pages = [ IMSPage("index", 1, package.root) ] self.generatePages(package.root, 2) uniquifyNames(self.pages) for page in self.pages: page.save(outputDir) manifest = Manifest(self.config, outputDir, package, self.pages) manifest.save() self.scriptsDir.copylist(('libot_drag.js', 'imscp_v1p1.xsd', 'imsmd_v1p2p2.xsd', 'ims_xml.xsd', 'common.js'), outputDir) self.templatesDir.copylist(('videoContainer.swf', 'magnifier.swf', 'xspf_player.swf'),outputDir) (self.templatesDir/'fdl.html').copyfile(outputDir/'fdl.html') zipped = ZipFile(self.filename, "w") for scormFile in outputDir.files(): zipped.write(scormFile, scormFile.basename().encode('utf8'), ZIP_DEFLATED) zipped.close() outputDir.rmtree()
def __init__(self, name): """ Initialize """ log.debug(u"init " + repr(name)) self._nextIdeviceId = 0 self._nextNodeId = 0 self._nodeIdDict = {} self._levelNames = [x_(u"Topic"), x_(u"Section"), x_(u"Unit")] self.name = name self._title = u'' self.filename = u'' self.root = Node(self, None, _(u"Home")) self.currentNode = self.root self.style = u"default" self.isChanged = 0 self.idevices = [] self.dublinCore = DublinCore() self.resourceDir = TempDirPath()
def export(self, package): """ Export SCORM package """ # First do the export to a temporary directory outputDir = TempDirPath() # Export the package content self.pages = [ ScormPage("index", 1, package.root, scormType=self.scormType) ] self.generatePages(package.root, 2) uniquifyNames(self.pages) for page in self.pages: page.save(outputDir) if not self.hasForum: for idevice in page.node.idevices: if hasattr(idevice, "isForum"): if idevice.forum.lms.lms == "moodle": self.hasForum = True break # Create the manifest file manifest = Manifest(self.config, outputDir, package, self.pages, self.scormType) manifest.save("imsmanifest.xml") if self.hasForum: manifest.save("discussionforum.xml") # Copy the style sheet files to the output dir # But not nav.css styleFiles = [self.styleDir / '..' / 'base.css'] styleFiles += [self.styleDir / '..' / 'popup_bg.gif'] styleFiles += [ f for f in self.styleDir.files("*.css") if f.basename() <> "nav.css" ] styleFiles += self.styleDir.files("*.jpg") styleFiles += self.styleDir.files("*.gif") styleFiles += self.styleDir.files("*.png") styleFiles += self.styleDir.files("*.js") styleFiles += self.styleDir.files("*.html") # FIXME for now, only copy files referenced in Common Cartridge # this really should apply to all exports, but without a manifest # of the files needed by an included stylesheet it is too restrictive if self.scormType == "commoncartridge": for sf in styleFiles[:]: if sf.basename() not in manifest.dependencies: styleFiles.remove(sf) self.styleDir.copylist(styleFiles, outputDir) # copy the package's resource files package.resourceDir.copyfiles(outputDir) # Copy the scripts if self.scormType == "commoncartridge": self.scriptsDir.copylist(('libot_drag.js', 'common.js'), outputDir) else: self.scriptsDir.copylist(('APIWrapper.js', 'SCOFunctions.js', 'libot_drag.js', 'common.js'), outputDir) schemasDir = "" if self.scormType == "scorm1.2": schemasDir = self.schemasDir / "scorm1.2" schemasDir.copylist( ('imscp_rootv1p1p2.xsd', 'imsmd_rootv1p2p1.xsd', 'adlcp_rootv1p2.xsd', 'ims_xml.xsd'), outputDir) elif self.scormType == "scorm2004": schemasDir = self.schemasDir / "scorm2004" schemasDir.copylist( ('imscp_rootv1p1p2.xsd', 'imsmd_rootv1p2p1.xsd', 'adlcp_rootv1p2.xsd', 'ims_xml.xsd'), outputDir) # copy players for media idevices. hasFlowplayer = False hasMagnifier = False hasXspfplayer = False isBreak = False for page in self.pages: if isBreak: break for idevice in page.node.idevices: if (hasFlowplayer and hasMagnifier and hasXspfplayer): isBreak = True break if not hasFlowplayer: if 'flowPlayer.swf' in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if 'magnifier.swf' in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if 'xspf_player.swf' in idevice.systemResources: hasXspfplayer = True if hasFlowplayer: videofile = (self.templatesDir / 'flowPlayer.swf') videofile.copyfile(outputDir / 'flowPlayer.swf') if hasMagnifier: videofile = (self.templatesDir / 'magnifier.swf') videofile.copyfile(outputDir / 'magnifier.swf') if hasXspfplayer: videofile = (self.templatesDir / 'xspf_player.swf') videofile.copyfile(outputDir / 'xspf_player.swf') if self.scormType == "scorm1.2" or self.scormType == "scorm2004": if package.license == "GNU Free Documentation License": # include a copy of the GNU Free Documentation Licence (self.templatesDir / 'fdl.html').copyfile(outputDir / 'fdl.html') # Zip it up! self.filename.safeSave( self.doZip, _('EXPORT FAILED!\nLast succesful export is %s.'), outputDir) # Clean up the temporary dir outputDir.rmtree()
def export(self, package): """ Export SCORM package """ # First do the export to a temporary directory outputDir = TempDirPath() # Export the package content self.pages = [ ScormPage("index", 1, package.root, scormType=self.scormType) ] self.generatePages(package.root, 2) uniquifyNames(self.pages) for page in self.pages: page.save(outputDir) if not self.hasForum: for idevice in page.node.idevices: if hasattr(idevice, "isForum"): if idevice.forum.lms.lms == "moodle": self.hasForum = True break # Create the manifest file manifest = Manifest(self.config, outputDir, package, self.pages, self.scormType) manifest.save("imsmanifest.xml") if self.hasForum: manifest.save("discussionforum.xml") # Copy the style sheet files to the output dir # But not nav.css styleFiles = [self.styleDir/'..'/'base.css'] styleFiles += [self.styleDir/'..'/'popup_bg.gif'] styleFiles += [f for f in self.styleDir.files("*.css") if f.basename() <> "nav.css"] styleFiles += self.styleDir.files("*.jpg") styleFiles += self.styleDir.files("*.gif") styleFiles += self.styleDir.files("*.png") styleFiles += self.styleDir.files("*.js") styleFiles += self.styleDir.files("*.html") # FIXME for now, only copy files referenced in Common Cartridge # this really should apply to all exports, but without a manifest # of the files needed by an included stylesheet it is too restrictive if self.scormType == "commoncartridge": for sf in styleFiles[:]: if sf.basename() not in manifest.dependencies: styleFiles.remove(sf) self.styleDir.copylist(styleFiles, outputDir) # copy the package's resource files package.resourceDir.copyfiles(outputDir) # Copy the scripts if self.scormType == "commoncartridge": self.scriptsDir.copylist(('libot_drag.js', 'common.js'), outputDir) else: self.scriptsDir.copylist(('APIWrapper.js', 'SCOFunctions.js', 'libot_drag.js', 'common.js'), outputDir) schemasDir = "" if self.scormType == "scorm1.2": schemasDir = self.schemasDir/"scorm1.2" schemasDir.copylist(('imscp_rootv1p1p2.xsd', 'imsmd_rootv1p2p1.xsd', 'adlcp_rootv1p2.xsd', 'ims_xml.xsd'), outputDir) elif self.scormType == "scorm2004": schemasDir = self.schemasDir/"scorm2004" schemasDir.copylist(('imscp_rootv1p1p2.xsd', 'imsmd_rootv1p2p1.xsd', 'adlcp_rootv1p2.xsd', 'ims_xml.xsd'), outputDir) # copy players for media idevices. hasFlowplayer = False hasMagnifier = False hasXspfplayer = False isBreak = False for page in self.pages: if isBreak: break for idevice in page.node.idevices: if (hasFlowplayer and hasMagnifier and hasXspfplayer): isBreak = True break if not hasFlowplayer: if 'flowPlayer.swf' in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if 'magnifier.swf' in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if 'xspf_player.swf' in idevice.systemResources: hasXspfplayer = True if hasFlowplayer: videofile = (self.templatesDir/'flowPlayer.swf') videofile.copyfile(outputDir/'flowPlayer.swf') if hasMagnifier: videofile = (self.templatesDir/'magnifier.swf') videofile.copyfile(outputDir/'magnifier.swf') if hasXspfplayer: videofile = (self.templatesDir/'xspf_player.swf') videofile.copyfile(outputDir/'xspf_player.swf') if self.scormType == "scorm1.2" or self.scormType == "scorm2004": if package.license == "GNU Free Documentation License": # include a copy of the GNU Free Documentation Licence (self.templatesDir/'fdl.html').copyfile(outputDir/'fdl.html') # Zip it up! self.filename.safeSave(self.doZip, _('EXPORT FAILED!\nLast succesful export is %s.'), outputDir) # Clean up the temporary dir outputDir.rmtree()
def export(self, package): """ Export SCORM package """ # First do the export to a temporary directory outputDir = TempDirPath() self.metadataType = package.exportMetadataType # Copy the style files to the output dir # But not nav.css styleFiles = [self.styleDir/'..'/'popup_bg.gif'] styleFiles += self.styleDir.files("*.*") if "nav.css" in styleFiles: styleFiles.remove("nav.css") self.styleDir.copylist(styleFiles, outputDir) # copy the package's resource files for resourceFile in package.resourceDir.walkfiles(): file = package.resourceDir.relpathto(resourceFile) if ("/" in file): Dir = Path(outputDir/file[:file.rindex("/")]) if not Dir.exists(): Dir.makedirs() resourceFile.copy(outputDir/Dir) else: resourceFile.copy(outputDir) listCSSFiles=getFilesCSSToMinify('ims', self.styleDir) exportMinFileCSS(listCSSFiles, outputDir) # Export the package content self.pages = [ IMSPage("index", 1, package.root, metadataType=self.metadataType) ] self.generatePages(package.root, 2) uniquifyNames(self.pages) for page in self.pages: page.save(outputDir, self.pages) # Create the manifest file manifest = Manifest(self.config, outputDir, package, self.pages, self.metadataType) manifest.save("imsmanifest.xml") # Create lang file langGameFile = open(outputDir + '/common_i18n.js', "w") langGameFile.write(common.getJavaScriptStrings(False)) langGameFile.close() # jQuery my_style = G.application.config.styleStore.getStyle(page.node.package.style) if my_style.hasValidConfig(): if my_style.get_jquery() == True: jsFile = (self.scriptsDir/'exe_jquery.js') jsFile.copyfile(outputDir/'exe_jquery.js') else: jsFile = (self.scriptsDir/'exe_jquery.js') jsFile.copyfile(outputDir/'exe_jquery.js') dT = common.getExportDocType() if dT == "HTML5": jsFile = (self.scriptsDir/'exe_html5.js') jsFile.copyfile(outputDir/'exe_html5.js') listFiles=getFilesJSToMinify('ims', self.scriptsDir) exportMinFileJS(listFiles, outputDir) self.schemasDir.copylist(('imscp_v1p1.xsd', 'imsmd_v1p2p2.xsd', 'lom.xsd', 'lomCustom.xsd', 'ims_xml.xsd'), outputDir) # copy players for media idevices. hasFlowplayer = False hasMagnifier = False hasXspfplayer = False hasGallery = False hasFX = False hasSH = False hasGames = False hasElpLink = False hasWikipedia = False isBreak = False hasInstructions = False hasMediaelement = False hasTooltips = False hasABCMusic = False listIdevicesFiles = [] for page in self.pages: if isBreak: break for idevice in page.node.idevices: if (hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery and hasFX and hasSH and hasGames and hasElpLink and hasWikipedia and hasInstructions and hasMediaelement and hasTooltips and hasABCMusic): isBreak = True break if not hasFlowplayer: if 'flowPlayer.swf' in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if 'mojomagnify.js' in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if 'xspf_player.swf' in idevice.systemResources: hasXspfplayer = True if not hasGallery: hasGallery = common.ideviceHasGallery(idevice) if not hasFX: hasFX = common.ideviceHasFX(idevice) if not hasSH: hasSH = common.ideviceHasSH(idevice) if not hasGames: hasGames = common.ideviceHasGames(idevice) if not hasElpLink: hasElpLink = common.ideviceHasElpLink(idevice,package) if not hasWikipedia: if 'WikipediaIdevice' == idevice.klass: hasWikipedia = True if not hasInstructions: if 'TrueFalseIdevice' == idevice.klass or 'MultichoiceIdevice' == idevice.klass or 'VerdaderofalsofpdIdevice' == idevice.klass or 'EleccionmultiplefpdIdevice' == idevice.klass: hasInstructions = True if not hasMediaelement: hasMediaelement = common.ideviceHasMediaelement(idevice) if not hasTooltips: hasTooltips = common.ideviceHasTooltips(idevice) if not hasABCMusic: hasABCMusic = common.ideviceHasABCMusic(idevice) if hasattr(idevice, "_iDeviceDir"): listIdevicesFiles.append((idevice.get_jsidevice_dir()/'export')) common.exportJavaScriptIdevicesFiles(page.node.idevices, outputDir); if hasFlowplayer: videofile = (self.templatesDir/'flowPlayer.swf') videofile.copyfile(outputDir/'flowPlayer.swf') controlsfile = (self.templatesDir/'flowplayer.controls.swf') controlsfile.copyfile(outputDir/'flowplayer.controls.swf') if hasMagnifier: videofile = (self.templatesDir/'mojomagnify.js') videofile.copyfile(outputDir/'mojomagnify.js') if hasXspfplayer: videofile = (self.templatesDir/'xspf_player.swf') videofile.copyfile(outputDir/'xspf_player.swf') if hasGallery: exeLightbox = (self.scriptsDir/'exe_lightbox') exeLightbox.copyfiles(outputDir) if hasFX: exeEffects = (self.scriptsDir/'exe_effects') exeEffects.copyfiles(outputDir) if hasSH: exeSH = (self.scriptsDir/'exe_highlighter') exeSH.copyfiles(outputDir) if hasGames: exeGames = (self.scriptsDir/'exe_games') exeGames.copyfiles(outputDir) # Add game js string to common_i18n langGameFile = open(outputDir + '/common_i18n.js', "a") langGameFile.write(common.getGamesJavaScriptStrings(False)) langGameFile.close() if hasElpLink or package.get_exportElp(): # Export the elp file currentPackagePath = Path(package.filename) currentPackagePath.copyfile(outputDir/package.name+'.elp') if hasWikipedia: wikipediaCSS = (self.cssDir/'exe_wikipedia.css') wikipediaCSS.copyfile(outputDir/'exe_wikipedia.css') if hasInstructions: common.copyFileIfNotInStyle('panel-amusements.png', self, outputDir) common.copyFileIfNotInStyle('stock-stop.png', self, outputDir) if hasMediaelement: mediaelement = (self.scriptsDir/'mediaelement') mediaelement.copyfiles(outputDir) if dT != "HTML5": jsFile = (self.scriptsDir/'exe_html5.js') jsFile.copyfile(outputDir/'exe_html5.js') if hasTooltips: exe_tooltips = (self.scriptsDir/'exe_tooltips') exe_tooltips.copyfiles(outputDir) if hasABCMusic: pluginScripts = (self.scriptsDir/'tinymce_4/js/tinymce/plugins/abcmusic/export') pluginScripts.copyfiles(outputDir) if hasattr(package, 'exportSource') and package.exportSource: (G.application.config.webDir/'templates'/'content.xsd').copyfile(outputDir/'content.xsd') (outputDir/'content.data').write_bytes(encodeObject(package)) (outputDir/'contentv3.xml').write_bytes(encodeObjectToXML(package)) if package.license == "license GFDL": # include a copy of the GNU Free Documentation Licence (self.templatesDir/'fdl.html').copyfile(outputDir/'fdl.html') # Zip it up! self.filename.safeSave(self.doZip, _('EXPORT FAILED!\nLast succesful export is %s.'), outputDir) # Clean up the temporary dir outputDir.rmtree()
def export(self, package): """ Export SCORM package """ # First do the export to a temporary directory outputDir = TempDirPath() self.metadataType = package.exportMetadataType # copy the package's resource files package.resourceDir.copyfiles(outputDir) # copy the package's resource files, only non existant in outputDir # outputDirFiles = outputDir.files() # for rfile in package.resourceDir.files(): # if rfile not in outputDirFiles: # rfile.copy(outputDir) # copy the package's resource files, only indexed in package.resources # for md5 in package.resources.values(): # for resource in md5: # resource.path.copy(outputDir) # Export the package content # Import the Scorm Page class , if the secure mode is off. If the style has it's own page class # use that, else use the default one. if self.styleSecureMode == "0": if (self.styleDir / "scormpage.py").exists(): global ScormPage module = imp.load_source("ScormPage", self.styleDir / "scormpage.py") ScormPage = module.ScormPage self.pages = [ScormPage("index", 1, package.root, scormType=self.scormType, metadataType=self.metadataType)] self.generatePages(package.root, 2) uniquifyNames(self.pages) for page in self.pages: page.save(outputDir) if not self.hasForum: for idevice in page.node.idevices: if hasattr(idevice, "isForum"): if idevice.forum.lms.lms == "moodle": self.hasForum = True break # Create the manifest file manifest = Manifest(self.config, outputDir, package, self.pages, self.scormType, self.metadataType) manifest.save("imsmanifest.xml") if self.hasForum: manifest.save("discussionforum.xml") # Copy the style sheet files to the output dir styleFiles = [self.styleDir / ".." / "base.css"] styleFiles += [self.styleDir / ".." / "popup_bg.gif"] # And with all the files of the style we avoid problems: styleFiles += self.styleDir.files("*.*") if self.scormType == "commoncartridge": for sf in styleFiles[:]: if sf.basename() not in manifest.dependencies: styleFiles.remove(sf) self.styleDir.copylist(styleFiles, outputDir) # Copy the scripts dT = common.getExportDocType() if dT == "HTML5": jsFile = self.scriptsDir / "exe_html5.js" jsFile.copyfile(outputDir / "exe_html5.js") # jQuery my_style = G.application.config.styleStore.getStyle(page.node.package.style) if my_style.hasValidConfig: if my_style.get_jquery() == True: jsFile = self.scriptsDir / "exe_jquery.js" jsFile.copyfile(outputDir / "exe_jquery.js") else: jsFile = self.scriptsDir / "exe_jquery.js" jsFile.copyfile(outputDir / "exe_jquery.js") if self.scormType == "commoncartridge": jsFile = self.scriptsDir / "common.js" jsFile.copyfile(outputDir / "common.js") if self.scormType == "scorm2004" or self.scormType == "scorm1.2": self.scriptsDir.copylist(("SCORM_API_wrapper.js", "SCOFunctions.js", "common.js"), outputDir) # about SCHEMAS: schemasDir = "" if self.scormType == "scorm1.2": schemasDir = self.schemasDir / "scorm1.2" schemasDir.copylist( ( "imscp_rootv1p1p2.xsd", "imsmd_rootv1p2p1.xsd", "adlcp_rootv1p2.xsd", "lom.xsd", "lomCustom.xsd", "ims_xml.xsd", ), outputDir, ) elif self.scormType == "scorm2004": schemasDir = self.schemasDir / "scorm2004" schemasDir.copylist( ( "adlcp_v1p3.xsd", "adlnav_v1p3.xsd", "adlseq_v1p3.xsd", "datatypes.dtd", "imscp_v1p1.xsd", "imsssp_v1p0.xsd", "imsss_v1p0.xsd", "imsss_v1p0auxresource.xsd", "imsss_v1p0control.xsd", "imsss_v1p0delivery.xsd", "imsmd_rootv1p2p1.xsd", "imsss_v1p0limit.xsd", "imsss_v1p0objective.xsd", "imsss_v1p0random.xsd", "imsss_v1p0rollup.xsd", "imsss_v1p0seqrule.xsd", "imsss_v1p0util.xsd", "ims_xml.xsd", "lom.xsd", "lomCustom.xsd", "xml.xsd", "XMLSchema.dtd", ), outputDir, ) try: import shutil, errno shutil.copytree(schemasDir / "common", outputDir / "common") shutil.copytree(schemasDir / "extend", outputDir / "extend") shutil.copytree(schemasDir / "unique", outputDir / "unique") shutil.copytree(schemasDir / "vocab", outputDir / "vocab") except OSError as exc: if exc.errno == errno.ENOTDIR: shutil.copy(schemasDir, outputDir) else: raise # copy players for media idevices. hasFlowplayer = False hasMagnifier = False hasXspfplayer = False hasGallery = False hasWikipedia = False isBreak = False hasInstructions = False hasMediaelement = False for page in self.pages: if isBreak: break for idevice in page.node.idevices: if ( hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery and hasWikipedia and hasInstructions and hasMediaelement ): isBreak = True break if not hasFlowplayer: if "flowPlayer.swf" in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if "mojomagnify.js" in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if "xspf_player.swf" in idevice.systemResources: hasXspfplayer = True if not hasGallery: hasGallery = common.ideviceHasGallery(idevice) if not hasWikipedia: if "WikipediaIdevice" == idevice.klass: hasWikipedia = True if not hasInstructions: if ( "TrueFalseIdevice" == idevice.klass or "MultichoiceIdevice" == idevice.klass or "VerdaderofalsofpdIdevice" == idevice.klass or "EleccionmultiplefpdIdevice" == idevice.klass ): hasInstructions = True if not hasMediaelement: hasMediaelement = common.ideviceHasMediaelement(idevice) if hasFlowplayer: videofile = self.templatesDir / "flowPlayer.swf" videofile.copyfile(outputDir / "flowPlayer.swf") controlsfile = self.templatesDir / "flowplayer.controls.swf" controlsfile.copyfile(outputDir / "flowplayer.controls.swf") if hasMagnifier: videofile = self.templatesDir / "mojomagnify.js" videofile.copyfile(outputDir / "mojomagnify.js") if hasXspfplayer: videofile = self.templatesDir / "xspf_player.swf" videofile.copyfile(outputDir / "xspf_player.swf") if hasGallery: imageGalleryCSS = self.cssDir / "exe_lightbox.css" imageGalleryCSS.copyfile(outputDir / "exe_lightbox.css") imageGalleryJS = self.scriptsDir / "exe_lightbox.js" imageGalleryJS.copyfile(outputDir / "exe_lightbox.js") self.imagesDir.copylist( ( "exe_lightbox_close.png", "exe_lightbox_loading.gif", "exe_lightbox_next.png", "exe_lightbox_prev.png", ), outputDir, ) if hasWikipedia: wikipediaCSS = self.cssDir / "exe_wikipedia.css" wikipediaCSS.copyfile(outputDir / "exe_wikipedia.css") if hasInstructions: common.copyFileIfNotInStyle("panel-amusements.png", self, outputDir) common.copyFileIfNotInStyle("stock-stop.png", self, outputDir) if hasMediaelement: mediaelement = self.scriptsDir / "mediaelement" mediaelement.copyfiles(outputDir) if dT != "HTML5": jsFile = self.scriptsDir / "exe_html5.js" if self.scormType == "scorm1.2" or self.scormType == "scorm2004": if package.license == "license GFDL": # include a copy of the GNU Free Documentation Licence (self.templatesDir / "fdl.html").copyfile(outputDir / "fdl.html") if hasattr(package, "scowsinglepage") and package.scowsinglepage: page = SinglePage("singlepage_index", 1, package.root) page.save(outputDir / "singlepage_index.html") # Incluide eXe's icon if the Style doesn't have one themePath = Path(G.application.config.stylesDir / package.style) themeFavicon = themePath.joinpath("favicon.ico") if not themeFavicon.exists(): faviconFile = self.imagesDir / "favicon.ico" faviconFile.copyfile(outputDir / "favicon.ico") if hasattr(package, "scowwebsite") and package.scowwebsite: website = WebsiteExport(self.config, self.styleDir, outputDir, "website_") website.export(package) (self.styleDir / "nav.css").copyfile(outputDir / "nav.css") # Incluide eXe's icon if the Style doesn't have one themePath = Path(G.application.config.stylesDir / package.style) themeFavicon = themePath.joinpath("favicon.ico") if not themeFavicon.exists(): faviconFile = self.imagesDir / "favicon.ico" faviconFile.copyfile(outputDir / "favicon.ico") if hasattr(package, "exportSource") and package.exportSource: (G.application.config.webDir / "templates" / "content.xsd").copyfile(outputDir / "content.xsd") (outputDir / "content.data").write_bytes(encodeObject(package)) (outputDir / "contentv3.xml").write_bytes(encodeObjectToXML(package)) # Zip it up! self.filename.safeSave(self.doZip, _("EXPORT FAILED!\nLast succesful export is %s."), outputDir) # Clean up the temporary dir outputDir.rmtree()
def export(self, package): """ Export epub 3 package """ # First do the export to a temporary directory outputDir = TempDirPath() ''' fileDir = outputDir/"META-INF" fileDir.mkdir() fileDir = outputDir/"Content" fileDir.mkdir() ''' metainfPages = Path(outputDir.abspath() + '/META-INF') # metainfPages = outputDir/'META-INF' metainfPages.mkdir() contentPages = Path(outputDir.abspath() + '/EPUB') # contentPages = outputDir/'Content' contentPages.mkdir() # print contentPages.abspath() # print outputDir.abspath() # Export the package content self.pages = [Epub3Cover("cover", 1, package.root)] self.generatePages(package.root, 2) uniquifyNames(self.pages) cover = None for page in self.pages: page.save(contentPages) if hasattr(page, 'cover'): cover = page.cover # Create mimetype file mimetypeFile = open(outputDir.abspath() + '/mimetype', "w") mimetypeFile.write('application/epub+zip') mimetypeFile.close() # Copy the style sheet files to the output dir # But not nav.css styleFiles = [self.styleDir / '..' / 'base.css'] styleFiles += [self.styleDir / '..' / 'popup_bg.gif'] styleFiles += [f for f in self.styleDir.files("*.css") if f.basename() != "nav.css"] styleFiles += self.styleDir.files("*.jpg") styleFiles += self.styleDir.files("*.gif") styleFiles += self.styleDir.files("*.png") styleFiles += self.styleDir.files("*.js") styleFiles += self.styleDir.files("*.html") styleFiles += self.styleDir.files("*.ttf") styleFiles += self.styleDir.files("*.eot") styleFiles += self.styleDir.files("*.otf") styleFiles += self.styleDir.files("*.woff") # FIXME for now, only copy files referenced in Common Cartridge # this really should apply to all exports, but without a manifest # of the files needed by an included stylesheet it is too restrictive package.resourceDir.copyfiles(contentPages) self.styleDir.copylist(styleFiles, contentPages) self.scriptsDir.copylist(('common.js',), contentPages) # copy players for media idevices. hasFlowplayer = False hasMagnifier = False hasXspfplayer = False hasGallery = False hasFX = False hasGames = False hasWikipedia = False isBreak = False hasInstructions = False hasTooltips = False for page in self.pages: if isBreak: break for idevice in page.node.idevices: if (hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery and hasFX and hasGames and hasWikipedia): isBreak = True break if not hasFlowplayer: if 'flowPlayer.swf' in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if 'mojomagnify.js' in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if 'xspf_player.swf' in idevice.systemResources: hasXspfplayer = True if not hasGallery: hasGallery = common.ideviceHasGallery(idevice) if not hasFX: hasFX = common.ideviceHasFX(idevice) if not hasGames: hasGames = common.ideviceHasGames(idevice) if not hasWikipedia: if 'WikipediaIdevice' == idevice.klass: hasWikipedia = True if not hasInstructions: if 'TrueFalseIdevice' == idevice.klass or 'MultichoiceIdevice' == idevice.klass or 'VerdaderofalsofpdIdevice' == idevice.klass or 'EleccionmultiplefpdIdevice' == idevice.klass: hasInstructions = True if not hasTooltips: hasTooltips = common.ideviceHasTooltips(idevice) if hasFlowplayer: videofile = (self.templatesDir / 'flowPlayer.swf') videofile.copyfile(contentPages / 'flowPlayer.swf') controlsfile = (self.templatesDir / 'flowplayer.controls.swf') controlsfile.copyfile(contentPages / 'flowplayer.controls.swf') if hasMagnifier: videofile = (self.templatesDir / 'mojomagnify.js') videofile.copyfile(contentPages / 'mojomagnify.js') if hasXspfplayer: videofile = (self.templatesDir / 'xspf_player.swf') videofile.copyfile(contentPages / 'xspf_player.swf') if hasGallery: exeLightbox = (self.scriptsDir / 'exe_lightbox') exeLightbox.copyfiles(contentPages) if hasFX: exeEffects = (self.scriptsDir / 'exe_effects') exeEffects.copyfiles(contentPages) if hasGames: exeGames = (self.scriptsDir / 'exe_games') exeGames.copyfiles(contentPages) if hasWikipedia: wikipediaCSS = (self.cssDir / 'exe_wikipedia.css') wikipediaCSS.copyfile(contentPages / 'exe_wikipedia.css') if hasInstructions: common.copyFileIfNotInStyle('panel-amusements.png', self, contentPages) common.copyFileIfNotInStyle('stock-stop.png', self, contentPages) if hasTooltips: exe_tooltips = (self.scriptsDir / 'exe_tooltips') exe_tooltips.copyfiles(contentPages) my_style = G.application.config.styleStore.getStyle(package.style) if my_style.hasValidConfig: if my_style.get_jquery() == True: jsFile = (self.scriptsDir / 'exe_jquery.js') jsFile.copyfile(contentPages / 'exe_jquery.js') else: jsFile = (self.scriptsDir / 'exe_jquery.js') jsFile.copyfile(contentPages / 'exe_jquery.js') # if hasattr(package, 'exportSource') and package.exportSource: # (G.application.config.webDir / 'templates' / 'content.xsd').copyfile(outputDir / 'content.xsd') # (outputDir / 'content.data').write_bytes(encodeObject(package)) # (outputDir / 'contentv3.xml').write_bytes(encodeObjectToXML(package)) if package.license == "license GFDL": # include a copy of the GNU Free Documentation Licence (self.templatesDir / 'fdl.html').copyfile(contentPages / 'fdl.html') # Create the nav.xhtml file container = NavEpub3(self.pages, contentPages) container.save() # Create the publication file publication = PublicationEpub3(self.config, contentPages, package, self.pages, cover) publication.save("package.opf") # Create the container file container = ContainerEpub3(metainfPages) container.save("container.xml") # Zip it up! self.filename.safeSave(self.doZip, _(u'EXPORT FAILED!\nLast succesful export is %s.'), outputDir) # Clean up the temporary dir outputDir.rmtree()
class Package(Persistable): """ Package represents the collection of resources the user is editing i.e. the "package". """ persistenceVersion = 9 nonpersistant = ["resourceDir", "filename"] # Name is used in filenames and urls (saving and navigating) _name = "" tempFile = False # This is set when the package is saved as a temp copy file # Title is rendered in exports _title = "" _author = "" _description = "" _backgroundImg = "" # This is like a constant defaultLevelNames = [x_(u"Topic"), x_(u"Section"), x_(u"Unit")] def __init__(self, name): """ Initialize """ log.debug(u"init " + repr(name)) self._nextIdeviceId = 0 self._nextNodeId = 0 # For looking up nodes by ids self._nodeIdDict = {} self._levelNames = self.defaultLevelNames[:] self.name = name self._title = u"" self._backgroundImg = u"" self.backgroundImgTile = False # Empty if never saved/loaded self.filename = u"" self.root = Node(self, None, _(u"Home")) self.currentNode = self.root self.style = u"default" self.isChanged = False self.idevices = [] self.dublinCore = DublinCore() self.scolinks = False self.license = "None" self.footer = "" # Temporary directory to hold resources in self.resourceDir = TempDirPath() self.resources = {} # Checksum-[_Resource(),..] # Property Handlers def set_name(self, value): self._name = toUnicode(value) def set_title(self, value): self._title = toUnicode(value) def set_author(self, value): self._author = toUnicode(value) def set_description(self, value): self._description = toUnicode(value) def get_backgroundImg(self): """Get the background image for this package""" if self._backgroundImg: return "file://" + self._backgroundImg.path else: return "" def set_backgroundImg(self, value): """Set the background image for this package""" if self._backgroundImg: self._backgroundImg.delete() if value: if value.startswith("file://"): value = value[7:] imgFile = Path(value) self._backgroundImg = Resource(self, Path(imgFile)) else: self._backgroundImg = u"" def get_level1(self): return self.levelName(0) def set_level1(self, value): if value != "": self._levelNames[0] = value else: self._levelNames[0] = self.defaultLevelNames[0] def get_level2(self): return self.levelName(1) def set_level2(self, value): if value != "": self._levelNames[1] = value else: self._levelNames[1] = self.defaultLevelNames[1] def get_level3(self): return self.levelName(2) def set_level3(self, value): if value != "": self._levelNames[2] = value else: self._levelNames[2] = self.defaultLevelNames[2] # Properties name = property(lambda self: self._name, set_name) title = property(lambda self: self._title, set_title) author = property(lambda self: self._author, set_author) description = property(lambda self: self._description, set_description) backgroundImg = property(get_backgroundImg, set_backgroundImg) level1 = property(get_level1, set_level1) level2 = property(get_level2, set_level2) level3 = property(get_level3, set_level3) def findNode(self, nodeId): """ Finds a node from its nodeId (nodeId can be a string or a list/tuple) """ log.debug(u"findNode" + repr(nodeId)) node = self._nodeIdDict.get(nodeId) if node and node.package is self: return node else: return None def levelName(self, level): """ Return the level name """ if level < len(self._levelNames): return _(self._levelNames[level]) else: return _(u"?????") def save(self, filename=None, tempFile=False): """ Save package to disk pass an optional filename """ self.tempFile = tempFile # Get the filename if filename: filename = Path(filename) # If we are being given a new filename... # Change our name to match our new filename name = filename.splitpath()[1] if not tempFile: self.name = name.basename().splitext()[0] elif self.filename: # Otherwise use our last saved/loaded from filename filename = Path(self.filename) else: # If we don't have a last saved/loaded from filename, # raise an exception because, we need to have a new # file passed when a brand new package is saved raise AssertionError(u"No name passed when saving a new package") # Store our new filename for next file|save, and save the package log.debug(u"Will save %s to: %s" % (self.name, filename)) if tempFile: self.nonpersistant.remove("filename") oldFilename, self.filename = self.filename, unicode(self.filename) try: filename.safeSave(self.doSave, _("SAVE FAILED!\nLast succesful save is %s.")) finally: self.nonpersistant.append("filename") self.filename = oldFilename else: # Update our new filename for future saves self.filename = filename filename.safeSave(self.doSave, _("SAVE FAILED!\nLast succesful save is %s.")) self.isChanged = False self.updateRecentDocuments(filename) def updateRecentDocuments(self, filename): """ Updates the list of recent documents """ # Don't update the list for the generic.data "package" genericData = G.application.config.configDir / "idevices" / "generic.data" if genericData.isfile() or genericData.islink(): if Path(filename).samefile(genericData): return # Save in recentDocuments list recentProjects = G.application.config.recentProjects if filename in recentProjects: # If we're already number one, carry on if recentProjects[0] == filename: return recentProjects.remove(filename) recentProjects.insert(0, filename) del recentProjects[5:] # Delete any older names from the list G.application.config.configParser.write() # Save the settings def doSave(self, fileObj): """ Actually performs the save to 'fileObj'. """ zippedFile = zipfile.ZipFile(fileObj, "w", zipfile.ZIP_DEFLATED) try: for resourceFile in self.resourceDir.files(): zippedFile.write( unicode(resourceFile.normpath()), resourceFile.name.encode("utf8"), zipfile.ZIP_DEFLATED ) zinfo = zipfile.ZipInfo(filename="content.data", date_time=time.localtime()[0:6]) zinfo.external_attr = 0100644 << 16L zippedFile.writestr(zinfo, encodeObject(self)) finally: zippedFile.close() def extractNode(self): """ Clones and extracts the currently selected node into a new package. """ newPackage = Package("NoName") # Name will be set once it is saved.. newPackage.title = self.currentNode.title newPackage.style = self.style newPackage.author = self.author newPackage._nextNodeId = self._nextNodeId # Copy the nodes from the original package # and merge into the root of the new package self.currentNode.copyToPackage(newPackage) return newPackage @staticmethod def load(filename, newLoad=True, destinationPackage=None): """ Load package from disk, returns a package. """ if not zipfile.is_zipfile(filename): return None zippedFile = zipfile.ZipFile(filename, "r") try: # Get the jellied package data toDecode = zippedFile.read(u"content.data") except KeyError: log.info("no content.data, trying Common Cartridge/Content Package") newPackage = loadCC(zippedFile, filename) newPackage.tempFile = False newPackage.isChanged = False newPackage.filename = Path(filename) return newPackage # Need to add a TempDirPath because it is a nonpersistant member resourceDir = TempDirPath() # Extract resource files from package to temporary directory for fn in zippedFile.namelist(): if unicode(fn, "utf8") != u"content.data": outFile = open(resourceDir / fn, "wb") outFile.write(zippedFile.read(fn)) outFile.flush() outFile.close() try: newPackage = decodeObjectRaw(toDecode) G.application.afterUpgradeHandlers = [] newPackage.resourceDir = resourceDir G.application.afterUpgradeZombies2Delete = [] if newLoad: # provide newPackage to doUpgrade's versionUpgrade() to # correct old corrupt extracted packages by setting the # any corrupt package references to the new package: log.debug('load() about to doUpgrade newPackage "' + newPackage._name + '" ' + repr(newPackage)) if hasattr(newPackage, "resourceDir"): log.debug("newPackage resourceDir = " + newPackage.resourceDir) else: # even though it was just set above? should not get here: log.error("newPackage resourceDir has NO resourceDir!") doUpgrade(newPackage) # after doUpgrade, compare the largest found field ID: if G.application.maxFieldId >= Field.nextId: Field.nextId = G.application.maxFieldId + 1 else: # and when merging, automatically set package references to # the destinationPackage, into which this is being merged: log.debug( 'load() about to merge doUpgrade newPackage "' + newPackage._name + '" ' + repr(newPackage) + ' INTO destinationPackage "' + destinationPackage._name + '" ' + repr(destinationPackage) ) log.debug("using their resourceDirs:") if hasattr(newPackage, "resourceDir"): log.debug(" newPackage resourceDir = " + newPackage.resourceDir) else: log.error("newPackage has NO resourceDir!") if hasattr(destinationPackage, "resourceDir"): log.debug(" destinationPackage resourceDir = " + destinationPackage.resourceDir) else: log.error("destinationPackage has NO resourceDir!") doUpgrade(destinationPackage, isMerge=True, preMergePackage=newPackage) # after doUpgrade, compare the largest found field ID: if G.application.maxFieldId >= Field.nextId: Field.nextId = G.application.maxFieldId + 1 except: import traceback traceback.print_exc() raise if newPackage.tempFile: # newPackage.filename was stored as it's original filename newPackage.tempFile = False else: # newPackage.filename is the name that the package was last loaded from # or saved to newPackage.filename = Path(filename) # Let idevices and nodes handle any resource upgrading they may need to # Note: Package afterUpgradeHandlers *must* be done after Resources' # and the package should be updated before everything else, # so, prioritize with a 3-pass, 3-level calling setup # in order of: 1) resources, 2) package, 3) anything other objects for handler_priority in range(3): for handler in G.application.afterUpgradeHandlers: if handler_priority == 0 and repr(handler.im_class) == "<class 'exe.engine.resource.Resource'>": # level-0 handlers: Resource handler() elif handler_priority == 1 and repr(handler.im_class) == "<class 'exe.engine.package.Package'>": # level-1 handlers: Package (requires resources first) if handler.im_self == newPackage: handler() else: log.warn("Extra package object found, " + "ignoring its afterUpgradeHandler: " + repr(handler)) elif ( handler_priority == 2 and repr(handler.im_class) != "<class 'exe.engine.resource.Resource'>" and repr(handler.im_class) != "<class 'exe.engine.package.Package'>" ): # level-2 handlers: all others handler() G.application.afterUpgradeHandlers = [] num_zombies = len(G.application.afterUpgradeZombies2Delete) for i in range(num_zombies - 1, -1, -1): zombie = G.application.afterUpgradeZombies2Delete[i] # now, the zombie list can contain nodes OR resources to delete. # if zombie is a node, then also pass in a pruning parameter.. zombie_is_node = False if isinstance(zombie, Node): zombie_is_node = True if zombie_is_node: zombie.delete(pruningZombies=True) else: zombie.delete() del zombie G.application.afterUpgradeZombies2Delete = [] newPackage.updateRecentDocuments(newPackage.filename) newPackage.isChanged = False return newPackage def cleanUpResources(self): """ Removes duplicate resource files """ # Delete unused resources. # Only really needed for upgrading to version 0.20, # but upgrading of resources and package happens in no particular order # and must be done after all resources have been upgraded # some earlier .elp files appear to have been corrupted with # two packages loaded, *possibly* from some strange extract/merge # functionality in earlier eXe versions? # Regardless, only the real package will have a resourceDir, # and the other will fail. # For now, then, put in this quick and easy safety check: if not hasattr(self, "resourceDir"): log.warn("cleanUpResources called on a redundant package") return existingFiles = set([fn.basename() for fn in self.resourceDir.files()]) usedFiles = set([reses[0].storageName for reses in self.resources.values()]) for fn in existingFiles - usedFiles: (self.resourceDir / fn).remove() def findResourceByName(self, queryName): """ Support for merging, and anywhere else that unique names might be checked before actually comparing against the files (as will be done by the resource class itself in its _addOurselvesToPackage() ) """ foundResource = None queryResources = self.resources for this_checksum in queryResources: for this_resource in queryResources[this_checksum]: if queryName == this_resource.storageName: foundResource = this_resource return foundResource return foundResource def upgradeToVersion1(self): """ Called to upgrade from 0.3 release """ self._nextNodeId = 0 self._nodeIdDict = {} # Also upgrade all the nodes. # This needs to be done here so that draft gets id 0 # If it's done in the nodes, the ids are assigned in reverse order draft = getattr(self, "draft") draft._id = self._regNewNode(draft) draft._package = self setattr(self, "editor", Node(self, None, _(u"iDevice Editor"))) # Add a default idevice to the editor idevice = GenericIdevice("", "", "", "", "") editor = getattr(self, "editor") idevice.parentNode = editor editor.addIdevice(idevice) def superReg(node): """Registers all our nodes because in v0 they were not registered in this way""" node._id = self._regNewNode(node) node._package = self for child in node.children: superReg(child) superReg(self.root) def _regNewNode(self, node): """ Called only by nodes, stores the node in our id lookup dict returns a new unique id """ id_ = unicode(self._nextNodeId) self._nextNodeId += 1 self._nodeIdDict[id_] = node return id_ def getNewIdeviceId(self): """ Returns an iDevice Id which is unique for this package. """ id_ = unicode(self._nextIdeviceId) self._nextIdeviceId += 1 return id_ def upgradeToVersion2(self): """ Called to upgrade from 0.4 release """ getattr(self, "draft").delete() getattr(self, "editor").delete() delattr(self, "draft") delattr(self, "editor") # Need to renumber nodes because idevice node and draft nodes are gone self._nextNodeId = 0 def renumberNode(node): """ Gives the old node a number """ node._id = self._regNewNode(node) for child in node.children: renumberNode(child) renumberNode(self.root) def upgradeToVersion3(self): """ Also called to upgrade from 0.4 release """ self._nextIdeviceId = 0 def upgradeToVersion4(self): """ Puts properties in their place Also called to upgrade from 0.8 release """ self._name = toUnicode(self.__dict__["name"]) self._author = toUnicode(self.__dict__["author"]) self._description = toUnicode(self.__dict__["description"]) def upgradeToVersion5(self): """ For version 0.11 """ self._levelNames = self.levelNames del self.levelNames def upgradeToVersion6(self): """ For version 0.14 """ self.dublinCore = DublinCore() # Copy some of the package properties to dublin core self.title = self.root.title self.dublinCore.title = self.root.title self.dublinCore.creator = self._author self.dublinCore.description = self._description self.scolinks = False def upgradeToVersion7(self): """ For version 0.15 """ self._backgroundImg = "" self.backgroundImgTile = False def upgradeToVersion8(self): """ For version 0.20, alpha, for nightlies r2469 """ self.license = "None" self.footer = "" self.idevices = [] def upgradeToVersion9(self): """ For version >= 0.20.4 """ if not hasattr(self, "resources"): # The hasattr is needed, because sometimes, Resource instances are upgraded # first and they also set this attribute on the package self.resources = {} G.application.afterUpgradeHandlers.append(self.cleanUpResources)
def main(): if len(sys.argv) < 2: print 'Usage: %s [version] [--install] [--local|username password]' % sys.argv[0] print 'Where [version] is the branch you want to checkout' print 'and username and password are for your eduforge account' print 'Eg. %s 0.7 --local' % sys.argv[0] else: version = sys.argv[1] # Calc the svn branch name branch = 'http://exe.cfdl.auckland.ac.nz/svn/exe/branches/%s' % version # Get the original exe dir origDir = Path(sys.argv[0]).abspath().dirname() # Make the temp dir tmp = TempDirPath() os.chdir(tmp) # Do the export os.system('svn export %s exe' % branch) # Copy firefox accross (origDir/'../../exe/webui/firefox').copytree(tmp/'exe/exe/webui/firefox') # Now make the tarball os.chdir(tmp/'exe') tarball = Path('../exe-%s-source.tgz' % version).abspath() os.system('tar czf %s *' % tarball) os.chdir(tmp) # Upload it if '--local' not in sys.argv: # Connect with sftp try: from paramiko import Transport except ImportError: print 'To upload you need to install paramiko python library from:' print 'http://www.lag.net/paramiko' sys.exit(2) from socket import socket, gethostbyname s = socket() s.connect((gethostbyname('shell.eduforge.org'), 22)) t = Transport(s) t.connect() t.auth_password(sys.argv[-2], sys.argv[-1]) f = t.open_sftp_client() # See that the directory structure looks good f.chdir('/home/pub/exe') f.put(tarball.encode('utf8'), tarball.basename().encode('utf8')) # If we're root, copy the tarball to the portage cache dir to save # downloading it when emerging (for me anyway) if os.getuid() == 0: tarball.copyfile('/usr/portage/distfiles/' + tarball.basename()) # Copy the ebuild file os.chdir(tmp/'exe/installs/gentoo') newEbuildFilename = Path('exe-%s.ebuild' % version).abspath() if not newEbuildFilename.exists(): Path('exe-0.7.ebuild').copy(newEbuildFilename) # If we're root, rebuild the digests and remake the install if os.getuid() == 0: ebuildDir = Path('/usr/local/portage/dev-python/exe') if ebuildDir.exists(): ebuildDir.rmtree() ebuildDir.makedirs() os.chdir(ebuildDir) newEbuildFilename.copy(ebuildDir) # Copy the patch file filesDir = ebuildDir/'files' filesDir.makedirs() Path(tmp/'exe/installs/gentoo/all-config.patch').copy(filesDir) # Remove any old source if it exists and we're supposed to download # it if '--local' not in sys.argv: oldTarball = Path('/usr/portage/distfiles/')/tarball.basename() if oldTarball.exists(): oldTarball.remove() os.environ['GENTOO_MIRRORS']='' os.system('ebuild %s fetch' % newEbuildFilename.basename()) os.system('ebuild %s manifest' % newEbuildFilename.basename()) os.system('ebuild %s digest' % newEbuildFilename.basename()) if '--install' in sys.argv: os.system('ebuild %s install' % newEbuildFilename.basename())
def export(self, package): """ Export SCORM package """ # First do the export to a temporary directory outputDir = TempDirPath() self.metadataType = package.exportMetadataType # copy the package's resource files for resourceFile in package.resourceDir.walkfiles(): file = package.resourceDir.relpathto(resourceFile) if ("/" in file): Dir = Path(outputDir/file[:file.rindex("/")]) if not Dir.exists(): Dir.makedirs() resourceFile.copy(outputDir/Dir) else: resourceFile.copy(outputDir) # copy the package's resource files, only non existant in outputDir # outputDirFiles = outputDir.files() # for rfile in package.resourceDir.files(): # if rfile not in outputDirFiles: # rfile.copy(outputDir) # copy the package's resource files, only indexed in package.resources # for md5 in package.resources.values(): # for resource in md5: # resource.path.copy(outputDir) # Export the package content # Import the Scorm Page class , if the secure mode is off. If the style has it's own page class # use that, else use the default one. if self.styleSecureMode=="0": if (self.styleDir/"scormpage.py").exists(): global ScormPage module = imp.load_source("ScormPage",self.styleDir/"scormpage.py") ScormPage = module.ScormPage self.pages = [ ScormPage("index", 1, package.root, scormType=self.scormType, metadataType=self.metadataType) ] self.generatePages(package.root, 2) uniquifyNames(self.pages) for page in self.pages: page.save(outputDir, self.pages) if not self.hasForum: for idevice in page.node.idevices: if hasattr(idevice, "isForum"): if idevice.forum.lms.lms == "moodle": self.hasForum = True break # Create the manifest file manifest = Manifest(self.config, outputDir, package, self.pages, self.scormType, self.metadataType) modifiedMetaData = manifest.save("imsmanifest.xml") # Create lang file langFile = open(outputDir + '/common_i18n.js', "w") langFile.write(common.getJavaScriptStrings(False)) langFile.close() if self.hasForum: manifest.save("discussionforum.xml") # Copy the style files to the output dir styleFiles = [self.styleDir/'..'/'popup_bg.gif'] # And with all the files of the style we avoid problems: styleFiles += self.styleDir.files("*.*") if self.scormType == "commoncartridge": for sf in styleFiles[:]: if sf.basename() not in manifest.dependencies: styleFiles.remove(sf) self.styleDir.copylist(styleFiles, outputDir) listCSSFiles=getFilesCSSToMinify('scorm', self.styleDir) exportMinFileCSS(listCSSFiles, outputDir) # Copy the scripts dT = common.getExportDocType() if dT == "HTML5": #listFiles+=[self.scriptsDir/'exe_html5.js'] #listOutFiles+=[outputDir/'exe_html5.js'] jsFile = (self.scriptsDir/'exe_html5.js') jsFile.copyfile(outputDir/'exe_html5.js') # jQuery my_style = G.application.config.styleStore.getStyle(page.node.package.style) if my_style.hasValidConfig: if my_style.get_jquery() == True: #listFiles+=[self.scriptsDir/'exe_jquery.js'] #listOutFiles+=[outputDir/'exe_jquery.js'] jsFile = (self.scriptsDir/'exe_jquery.js') jsFile.copyfile(outputDir/'exe_jquery.js') else: #listFiles+=[self.scriptsDir/'exe_jquery.js'] #listOutFiles+=[outputDir/'exe_jquery.js'] jsFile = (self.scriptsDir/'exe_jquery.js') jsFile.copyfile(outputDir/'exe_jquery.js') if self.scormType == "commoncartridge" or self.scormType == "scorm2004" or self.scormType == "scorm1.2": listFiles=getFilesJSToMinify('scorm', self.scriptsDir) exportMinFileJS(listFiles, outputDir) if self.scormType == "scorm2004" or self.scormType == "scorm1.2": self.scriptsDir.copylist(('SCORM_API_wrapper.js', 'SCOFunctions.js'), outputDir) # about SCHEMAS: schemasDir = "" if self.scormType == "scorm1.2": schemasDir = self.schemasDir/"scorm1.2" schemasDir.copylist(('imscp_rootv1p1p2.xsd', 'imsmd_rootv1p2p1.xsd', 'adlcp_rootv1p2.xsd', 'lom.xsd', 'lomCustom.xsd', 'ims_xml.xsd'), outputDir) elif self.scormType == "scorm2004": schemasDir = self.schemasDir/"scorm2004" schemasDir.copylist(('adlcp_v1p3.xsd', 'adlnav_v1p3.xsd', 'adlseq_v1p3.xsd', 'datatypes.dtd', 'imscp_v1p1.xsd', 'imsssp_v1p0.xsd', 'imsss_v1p0.xsd', 'imsss_v1p0auxresource.xsd', 'imsss_v1p0control.xsd', 'imsss_v1p0delivery.xsd', 'imsmd_rootv1p2p1.xsd', 'imsss_v1p0limit.xsd', 'imsss_v1p0objective.xsd', 'imsss_v1p0random.xsd', 'imsss_v1p0rollup.xsd', 'imsss_v1p0seqrule.xsd', 'imsss_v1p0util.xsd', 'ims_xml.xsd', 'lom.xsd', 'lomCustom.xsd', 'xml.xsd', 'XMLSchema.dtd'), outputDir) try: import shutil, errno shutil.copytree(schemasDir/"common", outputDir/"common") shutil.copytree(schemasDir/"extend", outputDir/"extend") shutil.copytree(schemasDir/"unique", outputDir/"unique") shutil.copytree(schemasDir/"vocab", outputDir/"vocab") except OSError as exc: if exc.errno == errno.ENOTDIR: shutil.copy(schemasDir, outputDir) else: raise # copy players for media idevices. hasFlowplayer = False hasMagnifier = False hasXspfplayer = False hasGallery = False hasFX = False hasSH = False hasGames = False hasElpLink = False hasWikipedia = False isBreak = False hasInstructions = False hasMediaelement = False hasTooltips = False hasABCMusic = False listIdevicesFiles = [] for page in self.pages: if isBreak: break for idevice in page.node.idevices: if (hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery and hasFX and hasSH and hasGames and hasElpLink and hasWikipedia and hasInstructions and hasMediaelement and hasTooltips and hasABCMusic): isBreak = True break if not hasFlowplayer: if 'flowPlayer.swf' in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if 'mojomagnify.js' in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if 'xspf_player.swf' in idevice.systemResources: hasXspfplayer = True if not hasGallery: hasGallery = common.ideviceHasGallery(idevice) if not hasFX: hasFX = common.ideviceHasFX(idevice) if not hasSH: hasSH = common.ideviceHasSH(idevice) if not hasGames: hasGames = common.ideviceHasGames(idevice) if not hasElpLink: hasElpLink = common.ideviceHasElpLink(idevice,package) if not hasWikipedia: if 'WikipediaIdevice' == idevice.klass: hasWikipedia = True if not hasInstructions: if 'TrueFalseIdevice' == idevice.klass or 'MultichoiceIdevice' == idevice.klass or 'VerdaderofalsofpdIdevice' == idevice.klass or 'EleccionmultiplefpdIdevice' == idevice.klass: hasInstructions = True if not hasMediaelement: hasMediaelement = common.ideviceHasMediaelement(idevice) if not hasTooltips: hasTooltips = common.ideviceHasTooltips(idevice) if not hasABCMusic: hasABCMusic = common.ideviceHasABCMusic(idevice) if hasattr(idevice, "_iDeviceDir"): listIdevicesFiles.append((Path(idevice._iDeviceDir)/'export')) common.exportJavaScriptIdevicesFiles(page.node.idevices, outputDir); if hasFlowplayer: videofile = (self.templatesDir/'flowPlayer.swf') videofile.copyfile(outputDir/'flowPlayer.swf') controlsfile = (self.templatesDir/'flowplayer.controls.swf') controlsfile.copyfile(outputDir/'flowplayer.controls.swf') if hasMagnifier: videofile = (self.templatesDir/'mojomagnify.js') videofile.copyfile(outputDir/'mojomagnify.js') if hasXspfplayer: videofile = (self.templatesDir/'xspf_player.swf') videofile.copyfile(outputDir/'xspf_player.swf') if hasGallery: exeLightbox = (self.scriptsDir/'exe_lightbox') exeLightbox.copyfiles(outputDir) if hasFX: exeEffects = (self.scriptsDir/'exe_effects') exeEffects.copyfiles(outputDir) if hasSH: exeSH = (self.scriptsDir/'exe_highlighter') exeSH.copyfiles(outputDir) if hasGames: exeGames = (self.scriptsDir/'exe_games') exeGames.copyfiles(outputDir) # Add game js string to common_i18n langGameFile = open(outputDir + '/common_i18n.js', "a") langGameFile.write(common.getGamesJavaScriptStrings(False)) langGameFile.close() if hasElpLink or package.get_exportElp(): # Export the elp file currentPackagePath = Path(package.filename) currentPackagePath.copyfile(outputDir/package.name+'.elp') if hasWikipedia: wikipediaCSS = (self.cssDir/'exe_wikipedia.css') wikipediaCSS.copyfile(outputDir/'exe_wikipedia.css') if hasInstructions: common.copyFileIfNotInStyle('panel-amusements.png', self, outputDir) common.copyFileIfNotInStyle('stock-stop.png', self, outputDir) if hasMediaelement: mediaelement = (self.scriptsDir/'mediaelement') mediaelement.copyfiles(outputDir) if dT != "HTML5": jsFile = (self.scriptsDir/'exe_html5.js') if hasTooltips: exe_tooltips = (self.scriptsDir/'exe_tooltips') exe_tooltips.copyfiles(outputDir) if hasABCMusic: pluginScripts = (self.scriptsDir/'tinymce_4/js/tinymce/plugins/abcmusic/export') pluginScripts.copyfiles(outputDir) ext = ".html" if G.application.config.cutFileName == "1": ext = ".htm" if self.scormType == "scorm1.2" or self.scormType == "scorm2004": if package.license == "license GFDL": # include a copy of the GNU Free Documentation Licence (self.templatesDir/'fdl' + ext).copyfile(outputDir/'fdl' + ext) if hasattr(package, 'scowsinglepage') and package.scowsinglepage: page = SinglePage("singlepage_index", 1, package.root) page.save(outputDir/"singlepage_index" + ext) # Incluide eXe's icon if the Style doesn't have one themePath = Path(G.application.config.stylesDir/package.style) themeFavicon = themePath.joinpath("favicon.ico") if not themeFavicon.exists(): faviconFile = (self.imagesDir/'favicon.ico') faviconFile.copyfile(outputDir/'favicon.ico') if hasattr(package, 'scowwebsite') and package.scowwebsite: website = WebsiteExport(self.config, self.styleDir, outputDir, "website_") website.export(package) (self.styleDir/'nav.css').copyfile(outputDir/'nav.css') # Incluide eXe's icon if the Style doesn't have one themePath = Path(G.application.config.stylesDir/package.style) themeFavicon = themePath.joinpath("favicon.ico") if not themeFavicon.exists(): faviconFile = (self.imagesDir/'favicon.ico') faviconFile.copyfile(outputDir/'favicon.ico') if hasattr(package, 'exportSource') and package.exportSource: (G.application.config.webDir/'templates'/'content.xsd').copyfile(outputDir/'content.xsd') (outputDir/'content.data').write_bytes(encodeObject(package)) (outputDir/'contentv3.xml').write_bytes(encodeObjectToXML(package)) # Zip it up! self.filename.safeSave(self.doZip, _('EXPORT FAILED!\nLast succesful export is %s.'), outputDir) # Clean up the temporary dir outputDir.rmtree() return modifiedMetaData
def export(self, package): """ Export SCORM package """ outputDir = TempDirPath() styleFiles = [self.styleDir / ".." / "base.css"] styleFiles += [self.styleDir / ".." / "popup_bg.gif"] styleFiles += self.styleDir.files("*.css") if "nav.css" in styleFiles: styleFiles.remove("nav.css") styleFiles += self.styleDir.files("*.jpg") styleFiles += self.styleDir.files("*.gif") styleFiles += self.styleDir.files("*.png") styleFiles += self.styleDir.files("*.js") styleFiles += self.styleDir.files("*.html") self.styleDir.copylist(styleFiles, outputDir) package.resourceDir.copyfiles(outputDir) self.pages = [ScormPage("index", 1, package.root, scormType=self.scormType)] self.generatePages(package.root, 2) uniquifyNames(self.pages) for page in self.pages: page.save(outputDir) if not self.hasForum: for idevice in page.node.idevices: if hasattr(idevice, "isForum"): if idevice.forum.lms.lms == "moodle": self.hasForum = True break manifest = Manifest(self.config, outputDir, package, self.pages, self.scormType) manifest.save("imsmanifest.xml") if self.hasForum: manifest.save("discussionforum.xml") self.scriptsDir.copylist(("APIWrapper.js", "SCOFunctions.js", "libot_drag.js", "common.js"), outputDir) schemasDir = "" if self.scormType == "scorm1.2": schemasDir = self.schemasDir / "scorm1.2" schemasDir.copylist( ("imscp_rootv1p1p2.xsd", "imsmd_rootv1p2p1.xsd", "adlcp_rootv1p2.xsd", "ims_xml.xsd"), outputDir ) elif self.scormType == "scorm2004": schemasDir = self.schemasDir / "scorm2004" schemasDir.copylist( ("imscp_rootv1p1p2.xsd", "imsmd_rootv1p2p1.xsd", "adlcp_rootv1p2.xsd", "ims_xml.xsd"), outputDir ) hasFlowplayer = False hasMagnifier = False hasXspfplayer = False isBreak = False for page in self.pages: if isBreak: break for idevice in page.node.idevices: if hasFlowplayer and hasMagnifier and hasXspfplayer: isBreak = True break if not hasFlowplayer: if "flowPlayer.swf" in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if "magnifier.swf" in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if "xspf_player.swf" in idevice.systemResources: hasXspfplayer = True if hasFlowplayer: videofile = self.templatesDir / "flowPlayer.swf" videofile.copyfile(outputDir / "flowPlayer.swf") if hasMagnifier: videofile = self.templatesDir / "magnifier.swf" videofile.copyfile(outputDir / "magnifier.swf") if hasXspfplayer: videofile = self.templatesDir / "xspf_player.swf" videofile.copyfile(outputDir / "xspf_player.swf") if self.scormType == "scorm1.2" or self.scormType == "scorm2004": (self.templatesDir / "fdl.html").copyfile(outputDir / "fdl.html") self.filename.safeSave(self.doZip, _("EXPORT FAILED!\nLast succesful export is %s."), outputDir) outputDir.rmtree()
class WikipediaIdevice(Idevice): """ A Wikipedia Idevice is one built from a Wikipedia article. """ persistenceVersion = 8 def __init__(self, defaultSite): Idevice.__init__(self, x_(u"Wiki Article"), x_(u"University of Auckland"), x_(u"""<p>The Wikipedia iDevice allows you to locate existing content from within Wikipedia and download this content into your eXe resource. The Wikipedia Article iDevice takes a snapshot copy of the article content. Changes in Wikipedia will not automatically update individual snapshot copies in eXe, a fresh copy of the article will need to be taken. Likewise, changes made in eXe will not be updated in Wikipedia. </p> <p>Wikipedia content is covered by the GNU free documentation license.</p>"""), u"", u"") self.emphasis = Idevice.NoEmphasis self.articleName = u"" self.article = TextAreaField(x_(u"Article")) self.article.idevice = self self.images = {} self.site = defaultSite self.icon = u"inter" self.systemResources += ["fdl.html"] self._langInstruc = x_(u"""Select the appropriate language version of Wikipedia to search and enter search term.""") self._searchInstruc = x_("""Enter a phrase or term you wish to search within Wikipedia.""") self.ownUrl = "" # Properties langInstruc = lateTranslate('langInstruc') searchInstruc = lateTranslate('searchInstruc') def loadArticle(self, name): """ Load the article from Wikipedia """ self.articleName = name url = "" name = urllib.quote(name.replace(" ", "_").encode('utf-8')) try: url = (self.site or self.ownUrl) if not url.endswith('/') and name <> '': url += '/' if '://' not in url: url = 'http://' + url url += name net = urllib.urlopen(url) page = net.read() net.close() except IOError, error: log.warning(unicode(error)) self.article.content = _(u"Unable to download from %s <br/>Please check the spelling and connection and try again.") % url self.article.content_w_resourcePaths = self.article.content self.article.content_wo_resourcePaths = self.article.content return page = unicode(page, "utf8") # FIXME avoid problems with numeric entities in attributes page = page.replace(u' ', u' ') # avoidParserProblems is set to False because BeautifulSoup's # cleanup was causing a "concatenating Null+Str" error, # and Wikipedia's HTML doesn't need cleaning up. # BeautifulSoup is faster this way too. soup = BeautifulSoup(page, False) content = soup.first('div', {'id': "content"}) # remove the wiktionary, wikimedia commons, and categories boxes # and the protected icon and the needs citations box if content: infoboxes = content.findAll('div', {'class' : 'infobox sisterproject'}) [infobox.extract() for infobox in infoboxes] catboxes = content.findAll('div', {'id' : 'catlinks'}) [catbox.extract() for catbox in catboxes] amboxes = content.findAll('table', {'class' : re.compile(r'.*\bambox\b.*')}) [ambox.extract() for ambox in amboxes] protecteds = content.findAll('div', {'id' : 'protected-icon'}) [protected.extract() for protected in protecteds] else: content = soup.first('body') if not content: log.error("no content") self.article.content = _(u"Unable to download from %s <br/>Please check the spelling and connection and try again.") % url # set the other elements as well self.article.content_w_resourcePaths = self.article.content self.article.content_wo_resourcePaths = self.article.content return # clear out any old images while self.userResources: self.userResources[0].delete() self.images = {} # Download the images bits = url.split('/') netloc = '%s//%s' % (bits[0], bits[2]) path = '/'.join(bits[3:-1]) tmpDir = TempDirPath() for imageTag in content.fetch('img'): imageSrc = unicode(imageTag['src']) imageName = imageSrc.split('/')[-1] # Search if we've already got this image if imageName not in self.images: if not imageSrc.startswith("http://"): if imageSrc.startswith("/"): imageSrc = netloc + imageSrc else: imageSrc = '%s/%s/%s' % (netloc, path, imageSrc) urllib.urlretrieve(imageSrc, tmpDir/imageName) new_resource = Resource(self, tmpDir/imageName) if new_resource._storageName != imageName: # looks like it was changed due to a possible conflict, # so reset the imageName accordingly for the content: imageName = new_resource._storageName self.images[imageName] = True # We have to use absolute URLs if we want the images to # show up in edit mode inside FCKEditor imageTag['src'] = (u"/" + self.parentNode.package.name + u"/resources/" + imageName) self.article.content = self.reformatArticle(netloc, unicode(content)) # now that these are supporting images, any direct manipulation # of the content field must also store this updated information # into the other corresponding fields of TextAreaField: # (perhaps eventually a property should be made for TextAreaField # such that these extra set's are not necessary, but for now, here:) self.article.content_w_resourcePaths = self.article.content self.article.content_wo_resourcePaths = self.article.content
print '"ncftpget" not found. Go: sudo apt-get install ncftp' if not ok: sys.exit(1) os.system("fakeroot debian/rules binary") else: raise Exception('You need to copy the firefox installation to "exe/webui/firefox"') packages = (exeDir / "..").glob("*.deb") if not packages: print "No packages found" sys.exit(1) packages.sort() package = packages[-1] tmp = None if "index" in sys.argv: print "Creating Index..." tmp = TempDirPath() pool = tmp / "pool" pool.mkdir() package.copyfile(pool / package.basename()) pool.chdir() tmp.chdir() os.system("dpkg-scanpackages pool /dev/null | gzip -9c > pool/Packages.gz") if "copy" in sys.argv: if "index" in sys.argv: print "copying index file to", exeDir (pool / "Packages.gz").copy(exeDir) pool = exeDir if server: print "connecting to %s..." % server from socket import socket, gethostbyname
class Package(Persistable): """ Package represents the collection of resources the user is editing i.e. the "package". """ persistenceVersion = 9 nonpersistant = ['resourceDir', 'filename'] _name = '' tempFile = False # This is set when the package is saved as a temp copy file _title = '' _author = '' _description = '' _backgroundImg = '' defaultLevelNames = [x_(u"Topic"), x_(u"Section"), x_(u"Unit")] def __init__(self, name): """ Initialize """ log.debug(u"init " + repr(name)) self._nextIdeviceId = 0 self._nextNodeId = 0 self._nodeIdDict = {} self._levelNames = self.defaultLevelNames[:] self.name = name self._title = u'' self._backgroundImg = u'' self.backgroundImgTile = False self.filename = u'' self.root = Node(self, None, _(u"Home")) self.currentNode = self.root self.style = u"default" self.isChanged = False self.idevices = [] self.dublinCore = DublinCore() self.scolinks = False self.license = "None" self.footer = "" self.resourceDir = TempDirPath() self.resources = {} # Checksum-[_Resource(),..] def set_name(self, value): self._name = toUnicode(value) def set_title(self, value): self._title = toUnicode(value) def set_author(self, value): self._author = toUnicode(value) def set_description(self, value): self._description = toUnicode(value) def get_backgroundImg(self): """Get the background image for this package""" if self._backgroundImg: return "file://" + self._backgroundImg.path else: return "" def set_backgroundImg(self, value): """Set the background image for this package""" if self._backgroundImg: self._backgroundImg.delete() if value: if value.startswith("file://"): value = value[7:] imgFile = Path(value) self._backgroundImg = Resource(self, Path(imgFile)) else: self._backgroundImg = u'' def get_level1(self): return self.levelName(0) def set_level1(self, value): if value != '': self._levelNames[0] = value else: self._levelNames[0] = self.defaultLevelNames[0] def get_level2(self): return self.levelName(1) def set_level2(self, value): if value != '': self._levelNames[1] = value else: self._levelNames[1] = self.defaultLevelNames[1] def get_level3(self): return self.levelName(2) def set_level3(self, value): if value != '': self._levelNames[2] = value else: self._levelNames[2] = self.defaultLevelNames[2] name = property(lambda self:self._name, set_name) title = property(lambda self:self._title, set_title) author = property(lambda self:self._author, set_author) description = property(lambda self:self._description, set_description) backgroundImg = property(get_backgroundImg, set_backgroundImg) level1 = property(get_level1, set_level1) level2 = property(get_level2, set_level2) level3 = property(get_level3, set_level3) def findNode(self, nodeId): """ Finds a node from its nodeId (nodeId can be a string or a list/tuple) """ log.debug(u"findNode" + repr(nodeId)) node = self._nodeIdDict.get(nodeId) if node and node.package is self: return node else: return None def levelName(self, level): """ Return the level name """ if level < len(self._levelNames): return _(self._levelNames[level]) else: return _(u"?????") def save(self, filename=None, tempFile=False): """ Save package to disk pass an optional filename """ self.tempFile = tempFile if filename: filename = Path(filename) name = filename.splitpath()[1] if not tempFile: self.name = name.basename().splitext()[0] elif self.filename: filename = Path(self.filename) else: raise AssertionError(u'No name passed when saving a new package') log.debug(u"Will save %s to: %s" % (self.name, filename)) if tempFile: self.nonpersistant.remove('filename') oldFilename, self.filename = self.filename, unicode(self.filename) try: filename.safeSave(self.doSave, _('SAVE FAILED!\nLast succesful save is %s.')) finally: self.nonpersistant.append('filename') self.filename = oldFilename else: self.filename = filename filename.safeSave(self.doSave, _('SAVE FAILED!\nLast succesful save is %s.')) self.isChanged = False self.updateRecentDocuments(filename) def updateRecentDocuments(self, filename): """ Updates the list of recent documents """ genericData = G.application.config.configDir/'idevices'/'generic.data' if genericData.isfile() or genericData.islink(): if Path(filename).samefile(genericData): return recentProjects = G.application.config.recentProjects if filename in recentProjects: if recentProjects[0] == filename: return recentProjects.remove(filename) recentProjects.insert(0, filename) del recentProjects[5:] # Delete any older names from the list G.application.config.configParser.write() # Save the settings def doSave(self, fileObj): """ Actually performs the save to 'fileObj'. """ zippedFile = zipfile.ZipFile(fileObj, "w", zipfile.ZIP_DEFLATED) try: for resourceFile in self.resourceDir.files(): zippedFile.write(unicode(resourceFile.normpath()), resourceFile.name.encode('utf8'), zipfile.ZIP_DEFLATED) zinfo = zipfile.ZipInfo(filename='content.data', date_time=time.localtime()[0:6]) zinfo.external_attr = 0100644<<16L zippedFile.writestr(zinfo, encodeObject(self)) finally: zippedFile.close() def extractNode(self): """ Clones and extracts the currently selected node into a new package. """ newPackage = Package('NoName') # Name will be set once it is saved.. newPackage.title = self.currentNode.title newPackage.style = self.style newPackage.author = self.author newPackage._nextNodeId = self._nextNodeId self.currentNode.copyToPackage(newPackage) return newPackage @staticmethod def load(filename, newLoad=True, destinationPackage=None): """ Load package from disk, returns a package. """ if not zipfile.is_zipfile(filename): return None zippedFile = zipfile.ZipFile(filename, "r") toDecode = zippedFile.read(u"content.data") resourceDir = TempDirPath() for fn in zippedFile.namelist(): if unicode(fn, 'utf8') != u"content.data": outFile = open(resourceDir/fn, "wb") outFile.write(zippedFile.read(fn)) outFile.flush() outFile.close() try: newPackage = decodeObjectRaw(toDecode) G.application.afterUpgradeHandlers = [] newPackage.resourceDir = resourceDir G.application.afterUpgradeZombies2Delete = [] if newLoad: log.debug("load() about to doUpgrade newPackage \"" + newPackage._name + "\" " + repr(newPackage) ) if hasattr(newPackage, 'resourceDir'): log.debug("newPackage resourceDir = " + newPackage.resourceDir) else: log.error("newPackage resourceDir has NO resourceDir!") doUpgrade(newPackage) else: log.debug("load() about to merge doUpgrade newPackage \"" + newPackage._name + "\" " + repr(newPackage) + " INTO destinationPackage \"" + destinationPackage._name + "\" " + repr(destinationPackage)) log.debug("using their resourceDirs:") if hasattr(newPackage, 'resourceDir'): log.debug(" newPackage resourceDir = " + newPackage.resourceDir) else: log.error("newPackage has NO resourceDir!") if hasattr(destinationPackage, 'resourceDir'): log.debug(" destinationPackage resourceDir = " + destinationPackage.resourceDir) else: log.error("destinationPackage has NO resourceDir!") doUpgrade(destinationPackage, isMerge=True, preMergePackage=newPackage) except: import traceback traceback.print_exc() raise if newPackage.tempFile: newPackage.tempFile = False else: newPackage.filename = Path(filename) for handler_priority in range(3): for handler in G.application.afterUpgradeHandlers: if handler_priority == 0 and \ repr(handler.im_class)=="<class 'exe.engine.resource.Resource'>": handler() elif handler_priority == 1 and \ repr(handler.im_class)=="<class 'exe.engine.package.Package'>": if handler.im_self == newPackage: handler() else: log.warn("Extra package object found, " \ + "ignoring its afterUpgradeHandler: " \ + repr(handler)) elif handler_priority == 2 and \ repr(handler.im_class)!="<class 'exe.engine.resource.Resource'>" \ and \ repr(handler.im_class)!="<class 'exe.engine.package.Package'>": handler() G.application.afterUpgradeHandlers = [] num_zombies = len(G.application.afterUpgradeZombies2Delete) for i in range(num_zombies-1, -1, -1): zombie = G.application.afterUpgradeZombies2Delete[i] zombie_is_node = False if isinstance(zombie, Node): zombie_is_node = True if zombie_is_node: zombie.delete(pruningZombies=True) else: zombie.delete() del zombie G.application.afterUpgradeZombies2Delete = [] newPackage.updateRecentDocuments(newPackage.filename) newPackage.isChanged = False return newPackage def cleanUpResources(self): """ Removes duplicate resource files """ if not hasattr(self,'resourceDir'): log.warn("cleanUpResources called on a redundant package") return existingFiles = set([fn.basename() for fn in self.resourceDir.files()]) usedFiles = set([reses[0].storageName for reses in self.resources.values()]) for fn in existingFiles - usedFiles: (self.resourceDir/fn).remove() def findResourceByName(self, queryName): """ Support for merging, and anywhere else that unique names might be checked before actually comparing against the files (as will be done by the resource class itself in its _addOurselvesToPackage() ) """ foundResource = None queryResources = self.resources for this_checksum in queryResources: for this_resource in queryResources[this_checksum]: if queryName == this_resource.storageName: foundResource = this_resource return foundResource return foundResource def upgradeToVersion1(self): """ Called to upgrade from 0.3 release """ self._nextNodeId = 0 self._nodeIdDict = {} draft = getattr(self, 'draft') draft._id = self._regNewNode(draft) draft._package = self setattr(self, 'editor', Node(self, None, _(u"iDevice Editor"))) idevice = GenericIdevice("", "", "", "", "") editor = getattr(self, 'editor') idevice.parentNode = editor editor.addIdevice(idevice) def superReg(node): """Registers all our nodes because in v0 they were not registered in this way""" node._id = self._regNewNode(node) node._package = self for child in node.children: superReg(child) superReg(self.root) def _regNewNode(self, node): """ Called only by nodes, stores the node in our id lookup dict returns a new unique id """ id_ = unicode(self._nextNodeId) self._nextNodeId += 1 self._nodeIdDict[id_] = node return id_ def getNewIdeviceId(self): """ Returns an iDevice Id which is unique for this package. """ id_ = unicode(self._nextIdeviceId) self._nextIdeviceId += 1 return id_ def upgradeToVersion2(self): """ Called to upgrade from 0.4 release """ getattr(self, 'draft').delete() getattr(self, 'editor').delete() delattr(self, 'draft') delattr(self, 'editor') self._nextNodeId = 0 def renumberNode(node): """ Gives the old node a number """ node._id = self._regNewNode(node) for child in node.children: renumberNode(child) renumberNode(self.root) def upgradeToVersion3(self): """ Also called to upgrade from 0.4 release """ self._nextIdeviceId = 0 def upgradeToVersion4(self): """ Puts properties in their place Also called to upgrade from 0.8 release """ self._name = toUnicode(self.__dict__['name']) self._author = toUnicode(self.__dict__['author']) self._description = toUnicode(self.__dict__['description']) def upgradeToVersion5(self): """ For version 0.11 """ self._levelNames = self.levelNames del self.levelNames def upgradeToVersion6(self): """ For version 0.14 """ self.dublinCore = DublinCore() self.title = self.root.title self.dublinCore.title = self.root.title self.dublinCore.creator = self._author self.dublinCore.description = self._description self.scolinks = False def upgradeToVersion7(self): """ For version 0.15 """ self._backgroundImg = '' self.backgroundImgTile = False def upgradeToVersion8(self): """ For version 0.20, alpha, for nightlies r2469 """ self.license = 'None' self.footer = "" self.idevices = [] def upgradeToVersion9(self): """ For version >= 0.20.4 """ if not hasattr(self, 'resources'): self.resources = {} G.application.afterUpgradeHandlers.append(self.cleanUpResources)
class Package(Persistable): """ Package represents the collection of resources the user is editing i.e. the "package". """ persistenceVersion = 8 nonpersistant = ["resourceDir", "filename"] _name = "" tempFile = False # This is set when the package is saved as a temp copy file _title = "" _author = "" _description = "" _backgroundImg = "" defaultLevelNames = [x_(u"Topic"), x_(u"Section"), x_(u"Unit")] def __init__(self, name): """ Initialize """ log.debug(u"init " + repr(name)) self._nextIdeviceId = 0 self._nextNodeId = 0 self._nodeIdDict = {} self._levelNames = self.defaultLevelNames[:] self.name = name self._title = u"" self._backgroundImg = u"" self.backgroundImgTile = False self.filename = u"" self.root = Node(self, None, _(u"Home")) self.currentNode = self.root self.style = u"default" self.isChanged = 0 self.idevices = [] self.dublinCore = DublinCore() self.scolinks = False self.license = "None" self.footer = "" self.resourceDir = TempDirPath() def set_name(self, value): self._name = toUnicode(value) def set_title(self, value): self._title = toUnicode(value) def set_author(self, value): self._author = toUnicode(value) def set_description(self, value): self._description = toUnicode(value) def get_backgroundImg(self): """Get the background image for this package""" if self._backgroundImg: return "file://" + self._backgroundImg.path else: return "" def set_backgroundImg(self, value): """Set the background image for this package""" if self._backgroundImg: self._backgroundImg.delete() if value: if value.startswith("file://"): value = value[7:] imgFile = Path(value) self._backgroundImg = Resource(self, Path(imgFile)) else: self._backgroundImg = u"" def get_level1(self): return self.levelName(0) def set_level1(self, value): if value != "": self._levelNames[0] = value else: self._levelNames[0] = self.defaultLevelNames[0] def get_level2(self): return self.levelName(1) def set_level2(self, value): if value != "": self._levelNames[1] = value else: self._levelNames[1] = self.defaultLevelNames[1] def get_level3(self): return self.levelName(2) def set_level3(self, value): if value != "": self._levelNames[2] = value else: self._levelNames[2] = self.defaultLevelNames[2] name = property(lambda self: self._name, set_name) title = property(lambda self: self._title, set_title) author = property(lambda self: self._author, set_author) description = property(lambda self: self._description, set_description) backgroundImg = property(get_backgroundImg, set_backgroundImg) level1 = property(get_level1, set_level1) level2 = property(get_level2, set_level2) level3 = property(get_level3, set_level3) def findNode(self, nodeId): """ Finds a node from its nodeId (nodeId can be a string or a list/tuple) """ log.debug(u"findNode" + repr(nodeId)) node = self._nodeIdDict.get(nodeId) if node and node.package is self: return node else: return None def levelName(self, level): """ Return the level name """ if level < len(self._levelNames): return _(self._levelNames[level]) else: return _(u"?????") def save(self, filename=None, tempFile=False): """ Save package to disk pass an optional filename """ self.tempFile = tempFile if filename: filename = Path(filename) name = filename.splitpath()[1] if not tempFile: self.name = name.basename().splitext()[0] elif self.filename: filename = Path(self.filename) else: raise AssertionError(u"No name passed when saving a new package") log.debug(u"Will save %s to: %s" % (self.name, filename)) if tempFile: self.nonpersistant.remove("filename") oldFilename, self.filename = self.filename, unicode(self.filename) try: filename.safeSave(self.doSave, _("SAVE FAILED!\nLast succesful save is %s.")) finally: self.nonpersistant.append("filename") self.filename = oldFilename else: self.filename = filename filename.safeSave(self.doSave, _("SAVE FAILED!\nLast succesful save is %s.")) self.isChanged = 0 self.updateRecentDocuments(filename) def updateRecentDocuments(self, filename): """ Updates the list of recent documents """ from exe.application import application genericData = application.config.configDir / "idevices" / "generic.data" if genericData.isfile() or genericData.islink(): if Path(filename).samefile(genericData): return recentProjects = application.config.recentProjects fn = filename.encode("utf-8") if fn in recentProjects: if recentProjects[0] == fn: return recentProjects.remove(fn) recentProjects.insert(0, filename) del recentProjects[5:] # Delete any older names from the list application.config.configParser.write() # Save the settings def doSave(self, fileObj): """ Actually performs the save to 'fileObj'. """ zippedFile = zipfile.ZipFile(fileObj, "w", zipfile.ZIP_DEFLATED) try: for resourceFile in self.resourceDir.files(): zippedFile.write( unicode(resourceFile.normpath()), resourceFile.name.encode("utf8"), zipfile.ZIP_DEFLATED ) zippedFile.writestr("content.data", encodeObject(self)) finally: zippedFile.close() @staticmethod def load(filename): """ Load package from disk, returns a package """ if not zipfile.is_zipfile(filename): return None zippedFile = zipfile.ZipFile(filename, "r", zipfile.ZIP_DEFLATED) toDecode = zippedFile.read(u"content.data") try: newPackage = decodeObjectRaw(toDecode) newPackage.afterUpgradeHandlers = [] doUpgrade() except: import traceback traceback.print_exc() raise if newPackage.tempFile: newPackage.tempFile = False else: newPackage.filename = Path(filename) newPackage.resourceDir = TempDirPath() for filename in zippedFile.namelist(): if unicode(filename, "utf8") != u"content.data": outFile = open(newPackage.resourceDir / filename, "wb") outFile.write(zippedFile.read(filename)) for handler in newPackage.afterUpgradeHandlers: handler() del newPackage.afterUpgradeHandlers newPackage.updateRecentDocuments(newPackage.filename) return newPackage def upgradeToVersion1(self): """ Called to upgrade from 0.3 release """ self._nextNodeId = 0 self._nodeIdDict = {} draft = getattr(self, "draft") draft._id = self._regNewNode(draft) draft._package = self setattr(self, "editor", Node(self, None, _(u"iDevice Editor"))) idevice = GenericIdevice("", "", "", "", "") editor = getattr(self, "editor") idevice.parentNode = editor editor.addIdevice(idevice) def superReg(node): """Registers all our nodes because in v0 they were not registered in this way""" node._id = self._regNewNode(node) node._package = self for child in node.children: superReg(child) superReg(self.root) def _regNewNode(self, node): """ Called only by nodes, stores the node in our id lookup dict returns a new unique id """ id_ = unicode(self._nextNodeId) self._nextNodeId += 1 self._nodeIdDict[id_] = node return id_ def getNewIdeviceId(self): """ Returns an iDevice Id which is unique for this package. """ id_ = unicode(self._nextIdeviceId) self._nextIdeviceId += 1 return id_ def upgradeToVersion2(self): """ Called to upgrade from 0.4 release """ getattr(self, "draft").delete() getattr(self, "editor").delete() delattr(self, "draft") delattr(self, "editor") self._nextNodeId = 0 def renumberNode(node): """ Gives the old node a number """ node._id = self._regNewNode(node) for child in node.children: renumberNode(child) renumberNode(self.root) def upgradeToVersion3(self): """ Also called to upgrade from 0.4 release """ self._nextIdeviceId = 0 def upgradeToVersion4(self): """ Puts properties in their place Also called to upgrade from 0.8 release """ self._name = toUnicode(self.__dict__["name"]) self._author = toUnicode(self.__dict__["author"]) self._description = toUnicode(self.__dict__["description"]) def upgradeToVersion5(self): """ For version 0.11 """ self._levelNames = self.levelNames del self.levelNames def upgradeToVersion6(self): """ For version 0.14 """ self.dublinCore = DublinCore() self.title = self.root.title self.dublinCore.title = self.root.title self.dublinCore.creator = self._author self.dublinCore.description = self._description self.scolinks = False def upgradeToVersion7(self): """ For version 0.15 """ self._backgroundImg = "" self.backgroundImgTile = False def upgradeToVersion8(self): """ For version 0.20 """ self.license = "None" self.footer = ""
def export(self, package): """ Export SCORM package """ outputDir = TempDirPath() styleFiles = [self.styleDir/'..'/'base.css'] styleFiles += [self.styleDir/'..'/'popup_bg.gif'] styleFiles += self.styleDir.files("*.css") if "nav.css" in styleFiles: styleFiles.remove("nav.css") styleFiles += self.styleDir.files("*.jpg") styleFiles += self.styleDir.files("*.gif") styleFiles += self.styleDir.files("*.png") styleFiles += self.styleDir.files("*.js") styleFiles += self.styleDir.files("*.html") self.styleDir.copylist(styleFiles, outputDir) package.resourceDir.copyfiles(outputDir) self.pages = [ IMSPage("index", 1, package.root) ] self.generatePages(package.root, 2) uniquifyNames(self.pages) for page in self.pages: page.save(outputDir) manifest = Manifest(self.config, outputDir, package, self.pages) manifest.save() self.scriptsDir.copylist(('libot_drag.js', 'common.js'), outputDir) self.schemasDir.copylist(('imscp_v1p1.xsd', 'imsmd_v1p2p2.xsd', 'ims_xml.xsd'), outputDir) hasFlowplayer = False hasMagnifier = False hasXspfplayer = False isBreak = False for page in self.pages: if isBreak: break for idevice in page.node.idevices: if (hasFlowplayer and hasMagnifier and hasXspfplayer): isBreak = True break if not hasFlowplayer: if 'flowPlayer.swf' in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if 'magnifier.swf' in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if 'xspf_player.swf' in idevice.systemResources: hasXspfplayer = True if hasFlowplayer: videofile = (self.templatesDir/'flowPlayer.swf') videofile.copyfile(outputDir/'flowPlayer.swf') if hasMagnifier: videofile = (self.templatesDir/'magnifier.swf') videofile.copyfile(outputDir/'magnifier.swf') if hasXspfplayer: videofile = (self.templatesDir/'xspf_player.swf') videofile.copyfile(outputDir/'xspf_player.swf') (self.templatesDir/'fdl.html').copyfile(outputDir/'fdl.html') self.filename.safeSave(self.doZip, _('EXPORT FAILED!\nLast succesful export is %s.'), outputDir) outputDir.rmtree()
def export(self, package): """ Export SCORM package """ # First do the export to a temporary directory outputDir = TempDirPath() self.metadataType = package.exportMetadataType # Copy the style sheet files to the output dir # But not nav.css styleFiles = [self.styleDir / ".." / "base.css"] styleFiles += [self.styleDir / ".." / "popup_bg.gif"] styleFiles += self.styleDir.files("*.css") if "nav.css" in styleFiles: styleFiles.remove("nav.css") styleFiles += self.styleDir.files("*.jpg") styleFiles += self.styleDir.files("*.gif") styleFiles += self.styleDir.files("*.png") styleFiles += self.styleDir.files("*.js") styleFiles += self.styleDir.files("*.html") styleFiles += self.styleDir.files("*.ttf") styleFiles += self.styleDir.files("*.eot") styleFiles += self.styleDir.files("*.otf") styleFiles += self.styleDir.files("*.woff") self.styleDir.copylist(styleFiles, outputDir) # copy the package's resource files package.resourceDir.copyfiles(outputDir) # Export the package content self.pages = [IMSPage("index", 1, package.root, metadataType=self.metadataType)] self.generatePages(package.root, 2) uniquifyNames(self.pages) for page in self.pages: page.save(outputDir) # Create the manifest file manifest = Manifest(self.config, outputDir, package, self.pages, self.metadataType) manifest.save("imsmanifest.xml") # Copy the scripts # jQuery my_style = G.application.config.styleStore.getStyle(page.node.package.style) if my_style.hasValidConfig: if my_style.get_jquery() == True: jsFile = self.scriptsDir / "exe_jquery.js" jsFile.copyfile(outputDir / "exe_jquery.js") else: jsFile = self.scriptsDir / "exe_jquery.js" jsFile.copyfile(outputDir / "exe_jquery.js") jsFile = self.scriptsDir / "common.js" jsFile.copyfile(outputDir / "common.js") dT = common.getExportDocType() if dT == "HTML5": jsFile = self.scriptsDir / "exe_html5.js" jsFile.copyfile(outputDir / "exe_html5.js") self.schemasDir.copylist( ("imscp_v1p1.xsd", "imsmd_v1p2p2.xsd", "lom.xsd", "lomCustom.xsd", "ims_xml.xsd"), outputDir ) # copy players for media idevices. hasFlowplayer = False hasMagnifier = False hasXspfplayer = False hasGallery = False hasWikipedia = False isBreak = False hasInstructions = False hasMediaelement = False for page in self.pages: if isBreak: break for idevice in page.node.idevices: if ( hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery and hasWikipedia and hasInstructions and hasMediaelement ): isBreak = True break if not hasFlowplayer: if "flowPlayer.swf" in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if "mojomagnify.js" in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if "xspf_player.swf" in idevice.systemResources: hasXspfplayer = True if not hasGallery: hasGallery = common.ideviceHasGallery(idevice) if not hasWikipedia: if "WikipediaIdevice" == idevice.klass: hasWikipedia = True if not hasInstructions: if ( "TrueFalseIdevice" == idevice.klass or "MultichoiceIdevice" == idevice.klass or "VerdaderofalsofpdIdevice" == idevice.klass or "EleccionmultiplefpdIdevice" == idevice.klass ): hasInstructions = True if not hasMediaelement: hasMediaelement = common.ideviceHasMediaelement(idevice) if hasFlowplayer: videofile = self.templatesDir / "flowPlayer.swf" videofile.copyfile(outputDir / "flowPlayer.swf") controlsfile = self.templatesDir / "flowplayer.controls.swf" controlsfile.copyfile(outputDir / "flowplayer.controls.swf") if hasMagnifier: videofile = self.templatesDir / "mojomagnify.js" videofile.copyfile(outputDir / "mojomagnify.js") if hasXspfplayer: videofile = self.templatesDir / "xspf_player.swf" videofile.copyfile(outputDir / "xspf_player.swf") if hasGallery: imageGalleryCSS = self.cssDir / "exe_lightbox.css" imageGalleryCSS.copyfile(outputDir / "exe_lightbox.css") imageGalleryJS = self.scriptsDir / "exe_lightbox.js" imageGalleryJS.copyfile(outputDir / "exe_lightbox.js") self.imagesDir.copylist( ( "exe_lightbox_close.png", "exe_lightbox_loading.gif", "exe_lightbox_next.png", "exe_lightbox_prev.png", ), outputDir, ) if hasWikipedia: wikipediaCSS = self.cssDir / "exe_wikipedia.css" wikipediaCSS.copyfile(outputDir / "exe_wikipedia.css") if hasInstructions: common.copyFileIfNotInStyle("panel-amusements.png", self, outputDir) common.copyFileIfNotInStyle("stock-stop.png", self, outputDir) if hasMediaelement: mediaelement = self.scriptsDir / "mediaelement" mediaelement.copyfiles(outputDir) if dT != "HTML5": jsFile = self.scriptsDir / "exe_html5.js" jsFile.copyfile(outputDir / "exe_html5.js") if hasattr(package, "exportSource") and package.exportSource: (G.application.config.webDir / "templates" / "content.xsd").copyfile(outputDir / "content.xsd") (outputDir / "content.data").write_bytes(encodeObject(package)) (outputDir / "contentv3.xml").write_bytes(encodeObjectToXML(package)) if package.license == "license GFDL": # include a copy of the GNU Free Documentation Licence (self.templatesDir / "fdl.html").copyfile(outputDir / "fdl.html") # Zip it up! self.filename.safeSave(self.doZip, _("EXPORT FAILED!\nLast succesful export is %s."), outputDir) # Clean up the temporary dir outputDir.rmtree()
def export(self, package): """ Export SCORM package """ # First do the export to a temporary directory outputDir = TempDirPath() self.metadataType = package.exportMetadataType # copy the package's resource files package.resourceDir.copyfiles(outputDir) # copy the package's resource files, only non existant in outputDir # outputDirFiles = outputDir.files() # for rfile in package.resourceDir.files(): # if rfile not in outputDirFiles: # rfile.copy(outputDir) # copy the package's resource files, only indexed in package.resources # for md5 in package.resources.values(): # for resource in md5: # resource.path.copy(outputDir) # Export the package content # Import the Scorm Page class , if the secure mode is off. If the style has it's own page class # use that, else use the default one. if self.styleSecureMode=="0": if (self.styleDir/"scormpage.py").exists(): global ScormPage module = imp.load_source("ScormPage",self.styleDir/"scormpage.py") ScormPage = module.ScormPage self.pages = [ ScormPage("index", 1, package.root, scormType=self.scormType, metadataType=self.metadataType) ] self.generatePages(package.root, 2) uniquifyNames(self.pages) for page in self.pages: page.save(outputDir) if not self.hasForum: for idevice in page.node.idevices: if hasattr(idevice, "isForum"): if idevice.forum.lms.lms == "moodle": self.hasForum = True break # Create the manifest file manifest = Manifest(self.config, outputDir, package, self.pages, self.scormType, self.metadataType) manifest.save("imsmanifest.xml") if self.hasForum: manifest.save("discussionforum.xml") # Copy the style sheet files to the output dir styleFiles = [self.styleDir/'..'/'base.css'] styleFiles += [self.styleDir/'..'/'popup_bg.gif'] # And with all the files of the style we avoid problems: styleFiles += self.styleDir.files("*.*") if self.scormType == "commoncartridge": for sf in styleFiles[:]: if sf.basename() not in manifest.dependencies: styleFiles.remove(sf) self.styleDir.copylist(styleFiles, outputDir) # Copy the scripts dT = common.getExportDocType() if dT == "HTML5": jsFile = (self.scriptsDir/'exe_html5.js') jsFile.copyfile(outputDir/'exe_html5.js') # jQuery my_style = G.application.config.styleStore.getStyle(page.node.package.style) if my_style.hasValidConfig: if my_style.get_jquery() == True: jsFile = (self.scriptsDir/'exe_jquery.js') jsFile.copyfile(outputDir/'exe_jquery.js') else: jsFile = (self.scriptsDir/'exe_jquery.js') jsFile.copyfile(outputDir/'exe_jquery.js') if self.scormType == "commoncartridge": jsFile = (self.scriptsDir/'common.js') jsFile.copyfile(outputDir/'common.js') if self.scormType == "scorm2004" or self.scormType == "scorm1.2": self.scriptsDir.copylist(('SCORM_API_wrapper.js', 'SCOFunctions.js', 'lernmodule_net.js', 'lernmodule_net_custom.js', 'common.js'), outputDir) # about SCHEMAS: schemasDir = "" if self.scormType == "scorm1.2": schemasDir = self.schemasDir/"scorm1.2" schemasDir.copylist(('imscp_rootv1p1p2.xsd', 'imsmd_rootv1p2p1.xsd', 'adlcp_rootv1p2.xsd', 'lom.xsd', 'lomCustom.xsd', 'ims_xml.xsd'), outputDir) elif self.scormType == "scorm2004": schemasDir = self.schemasDir/"scorm2004" schemasDir.copylist(('adlcp_v1p3.xsd', 'adlnav_v1p3.xsd', 'adlseq_v1p3.xsd', 'datatypes.dtd', 'imscp_v1p1.xsd', 'imsssp_v1p0.xsd', 'imsss_v1p0.xsd', 'imsss_v1p0auxresource.xsd', 'imsss_v1p0control.xsd', 'imsss_v1p0delivery.xsd', 'imsmd_rootv1p2p1.xsd', 'imsss_v1p0limit.xsd', 'imsss_v1p0objective.xsd', 'imsss_v1p0random.xsd', 'imsss_v1p0rollup.xsd', 'imsss_v1p0seqrule.xsd', 'imsss_v1p0util.xsd', 'ims_xml.xsd', 'lom.xsd', 'lomCustom.xsd', 'xml.xsd', 'XMLSchema.dtd'), outputDir) try: import shutil, errno shutil.copytree(schemasDir/"common", outputDir/"common") shutil.copytree(schemasDir/"extend", outputDir/"extend") shutil.copytree(schemasDir/"unique", outputDir/"unique") shutil.copytree(schemasDir/"vocab", outputDir/"vocab") except OSError as exc: if exc.errno == errno.ENOTDIR: shutil.copy(schemasDir, outputDir) else: raise # copy players for media idevices. hasFlowplayer = False hasMagnifier = False hasXspfplayer = False hasGallery = False hasWikipedia = False isBreak = False hasInstructions = False hasMediaelement = False for page in self.pages: if isBreak: break for idevice in page.node.idevices: if (hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery and hasWikipedia and hasInstructions and hasMediaelement): isBreak = True break if not hasFlowplayer: if 'flowPlayer.swf' in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if 'mojomagnify.js' in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if 'xspf_player.swf' in idevice.systemResources: hasXspfplayer = True if not hasGallery: hasGallery = common.ideviceHasGallery(idevice) if not hasWikipedia: if 'WikipediaIdevice' == idevice.klass: hasWikipedia = True if not hasInstructions: if 'TrueFalseIdevice' == idevice.klass or 'MultichoiceIdevice' == idevice.klass or 'VerdaderofalsofpdIdevice' == idevice.klass or 'EleccionmultiplefpdIdevice' == idevice.klass: hasInstructions = True if not hasMediaelement: hasMediaelement = common.ideviceHasMediaelement(idevice) if hasFlowplayer: videofile = (self.templatesDir/'flowPlayer.swf') videofile.copyfile(outputDir/'flowPlayer.swf') controlsfile = (self.templatesDir/'flowplayer.controls.swf') controlsfile.copyfile(outputDir/'flowplayer.controls.swf') if hasMagnifier: videofile = (self.templatesDir/'mojomagnify.js') videofile.copyfile(outputDir/'mojomagnify.js') if hasXspfplayer: videofile = (self.templatesDir/'xspf_player.swf') videofile.copyfile(outputDir/'xspf_player.swf') if hasGallery: imageGalleryCSS = (self.cssDir/'exe_lightbox.css') imageGalleryCSS.copyfile(outputDir/'exe_lightbox.css') imageGalleryJS = (self.scriptsDir/'exe_lightbox.js') imageGalleryJS.copyfile(outputDir/'exe_lightbox.js') self.imagesDir.copylist(('exe_lightbox_close.png', 'exe_lightbox_loading.gif', 'exe_lightbox_next.png', 'exe_lightbox_prev.png'), outputDir) if hasWikipedia: wikipediaCSS = (self.cssDir/'exe_wikipedia.css') wikipediaCSS.copyfile(outputDir/'exe_wikipedia.css') if hasInstructions: common.copyFileIfNotInStyle('panel-amusements.png', self, outputDir) common.copyFileIfNotInStyle('stock-stop.png', self, outputDir) if hasMediaelement: mediaelement = (self.scriptsDir/'mediaelement') mediaelement.copyfiles(outputDir) if dT != "HTML5": jsFile = (self.scriptsDir/'exe_html5.js') if self.scormType == "scorm1.2" or self.scormType == "scorm2004": if package.license == "license GFDL": # include a copy of the GNU Free Documentation Licence (self.templatesDir/'fdl.html').copyfile(outputDir/'fdl.html') if hasattr(package, 'scowsinglepage') and package.scowsinglepage: page = SinglePage("singlepage_index", 1, package.root) page.save(outputDir/"singlepage_index.html") # Incluide eXe's icon if the Style doesn't have one themePath = Path(G.application.config.stylesDir/package.style) themeFavicon = themePath.joinpath("favicon.ico") if not themeFavicon.exists(): faviconFile = (self.imagesDir/'favicon.ico') faviconFile.copyfile(outputDir/'favicon.ico') if hasattr(package, 'scowwebsite') and package.scowwebsite: website = WebsiteExport(self.config, self.styleDir, outputDir, "website_") website.export(package) (self.styleDir/'nav.css').copyfile(outputDir/'nav.css') # Incluide eXe's icon if the Style doesn't have one themePath = Path(G.application.config.stylesDir/package.style) themeFavicon = themePath.joinpath("favicon.ico") if not themeFavicon.exists(): faviconFile = (self.imagesDir/'favicon.ico') faviconFile.copyfile(outputDir/'favicon.ico') if hasattr(package, 'exportSource') and package.exportSource: (G.application.config.webDir/'templates'/'content.xsd').copyfile(outputDir/'content.xsd') (outputDir/'content.data').write_bytes(encodeObject(package)) (outputDir/'contentv3.xml').write_bytes(encodeObjectToXML(package)) # Zip it up! self.filename.safeSave(self.doZip, _('EXPORT FAILED!\nLast succesful export is %s.'), outputDir) # Clean up the temporary dir outputDir.rmtree()
def load(filename, newLoad=True, destinationPackage=None): """ Load package from disk, returns a package. """ if not zipfile.is_zipfile(filename): return None zippedFile = zipfile.ZipFile(filename, "r") try: # Get the jellied package data toDecode = zippedFile.read(u"content.data") except KeyError: log.info("no content.data, trying Common Cartridge/Content Package") newPackage = loadCC(zippedFile, filename) newPackage.tempFile = False newPackage.isChanged = False newPackage.filename = Path(filename) return newPackage # Need to add a TempDirPath because it is a nonpersistant member resourceDir = TempDirPath() # Extract resource files from package to temporary directory for fn in zippedFile.namelist(): if unicode(fn, 'utf8') != u"content.data": outFile = open(resourceDir/fn, "wb") outFile.write(zippedFile.read(fn)) outFile.flush() outFile.close() try: newPackage = decodeObjectRaw(toDecode) G.application.afterUpgradeHandlers = [] newPackage.resourceDir = resourceDir G.application.afterUpgradeZombies2Delete = [] if newLoad: # provide newPackage to doUpgrade's versionUpgrade() to # correct old corrupt extracted packages by setting the # any corrupt package references to the new package: log.debug("load() about to doUpgrade newPackage \"" + newPackage._name + "\" " + repr(newPackage) ) if hasattr(newPackage, 'resourceDir'): log.debug("newPackage resourceDir = " + newPackage.resourceDir) else: # even though it was just set above? should not get here: log.error("newPackage resourceDir has NO resourceDir!") doUpgrade(newPackage) # after doUpgrade, compare the largest found field ID: if G.application.maxFieldId >= Field.nextId: Field.nextId = G.application.maxFieldId + 1 else: # and when merging, automatically set package references to # the destinationPackage, into which this is being merged: log.debug("load() about to merge doUpgrade newPackage \"" + newPackage._name + "\" " + repr(newPackage) + " INTO destinationPackage \"" + destinationPackage._name + "\" " + repr(destinationPackage)) log.debug("using their resourceDirs:") if hasattr(newPackage, 'resourceDir'): log.debug(" newPackage resourceDir = " + newPackage.resourceDir) else: log.error("newPackage has NO resourceDir!") if hasattr(destinationPackage, 'resourceDir'): log.debug(" destinationPackage resourceDir = " + destinationPackage.resourceDir) else: log.error("destinationPackage has NO resourceDir!") doUpgrade(destinationPackage, isMerge=True, preMergePackage=newPackage) # after doUpgrade, compare the largest found field ID: if G.application.maxFieldId >= Field.nextId: Field.nextId = G.application.maxFieldId + 1 except: import traceback traceback.print_exc() raise if newPackage.tempFile: # newPackage.filename was stored as it's original filename newPackage.tempFile = False else: # newPackage.filename is the name that the package was last loaded from # or saved to newPackage.filename = Path(filename) # Let idevices and nodes handle any resource upgrading they may need to # Note: Package afterUpgradeHandlers *must* be done after Resources' # and the package should be updated before everything else, # so, prioritize with a 3-pass, 3-level calling setup # in order of: 1) resources, 2) package, 3) anything other objects for handler_priority in range(3): for handler in G.application.afterUpgradeHandlers: if handler_priority == 0 and \ repr(handler.im_class)=="<class 'exe.engine.resource.Resource'>": # level-0 handlers: Resource handler() elif handler_priority == 1 and \ repr(handler.im_class)=="<class 'exe.engine.package.Package'>": # level-1 handlers: Package (requires resources first) if handler.im_self == newPackage: handler() else: log.warn("Extra package object found, " \ + "ignoring its afterUpgradeHandler: " \ + repr(handler)) elif handler_priority == 2 and \ repr(handler.im_class)!="<class 'exe.engine.resource.Resource'>" \ and \ repr(handler.im_class)!="<class 'exe.engine.package.Package'>": # level-2 handlers: all others handler() G.application.afterUpgradeHandlers = [] num_zombies = len(G.application.afterUpgradeZombies2Delete) for i in range(num_zombies-1, -1, -1): zombie = G.application.afterUpgradeZombies2Delete[i] # now, the zombie list can contain nodes OR resources to delete. # if zombie is a node, then also pass in a pruning parameter.. zombie_is_node = False if isinstance(zombie, Node): zombie_is_node = True if zombie_is_node: zombie.delete(pruningZombies=True) else: zombie.delete() del zombie G.application.afterUpgradeZombies2Delete = [] newPackage.updateRecentDocuments(newPackage.filename) newPackage.isChanged = False return newPackage
def export(self, package): """ Export SCORM package """ # First do the export to a temporary directory outputDir = TempDirPath() self.metadataType = package.exportMetadataType # Copy the style sheet files to the output dir # But not nav.css styleFiles = [self.styleDir / '..' / 'base.css'] styleFiles += [self.styleDir / '..' / 'popup_bg.gif'] styleFiles += self.styleDir.files("*.css") if "nav.css" in styleFiles: styleFiles.remove("nav.css") styleFiles += self.styleDir.files("*.jpg") styleFiles += self.styleDir.files("*.gif") styleFiles += self.styleDir.files("*.png") styleFiles += self.styleDir.files("*.js") styleFiles += self.styleDir.files("*.html") styleFiles += self.styleDir.files("*.ttf") styleFiles += self.styleDir.files("*.eot") styleFiles += self.styleDir.files("*.otf") styleFiles += self.styleDir.files("*.woff") self.styleDir.copylist(styleFiles, outputDir) # copy the package's resource files package.resourceDir.copyfiles(outputDir) # Export the package content self.pages = [ IMSPage("index", 1, package.root, metadataType=self.metadataType) ] self.generatePages(package.root, 2) uniquifyNames(self.pages) for page in self.pages: page.save(outputDir) # Create the manifest file manifest = Manifest(self.config, outputDir, package, self.pages, self.metadataType) manifest.save("imsmanifest.xml") # Copy the scripts # jQuery my_style = G.application.config.styleStore.getStyle( page.node.package.style) if my_style.hasValidConfig: if my_style.get_jquery() == True: jsFile = (self.scriptsDir / 'exe_jquery.js') jsFile.copyfile(outputDir / 'exe_jquery.js') else: jsFile = (self.scriptsDir / 'exe_jquery.js') jsFile.copyfile(outputDir / 'exe_jquery.js') jsFile = (self.scriptsDir / 'common.js') jsFile.copyfile(outputDir / 'common.js') dT = common.getExportDocType() if dT == "HTML5": jsFile = (self.scriptsDir / 'exe_html5.js') jsFile.copyfile(outputDir / 'exe_html5.js') self.schemasDir.copylist(('imscp_v1p1.xsd', 'imsmd_v1p2p2.xsd', 'lom.xsd', 'lomCustom.xsd', 'ims_xml.xsd'), outputDir) # copy players for media idevices. hasFlowplayer = False hasMagnifier = False hasXspfplayer = False hasGallery = False hasFX = False hasSH = False hasGames = False hasWikipedia = False isBreak = False hasInstructions = False hasMediaelement = False hasTooltips = False for page in self.pages: if isBreak: break for idevice in page.node.idevices: if (hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery and hasFX and hasSH and hasGames and hasWikipedia and hasInstructions and hasMediaelement and hasTooltips): isBreak = True break if not hasFlowplayer: if 'flowPlayer.swf' in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if 'mojomagnify.js' in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if 'xspf_player.swf' in idevice.systemResources: hasXspfplayer = True if not hasGallery: hasGallery = common.ideviceHasGallery(idevice) if not hasFX: hasFX = common.ideviceHasFX(idevice) if not hasSH: hasSH = common.ideviceHasSH(idevice) if not hasGames: hasGames = common.ideviceHasGames(idevice) if not hasWikipedia: if 'WikipediaIdevice' == idevice.klass: hasWikipedia = True if not hasInstructions: if 'TrueFalseIdevice' == idevice.klass or 'MultichoiceIdevice' == idevice.klass or 'VerdaderofalsofpdIdevice' == idevice.klass or 'EleccionmultiplefpdIdevice' == idevice.klass: hasInstructions = True if not hasMediaelement: hasMediaelement = common.ideviceHasMediaelement(idevice) if not hasTooltips: hasTooltips = common.ideviceHasTooltips(idevice) if hasFlowplayer: videofile = (self.templatesDir / 'flowPlayer.swf') videofile.copyfile(outputDir / 'flowPlayer.swf') controlsfile = (self.templatesDir / 'flowplayer.controls.swf') controlsfile.copyfile(outputDir / 'flowplayer.controls.swf') if hasMagnifier: videofile = (self.templatesDir / 'mojomagnify.js') videofile.copyfile(outputDir / 'mojomagnify.js') if hasXspfplayer: videofile = (self.templatesDir / 'xspf_player.swf') videofile.copyfile(outputDir / 'xspf_player.swf') if hasGallery: exeLightbox = (self.scriptsDir / 'exe_lightbox') exeLightbox.copyfiles(outputDir) if hasFX: exeEffects = (self.scriptsDir / 'exe_effects') exeEffects.copyfiles(outputDir) if hasSH: exeSH = (self.scriptsDir / 'exe_highlighter') exeSH.copyfiles(outputDir) if hasGames: exeGames = (self.scriptsDir / 'exe_games') exeGames.copyfiles(outputDir) if hasWikipedia: wikipediaCSS = (self.cssDir / 'exe_wikipedia.css') wikipediaCSS.copyfile(outputDir / 'exe_wikipedia.css') if hasInstructions: common.copyFileIfNotInStyle('panel-amusements.png', self, outputDir) common.copyFileIfNotInStyle('stock-stop.png', self, outputDir) if hasMediaelement: mediaelement = (self.scriptsDir / 'mediaelement') mediaelement.copyfiles(outputDir) if dT != "HTML5": jsFile = (self.scriptsDir / 'exe_html5.js') jsFile.copyfile(outputDir / 'exe_html5.js') if hasTooltips: exe_tooltips = (self.scriptsDir / 'exe_tooltips') exe_tooltips.copyfiles(outputDir) if hasattr(package, 'exportSource') and package.exportSource: (G.application.config.webDir / 'templates' / 'content.xsd').copyfile(outputDir / 'content.xsd') (outputDir / 'content.data').write_bytes(encodeObject(package)) (outputDir / 'contentv3.xml').write_bytes( encodeObjectToXML(package)) if package.license == "license GFDL": # include a copy of the GNU Free Documentation Licence (self.templatesDir / 'fdl.html').copyfile(outputDir / 'fdl.html') # Zip it up! self.filename.safeSave( self.doZip, _('EXPORT FAILED!\nLast succesful export is %s.'), outputDir) # Clean up the temporary dir outputDir.rmtree()
def export(self, package): """ Export SCORM package """ outputDir = TempDirPath() self.pages = [ ScormPage("index", 1, package.root, scormType=self.scormType) ] self.generatePages(package.root, 2) uniquifyNames(self.pages) for page in self.pages: page.save(outputDir) if not self.hasForum: for idevice in page.node.idevices: if hasattr(idevice, "isForum"): if idevice.forum.lms.lms == "moodle": self.hasForum = True break manifest = Manifest(self.config, outputDir, package, self.pages, self.scormType) manifest.save("imsmanifest.xml") if self.hasForum: manifest.save("discussionforum.xml") styleFiles = [self.styleDir/'..'/'base.css'] styleFiles += [self.styleDir/'..'/'popup_bg.gif'] styleFiles += [f for f in self.styleDir.files("*.css") if f.basename() <> "nav.css"] styleFiles += self.styleDir.files("*.jpg") styleFiles += self.styleDir.files("*.gif") styleFiles += self.styleDir.files("*.png") styleFiles += self.styleDir.files("*.js") styleFiles += self.styleDir.files("*.html") if self.scormType == "commoncartridge": for sf in styleFiles[:]: if sf.basename() not in manifest.dependencies: styleFiles.remove(sf) self.styleDir.copylist(styleFiles, outputDir) package.resourceDir.copyfiles(outputDir) if self.scormType == "commoncartridge": self.scriptsDir.copylist(('libot_drag.js', 'common.js'), outputDir) else: self.scriptsDir.copylist(('APIWrapper.js', 'SCOFunctions.js', 'libot_drag.js', 'common.js'), outputDir) schemasDir = "" if self.scormType == "scorm1.2": schemasDir = self.schemasDir/"scorm1.2" schemasDir.copylist(('imscp_rootv1p1p2.xsd', 'imsmd_rootv1p2p1.xsd', 'adlcp_rootv1p2.xsd', 'ims_xml.xsd'), outputDir) elif self.scormType == "scorm2004": schemasDir = self.schemasDir/"scorm2004" schemasDir.copylist(('imscp_rootv1p1p2.xsd', 'imsmd_rootv1p2p1.xsd', 'adlcp_rootv1p2.xsd', 'ims_xml.xsd'), outputDir) hasFlowplayer = False hasMagnifier = False hasXspfplayer = False isBreak = False for page in self.pages: if isBreak: break for idevice in page.node.idevices: if (hasFlowplayer and hasMagnifier and hasXspfplayer): isBreak = True break if not hasFlowplayer: if 'flowPlayer.swf' in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if 'magnifier.swf' in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if 'xspf_player.swf' in idevice.systemResources: hasXspfplayer = True if hasFlowplayer: videofile = (self.templatesDir/'flowPlayer.swf') videofile.copyfile(outputDir/'flowPlayer.swf') if hasMagnifier: videofile = (self.templatesDir/'magnifier.swf') videofile.copyfile(outputDir/'magnifier.swf') if hasXspfplayer: videofile = (self.templatesDir/'xspf_player.swf') videofile.copyfile(outputDir/'xspf_player.swf') if self.scormType == "scorm1.2" or self.scormType == "scorm2004": (self.templatesDir/'fdl.html').copyfile(outputDir/'fdl.html') self.filename.safeSave(self.doZip, _('EXPORT FAILED!\nLast succesful export is %s.'), outputDir) outputDir.rmtree()
def export(self, package): """ Export SCORM package """ # First do the export to a temporary directory outputDir = TempDirPath() self.metadataType = package.exportMetadataType # copy the package's resource files for resourceFile in package.resourceDir.walkfiles(): file = package.resourceDir.relpathto(resourceFile) if ("/" in file): Dir = Path(outputDir / file[:file.rindex("/")]) if not Dir.exists(): Dir.makedirs() resourceFile.copy(outputDir / Dir) else: resourceFile.copy(outputDir) # copy the package's resource files, only non existant in outputDir # outputDirFiles = outputDir.files() # for rfile in package.resourceDir.files(): # if rfile not in outputDirFiles: # rfile.copy(outputDir) # copy the package's resource files, only indexed in package.resources # for md5 in package.resources.values(): # for resource in md5: # resource.path.copy(outputDir) # Export the package content # Import the Scorm Page class , if the secure mode is off. If the style has it's own page class # use that, else use the default one. if self.styleSecureMode == "0": if (self.styleDir / "scormpage.py").exists(): global ScormPage module = imp.load_source("ScormPage", self.styleDir / "scormpage.py") ScormPage = module.ScormPage self.pages = [ ScormPage("index", 1, package.root, scormType=self.scormType, metadataType=self.metadataType) ] self.generatePages(package.root, 2) uniquifyNames(self.pages) for page in self.pages: page.save(outputDir, self.pages) if not self.hasForum: for idevice in page.node.idevices: if hasattr(idevice, "isForum"): if idevice.forum.lms.lms == "moodle": self.hasForum = True break # Create the manifest file manifest = Manifest(self.config, outputDir, package, self.pages, self.scormType, self.metadataType) modifiedMetaData = manifest.save("imsmanifest.xml") # Create lang file langFile = open(outputDir + '/common_i18n.js', "w") langFile.write(common.getJavaScriptStrings(False)) langFile.close() if self.hasForum: manifest.save("discussionforum.xml") # Copy the style files to the output dir styleFiles = [self.styleDir / '..' / 'popup_bg.gif'] # And with all the files of the style we avoid problems: styleFiles += self.styleDir.files("*.*") if self.scormType == "commoncartridge": for sf in styleFiles[:]: if sf.basename() not in manifest.dependencies: styleFiles.remove(sf) self.styleDir.copylist(styleFiles, outputDir) listCSSFiles = getFilesCSSToMinify('scorm', self.styleDir) exportMinFileCSS(listCSSFiles, outputDir) # Copy the scripts dT = common.getExportDocType() if dT == "HTML5": #listFiles+=[self.scriptsDir/'exe_html5.js'] #listOutFiles+=[outputDir/'exe_html5.js'] jsFile = (self.scriptsDir / 'exe_html5.js') jsFile.copyfile(outputDir / 'exe_html5.js') # jQuery my_style = G.application.config.styleStore.getStyle( page.node.package.style) if my_style.hasValidConfig(): if my_style.get_jquery() == True: #listFiles+=[self.scriptsDir/'exe_jquery.js'] #listOutFiles+=[outputDir/'exe_jquery.js'] jsFile = (self.scriptsDir / 'exe_jquery.js') jsFile.copyfile(outputDir / 'exe_jquery.js') else: #listFiles+=[self.scriptsDir/'exe_jquery.js'] #listOutFiles+=[outputDir/'exe_jquery.js'] jsFile = (self.scriptsDir / 'exe_jquery.js') jsFile.copyfile(outputDir / 'exe_jquery.js') if self.scormType == "commoncartridge" or self.scormType == "scorm2004" or self.scormType == "scorm1.2": listFiles = getFilesJSToMinify('scorm', self.scriptsDir) exportMinFileJS(listFiles, outputDir) if self.scormType == "scorm2004" or self.scormType == "scorm1.2": self.scriptsDir.copylist( ('SCORM_API_wrapper.js', 'SCOFunctions.js'), outputDir) # about SCHEMAS: schemasDir = "" if self.scormType == "scorm1.2": schemasDir = self.schemasDir / "scorm1.2" schemasDir.copylist(('imscp_rootv1p1p2.xsd', 'imsmd_rootv1p2p1.xsd', 'adlcp_rootv1p2.xsd', 'lom.xsd', 'lomCustom.xsd', 'ims_xml.xsd'), outputDir) elif self.scormType == "scorm2004": schemasDir = self.schemasDir / "scorm2004" schemasDir.copylist( ('adlcp_v1p3.xsd', 'adlnav_v1p3.xsd', 'adlseq_v1p3.xsd', 'datatypes.dtd', 'imscp_v1p1.xsd', 'imsssp_v1p0.xsd', 'imsss_v1p0.xsd', 'imsss_v1p0auxresource.xsd', 'imsss_v1p0control.xsd', 'imsss_v1p0delivery.xsd', 'imsmd_rootv1p2p1.xsd', 'imsss_v1p0limit.xsd', 'imsss_v1p0objective.xsd', 'imsss_v1p0random.xsd', 'imsss_v1p0rollup.xsd', 'imsss_v1p0seqrule.xsd', 'imsss_v1p0util.xsd', 'ims_xml.xsd', 'lom.xsd', 'lomCustom.xsd', 'xml.xsd', 'XMLSchema.dtd'), outputDir) try: import shutil, errno shutil.copytree(schemasDir / "common", outputDir / "common") shutil.copytree(schemasDir / "extend", outputDir / "extend") shutil.copytree(schemasDir / "unique", outputDir / "unique") shutil.copytree(schemasDir / "vocab", outputDir / "vocab") except OSError as exc: if exc.errno == errno.ENOTDIR: shutil.copy(schemasDir, outputDir) else: raise # copy players for media idevices. hasFlowplayer = False hasMagnifier = False hasXspfplayer = False hasGallery = False hasFX = False hasSH = False hasGames = False hasElpLink = False hasWikipedia = False isBreak = False hasInstructions = False hasMediaelement = False hasTooltips = False hasABCMusic = False listIdevicesFiles = [] for page in self.pages: if isBreak: break for idevice in page.node.idevices: if (hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery and hasFX and hasSH and hasGames and hasElpLink and hasWikipedia and hasInstructions and hasMediaelement and hasTooltips and hasABCMusic): isBreak = True break if not hasFlowplayer: if 'flowPlayer.swf' in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if 'mojomagnify.js' in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if 'xspf_player.swf' in idevice.systemResources: hasXspfplayer = True if not hasGallery: hasGallery = common.ideviceHasGallery(idevice) if not hasFX: hasFX = common.ideviceHasFX(idevice) if not hasSH: hasSH = common.ideviceHasSH(idevice) if not hasGames: hasGames = common.ideviceHasGames(idevice) if not hasElpLink: hasElpLink = common.ideviceHasElpLink(idevice, package) if not hasWikipedia: if 'WikipediaIdevice' == idevice.klass: hasWikipedia = True if not hasInstructions: if 'TrueFalseIdevice' == idevice.klass or 'MultichoiceIdevice' == idevice.klass or 'VerdaderofalsofpdIdevice' == idevice.klass or 'EleccionmultiplefpdIdevice' == idevice.klass: hasInstructions = True if not hasMediaelement: hasMediaelement = common.ideviceHasMediaelement(idevice) if not hasTooltips: hasTooltips = common.ideviceHasTooltips(idevice) if not hasABCMusic: hasABCMusic = common.ideviceHasABCMusic(idevice) if hasattr(idevice, "_iDeviceDir"): listIdevicesFiles.append( (idevice.get_jsidevice_dir() / 'export')) common.exportJavaScriptIdevicesFiles(page.node.idevices, outputDir) if hasFlowplayer: videofile = (self.templatesDir / 'flowPlayer.swf') videofile.copyfile(outputDir / 'flowPlayer.swf') controlsfile = (self.templatesDir / 'flowplayer.controls.swf') controlsfile.copyfile(outputDir / 'flowplayer.controls.swf') if hasMagnifier: videofile = (self.templatesDir / 'mojomagnify.js') videofile.copyfile(outputDir / 'mojomagnify.js') if hasXspfplayer: videofile = (self.templatesDir / 'xspf_player.swf') videofile.copyfile(outputDir / 'xspf_player.swf') if hasGallery: exeLightbox = (self.scriptsDir / 'exe_lightbox') exeLightbox.copyfiles(outputDir) if hasFX: exeEffects = (self.scriptsDir / 'exe_effects') exeEffects.copyfiles(outputDir) if hasSH: exeSH = (self.scriptsDir / 'exe_highlighter') exeSH.copyfiles(outputDir) if hasGames: exeGames = (self.scriptsDir / 'exe_games') exeGames.copyfiles(outputDir) # Add game js string to common_i18n langGameFile = open(outputDir + '/common_i18n.js', "a") langGameFile.write(common.getGamesJavaScriptStrings(False)) langGameFile.close() if hasElpLink or package.get_exportElp(): # Export the elp file currentPackagePath = Path(package.filename) currentPackagePath.copyfile(outputDir / package.name + '.elp') if hasWikipedia: wikipediaCSS = (self.cssDir / 'exe_wikipedia.css') wikipediaCSS.copyfile(outputDir / 'exe_wikipedia.css') if hasInstructions: common.copyFileIfNotInStyle('panel-amusements.png', self, outputDir) common.copyFileIfNotInStyle('stock-stop.png', self, outputDir) if hasMediaelement: mediaelement = (self.scriptsDir / 'mediaelement') mediaelement.copyfiles(outputDir) if dT != "HTML5": jsFile = (self.scriptsDir / 'exe_html5.js') if hasTooltips: exe_tooltips = (self.scriptsDir / 'exe_tooltips') exe_tooltips.copyfiles(outputDir) if hasABCMusic: pluginScripts = (self.scriptsDir / 'tinymce_4/js/tinymce/plugins/abcmusic/export') pluginScripts.copyfiles(outputDir) ext = ".html" if G.application.config.cutFileName == "1": ext = ".htm" if self.scormType == "scorm1.2" or self.scormType == "scorm2004": if package.license == "license GFDL": # include a copy of the GNU Free Documentation Licence (self.templatesDir / 'fdl' + ext).copyfile(outputDir / 'fdl' + ext) if hasattr(package, 'scowsinglepage') and package.scowsinglepage: page = SinglePage("singlepage_index", 1, package.root) page.save(outputDir / "singlepage_index" + ext) # Incluide eXe's icon if the Style doesn't have one themePath = Path(G.application.config.stylesDir / package.style) themeFavicon = themePath.joinpath("favicon.ico") if not themeFavicon.exists(): faviconFile = (self.imagesDir / 'favicon.ico') faviconFile.copyfile(outputDir / 'favicon.ico') if hasattr(package, 'scowwebsite') and package.scowwebsite: website = WebsiteExport(self.config, self.styleDir, outputDir, "website_") website.export(package) (self.styleDir / 'nav.css').copyfile(outputDir / 'nav.css') # Incluide eXe's icon if the Style doesn't have one themePath = Path(G.application.config.stylesDir / package.style) themeFavicon = themePath.joinpath("favicon.ico") if not themeFavicon.exists(): faviconFile = (self.imagesDir / 'favicon.ico') faviconFile.copyfile(outputDir / 'favicon.ico') if hasattr(package, 'exportSource') and package.exportSource: (G.application.config.webDir / 'templates' / 'content.xsd').copyfile(outputDir / 'content.xsd') (outputDir / 'content.data').write_bytes(encodeObject(package)) (outputDir / 'contentv3.xml').write_bytes( encodeObjectToXML(package)) # Zip it up! self.filename.safeSave( self.doZip, _('EXPORT FAILED!\nLast succesful export is %s.'), outputDir) # Clean up the temporary dir outputDir.rmtree() return modifiedMetaData
class WikipediaIdevice(Idevice): """ A Wikipedia Idevice is one built from a Wikipedia article. """ persistenceVersion = 9 def __init__(self, defaultSite): Idevice.__init__( self, x_(u"Wiki Article"), x_(u"University of Auckland"), x_(u"""<p>The Wikipedia iDevice allows you to locate existing content from within Wikipedia and download this content into your eXe resource. The Wikipedia Article iDevice takes a snapshot copy of the article content. Changes in Wikipedia will not automatically update individual snapshot copies in eXe, a fresh copy of the article will need to be taken. Likewise, changes made in eXe will not be updated in Wikipedia. </p> <p>Wikipedia content is covered by the GNU Free Documentation 1.2 License, and since 2009 additionally by the Creative Commons Attribution-ShareAlike 3.0 Unported License.</p>"""), u"", u"") self.emphasis = Idevice.NoEmphasis self.articleName = u"" self.article = TextAreaField(x_(u"Article")) self.article.idevice = self self.images = {} self.site = defaultSite self.icon = u"inter" self._langInstruc = x_(u"""Select the appropriate language version of Wikipedia to search and enter search term.""") self._searchInstruc = x_("""Enter a phrase or term you wish to search within Wikipedia.""") self.ownUrl = "" self.systemResources += ['exe_wikipedia.css'] # Properties langInstruc = lateTranslate('langInstruc') searchInstruc = lateTranslate('searchInstruc') def loadArticle(self, name): """ Load the article from Wikipedia """ self.articleName = name url = '' name = urllib.quote(name.replace(" ", "_").encode('utf-8')) # Get the full URL of the site url = self.site or self.ownUrl if not url.endswith('/') and name != '': url += '/' if '://' not in url: url = 'http://' + url url += name # Get the site content try: net = urllib.urlopen(url) page = net.read() net.close() except IOError, error: log.warning(unicode(error)) self.article.content = _( u"Unable to download from %s <br/>Please check the spelling and connection and try again." ) % url self.article.content_w_resourcePaths = self.article.content self.article.content_wo_resourcePaths = self.article.content return page = unicode(page, "utf8") # FIXME avoid problems with numeric entities in attributes page = page.replace(u' ', u' ') # avoidParserProblems is set to False because BeautifulSoup's # cleanup was causing a "concatenating Null+Str" error, # and Wikipedia's HTML doesn't need cleaning up. # BeautifulSoup is faster this way too. soup = BeautifulSoup(page, False) content = soup.first('div', {'id': "content"}) # Fix bug #1359: El estilo ITE no respeta ancho de página al exportar # a páginas web si se usa iDevice wikipedia content['id'] = "wikipedia-content" # remove the wiktionary, wikimedia commons, and categories boxes # and the protected icon and the needs citations box if content: infoboxes = content.findAll('div', {'class': 'infobox sisterproject'}) [infobox.extract() for infobox in infoboxes] catboxes = content.findAll('div', {'id': 'catlinks'}) [catbox.extract() for catbox in catboxes] amboxes = content.findAll('table', {'class': re.compile(r'.*\bambox\b.*')}) [ambox.extract() for ambox in amboxes] protecteds = content.findAll('div', {'id': 'protected-icon'}) [protected.extract() for protected in protecteds] # Extract HTML comments comments = content.findAll( text=lambda text: isinstance(text, Comment)) [comment.extract() for comment in comments] else: content = soup.first('body') # If we still don't have content it means there is a problem with the article if not content: log.error(u"No content on Wikipedia article: %s" % url) self.article.content = _( u"Unable to download from %s <br/>Please check the spelling and connection and try again." ) % url # Set the other elements as well self.article.content_w_resourcePaths = self.article.content self.article.content_wo_resourcePaths = self.article.content return # Clear out any old images while self.userResources: self.userResources[0].delete() self.images = {} # Download the images bits = url.split('/') netloc = '%s//%s' % (bits[0], bits[2]) path = '/'.join(bits[3:-1]) tmpDir = TempDirPath() # Fetch all images from content for imageTag in content.fetch('img'): # Get src and image filename imageSrc = unicode(imageTag['src']) imageName = imageSrc.split('/')[-1] imageName = imageName.replace('>', '>') imageName = imageName.replace('<', '<') imageName = imageName.replace('"', '"') imageName = imageName.replace(' ', '') imageName = imageName.replace('%2C', ',') imageName = imageName.replace('%22', '"') imageName = imageName.replace('%28', '(') imageName = imageName.replace('%29', ')') imageName = imageName.replace('%C3%A5', 'å') # Decode image name imageName = urllib.unquote(imageName) # Search if we've already got this image if imageName not in self.images: if not re.match("^http(s)?:\/\/", imageSrc): if imageSrc.startswith("/"): imageSrc = bits[0] + imageSrc else: imageSrc = '%s/%s/%s' % (netloc, path, imageSrc) try: # download with its original name... in ASCII: ## er... just because some repositories do not undestand no ascii names of files: imageName = imageName.encode('ascii', 'ignore') # If the image file doesn't have an extension try to guess it if not re.match('^.*\.(.){1,}', imageName): # Open a conecction with the image and get the headers online_resource = urllib.urlopen(imageSrc) image_info = online_resource.info() online_resource.close() # Try to guess extension from mimetype extension = mimetypes.guess_extension( image_info['content-type']) # Wikimedia uses mainly SVG images so we can safely say that # this image is in svg (if it wasn't if wouldn't be shown anyway) extension = extenion or '.svg' imageName = imageName + extension # Download image urllib.urlretrieve(imageSrc, tmpDir / imageName) # Add the new resource new_resource = Resource(self, tmpDir / imageName) except: log.error(u'Unable to download file: %s' % imageSrc) # If there is an exception try to get the next one continue if new_resource._storageName != imageName: # looks like it was changed due to a possible conflict, # so reset the imageName accordingly for the content: imageName = new_resource._storageName self.images[imageName] = True imageTag['src'] = u"resources/" + imageName self.article.content = self.reformatArticle(netloc, unicode(content)) # now that these are supporting images, any direct manipulation # of the content field must also store this updated information # into the other corresponding fields of TextAreaField: # (perhaps eventually a property should be made for TextAreaField # such that these extra set's are not necessary, but for now, here:) self.article.content_w_resourcePaths = self.article.content self.article.content_wo_resourcePaths = self.article.content
def export(self, package): """ Export epub 3 package """ # First do the export to a temporary directory outputDir = TempDirPath() ''' fileDir = outputDir/"META-INF" fileDir.mkdir() fileDir = outputDir/"Content" fileDir.mkdir() ''' metainfPages = Path(outputDir.abspath() + '/META-INF') # metainfPages = outputDir/'META-INF' metainfPages.mkdir() contentPages = Path(outputDir.abspath() + '/EPUB') # contentPages = outputDir/'Content' contentPages.mkdir() # print contentPages.abspath() # print outputDir.abspath() # Export the package content self.pages = [Epub3Cover("cover", 1, package.root)] self.generatePages(package.root, 2) uniquifyNames(self.pages) cover = None for page in self.pages: page.save(contentPages, self.pages) if hasattr(page, 'cover'): cover = page.cover # Create mimetype file mimetypeFile = open(outputDir.abspath() + '/mimetype', "w") mimetypeFile.write('application/epub+zip') mimetypeFile.close() # Create common_i18n file langFile = open(contentPages + '/common_i18n.js', "w") langFile.write(common.getJavaScriptStrings(False)) langFile.close() # Copy the style files to the output dir # But not nav.css styleFiles = [self.styleDir /'..'/ 'popup_bg.gif'] styleFiles += [f for f in self.styleDir.files("*.*") if f.basename() not in ['nav.css']] # FIXME for now, only copy files referenced in Common Cartridge # this really should apply to all exports, but without a manifest # of the files needed by an included stylesheet it is too restrictive # Add fallback document for possible image links if Path(self.styleDir/'fallback.xhtml').exists(): styleFiles += [self.styleDir /'fallback.xhtml'] else: styleFiles += [self.styleDir/'..'/'fallback.xhtml'] # copy the package's resource files for resourceFile in package.resourceDir.walkfiles(): fn = package.resourceDir.relpathto(resourceFile) if ("/" in fn): Dir = Path(contentPages/fn[:fn.rindex("/")]) if not Dir.exists(): Dir.makedirs() resourceFile.copy(contentPages/Dir) else: resourceFile.copy(contentPages) self.styleDir.copylist(styleFiles, contentPages) # copy players for media idevices. hasFlowplayer = False hasMagnifier = False hasXspfplayer = False hasGallery = False hasFX = False hasSH = False hasGames = False hasElpLink = False hasWikipedia = False isBreak = False hasInstructions = False hasTooltips = False hasABCMusic = False for page in self.pages: if isBreak: break for idevice in page.node.idevices: if (hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery and hasFX and hasSH and hasGames and hasElpLink and hasWikipedia and hasInstructions and hasTooltips and hasABCMusic): isBreak = True break if not hasFlowplayer: if 'flowPlayer.swf' in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if 'mojomagnify.js' in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if 'xspf_player.swf' in idevice.systemResources: hasXspfplayer = True if not hasGallery: hasGallery = common.ideviceHasGallery(idevice) if not hasFX: hasFX = common.ideviceHasFX(idevice) if not hasSH: hasSH = common.ideviceHasSH(idevice) if not hasGames: hasGames = common.ideviceHasGames(idevice) if not hasElpLink: hasElpLink = common.ideviceHasElpLink(idevice,package) if not hasWikipedia: if 'WikipediaIdevice' == idevice.klass: hasWikipedia = True if not hasInstructions: if 'TrueFalseIdevice' == idevice.klass or 'MultichoiceIdevice' == idevice.klass or 'VerdaderofalsofpdIdevice' == idevice.klass or 'EleccionmultiplefpdIdevice' == idevice.klass: hasInstructions = True if not hasTooltips: hasTooltips = common.ideviceHasTooltips(idevice) if not hasABCMusic: hasABCMusic = common.ideviceHasABCMusic(idevice) common.exportJavaScriptIdevicesFiles(page.node.idevices, contentPages); if hasFlowplayer: videofile = (self.templatesDir / 'flowPlayer.swf') videofile.copyfile(contentPages / 'flowPlayer.swf') controlsfile = (self.templatesDir / 'flowplayer.controls.swf') controlsfile.copyfile(contentPages / 'flowplayer.controls.swf') if hasMagnifier: videofile = (self.templatesDir / 'mojomagnify.js') videofile.copyfile(contentPages / 'mojomagnify.js') if hasXspfplayer: videofile = (self.templatesDir / 'xspf_player.swf') videofile.copyfile(contentPages / 'xspf_player.swf') if hasGallery: exeLightbox = (self.scriptsDir / 'exe_lightbox') exeLightbox.copyfiles(contentPages) if hasFX: exeEffects = (self.scriptsDir / 'exe_effects') exeEffects.copyfiles(contentPages) if hasSH: exeSH = (self.scriptsDir / 'exe_highlighter') exeSH.copyfiles(contentPages) if hasGames: exeGames = (self.scriptsDir / 'exe_games') exeGames.copyfiles(contentPages) # Add game js string to common_i18n langGameFile = open(contentPages + '/common_i18n.js', "a") langGameFile.write(common.getGamesJavaScriptStrings(False)) langGameFile.close() if hasElpLink or package.get_exportElp(): # Export the elp file currentPackagePath = Path(package.filename) currentPackagePath.copyfile(contentPages/package.name+'.elp') if hasWikipedia: wikipediaCSS = (self.cssDir / 'exe_wikipedia.css') wikipediaCSS.copyfile(contentPages / 'exe_wikipedia.css') if hasInstructions: common.copyFileIfNotInStyle('panel-amusements.png', self, contentPages) common.copyFileIfNotInStyle('stock-stop.png', self, contentPages) if hasTooltips: exe_tooltips = (self.scriptsDir / 'exe_tooltips') exe_tooltips.copyfiles(contentPages) if hasABCMusic: pluginScripts = (self.scriptsDir/'tinymce_4/js/tinymce/plugins/abcmusic/export') pluginScripts.copyfiles(contentPages) my_style = G.application.config.styleStore.getStyle(package.style) if my_style.hasValidConfig: if my_style.get_jquery() == True: jsFile = (self.scriptsDir / 'exe_jquery.js') jsFile.copyfile(contentPages / 'exe_jquery.js') else: jsFile = (self.scriptsDir / 'exe_jquery.js') jsFile.copyfile(contentPages / 'exe_jquery.js') # Copy and minify CSS files css_files = getFilesCSSToMinify('epub3', self.styleDir) exportMinFileCSS(css_files, contentPages) # Copy and minify JS files js_files = getFilesJSToMinify('epub3', self.scriptsDir) exportMinFileJS(js_files, contentPages) # if hasattr(package, 'exportSource') and package.exportSource: # (G.application.config.webDir / 'templates' / 'content.xsd').copyfile(outputDir / 'content.xsd') # (outputDir / 'content.data').write_bytes(encodeObject(package)) # (outputDir / 'contentv3.xml').write_bytes(encodeObjectToXML(package)) if package.license == "license GFDL": # include a copy of the GNU Free Documentation Licence (self.templatesDir / 'fdl.html').copyfile(contentPages / 'fdl.html') # Create the nav.xhtml file container = NavEpub3(self.pages, contentPages) container.save() # Create the publication file publication = PublicationEpub3(self.config, contentPages, package, self.pages, cover) publication.save("package.opf") # Create the container file container = ContainerEpub3(metainfPages) container.save("container.xml") # Zip it up! self.filename.safeSave(self.doZip, _(u'EXPORT FAILED!\nLast succesful export is %s.'), outputDir) # Clean up the temporary dir outputDir.rmtree()
def export(self, package): """ Export SCORM package """ # First do the export to a temporary directory outputDir = TempDirPath() self.metadataType = package.exportMetadataType # Copy the style sheet files to the output dir # But not nav.css styleFiles = [self.styleDir/'..'/'popup_bg.gif'] styleFiles += self.styleDir.files("*.css") if "nav.css" in styleFiles: styleFiles.remove("nav.css") styleFiles += self.styleDir.files("*.jpg") styleFiles += self.styleDir.files("*.gif") styleFiles += self.styleDir.files("*.png") styleFiles += self.styleDir.files("*.js") styleFiles += self.styleDir.files("*.html") styleFiles += self.styleDir.files("*.ttf") styleFiles += self.styleDir.files("*.eot") styleFiles += self.styleDir.files("*.otf") styleFiles += self.styleDir.files("*.woff") self.styleDir.copylist(styleFiles, outputDir) # copy the package's resource files package.resourceDir.copyfiles(outputDir) listCSSFiles=getFilesCSSToMinify('ims', self.styleDir) exportMinFileCSS(listCSSFiles, outputDir) # Export the package content self.pages = [ IMSPage("index", 1, package.root, metadataType=self.metadataType) ] self.generatePages(package.root, 2) uniquifyNames(self.pages) for page in self.pages: page.save(outputDir) # Create the manifest file manifest = Manifest(self.config, outputDir, package, self.pages, self.metadataType) manifest.save("imsmanifest.xml") # Copy the scripts # jQuery my_style = G.application.config.styleStore.getStyle(page.node.package.style) if my_style.hasValidConfig: if my_style.get_jquery() == True: jsFile = (self.scriptsDir/'exe_jquery.js') jsFile.copyfile(outputDir/'exe_jquery.js') else: jsFile = (self.scriptsDir/'exe_jquery.js') jsFile.copyfile(outputDir/'exe_jquery.js') dT = common.getExportDocType() if dT == "HTML5": jsFile = (self.scriptsDir/'exe_html5.js') jsFile.copyfile(outputDir/'exe_html5.js') listFiles=getFilesJSToMinify('ims', self.scriptsDir) exportMinFileJS(listFiles, outputDir) self.schemasDir.copylist(('imscp_v1p1.xsd', 'imsmd_v1p2p2.xsd', 'lom.xsd', 'lomCustom.xsd', 'ims_xml.xsd'), outputDir) # copy players for media idevices. hasFlowplayer = False hasMagnifier = False hasXspfplayer = False hasGallery = False hasFX = False hasSH = False hasGames = False hasWikipedia = False isBreak = False hasInstructions = False hasMediaelement = False hasTooltips = False for page in self.pages: if isBreak: break for idevice in page.node.idevices: if (hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery and hasFX and hasSH and hasGames and hasWikipedia and hasInstructions and hasMediaelement and hasTooltips): isBreak = True break if not hasFlowplayer: if 'flowPlayer.swf' in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if 'mojomagnify.js' in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if 'xspf_player.swf' in idevice.systemResources: hasXspfplayer = True if not hasGallery: hasGallery = common.ideviceHasGallery(idevice) if not hasFX: hasFX = common.ideviceHasFX(idevice) if not hasSH: hasSH = common.ideviceHasSH(idevice) if not hasGames: hasGames = common.ideviceHasGames(idevice) if not hasWikipedia: if 'WikipediaIdevice' == idevice.klass: hasWikipedia = True if not hasInstructions: if 'TrueFalseIdevice' == idevice.klass or 'MultichoiceIdevice' == idevice.klass or 'VerdaderofalsofpdIdevice' == idevice.klass or 'EleccionmultiplefpdIdevice' == idevice.klass: hasInstructions = True if not hasMediaelement: hasMediaelement = common.ideviceHasMediaelement(idevice) if not hasTooltips: hasTooltips = common.ideviceHasTooltips(idevice) if hasFlowplayer: videofile = (self.templatesDir/'flowPlayer.swf') videofile.copyfile(outputDir/'flowPlayer.swf') controlsfile = (self.templatesDir/'flowplayer.controls.swf') controlsfile.copyfile(outputDir/'flowplayer.controls.swf') if hasMagnifier: videofile = (self.templatesDir/'mojomagnify.js') videofile.copyfile(outputDir/'mojomagnify.js') if hasXspfplayer: videofile = (self.templatesDir/'xspf_player.swf') videofile.copyfile(outputDir/'xspf_player.swf') if hasGallery: exeLightbox = (self.scriptsDir/'exe_lightbox') exeLightbox.copyfiles(outputDir) if hasFX: exeEffects = (self.scriptsDir/'exe_effects') exeEffects.copyfiles(outputDir) if hasSH: exeSH = (self.scriptsDir/'exe_highlighter') exeSH.copyfiles(outputDir) if hasGames: exeGames = (self.scriptsDir/'exe_games') exeGames.copyfiles(outputDir) if hasWikipedia: wikipediaCSS = (self.cssDir/'exe_wikipedia.css') wikipediaCSS.copyfile(outputDir/'exe_wikipedia.css') if hasInstructions: common.copyFileIfNotInStyle('panel-amusements.png', self, outputDir) common.copyFileIfNotInStyle('stock-stop.png', self, outputDir) if hasMediaelement: mediaelement = (self.scriptsDir/'mediaelement') mediaelement.copyfiles(outputDir) if dT != "HTML5": jsFile = (self.scriptsDir/'exe_html5.js') jsFile.copyfile(outputDir/'exe_html5.js') if hasTooltips: exe_tooltips = (self.scriptsDir/'exe_tooltips') exe_tooltips.copyfiles(outputDir) if hasattr(package, 'exportSource') and package.exportSource: (G.application.config.webDir/'templates'/'content.xsd').copyfile(outputDir/'content.xsd') (outputDir/'content.data').write_bytes(encodeObject(package)) (outputDir/'contentv3.xml').write_bytes(encodeObjectToXML(package)) if package.license == "license GFDL": # include a copy of the GNU Free Documentation Licence (self.templatesDir/'fdl.html').copyfile(outputDir/'fdl.html') # Zip it up! self.filename.safeSave(self.doZip, _('EXPORT FAILED!\nLast succesful export is %s.'), outputDir) # Clean up the temporary dir outputDir.rmtree()
def export(self, package): """ Export SCORM package """ # First do the export to a temporary directory outputDir = TempDirPath() # copy the package's resource files package.resourceDir.copyfiles(outputDir) # copy the package's resource files, only non existant in outputDir # outputDirFiles = outputDir.files() # for rfile in package.resourceDir.files(): # if rfile not in outputDirFiles: # rfile.copy(outputDir) # copy the package's resource files, only indexed in package.resources # for md5 in package.resources.values(): # for resource in md5: # resource.path.copy(outputDir) # Export the package content self.pages = [ ScormPage("index", 1, package.root, scormType=self.scormType) ] self.generatePages(package.root, 2) uniquifyNames(self.pages) for page in self.pages: page.save(outputDir) if not self.hasForum: for idevice in page.node.idevices: if hasattr(idevice, "isForum"): if idevice.forum.lms.lms == "moodle": self.hasForum = True break # Create the manifest file manifest = Manifest(self.config, outputDir, package, self.pages, self.scormType) manifest.save("imsmanifest.xml") if self.hasForum: manifest.save("discussionforum.xml") # Copy the style sheet files to the output dir # But not nav.css styleFiles = [self.styleDir/'..'/'base.css'] styleFiles += [self.styleDir/'..'/'popup_bg.gif'] styleFiles += [f for f in self.styleDir.files("*.css") if f.basename() <> "nav.css"] styleFiles += self.styleDir.files("*.jpg") styleFiles += self.styleDir.files("*.gif") styleFiles += self.styleDir.files("*.png") styleFiles += self.styleDir.files("*.js") styleFiles += self.styleDir.files("*.html") styleFiles += self.styleDir.files("*.ttf") styleFiles += self.styleDir.files("*.eot") styleFiles += self.styleDir.files("*.otf") styleFiles += self.styleDir.files("*.woff") # FIXME for now, only copy files referenced in Common Cartridge # this really should apply to all exports, but without a manifest # of the files needed by an included stylesheet it is too restrictive if self.scormType == "commoncartridge": for sf in styleFiles[:]: if sf.basename() not in manifest.dependencies: styleFiles.remove(sf) self.styleDir.copylist(styleFiles, outputDir) # Copy the scripts if self.scormType == "commoncartridge": self.scriptsDir.copylist(('libot_drag.js', 'common.js'), outputDir) else: self.scriptsDir.copylist(('APIWrapper.js', 'lernmodule_net.js', 'SCOFunctions.js', 'libot_drag.js', 'common.js'), outputDir) schemasDir = "" if self.scormType == "scorm1.2": schemasDir = self.schemasDir/"scorm1.2" schemasDir.copylist(('imscp_rootv1p1p2.xsd', 'imsmd_rootv1p2p1.xsd', 'adlcp_rootv1p2.xsd', 'ims_xml.xsd'), outputDir) elif self.scormType == "scorm2004": schemasDir = self.schemasDir/"scorm2004" schemasDir.copylist(('imscp_rootv1p1p2.xsd', 'imsmd_rootv1p2p1.xsd', 'adlcp_rootv1p2.xsd', 'ims_xml.xsd'), outputDir) # copy players for media idevices. hasFlowplayer = False hasMagnifier = False hasXspfplayer = False hasGallery = False isBreak = False for page in self.pages: if isBreak: break for idevice in page.node.idevices: if (hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery): isBreak = True break if not hasFlowplayer: if 'flowPlayer.swf' in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if 'magnifier.swf' in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if 'xspf_player.swf' in idevice.systemResources: hasXspfplayer = True if not hasGallery: if 'GalleryIdevice' == idevice.klass: hasGallery = True if hasFlowplayer: videofile = (self.templatesDir/'flowPlayer.swf') videofile.copyfile(outputDir/'flowPlayer.swf') controlsfile = (self.templatesDir/'flowplayer.controls.swf') controlsfile.copyfile(outputDir/'flowplayer.controls.swf') if hasMagnifier: videofile = (self.templatesDir/'magnifier.swf') videofile.copyfile(outputDir/'magnifier.swf') if hasXspfplayer: videofile = (self.templatesDir/'xspf_player.swf') videofile.copyfile(outputDir/'xspf_player.swf') if hasGallery: imageGalleryCSS = (self.cssDir/'exe_lightbox.css') imageGalleryCSS.copyfile(outputDir/'exe_lightbox.css') imageGalleryJS = (self.scriptsDir/'exe_lightbox.js') imageGalleryJS.copyfile(outputDir/'exe_lightbox.js') self.imagesDir.copylist(('exeGallery_actions.png', 'exeGallery_loading.gif'), outputDir) if self.scormType == "scorm1.2" or self.scormType == "scorm2004": if package.license == "GNU Free Documentation License": # include a copy of the GNU Free Documentation Licence (self.templatesDir/'fdl.html').copyfile(outputDir/'fdl.html') if hasattr(package, 'scowsinglepage') and package.scowsinglepage: page = SinglePage("singlepage_index", 1, package.root) page.save(outputDir/"singlepage_index.html") if hasattr(package, 'scowwebsite') and package.scowwebsite: website = WebsiteExport(self.config, self.styleDir, outputDir, "website_") website.export(package) (self.styleDir/'nav.css').copyfile(outputDir/'nav.css') if hasattr(package, 'scowsource') and package.scowsource: (G.application.config.xulDir/'templates'/'content.xsd').copyfile(outputDir/'content.xsd') (outputDir/'content.data').write_bytes(encodeObject(package)) (outputDir/'contentv2.xml').write_bytes(encodeObjectToXML(package)) # Zip it up! self.filename.safeSave(self.doZip, _('EXPORT FAILED!\nLast succesful export is %s.'), outputDir) # Clean up the temporary dir outputDir.rmtree()
def export(self, package): """ Export epub 3 package """ # First do the export to a temporary directory outputDir = TempDirPath() ''' fileDir = outputDir/"META-INF" fileDir.mkdir() fileDir = outputDir/"Content" fileDir.mkdir() ''' metainfPages = Path(outputDir.abspath() + '/META-INF') # metainfPages = outputDir/'META-INF' metainfPages.mkdir() contentPages = Path(outputDir.abspath() + '/EPUB') quizContentPages = Path(outputDir.abspath() + '/EPUB/tools/quiz') quizImagesPages = Path(quizContentPages.abspath() + '/images') quizScriptsPages = Path(quizContentPages.abspath() + '/scripts') quizVideoPages = Path(quizContentPages.abspath() + '/video') quizCssPages = Path(quizContentPages.abspath() + '/css') quizFilesPages = Path(quizContentPages.abspath() + '/css') # contentPages = outputDir/'Content' contentPages.mkdir() quizContentPages.makedirs() quizImagesPages.mkdir() quizScriptsPages.mkdir() quizVideoPages.mkdir() quizCssPages.mkdir() quizFilesPages.mkdir() # print contentPages.abspath() # print outputDir.abspath() # Export the package content self.pages = [Epub3Cover("cover", 1, package.root)] self.generatePages(package.root, 2) uniquifyNames(self.pages) cover = None for page in self.pages: page.save(contentPages) if hasattr(page, 'cover'): cover = page.cover # Create mimetype file mimetypeFile = open(outputDir.abspath() + '/mimetype', "w") mimetypeFile.write('application/epub+zip') mimetypeFile.close() # Copy the style sheet files to the output dir # But not nav.css cssStyleFiles = [self.styleDir / '..' / 'base.css'] cssStyleFiles += [f for f in self.styleDir.files("*.css") if f.basename() != "nav.css"] imgStyleFiles = [self.styleDir / '..' / 'popup_bg.gif'] imgStyleFiles += self.styleDir.files("*.jpg") imgStyleFiles += self.styleDir.files("*.gif") imgStyleFiles += self.styleDir.files("*.png") scriptStyleFiles = self.styleDir.files("*.js") filesStyleFiles = self.styleDir.files("*.html") filesStyleFiles += self.styleDir.files("*.ttf") filesStyleFiles += self.styleDir.files("*.eot") filesStyleFiles += self.styleDir.files("*.otf") filesStyleFiles += self.styleDir.files("*.woff") # FIXME for now, only copy files referenced in Common Cartridge # this really should apply to all exports, but without a manifest # of the files needed by an included stylesheet it is too restrictive package.resourceDir.copyfiles(contentPages) self.styleDir.copylist(cssStyleFiles, quizCssPages) self.styleDir.copylist(imgStyleFiles, quizImagesPages) self.styleDir.copylist(scriptStyleFiles, quizScriptsPages) self.styleDir.copylist(filesStyleFiles, quizFilesPages) self.scriptsDir.copylist(('common.js',), quizScriptsPages) # copy players for media idevices. hasFlowplayer = False hasMagnifier = False hasXspfplayer = False hasGallery = False hasFX = False hasSH = False hasGames = False hasWikipedia = False isBreak = False hasInstructions = False hasTooltips = False for page in self.pages: if isBreak: break for idevice in page.node.idevices: if (hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery and hasFX and hasSH and hasGames and hasWikipedia): isBreak = True break if not hasFlowplayer: if 'flowPlayer.swf' in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if 'mojomagnify.js' in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if 'xspf_player.swf' in idevice.systemResources: hasXspfplayer = True if not hasGallery: hasGallery = common.ideviceHasGallery(idevice) if not hasFX: hasFX = common.ideviceHasFX(idevice) if not hasSH: hasSH = common.ideviceHasSH(idevice) if not hasGames: hasGames = common.ideviceHasGames(idevice) if not hasWikipedia: if 'WikipediaIdevice' == idevice.klass: hasWikipedia = True if not hasInstructions: if 'TrueFalseIdevice' == idevice.klass or 'MultichoiceIdevice' == idevice.klass or 'VerdaderofalsofpdIdevice' == idevice.klass or 'EleccionmultiplefpdIdevice' == idevice.klass: hasInstructions = True if not hasTooltips: hasTooltips = common.ideviceHasTooltips(idevice) if hasFlowplayer: videofile = (self.templatesDir / 'flowPlayer.swf') videofile.copyfile(contentPages / 'flowPlayer.swf') controlsfile = (self.templatesDir / 'flowplayer.controls.swf') controlsfile.copyfile(contentPages / 'flowplayer.controls.swf') if hasMagnifier: videofile = (self.templatesDir / 'mojomagnify.js') videofile.copyfile(contentPages / 'mojomagnify.js') if hasXspfplayer: videofile = (self.templatesDir / 'xspf_player.swf') videofile.copyfile(contentPages / 'xspf_player.swf') if hasGallery: exeLightbox = (self.scriptsDir / 'exe_lightbox') exeLightbox.copyfiles(contentPages) if hasFX: exeEffects = (self.scriptsDir / 'exe_effects') exeEffects.copyfiles(contentPages) if hasSH: exeSH = (self.scriptsDir / 'exe_highlighter') exeSH.copyfiles(contentPages) if hasGames: exeGames = (self.scriptsDir / 'exe_games') exeGames.copyfiles(contentPages) if hasWikipedia: wikipediaCSS = (self.cssDir / 'exe_wikipedia.css') wikipediaCSS.copyfile(contentPages / 'exe_wikipedia.css') if hasInstructions: common.copyFileIfNotInStyle('panel-amusements.png', self, contentPages) common.copyFileIfNotInStyle('stock-stop.png', self, contentPages) if hasTooltips: exe_tooltips = (self.scriptsDir / 'exe_tooltips') exe_tooltips.copyfiles(contentPages) my_style = G.application.config.styleStore.getStyle(package.style) if my_style.hasValidConfig: if my_style.get_jquery() == True: jsFile = (self.scriptsDir / 'exe_jquery.js') jsFile.copyfile(contentPages / 'exe_jquery.js') else: jsFile = (self.scriptsDir / 'exe_jquery.js') jsFile.copyfile(contentPages / 'exe_jquery.js') # if hasattr(package, 'exportSource') and package.exportSource: # (G.application.config.webDir / 'templates' / 'content.xsd').copyfile(outputDir / 'content.xsd') # (outputDir / 'content.data').write_bytes(encodeObject(package)) # (outputDir / 'contentv3.xml').write_bytes(encodeObjectToXML(package)) if package.license == "license GFDL": # include a copy of the GNU Free Documentation Licence (self.templatesDir / 'fdl.html').copyfile(contentPages / 'fdl.html') # Create the nav.xhtml file container = NavEpub3(self.pages, contentPages) container.save() # Create the publication file publication = PublicationEpub3(self.config, contentPages, package, self.pages, cover) publication.save("package.opf") # Create the container file container = ContainerEpub3(metainfPages) container.save("container.xml") # Zip it up! self.filename.safeSave(self.doZip, _(u'EXPORT FAILED!\nLast succesful export is %s.'), outputDir) # Clean up the temporary dir outputDir.rmtree()
def export(self, package): """ Export SCORM package """ # First do the export to a temporary directory outputDir = TempDirPath() # Copy the style sheet files to the output dir # But not nav.css styleFiles = [self.styleDir / '..' / 'base.css'] styleFiles += [self.styleDir / '..' / 'popup_bg.gif'] styleFiles += self.styleDir.files("*.css") if "nav.css" in styleFiles: styleFiles.remove("nav.css") styleFiles += self.styleDir.files("*.jpg") styleFiles += self.styleDir.files("*.gif") styleFiles += self.styleDir.files("*.png") styleFiles += self.styleDir.files("*.js") styleFiles += self.styleDir.files("*.html") styleFiles += self.styleDir.files("*.ttf") styleFiles += self.styleDir.files("*.eot") styleFiles += self.styleDir.files("*.otf") styleFiles += self.styleDir.files("*.woff") self.styleDir.copylist(styleFiles, outputDir) # copy the package's resource files package.resourceDir.copyfiles(outputDir) # Export the package content self.pages = [IMSPage("index", 1, package.root)] self.generatePages(package.root, 2) uniquifyNames(self.pages) for page in self.pages: page.save(outputDir) # Create the manifest file manifest = Manifest(self.config, outputDir, package, self.pages) manifest.save() # Copy the scripts - with modification by lernmodule.net self.scriptsDir.copylist( ('libot_drag.js', 'lernmodule_net.js', 'common.js'), outputDir) self.schemasDir.copylist( ('imscp_v1p1.xsd', 'imsmd_v1p2p2.xsd', 'ims_xml.xsd'), outputDir) # copy players for media idevices. hasFlowplayer = False hasMagnifier = False hasXspfplayer = False hasGallery = False isBreak = False for page in self.pages: if isBreak: break for idevice in page.node.idevices: if (hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery): isBreak = True break if not hasFlowplayer: if 'flowPlayer.swf' in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if 'magnifier.swf' in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if 'xspf_player.swf' in idevice.systemResources: hasXspfplayer = True if not hasGallery: if 'GalleryIdevice' == idevice.klass: hasGallery = True if hasFlowplayer: videofile = (self.templatesDir / 'flowPlayer.swf') videofile.copyfile(outputDir / 'flowPlayer.swf') controlsfile = (self.templatesDir / 'flowplayer.controls.swf') controlsfile.copyfile(outputDir / 'flowplayer.controls.swf') if hasMagnifier: videofile = (self.templatesDir / 'magnifier.swf') videofile.copyfile(outputDir / 'magnifier.swf') if hasXspfplayer: videofile = (self.templatesDir / 'xspf_player.swf') videofile.copyfile(outputDir / 'xspf_player.swf') if hasGallery: imageGalleryCSS = (self.cssDir / 'exe_lightbox.css') imageGalleryCSS.copyfile(outputDir / 'exe_lightbox.css') imageGalleryJS = (self.scriptsDir / 'exe_lightbox.js') imageGalleryJS.copyfile(outputDir / 'exe_lightbox.js') self.imagesDir.copylist( ('exeGallery_actions.png', 'exeGallery_loading.gif'), outputDir) if package.license == "GNU Free Documentation License": # include a copy of the GNU Free Documentation Licence (self.templatesDir / 'fdl.html').copyfile(outputDir / 'fdl.html') # Zip it up! self.filename.safeSave( self.doZip, _('EXPORT FAILED!\nLast succesful export is %s.'), outputDir) # Clean up the temporary dir outputDir.rmtree()
class Package(Persistable): """ Package represents the collection of resources the user is editing i.e. the "package". """ persistenceVersion = 7 nonpersistant = ['resourceDir', 'filename'] _name = '' _title = '' _author = '' _description = '' _backgroundImg = '' defaultLevelNames = [x_(u"Topic"), x_(u"Section"), x_(u"Unit")] def __init__(self, name): """ Initialize """ log.debug(u"init " + repr(name)) self._nextIdeviceId = 0 self._nextNodeId = 0 self._nodeIdDict = {} self._levelNames = self.defaultLevelNames[:] self.name = name self._title = u'' self._backgroundImg = u'' self.backgroundImgTile = False self.filename = u'' self.root = Node(self, None, _(u"Home")) self.currentNode = self.root self.style = u"default" self.isChanged = 0 self.idevices = [] self.dublinCore = DublinCore() self.scolinks = False self.resourceDir = TempDirPath() def set_name(self, value): self._name = toUnicode(value) def set_title(self, value): self._title = toUnicode(value) def set_author(self, value): self._author = toUnicode(value) def set_description(self, value): self._description = toUnicode(value) def get_backgroundImg(self): """Get the background image for this package""" if self._backgroundImg: return "file://" + self._backgroundImg.path else: return "" def set_backgroundImg(self, value): """Set the background image for this package""" if self._backgroundImg: self._backgroundImg.delete() if value: if value.startswith("file://"): value = value[7:] imgFile = Path(value) self._backgroundImg = Resource(self, Path(imgFile)) else: self._backgroundImg = u'' def get_level1(self): return self.levelName(0) def set_level1(self, value): if value != '': self._levelNames[0] = value else: self._levelNames[0] = self.defaultLevelNames[0] def get_level2(self): return self.levelName(1) def set_level2(self, value): if value != '': self._levelNames[1] = value else: self._levelNames[1] = self.defaultLevelNames[1] def get_level3(self): return self.levelName(2) def set_level3(self, value): if value != '': self._levelNames[2] = value else: self._levelNames[2] = self.defaultLevelNames[2] name = property(lambda self:self._name, set_name) title = property(lambda self:self._title, set_title) author = property(lambda self:self._author, set_author) description = property(lambda self:self._description, set_description) backgroundImg = property(get_backgroundImg, set_backgroundImg) level1 = property(get_level1, set_level1) level2 = property(get_level2, set_level2) level3 = property(get_level3, set_level3) def findNode(self, nodeId): """ Finds a node from its nodeId (nodeId can be a string or a list/tuple) """ log.debug(u"findNode" + repr(nodeId)) node = self._nodeIdDict.get(nodeId) if node and node.package is self: return node else: return None def levelName(self, level): """ Return the level name """ if level < len(self._levelNames): return _(self._levelNames[level]) else: return _(u"?????") def save(self, filename=None): """ Save package to disk pass an optional filename """ if filename: filename = Path(filename) name = filename.splitpath()[1] self.name = name.basename().splitext()[0] elif self.filename: filename = Path(self.filename) else: raise AssertionError(u'No name passed when saving a new package') self.filename = filename log.debug(u"Will save %s to: %s" % (self.name, filename)) self.isChanged = 0 zippedFile = zipfile.ZipFile(filename, "w", zipfile.ZIP_DEFLATED) try: for resourceFile in self.resourceDir.files(): zippedFile.write(unicode(resourceFile.normpath()), resourceFile.name.encode('utf8')) zippedFile.writestr("content.data", encodeObject(self)) finally: zippedFile.close() @staticmethod def load(filename): """ Load package from disk, returns a package """ if not zipfile.is_zipfile(filename): return None zippedFile = zipfile.ZipFile(filename, "r", zipfile.ZIP_DEFLATED) toDecode = zippedFile.read(u"content.data") try: newPackage = decodeObjectRaw(toDecode) newPackage.afterUpgradeHandlers = [] doUpgrade() except: import traceback traceback.print_exc() raise newPackage.filename = Path(filename) newPackage.resourceDir = TempDirPath() for filename in zippedFile.namelist(): if unicode(filename, 'utf8') != u"content.data": outFile = open(newPackage.resourceDir/filename, "wb") outFile.write(zippedFile.read(filename)) for handler in newPackage.afterUpgradeHandlers: handler() del newPackage.afterUpgradeHandlers return newPackage def upgradeToVersion1(self): """ Called to upgrade from 0.3 release """ self._nextNodeId = 0 self._nodeIdDict = {} draft = getattr(self, 'draft') draft._id = self._regNewNode(draft) draft._package = self setattr(self, 'editor', Node(self, None, _(u"iDevice Editor"))) idevice = GenericIdevice("", "", "", "", "") editor = getattr(self, 'editor') idevice.parentNode = editor editor.addIdevice(idevice) def superReg(node): """Registers all our nodes because in v0 they were not registered in this way""" node._id = self._regNewNode(node) node._package = self for child in node.children: superReg(child) superReg(self.root) def _regNewNode(self, node): """ Called only by nodes, stores the node in our id lookup dict returns a new unique id """ id_ = unicode(self._nextNodeId) self._nextNodeId += 1 self._nodeIdDict[id_] = node return id_ def getNewIdeviceId(self): """ Returns an iDevice Id which is unique for this package. """ id_ = unicode(self._nextIdeviceId) self._nextIdeviceId += 1 return id_ def upgradeToVersion2(self): """ Called to upgrade from 0.4 release """ getattr(self, 'draft').delete() getattr(self, 'editor').delete() delattr(self, 'draft') delattr(self, 'editor') self._nextNodeId = 0 def renumberNode(node): """ Gives the old node a number """ node._id = self._regNewNode(node) for child in node.children: renumberNode(child) renumberNode(self.root) def upgradeToVersion3(self): """ Also called to upgrade from 0.4 release """ self._nextIdeviceId = 0 def upgradeToVersion4(self): """ Puts properties in their place Also called to upgrade from 0.8 release """ self._name = toUnicode(self.__dict__['name']) self._author = toUnicode(self.__dict__['author']) self._description = toUnicode(self.__dict__['description']) def upgradeToVersion5(self): """ For version 0.11 """ self._levelNames = self.levelNames del self.levelNames def upgradeToVersion6(self): """ For version 0.14 """ self.dublinCore = DublinCore() self.title = self.root.title self.dublinCore.title = self.root.title self.dublinCore.creator = self._author self.dublinCore.description = self._description self.scolinks = False def upgradeToVersion7(self): """ For version 0.15 """ self._backgroundImg = '' self.backgroundImgTile = False
def export(self, package): """ Export SCORM package """ # First do the export to a temporary directory outputDir = TempDirPath() # copy the package's resource files package.resourceDir.copyfiles(outputDir) # copy the package's resource files, only non existant in outputDir # outputDirFiles = outputDir.files() # for rfile in package.resourceDir.files(): # if rfile not in outputDirFiles: # rfile.copy(outputDir) # copy the package's resource files, only indexed in package.resources # for md5 in package.resources.values(): # for resource in md5: # resource.path.copy(outputDir) # Export the package content self.pages = [ ScormPage("index", 1, package.root, scormType=self.scormType, metadataType=self.metadataType) ] self.generatePages(package.root, 2) uniquifyNames(self.pages) for page in self.pages: page.save(outputDir) if not self.hasForum: for idevice in page.node.idevices: if hasattr(idevice, "isForum"): if idevice.forum.lms.lms == "moodle": self.hasForum = True break # Create the manifest file manifest = Manifest(self.config, outputDir, package, self.pages, self.scormType, self.metadataType) manifest.save("imsmanifest.xml") if self.hasForum: manifest.save("discussionforum.xml") # Copy the style sheet files to the output dir # But not nav.css styleFiles = [self.styleDir/'..'/'base.css'] styleFiles += [self.styleDir/'..'/'popup_bg.gif'] styleFiles += [f for f in self.styleDir.files("*.css") if f.basename() <> "nav.css"] styleFiles += self.styleDir.files("*.jpg") styleFiles += self.styleDir.files("*.gif") styleFiles += self.styleDir.files("*.png") styleFiles += self.styleDir.files("*.js") styleFiles += self.styleDir.files("*.html") styleFiles += self.styleDir.files("*.ttf") styleFiles += self.styleDir.files("*.eot") styleFiles += self.styleDir.files("*.otf") styleFiles += self.styleDir.files("*.woff") # FIXME for now, only copy files referenced in Common Cartridge # this really should apply to all exports, but without a manifest # of the files needed by an included stylesheet it is too restrictive if self.scormType == "commoncartridge": for sf in styleFiles[:]: if sf.basename() not in manifest.dependencies: styleFiles.remove(sf) self.styleDir.copylist(styleFiles, outputDir) # Copy the scripts if self.scormType == "commoncartridge": self.scriptsDir.copylist(('libot_drag.js', 'common.js'), outputDir) if self.scormType == "scorm2004": self.scriptsDir.copylist(('AC_RunActiveContent.js', 'SCORM_API_wrapper.js', 'SCOFunctions.js', 'libot_drag.js', 'common.js'), outputDir) if self.scormType != "commoncartridge" and self.scormType != "scorm2004": self.scriptsDir.copylist(('APIWrapper.js', 'SCOFunctions.js', 'libot_drag.js', 'common.js'), outputDir) schemasDir = "" if self.scormType == "scorm1.2": schemasDir = self.schemasDir/"scorm1.2" schemasDir.copylist(('imscp_rootv1p1p2.xsd', 'imsmd_rootv1p2p1.xsd', 'adlcp_rootv1p2.xsd', 'ims_xml.xsd'), outputDir) elif self.scormType == "scorm2004": schemasDir = self.schemasDir/"scorm2004" schemasDir.copylist(('adlcp_v1p3.xsd', 'adlnav_v1p3.xsd', 'adlseq_v1p3.xsd', 'datatypes.dtd', 'imscp_v1p1.xsd', 'imsssp_v1p0.xsd', 'imsss_v1p0.xsd', 'imsss_v1p0auxresource.xsd', 'imsss_v1p0control.xsd', 'imsss_v1p0delivery.xsd', 'imsss_v1p0limit.xsd', 'imsss_v1p0objective.xsd', 'imsss_v1p0random.xsd', 'imsss_v1p0rollup.xsd', 'imsss_v1p0seqrule.xsd', 'imsss_v1p0util.xsd', 'ims_xml.xsd', 'lom.xsd', 'lomCustom.xsd', 'xml.xsd', 'XMLSchema.dtd'), outputDir) try: import shutil, errno shutil.copytree(schemasDir/"lom", outputDir/"lom") except OSError as exc: if exc.errno == errno.ENOTDIR: shutil.copy(schemasDir/"lom", outputDir/"lom") else: raise # copy players for media idevices. hasFlowplayer = False hasMagnifier = False hasXspfplayer = False hasGallery = False isBreak = False for page in self.pages: if isBreak: break for idevice in page.node.idevices: if (hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery): isBreak = True break if not hasFlowplayer: if 'flowPlayer.swf' in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if 'magnifier.swf' in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if 'xspf_player.swf' in idevice.systemResources: hasXspfplayer = True if not hasGallery: if 'GalleryIdevice' == idevice.klass: hasGallery = True if hasFlowplayer: videofile = (self.templatesDir/'flowPlayer.swf') videofile.copyfile(outputDir/'flowPlayer.swf') controlsfile = (self.templatesDir/'flowplayer.controls.swf') controlsfile.copyfile(outputDir/'flowplayer.controls.swf') if hasMagnifier: videofile = (self.templatesDir/'magnifier.swf') videofile.copyfile(outputDir/'magnifier.swf') if hasXspfplayer: videofile = (self.templatesDir/'xspf_player.swf') videofile.copyfile(outputDir/'xspf_player.swf') if hasGallery: imageGalleryCSS = (self.cssDir/'exe_lightbox.css') imageGalleryCSS.copyfile(outputDir/'exe_lightbox.css') imageGalleryJS = (self.scriptsDir/'exe_lightbox.js') imageGalleryJS.copyfile(outputDir/'exe_lightbox.js') self.imagesDir.copylist(('exeGallery_actions.png', 'exeGallery_loading.gif', 'stock-insert-image.png'), outputDir) if self.scormType == "scorm1.2" or self.scormType == "scorm2004": if package.license == "GNU Free Documentation License": # include a copy of the GNU Free Documentation Licence (self.templatesDir/'fdl.html').copyfile(outputDir/'fdl.html') if hasattr(package, 'scowsinglepage') and package.scowsinglepage: page = SinglePage("singlepage_index", 1, package.root) page.save(outputDir/"singlepage_index.html") if hasattr(package, 'scowwebsite') and package.scowwebsite: website = WebsiteExport(self.config, self.styleDir, outputDir, "website_") website.export(package) (self.styleDir/'nav.css').copyfile(outputDir/'nav.css') if hasattr(package, 'scowsource') and package.scowsource: (G.application.config.webDir/'templates'/'content.xsd').copyfile(outputDir/'content.xsd') (outputDir/'content.data').write_bytes(encodeObject(package)) (outputDir/'contentv2.xml').write_bytes(encodeObjectToXML(package)) # Zip it up! self.filename.safeSave(self.doZip, _('EXPORT FAILED!\nLast succesful export is %s.'), outputDir) # Clean up the temporary dir outputDir.rmtree()
def export(self, package): """ Export epub 3 package """ # First do the export to a temporary directory outputDir = TempDirPath() """ fileDir = outputDir/"META-INF" fileDir.mkdir() fileDir = outputDir/"Content" fileDir.mkdir() """ metainfPages = Path(outputDir.abspath() + "/META-INF") # metainfPages = outputDir/'META-INF' metainfPages.mkdir() contentPages = Path(outputDir.abspath() + "/EPUB") # contentPages = outputDir/'Content' contentPages.mkdir() # print contentPages.abspath() # print outputDir.abspath() # Export the package content self.pages = [Epub3Cover("cover", 1, package.root)] self.generatePages(package.root, 2) uniquifyNames(self.pages) cover = None for page in self.pages: page.save(contentPages) if hasattr(page, "cover"): cover = page.cover # Create mimetype file mimetypeFile = open(outputDir.abspath() + "/mimetype", "w") mimetypeFile.write("application/epub+zip") mimetypeFile.close() # Copy the style sheet files to the output dir # But not nav.css styleFiles = [self.styleDir / ".." / "popup_bg.gif"] styleFiles += [f for f in self.styleDir.files("*.css") if f.basename() != "nav.css"] styleFiles += self.styleDir.files("*.jpg") styleFiles += self.styleDir.files("*.gif") styleFiles += self.styleDir.files("*.png") styleFiles += self.styleDir.files("*.js") styleFiles += self.styleDir.files("*.html") styleFiles += self.styleDir.files("*.ttf") styleFiles += self.styleDir.files("*.eot") styleFiles += self.styleDir.files("*.otf") styleFiles += self.styleDir.files("*.woff") # FIXME for now, only copy files referenced in Common Cartridge # this really should apply to all exports, but without a manifest # of the files needed by an included stylesheet it is too restrictive package.resourceDir.copyfiles(contentPages) self.styleDir.copylist(styleFiles, contentPages) listCSSFiles = getFilesCSSToMinify("epub3", self.styleDir) exportMinFileCSS(listCSSFiles, outputDir) listFiles = [] listOutFiles = [] listFiles += [self.scriptsDir / "common.js"] listOutFiles += [outputDir / "common.js"] # copy players for media idevices. hasFlowplayer = False hasMagnifier = False hasXspfplayer = False hasGallery = False hasFX = False hasSH = False hasGames = False hasWikipedia = False isBreak = False hasInstructions = False hasTooltips = False for page in self.pages: if isBreak: break for idevice in page.node.idevices: if ( hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery and hasFX and hasSH and hasGames and hasWikipedia ): isBreak = True break if not hasFlowplayer: if "flowPlayer.swf" in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if "mojomagnify.js" in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if "xspf_player.swf" in idevice.systemResources: hasXspfplayer = True if not hasGallery: hasGallery = common.ideviceHasGallery(idevice) if not hasFX: hasFX = common.ideviceHasFX(idevice) if not hasSH: hasSH = common.ideviceHasSH(idevice) if not hasGames: hasGames = common.ideviceHasGames(idevice) if not hasWikipedia: if "WikipediaIdevice" == idevice.klass: hasWikipedia = True if not hasInstructions: if ( "TrueFalseIdevice" == idevice.klass or "MultichoiceIdevice" == idevice.klass or "VerdaderofalsofpdIdevice" == idevice.klass or "EleccionmultiplefpdIdevice" == idevice.klass ): hasInstructions = True if not hasTooltips: hasTooltips = common.ideviceHasTooltips(idevice) if hasFlowplayer: videofile = self.templatesDir / "flowPlayer.swf" videofile.copyfile(contentPages / "flowPlayer.swf") controlsfile = self.templatesDir / "flowplayer.controls.swf" controlsfile.copyfile(contentPages / "flowplayer.controls.swf") if hasMagnifier: videofile = self.templatesDir / "mojomagnify.js" videofile.copyfile(contentPages / "mojomagnify.js") if hasXspfplayer: videofile = self.templatesDir / "xspf_player.swf" videofile.copyfile(contentPages / "xspf_player.swf") if hasGallery: exeLightbox = self.scriptsDir / "exe_lightbox" exeLightbox.copyfiles(contentPages) if hasFX: exeEffects = self.scriptsDir / "exe_effects" exeEffects.copyfiles(contentPages) if hasSH: exeSH = self.scriptsDir / "exe_highlighter" exeSH.copyfiles(contentPages) if hasGames: exeGames = self.scriptsDir / "exe_games" exeGames.copyfiles(contentPages) if hasWikipedia: wikipediaCSS = self.cssDir / "exe_wikipedia.css" wikipediaCSS.copyfile(contentPages / "exe_wikipedia.css") if hasInstructions: common.copyFileIfNotInStyle("panel-amusements.png", self, contentPages) common.copyFileIfNotInStyle("stock-stop.png", self, contentPages) if hasTooltips: exe_tooltips = self.scriptsDir / "exe_tooltips" exe_tooltips.copyfiles(contentPages) my_style = G.application.config.styleStore.getStyle(package.style) if my_style.hasValidConfig: if my_style.get_jquery() == True: jsFile = self.scriptsDir / "exe_jquery.js" jsFile.copyfile(contentPages / "exe_jquery.js") else: jsFile = self.scriptsDir / "exe_jquery.js" jsFile.copyfile(contentPages / "exe_jquery.js") listFiles = getFilesJSToMinify("epub3", self.scriptsDir) exportMinFileJS(listFiles, outputDir) # if hasattr(package, 'exportSource') and package.exportSource: # (G.application.config.webDir / 'templates' / 'content.xsd').copyfile(outputDir / 'content.xsd') # (outputDir / 'content.data').write_bytes(encodeObject(package)) # (outputDir / 'contentv3.xml').write_bytes(encodeObjectToXML(package)) if package.license == "license GFDL": # include a copy of the GNU Free Documentation Licence (self.templatesDir / "fdl.html").copyfile(contentPages / "fdl.html") # Create the nav.xhtml file container = NavEpub3(self.pages, contentPages) container.save() # Create the publication file publication = PublicationEpub3(self.config, contentPages, package, self.pages, cover) publication.save("package.opf") # Create the container file container = ContainerEpub3(metainfPages) container.save("container.xml") # Zip it up! self.filename.safeSave(self.doZip, _(u"EXPORT FAILED!\nLast succesful export is %s."), outputDir) # Clean up the temporary dir outputDir.rmtree()
class Package(Persistable): """ Package represents the collection of resources the user is editing i.e. the "package". """ persistenceVersion = 9 nonpersistant = ['resourceDir', 'filename'] # Name is used in filenames and urls (saving and navigating) _name = '' tempFile = False # This is set when the package is saved as a temp copy file # Title is rendered in exports _title = '' _author = '' _description = '' _backgroundImg = '' # This is like a constant defaultLevelNames = [x_(u"Topic"), x_(u"Section"), x_(u"Unit")] def __init__(self, name): """ Initialize """ log.debug(u"init " + repr(name)) self._nextIdeviceId = 0 self._nextNodeId = 0 # For looking up nodes by ids self._nodeIdDict = {} self._levelNames = self.defaultLevelNames[:] self.name = name self._title = u'' self._backgroundImg = u'' self.backgroundImgTile = False # Empty if never saved/loaded self.filename = u'' self.root = Node(self, None, _(u"Home")) self.currentNode = self.root self.style = u"default" self.isChanged = False self.idevices = [] self.dublinCore = DublinCore() self.scolinks = False self.license = "None" self.footer = "" # Temporary directory to hold resources in self.resourceDir = TempDirPath() self.resources = {} # Checksum-[_Resource(),..] # Property Handlers def set_name(self, value): self._name = toUnicode(value) def set_title(self, value): self._title = toUnicode(value) def set_author(self, value): self._author = toUnicode(value) def set_description(self, value): self._description = toUnicode(value) def get_backgroundImg(self): """Get the background image for this package""" if self._backgroundImg: return "file://" + self._backgroundImg.path else: return "" def set_backgroundImg(self, value): """Set the background image for this package""" if self._backgroundImg: self._backgroundImg.delete() if value: if value.startswith("file://"): value = value[7:] imgFile = Path(value) self._backgroundImg = Resource(self, Path(imgFile)) else: self._backgroundImg = u'' def get_level1(self): return self.levelName(0) def set_level1(self, value): if value != '': self._levelNames[0] = value else: self._levelNames[0] = self.defaultLevelNames[0] def get_level2(self): return self.levelName(1) def set_level2(self, value): if value != '': self._levelNames[1] = value else: self._levelNames[1] = self.defaultLevelNames[1] def get_level3(self): return self.levelName(2) def set_level3(self, value): if value != '': self._levelNames[2] = value else: self._levelNames[2] = self.defaultLevelNames[2] # Properties name = property(lambda self:self._name, set_name) title = property(lambda self:self._title, set_title) author = property(lambda self:self._author, set_author) description = property(lambda self:self._description, set_description) backgroundImg = property(get_backgroundImg, set_backgroundImg) level1 = property(get_level1, set_level1) level2 = property(get_level2, set_level2) level3 = property(get_level3, set_level3) def findNode(self, nodeId): """ Finds a node from its nodeId (nodeId can be a string or a list/tuple) """ log.debug(u"findNode" + repr(nodeId)) node = self._nodeIdDict.get(nodeId) if node and node.package is self: return node else: return None def levelName(self, level): """ Return the level name """ if level < len(self._levelNames): return _(self._levelNames[level]) else: return _(u"?????") def save(self, filename=None, tempFile=False): """ Save package to disk pass an optional filename """ self.tempFile = tempFile # Get the filename if filename: filename = Path(filename) # If we are being given a new filename... # Change our name to match our new filename name = filename.splitpath()[1] if not tempFile: self.name = name.basename().splitext()[0] elif self.filename: # Otherwise use our last saved/loaded from filename filename = Path(self.filename) else: # If we don't have a last saved/loaded from filename, # raise an exception because, we need to have a new # file passed when a brand new package is saved raise AssertionError(u'No name passed when saving a new package') # Store our new filename for next file|save, and save the package log.debug(u"Will save %s to: %s" % (self.name, filename)) if tempFile: self.nonpersistant.remove('filename') oldFilename, self.filename = self.filename, unicode(self.filename) try: filename.safeSave(self.doSave, _('SAVE FAILED!\nLast succesful save is %s.')) finally: self.nonpersistant.append('filename') self.filename = oldFilename else: # Update our new filename for future saves self.filename = filename filename.safeSave(self.doSave, _('SAVE FAILED!\nLast succesful save is %s.')) self.isChanged = False self.updateRecentDocuments(filename) def updateRecentDocuments(self, filename): """ Updates the list of recent documents """ # Don't update the list for the generic.data "package" genericData = G.application.config.configDir/'idevices'/'generic.data' if genericData.isfile() or genericData.islink(): if Path(filename).samefile(genericData): return # Save in recentDocuments list recentProjects = G.application.config.recentProjects if filename in recentProjects: # If we're already number one, carry on if recentProjects[0] == filename: return recentProjects.remove(filename) recentProjects.insert(0, filename) del recentProjects[5:] # Delete any older names from the list G.application.config.configParser.write() # Save the settings def doSave(self, fileObj): """ Actually performs the save to 'fileObj'. """ zippedFile = zipfile.ZipFile(fileObj, "w", zipfile.ZIP_DEFLATED) try: for resourceFile in self.resourceDir.files(): zippedFile.write(unicode(resourceFile.normpath()), resourceFile.name.encode('utf8'), zipfile.ZIP_DEFLATED) zinfo = zipfile.ZipInfo(filename='content.data', date_time=time.localtime()[0:6]) zinfo.external_attr = 0100644<<16L zippedFile.writestr(zinfo, encodeObject(self)) finally: zippedFile.close() def extractNode(self): """ Clones and extracts the currently selected node into a new package. """ newPackage = Package('NoName') # Name will be set once it is saved.. newPackage.title = self.currentNode.title newPackage.style = self.style newPackage.author = self.author newPackage._nextNodeId = self._nextNodeId # Copy the nodes from the original package # and merge into the root of the new package self.currentNode.copyToPackage(newPackage) return newPackage @staticmethod def load(filename, newLoad=True, destinationPackage=None): """ Load package from disk, returns a package. """ if not zipfile.is_zipfile(filename): return None zippedFile = zipfile.ZipFile(filename, "r") try: # Get the jellied package data toDecode = zippedFile.read(u"content.data") except KeyError: log.info("no content.data, trying Common Cartridge/Content Package") newPackage = loadCC(zippedFile, filename) newPackage.tempFile = False newPackage.isChanged = False newPackage.filename = Path(filename) return newPackage # Need to add a TempDirPath because it is a nonpersistant member resourceDir = TempDirPath() # Extract resource files from package to temporary directory for fn in zippedFile.namelist(): if unicode(fn, 'utf8') != u"content.data": outFile = open(resourceDir/fn, "wb") outFile.write(zippedFile.read(fn)) outFile.flush() outFile.close() try: newPackage = decodeObjectRaw(toDecode) G.application.afterUpgradeHandlers = [] newPackage.resourceDir = resourceDir G.application.afterUpgradeZombies2Delete = [] if newLoad: # provide newPackage to doUpgrade's versionUpgrade() to # correct old corrupt extracted packages by setting the # any corrupt package references to the new package: log.debug("load() about to doUpgrade newPackage \"" + newPackage._name + "\" " + repr(newPackage) ) if hasattr(newPackage, 'resourceDir'): log.debug("newPackage resourceDir = " + newPackage.resourceDir) else: # even though it was just set above? should not get here: log.error("newPackage resourceDir has NO resourceDir!") doUpgrade(newPackage) # after doUpgrade, compare the largest found field ID: if G.application.maxFieldId >= Field.nextId: Field.nextId = G.application.maxFieldId + 1 else: # and when merging, automatically set package references to # the destinationPackage, into which this is being merged: log.debug("load() about to merge doUpgrade newPackage \"" + newPackage._name + "\" " + repr(newPackage) + " INTO destinationPackage \"" + destinationPackage._name + "\" " + repr(destinationPackage)) log.debug("using their resourceDirs:") if hasattr(newPackage, 'resourceDir'): log.debug(" newPackage resourceDir = " + newPackage.resourceDir) else: log.error("newPackage has NO resourceDir!") if hasattr(destinationPackage, 'resourceDir'): log.debug(" destinationPackage resourceDir = " + destinationPackage.resourceDir) else: log.error("destinationPackage has NO resourceDir!") doUpgrade(destinationPackage, isMerge=True, preMergePackage=newPackage) # after doUpgrade, compare the largest found field ID: if G.application.maxFieldId >= Field.nextId: Field.nextId = G.application.maxFieldId + 1 except: import traceback traceback.print_exc() raise if newPackage.tempFile: # newPackage.filename was stored as it's original filename newPackage.tempFile = False else: # newPackage.filename is the name that the package was last loaded from # or saved to newPackage.filename = Path(filename) # Let idevices and nodes handle any resource upgrading they may need to # Note: Package afterUpgradeHandlers *must* be done after Resources' # and the package should be updated before everything else, # so, prioritize with a 3-pass, 3-level calling setup # in order of: 1) resources, 2) package, 3) anything other objects for handler_priority in range(3): for handler in G.application.afterUpgradeHandlers: if handler_priority == 0 and \ repr(handler.im_class)=="<class 'exe.engine.resource.Resource'>": # level-0 handlers: Resource handler() elif handler_priority == 1 and \ repr(handler.im_class)=="<class 'exe.engine.package.Package'>": # level-1 handlers: Package (requires resources first) if handler.im_self == newPackage: handler() else: log.warn("Extra package object found, " \ + "ignoring its afterUpgradeHandler: " \ + repr(handler)) elif handler_priority == 2 and \ repr(handler.im_class)!="<class 'exe.engine.resource.Resource'>" \ and \ repr(handler.im_class)!="<class 'exe.engine.package.Package'>": # level-2 handlers: all others handler() G.application.afterUpgradeHandlers = [] num_zombies = len(G.application.afterUpgradeZombies2Delete) for i in range(num_zombies-1, -1, -1): zombie = G.application.afterUpgradeZombies2Delete[i] # now, the zombie list can contain nodes OR resources to delete. # if zombie is a node, then also pass in a pruning parameter.. zombie_is_node = False if isinstance(zombie, Node): zombie_is_node = True if zombie_is_node: zombie.delete(pruningZombies=True) else: zombie.delete() del zombie G.application.afterUpgradeZombies2Delete = [] newPackage.updateRecentDocuments(newPackage.filename) newPackage.isChanged = False return newPackage def cleanUpResources(self): """ Removes duplicate resource files """ # Delete unused resources. # Only really needed for upgrading to version 0.20, # but upgrading of resources and package happens in no particular order # and must be done after all resources have been upgraded # some earlier .elp files appear to have been corrupted with # two packages loaded, *possibly* from some strange extract/merge # functionality in earlier eXe versions? # Regardless, only the real package will have a resourceDir, # and the other will fail. # For now, then, put in this quick and easy safety check: if not hasattr(self,'resourceDir'): log.warn("cleanUpResources called on a redundant package") return existingFiles = set([fn.basename() for fn in self.resourceDir.files()]) usedFiles = set([reses[0].storageName for reses in self.resources.values()]) for fn in existingFiles - usedFiles: (self.resourceDir/fn).remove() def findResourceByName(self, queryName): """ Support for merging, and anywhere else that unique names might be checked before actually comparing against the files (as will be done by the resource class itself in its _addOurselvesToPackage() ) """ foundResource = None queryResources = self.resources for this_checksum in queryResources: for this_resource in queryResources[this_checksum]: if queryName == this_resource.storageName: foundResource = this_resource return foundResource return foundResource def upgradeToVersion1(self): """ Called to upgrade from 0.3 release """ self._nextNodeId = 0 self._nodeIdDict = {} # Also upgrade all the nodes. # This needs to be done here so that draft gets id 0 # If it's done in the nodes, the ids are assigned in reverse order draft = getattr(self, 'draft') draft._id = self._regNewNode(draft) draft._package = self setattr(self, 'editor', Node(self, None, _(u"iDevice Editor"))) # Add a default idevice to the editor idevice = GenericIdevice("", "", "", "", "") editor = getattr(self, 'editor') idevice.parentNode = editor editor.addIdevice(idevice) def superReg(node): """Registers all our nodes because in v0 they were not registered in this way""" node._id = self._regNewNode(node) node._package = self for child in node.children: superReg(child) superReg(self.root) def _regNewNode(self, node): """ Called only by nodes, stores the node in our id lookup dict returns a new unique id """ id_ = unicode(self._nextNodeId) self._nextNodeId += 1 self._nodeIdDict[id_] = node return id_ def getNewIdeviceId(self): """ Returns an iDevice Id which is unique for this package. """ id_ = unicode(self._nextIdeviceId) self._nextIdeviceId += 1 return id_ def upgradeToVersion2(self): """ Called to upgrade from 0.4 release """ getattr(self, 'draft').delete() getattr(self, 'editor').delete() delattr(self, 'draft') delattr(self, 'editor') # Need to renumber nodes because idevice node and draft nodes are gone self._nextNodeId = 0 def renumberNode(node): """ Gives the old node a number """ node._id = self._regNewNode(node) for child in node.children: renumberNode(child) renumberNode(self.root) def upgradeToVersion3(self): """ Also called to upgrade from 0.4 release """ self._nextIdeviceId = 0 def upgradeToVersion4(self): """ Puts properties in their place Also called to upgrade from 0.8 release """ self._name = toUnicode(self.__dict__['name']) self._author = toUnicode(self.__dict__['author']) self._description = toUnicode(self.__dict__['description']) def upgradeToVersion5(self): """ For version 0.11 """ self._levelNames = self.levelNames del self.levelNames def upgradeToVersion6(self): """ For version 0.14 """ self.dublinCore = DublinCore() # Copy some of the package properties to dublin core self.title = self.root.title self.dublinCore.title = self.root.title self.dublinCore.creator = self._author self.dublinCore.description = self._description self.scolinks = False def upgradeToVersion7(self): """ For version 0.15 """ self._backgroundImg = '' self.backgroundImgTile = False def upgradeToVersion8(self): """ For version 0.20, alpha, for nightlies r2469 """ self.license = 'None' self.footer = "" self.idevices = [] def upgradeToVersion9(self): """ For version >= 0.20.4 """ if not hasattr(self, 'resources'): # The hasattr is needed, because sometimes, Resource instances are upgraded # first and they also set this attribute on the package self.resources = {} G.application.afterUpgradeHandlers.append(self.cleanUpResources)
def testExport(self): # Delete the output dir outdir = TempDirPath() G.application = Application() G.application.loadConfiguration() G.application.preLaunch() # Load a package package = Package.load('testing/testPackage2.elp') # Do the export style_dir = G.application.config.stylesDir / package.style exporter = WebsiteExport(G.application.config, style_dir, outdir) exporter.export(package) # Check that it all exists now assert outdir.isdir() assert (outdir / 'index.html').isfile() # Check that the style sheets have been copied for filename in style_dir.files(): #Skip the styles config.xml - that should not be included if filename.basename() == "config.xml": continue assert ((outdir / filename.basename()).exists(), 'Style file "%s" not copied' % (outdir / filename.basename())) #check the modification time is correct f_dst = Path(outdir/filename.basename()) f_src = Path(filename) self.assertTrue( TestUtils.mod_time_diff(f_dst, f_src) < 0.1, "Modification time in style dir preserved") for res_file in package.resourceDir.files(): dst_file = Path(outdir/ res_file.basename()) self.assertTrue(dst_file.isfile()) self.assertTrue( TestUtils.mod_time_diff(res_file, dst_file) < 0.1, "Resource file %s has same mod time as origin" \ % res_file.basename()) #test that everything that was copied hahs the right mod time copy_list = package.make_system_copy_list(style_dir, G.application.config.webDir/"scripts" , G.application.config.webDir/"templates", G.application.config.webDir/"images", G.application.config.webDir/"css", outdir) TestUtils.check_copy_list_mod_time(copy_list, self) # Check that each node in the package has had a page made pagenodes = Set([p.node for p in exporter.pages]) othernodes = Set(self._getNodes([], package.root)) assert pagenodes == othernodes for page in exporter.pages: self._testPage(page, outdir)
def export(self, package): """ Export SCORM package """ # First do the export to a temporary directory outputDir = TempDirPath() self.metadataType = package.exportMetadataType # Copy the style files to the output dir # But not nav.css styleFiles = [self.styleDir/'..'/'popup_bg.gif'] styleFiles += self.styleDir.files("*.*") if "nav.css" in styleFiles: styleFiles.remove("nav.css") self.styleDir.copylist(styleFiles, outputDir) # copy the package's resource files for resourceFile in package.resourceDir.walkfiles(): file = package.resourceDir.relpathto(resourceFile) if ("/" in file): Dir = Path(outputDir/file[:file.rindex("/")]) if not Dir.exists(): Dir.makedirs() resourceFile.copy(outputDir/Dir) else: resourceFile.copy(outputDir) listCSSFiles=getFilesCSSToMinify('ims', self.styleDir) exportMinFileCSS(listCSSFiles, outputDir) # Export the package content self.pages = [ IMSPage("index", 1, package.root, metadataType=self.metadataType) ] self.generatePages(package.root, 2) uniquifyNames(self.pages) for page in self.pages: page.save(outputDir, self.pages) # Create the manifest file manifest = Manifest(self.config, outputDir, package, self.pages, self.metadataType) manifest.save("imsmanifest.xml") # Create lang file langGameFile = open(outputDir + '/common_i18n.js', "w") langGameFile.write(common.getJavaScriptStrings(False)) langGameFile.close() # jQuery my_style = G.application.config.styleStore.getStyle(page.node.package.style) if my_style.hasValidConfig: if my_style.get_jquery() == True: jsFile = (self.scriptsDir/'exe_jquery.js') jsFile.copyfile(outputDir/'exe_jquery.js') else: jsFile = (self.scriptsDir/'exe_jquery.js') jsFile.copyfile(outputDir/'exe_jquery.js') dT = common.getExportDocType() if dT == "HTML5": jsFile = (self.scriptsDir/'exe_html5.js') jsFile.copyfile(outputDir/'exe_html5.js') listFiles=getFilesJSToMinify('ims', self.scriptsDir) exportMinFileJS(listFiles, outputDir) self.schemasDir.copylist(('imscp_v1p1.xsd', 'imsmd_v1p2p2.xsd', 'lom.xsd', 'lomCustom.xsd', 'ims_xml.xsd'), outputDir) # copy players for media idevices. hasFlowplayer = False hasMagnifier = False hasXspfplayer = False hasGallery = False hasFX = False hasSH = False hasGames = False hasElpLink = False hasWikipedia = False isBreak = False hasInstructions = False hasMediaelement = False hasTooltips = False hasABCMusic = False listIdevicesFiles = [] for page in self.pages: if isBreak: break for idevice in page.node.idevices: if (hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery and hasFX and hasSH and hasGames and hasElpLink and hasWikipedia and hasInstructions and hasMediaelement and hasTooltips and hasABCMusic): isBreak = True break if not hasFlowplayer: if 'flowPlayer.swf' in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if 'mojomagnify.js' in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if 'xspf_player.swf' in idevice.systemResources: hasXspfplayer = True if not hasGallery: hasGallery = common.ideviceHasGallery(idevice) if not hasFX: hasFX = common.ideviceHasFX(idevice) if not hasSH: hasSH = common.ideviceHasSH(idevice) if not hasGames: hasGames = common.ideviceHasGames(idevice) if not hasElpLink: hasElpLink = common.ideviceHasElpLink(idevice,package) if not hasWikipedia: if 'WikipediaIdevice' == idevice.klass: hasWikipedia = True if not hasInstructions: if 'TrueFalseIdevice' == idevice.klass or 'MultichoiceIdevice' == idevice.klass or 'VerdaderofalsofpdIdevice' == idevice.klass or 'EleccionmultiplefpdIdevice' == idevice.klass: hasInstructions = True if not hasMediaelement: hasMediaelement = common.ideviceHasMediaelement(idevice) if not hasTooltips: hasTooltips = common.ideviceHasTooltips(idevice) if not hasABCMusic: hasABCMusic = common.ideviceHasABCMusic(idevice) if hasattr(idevice, "_iDeviceDir"): listIdevicesFiles.append((Path(idevice._iDeviceDir)/'export')) common.exportJavaScriptIdevicesFiles(page.node.idevices, outputDir); if hasFlowplayer: videofile = (self.templatesDir/'flowPlayer.swf') videofile.copyfile(outputDir/'flowPlayer.swf') controlsfile = (self.templatesDir/'flowplayer.controls.swf') controlsfile.copyfile(outputDir/'flowplayer.controls.swf') if hasMagnifier: videofile = (self.templatesDir/'mojomagnify.js') videofile.copyfile(outputDir/'mojomagnify.js') if hasXspfplayer: videofile = (self.templatesDir/'xspf_player.swf') videofile.copyfile(outputDir/'xspf_player.swf') if hasGallery: exeLightbox = (self.scriptsDir/'exe_lightbox') exeLightbox.copyfiles(outputDir) if hasFX: exeEffects = (self.scriptsDir/'exe_effects') exeEffects.copyfiles(outputDir) if hasSH: exeSH = (self.scriptsDir/'exe_highlighter') exeSH.copyfiles(outputDir) if hasGames: exeGames = (self.scriptsDir/'exe_games') exeGames.copyfiles(outputDir) # Add game js string to common_i18n langGameFile = open(outputDir + '/common_i18n.js', "a") langGameFile.write(common.getGamesJavaScriptStrings(False)) langGameFile.close() if hasElpLink or package.get_exportElp(): # Export the elp file currentPackagePath = Path(package.filename) currentPackagePath.copyfile(outputDir/package.name+'.elp') if hasWikipedia: wikipediaCSS = (self.cssDir/'exe_wikipedia.css') wikipediaCSS.copyfile(outputDir/'exe_wikipedia.css') if hasInstructions: common.copyFileIfNotInStyle('panel-amusements.png', self, outputDir) common.copyFileIfNotInStyle('stock-stop.png', self, outputDir) if hasMediaelement: mediaelement = (self.scriptsDir/'mediaelement') mediaelement.copyfiles(outputDir) if dT != "HTML5": jsFile = (self.scriptsDir/'exe_html5.js') jsFile.copyfile(outputDir/'exe_html5.js') if hasTooltips: exe_tooltips = (self.scriptsDir/'exe_tooltips') exe_tooltips.copyfiles(outputDir) if hasABCMusic: pluginScripts = (self.scriptsDir/'tinymce_4/js/tinymce/plugins/abcmusic/export') pluginScripts.copyfiles(outputDir) if hasattr(package, 'exportSource') and package.exportSource: (G.application.config.webDir/'templates'/'content.xsd').copyfile(outputDir/'content.xsd') (outputDir/'content.data').write_bytes(encodeObject(package)) (outputDir/'contentv3.xml').write_bytes(encodeObjectToXML(package)) if package.license == "license GFDL": # include a copy of the GNU Free Documentation Licence (self.templatesDir/'fdl.html').copyfile(outputDir/'fdl.html') # Zip it up! self.filename.safeSave(self.doZip, _('EXPORT FAILED!\nLast succesful export is %s.'), outputDir) # Clean up the temporary dir outputDir.rmtree()
def export(self, package): """ Export epub 3 package """ # First do the export to a temporary directory outputDir = TempDirPath() ''' fileDir = outputDir/"META-INF" fileDir.mkdir() fileDir = outputDir/"Content" fileDir.mkdir() ''' metainfPages = Path(outputDir.abspath() + '/META-INF') # metainfPages = outputDir/'META-INF' metainfPages.mkdir() contentPages = Path(outputDir.abspath() + '/EPUB') # contentPages = outputDir/'Content' contentPages.mkdir() # print contentPages.abspath() # print outputDir.abspath() # Export the package content self.pages = [Epub3Cover("cover", 1, package.root)] self.generatePages(package.root, 2) uniquifyNames(self.pages) cover = None for page in self.pages: page.save(contentPages, self.pages) if hasattr(page, 'cover'): cover = page.cover # Create mimetype file mimetypeFile = open(outputDir.abspath() + '/mimetype', "w") mimetypeFile.write('application/epub+zip') mimetypeFile.close() # Create common_i18n file langFile = open(contentPages + '/common_i18n.js', "w") langFile.write(common.getJavaScriptStrings(False)) langFile.close() # Copy the style files to the output dir # But not nav.css styleFiles = [self.styleDir / '..' / 'popup_bg.gif'] styleFiles += [ f for f in self.styleDir.files("*.*") if f.basename() not in ['nav.css'] ] # FIXME for now, only copy files referenced in Common Cartridge # this really should apply to all exports, but without a manifest # of the files needed by an included stylesheet it is too restrictive # Add fallback document for possible image links if Path(self.styleDir / 'fallback.xhtml').exists(): styleFiles += [self.styleDir / 'fallback.xhtml'] else: styleFiles += [self.styleDir / '..' / 'fallback.xhtml'] # copy the package's resource files for resourceFile in package.resourceDir.walkfiles(): fn = package.resourceDir.relpathto(resourceFile) if ("/" in fn): Dir = Path(contentPages / fn[:fn.rindex("/")]) if not Dir.exists(): Dir.makedirs() resourceFile.copy(contentPages / Dir) else: resourceFile.copy(contentPages) self.styleDir.copylist(styleFiles, contentPages) # copy players for media idevices. hasFlowplayer = False hasMagnifier = False hasXspfplayer = False hasGallery = False hasFX = False hasSH = False hasGames = False hasWikipedia = False isBreak = False hasInstructions = False hasTooltips = False hasABCMusic = False for page in self.pages: if isBreak: break for idevice in page.node.idevices: if (hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery and hasFX and hasSH and hasGames and hasWikipedia and hasInstructions and hasTooltips and hasABCMusic): isBreak = True break if not hasFlowplayer: if 'flowPlayer.swf' in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if 'mojomagnify.js' in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if 'xspf_player.swf' in idevice.systemResources: hasXspfplayer = True if not hasGallery: hasGallery = common.ideviceHasGallery(idevice) if not hasFX: hasFX = common.ideviceHasFX(idevice) if not hasSH: hasSH = common.ideviceHasSH(idevice) if not hasGames: hasGames = common.ideviceHasGames(idevice) if not hasWikipedia: if 'WikipediaIdevice' == idevice.klass: hasWikipedia = True if not hasInstructions: if 'TrueFalseIdevice' == idevice.klass or 'MultichoiceIdevice' == idevice.klass or 'VerdaderofalsofpdIdevice' == idevice.klass or 'EleccionmultiplefpdIdevice' == idevice.klass: hasInstructions = True if not hasTooltips: hasTooltips = common.ideviceHasTooltips(idevice) if not hasABCMusic: hasABCMusic = common.ideviceHasABCMusic(idevice) common.exportJavaScriptIdevicesFiles(page.node.idevices, contentPages) if hasFlowplayer: videofile = (self.templatesDir / 'flowPlayer.swf') videofile.copyfile(contentPages / 'flowPlayer.swf') controlsfile = (self.templatesDir / 'flowplayer.controls.swf') controlsfile.copyfile(contentPages / 'flowplayer.controls.swf') if hasMagnifier: videofile = (self.templatesDir / 'mojomagnify.js') videofile.copyfile(contentPages / 'mojomagnify.js') if hasXspfplayer: videofile = (self.templatesDir / 'xspf_player.swf') videofile.copyfile(contentPages / 'xspf_player.swf') if hasGallery: exeLightbox = (self.scriptsDir / 'exe_lightbox') exeLightbox.copyfiles(contentPages) if hasFX: exeEffects = (self.scriptsDir / 'exe_effects') exeEffects.copyfiles(contentPages) if hasSH: exeSH = (self.scriptsDir / 'exe_highlighter') exeSH.copyfiles(contentPages) if hasGames: exeGames = (self.scriptsDir / 'exe_games') exeGames.copyfiles(contentPages) # Add game js string to common_i18n langGameFile = open(contentPages + '/common_i18n.js', "a") langGameFile.write(common.getGamesJavaScriptStrings(False)) langGameFile.close() if hasWikipedia: wikipediaCSS = (self.cssDir / 'exe_wikipedia.css') wikipediaCSS.copyfile(contentPages / 'exe_wikipedia.css') if hasInstructions: common.copyFileIfNotInStyle('panel-amusements.png', self, contentPages) common.copyFileIfNotInStyle('stock-stop.png', self, contentPages) if hasTooltips: exe_tooltips = (self.scriptsDir / 'exe_tooltips') exe_tooltips.copyfiles(contentPages) if hasABCMusic: pluginScripts = (self.scriptsDir / 'tinymce_4/js/tinymce/plugins/abcmusic/export') pluginScripts.copyfiles(contentPages) my_style = G.application.config.styleStore.getStyle(package.style) if my_style.hasValidConfig: if my_style.get_jquery() == True: jsFile = (self.scriptsDir / 'exe_jquery.js') jsFile.copyfile(contentPages / 'exe_jquery.js') else: jsFile = (self.scriptsDir / 'exe_jquery.js') jsFile.copyfile(contentPages / 'exe_jquery.js') # Copy and minify CSS files css_files = getFilesCSSToMinify('epub3', self.styleDir) exportMinFileCSS(css_files, contentPages) # Copy and minify JS files js_files = getFilesJSToMinify('epub3', self.scriptsDir) exportMinFileJS(js_files, contentPages) # if hasattr(package, 'exportSource') and package.exportSource: # (G.application.config.webDir / 'templates' / 'content.xsd').copyfile(outputDir / 'content.xsd') # (outputDir / 'content.data').write_bytes(encodeObject(package)) # (outputDir / 'contentv3.xml').write_bytes(encodeObjectToXML(package)) if package.license == "license GFDL": # include a copy of the GNU Free Documentation Licence (self.templatesDir / 'fdl.html').copyfile(contentPages / 'fdl.html') # Create the nav.xhtml file container = NavEpub3(self.pages, contentPages) container.save() # Create the publication file publication = PublicationEpub3(self.config, contentPages, package, self.pages, cover) publication.save("package.opf") # Create the container file container = ContainerEpub3(metainfPages) container.save("container.xml") # Zip it up! self.filename.safeSave( self.doZip, _(u'EXPORT FAILED!\nLast succesful export is %s.'), outputDir) # Clean up the temporary dir outputDir.rmtree()
def export(self, package): """ Export SCORM package """ # First do the export to a temporary directory outputDir = TempDirPath() # Copy the style sheet files to the output dir # But not nav.css styleFiles = [self.styleDir/'..'/'base.css'] styleFiles += [self.styleDir/'..'/'popup_bg.gif'] styleFiles += self.styleDir.files("*.css") if "nav.css" in styleFiles: styleFiles.remove("nav.css") styleFiles += self.styleDir.files("*.jpg") styleFiles += self.styleDir.files("*.gif") styleFiles += self.styleDir.files("*.png") styleFiles += self.styleDir.files("*.js") styleFiles += self.styleDir.files("*.html") styleFiles += self.styleDir.files("*.ttf") styleFiles += self.styleDir.files("*.eot") styleFiles += self.styleDir.files("*.otf") styleFiles += self.styleDir.files("*.woff") self.styleDir.copylist(styleFiles, outputDir) # copy the package's resource files package.resourceDir.copyfiles(outputDir) # Export the package content self.pages = [ IMSPage("index", 1, package.root) ] self.generatePages(package.root, 2) uniquifyNames(self.pages) for page in self.pages: page.save(outputDir) # Create the manifest file manifest = Manifest(self.config, outputDir, package, self.pages) manifest.save() # Copy the scripts self.scriptsDir.copylist(('libot_drag.js', 'common.js'), outputDir) self.schemasDir.copylist(('imscp_v1p1.xsd', 'imsmd_v1p2p2.xsd', 'ims_xml.xsd'), outputDir) # copy players for media idevices. hasFlowplayer = False hasMagnifier = False hasXspfplayer = False hasGallery = False isBreak = False for page in self.pages: if isBreak: break for idevice in page.node.idevices: if (hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery): isBreak = True break if not hasFlowplayer: if 'flowPlayer.swf' in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if 'magnifier.swf' in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if 'xspf_player.swf' in idevice.systemResources: hasXspfplayer = True if not hasGallery: if 'GalleryIdevice' == idevice.klass: hasGallery = True if hasFlowplayer: videofile = (self.templatesDir/'flowPlayer.swf') videofile.copyfile(outputDir/'flowPlayer.swf') controlsfile = (self.templatesDir/'flowplayer.controls.swf') controlsfile.copyfile(outputDir/'flowplayer.controls.swf') if hasMagnifier: videofile = (self.templatesDir/'magnifier.swf') videofile.copyfile(outputDir/'magnifier.swf') if hasXspfplayer: videofile = (self.templatesDir/'xspf_player.swf') videofile.copyfile(outputDir/'xspf_player.swf') if hasGallery: imageGalleryCSS = (self.cssDir/'exe_lightbox.css') imageGalleryCSS.copyfile(outputDir/'exe_lightbox.css') imageGalleryJS = (self.scriptsDir/'exe_lightbox.js') imageGalleryJS.copyfile(outputDir/'exe_lightbox.js') self.imagesDir.copylist(('exeGallery_actions.png', 'exeGallery_loading.gif', 'stock-insert-image.png'), outputDir) if package.license == "GNU Free Documentation License": # include a copy of the GNU Free Documentation Licence (self.templatesDir/'fdl.html').copyfile(outputDir/'fdl.html') # Zip it up! self.filename.safeSave(self.doZip, _('EXPORT FAILED!\nLast succesful export is %s.'), outputDir) # Clean up the temporary dir outputDir.rmtree()