iva-0.7.4/ 0000755 0000000 0000000 00000000000 10345616031 0013345 5 ustar viewcvs viewcvs 0000001 0000000 iva-0.7.4/Blog.py 0000644 0000000 0000000 00000032440 10345616031 0014605 0 ustar viewcvs viewcvs 0000001 0000000 # -*- coding: utf-8
# $Id$
#
# Copyright 2005 by IVA Team and contributors
#
# This file is part of IVA.
#
# IVA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# IVA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with IVA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
__version__ = "$Revision$"[11:-2]
from common import translate
import AccessControl
import OFS, Globals
from OFS import SimpleItem
import types
import time
from TraversableWrapper import Traversable
from Globals import Persistent
from AccessControl import ClassSecurityInfo
from Cruft import Cruft
from common import perm_view, perm_edit
from input_checks import strip_tags, strip_all, normal_entry_tags_and_link
### Container for blog
#########################
class Blog(
OFS.Folder.Folder,
OFS.SimpleItem.Item,
Persistent,
AccessControl.Role.RoleManager,
Traversable,
Cruft
):
""" Container for a blog """
meta_type = "Blog"
security = ClassSecurityInfo()
entryID = 0
def getTimeAsText(self, REQUEST, tiime):
"Displays nice time, translated as timestamp_format"
return time.strftime(translate(self,'timestamp_format',default="%H:%M %Y-%m-%d",target=self.giveLanguage(REQUEST)), time.localtime(tiime))
def course_id_from_url(self, REQUEST):
"Extract course id from webtop course folder: /fle_users/uname/webtop/cID/Blog/"
url = self.absolute_url()
start = url.find('/webtop/c')
if start>0:
stop = url.find('/',start+9)
return int(url[start+9:stop])
return -1
def __init__(self, id=''):
"Initialize Blog"
if id:
self.id = id
else:
self.id = 'Blog'
security.declareProtected(perm_view,'get_name')
def get_name(self):
"Get my name, for Leivapururiba"
return "Blog"
security.declareProtected(perm_view,'isOwner')
def isOwner(self,REQUEST,user=False):
"Wether authenticated user is the owner of this blog or teacher, when this is course blog"
x = self.absolute_url()
if x.find('/fle_users/')>0:
return self.kasutajaNimi(REQUEST)==str(REQUEST.AUTHENTICATED_USER)
if x.find('/courses/')>0 and user:
return user.has_role(('Manager','IVAAdmin','Teacher',),self)
return False
security.declareProtected(perm_view,'getNumberOfEntries')
def getNumberOfEntries(self):
"Number of entries in blog"
return len(self.objectValues('Blog'))
security.declareProtected(perm_view,'getEntries')
def getEntries(self,nr=0):
"Array with all entries in the blog"
objects = self.objectValues('Blog')
objects.reverse()
if nr>0:
return objects[:nr]
return objects
security.declareProtected(perm_view,'getArchiveEntries')
def getArchiveEntries(self,REQUEST):
"Array with entries from specified month"
month = REQUEST.get('month', None)
if month is None:
return []
entries = self.getEntries()
result = []
for x in entries:
if time.strftime("%m.%Y",time.localtime(x.getTime()))==month:
result.append(x)
return result
security.declareProtected(perm_view,'getEntriesArchive')
def getEntriesArchive(self,REQUEST):
"Array with entries archive data"
months = ('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December')
entries = self.getEntries()
archive = []
pmonth = ""
for x in entries:
month = time.strftime('%m.%Y',time.localtime(x.getTime()))
if month != pmonth:
pmonth = month
archive.append([month,months[int(month[:2])-1],month[-4:]])
return archive
security.declareProtected(perm_edit,'addEntry')
def addEntry(self, REQUEST, title, intro, content, userLocation):
"Data from addEntryForm"
k=Entry(str(REQUEST.AUTHENTICATED_USER),title,intro,content)
self.entryID += 1
k.id = "entry"+str(self.entryID)
self._setObject(k.id, k)
return REQUEST.RESPONSE.redirect(self.absolute_url()+"?userLocation="+userLocation)
security.declarePublic('rss')
def rss(self, REQUEST):
"Blogs RSS feed version 2.0"
REQUEST.RESPONSE.setHeader("Content-type","text/xml")
t = """\n"""
t += """\n"""
t += "\t\n"
# Create RSS channel description
cid = self.course_id_from_url(REQUEST)
cname = ""
description = ""
userLocation = ""
uname = self.kasutajaNimi(REQUEST)
url = self.absolute_url()
if cid>0: #We are on somebodys webtop -> course nr cid
cattr = getattr(self.fle_root().courses, str(cid))
cname = str(cattr.get_name())
description = str(cattr.get_description())
userLocation = "Webtop"
else: # It's course blog ...
if url.find('/courses/')>0:
cname = str(self.parent().get_name())
description = str(self.parent().get_description())
userLocation = "Bookshelf"
else: # ... or personal one
description = self.firstAndLast(uname)
userLocation = "Organizer"
t += "\t\t"+description+"\n"
# Create RSS channel title
titel = "IVA Blog"
if uname!="":
titel += ": "+self.firstAndLast(uname)
if cname!="":
titel += " @ "+cname
t += "\t\t"+titel+"\n"
t += "\t\t"+self.absolute_url()+"?userLocation="+userLocation+"\n"
#Create RSS channel image
url = ""
if cname=="":
if self.parent().has_photo:
url = self.parent().get_photo_url()
else:
if cid<=0:
if self.parent().hasLogo():
url = self.parent().getLogoURL()
#url = self.parent().absolute_url()+"/kysiLogo"
else:
if cattr.hasLogo():
url = cattr.getLogoURL()
#url = cattr.absolute_url()+"/kysiLogo"
if url != "": #If we have an image
t += "\t\t\n"
t += "\t\t\t"+url+"\n"
t += "\t\t\t"+titel+"\n"
t += "\t\t\t"+self.absolute_url()+"?userLocation="+userLocation+"\n"
t += "\t\t\n"
# Create RSS channel items - 20 last items
for x in self.getEntries(20):
t += "\t\t\n"
t += "\t\t\t"+x.getTitle()+" ("+str(x.getNumberOfComments())+")\n"
t += "\t\t\t"+x.absolute_url()+"/blog_entry?userLocation="+userLocation+"\n"
t += "\t\t\t"+x.getIntro()+"\n"
t += "\t\t\t"+x.getFormattedTime(REQUEST)+"\n"
t += "\t\t\t"+x.getAuthor()+"\n"
t += "\t\t\t"+x.absolute_url()+"/blog_entry?showComments=1&userLocation="+userLocation+"#Comments\n"
t += "\t\t\t"+x.absolute_url()+"\n"
t += "\t\t\n"
t += "\t\n"
t += "\n"
return t
security.declareProtected(perm_view,'index_html')
def index_html(self, REQUEST, userLocation="Webtop"):
"Blogs index - should be redirected to blogs index page"
page = "blog"
if userLocation=="Bookshelf":
page = "course"
return REQUEST.RESPONSE.redirect(self.absolute_url()+"/"+page+"_index?userLocation="+userLocation)
### Container for blog entry
###############################
class Entry(
OFS.Folder.Folder,
OFS.SimpleItem.Item,
Persistent,
AccessControl.Role.RoleManager,
Traversable,
Cruft
):
"Blog entry - a folder, whose attributes are the entry and items are comments"
meta_type = "Blog" #For links in left menu on webtop, Entry is also Blog
security = ClassSecurityInfo()
commentID = 0
def __init__(self, author, title, intro, content):
"Create an entry"
if title=="":
title="Untitled"
self.author = author
self.title = strip_all(title)
self.intro = strip_tags(intro,normal_entry_tags_and_link)
self.content = strip_tags(content,normal_entry_tags_and_link)
self.time = time.time()
self.changeTime = -1
security.declareProtected(perm_view,'getNumberOfComments')
def getNumberOfComments(self):
"Number of comments for this entry"
return len(self.objectValues('BlogComment'))
def getID(self):
"ID"
return self.id
security.declareProtected(perm_view,'get_name')
def get_name(self):
"Get my name, for Leivapururiba"
return self.title
security.declareProtected(perm_view,'getTitle')
def getTitle(self):
"Title of entry"
return self.title
security.declareProtected(perm_view,'getIntro')
def getIntro(self,formatted=False):
"Entrys intro. Formatted means that \n are replaced with \n. Unformatted is for changeEntryForm"
if formatted:
import re
return re.sub("\n"," \n",self.intro)
return self.intro
security.declareProtected(perm_view,'getContent')
def getContent(self,formatted=False):
"Content of entry. Formatted means that \n are replaced with \n. Unformatted is for changeEntryForm"
if formatted:
import re
return re.sub("\n"," \n",self.content)
return self.content
security.declareProtected(perm_view,'getAuthor')
def getAuthor(self,formatted=False):
"Author of entry - formatted means first and last rather than user name"
if formatted:
return self.firstAndLast(self.author)
return self.author
security.declareProtected(perm_view,'getTime')
def getTime(self):
"Entry submission time"
return self.time
security.declareProtected(perm_view,'getFormattedTime')
def getFormattedTime(self, REQUEST):
"Entry submission time as formatted text"
return self.getTimeAsText(REQUEST, self.time)
security.declareProtected(perm_view,'getComments')
def getComments(self, REQUEST):
"Array with 'count' comments starting from 'start' for this entry"
start = int(REQUEST.get('start',1))-1
count = int(REQUEST.get('count',10))
comments = self.objectValues('BlogComment')
return comments[start:start+count]
security.declareProtected(perm_view,'getIntervals')
def getIntervals(self, REQUEST):
"Get comment intervals"
count = int(REQUEST.get('count',10))
intervals = []
nr = self.getNumberOfComments()
for x in range(int(nr/count)+1):
f = x*count+1
l = (x+1)*count
if l>nr:
l = nr
if f<=l:
intervals.append([count, f, l])
return intervals
security.declareProtected(perm_view,'hasBeenChanged')
def hasBeenChanged(self):
"Wether this entry has been changed or not"
return self.changeTime>-1
security.declareProtected(perm_view,'getChangeTime')
def getChangeTime(self):
"Get entry's change time"
return self.changeTime
security.declareProtected(perm_view,'getFormattedChangeTime')
def getFormattedChangeTime(self, REQUEST):
"Get change time as formatted text"
if self.hasBeenChanged():
return self.getTimeAsText(REQUEST,self.changeTime)
return "*"
security.declareProtected(perm_edit,'changeEntry')
def changeEntry(self, REQUEST, title, intro, content, userLocation):
"Change entry"
if title=="":
title = "Untitled"
self.title = strip_all(title)
self.intro = strip_tags(intro,normal_entry_tags_and_link)
self.content = strip_tags(content,normal_entry_tags_and_link)
self.changeTime=time.time()
return REQUEST.RESPONSE.redirect(self.absolute_url()+"/blog_entry?userLocation="+userLocation)
security.declareProtected(perm_view,'addComment')
def addComment(self, REQUEST, title, content, userLocation):
"Add comment to this entry"
c = Comment(str(REQUEST.AUTHENTICATED_USER), title, content)
self.commentID += 1
c.id = "comment"+str(self.commentID)
self._setObject(c.id, c)
return REQUEST.RESPONSE.redirect(self.absolute_url()+"/blog_entry?showComments=1&start="+str(int(self.getNumberOfComments()/10)*10+1)+"&userLocation="+userLocation+"#"+c.id)
security.declareProtected(perm_view,'index_html')
def index_html(self, REQUEST, userLocation="Organizer"):
"Entrys index page"
return REQUEST.RESPONSE.redirect(self.absolute_url()+"/blog_entry?userLocation="+userLocation)
### Container for blog entry comments
########################################
class Comment(
OFS.SimpleItem.Item,
Persistent,
AccessControl.Role.RoleManager,
Traversable,
Cruft,
):
"Comments for entries"
meta_type = "BlogComment"
security = ClassSecurityInfo()
def __init__(self, author, title, content):
"Create a comment"
if title=="":
title="Untitled"
self.author = author
self.title = strip_all(title)
self.content = strip_all(content)
self.time = time.time()
def getID(self):
"ID"
return self.id
security.declareProtected(perm_view,'getAuthor')
def getAuthor(self,formatted=False):
"Author of comment"
if formatted:
return self.firstAndLast(self.author)
return self.author
security.declareProtected(perm_view,'getTitle')
def getTitle(self):
"Title of comment"
return self.title
security.declareProtected(perm_view,'getContent')
def getContent(self,formatted=False):
"Content of comment. Formatted means that \n is replaced with \n"
if formatted:
import re
return re.sub("\n"," \n",self.content)
return self.content
security.declareProtected(perm_view,'getTime')
def getTime(self):
"Entry submission time"
return self.time
security.declareProtected(perm_view,'getFormattedTime')
def getFormattedTime(self, REQUEST):
"Entry submission time as formatted text"
return self.getTimeAsText(REQUEST, self.time)
security.declareProtected(perm_view,'index_html')
def index_html(self, REQUEST):
"Comments index page"
return REQUEST.RESPONSE.redirect(self.parent().absolute_url())
iva-0.7.4/COPYING 0000644 0000000 0000000 00000043131 10345616031 0014402 0 ustar viewcvs viewcvs 0000001 0000000 GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Copyright (C)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.
iva-0.7.4/Course.py 0000644 0000000 0000000 00000137757 10345616031 0015203 0 ustar viewcvs viewcvs 0000001 0000000 # -*- coding: utf-8
# $Id$
#
# Copyright 2001, 2002 by IVA Team and contributors
#
# This file is part of IVA.
#
# IVA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# IVA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with IVA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""Contains class Course, which represents one course, which has one or more CourseContexts, which in turn contain knowledge building conversations."""
__version__ = '$Revision$'[11:-2]
import time, strptime
import string, types
import OFS, Globals
from Globals import Persistent, Acquisition
import AccessControl
from AccessControl import ClassSecurityInfo
import copy
import re
import Kodutoo
import Blog
try:
from Products.ZWiki.ZWikiPage import ZWikiPage
USE_ZWIKI = 1
except:
USE_ZWIKI = 0
from Jamming import Jamming
from TraversableWrapper import Traversable
from common import add_dtml, reload_dtml, intersect_bool, make_action, get_roles, get_local_roles, translate
from input_checks import strip_all, is_valid_title
from CourseContext import CourseContext
#from ThinkingTypeSetManager import ThinkingTypeSetManager as TTSM
from Thread import Thread
from Cruft import Cruft
from TempObjectManager import TempObjectManager
from input_checks import render, normal_entry_tags_and_link
from common import perm_view, perm_edit, perm_manage, perm_add_lo
from Products.ZCatalog.CatalogPathAwareness import CatalogAware
import WebtopTrash
import Subgroups
import Kalender
import WordMap
from QuizManager import QuizManager
# Each Course object contains (usually) one or more CourseContexts, which
# represent different aspects of the course.
# A Course contains information and services on one course implementation.
class Course(
Persistent,
Traversable,
Cruft,
OFS.Folder.Folder,
AccessControl.Role.RoleManager,
OFS.SimpleItem.Item,
Thread,
CatalogAware,
):
"""Course, contained within CourseManager, represents one course."""
meta_type = 'Course'
security = ClassSecurityInfo()
security.declareObjectPublic()
# Call courses/course_html (This way we avoid copying index_html
# to each instance of Course class.)
# ATTENTION: We don't exactly know how this works (for example,
# do we really need REQUEST ?)
#
#TODO: This could be done with a URL pointing to the course_html script.
#But if we need this default implementation, we could use
#restrictedTraverse('course_html') to activate Zope acquisition.
#FIX:bla?
security.declareProtected('View', 'index_html')
def index_html(self, REQUEST=None):
"""Default script"""
return REQUEST.RESPONSE.redirect('course_html')
# Parameters:
#
#- parent: should be a CourseManager
#
#- name: name of the Course
#
#- tts: list of ThinkingTypeSets (copies are made in manage_afterAdd)
#
#- teachers: list of users (of class UserInfo?) that are granted
#Teacher privileges
#
#- etc: other textual information
def __init__(
self,
parent, # Whatever you do, dont bind this to self.
name,
teachers,
description='',
organisation='',
methods='',
starting_date='',
ending_date='',
uniq_id=''
):
"""Constructor of the course."""
# Overriding all_meta_types is not not beautiful...but, hey!, it works!
#self.all_meta_types = (
# {'name': 'ThinkingTypeSet',
# 'action': 'get_id'},)
# Cache active members.
self.active_memb_cache = []
# Remove all HTML tags from parameters
name = strip_all(name)
description = strip_all(description)
methods = strip_all(methods)
organisation = strip_all(organisation)
Thread.__init__(self, parent) # Takes care of id and title.
if teachers != ('',):
for teacher in teachers:
self.set_roles(teacher, ('Teacher',))
self.__name = name # name of the course
self.__organisation = organisation
self.__description = description
self.__methods = methods
self.__starting_date = starting_date
self.__ending_date = ending_date
self.__credits = ''
self.__courseID = ''
self.__quote = ''
self.course_category = 0
self.default_catalog = 'courses_zcatalog'
# course should have uniq id since self.id tends to change
self.setUniqId(uniq_id)
# This is for group folder path listings - show path up to course.
self.toplevel = 1
security.declarePrivate('manage_afterAdd')
#Each course should have its own copy of the ThinkingTypeSets,
#as the course administrator (teacher) should be able to edit them,
#create new ones and so forth. These changes must not propagate to
#other courses: hence the copying of the set.
def manage_afterAdd(self, item, container):
"""foo"""
from common import roles_student, roles_tutor, roles_teacher
from common import roles_admin
# add subgroups manager
sg = Subgroups.SubgroupManager()
self._setObject(sg.id, sg)
# add quizes
qm = QuizManager()
self._setObject(qm.id, qm)
# add jamming
self._setObject('jamming', Jamming('jamming'))
# add wordmaps
# XXX: disabled untill announced
#wf=WordMap.WordmapFolder()
#wf.id="wordmaps"
#self._setObject(wf.id, wf)
# add assignments
k=Kodutoo.KodutoodeKataloog()
k.id='kodutood'
self._setObject(k.id, k)
self.index_object()
# add blog
b = Blog.Blog()
b.id = "Blog"
self._setObject(b.id,b)
# add calendar
cal = Kalender.KalendriSyndmusteKataloog()
self._setObject('syndmused', cal)
security.declarePrivate('manage_beforeDelete')
def manage_beforeDelete(self, item, container):
""" manage before delete """
self.unindex_object()
security.declareProtected(perm_edit, 'add_course_form_handler')
def add_course_form_handler(self, REQUEST,
course_id, my_name, desc, organisation, methods,
start_date, end_date,
cancel='', # submit buttons
add='', #
tekst='',
logo_upload=None,
staatus=0,
regStatus=0,
cCat = 0,
credits='',
courseID='',
delete_logo='',
):
""" modify course info, override CourseManager method. """
if cancel:
return REQUEST.RESPONSE.redirect('course_info?course_id=%s' % course_id)
elif not add: raise 'IVA Error', 'Inknown button'
if course_id != self.get_id() or not course_id:
return
action=apply(
make_action,
['manage_course_info'] +
[(x, eval(x)) for x in
('my_name', 'desc', 'organisation', 'methods',
'start_date', 'end_date')])
action += '&course_id=' + course_id
my_name=my_name.strip()
if not is_valid_title(my_name):
return self.message_dialog_error(
self, REQUEST,
title='Invalid name',
message='Give valid name',
action=action)
if my_name != self.get_name():
if my_name in [x.get_name for x in self.get_courses()]:
return self.message_dialog_error(
self, REQUEST,
title='Invalid name',
message="Name '%s' taken" % my_name,
action=action)
from common import convert_date # convert dates to time.time()-format
errors = []
if not start_date:
starting_date = 0
else:
try:
time_tuple = strptime.strptime(start_date,
translate(self,'short_date_format',default="%Y-%m-%d",target=self.giveLanguage(REQUEST)))
starting_date = convert_date(str(time_tuple[2]), # day
str(time_tuple[1]), # month
str(time_tuple[0])) # year
except:
errors.append(translate(self,'Starting date:',default="%Y-%m-%d",target=self.giveLanguage(REQUEST)),)
if not end_date:
ending_date = 0
else:
try:
time_tuple = strptime.strptime(end_date,
translate(self,'short_date_format',default="%Y-%m-%d",target=self.giveLanguage(REQUEST)))
ending_date = convert_date(str(time_tuple[2]), # day
str(time_tuple[1]), # month
str(time_tuple[0])) # year
except:
errors.append(translate(self,'Ending date:',default="%Y-%m-%d",target=self.giveLanguage(REQUEST)),)
organisation = organisation.strip()
if organisation and not is_valid_title(organisation):
errors.append(translate(self,'Organization',target=self.giveLanguage(REQUEST)))
if len(errors) > 0:
return self.message_dialog_error(
self, REQUEST,
title='Invalid input',
message=translate(self,'Invalid fields',target=self.giveLanguage(REQUEST)) + ": '" + \
"' , '".join(errors) + "'",
action=action)
logo = None
try:
if len(logo_upload.filename)>0:
logo=logo_upload.read()
else:
logo = None
except AttributeError:
pass
self.update(
my_name,
desc,
organisation,
methods,
starting_date,
ending_date,
tekst,
logo,
staatus,
regStatus,
cCat,
credits,
courseID,
delete_logo,
)
return REQUEST.RESPONSE.redirect(self.absolute_url()+'/gf/course_info')
def is_courseContext(self):
""" is course context? """
return
def kasTeadmuspajasKontekste(self):
"jah/ei"
return len(self.objectValues('CourseContext'))>0
def kasMeediapajasProjekte(self):
"jah/ei"
return len(self.jamming.objectValues('JamSession'))>0
def kysiOotajad(self, REQUEST=None):
"Kursusele registreerunud, keda pole veel kinnitatud"
return getattr(self, 'ootajad', [])
security.declareProtected(perm_edit,'manage_pendingUsers_handler')
def manage_pendingUsers_handler(self, REQUEST, addtocourse='',deletefromlist='',pender=''):
"Lisamine vői kustutus"
#from Kirjakast import Kirjakast
temp = getattr(self.fle_root(), 'fle_users')
if not pender:
return self.message_dialog_error(self, REQUEST,
title="Error",
message='Please select some users first',
action='manage_pendingUsers')
if type(pender)==types.StringType:
pender=(pender,)
penders=self.kysiOotajad()
new_penders = []
if deletefromlist:
for x in pender:
puser = getattr(temp, x)
for y in penders:
if y == x: continue
new_penders.append(y)
if addtocourse:
for x in pender:
puser = getattr(temp, x)
self.add_student(puser.get_uname())
mess_title = translate(self,'Added to course',target=self.giveLanguage(REQUEST))
mess_body = translate(self,'You have been added to course ',target=self.giveLanguage(REQUEST))+' '+self.get_name()
puser.kirjad.saadaKiri(REQUEST,puser.get_uname(),puser.get_uname(),mess_title,mess_body,999999)
for x in penders:
if x not in pender:
new_penders.append(x)
self.ootajad=new_penders
return REQUEST.RESPONSE.redirect('haldusleht')
def ootajastKursuseLiikmeks(self, REQUEST, kasutaja):
"Lisamine"
self.add_student(kasutaja)
return 1
def lisaOotaja(self, REQUEST, ootaja):
""" Kasutaja lisab end ootama """
if self.getRegStatus()=='2': #automaatregistreerumine
self.ootajastKursuseLiikmeks(REQUEST, ootaja)
else:
m=self.kysiOotajad(REQUEST)
if ootaja not in m:
m.append(ootaja)
elif ootaja in m:
m.remove(ootaja)
self.ootajad=m
return 0
def kasOotaja(self, nimi):
"Kas jooksev kasutaja on kursusele ootaja"
m=self.kysiOotajad()
kas=0
for x in m:
if nimi==x:
kas=1
return kas
security.declareProtected(perm_view, 'get_printable_name')
# No additional comments.
def get_printable_name(self):
"""Return name of the course."""
return self.__name
security.declareProtected(perm_view, 'get_bg_colour_name')
def get_bg_colour_name(self):
"""..."""
return 'gr'
# security.declareProtected(perm_view, 'get_name')
security.declarePublic('get_name')
# No additional comments.
def get_name(self):
"""Get course name."""
return self.__name
security.declareProtected(perm_view, 'get_organisation')
# No additional comments.
def get_organisation(self):
"""Get organisation name."""
return self.__organisation
security.declareProtected(perm_view, 'get_description')
# No additional comments.
def get_description(self):
"""Get description."""
return self.__description
security.declareProtected(perm_view,'render_description')
def render_description(self):
"""Render description."""
return render(
self.get_description(),
legal_tags=normal_entry_tags_and_link)
security.declareProtected(perm_view, 'get_methods')
# No additional comments.
def get_methods(self):
"""Get info on methods."""
return self.__methods
security.declareProtected(perm_view,'render_methods')
def render_methods(self):
"""Render methods."""
return render(
self.get_methods(),
legal_tags=normal_entry_tags_and_link)
def get_courseID(self):
""" get course id """
try:
return self.__courseID
except AttributeError:
return ""
def set_courseID(self,courseID):
""" set course id(the other one) """
self.__courseID = courseID
def get_credits(self):
""" get credits info """
try:
return self.__credits
except AttributeError:
return ""
def set_credits(self,credits):
""" set credits """
self.__credits = credits
# security.declareProtected(perm_view, 'get_teachers')
# No additional comments.
security.declarePublic('get_teachers')
def get_teachers(self):
"""Get teachers."""
retval = []
for (user, roles) in self.get_local_roles():
if 'Teacher' in roles:
retval.append(user)
return retval
security.declareProtected(perm_view, 'get_start_dd')
# No additional comments.
def get_start_dd(self):
"""Return starting day."""
if self.__starting_date:
return time.localtime(self.__starting_date)[2]
else:
return ''
security.declareProtected(perm_view, 'get_start_mm')
# No additional comments.
def get_start_mm(self):
"""Return starting month."""
if self.__starting_date:
return time.localtime(self.__starting_date)[1]
else:
return ''
security.declareProtected(perm_view, 'get_start_yyyy')
# No additional comments.
def get_start_yyyy(self):
"""Return starting year."""
if self.__starting_date:
return time.localtime(self.__starting_date)[0]
else:
return ''
security.declareProtected(perm_view, 'get_end_dd')
# No additional comments.
def get_end_dd(self):
"""Return ending day."""
if self.__ending_date:
return time.localtime(self.__ending_date)[2]
else:
return ''
security.declareProtected(perm_view, 'get_end_mm')
# No additional comments.
def get_end_mm(self):
"""Return ending month."""
if self.__ending_date:
return time.localtime(self.__ending_date)[1]
else:
return ''
security.declareProtected(perm_view, 'get_end_yyyy')
# No additional comments.
def get_end_yyyy(self):
"""Return ending year."""
if self.__ending_date:
return time.localtime(self.__ending_date)[0]
else:
return ''
# security.declareProtected(perm_view, 'get_printable_starting_date')
security.declarePublic('get_printable_starting_date')
#FIX:security check
# No additional comments.
def get_printable_starting_date(self, REQUEST):
"""Get starting date."""
return time.strftime(translate(self,'short_date_format',default="%Y-%m-%d",target=self.giveLanguage(REQUEST)),
time.localtime(self.__starting_date))
# security.declareProtected(perm_view, 'get_printable_ending_date')
security.declarePublic('get_printable_ending_date')
#FIX:security check
# No additional comments.
def get_printable_ending_date(self, REQUEST):
"""Get ending date."""
if self.__ending_date == 0: return ''
return time.strftime(translate(self,'short_date_format',default="%Y-%m-%d",target=self.giveLanguage(REQUEST)),
time.localtime(self.__ending_date))
security.declarePrivate('get_start_date')
def get_start_date(self):
return self.__starting_date
security.declarePrivate('get_end_date')
def get_end_date(self):
return self.__ending_date
security.declareProtected(perm_view, 'get_users')
def get_users(self, REQUEST):
"""Return dict with 2 members of attendees as UserInfo objects.
'active_d' is the list of active members.
'others_d' is the rest ..
[[UIObj'active1'], [UIObj'other1', UIObj'other2', ..]]"""
rv = {'active_d':[], 'others_d': []}
au = str(REQUEST.AUTHENTICATED_USER)
for uname in [(u[0]) for u in self.get_local_roles()]:
from Errors import FleError
try:
o = self.fle_users.get_user_info(uname)
if uname == au or uname in self.active_memb_cache:
rv['active_d'].append(o)
else:
rv['others_d'].append(o)
except FleError:
pass
return rv
security.declarePublic('get_n_users')
def get_n_users(self):
return len(self.get_all_users_id())
security.declareProtected(perm_view, 'get_all_users')
def get_all_users(self):
"""Return a list of all users on course."""
rv = []
for uname in self.get_all_users_id():
try:
rv.append(self.fle_users.get_user_info(uname))
except Exception:
pass
return rv
def kasutajateKodutoodeArhiiv(self, REQUEST):
"Arhiiv, kuhu paigutatakse kasutaja esitatud materjalid"
import tempfile
import zipfile
failinimi=tempfile.mktemp()
arhiiv=zipfile.ZipFile(failinimi,"w",zipfile.ZIP_DEFLATED)
kasutajad=self.get_all_users()
for x in kasutajad:
kc=getattr(x.webtop, 'c'+self.id)
for too in self.kodutood.objectValues():
if too.tyyp==1: #materjal
if hasattr(kc, 'portfolio'):
if hasattr(kc.portfolio, too.id):
tookataloog=getattr(kc.portfolio, too.id)
tookataloog.looArhiiv(REQUEST, arhiiv, x.id+'/')
if too.tyyp==2: #grupp
mitu=0
punkte=-1
for kg in x.kysiKursuseSisegrupid(self):
if kg.id in too.grupid:
#XXX:TODO: check this, might be incorrect
esitluskaust=getattr(self.leiaGrupiKaust(kg.id), too.id)
esitluskaust.looArhiiv(REQUEST, arhiiv, kg.id+'/')
arhiiv.close()
file = open(failinimi,"rb")
export_data=file.read()
file.close()
import os
os.remove(failinimi)
REQUEST.RESPONSE.setHeader('Content-type','application/zip')
REQUEST.RESPONSE.setHeader('Content-disposition','attachment; filename=tooarhiiv.zip')
return export_data
def fotogaKasutajad(self):
"kasutajad, kel on foto"
m=[]
for x in self.get_all_users():
if x.has_photo():
m.append(x)
return m
def fototaKasutajad(self):
"kasutajad, kel pole fotot"
m=[]
for x in self.get_all_users():
if not x.has_photo():
m.append(x)
return m
security.declareProtected(perm_view, 'get_all_users_id')
def get_all_users_id(self):
"""Return a list of all users on this course. Same thing as
get_all_users, but this one returns a list of id's of UserInfo
objects, not the UserInfo object reference."""
cl = []
for u in self.get_local_roles():
if 'Student' in u[1] or 'Teacher' in u[1]: cl.append(u[0])
return cl
# return [u[0] for u in self.get_local_roles()]
security.declareProtected(perm_view, 'get_users_with_role')
def get_users_with_role(self, role):
"""Return a list of participants who have a specified role."""
rv = []
for e in self.get_local_roles():
if role in e[1]:
# try:
rv.append(self.fle_users.get_user_info(e[0]))
# except Exception:
# pass
return rv
def get_sorted_user_list(self, role):
nimed = []
rolliga = self.get_users_with_role(role)
for aaa in rolliga:
temp = []
if aaa.get_last_name()=='' and aaa.get_first_name()=='':
temp.append(aaa.get_id())
temp.append(aaa.get_id())
temp.append(aaa)
nimed.append(temp)
else:
temp.append(aaa.get_last_name().lower())
temp.append(aaa.get_first_name().lower())
temp.append(aaa)
nimed.append(temp)
nimed.sort()
uuserid = []
for kasutajad in nimed:
uuserid.append(kasutajad[2])
return uuserid
security.declareProtected(perm_edit, 'add_student')
#The person is added with Student role access.
# NOTE: This method is no longer needed, except in the test cases!
def add_student(self, name):
"""Add person to the course."""
# Check that user exists... Raises exception if not.
#XXX: is this really needed!? now commented out
# self.fle_users.get_user_info(name)
uinf = self.fle_users.get_user_info(name)
uinf.user_courselist_cache.append(self.get_id())
uinf._p_changed = True
self.set_roles(name, ('Student',))
self.reindex_object()
security.declareProtected(perm_view, 'get_valid_roles')
# No additional comments.
def get_valid_roles(self):
"""Get the roles valid for persons added to the course."""
from CourseManager import course_level_roles
valid_roles = list(course_level_roles)
#valid_roles.append('Teacher')
return valid_roles
security.declareProtected(perm_manage, 'remove_person')
def remove_person(self, person):
"""Remove person from the course."""
# Check that user exists... Raises exception if not.
kasutaja=self.fle_users.get_user_info(person)
try:
kasutaja.user_courselist_cache.remove(self.get_id())
except:
pass
kasutaja._p_changed = True
#We have to do it the hard way since set_jooksev_kursus turns me away
kasutaja.jooksev_kursus=0
# We use the get_local_roles method, because we need to
# see if the user has a role attached to this course object
# specifically, and we don't want the roles in the acquisition
# tree to interfere.
if len(get_local_roles(self,person))==0:
raise FleError, ("User "+person+" does not belong to this course.")
self.__unset_roles((person,))
# Note: person _must_ be a sequence!
def __unset_roles(self, persons):
"""Unset roles of one user."""
self.manage_delLocalRoles(persons)
security.declareProtected(perm_view, 'has_role')
# No additional comments.
def has_role(self, person, role):
"""Return whether the user is in the specified role."""
return role in get_roles(self,person)
security.declareProtected(perm_view, 'get_teacher')
def get_teacher(self):
"""Get the name of the teacher (creator of the course)."""
for user,roles in self.get_local_roles():
if 'Teacher' in roles:
return user
raise 'Course has no teacher!'
security.declareProtected(perm_edit, 'set_roles')
# Note: roles _must_ be a sequence!
# Called from CourseManager.add_users_form_handler
def set_roles(self, person, roles):
"""Set roles of one person."""
self.__unset_roles(person)
self.manage_setLocalRoles(person, roles)
# FIXME: input_checks: tt_set_name not checked
# FIXME: input_checks: two course contexts can have identical name.
security.declareProtected(perm_add_lo, 'add_course_context')
# Handler for add_course_context_form
def add_course_context(
self, my_name, description, tt_set_name,
description_long,
REQUEST,
use_roleplay='', # New in ZPTIVA
show_only_roleplay='',
# Submit buttons.
publish='',
cancel='',
):
"""Add CourseContext object."""
if publish:
error_fields = []
errors = []
my_name = my_name.strip()
if not is_valid_title(my_name):
error_fields.append(translate(self,'title of context',target=self.giveLanguage(REQUEST)))
if my_name in [x[1] for x in self.get_course_context_names()]:
errors.append(translate(self,"Name '%s' taken",target=self.giveLanguage(REQUEST)) % my_name)
# Variables 'description' and 'description_long' are not checked
# because render_description() and render_long_description()
# methods in CourseContext filter out unwanted HTML tags.
if len(error_fields) > 0 or len(errors) > 0:
msg = ", ".join(errors)
if len(error_fields) > 0:
msg = msg + " " + 'Invalid fields' + \
": '" + "' , '".join(error_fields) + "'"
return self.message_dialog_error(
self, REQUEST,
title='Invalid input',
message=msg,
action=apply(
make_action,
['add_course_context_form'] +
[(x, eval(x)) for x in
('my_name', 'description', 'tt_set_name',
'description_long')]))
uname=str(REQUEST.AUTHENTICATED_USER)
obj = CourseContext(
self, my_name, description, description_long, tt_set_name,
uname,)
obj.public = 1
if (show_only_roleplay)==1:
obj.__roleplay_only = 1
id = obj.get_id()
self._setObject(id, obj)
#XXX: statistics - lisaSyndmus(konteksteLisatud. should it be somewhere?
#self.lisaSyndmus(REQUEST, 'konteksteLisatud')
try:
obj.changeOwnership(self.acl_users.getUser(uname).__of__(self.acl_users))
obj.manage_setLocalRoles(uname,('Owner',))
except:
pass
if REQUEST:
pagename=""
if use_roleplay:
pagename="course_setup_roleplay_form"
REQUEST.RESPONSE.redirect('%s/%s' % (str(id),pagename))
elif cancel:
return REQUEST.RESPONSE.redirect(REQUEST.URL1)
else:
raise "add_course_context called without 'publish' or 'cancel'"
security.declareProtected(perm_view, 'get_course_context_names')
# No additional comments.
def get_course_context_names(self):
"""Return a list of CourseContext names."""
retval = {}
for e in self.get_children('CourseContext'):
id = e.get_id()
name = e.get_name()
retval[id] = name
return retval.items()
#security.declareProtected(perm_view, 'get_n_notes')
def get_n_notes(self):
"""Returns a sum of all notes in all contexts."""
count = 0
for cc in self.get_course_contexts():
count += cc.get_n_notes()
return count
security.declareProtected(perm_view, 'get_n_unread_notes')
def get_n_unread_notes(self,uname):
"""Returns a sum of all unread notes in all contexts."""
count = 0
for cc in self.get_course_contexts():
count += cc.get_n_unread_notes(uname)
return count
security.declarePublic('update')
# Parameters are received from the form (apparently).
def update(
self,
name,
description,
organisation,
methods,
starting_date,
ending_date,
tekst,
logo=None,
status=0,
regStatus = 0,
cCat = 0,
credits='',
courseID='',
delete_logo = '',
):
"""Edit course information."""
self.__name = name
self.__description = description
self.__organisation = organisation
self.__methods = methods
self.__starting_date = starting_date
self.__ending_date = ending_date
self.setQuote(tekst)
if logo:
self.setLogo(logo)
self.setStatus(status)
self.setRegStatus(regStatus)
if cCat:
self.setCourseCategory(int(cCat))
self.set_credits(credits)
self.set_courseID(courseID)
if delete_logo:
self.removeLogo()
#XXX: remove
self.default_catalog = 'courses_zcatalog'
self.reindex_object()
security.declareProtected(perm_view, 'get_course_contexts')
def get_course_contexts(self):
"""Return a list of all course contexts in this course."""
for abc in self.get_children('CourseContext'):
if not getattr(abc, 'public', None):
abc.public = 1
return self.get_children('CourseContext')
security.declareProtected(perm_view, 'get_course_context_ids_in_order')
def get_course_context_ids_in_order(self, id_list):
"""Return a list of ids of all course contexts in this course."""
return [o.get_id() for o in self.get_course_contexts_in_order(id_list)]
security.declareProtected(perm_edit, 'delete_course_context')
def context_form_handler(self,REQUEST,cc_id,staatus='', kustuta=''):
""" delete or change status """
import types
if type(cc_id) is types.StringType:
cc_id = ((cc_id),)
#if staatus and kustuta:
# raise 'IVA error','oops, both buttons athe same time in Knowledge building form'
for abc in cc_id:
self.hide_show_course_context(abc)
#if kustuta:
# for abc in cc_id:
# self.delete_course_context(abc)
return REQUEST.RESPONSE.redirect(self.absolute_url()+'/course_html')
security.declareProtected(perm_edit, 'delete_course_context')
def delete_course_context(self,id):
for c in self.get_children('CourseContext'):
if c.get_id() == id:
self._delObject(id)
return
security.declareProtected(perm_edit, 'hide_show_course_context')
def hide_show_course_context(self,id):
for c in self.get_children('CourseContext'):
if c.get_id() == id:
if c.public == 1:
c.public = 0
else:
c.public = 1
return
# FIXME: See the random comment below, random is not
# FIXME: probably the order that we really want.
security.declareProtected(perm_view, 'get_course_contexts_in_order')
def get_course_contexts_in_order(self, id_list):
"""Return a list of all course contexts in this course."""
contexts = {}
for c in self.get_children('CourseContext'):
contexts[c.get_id()] = c
try:
pass
except:
c.public = 1
retval = []
if id_list and id_list != ['']:
if type(id_list) == types.StringType:
id_list = (id_list, )
# Return courses contexts in a given order.
for identifier in id_list:
try:
retval.append(contexts[identifier])
del contexts[identifier]
except KeyError: # invalid id_list
pass
# If we still course contexts left (id_list is shorter
# than the actual number of course_contexts), append
# them to list in a random order.
for key in contexts.keys():
retval.append(contexts[key])
return retval
security.declarePublic('may_view_course')
def may_view_course(self, REQUEST):
"""Return boolean depending on wether user may or may not view
the course."""
from AccessControl.PermissionRole import rolesForPermissionOn
return intersect_bool(
get_roles(self,str(REQUEST.AUTHENTICATED_USER)),
rolesForPermissionOn(perm_view,self))
security.declareProtected(perm_view, 'may_add_course_context')
def may_add_course_context(self, person):
"""Return boolean depending on wether user may or may not add
a course context to the course."""
from AccessControl.PermissionRole import rolesForPermissionOn
return intersect_bool(
get_roles(self,person),
rolesForPermissionOn(perm_add_lo,self))
security.declareProtected(perm_view, 'may_edit_course')
def may_edit_course(self, person):
"""Return boolean depending on whether person can edit the course
or not."""
from AccessControl.PermissionRole import rolesForPermissionOn
return intersect_bool(
get_roles(self,person),
rolesForPermissionOn(perm_edit,self))
security.declareProtected(perm_view, 'active_members')
#FIXME: Why not "get_active_members"
def active_members(self):
"""Return a list of names of users who are active."""
return self.active_memb_cache
security.declareProtected(perm_view, 'has_group_folder')
def has_group_folder(self):
"""Return whether course has a group folder or not."""
return len(self.objectIds('GroupFolder'))>0
def add_folder(self, my_name):
from GroupFolder import GroupFolder
from GroupFolderProxy import GroupFolderProxy
new_id = 'gf'
fol = GroupFolder(None,my_name)
fol.id=new_id
self._setObject(new_id,fol)
fol=fol.__of__(self)
# self.make_group_folder_proxies(self.get_all_users())
proxy = GroupFolderProxy(None, # any sense?
self.get_name(),
self.get_id())
self.jamming._setObject('0', proxy)
return fol
def make_group_folder_proxies(self, users):
for user in users:
# user.webtop.add_link(self.get_name()+" (Shared)",self.get_url_to_object(self.gf),1)
user.webtop.add_group_folder_proxy(self.get_name(), self.get_id())
def remove_folder_link(self,users):
gf = self.get_child('gf')
for user in users:
fol = user.webtop
self.__recurse_remove_folder_link(fol, gf)
def __recurse_remove_folder_link(self, folder, gf):
for (_id, proxy_fol) in folder.objectItems('GroupFolderProxy'):
if proxy_fol.is_proxy_for(gf):
folder._delObject(_id)
for fol in folder.objectValues('WebtopFolder'):
self.__recurse_remove_folder_link(fol, gf)
security.declareProtected(perm_edit, 'teacher_import_handler')
def teacher_import_handler(self, REQUEST, file='', to_import=''):
""" Form handler for teacher """
kursusenr = self.get_course_id_from_req(REQUEST)
if not self.kas_opetaja(REQUEST):
return "Keelatud"
uname = REQUEST.AUTHENTICATED_USER.getUserName()
from ImportExportIMS import Importer
from ImportExport import Exporter
import tempfile, os
filename = tempfile.mktemp()
f = open(filename,"w+b")
f.write(file.read())
f.close()
import_data=None
imported = Importer(uname,self.fle_root(),'',getattr(self.fle_root().courses, kursusenr),kasuta_jooksvat=1)
imported.loadZip(filename)
element = imported.loadFile('imsmanifest.xml')
imported.processFile(self,element)
return REQUEST.RESPONSE.redirect(self.absolute_url()+'/'+str(kursusenr)+'/gf/course_info')
security.declareProtected(perm_edit, 'teacher_export')
def teacher_export(self,REQUEST):
""" teacher export """
return self.iva_ims_export(REQUEST)
security.declareProtected(perm_edit, 'iva_ims_export')
def iva_ims_export(self, REQUEST=None, testinimi='',teacherExporting=1):
""" Course or a quiz export. XML format. """
from ImportExportIMS import Kirjutus
from ImportExportIMS import kirjutaYldM
import tempfile, os
failinimi = tempfile.mktemp()
# self.fle_users.export_users(REQUEST,failinimi='ivaexport.zip',kursusega='jah',palju='self.fle_root().fle_users.get_users()')
if testinimi:
yld = kirjutaYldM()
yld.kirjutaYldmanifest(self.get_id(),'QTI test','imsqti_xmlv1p1','','qti.xml')
yld.lisaFaili(failinimi)
k= Kirjutus(self.fle_root(), self.get_id())
#k.looKursuseFail()
#k.exportQTI(failinimi,'')
parent = k.looTestiFail()
k.kirjutaTestid(parent,testinimi)
k.kirjutaTestidZipi(failinimi,'')
#k.pakiKursusFaili(failinimi)
# k.pakiTulemusFaili(failinimi,testsonly="testsonly")
else:
yld = kirjutaYldM()
yld.kirjutaYldmanifest(self.get_id(), self.get_description(),base=str(self.get_id())+"/")
yld.lisaFaili(failinimi)
k = Kirjutus(self.fle_root(), self.get_id())
k.looKursuseFail()
k.kirjutavCal(self.syndmused,'kursus','GROUP')
k.kirjutaWebtop(self.gf,tiitel='RAAMATURIIUL')
for sisegr in self.subgroups.objectValues('GroupFolder'):
k.kirjutaWebtop(sisegr,'SISEGRUPP:'+sisegr.get_name())
try:
k.kirjutavCal(sisegr.syndmused,sisegr.get_name(),'GROUP')
except:
pass
if not teacherExporting:
k.kirjutaKasutajaWebtop(self.get_all_users())
#k.kirjutaKasutajaSyndmus(self.get_all_users())
self.fle_users.export_users(REQUEST,failinimi=failinimi,kursusega=self.get_id(),palju='kursus.get_all_users()')
k.kirjutaItem(k.organization, tiitel='KURSUSE KASUTAJAD',parameters='KURSUSE KASUTAJAD')
k.kirjutaResource(k.resources, 'imsent_xmlv1p1','users.xml')
k.exportQTI(failinimi,str(self.get_id())+"/",teacherExporting=teacherExporting)
k.exportPajad(failinimi,str(self.get_id())+"/",startonly=teacherExporting)
k.exportKodutood(self.kodutood,failinimi,str(self.get_id())+"/")
k.pakiKursusFaili(failinimi)
if REQUEST:
file = open(failinimi,"rb")
export_data=file.read()
file.close()
os.remove(failinimi)
REQUEST.RESPONSE.setHeader('Content-disposition','attachment; filename=ivaexport.zip')
REQUEST.RESPONSE.setHeader('content-type','application/zip')
return export_data
else:
import os
import shutil
name='iva_'+re.sub('[^a-zA-Z0-9]', '_', self.get_name())
name2 = name
number = 1
searched=0
print os.path.isfile(os.path.join(Globals.INSTANCE_HOME,'var',name+'.zip'))
print os.path.join(Globals.INSTANCE_HOME,'var',name+'.zip')
while os.path.isfile(os.path.join(Globals.INSTANCE_HOME,'var',name+'.zip')):
number = number + 1
name = name2+'_ver'+str(number)
searched=1
name += '.zip'
shutil.move(failinimi,os.path.join(Globals.INSTANCE_HOME,'var',name))
return self.get_name() + ' - ' + os.path.join(Globals.INSTANCE_HOME,'var',name)
def write_touchgraph_data(self,obj,type,children_types=None,extra_links=None):
links = ''
if children_types:
links = ' '.join(obj.objectIds(children_types))
if extra_links:
links = ' '.join((links,extra_links))
if not links:
links=' '
return obj.get_id()+'\t'+\
type+"\t"+\
self.REQUEST.BASE0+self.get_url_to_object(obj)+'\t'+\
obj.get_name()+'\t'\
+links+'\t'
# But should we protect it somehow?
# The Java client would then need authentication
def touchgraph_data(self):
"""This is a public method."""
data=self.write_touchgraph_data(self,"COURSE","CourseContext")
for ctx in self.objectValues("CourseContext"):
data=data+ctx.touchgraph_data()
return data+"[END DATA]"
def getQuote(self):
"Kursuse uudis/moto. Vastab tyhja kui pole"
return self.__quote
def setQuote(self, tekst):
""" set quote """
self.__quote=tekst
security.declareProtected(perm_edit, 'removeLogo')
def removeLogo(self):
""" remove logo """
imgp = getattr(self.fle_root().images, 'courses_imgs', None)
try:
imgp._delObject('course_'+str(self.get_id())+'_image')
except AttributeError:
pass
security.declareProtected(perm_edit, 'setLogo')
def setLogo(self, img):
""" add course logo """
resize = 1
try:
from PIL import Image
except ImportError:
resize = 0
import cStringIO
imgp = getattr(self.fle_root().images, 'courses_imgs', None)
if imgp is None:
return 0
try:
s = cStringIO.StringIO(img)
if resize:
im = Image.open(s)
(width, height) = im.size
if height == 80 and im.format == 'JPEG':
pass
else:
if im.mode != 'RGB':
im = im.convert('RGB')
if height > 300:
mod = float(300)/float(height)
width = width*mod
height = height*mod
im = im.resize((int(width),int(height)))
if width > 300:
mod = float(300)/float(width)
width = width*mod
height = height*mod
im = im.resize((int(width),int(height)))
s = cStringIO.StringIO()
try:
im.save(s, "JPEG", quality=100)
except KeyError:
im.save(s, "GIF", quality=100)
s.seek(0)
img = s.read()
try:
imgp._delObject('course_'+str(self.get_id())+'_image')
except AttributeError:
pass
imgp.manage_addImage('course_'+str(self.get_id())+'_image', img, 'image')
img = getattr(imgp, 'course_'+str(self.get_id())+'_image')
img.ZCacheable_setManagerId('HTTPCache')
img.ZCacheable_invalidate()
except:
return 0
self.setLogoThumbnail()
return 1
security.declarePrivate('setLogoThumbnail')
def setLogoThumbnail(self):
""" creates thumbnail from uploaded course logo """
resize = 1
try:
from PIL import Image
except ImportError:
resize = 0
if not resize: return 1
import cStringIO
imgp = getattr(self.fle_root().images, 'courses_imgs', None)
if imgp is None:
return 1
if 1==1:
oimg = getattr(imgp, 'course_'+str(self.get_id())+'_image', None)
try:
s = cStringIO.StringIO(oimg.data)
except TypeError:
s = cStringIO.StringIO(str(oimg.data))
if s is None: return 1
im = Image.open(s)
(width, height) = im.size
# resize image 59x59
if height > 59:
mod = float(59)/float(height)
width = width*mod
height = height*mod
im = im.resize((int(width), int(height)))
if width > 59:
mod = float(59)/float(width)
width = width*mod
height = height*mod
im = im.resize((int(width), int(height)))
s = cStringIO.StringIO()
try:
im.save(s, "JPEG", quality=100)
except KeyError:
im.save(s, "GIF", quality=100)
s.seek(0)
img = s.read()
try:
imgp._delObject('course_'+str(self.get_id())+'_image_thumbnail')
except AttributeError:
pass
imgp.manage_addImage('course_'+str(self.get_id())+'_image_thumbnail', img, 'image')
img = getattr(imgp, 'course_'+str(self.get_id())+'_image_thumbnail')
img.ZCacheable_setManagerId('HTTPCache')
img.ZCacheable_invalidate()
def hasLogo(self):
""" if course has its own logo """
# XXX:weird hack
if not getattr(self.images.courses_imgs, 'course_'+str(self.get_id())+'_image', None):
return 0
return 1
def hasLogoThumbnail(self):
""" if course logo has thumbnail """
if not self.hasLogo():
return 0
if not getattr(self.images.courses_imgs, 'course_'+str(self.get_id())+'_image_thumbnail', None):
self.setLogoThumbnail()
return 0
return 1
def getLogoTag(self, REQUEST=None):
""" "
return getattr(self.images, 'course_default')
def getLogoURL(self):
""" URL to course logo """
if self.hasLogo():
return getattr(self.images.courses_imgs, 'course_'+str(self.get_id())+'_image', None).absolute_url(1)
return getattr(self.images, 'course_default').absolute_url(1)
def getLogoThumbnailURL(self):
""" URL to course logo thumbnail """
if self.hasLogoThumbnail():
return getattr(self.images.courses_imgs, 'course_'+str(self.get_id())+'_image_thumbnail', None).absolute_url(1)
return getattr(self.images, 'course_default').absolute_url(1)
def setStatus(self, sttus):
""" set course statuse """
self.staatus=sttus
def setRegStatus(self, regStatus):
""" set registration status """
self.regStatus = regStatus
def getStatus(self):
""" get course status """
if getattr(self, 'staatus', None) is None:
return 0
else:
return self.staatus
def getRegStatus(self):
""" return how students get to course """
return getattr(self, 'regStatus', 0)
security.declareProtected(perm_view, 'search_form_handler')
def search_form_handler(
self,
REQUEST,
cancel=None, # submit buttons
submit=None, #
get_name = None,
get_content= None
):
"""Search form handler."""
if (submit) and ((get_name) or (get_content)):
for s in 'get_name', 'get_content':
REQUEST.set(s, REQUEST[s])
if REQUEST['get_author_name'] == '___anyone___':
uname = str(self.REQUEST.AUTHENTICATED_USER)
if len(self.fle_users.get_user_info(uname).user_courses()) > 0:
REQUEST.set('get_author_name',
self.courses.get_unames_on_my_courses(REQUEST))
else:
REQUEST.set('get_author_name', uname)
else:
REQUEST.set('get_author_name', REQUEST['get_author_name'])
return self.wt_search_results(self, REQUEST)
elif cancel:
REQUEST.RESPONSE.redirect('index_html')
else:
REQUEST.RESPONSE.redirect(REQUEST['HTTP_REFERER'])
security.declareProtected(perm_view,'getCourseCategory')
def getCourseCategory(self):
return self.course_category
security.declarePrivate('setcourseCategory')
def setCourseCategory(self, id):
self.course_category = id
self._p_changed = 1
def get_n_artefacts(self):
""" number of artefacts on a course """
total = 0
for x in self.jamming.objectValues('JamSession'):
total += x.get_n_artefacts()
return total
def total_n_unseen_jams(self,REQUEST):
total = 0
for x in self.jamming.objectValues('JamSession'):
total += x.get_n_unread_artefacts(REQUEST)
return total
def isCourseAlive(self):
""" when was last input, new objects, artefacts? """
#XXX: isCourseAlive ZZZ, this is serious and need a rewrite!
curtime = time.time()
aeg = curtime-86400*30
#XXX: go away!
if self.lastModify() time:
time = tmp
return float(time)
def lastModify_printable(self,REQUEST):
""" returns printable last modification date """
return time.strftime(translate(self,'short_date_format',default="%Y-%m-%d",target=self.giveLanguage(REQUEST)),time.localtime(self.lastModify()))
def lastActive(self):
""" return last visit to course """
last = 0
for x in self.get_all_users():
tmp = self.Statistics.getUserCourseStat(int(self.get_id()), 'lastAccess', x.get_uname())
if tmp > last:
last = tmp
return last
def lastActive_printable(self,REQUEST):
""" return last visit to course """
return time.strftime(translate(self,'short_date_format',default="%Y-%m-%d",target=self.giveLanguage(REQUEST)),time.localtime(self.lastActive()))
security.declareProtected(perm_manage, 'getUniqId')
def getUniqId(self):
""" return uniq id. we take it with us when exporting and put it back when importing
should be random enough to avoid collision
"""
return self.__uniq_id
security.declarePrivate('setUniqId')
def setUniqId(self, uniq_id):
""" set course uniq id. don't change it. method is here only for beauty """
if not uniq_id:
raise 'IVA error:', 'uniq id not passed'
self.__uniq_id = uniq_id
return 1
security.declareProtected(perm_view, 'hasWordmaps')
def hasWordmaps(self):
""" if course has wordmaps """
return getattr(self, 'wordmaps', None)
security.declareProtected(perm_edit, 'createWordmaps')
def createWordmaps(self):
""" create wordmaps """
if not self.hasWordmaps():
import WordMap
wf=WordMap.WordmapFolder()
wf.id="wordmaps"
self._setObject(wf.id, wf)
return self.message_dialog(message='Wordmaps created', action='tootubade_leht')
else:
return self.message_dialog(message='This course already has wordmaps', action='tootubade_leht')
Globals.default__class_init__(Course)
# EOF
iva-0.7.4/CourseContext.py 0000644 0000000 0000000 00000041447 10345616031 0016536 0 ustar viewcvs viewcvs 0000001 0000000 # -*- coding: utf-8
# $Id$
# Copyright 2001, 2002 by IVA Team and contributors
#
# This file is part of IVA.
#
# IVA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# IVA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with IVA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""Contains class CourseContext, which represents one part of a Course."""
__version__ = "$Revision$"[11:-2]
import OFS, Globals
import AccessControl
import re, string, types
from Thread import Thread, EventManager
from common import reload_dtml, add_dtml, intersect_bool, make_action, get_roles
from input_checks import strip_all, render, is_valid_title, \
normal_entry_tags_and_link
from TraversableWrapper import TraversableWrapper, Traversable
from AccessControl import ClassSecurityInfo
from NoteDTML import NoteDTML
from Cruft import Cruft
from TempObjectManager import TempObjectManager
from common import perm_view, perm_edit, perm_manage, perm_add_lo, translate
from Errors import FleError
import Course
# CourseContexts exist inside Courses. Each course has at least one
# context, since contexts in turn can contain Notes that form
# knowledge building threads.
class CourseContext(
EventManager,
TraversableWrapper,
Traversable,
Cruft,
Thread,
NoteDTML,
TempObjectManager,
):
"""Course Context."""
meta_type = 'CourseContext'
security = ClassSecurityInfo()
security.declareObjectPublic()
# Call courses/context_html (This way we avoid copying index_html
# to each instance of CourseContext class.)
security.declareProtected(perm_view, 'index_html')
def index_html(self, REQUEST):
"""index_html page."""
self.update_reader(str(REQUEST.AUTHENTICATED_USER))
self.updateStat(REQUEST, 'visit_knowledgebuilding')
return REQUEST.RESPONSE.redirect('context_html')
#return self.courses.context_html(self, REQUEST)
# @tts_name: id of the global knowledge type set that should
# be copied to this context. If set to '' or None, nothing is
# copied.
def __init__(
self, parent, my_name, description, descr_long, tts_name, author):
"""Construct the course context object."""
Thread.__init__(self, parent)
EventManager.__init__(self)
NoteDTML.__init__(self)
self.__name = strip_all(my_name) # Get rid of possible HTML tags
# Variables description and descr_long are not filtered because
# render_description() and get_long_description() methods do the
# filtering... (Why? To make it slower? At least this way it is
# easier to change tags that are filtered afterwards.)
self.__description = description
self.__author = author
self.__roleplay_in_use = 0
self.__roleplay = {}
self.__roleplay_only = 0
# Adds long course context description.
#
# Why don't we just use self.descr_long ? Is it too simple solution? ;)
# (ik/16.1.2002)
if not descr_long:
descr_long = ' '
self.manage_addDTMLDocument('descr_long', '', descr_long)
# Select the thinking type set to use for this course context.
if tts_name:
h = parent.fle_root().typesets
if not h.is_valid_tts(tts_name):
raise 'FLE Error', 'Non-existing thinking type set to use for Course Context.'
# Store the name, even if it's None
self._tt_set_id = tts_name
security.declarePrivate('manage_afterAdd')
def manage_afterAdd(self, item, container):
"""Set default permissions for different roles."""
from common import roles_student, roles_tutor, roles_teacher
from common import roles_admin
self.manage_permission(perm_manage, roles_admin, 0)
self.manage_permission(perm_edit, roles_teacher+('Owner',), 0)
self.manage_permission(perm_add_lo, roles_student, 0)
# self.manage_permission(perm_view, roles_student, 0)
if self._tt_set_id:
# Make a real copy of the global typeset.
tt_set = getattr(self.typesets, self._tt_set_id)
self._setObject(
self._tt_set_id,
tt_set.make_copy())
TempObjectManager.manage_afterAdd(self, item, container)
security.declareProtected(perm_view, 'get_author')
def get_author(self):
"""Return author name."""
return self.__author
def is_courseContext(self):
""" is course context? """
return 1
security.declareProtected(perm_view, 'may_edit_course_context')
def may_edit_course_context(self, person):
"""Return boolean depending on whether person can edit the course
context or not."""
from AccessControl.PermissionRole import rolesForPermissionOn
return intersect_bool(
get_roles(self,person),
rolesForPermissionOn(perm_edit,self))
security.declareProtected(perm_view, 'get_n_notes')
def get_n_notes(self):
"""Return number of notes in this CourseContext."""
n = 0
for note in self.get_children('Note'):
n += note.get_n_notes()
return n
# This is a stub that is needed, because when a note is published, it
# will call its parent's uncache_notes method. When a new thread is
# started, the call ends up here.
def uncache_notes(self):
pass
security.declareProtected(perm_view, 'get_n_unread_notes')
def get_n_unread_notes(self, uname):
"""Return number of unread notes in this CourseContext for given user."""
n = 0
for note in self.get_children('Note'):
n += note.get_n_unread_notes(uname)
return n
security.declareProtected(perm_view, 'get_printable_name')
# No additional comments.
def get_printable_name(self):
"""Return name of the CourseContext"""
return self.__name
security.declareProtected(perm_view, 'get_possible_follow_ups')
def get_possible_follow_ups(self):
return self.get_thinking_type_thread_start()
security.declareProtected(perm_view, 'get_thinking_type_thread_start')
def get_thinking_type_thread_start(self):
"""Gives list of thinking types that can start a thread."""
tts = self.get_thinking_type_set()
return tts.get_thinking_type_thread_start()
security.declareProtected(perm_view, 'get_thinking_type_set')
def get_thinking_type_set(self):
"""Return ThinkingTypeSet object."""
return self.get_child(self._tt_set_id)
security.declareProtected(perm_view, 'get_thinking_type_set_id')
def get_thinking_type_set_id(self):
"""Return ThinkingTypeSet id."""
return self._tt_set_id
security.declareProtected(perm_view, 'get_name')
# No additional comments.
def get_name(self):
"""Return name."""
return self.__name
security.declareProtected(perm_view, 'get_description')
# No additional comments.
def get_description(self):
"""Return description."""
return self.__description
security.declareProtected(perm_view,'render_description')
def render_description(self):
"""Render description."""
return render(
self.get_description(),
legal_tags=normal_entry_tags_and_link)
security.declareProtected(perm_view, 'get_long_description')
# No additional comments.
def get_long_description(self):
"""Return description."""
return self._getOb('descr_long')()
security.declareProtected(perm_view, 'is_long_description_empty')
def is_long_description_empty(self):
"""Does long description contain only white space?"""
return self.get_long_description().strip() == ''
security.declareProtected(perm_view,'render_long_description')
def render_long_description(self):
"""Render long description."""
return render(
self.get_long_description(),
legal_tags=normal_entry_tags_and_link)
## security.declareProtected(perm_view, 'get_title')
## # No additional comments.
## def get_title(self):
## """Return title."""
## return self.title
security.declareProtected(perm_view, 'get_course_ref')
def get_course_ref(self):
"""Return reference to the course of this CourseContext."""
return self.find_class_obj(Course.Course)
# The following three ugly utility functions are called from dtml files
# to help constructing sensible URLs in Knowledge building.
security.declarePublic('get_url1')
# Called from ui/CourseContext/repr_norm.dtml
def get_url1(self, REQUEST):
"""Return url to the course context object."""
url = REQUEST.URL0
m = re.match("^(.*/courses/.*?/.*?)/.", url)
return m.group(1)
security.declarePublic('get_url2')
# Called from ui/CourseContext/repr_in_course.dtml
# Actual final view: index_html of Course
def get_url2(self, REQUEST, course_context_id):
"""Return url to the course context object."""
url = REQUEST.URL1
return url + "/" + course_context_id
security.declarePublic('get_url3')
# Called from ui/CourseManager/course_context_location_path.dtml
def get_url3(self, REQUEST):
"""Return URL to the course object."""
url = REQUEST.URL0
m = re.match("^(.*/courses/.*?)/", url)
return m.group(1)
security.declarePublic('is_temporary')
def is_temporary(self):
"""This is here to diguise CourseContext objects as Note objects. ;)"""
return 0
security.declareProtected(perm_edit, 'edit_course_context')
def edit_course_context(self,
REQUEST,
my_name = '',
description = '',
description_long = '',
use_roleplay = 0,
show_only_roleplay = '',
delete = '',
cancel = '', # submit buttons
publish = '', #
):
"""Handler for ui/CourseContext/edit_course_context_form.dtml."""
if delete:
# return self.message_dialog2(self, REQUEST,
# title='Title for three',
# message='Are you sure you want to delete %s context' % self.get_name(),
# handler='delete_form_handler',
# option1_value='Delete',
# option1_name='delete',
# option2_value='Cancel',
# option2_name='cancel',
# )
return self.message_dialog2(
self, REQUEST,
title = 'Confirmation',
message = translate(self,'Are you sure you want to delete this course context:',target=self.giveLanguage(REQUEST)) + ' ' + \
self.get_name(),
handler = 'delete_form_handler',
extra_value_name = 'ctx_id',
extra_values = (self.get_id(),),
option1_value = 'Cancel',
option1_name = 'cancel',
option2_value = 'Ok',
option2_name = 'delete'
)
elif publish:
error_fields = []
errors = []
my_name = my_name.strip()
if not is_valid_title(my_name):
error_fields.append(translate(self,'title of context',self.giveLanguage(REQUEST)))
if my_name != self.get_name() and \
my_name in [x[1] for x in self.get_course_context_names()]:
errors.append(translate(self,"Name '%s' taken",target=self.giveLanguage(REQUEST)) % my_name,)
# Variables 'description' and 'description_long' are not checked
# because render_description() and render_long_description()
# methods filter out unwanted HTML tags.
if len(error_fields) > 0 or len(errors) > 0:
msg = ", ".join(errors)
if len(error_fields) > 0:
msg = msg + " " + 'Invalid fields' + \
": '" + "' , '".join(error_fields) + "'"
return self.message_dialog_error(
self, REQUEST,
title='Invalid input',
message=msg,
action=apply(
make_action,
['edit_course_context_form'] +
[(x, eval(x)) for x in
('my_name', 'description', 'description_long')]))
self.__name = my_name
self.__description = description
# Edit long course context description.
description_long_ob = self._getOb('descr_long')
description_long_ob.manage_edit(description_long,
'description_long')
# Set roles for users.
#XXX below line might be useful!?
# self.set_roleplay(publish=1, REQUEST=REQUEST)
# Use roleplay?
self.__roleplay_in_use = use_roleplay
self.__roleplay_only = show_only_roleplay
if use_roleplay:
return REQUEST.RESPONSE.redirect('course_setup_roleplay_form')
else:
return REQUEST.RESPONSE.redirect('index_html')
elif cancel:
return REQUEST.RESPONSE.redirect('index_html')
else:
raise 'FLE error', 'Unknown button'
security.declarePrivate('set_roleplay_use')
def set_roleplay_use(self, in_use):
"""Set whether or not this context uses roleplaying."""
self.__roleplay_in_use = in_use
security.declareProtected(perm_view, 'uses_roleplay_only')
def uses_roleplay_only(self):
""" true and roles only will be displayed """
return self.__roleplay_only
def set_roleplay_only(self, value):
self.__roleplay_only = value
security.declareProtected(perm_view, 'uses_roleplay')
def uses_roleplay(self):
"""Returns whether or not this context uses roleplaying."""
return self.__roleplay_in_use
security.declarePrivate('set_user_role_name')
def set_user_role_name(self, uname, role_name):
"""Set playrole for user given by user's uname."""
self.__roleplay[uname] = role_name
self._p_changed = 1
security.declareProtected(perm_edit, 'set_roleplay')
def set_roleplay(self,cancel='',publish='',REQUEST=None):
"""Sets up roleplaying for this context."""
if publish and REQUEST:
self.__roleplay={}
self.__roleplay_in_use = 1
for (key,val) in REQUEST.items():
if key.startswith('roleplay_'):
self.__roleplay[key[9:]]=val
self._p_changed=1
REQUEST.RESPONSE.redirect('index_html')
security.declareProtected(perm_view, 'get_nickname_with_role_name')
def get_nickname_with_role_name(self, uname):
"""Return role name (if exists) followed by nickname in parentheses.
If roleplay is not used in this CourseContext returns only nickname."""
try:
nickname = self.fle_users.get_user_info(uname).firstAndLast(uname)
except FleError:
nickname = uname
if self.uses_roleplay():
role = self.get_role_played_by_user(uname)
if self.uses_roleplay_only():
return role
return role + ' (' + nickname + ')'
else:
return nickname
security.declareProtected(perm_view, 'get_role_played_by_user')
def get_role_played_by_user(self,uname):
"""Returns the role of the specified user in
this context's roleplay."""
try:
return self.__roleplay[uname]
except AttributeError:
return ""
except KeyError:
return ""
security.declareProtected(perm_edit, 'delete_form_handler')
def delete_form_handler(
self,
REQUEST,
delete='',
cancel='',
):
"""Form handler that is called from message_dialog2."""
if delete:
id_ = self.get_id()
self.parent()._delObject(id_)
return REQUEST.RESPONSE.redirect("../index_html")
# XXX: maybe we need it, I don't know...
#return REQUEST.RESPONSE.redirect(self.state_href_remove_from_list(REQUEST, "../index_html", 'cc_order' + self.parent().get_id(), id_))
else:
return REQUEST.RESPONSE.redirect("index_html")
def touchgraph_data(self):
data=self.write_touchgraph_data(self,"CONTEXT","Note")
set = self.get_thinking_type_set()
for tt in set.get_thinking_types():
data=data+tt.touchgraph_data()
for note in self.objectValues("Note"):
data=data+note.touchgraph_data()
return data
Globals.InitializeClass(CourseContext)
# EOF
iva-0.7.4/CourseManager.py 0000644 0000000 0000000 00000116443 10345616031 0016463 0 ustar viewcvs viewcvs 0000001 0000000 # -*- coding: utf-8
# $Id$
# Copyright 2001, 2002 by IVA Team and contributors
#
# This file is part of IVA.
#
# IVA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# IVA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with IVA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""Contains class CourseManager, which acts as a factory object for Courses and also the container for the courses."""
__version__ = '$Revision$'[11:-2]
import re, string, time
import strptime
import OFS, Globals, AccessControl
from Products.BTreeFolder2.BTreeFolder2 import BTreeFolder2
from Globals import Persistent, PersistentMapping
import types
from Products.ZCatalog.ZCatalog import ZCatalog
# from TraversableWrapper import TraversableWrapper as TW
from TraversableWrapper import Traversable
from Course import Course
from common import new_reload_dtml, reload_dtml, add_dtml, iterate_fle_path, \
quote_html_hack, make_action
from common import perm_view, perm_edit, perm_manage, perm_add_lo, perm_access,\
roles_admin, roles_staff, roles_user, translate
from input_checks import is_valid_title
from Thread import Thread
from AccessControl import ClassSecurityInfo
from Cruft import Cruft
from common import course_level_roles
from common import roles_teacher, roles_tutor, roles_student
import time
class IDManager(Thread):
security = ClassSecurityInfo()
def __init__(self):
self.__id_counter = 0L
# Overrides generate_id from Thread!
security.declarePrivate('generate_id')
def generate_id(self):
"""Return a probably random integer."""
self.__id_counter += 1L
return str(self.__id_counter)
# CourseManager exists in FLE/courses and contains all the courses
# that the FLE installation holds.
class CourseManager(
BTreeFolder2,
Traversable,
Cruft,
Persistent,
AccessControl.Role.RoleManager,
OFS.SimpleItem.Item,
IDManager,
):
"""FLE Coursemanager."""
meta_type = 'CourseManager'
security = ClassSecurityInfo()
security.declareObjectPublic()
# No additional comments.
def __init__(self, id):
"""Construct Course manager object."""
self.id = id
BTreeFolder2.__init__(self, id)
self.title = ''
self.cCategories = PersistentMapping()
self.cCategories['groups'] = {}
IDManager.__init__(self)
for role in course_level_roles:
self._addRole(role)
from common import new_reload_dtml
catalog = ZCatalog('catalog_notes', 'ZCatalog for notes')
# indexes
catalog.addIndex('get_subject', 'TextIndex')
catalog.addIndex('get_body', 'TextIndex')
catalog.addIndex('get_author', 'FieldIndex')
catalog.addIndex('get_tt_id', 'FieldIndex')
# metadata
catalog.addColumn('get_subject')
catalog.addColumn('get_author')
catalog.addColumn('absolute_url')
self._setObject('catalog_notes', catalog)
self._p_changed = 1
# ZCatalog for indexing courses.
catalog = ZCatalog('courses_zcatalog', 'ZCatalog for courses')
# indexes
catalog.addIndex('get_courseID','FieldIndex')
catalog.addIndex('getCourseCategory','FieldIndex')
catalog.addIndex('getStatus','FieldIndex')
catalog.addIndex('getRegStatus','FieldIndex')
catalog.addIndex('get_all_users_id','FieldIndex')
catalog.addIndex('get_end_date','FieldIndex') # XXX: Date index here maybe
catalog.addIndex('get_start_date','FieldIndex') # XXX: haven't tested it yet
catalog.addIndex('get_n_artefacts','FieldIndex') # XXX: after adding artefact
catalog.addIndex('get_n_notes','FieldIndex') # XXX: or note we need to reindex course
catalog.addIndex('get_n_users','FieldIndex')
catalog.addIndex('get_name','FieldIndex')
catalog.addIndex('get_teachers','FieldIndex')
catalog.addIndex('lastActive','FieldIndex') # XXX: should be fetch from somewhere else...
catalog.addIndex('lastModify','FieldIndex') # XXX
catalog.addIndex('meta_type','FieldIndex')
# metadata
catalog.addColumn('getCourseCategory')
catalog.addColumn('getLogoURL')
catalog.addColumn('getStatus')
catalog.addColumn('getRegStatus')
catalog.addColumn('get_all_users_id')
catalog.addColumn('get_courseID')
catalog.addColumn('get_end_date')
catalog.addColumn('get_id')
catalog.addColumn('get_n_artefacts')
catalog.addColumn('get_n_notes')
catalog.addColumn('get_n_users')
catalog.addColumn('get_name')
catalog.addColumn('get_start_date')
catalog.addColumn('get_teachers')
catalog.addColumn('lastActive')
catalog.addColumn('lastModify')
catalog.addColumn('meta_type')
catalog.addColumn('getLogoThumbnailURL')
self._setObject('courses_zcatalog', catalog)
self._p_changed = 1
security.declarePrivate('manage_afterAdd')
def manage_afterAdd(self, item, container):
"""Set default permissions for roles."""
self.manage_permission(perm_access, ('Manager','IVAAdmin','Student','Teacher','Anonymous'), 0)
self.manage_permission(perm_edit, ('Manager','IVAAdmin','Teacher'), 0)
self.manage_permission(perm_view, ('Manager','IVAAdmin','Teacher','Student'), 0)
self.manage_permission(perm_add_lo, ('Manager','IVAAdmin','Teacher'), 0)
try:
self.manage_permission('Zwiki: Add pages', ('Teacher','Owner',), 0)
self.manage_permission('Zwiki: Add wikis', ('Teacher','Owner',), 0)
self.manage_permission('Zwiki: Change page types', ('Teacher','Owner',), 0)
self.manage_permission('Zwiki: Delete pages', ('Teacher','Owner',), 0)
self.manage_permission('Zwiki: Edit pages', ('Teacher','Owner',), 0)
self.manage_permission('Zwiki: Rename pages', ('Teacher','Owner',), 0)
self.manage_permission('Zwiki: Reparent pages', ('Teacher','Owner',), 0)
except ValueError:
# we don't have zwiki around
pass
def get_text(self,elem):
""" olude sunnil ImportExport.py'st kopeeritud """
#XXX: this goes to common.py!
res=u''
for line in elem.childNodes:
res += line.nodeValue
return to_utf8(res)
def hasLogo(self):
return 0
security.declareProtected(perm_add_lo, 'add_course_impl')
def add_course_impl(self, teacher, uniq_id=None):
"""Implementation for add_course."""
if uniq_id is None:
suffix = '_'+str(int(time.time()))
uniq_id = self.generateId(prefix='course',suffix=suffix,rand_ceiling=99999999999)
obj = Course(
self,
'', # name
(teacher,),
'', # desc
'', # organisation
'', # methods
'', # starting_date
'', # ending_date
uniq_id, # uniq_id
)
id = obj.id
self._setObject(id, obj)
return id
security.declareProtected(perm_manage, 'add_course_form_handler')
#security.declareProtected(perm_edit, 'add_course_form_handler')
#security.declarePublic('add_course_form_handler')
# form handler for add_course_form_1_2.dtml
def add_course_form_handler(
self,
REQUEST,
course_id, my_name, desc, organisation, methods,
start_date, end_date,
creating_new_course='',
do_groupfolder='1',
cancel='', # submit buttons
add='', #
tekst='',
logo_upload=None,
staatus=0,
regStatus=0,
cCat = 0,
credits='',
courseID=''
):
"""Check user input data. this is for creating courses only for now."""
# return str(self.REQUEST.AUTHENTICATED_USER.getUserName())
if cancel:
# cancel button press
if creating_new_course:
REQUEST.RESPONSE.redirect('index_html')
else:
REQUEST.RESPONSE.redirect('course_info?course_id=%s' % course_id)
return
elif not add: raise 'FLE Error', 'Unknown button'
if not creating_new_course:
raise 'IVA Error', 'Calling add_course_form_handler without creating_new_course attribute'
# Ok, add button pressed
action=apply(
make_action,
['manage_course_info'] +
[(x, eval(x)) for x in
('my_name', 'desc', 'organisation', 'methods',
'start_date', 'end_date')])
if course_id:
action += '&course_id=' + course_id
else:
action += '&creating_new_course=1'
my_name=my_name.strip()
if not is_valid_title(my_name):
return self.message_dialog_error(
self, REQUEST,
title='Invalid name',
message='Give valid name',
action=action)
if creating_new_course and my_name in [x.get_name
for x in self.get_courses()]:
return self.message_dialog_error(
self, REQUEST,
title='Invalid name',
message="Name '%s' taken" % my_name,
action=action)
if not creating_new_course \
and my_name != self.get_child(course_id).get_name() \
and my_name in [x.get_name() for x in self.get_courses()]:
return self.message_dialog_error(
self, REQUEST,
title='Invalid name',
message="Name '%s' taken" % my_name,
action=action)
from common import convert_date # convert dates to time.time()-format
errors = []
if not start_date:
starting_date = 0
else:
try:
time_tuple = strptime.strptime(start_date,
translate(self,'short_date_format',default="%Y-%m-%d",target=self.giveLanguage(REQUEST)))
starting_date = convert_date(str(time_tuple[2]), # day
str(time_tuple[1]), # month
str(time_tuple[0])) # year
except: errors.append(translate(self,'Starting date:',target=self.giveLanguage(REQUEST)),)
if not end_date:
ending_date = 0
else:
try:
time_tuple = strptime.strptime(end_date,
translate(self,'short_date_format',default="%Y-%m-%d",target=self.giveLanguage(REQUEST)))
ending_date = convert_date(str(time_tuple[2]), # day
str(time_tuple[1]), # month
str(time_tuple[0])) # year
except: errors.append(translate(self,'Ending date:',target=self.giveLanguage(REQUEST)),)
organisation = organisation.strip()
if organisation and not is_valid_title(organisation):
errors.append(translate(self,'Organization',target=self.giveLanguage(REQUEST)))
# desc and methods are not checked because render_description() and
# render_methods() methods in Course filter out unwanted HTML tags.
if len(errors) > 0:
return self.message_dialog_error(
self, REQUEST,
title='Invalid input',
message=translate(self,'Invalid fields',target=self.giveLanguage(REQUEST)) + ": '" + \
"' , '".join(errors) + "'",
action=action)
# edit an existing course
if creating_new_course:
# Create new course, then proceed with updating it with
# supplied data
teacher = ''
course_id = self.add_course_impl(teacher)
#teacher_obj.user_courselist_cache.append(course_id)
logo=None
try: #Opera puhul ajab puuduva pildi juures kägu
if len(logo_upload.filename)>0:
logo=logo_upload.read()
else:
logo=None
except:
pass
course_obj = self.get_child(course_id)
course_obj.update(
my_name,
desc,
organisation,
methods,
starting_date,
ending_date,
tekst,
logo,
staatus,
cCat,
credits,
courseID
)
if creating_new_course:
if do_groupfolder:
course_obj.add_folder('CourseFolder')
else:
if do_groupfolder and not course_obj.has_group_folder():
course_obj.add_folder('CourseFolder')
# elif not do_groupfolder and course_obj.has_group_folder():
# course_obj._delObject('gf')
# REQUEST.RESPONSE.redirect('index_html')
# '%s/course_info?course_id=%s' % (course_id, course_id))
# REQUEST.RESPONSE.redirect(self.find_URL_of_fle_root(REQUEST)+'/courses/'+course_id+'/gf/course_info')
#return course_obj.kysiTekst()
if creating_new_course:
self.change_course(REQUEST, course_id)
REQUEST.RESPONSE.redirect(self.fle_root().absolute_url()+"/courses/manage_participants?pnimi=")
else:
REQUEST.RESPONSE.redirect(course_obj.absolute_url()+'/gf/course_info')
# return "Tere"
#security.declareProtected(perm_edit, 'get_courses')
security.declarePublic('get_courses')
# No additional comments.
def get_courses(self, REQUEST=None, **kw):
#XXX: zcatalog test
"""Return a list of Course objects in this manager."""
doSort = 0
doFilter = 0
try:
doSort = int(REQUEST.get('sortc', 0))
except AttributeError:
pass
try:
if int(REQUEST.filter):
# doSort = 99
doFilter = int(REQUEST.filter)
except AttributeError:
pass
if doSort == 1:
return self.courses_zcatalog(meta_type='Course', sort_on='getCourseCategory')
elif doSort == 99 and doFilter:
return self.courses_zcatalog(meta_type='Course', getCourseCategory=doFilter, sort_on='getCourseCategory')
elif doSort == 10:
return self.courses_zcatalog(meta_type='Course', sort_on='getStatus')
elif doSort == 20:
return self.courses_zcatalog(meta_type='Course', sort_on='get_n_users')
elif doSort == 30:
return self.courses_zcatalog(meta_type='Course', sort_on='lastModify')
elif doSort == 40:
return self.courses_zcatalog(meta_type='Course', sort_on='lastActive')
elif doSort == 50:
return self.courses_zcatalog(meta_type='Course', sort_on='get_n_notes')
elif doSort == 60:
return self.courses_zcatalog(meta_type='Course', sort_on='get_n_artefacts')
elif doFilter:
return self.courses_zcatalog(meta_type='Course', getCourseCategory=doFilter, sort_on='getCourseCategory')
else:
return self.courses_zcatalog(meta_type='Course', sort_on='get_name', **kw)
#return self.courses_zcatalog(meta_type='Course', sort_on='kysiStaatus')
#if doSort: return self.sorted_course_list(doSort,doFilter)
#else: return self.get_children('Course')
security.declareProtected(perm_edit, 'get_user_ids_on_course')
def get_user_ids_on_course(self, course_id):
"""Return UserInfo ids (list) on a given course."""
return self.get_child(course_id).get_all_users_id()
#XXX: FIX: security check
#security.declareProtected(perm_edit, 'get_users_not_on_the_course')
security.declarePublic('get_users_not_on_the_course')
def get_users_not_on_the_course(self, course_id, jarjestus="", omadus="", alates="", kuni=""):
"""Get all users who are not on the given course.
Return list of UserInfo objects."""
print jarjestus, omadus, alates, kuni
aaeg = time.time()
try:
course_obj = self.get_child(course_id)
except AttributeError:
raise 'FLE Error', 'Errorneous course id.'
attendees = course_obj.get_all_users()
if jarjestus=="":
all_users = self.fle_users.get_users()
if jarjestus=="kasutajanimi":
all_users = self.fle_users.get_users_sorted_by_uname()
non_att = []
faaeg = time.time()
for user in all_users:
if user not in attendees:
lisada=1
if omadus!="":
if alates != "":
if user.kysi_omadus(omadus)kuni and (user.kysi_omadus(omadus)[:len(kuni)]!=kuni):
lisada=0
if lisada:
non_att.append(user)
feaeg = time.time()
print "for: ", feaeg-faaeg
eaeg = time.time()
print "get_users_not_on_the_course", eaeg-aaeg
return non_att
#security.declareProtected(perm_edit, 'get_users_not_on_the_course')
# security.declarePublic('get_users_not_on_the_course')
# No additional comments
# def get_users_not_on_the_course(self, course_id):
# """Get all users who are not on the given course.
# Return list of UserInfo objects."""
# try:
# course_obj = self.get_child(course_id)
# except AttributeError:
# raise 'FLE Error', 'Errorneous course id.'
#
# attendees = course_obj.get_all_users()
# all_users = self.fle_users.get_users()
#
# non_att = []
#
# for user in all_users:
# if user not in attendees:
# non_att.append(user)
#
# return non_att
# FIXME: input_checks
#security.declareProtected(perm_view, 'add_users_form_handler')
security.declarePublic('add_users_form_handler')
# handler for form add_course_form_2_2.dtml
def add_users_form_handler(
self, course_id,
REQUEST,
users_None='', # checkboxes
users_Teacher='',
users_Tutor='',
users_Student='',
None_to_Teacher='', # submit buttons
Teacher_to_None='',
None_to_Tutor='',
Tutor_to_None='',
None_to_Student='',
Student_to_None='',
Tutor_to_Teacher='',
Teacher_to_Tutor='',
Student_to_Tutor='',
Tutor_to_Student='',
):
"""Adding and removing users from a given course."""
from Kirjakast import Kirjakast
course = self.get_child(course_id)
if not self.kas_opetaja(REQUEST, course.get_id()) and not REQUEST.AUTHENTICATED_USER.has_role('Manager'):
raise Unauthorized
temp = getattr(self.fle_root(), 'fle_users')
for x in ('None_to_Teacher', # left/right
'Teacher_to_None',
'None_to_Tutor',
'Tutor_to_None',
'None_to_Student',
'Student_to_None',
'Tutor_to_Teacher', # up/down
'Teacher_to_Tutor',
'Student_to_Tutor',
'Tutor_to_Student'):
if eval(x):
m = re.match("^(.*)_to_(.*)", x)
old_role = m.group(1)
new_role = m.group(2)
if 'Student' in new_role and not self.isCourseReady(course):
return self.message_dialog_error(
title="Error",
message="Students can be added to the course when all required course information is submitted and course status is open(not preparing, not finished). Adding teachers is OK.",
action="manage_participants")
users = "users_%s" % old_role
if eval(users):
owners = [u[0] for u in self.get_local_roles()]
if type(eval(users)) is types.StringType:
exec '%s = [%s,]' % (users, users)
# if new_role == 'Teacher':
# for user in eval(users):
# uinf = self.fle_users.get_user_info(user)
# uinf.set_roles(('Teacher',))
# print uinf.getRoles()
if new_role == 'None':
for user in eval(users):
course.remove_person(user)
if course.has_group_folder():
course.remove_folder_link(
(self.fle_users.get_user_info(user),))
else:
for user in eval(users):
if user in owners:
new_roles = (new_role, 'Owner')
else:
new_roles = (new_role,)
#XXX:dublicate user_courselist_cache :(
uinf = self.fle_users.get_user_info(user)
if course.get_id() not in uinf.user_courselist_cache:
uinf.user_courselist_cache.append(course.get_id())
uinf._p_changed = True
course.set_roles(user, new_roles)
try:
koht = getattr(temp, user)
koht2 = getattr(koht, 'kirjad')
tlang = uinf.get_language()
teade=translate(self,'You have been added to course ',target=tlang)
koht2.saadaKiri(REQUEST, uinf.get_uname(), uinf.get_uname(), teade,'\n\n\n'+\
teade+": "+\
str(course.get_name()),9999)
except:
pass
else:
return self.message_dialog_error(
self, REQUEST,
title='Error',
message='Please select some users first',
action='manage_participants')
course.reindex_object()
REQUEST.RESPONSE.redirect('manage_participants')
#'add_course_form_2_2?course_id=' + course_id))
return
# Should be never reached.
return REQUEST
security.declareProtected(perm_manage, 'courses_form_handler')
# index_html form handler
#XXX: security check!
def courses_form_handler(
self,
REQUEST,
delete='', # form submit button
course_export='',
course_ids=None,
):
"""Form handler for courses index page."""
import types
if int(self.kas_opetaja(REQUEST))!=1:
if not self.fle_root().fle_users.is_power_user(REQUEST.AUTHENTICATED_USER):
return "Access denied"
if not course_ids:
return self.message_dialog_error(
self, REQUEST,
title='No course selected',
message='Please select a course from the course list.',
action='index_html')
if delete:
if type(course_ids) is types.StringType:
course_ids=(course_ids,)
return self.message_dialog2(
self, REQUEST,
title = 'Confirmation',
message = translate(self, 'Are you sure you want to delete the following courses:', target=self.giveLanguage(REQUEST)) + ' ' + \
', '.join([getattr(self, ci).get_name() for ci in course_ids]),
handler = 'delete_courses_form_handler',
extra_value_name = 'course_ids',
extra_values = course_ids,
option1_value = 'Cancel',
option1_name = 'cancel',
option2_value = 'Ok',
option2_name = 'delete')
#REQUEST.RESPONSE.redirect('index_html')
elif course_export:
if type(course_ids) is types.StringType:
course_ids=(course_ids,)
message = self.do_courses_export(course_ids)
message = translate(self,'Exported course(s) are save to following location:',target=self.giveLanguage(REQUEST))+message
return self.index_html(message=message)
else:
# This code should never be reached.
raise 'FLE Error', 'Unknown button'
security.declarePrivate('do_courses_export')
# index_html form handler
def do_courses_export(self,course_ids):
message = ""
for c_id in course_ids:
course = self.get_child(c_id)
message += ' ' + course.iva_ims_export(teacherExporting=0)
get_transaction().commit()
return message
# FIXME: input_checks
security.declareProtected(perm_manage, 'delete_courses_form_handler')
def delete_courses_form_handler(
self,
REQUEST,
course_ids,
delete='',
cancel='',
):
"""Form handler that is called from message_dialog2."""
if delete:
for course_id in course_ids:
for wt in [user.get_webtop() for user in
self.get_child(course_id).get_all_users()]:
wt.recursive_delete_group_folder_proxy(course_id)
[self.get_child(course_id).remove_person(user.get_uname()) for user in self.get_child(course_id).get_all_users()]
self._delObject(course_id)
elif cancel:
pass
else:
# This code should never be reached.
raise 'FLE Error', 'Unknown button'
REQUEST.RESPONSE.redirect('index_html')
security.declarePublic('has_courses')
def has_courses(self):
"""Return boolean describing whether there is an existing course on
the system."""
return not not self.get_children('Course')
def get_course_id_from_req(self, req):
"""Extract a course id from REQUEST. This is needed by
the CourseManager.course_selection dtml method."""
path = req.PATH_TRANSLATED
splitter = '/'
if splitter not in path:
splitter = '\\'
i = string.find(path, "courses")
ri = string.rfind(path, "courses")
if (i == -1) or (ri == -1):
return None
if (ri != i):
# There is more than one 'courses' word in path.
# We'll have to use the reverse one.
i = ri
plst = filter(lambda x:x, string.split(path[i:], splitter))
try:
return plst[1]
except IndexError:
return None
def get_formatted_current_date(self, REQUEST):
"""Return date formatted depending on user's language."""
return time.strftime(translate(self,'short_date_format',default="%Y-%m-%d",target=self.giveLanguage(REQUEST)), time.localtime())
def get_printable_starting_date(self, REQUEST):
""" return current time, no starting time for coursemanager """
return self.get_formatted_current_date(REQUEST)
def get_printable_ending_date(self, REQUEST):
""" return current time, no ending time fot coursemanaget.
this is here for course adding page """
return self.get_formatted_current_date(REQUEST)
def testideImport(self,REQUEST):
""" impordime testid"""
tulemus=""
return self.defaultRender(page=tulemus)
# security.declareProtected(perm_view, 'user_course_export')
security.declarePublic('user_course_export')
def user_course_export(self,REQUEST):
""" user exports its course for viewing offline """
from ImportExportIMS import Kirjutus
from ImportExportIMS import kirjutaYldM
import tempfile, os
uname = REQUEST.AUTHENTICATED_USER.getUserName()
knr=self.fle_root().jooksva_kursuse_nr(self, REQUEST)
# knr=self.fle_root().jooksva_kursuse_nr(self, REQUEST)
knr = self.get_course_id_from_req(REQUEST)
kasutaja = self.fle_users.get_user_info(uname)
kasutaja = ((kasutaja),)
failinimi = tempfile.mktemp()
kursus = self.get_child(knr)
k = Kirjutus(self.fle_root(), kursus.get_id())
k.looKursuseFail()
k.kirjutaWebtop(kursus.gf, tiitel='RAAMATURIIUL')
k.kirjutavCal(kursus.syndmused, 'kursus','GROUP')
k.kirjutaKasutajaWebtop(kasutaja)
k.kirjutaKasutajaSyndmus(kasutaja)
# k.kirjutaWiki(getattr(kursus,'ivawiki'))
for sisegr in kursus.subgroups.objectValues('GroupFolder'):
sisegr_kasutajad = kursus.kasutajad_sisegrupis(sisegr.get_name())
if uname not in sisegr_kasutajad:
continue
k.kirjutaWebtop(sisegr,'SISEGRUPP')
try:
k.kirjutavCal(sisegr.syndmused,sisegr.get_name(),'GROUP')
except:
pass
k.kirjutaKasutajaWiki(kasutaja)
k.exportPajad(failinimi, str(kursus.get_name()+"/"))
k.pakiKursusFaili(failinimi,str(kursus.get_name()))
file = open(failinimi, "rb")
export_data=file.read()
file.close()
os.remove(failinimi)
REQUEST.RESPONSE.setHeader('content-type','application/zip')
REQUEST.RESPONSE.setHeader('Content-disposition','attachment; filename=iva_arhiiv.zip')
return export_data
security.declareProtected(perm_manage, 'export_all_courses')
def export_all_courses(self,REQUEST,allcourses=''):
""" exports all courses """
#XXX: def export_all_courses: not needed. we should get rid of it!
from ImportExportIMS import Kirjutus
from ImportExportIMS import kirjutaYldM
import tempfile, os
yld = kirjutaYldM()
failinimi = tempfile.mktemp()
if not allcourses:
for course in self.get_courses():
k = Kirjutus(self.fle_root(), course.get_id())
k.looKursuseFail()
k.kirjutaWebtop(course.gf, tiitel='RAAMATURIIUL')
k.kirjutavCal(course.syndmused,'kursus','GROUP')
for sisegr in course.subgroups.objectValues('GroupFolder'):
k.kirjutaWebtop(sisegr,'SISEGRUPP')
try:
k.kirjutavCal(sisegr.syndmused,sisegr.get_name(),'GROUP')
except:
pass
k.kirjutaWebtop(course.ryhmalauad,'RYHMALAUAD')
k.kirjutaKasutajaWebtop(course.get_all_users())
k.kirjutaKasutajaSyndmus(course.get_all_users())
k.exportQTI(failinimi,str(course.get_id())+"/")
#k.kirjutaWiki(getattr(course,'ivawiki'))
#k.kirjutaKasutajaWiki(course.get_all_users())
yld.kirjutaYldmanifest(course.get_id(),course.get_description(),base=str(course.get_id())+"/")
#k.pakiTulemusFaili(failinimi)
self.fle_users.export_users(REQUEST,failinimi=failinimi,kursusega=course.get_id(),palju='self.fle_root().fle_users.get_users()')
k.kirjutaItem(k.organization, tiitel='KURSUSE KASUTAJAD')
k.kirjutaResource(k.resources, 'imsent_xmlv1p1','users.xml')
k.pakiKursusFaili(failinimi)
yld.lisaFaili(failinimi)
file = open(failinimi,"rb")
export_data=file.read()
file.close()
os.remove(failinimi)
REQUEST.RESPONSE.setHeader('Content-disposition','attachment; filename=ivaexport.zip')
REQUEST.RESPONSE.setHeader('content-type','application/zip')
return export_data
def import_form_handler(
self,
REQUEST,
file,
course_import='',
testsonly='',
wikionly='',
cancel='',
wiki_koht='',
):
"""Form handler for course importing."""
uname = REQUEST.AUTHENTICATED_USER.getUserName()
koht=wiki_koht[len(self.fle_root().absolute_url()):].split('/')
m = self.fle_root()
for x in koht:
if x:
m = getattr(m, x)
koht = m
# if not self.kas_opetaja(self, REQUEST):
# return "Keelatud juurdep22s"
if course_import:
from ImportExportIMS import Importer
from ImportExport import Exporter
import tempfile, os
filename = tempfile.mktemp()
f = open(filename,"w+b")
f.write(file.read())
f.close()
import_data=None
#exported = Exporter("Courses",filename)
if testsonly or wikionly:
# print u_wiki
if testsonly:
print "test ainult1"
imported = Importer(uname,self.fle_root(),'',getattr(self.fle_root().courses, self.get_course_id_from_req(REQUEST)),testonly=1,kasuta_jooksvat=1)
else:
print "test ainult2"
imported = Importer(uname,self.fle_root(),'',getattr(self.fle_root().courses, self.get_course_id_from_req(REQUEST)),userwikionly=koht)
else:
print "test ainult3"
imported = Importer(uname,self.fle_root())
imported.loadZip(filename)
element = imported.loadFile('imsmanifest.xml')
imported.processFile(self,element)
kala = "Import Course imported"
if wiki_koht:
REQUEST.RESPONSE.redirect(wiki_koht)
os.remove(filename)
return
if testsonly:
REQUEST.RESPONSE.redirect('testihaldus')
else:
REQUEST.RESPONSE.redirect('haldusleht')
os.remove(filename)
return
security.declareProtected(perm_manage,'import_form_handler2')
def import_form_handler2(self,REQUEST,zip='',importB=''):
""" imports from zip, located at zope instance's import folder """
if not importB:
return "x"
if not zip:
return "y"
uname = str(REQUEST.AUTHENTICATED_USER)
if importB:
from ImportExportIMS import Importer
from ImportExport import Exporter
import os, time
insthome = Globals.INSTANCE_HOME
oaeg_alg = time.time()
for names in zip:
zip_alg = time.time()
try:
path = os.path.join(insthome,'import')
filename = os.path.join(path,names)
except OSError:
return "z"
print filename
imported = Importer(uname,self.fle_root())
imported.loadZip(filename)
element = imported.loadFile('imsmanifest.xml')
imported.processFile(self,element)
zip_lopp = time.time()
print "Zip:",zip_lopp-zip_alg
get_transaction().commit()
oaeg_lopp = time.time()
print "Overall:", oaeg_lopp-oaeg_alg
return self.index_html(message="File(s) successfully imported.")
# return REQUEST.RESPONSE.redirect(self.fle_root().absolute_url()+'/courses/')
def coursesOpenToRegister(self, knimi):
""" Kursuste loetelu, kus kasutaja veel pole """
cm=self.get_courses(getRegStatus=['1','2'])
loetelu=[]
for c in cm:
leidub=0
rm=c.getObject().get_local_roles()
for r in rm:
if str(knimi)==r[0]:
leidub=1
if c.getObject().kasOotaja(knimi):
leidub=1
if not leidub:# and ((c.getStatus=='1') or (c.getObject().getStatus()=='4')):
loetelu.append(c)
return loetelu
#security.declareProtected(, 'kursusteleRegistreerimiseLeht')
def kursusteleRegistreerimiseLeht(self, REQUEST,kursus=()):
"Kasutajate lisamine ootele"
import types
if type(kursus)==types.StringType:
kursus=(kursus,)
for x in kursus:
getattr(self, x).lisaOotaja(REQUEST, str(REQUEST.AUTHENTICATED_USER))
return REQUEST.RESPONSE.redirect('organizer_openCourses')
def getStatuses(self):
""" return course statuses """
return range(3)
def getPrintableStatus(self, nr):
""" return printable course status """
statuses = ['Preparation', 'Active', 'Finished']
if int(nr)>2: return 'Invalid status'
return statuses[int(nr)]
def getRegStatuses(self):
""" return course registration status """
return range(3)
def getPrintableRegStatus(self, nr):
""" return printable registration status """
statuses = ['by teacher', 'with teacher\'s permission', 'automatically']
return statuses[int(nr)]
security.declareProtected(perm_view, 'get_unames_on_my_courses')
def get_unames_on_my_courses(self, REQUEST):
"""Return a list of unames (users that are on some course
than the caller."""
uname = str(REQUEST.AUTHENTICATED_USER)
uname_list = []
for course in self.get_courses():
unames_in_course = course.get_all_users_id()
if uname in unames_in_course:
uname_list += unames_in_course
retval = []
for uname in uname_list:
if uname not in retval:
retval.append(uname)
return retval
security.declareProtected(perm_manage, 'giveCategories')
def giveCategories(self):
#XXX: not needed!?
return self.cCategories.keys()
# security.declareProtected(perm_view,'getAllCategories')
def getAllCategories(self):
return self.cCategories['groups'].keys()
def getACat(self,id):
try:
return self.cCategories['relations'][str(id)]
except KeyError:
return None
# security.declareProtected(perm_view, 'treePrinter')
def treePrinter(self):
""" tree printer """
result = []
init = self.getCatForCat()
for x in init:
tmp = []
tmp.append('')
tmp.append(x)
result.append(tmp)
self.treeSlave(x,'-',result)
return result
# teachers are getting errors...
# security.declareProtected(perm_view,'getNameForID')
def getNameForID(self, id):
try:
int_id = int(id)
except ValueError:
int_id = 0
if id is not None and int_id != 0:
try:
return self.cCategories['groups'][int(id)]['Name']
except KeyError:
return "deleted..."
else:
return ""
def getParentForID(self, id):
try:
return self.cCategories['groups'][id]['Parent']
except KeyError:
return ''
security.declarePrivate('addcCategory')
def addcCategory(self, newcat, undercat):
from random import random
id = int(round(random()*1000000000))
self.cCategories['groups'][id] = {'Name':newcat, 'Parent':undercat}
self.cCategories._p_changed = 1
security.declarePrivate('renameCategory')
def renameCategory(self, id, newname):
self.cCategories['groups'][int(id)]['Name'] = newname
self.cCategories._p_changed = 1
security.declarePrivate('removeCategory')
def removeCategory(self, id):
self.cCategories['groups'].pop(int(id))
self.cCategories._p_changed=1
security.declarePrivate('treeSlave')
def treeSlave(self,cat, sep,result):
for x in self.getCatForCat(cat):
tmp = []
tmp.append(sep)
tmp.append(x)
result.append(tmp)
self.treeSlave(x,sep+'-',result)
return result
def getCatForCat(self,parent=''):
#pass
cats = []
if parent == '': parent = 'None'
else: parent = str(parent)
for x in self.cCategories['groups'].keys():
if self.cCategories['groups'][x]['Parent'] == parent:
cats.append(x)
return cats
security.declareProtected(perm_manage,'manageCategories_handler')
def manageCategories_handler(self, REQUEST, saveB='', deleteB='', deletec='', newCat='', underCat='', renameB='', renaming='', newname=''):
""" creates or deletes course category """
if saveB:
if not underCat:
underCat = 'None'
if newCat:
self.addcCategory(newCat, underCat)
if deleteB:
if type(deletec)==types.StringType: deletec=(deletec,)
for dc in deletec:
self.removeCategory(dc)
if renameB and newname and renaming:
self.renameCategory(renaming, newname)
return REQUEST.RESPONSE.redirect(self.absolute_url()+'/manageCategories')
self.cCategories = PersistentMapping()
self.cCategories['groups'] = {}
# self.cCategories['relations'] = {}
self.cCategories._p_changed = 1
def isCourseReady(self,course=None):
""" if all course fields are filled """
if not course: return 0
#if not int(course.getStatus()) or int(course.getStatus()==3): return 0
if not course.get_name() or not course.get_organisation() or not course.get_description() or not course.get_methods() or not course.get_start_date() or not course.get_end_date(): return 0
return 1
security.declareProtected(perm_manage,'ziplist')
def ziplist(self):
""" returns a list of importable zip-s """
import os
insthome = Globals.INSTANCE_HOME
try:
impath = os.path.join(insthome,'import')
except OSError:
return "no import folder found at %s" % insthome
files = []
for x in os.listdir(impath):
if x[-4:].lower() == '.zip':files.append(x)
return files
def change_course(self, REQUEST, course_nr):
""" change course """
if not course_nr:
return
user = self.fle_users.get_user_info(str(REQUEST.AUTHENTICATED_USER))
res = user.set_jooksev_kursus(course_nr, user.get_uname())
try:
c = self.get_child(course_nr)
except KeyError:
return
if not res:
return
wt = getattr(user, 'webtop', None)
if wt is None:
return
cw = getattr(wt, 'c'+course_nr, None)
folder = None
if cw is None:
#wt.lisa_kursuse_kaust(REQUEST, 'c'+course_nr)
folder = wt.add_folder('c'+course_nr, 'c'+course_nr)
folder.set_author(str(REQUEST.AUTHENTICATED_USER))
else:
folder = cw
user.check_portfolios(folder, c)
self.updateStat(REQUEST, 'numTimesEntered', int(course_nr))
self.registerVisit(REQUEST, course_nr, 'Organizer')
return REQUEST.RESPONSE.redirect(c.absolute_url()+'/course_index')
Globals.InitializeClass(CourseManager)
# EOF
iva-0.7.4/Cruft.py 0000644 0000000 0000000 00000051202 10345616031 0015002 0 ustar viewcvs viewcvs 0000001 0000000 # -*- coding: utf-8
# $Id$
#
# Copyright 2001, 2002 by IVA Team and contributors
#
# This file is part of IVA.
#
# IVA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# IVA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with IVA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""Contains class Cruft, which is used as a placeholder for miscellaneous utility functions that many objects need."""
__version__ = "$Revision$"[11:-2]
from AccessControl import ClassSecurityInfo
from urllib import quote
from common import perm_view, perm_edit, perm_manage, perm_add_lo, translate
import re
import common
import time
from common import get_local_roles
import string
from DateTime import DateTime
import calendar
calendar.setfirstweekday(0)
from Errors import FleError
class Cruft:
"""Class containing miscellaneous methods that are
historical baggage, but possible be gotten rid of, or
at least implemented differently or somewhere else."""
security = ClassSecurityInfo()
security.declarePublic('find_URL_of_fle_root')
def find_URL_of_fle_root(self, REQUEST):
"""Return URL of our FLE installation."""
import FLE
from string import rfind
url = REQUEST.URL1
obj = self
while not isinstance(obj, FLE.FLE):
obj = obj.parent()
url = url[:rfind(url,'/')]
return url
def find_URL_of_user_info(self, REQUEST):
"""Return URL of UserInfo."""
import UserInfo
from string import rfind
url = REQUEST.URL1
obj = self
while not isinstance(obj, UserInfo.UserInfo):
obj = obj.parent()
url = url[:rfind(url,'/')]
return url
security.declarePublic('find_URL_of_webtop')
def find_URL_of_webtop(self, REQUEST):
"""Return URL of Webtop."""
import Webtop
from string import rfind
url = REQUEST.URL1
obj = self
while not isinstance(obj, Webtop.Webtop):
obj = obj.parent()
url = url[:rfind(url,'/')]
return url
security.declarePublic('find_URL_of_group_folder')
def find_URL_of_group_folder(self, REQUEST):
"""Return URL of toplevel group folder or group folder proxy."""
import GroupFolder
import GroupFolderProxy
from string import rfind
url = REQUEST.URL1
obj = self
while 1:
if isinstance(obj, GroupFolderProxy.GroupFolderProxy):
return url
if isinstance(obj, GroupFolder.GroupFolder):
return url
obj = obj.parent()
url = url[:rfind(url,'/')]
return url
security.declarePublic('find_URL_of_thread_start_node')
def find_URL_of_thread_start_node(self, REQUEST):
"""Return URL of starting note."""
import CourseContext
from string import rfind
url = REQUEST.URL1
obj = self
while not isinstance(obj.parent(), CourseContext.CourseContext):
obj = obj.parent()
url = url[:rfind(url,'/')]
return url
security.declarePublic('find_URL_of_course')
def find_URL_of_course(self, REQUEST):
"""Return URL of starting note."""
obj = self
while not obj.meta_type == 'Course':
obj = obj.parent()
return obj.absolute_url()
security.declarePublic('find_URL_of_course_context')
def find_URL_of_course_context(self, REQUEST):
"""Return URL of starting note."""
import CourseContext
from string import rfind
url = REQUEST.URL1
obj = self
while not isinstance(obj, CourseContext.CourseContext):
obj = obj.parent()
url = url[:rfind(url,'/')]
return url
security.declarePublic('is_student')
def is_student(self, REQUEST,nr=None, uname=''):
""" is give user is student in given course """
splitter = '/'
if splitter not in REQUEST.PATH_TRANSLATED:
splitter = '\\'
if nr is None:
nr = self.jooksva_kursuse_nr(REQUEST,uname)
ic = string.rfind(REQUEST.PATH_TRANSLATED, 'fle_users')
url = REQUEST.PATH_TRANSLATED
if ic == -1:
nr = self.fle_root().courses.get_course_id_from_req(REQUEST)
else:
i = ic
plst = filter(lambda x:x, string.split(url[i:], splitter))
nr = plst[3][1:]
if not hasattr(self.fle_root().courses, str(nr)):
return 0
checkname = str(REQUEST.AUTHENTICATED_USER)
if 'Student' in get_local_roles(getattr(self.fle_root().courses, nr),checkname):
return 1
try:
fm = getattr(self.fle_root().fle_users, checkname)
if fm.has_any_role(('IVAAdmin','Manager')):
return 1
except:
return 0
return 0
security.declarePublic('kas_opetaja')
def kas_opetaja(self,REQUEST,nr=None,uname=''):
""" If user is teacher. Additional role checks """
if nr is None:
nr = self.jooksva_kursuse_nr(REQUEST,uname)
if not hasattr(self.fle_root().courses, str(nr)):
return 0
if uname:
pass
#checkname = uname
else:
pass
checkname = str(REQUEST.AUTHENTICATED_USER)
if checkname in getattr(self.fle_root().courses, nr).get_teachers():
return 1
#try:
#XXX: Should we put try except here?
if 1==1:
fm = getattr(self.fle_root().fle_users, checkname)
#XXX: this sucks?
if fm.has_any_role(('IVAAdmin','Manager')):
return 1
return 0
security.declarePublic('jooksva_kursuse_nimi')
def jooksva_kursuse_nimi(self,REQUEST,uname=''):
""" jooksva kursuse nimi """
nr = self.jooksva_kursuse_nr(REQUEST,uname)
try:
return str(getattr(self.fle_root().courses, nr).get_name())
except:
return translate(self,"course not selected", target=self.giveLanguage(REQUEST))
security.declarePublic('jooksva_kursuse_nr')
def jooksva_kursuse_nr(self,REQUEST,uname=''):
""" jooksva kursuse number """;
try:
if uname:
return str(getattr(self.fle_root().fle_users, uname).get_jooksev_kursus())
else:
return str(getattr(self.fle_root().fle_users, self.get_current_user(REQUEST)).get_jooksev_kursus())
except:
return 0
security.declarePublic('get_current_user')
def get_current_user(self, REQUEST):
"""Extract current user's name from the REQUEST object."""
return str(REQUEST.AUTHENTICATED_USER)
security.declarePublic('urlquote')
def urlquote(self, text):
"""urlquote given text."""
return quote(text)
def get_url_to_object(self,obj):
# Make a list of parents without the Application object
# (from obj to FLE)
return obj.absolute_url()+'/'
#objs = obj.aq_inner.aq_chain[:-1]
#objs.reverse()
#path='/'.join([x.getId() for x in objs])+'/'
#return path
def get_object_of_url(self,url,base,remove_last=1):
#XXX: broken for VirtualHostMonster!
path=url.split('/')
if remove_last:
path.pop() # remove last entry
path.reverse()
if path[-1]=='http:': # remove protocol
path.pop()
path.pop()
path.pop() # remove first (root) entry
obj = base.fle_root()
#obj = base.getPhysicalRoot()
try:
while path:
oname=path.pop()
obj=getattr(obj,oname).__of__(obj)
return obj
except:
#raise 'Internal link error, object not found',str(obj)+' - '+oname
return None
def kasutajaURList(self, REQUEST):
"Kasutajanimi"
nimi=self.kasutajaNimi(REQUEST)
if nimi=="":
return nimi
if nimi==str(REQUEST.AUTHENTICATED_USER):
return ""
return "> " + ""+nimi+""
def algusURList(self, REQUEST, osa):
"URL soovitud loiguni"
x=REQUEST.URL0
if x.find(osa)==-1:
return ""
return x[:x.find(osa)+len(osa)]
def kasLopeb(self, tekst, otsitav):
"jah/ei"
# return tekst+" ja " + otsitav
return tekst.endswith(otsitav)
def myOwnWebtop(self, REQUEST):
"jah/ei"
return self.kasutajaNimi(REQUEST)==str(REQUEST.AUTHENTICATED_USER)
def kasutajaNimi(self, REQUEST):
"nimi"
aadress=REQUEST.URL0
nr=aadress.find('fle_users')
if nr==-1:
return ""
ots=aadress.find('/', nr+10)
nimi=aadress[nr+10:ots]
nimi = re.sub('%20', ' ',nimi)
return nimi
def ajaMuutmisElemendid(self, elemendinimi, aeg=-1):
"Valikute kogum"
import YlTest
from YlTest import LahendusLuba
from types import StringType
abi=LahendusLuba()
if type(aeg)==StringType: aeg=float(aeg)
if aeg==-1:aeg=time.time()
m=time.localtime(aeg)
tulemus=abi.looValik(elemendinimi+"Aasta", m[0]-5, m[0]+10, m[0])
tulemus=tulemus+"-"+\
abi.looValik(elemendinimi+"Kuu", 1, 12, m[1])
tulemus=tulemus+"-"+\
abi.looValik(elemendinimi+"Paev", 1, 31, m[2])
tulemus=tulemus+" "+\
abi.looValik(elemendinimi+"Tund", 0, 23, m[3])
tulemus=tulemus+":"+\
abi.looValik(elemendinimi+"Minut", 0, 59, m[4], samm=5)
return tulemus
def set_undefined_page(self, message, REQUEST):
"""Set REQUEST.RESPONSE.redirect, so that we go to undefined page
and give an explanation."""
message = common.quote_html_hack(message)
REQUEST.RESPONSE.redirect("undefined_page?explanation=%s" % message)
security.declarePublic('to_str_list')
# Using eval would be simpler and more general, but
# we want to be paranoid.
def to_str_list(self, s):
"""Reverse str representation of list of strings back to list."""
return [x.strip() for x in s[1:-1].replace("'", "").split(',')]
def kasutajaasukoht(self, REQUEST,url=''):
"Kasutaja asukoht"
if url:
x = url
else:
x = REQUEST.URL0
if x.find('manage_')>0: return "Management"
if x.find('WelCome')>0: return "Bookshelf" #Course ZWiki
if x.find('assignmentGrading')>0: return "Webtop"
if x.find('createMail')>0 or x.find('edit_user_form')>0 or x.find('show_user_info')>0: return 'Organizer'
if x.find('kalendriAasta')>0 or x.find('organizer')>0 or x.find('logout')>0: return 'Organizer'
if x.find('course_info_user')>0: return "Webtop"
if x.find('course_index')>0 or x.find('course_info')>0: return 'Bookshelf'
if x.find('tootubade_leht')>0 or x.find('workshop_')>0: return "Workshops"
if x.find('/courses/')>0:
if x.find('/testihaldus')>0 or x.find('/courses/index_html')>0 or self.kas_haldus(REQUEST,x): return "Management"
if not x.find('/gf/')>0 and x.find('/testid/')>0: return "Management"
if x.find('import_form_handler2')>0: return "Management"
if not x.find('/gf/')>0: return "Workshops"
if x.find('/fle_users/')>0 and x.find('/webtop/')>0: return "Webtop"
if self.kas_haldus(REQUEST, x) or x.find('ootajateLoetelu')>0:
return 'Management'
else:
return 'Bookshelf'
def sisegrupiNimi(self, REQUEST):
"URList loetud grupi nimi"
#XXX: remove
x=REQUEST.URL0
if x.find('/subgroups/')>0:
algus=x.find('/subgroups/')
ots=x.find('/', algus+11)
if ots==-1:
tulemus=x[algus+11:]
else:
tulemus=x[algus+11:ots]
if tulemus == 'wt_index_html':
return "listing"
return tulemus
else:
return ""
security.declarePublic('kas_haldus')
def kas_haldus(self, REQUEST, veebiurl):
"kas sobib halduseks"
if re.match(".*/courses/[0-9]+/syndmused", veebiurl):
if self.kas_opetaja(self, REQUEST): return 1
else: return 0
laused=(
".*haldusleht",
".*testihaldus",
".*muuda_vorm",
".*kysimuse_vorm",
".*add_course_form",
".*sisegrupihaldus",
".*courses/index_html",
".*ylesandedMuutmisTabelina",
".*ylesanneteTyypideLoetelu",
".*pealkirjaMuutmisVormHTML",
".*muutmisVorm",
".*lubadeViited",
".*koigiLuba",
".*isikuLubadeLisamisVorm",
".*grupiLubadeLisamisVorm",
".*/filtreerimisvorm2",
".*/kasutajateTulemused",
".*/typesets",
".*/lahendusteStatistika",
".*/kodutood.*",
".*/manage_.*",
".*qtCatalog.*",
".*testideImport.*",
#".*",
)
leitud=0
x=veebiurl
for lause in laused:
if re.match(lause, x):
leitud=1
return leitud
security.declarePublic('kas_kasutaja_haldus')
def kas_kasutaja_haldus(self, veebiurl):
"kas sobib halduseks"
laused=(
".*kasutajate_haldamise_vorm",
".*kasutajateLisamisFailiVorm",
".*kasutajaLehelt1",
".*kasutajadFailist2",
".*kasutajadFailist1",
".*erialadeHalduseVorm",
".*/kasutajaotsing",
".*/kasutajateKustutus.*",
#".*",
)
leitud=0
x=veebiurl
for lause in laused:
if re.match(lause, x):
leitud=1
return leitud
security.declareProtected(perm_view, 'search_users') #XXX: is tthis right?
def search_users(self, first_name='', last_name='', uname='', organization='', exclude=[], sort_on='get_last_name'):
""" search users from zcatalog. exclude - excludes usernames, must be a list of username """
if organization == '-1': organization=''
elif not organization: organization=''
else: organization = self.fle_users.getAffiliation(int(organization))
query = {
'get_first_name':first_name,
'get_last_name':last_name,
'get_uname':uname,
'get_organization':organization,
}
print organization.decode('utf-8').encode('iso-8859-1')
print query, organization, query['get_organization']
results = self.fle_users.userinfo_zcatalog(query)
for x in results:
print x.get_organization
tmp = []
if exclude:
for x in results:
if x.get_uname in exclude:
continue
tmp.append(x)
#for y in exclude:
# if x.get_uname not in y:
# tmp.append(x)
# break
#else:
# tmp.append(x)
else:
tmp = results
return tmp
def zwiki_export(self,REQUEST,level,wiki_id):
""" zwiki manage form handler """
from ImportExportIMS import Kirjutus
from ImportExportIMS import kirjutaYldM
import tempfile, os
failinimi = tempfile.mktemp()
if not level: level=99999
# number = self.get_course_id_from_req(REQUEST)
number = 0
# nr = self.get_id()
# try:
# number = int(nr)
# except:
# number = int(nr[1:])
yld = kirjutaYldM()
yld.kirjutaYldmanifest(number,'WIKI',base=str(number)+'/')
yld.lisaFaili(failinimi)
k = Kirjutus(self.fle_root(), number)
k.looKursuseFail(0)
wikikoht=''
try:
wikikoht = getattr(self,wiki_id)
except:
pass
if wikikoht:
k.kirjutaWiki(wikikoht,'ZWiki',wikikoht.aq_inner.get_name(),wikikoht.wikiKaustEsimeneLeht(),palju=level)
# else:
# k.kirjutaKasutajaWiki((self.get_user_info(str(REQUEST.AUTHENTICATED_USER)),))
k.pakiKursusFaili(failinimi)
file = open(failinimi,"rb")
export_data=file.read()
file.close()
os.remove(failinimi)
REQUEST.RESPONSE.setHeader('Content-disposition','attachment; filename=zwikiexport.zip')
REQUEST.RESPONSE.setHeader('content-type','application/zip')
return export_data
security.declareProtected(perm_view, 'saadaEmail')
def saadaEmail(self,tomail,subject,message,saatja=''):
""" proovime saata kirja """
p_saatja = ''
if saatja:
p_saatja = saatja
if hasattr(self,'MFROM') and not p_saatja:
p_saatja = self.MFROM
if not p_saatja:
return 0
try:
mailhost = self.MailHost
message = "Content-Type:text/plain; charset=utf-8\n\n\n"+message
#message = message+"\n\n\nThis message was sent to you in IVA and it was forwared to your email as you requested."
print "message", message
mailhost.send(message,tomail,p_saatja,subject,encode='quoted-printable')
return 1
except:
return 0
def leivaPuru(self,REQUEST):
""" leivapuru """
#XXX:maybe we don't need this!
if REQUEST.URL0.find('kirjad')>0: return REQUEST['L_ic_mailbox']
if self.kasLopeb(REQUEST.URL1, 'webtop/c'+str(self.jooksva_kursuse_nr(self, REQUEST))):
return 'portfolio'
else:
return ""+'portfolio'+""
return "kala"
def numberToText(self, REQUEST, arv):
"Asendab punkti komaga, kui see vajalik"
tekst=str(arv)
eraldaja=translate(self, "decimal_separator", target=self.giveLanguage(REQUEST))
tekst=tekst.replace(".", eraldaja)
return tekst
def giveLanguage(self, REQUEST):
""" gives user language """
prev_lang = REQUEST.HTTP_ACCEPT_LANGUAGE
try:
if getattr(self.fle_root().fle_users, str(REQUEST.AUTHENTICATED_USER)).kasKeelBrauserist():
language = prev_lang
else:
language = getattr(self.fle_root().fle_users, str(REQUEST.AUTHENTICATED_USER)).get_language()
except:
language = prev_lang
#XXX: let's see if this works..
if language == 'et_ee':
language = 'et'
if language not in self.get_languages():
language = prev_lang
language = self.default_language
return language
def firstAndLast(self,uname='',req=None):
""" Give object author's first and last name """
abc = ''
if not uname and not req:
abc = self.getOwnerTuple()[1]
if not uname and not abc and req:
abc = str(req.AUTHENTICATED_USER)
elif not uname and not abc and not req:
abc = uname
elif uname:
abc = uname
try:
ui = self.fle_users.get_user_info(str(abc))
if ui and ui.get_first_name()!='' and ui.get_last_name()!='':
nimi = ui.get_first_name()+" "+ui.get_last_name()
else:
nimi = abc
except FleError:
nimi = uname
return nimi
def lastAndFirst(self,uname='',req=None):
""" Give object author's first and last name """
abc = ''
if not uname and not req:
abc = self.getOwnerTuple()[1]
if not uname and not abc and req:
abc = req.AUTHENTICATED_USER
elif uname and not abc and not req:
abc = uname
try:
ui = self.fle_users.get_user_info(str(abc))
if ui.get_first_name()=='' and ui.get_last_name()=='':
nimi = abc
else:
nimi = ui.get_last_name()+", "+ui.get_first_name()
except FleError:
nimi = uname
return nimi
def is_courseContext(self):
return 0
def getCalendar(self):
""" return closest calendar """
return getattr(self, 'syndmused', None)
def batch_previous(self, batch):
""" generate links to next and previous pages """
result = []
while batch.previous:
batch = batch.previous
result.append(batch.start-1)
result.reverse()
return result
def batch_next(self, batch):
""" return an array of next batch staring points """
result = []
while batch.next:
batch = batch.next
result.append(batch.start-1)
return result
security.declareProtected(perm_manage, 'migratePersonalEvents')
def migratePersonalEvents(self):
""" from 0.7 to 0.8
disables creation of personal event
method will go through all user's personal 'syndmused' folder and remove 'Add FLE LO'
permission from everybody
'Add FLE LO' permission will be given to 'User' and 'Owner' on 'subgroups' folder.
"""
a = self.courses.courses_zcatalog.addColumn('getLogoThumbnailURL')
for c in self.courses.get_courses():
g = c.getObject()
subgroup = getattr(g.aq_inner, 'subgroups', None)
if subgroup is None:
continue
subgroup.manage_permission('Add FLE LO', ('Owner', 'User'), 1)
for u in self.fle_users.get_users():
s = getattr(u.aq_inner, 'syndmused', None)
if s is None:
continue
s.manage_permission('Add FLE LO', (), 0)
return "Removed 'Add FLE LO' permission from users. Added 'Add FLE LO' permission on subgroups. Added thumbnail url metadata to course_zcatalog."
security.declareProtected(perm_manage, 'migrateTo072')
def migrateTo072(self):
""" migrates IVA to version 0.7.2 """
um = self.fle_users
umz = um.userinfo_zcatalog
umz.delIndex('get_organization')
umz.addIndex('get_organization', 'FieldIndex')
return "done"
# EOF
iva-0.7.4/Downloader.py 0000644 0000000 0000000 00000003733 10345616031 0016023 0 ustar viewcvs viewcvs 0000001 0000000 # -*- coding: utf-8
# $Id$
#
# Copyright 2001, 2002 by IVA Team and contributors
#
# This file is part of IVA.
#
# IVA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# IVA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with IVA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""This is the main module for FLE, containing the FLE class and the Zope factory method for creating a FLE installation inside Zope."""
__version__ = "$Revision$"[11:-2]
import os.path, string, time
import Globals
import AccessControl
import OFS
from OFS.Folder import Folder
from Cruft import Cruft
# This is the class for the FLE installation root object.
class Downloader(
Folder,
Cruft,
OFS.SimpleItem.Item,
):
"""Download assistant."""
security = AccessControl.ClassSecurityInfo()
security.declareObjectPublic()
def __bobo_traverse__(self, REQUEST, entry_name=None):
return self
def __call__(self,client=None,REQUEST={},RESPONSE=None, **kw):
#raise 'foo2','CALL CALLED: ' + str(REQUEST)
srcurl=REQUEST.get('src')
#raise 'foo',srcurl
obj=self.get_object_of_url(srcurl,self)
path=srcurl.split('/')
fname=path.pop()
if fname=='':
return obj.index_html(REQUEST,RESPONSE)
else:
try:
return apply(getattr(obj,fname),(REQUEST,))
except TypeError:
return apply(getattr(obj,fname),(REQUEST,RESPONSE))
Globals.InitializeClass(Downloader)
# EOF
iva-0.7.4/Errors.py 0000644 0000000 0000000 00000002060 10345616031 0015171 0 ustar viewcvs viewcvs 0000001 0000000 # -*- coding: utf-8
# $Id$
#
# Copyright 2001, 2002 by IVA Team and contributors
#
# This file is part of IVA.
#
# IVA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# IVA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with IVA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""Will contain the error classes FLE raises. Not currently in use."""
__version__ = "$Revision$"[11:-2]
class FleError(Exception):
def __init__(self, args):
Exception.__init__(self, args)
class UserAlreadyInGroup(FleError): pass
class NoSuchUser(FleError): pass
# EOF
iva-0.7.4/FLE.py 0000644 0000000 0000000 00000134362 10345616031 0014336 0 ustar viewcvs viewcvs 0000001 0000000 # -*- coding: utf-8
# $Id$
#
# Copyright 2001, 2002 by IVA Team and contributors
#
# This file is part of IVA.
#
# IVA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# IVA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with IVA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""This is the main module for FLE, containing the FLE class and the Zope factory method for creating a FLE installation inside Zope."""
__version__ = "$Revision$"[11:-2]
IVA_VERSION = "IVA 0.7.4"
import os.path, string, time
try:
from PIL import Image
PIL_imported = 1
except ImportError:
PIL_imported = 0
try:
from Products.PlacelessTranslationService import getTranslationService
PLACELESS = 1
except ImportError:
PLACELESS = 0
try:
from Products.ZWiki.ZWikiPage import ZWikiPage
ZWIKI_imported = 1
except ImportError:
ZWIKI_imported = 0
import Globals
from Products.PageTemplates.PageTemplateFile import PageTemplateFile
from Products.StandardCacheManagers import AcceleratedHTTPCacheManager
from Globals import Persistent, Acquisition, HTMLFile, PersistentMapping
import AccessControl
import OFS
from OFS.Folder import Folder
from Products.ZCatalog.ZCatalog import ZCatalog
from TraversableWrapper import TraversableWrapper as TW
from Cruft import Cruft
from ThinkingTypeSetManager import ThinkingTypeSetManager as TTSM
from UserManager import UserManager
from CourseManager import CourseManager
from Timer import Timer
from common import file_path, ui_path, translate
import Acquisition
import YlTest
from string import atoi
from common import add_dtml_obj, new_add_dtml_obj, add_image_obj, \
reload_dtml, add_dtml, reload_pt, add_pt_obj, add_pt
from common import perm_view, perm_edit, perm_manage, perm_add_lo, perm_access, \
roles_admin, roles_staff, roles_user
import common
import re
import YlHoidla
from YlHoidla import YlHoidla
try:
from Products.CMFCore.CookieCrumbler import CookieCrumbler, ATTEMPT_NONE, ATTEMPT_LOGIN, ATTEMPT_RESUME
CCAware = 1
except:
CCAware = 0
from Statistics import StatisticsRegister
# This is the class for the FLE installation root object.
class FLE(
Folder,
TW,
Cruft,
Persistent,
AccessControl.Role.RoleManager,
OFS.SimpleItem.Item,
Timer,
StatisticsRegister,
):
"""FLE product."""
security = AccessControl.ClassSecurityInfo()
security.declareObjectPublic()
meta_type = 'IVA'
security.declareProtected(perm_manage, 'management_tab')
# management_tab = Globals.DTMLFile('ui/FLE/management_tab', globals())
management_tab = PageTemplateFile('ui/management_tab', globals())
management_tab._owner = None
manage_options=(
{'label' : 'Tools', 'action' : 'management_tab'},
) + OFS.Folder.Folder.manage_options
dtml_files = (
('style_css','','ui/style_css'),
('style_cssWebtop','','ui/style_cssWebtop'),
('style_cssBookshelf','','ui/style_cssBookshelf'),
('style_cssWorkshops','','ui/style_cssWorkshops'),
('style_cssManagement','','ui/style_cssManagement'),
('style_cssOrganizer','','ui/style_cssOrganizer'),
('js/checkAll2','','ui/js/checkAll2'),
('js/tree','','ui/js/tree'),
('js/ivaeditor', '', 'ui/js/ivaeditor'),
('wiki_stylesheet', '', 'ui/Wiki/wiki_stylesheet'),
)
#index_html = Globals.HTMLFile("index_html", globals())
pt_files = ( # ZWiki files
('courses_list','list of courses','ui/courses_list'),
('password_form','','ui/password_form'),
('backlinks','ZWiki: backlinks','ui/Wiki/backlinks.pt'),
('badtemplate','ZWiki: bad template','ui/Wiki/badtemplate.pt'),
('contentspage','ZWiki: content','ui/Wiki/contentspage.pt'),
('diffform','ZWiki: Diffs','ui/Wiki/diffform.pt'),
('editform','ZWiki: Edit','ui/Wiki/editform.pt'),
('filterissues','ZWiki: filter issues','ui/Wiki/filterissues.pt'),
('issuetracker','ZWiki: issue tracer','ui/Wiki/issuetracker.pt'),
('ratingform','ZWiki: rating','ui/Wiki/ratingform.pt'),
('recentchanges','ZWiki: recent changes','ui/Wiki/recentchanges.pt'),
('searchwiki','ZWiki: search form','ui/Wiki/searchwiki.pt'),
('subscribeform','ZWiki: subscribe','ui/Wiki/subscribeform.pt'),
('useroptions','ZWiki: options','ui/Wiki/useroptions.pt'),
('wikipage_macros','ZWiki: macros','ui/Wiki/wikipage_macros.pt'),
('wikipage','ZWiki','ui/Wiki/wikipage.pt'),
('index_html','start page','ui/index_html'),
('start_page','start','ui/start_page'),
('defaultRender','','ui/defaultRender'),
('changeEvent','Change event','ui/changeEvent'),
('createMail','Compose message','ui/createMail'),
('event_index','event','ui/event_index'),
('event_list','event list','ui/event_list'),
('haldusleht','Management','ui/haldusleht'),
('mailbox_index','Mailbox','ui/mailbox_index'),
('mail_index','Message','ui/mail_index'),
('mailStatus','Message sent','ui/mailStatus'),
('main_macro','main macro','ui/main_macro.zpt'),
('blog_macro','Blog macro','ui/blog_macros.zpt'),
('blog_index','Blog','ui/blog_index'),
('blog_entry','Blog entry','ui/blog_entry'),
('blog_archive','Blog archive','ui/blog_archive'),
('blog_addEntryForm','Add entry','ui/blog_addEntryForm'),
('blog_changeEntryForm','Change entry','ui/blog_changeEntryForm'),
('manage_addAssignment','Add new assignment','ui/manage_addAssignment'),
('manage_addingUsers','Addig users','ui/manage_addingUsers'),
('manage_addIvaUsers','Add users','ui/manage_addIvaUsers'),
('manage_affiliations','manage affiliations','ui/manage_affiliations'),
('manage_assignments','manage assignments','ui/manage_assignments'),
('manage_changeAssignment','change assignment','ui/manage_changeAssignment'),
('manage_course_info','course info','ui/manage_course_info'),
('courses/manage_gradeAssignment','grade assignments','ui/courses/manage_gradeAssignment.zpt'),
('manage_iva_setup','IVA Setup','ui/manage_iva_setup'),
('manage_ivaUsers','Users','ui/manage_ivaUsers'),
('manage_participants','Participants','ui/manage_participants'),
('manage_userPermissions','User permissions','ui/manage_userPermissions'),
('manage_pendingUsers','Pending users','ui/manage_pendingUsers'),
('message_dialog','Dialog','ui/message_dialog'),
('message_dialog2','Dialog','ui/message_dialog2'),
('message_dialog_error','Error','ui/message_dialog_error'),
('organizer_calendar','Calendar','ui/organizer_calendar'),
('calendar','Calendar','ui/calendar.zpt'),
('organizer_change_course','Select a course','ui/organizer_change_course'),
('organizer_index','Welcome','ui/organizer_index'),
('page_macro','page macro','ui/page_macro.zpt'),
('sharedDocs','Shared documents','ui/sharedDocs'),
('standard_error_message','Error occured','ui/standard_error_message'),
('error_show_traceback','Traceback','ui/error_show_traceback.zpt'),
('assignmentGrading','Grading','ui/assignmentGrading'),
('testihaldus', 'Quizzes', 'ui/testihaldus'),
#('workshop_subgroup','','ui/subgroups/workshop_subgroup'),
('workshop_subgroup_add','Add subgroup','ui/subgroups/workshop_subgroup_add.zpt'),
('workshop_subgroup_list','Subgroups','ui/subgroups/workshop_subgroup_list.zpt'),
('workshop_subgroup_members','Subgroup members','ui/subgroups/workshop_subgroup_members.zpt'),
('portfolio_index', 'Portfolio', 'ui/portfolio_index.zpt'),
#('courses/sg_index_html','','ui/subgroups/sg_index_html.zpt'),
('hw_index_html', 'Assignment', 'ui/webtop/hw_index_html.zpt'),
('wt_add_folder','Adding a folder','ui/webtop/wt_add_folder.zpt'),
('wt_add_link','Adding a link','ui/webtop/wt_add_link.zpt'),
('wt_add_memo','Adding a memo','ui/webtop/wt_add_memo.zpt'),
('wt_add_wiki','Adding ZWiki','ui/webtop/wt_add_wiki.zpt'),
('wt_index_html','','ui/webtop/wt_index_html.zpt'),
('wt_itemProperties','Properties','ui/webtop/wt_itemProperties.zpt'),
('wt_manage','Export','ui/webtop/wt_manage.zpt'),
('wt_rename','renaming','ui/webtop/wt_rename.zpt'),
('wt_upload','Adding a document','ui/webtop/wt_upload.zpt'),
('wt_usercomments','Comments','ui/webtop/wt_usercomments.zpt'),
('wt_userForm','Sharing','ui/webtop/wt_userForm.zpt'),
('wt_view_memo','View memo','ui/webtop/wt_view_memo.zpt'),
('wt_zip_upload','Uploading and unzip a zip-file','ui/webtop/wt_zip_upload.zpt'),
('wt_visitors','Visitors','ui/webtop/wt_visitors.zpt'),
('wt_macros','Webtop macros','ui/webtop/wt_macros.zpt'),
('ylAlus_muutmisVorm', 'Change question', 'ui/ylAlus_muutmisVorm'),
('ylMeta_vorm1', 'metadata', 'ui/ylMeta_vorm1'),
('ylesandedMuutmisTabelina', 'Questions', 'ui/ylesandedMuutmisTabelina'),
('ylOtsing', 'Search results', 'ui/ylOtsing'),
('ylOtsinguVorm', 'Search questions', 'ui/ylOtsinguVorm'),
('ylTestSettingsForm', 'Quiz settings', 'ui/ylTestSettingsForm'),
('ylBlankQuestion', 'Blank', 'ui/ylBlankQuestion'),
('ylAddPicture', 'Add picture', 'ui/ylAddPicture'),
('ylTable', '', 'ui/ylTable'),
('qtChangeFormMatchingExercise', 'Change question', 'ui/qtChangeFormMatchingExercise'),
('qtChangeFormNumberSpaceExercise', 'Change question', 'ui/qtChangeFormNumberSpaceExercise'),
('qtChangeFormShortAnswerExercise', 'Change question', 'ui/qtChangeFormShortAnswerExercise'),
('qtChangeFormPercentExercise', 'Change question', 'ui/qtChangeFormPercentExercise'),
('qtTimeSettings', 'Settings', 'ui/qtTimeSettings'),
('qtTestAnswerTable', '', 'ui/qtTestAnswerTable'),
('qtTestAnswerCommentingTable', '', 'ui/qtTestAnswerCommentingTable'),
('qtTestAnswerStatistics', '', 'ui/qtTestAnswerStatistics'),
('qtUserResults', 'Responses', 'ui/qtUserResults'),
('qtExplanationQuiz', 'Explaination', 'ui/qtExplanationQuiz'),
('qtAnsweringForm', 'Answer', 'ui/qtAnsweringForm'),
('qtAnswersSaved', 'Answers saved', 'ui/qtAnswersSaved'),
('qtExerciseForm', 'Exercise', 'ui/qtExerciseForm'),
('qtExerciseAnswer', '', 'ui/qtExerciseAnswer'),
('wmapindex', 'Wordmaps', 'ui/wmapindex'),
('wordmaps_word_page', '', 'ui/wordmaps_word_page'),
('wordmaps_edge_page', '', 'ui/wordmaps_edge_page'),
('wordmaps_equation_redactor', '', 'ui/wordmaps_equation_redactor'),
('wordmaps_equation_buttons', '', 'ui/wordmaps_equation_buttons'),
('wordmaps_index_html', '', 'ui/wordmaps_index_html'),
('wordmaps_importing_page', '', 'ui/wordmaps_importing_page'),
('wordmaps_managing_page', '', 'ui/wordmaps_managing_page'),
('wordmaps_weight_page', '', 'ui/wordmaps_weight_page'),
('wordmaps_assessment_results', '', 'ui/wordmaps_assessment_results'),
('wordmaps_toolbox', '', 'ui/wordmaps_toolbox'),
('wordmaps_hierarhy', '', 'ui/wordmaps_hierarhy'),
('courses/add_course_context_form','Add Course Context','ui/courses/add_course_context_form'),
('courses/context_html','context','ui/courses/context_html'),
('courses/course_html','Knowledge Building','ui/courses/course_html'),
('courses/course_info','Course info','ui/courses/course_info'),
('courses/course_setup_roleplay_form','Roleplay setup','ui/courses/course_setup_roleplay_form'),
('courses/note_edit_form','Note editing','ui/courses/note_edit_form'),
('courses/index_html','Course management','ui/courses/index_html'),
('courses/note_preview_form','Note preview','ui/courses/note_preview_form'),
('courses/note_index_html','Note viewing','ui/courses/note_index_html'),
('courses/organizer_openCourses','Open courses','ui/courses/organizer_openCourses'),
('courses/printer_macro','Note printers','ui/courses/printer_macro'),
('courses/note_hide','Note hiding','ui/courses/note_hide'),
('courses/jamming_index_html','Jamming','ui/courses/jamming_index_html'),
('courses/jam_add_session_form','add jam session','ui/courses/jam_add_session_form'),
('courses/jamsession_index_html','Jamsession','ui/courses/jamsession_index_html'),
('courses/jam_add_artefact_form','Add artefact','ui/courses/jam_add_artefact_form'),
('courses/jam_artefact_index_html','Artefact','ui/courses/jam_artefact_index_html'),
('courses/jam_add_annotation_form','Add artefact annotation','ui/courses/jam_add_annotation_form'),
('courses/list_readers','Who has read it?','ui/courses/list_readers'),
('courses/manage_import_form','Import course','ui/courses/manage_import_form'),
('courses/teacher_import_form','Import course','ui/courses/teacher_import_form'),
('courses/manageCategories','manage course categories','ui/courses/manageCategories'),
('courses/course_index','Welcome to course','ui/courses/course_index'),
('courses/courseStatistics','Course statistics','ui/courses/courseStatistics'),
('courses/describeTTS','Describes thinkingtypeset','ui/courses/describeTTS'),
('courses/tootubade_leht','Workshop','ui/courses/tootubade_leht.zpt'),
('typesets/edit_form_1_3','Edit TTS 1/3','ui/typesets/edit_form_1_3'),
('typesets/edit_form_2_3','Edit TTS 2/3','ui/typesets/edit_form_2_3'),
('typesets/edit_form_3_3','Edit TTS 3/3','ui/typesets/edit_form_3_3'),
('typesets/index_html','Knowledge type sets','ui/typesets/index_html'),
('typesets/tts_index','Knowledge type set','ui/typesets/tts_index'),
('typesets/manage_import_form','Import knowledge type set','ui/typesets/manage_import_form'),
('register_form','Register form','ui/register_form'),
('fle_users/course_info_user','Logpage','ui/fle_users/course_info_user'),
('fle_users/user_courses_info','Statistics','ui/fle_users/user_courses_info'),
('fle_users/show_user_info','Show user info!','ui/fle_users/show_user_info'),
('fle_users/edit_user_form','Edit info','ui/fle_users/edit_user_form'),
('sub_manager_index','Subgroups','ui/subgroups/sub_manager_index.zpt'),
)
# NOTE: Since we use a python method index_html to do
# the redirection to the appropriate DTML method, EVERY FOLDER
# that the user access must have this index_html method
# (either through class inheritance or as its own dtml method,
# but not through acquisition from its containers). Acquisition
# cannot be used, since the object reference passed to the DTML
# method will point to the object where index_html was acquired.
# So all courses, contexts, notes, userinfos, webtops and webtopfolders
# and any other folderish objects must have this python method.
#security.declarePublic('index_html')
#def index_html(self,REQUEST):
# return self.ui.FLE.index_html(self,REQUEST)
# Parameters are received from the creation form at
# ui/FLE/creation_form.dtml
def __init__(
self, _id, title,
smtp_host, smtp_port=25,
_default_lang='en', _quota=3000000, mfrom='iva@htk.tpu.ee',
def_passwd=0,def_not_change=0,def_not_aff=0):
"""Construct FLE object."""
self.setup_timer()
errors = []
if not _id:
errors.append('ID not specified')
if not title:
errors.append('Title not specified')
if errors:
raise 'Insufficient form data',str(errors)
self.id = _id
self._default_lang=_default_lang
self._quota=_quota
self.title = title
self.mfrom = mfrom
self.def_asswd= int(def_passwd)
self.def_ot_change= int(def_not_change)
self.def_ot_aff= int(def_not_aff)
self._pending_users = PersistentMapping() # user list
self.__fle_root = ''
if len(smtp_host)>0 and smtp_port:
from Products.MailHost import MailHost
mailhost = MailHost.MailHost()
mailhost._init(smtp_host, int(smtp_port))
self._setObject('MailHost', mailhost)
# Add images to images/
self.manage_addFolder('images', 'Images')
AcceleratedHTTPCacheManager.manage_addAcceleratedHTTPCacheManager(self.images,'HTTPCache')
http_cache = getattr(self.images, 'HTTPCache')
http_cache.manage_editProps('', {'anonymous_only':0, 'interval':3600, 'notify_urls':''})
from common import image_file_path
self.add_images(self.images, image_file_path)
ims = getattr(self, 'images')
ims.manage_addFolder('courses_imgs', '')
ims.manage_addFolder('users_imgs', '')
# ZCatalog for webtop items
catalog = ZCatalog('catalog_webtop_items', 'ZCatalog for webtop items')
# indexes
catalog.addIndex('get_name', 'TextIndex')
catalog.addIndex('get_content', 'TextIndex')
catalog.addIndex('get_author', 'FieldIndex')
# metadata
catalog.addColumn('get_name')
catalog.addColumn('get_author')
catalog.addColumn('absolute_url')
self._setObject('catalog_webtop_items', catalog)
# ZCatalog for events
catalog = ZCatalog('catalog_events','ZCatalog for events')
# indexes
catalog.addIndex('meta_type', 'FieldIndex')
catalog.addIndex('path', 'PathIndex')
catalog.addIndex('kysiOlek', 'FieldIndex')
catalog.addIndex('getName', 'FieldIndex')
catalog.addIndex('asukohaNimi', 'FieldIndex')
catalog.addIndex('get_start_time', 'DateIndex')
catalog.addIndex('get_end_time', 'DateIndex')
# metadata
catalog.addColumn('getName')
catalog.addColumn('kysiOlek')
catalog.addColumn('getContent')
catalog.addColumn('kysiSiseviide')
catalog.addColumn('kysiViide')
catalog.addColumn('kysiAlgus')
catalog.addColumn('kysiLopp')
catalog.addColumn('get_start_time')
catalog.addColumn('get_end_time')
catalog.addColumn('absolute_url')
# add object
self._setObject('catalog_events', catalog)
# init Statistics
StatisticsRegister.__init__(self)
security.declarePrivate('manage_afterAdd')
# Executes a full FLE import if the export data was
# passed to the constructor (ie. uploaded via the creation
# form.
def manage_afterAdd(self, item, container):
"""Add roles to the root level Fle folder and do other
initialization tasks."""
stats = getattr(self, 'Statistics', None)
if stats is None:
from Statistics import StatisticsManager
stats = StatisticsManager()
self._setObject(stats.id, stats)
if not hasattr(self.aq_self, 'qtCatalog'):
self._setObject('qtCatalog', YlHoidla())
if hasattr(self,'typesets'):
# If the typesets directory already exists, then this
# isn't the initial installation, but rather a rename
# or a move operation.
# Skip everything!
return
self.manage_addProperty('Autoregister', 0, 'boolean')
# add property for FLE version number
self.manage_addProperty('webtop_quota', 1, 'boolean')
self.manage_addProperty('webtop_quota_amount', self._quota, 'string')
self.manage_addProperty('default_language', self._default_lang, 'string')
self.manage_addProperty('IVA_VERSION', IVA_VERSION, 'string')
self.manage_addProperty('MFROM',self.mfrom,'string')
self.manage_addProperty('def_passwd',int(self.def_asswd),'boolean')
self.manage_addProperty('def_not_change',int(self.def_ot_change),'boolean')
self.manage_addProperty('def_not_aff',int(self.def_ot_aff),'boolean')
tts_manager = TTSM('typesets', '')
self._setObject('typesets', tts_manager)
tts_manager=tts_manager.__of__(self)
from Downloader import Downloader
self._setObject('download',Downloader())
self.manage_addFolder('uploads','Wiki uploads')
self.manage_addFolder('js','JavaScripts')
from common import fle_roles
for role in fle_roles:
self._addRole(role)
self._addRole('Items')
self.manage_permission(perm_access, ('Manager','IVAAdmin','Member','Owner') ,0)
self.manage_permission(perm_view, ('Authenticated','Manager','IVAAdmin','Member','Owner') ,0)
self.manage_permission(perm_edit, ('Manager',), 0)
self.manage_permission(perm_manage, roles_admin, 0)
self.manage_permission(perm_add_lo, roles_admin, 0)
try:
self.manage_permission('Zwiki: Add comments', roles_user+('Authenticated','Owner',), 0)
self.manage_permission('Zwiki: Add pages', ('Owner',), 0)
self.manage_permission('Zwiki: Add wikis', ('Owner',), 0)
self.manage_permission('Zwiki: Change page types', ('Owner',), 0)
self.manage_permission('Zwiki: Delete pages', ('Owner',), 0)
self.manage_permission('Zwiki: Edit pages', ('Owner',), 0)
self.manage_permission('Zwiki: Rename pages', ('Owner',), 0)
self.manage_permission('Zwiki: Reparent pages', ('Owner',), 0)
except ValueError:
pass
self.uploads.manage_permission('Add Documents, Images, and Files', roles_user+('Authenticated','Owner',), 0)
um_obj = UserManager('fle_users',
#'FLE User Manager')
'')
self._setObject('fle_users',
um_obj)
# Create default knowledge type sets, whether importing
# or not.
tts_manager.load_default_sets()
# Let's do courses last, since if we're importing, we
# need to have the users already in place.
cm_obj = CourseManager('courses')
self._setObject('courses', cm_obj)
self.manage_addProduct['OFSP'].manage_addFolder('css')
#self.css._setObject('style_css', self.style_css)
self.reload_pt()
# Set the zope manageable dtml objects of this class.
self.reload_dtml()
self.setDefaultPermissions()
#XXX: migrate me too!?
if CCAware:
self.addCookieCrumbler()
security.declareProtected(perm_manage, 'reload_pt')
def reload_pt(self, REQUEST=None):
""" reload ZopePageTemplates """
reload_pt(self, self.pt_files)
self.setDefaultPermissions()
if REQUEST:
return self.message_dialog(
self, REQUEST,
title="Reloaded",
message="All page templates reloaded",
action='index_html')
security.declarePublic('setDefaultPermissions')
def setDefaultPermissions(self):
""" doc"""
getattr(self.images,'iva_logo_trans').manage_permission('View',['Authenticated', 'Anonymous',], 1)
getattr(self.images,'start_top_bg').manage_permission('View',['Authenticated', 'Anonymous',], 1)
getattr(self.images,'start_bg').manage_permission('View',['Authenticated', 'Anonymous',], 1)
getattr(self,'register_form').manage_permission('View',['Authenticated', 'Anonymous',], 1)
getattr(self,'courses_list').manage_permission('View',['Authenticated', 'Anonymous',], 1)
try:
getattr(self,'style_css').manage_permission('View',['Authenticated', 'Anonymous',], 1)
except:
pass
getattr(self,'index_html').manage_permission('View',['Authenticated', 'Anonymous',], 1)
getattr(self,'start_page').manage_permission('View',['Authenticated', 'Anonymous',], 1)
getattr(self,'password_form').manage_permission(perm_view,['Authenticated', 'Anonymous',], 1)
# getattr(self,'style_css').manage_permission(perm_view,['Anonymous'],0)
getattr(self,'register_form').manage_permission(perm_view,['Anonymous'],0)
getattr(self,'images').manage_permission('View',['Anonymous',],1)
try:
getattr(getattr(self,'js'), 'tree').manage_permission('View',['Anonymous',],1)
except AttributeError:
pass
getattr(self, 'main_macro').manage_permission('View',['Anonymous',],1)
security.declareProtected(perm_manage, 'reload_dtml')
def reload_dtml(self, REQUEST=None):
"""Reloads dtml stuff."""
reload_dtml(self, self.dtml_files)
self.setDefaultPermissions()
if REQUEST:
return self.message_dialog(
self, REQUEST,
title='Reloaded',
message='dtml files reloaded',
action='index_html')
security.declareProtected(perm_manage, 'reload_typesets')
def reload_typesets(self,REQUEST=None):
"""Reload typesets."""
self.typesets.load_default_sets()
if REQUEST:
return self.message_dialog(
self, REQUEST,
title='Reloaded',
message='Knowledge type sets reloaded',
action='index_html')
security.declareProtected(perm_manage, 'reload_images')
def reload_images(self,REQUEST=None):
"""Reload images."""
for e in self.images.objectIds():
if e in ('courses_imgs', 'users_imgs', 'HTTPCache'):
continue
self.images.manage_delObjects(e)
from common import image_file_path
self.add_images(self.images, image_file_path)
if REQUEST:
return self.message_dialog(
self, REQUEST,
title='Reloaded',
message='Images reloaded',
action='index_html')
security.declarePrivate('add_images')
# fs_path is CVS path
def add_images(self, zope_path, fs_path):
"""Add images recursively."""
for e in os.listdir(fs_path):
full_path = os.path.join(fs_path, e)
if os.path.isdir(full_path):
if e == 'CVS': continue
if e == '.svn': continue
zope_path.manage_addFolder(e, '')
self.add_images(getattr(zope_path, e), full_path)
else:
# title (3rd parameter) will be used as an alt parameter
# inside HTML tag. (Override in DTML code when you
# want some alt text (i.e. almost always...))
# This can be like this for now .... -granbo
import re
m = re.match("^(.*)\.", e)
add_image_obj(zope_path, m.group(1), '', full_path)
security.declareProtected(perm_manage, 'reload_all')
def reload_all(self, REQUEST=None):
"""Reload all dtml, style sheet, image, printer, and
translation files."""
self.IVA_VERSION = IVA_VERSION
# self.reload_all_dtml()
self.reload_images()
self.reload_pt()
self.reload_typesets()
self.reload_all_dtml()
if REQUEST:
return self.message_dialog(
self, REQUEST,
title='Reloaded',
message='Reloaded all dtml, css, images, and knowledge type sets',
action='index_html')
security.declareProtected(perm_manage, 'reload_all_dtml')
def reload_all_dtml(self, REQUEST=None):
"""Reload _all_ dtml files."""
from common import tree_reload_dtml
reload_dtml(self, self.dtml_files)
self.setDefaultPermissions()
if REQUEST:
return self.message_dialog(
self, REQUEST,
title='Reloaded',
message='dtml files reloaded',
action='index_html')
# security.declareProtected(perm_view, 'get_version')
security.declarePublic('get_version')
def get_version(self):
""" return IVA version """
return getattr(self, 'IVA_VERSION', 'IVA')
# FIXME: What should we do if self.webtop_quota_amount is invalid?
security.declareProtected(perm_view, 'get_quota')
def get_quota(self):
"""Return quota limit in bytes (-1 if no quota in use)."""
if not hasattr(self, 'webtop_quota'):
return -1
if not hasattr(self, 'webtop_quota_amount'):
return -1
if not self.webtop_quota:
return -1 # no quota
s = self.webtop_quota_amount.strip()
if s[-1].lower() == 'k':
return int(s[:-1]) * 1024
elif s[-1].lower() == 'm':
return int(s[:-1]) * 1024 * 1024
else:
return int(s)
#XXX: security check!
# security.declareProtected(perm_view, 'get_languages')
security.declarePublic('get_languages')
def get_languages(self):
""" return list of languages available """
lang_list = ['et','en','fi','ru', 'de']
return lang_list
def get_default_language(self):
"Vaikimisi keel"
return getattr(self, 'default_language', 'en')
# This is used by message_dialog.dtml.
def message_dialog_handler(self, action, REQUEST):
"""Redirects to the given URL, preserving the
state information in the url."""
REQUEST.RESPONSE.redirect(action)
security.declareProtected(perm_view, 'redirect_to_webtop')
def redirect_to_webtop(self, REQUEST):
"""Redirect to webtop."""
uname = str(REQUEST.AUTHENTICATED_USER)
if (not hasattr(self.fle_users.aq_self, uname)):
result = self.fle_users.add_user_fle(uname, ('Member',))
user = self.fle_users.get_user_info(uname)
if self.getUseFinger():
user.fingerNames()
jnr = user.get_jooksev_kursus()
self.courses.change_course(REQUEST, jnr)
#user.kontrolliKasutajaKodutood(REQUEST)
if user.get_first_name()=='' or user.get_last_name()=='':
return REQUEST.RESPONSE.redirect(self.fle_root().absolute_url()+'/fle_users/' + uname + '/webtop/edit_user_form')
if hasattr(user, 'perm_must_change'):
if user.perm_must_change == 1:
return REQUEST.RESPONSE.redirect(self.fle_root().absolute_url()+'/fle_users/' + uname + '/webtop/edit_user_form')
else:
return REQUEST.RESPONSE.redirect(self.fle_root().absolute_url()+'/organizer_index')
else:
return REQUEST.RESPONSE.redirect(self.fle_root().absolute_url()+'/organizer_index')
security.declareProtected(perm_manage, 'manage_workspace')
def manage_workspace(self,REQUEST):
"""This makes sure that ZCatalog doesn't override manage_workspace
and make it point to index_html, when we actually want manage_main"""
REQUEST.RESPONSE.redirect('manage_main')
def logout(self,REQUEST):
"""This is the logout instruction page."""
return self.message_dialog2(
self, REQUEST,
title= 'Logout',
message="To log out, either close your browser or press the Logout button below. When your browser asks for a username and password, just press Cancel. This will clear your login information from your browser's cache",
extra_value_name = '',
extra_values = (),
option1_value = 'Cancel',
option1_name = 'cancel',
option2_value = 'Logout',
option2_name = 'logout',
handler = 'clear_password')
security.declarePublic('clear_password')
def clear_password(
self,
cancel=None,
logout=None,
REQUEST=None):
"""This will clear the password cache."""
if logout:
#XXX: take care of session somehow, invalidating doesn't seem to work
#REQUEST.SESSION.invalidate()
REQUEST.RESPONSE.setStatus(401)
REQUEST.RESPONSE.setHeader("WWW-Authenticate", 'basic realm="Zope"')
try:
self.login.logout()
except AttributeError:
pass
return self.message_dialog(
self, REQUEST,
title='Logout',
message='You have been logged out.',
action = 'index_html')
else:
return self.redirect_to_webtop(REQUEST)
def has_PIL(self):
"""Has the system PIL (Python Image Library) installed?"""
return PIL_imported
def has_PLACELESS(self):
""" is PlacelessTranslationService installed? """
return PLACELESS
def has_CMF(self):
""" is CMF installed? """
return CCAware
def getId(self):
""" Return object id. Hack XXX """
return self.id
security.declarePublic('register_form_handler')
def register_form_handler(self, REQUEST,
regB='', cancelB='', # buttons
username='', fname='', lname='', email='', preflang='en',optmess='', numbercheck=0):
""" registers user """
if regB and self.get_allow_autoregister():
ok = 1
inv_val = ''
if username and fname and lname and email:
ok = 1
if not '@' in email and not '.' in email:
ok = 0
inv_val+= ' email'
else:
#XXX check email!?
pass
if not fname:
ok = 0
if inv_val: inv_val+=','
inv_val+=' first name'
if not lname:
ok = 0
if inv_val: inv_val+=','
inv_val+=' last name'
if numbercheck != REQUEST.SESSION.get('securenr'):
ok = 0
if inv_val: inv_val+=','
inv_val+= ' number'
if not username:
ok = 0
if inv_val: inv_val+=','
inv_val+=' username'
else:
if self.fle_users.is_valid_uname(username):
ok = 0
if inv_val: inv_val+=','
inv_val+=' username'
# XXX: maybe we don't want that!
# XXX: also check in fle_users folder for user record
# XXX: check for lowlevel acl_users?
if not ok:
return self.register_form(username=username, fname=fname, lname=lname, email=email, optmess=optmess,mess='invalid values: '+inv_val)
#do queueing
self._queue_user(username=username, fname=fname, lname=lname, email=email, preflang=preflang,optmess=optmess)
#XXX: subject of email. Translation!
message = translate(self,"registrant_waiting", target=preflang)
if self.saadaEmail(email,'useraccount request', message):
return translate(self,"You have been registered, check e-mail",target=self.giveLanguage(REQUEST))
else:
return translate(self,"You have been registered but some problems occured when sending email.",target=self.giveLanguage(REQUEST))
elif cancelB:
return REQUEST.RESPONSE.redirect('index_html')
raise "IVA Error", "unknown button in register_form_handler"
def lostPassword(self,REQUEST, send=0,knimi='', give_email=0):
if give_email:
if not knimi: return 0
try:
kasutaja = self.fle_users.get_user_info(knimi)
except:
return 0
if kasutaja.get_email() != '':
return 1
else:
return 0
return 0 # should never reach here
#if not hasattr(self.aq_self,'MailHost'):
if not getattr(self.aq_base, 'MailHost', None):
return ""
if send:
try:
kasutaja = self.fle_users.get_user_info(knimi)
except:
return 0
if kasutaja.get_email() == '':
return 0
sisu = '' #\nContent-Type:text/plain; charset=utf-8\n\n\n'
sisu += "\n"+translate(self,'Message from IVA server',target=self.giveLanguage(REQUEST))
sisu += "\n"+translate(self,'IVA server aadress:',target=self.giveLanguage(REQUEST))+" "+self.fle_root().absolute_url()
sisu += "\n"+translate(self,'Username:',target=self.giveLanguage(REQUEST))+" "+knimi
sisu += "\n"+translate(self,'Password:',target=self.giveLanguage(REQUEST))+" "
try:
sisu += kasutaja.getPassword()
except:
sisu += translate(self,"Error fetching password",target=self.giveLanguage(REQUEST))
self.saadaEmail(kasutaja.get_email(),'Lost password',sisu, kasutaja.get_email())
return "Recover password"
security.declarePublic('randomImage')
def randomImage(self):
""" chooses 3/4 images to place on frontpage """
imgs = self.images.frontpage.objectValues()
from random import shuffle
shuffle(imgs)
if self.get_allow_autoregister(): count=3
else: count = 4
return imgs[0:count]
security.declareProtected(perm_manage,'manage_iva_setup_pictures')
def manage_iva_setup_pictures(self, REQUEST, uploadB='', deleteB='',dele='', newimage=''):
""" upload picture, delete picture """
imgContainer = getattr(self.images, 'frontpage')
if deleteB:
from types import StringType
if type(dele) == StringType: dele = (dele,)
for x in dele:
imgContainer._delObject(x)
if uploadB and newimage:
import random
nid = ""
for x in range(15):
nr = 95
while 900 and smtp_port:
from Products.MailHost import MailHost
mailhost = MailHost.MailHost()
mailhost._init(smtp_host, atoi(smtp_port))
self._setObject('MailHost', mailhost)
else:
if len(smtp_host)>0 and smtp_port:
mailhost = getattr(self, 'MailHost')
mailhost.smtp_host = smtp_host
mailhost.smtp_port = smtp_port
self.MFROM = mailfrom
self.def_passwd = def_passwd
self.def_not_change = def_not_change
self.def_not_aff = def_not_aff
self.setUseFinger(useFinger)
self.setFingerHost(fingerHost)
self.setFingerPort(fingerPort)
return self.manage_iva_setup(mess='settings saved succesfully!')
return
security.declareProtected(perm_manage, 'unqueue_user')
def unqueue_user(self, uname):
del self._pending_users[uname]
security.declarePrivate('_queue_user')
def _queue_user(self,username='', fname='', lname='', email='', preflang='en',optmess=''):
# _pending_users
if not getattr(self.aq_base, '_pending_users', None):
self._pending_users = PersistentMapping()
#if not hasattr(self.aq_self, '_pending_users'):
# self._pending_users = PersistentMapping()
while self._pending_users.has_key(username):
username+='x'
self._pending_users[username] = {'fname':fname,'lname':lname,'email':email,'preflang':preflang,'optmess':optmess}
security.declareProtected(perm_manage,'get_pending_users')
def get_pending_users(self):
""" get pending users """
return self._pending_users.keys()
security.declareProtected(perm_manage,'get_pending_details')
def get_pending_details(self, uname):
""" get details of pending user """
return self._pending_users[uname]
security.declarePrivate('make_random_number')
def make_random_number(self, REQUEST):
# generates number and stores in in SESSION
import random
rnr = int(random.random()*10000000)
REQUEST.SESSION.set('securenr',rnr)
return rnr
def get_allow_autoregister(self):
return self.Autoregister
security.declarePublic('generate_picture')
def generate_picture(self, REQUEST, RESPONSE):
""" test"""
srnr = self.make_random_number(REQUEST)
import PIL
from PIL import Image, ImageDraw
import cStringIO
s = cStringIO.StringIO()
pilt = Image.new('RGB',(100,30),(255,255,255))
pil2 = ImageDraw.Draw(pilt)
tekst = str(srnr)
pil2.text((10,10),tekst,fill=(30,30,128))
pilt.save(s,'jpeg')
s.seek(0)
RESPONSE.setHeader('Content-Type','image/jpeg')
return s.read()
def tolgi(self, sona, REQUEST):
"Tőlgib etteantud jupi. Abifunktsioon DTML-ist tőlkimisel"
return translate(self, sona, target=self.giveLanguage(REQUEST))
security.declareProtected(perm_manage,'exportIMail')
def exportIMail(self,REQUEST):
""" export mailmessages """
from ImportExportIMS import Kirjutus
from ImportExportIMS import kirjutaYldM
import tempfile, os
name = 'ivamessages.zip'
path = os.path.join(Globals.INSTANCE_HOME,'var')
fname = os.path.join(path,name)
#fname = tempfile.mktemp()
yld = kirjutaYldM()
yld.kirjutaYldmanifest('innermail','Innermail messages',base='',href='messages.xml')
yld.lisaFaili(fname)
k = Kirjutus(self.fle_root(), self.get_id())
k.exportMail(fname)
#os.remove(fname)
return "Done! Zip-file is located at %s" % fname
security.declareProtected(perm_manage, 'exportServerSettings')
def exportServerSettings(self, REQUEST):
""" export server settings and course categories """
from ImportExportIMS import Kirjutus
from ImportExportIMS import kirjutaYldM
import tempfile, os
name = 'iva_settings.zip'
path = os.path.join(Globals.INSTANCE_HOME,'var')
fname = os.path.join(path,name)
yld = kirjutaYldM()
yld.kirjutaYldmanifest('IVA_C','IVA course categories',base='',href='course_cat.xml')
yld.kirjutaYldmanifest('IVA_S','IVA server settings',base='',href='settings.xml')
yld.kirjutaYldmanifest('IVA_A','IVA affiliation codes',base='',href='affiliations.xml')
yld.lisaFaili(fname)
k = Kirjutus(self.fle_root(), self.get_id())
k.looKursuseFail(0)
#... do stuff
k.exportCourseCategories(fname)
k.exportServerSettings(fname)
k.exportAffiliations(fname)
return "Done! Zip-file is located at %s" % fname
security.declareProtected(perm_manage,'exportICAL')
def exportICAL(self,REQUEST):
""" export user events """
from ImportExportIMS import Kirjutus
from ImportExportIMS import kirjutaYldM
import tempfile, os
name = 'iva_events.zip'
path = os.path.join(Globals.INSTANCE_HOME,'var')
fname = os.path.join(path,name)
#fname = tempfile.mktemp()
yld = kirjutaYldM()
yld.kirjutaYldmanifest('IVA','IVA user events',base='IVA/',href='imsmanifest.xml')
# yld.kirjutaYldmanifest()
yld.lisaFaili(fname)
k = Kirjutus(self.fle_root(), self.get_id())
k.looKursuseFail(0)
k.kirjutaKasutajaSyndmus(self.fle_users.get_users())
k.pakiKursusFaili(fname)
#os.remove(fname)
return "Done! Zip-file is located at %s" % fname
security.declareProtected(perm_view,'getUseFinger')
def getUseFinger(self):
""" return if user information should be pulled via finger """
if not hasattr(self, 'useFinger'):
return 0
return self.useFinger
security.declareProtected(perm_manage,'setUseFinger')
def setUseFinger(self, state):
""" set if we should use finger """
self.useFinger = int(state)
security.declareProtected(perm_view,'getFingerPort')
def getFingerPort(self):
""" return finger port """
if not hasattr(self, 'fingerPort'):
return "79"
return self.fingerPort
security.declareProtected(perm_manage,'setFingerPort')
def setFingerPort(self, port):
""" set finger daemon port """
self.fingerPort = int(port)
security.declareProtected(perm_view,'getFingerHost')
def getFingerHost(self):
""" return finger daemon host """
if not hasattr(self, 'fingerHost'):
return ""
return self.fingerHost
security.declareProtected(perm_manage,'setFingerHost')
def setFingerHost(self, host):
""" set fingerdaemon host """
self.fingerHost = host
def getCourseForID(self, REQUEST, course_id, curUser):
""" return course instance or set current course id to 0 """
#if not hasattr(self.courses.aq_self, course_id):
course = getattr(self.courses, course_id, '')
if course == '' and int(course_id) != 0:
curUser.jooksev_kursus = 0
return REQUEST.RESPONSE.redirect('organizer_index')
return course
security.declareProtected(perm_manage,'addCookieCrumbler')
def addCookieCrumbler(self):
""" xxx """
if hasattr(self.aq_self, 'login'):
return
cc = CookieCrumbler()
cc.id = 'login'
self._setObject('login', cc)
#XXX: picture location!!!
login_form = """
"""
self.manage_addDTMLMethod('login_form','CookieCruymblers login form',login_form)
getattr(self,'login_form').manage_permission('View',['Authenticated', 'Anonymous',], 1)
cc = getattr(self, 'login')
cc.auth_cookie = '__iva'
cc.name_cookie = '__iva_name'
cc.pw_cookie = '__iva_password'
cc.persist_cookie = '__iva_persistent'
return "ok"
security.declarePublic('verifyUserLocation')
def verifyUserLocation(self, userLocation):
""" asd """
if userLocation not in ('Organizer','Workshops','Management','Bookshelf','Webtop'):
return 1
return 0
security.declareProtected(perm_view, 'getLangCode')
def getLangCode(self, REQUEST, nr=0, curUser=None):
""" return language code """
if not curUser.kasKeelBrauserist():
return curUser.get_language()
lang = REQUEST.HTTP_ACCEPT_LANGUAGE # et,en;q=0.8,ru;q=0.5,en-us;q=0.3
existing_langs = self.get_languages()
atmp = lang.split(',') # ['et', 'en;q=0.8', 'ru;q=0.5', 'en-us;q=0.3'] --> 'et'
if len(atmp)>nr:
a = atmp[nr]
else:
return 2
b = a.split(';')[0]
c = b.split('-')[0]
if c not in existing_langs:
status = self.getLangCode(REQUEST, nr+1)
if status == 2:
return 'en'
c = status
return c
Globals.InitializeClass(FLE)
# FIXME: input_checks (some checks done in FLE.__init__)
def manage_addFLE(
self, id='', title='',
try_it = 0, shere='',
smtp_host='', smtp_port=25,
lang='en', quota=3000000, mfrom='iva@htk.tpu.ee',def_passwd=0,
def_not_change=0,def_not_aff=0):
"""Create a FLE object. (Product Factory Method)."""
if try_it:
warnings = []
errors = []
if not CCAware:
warnings.append('CMF not installed - CookieCrumbler not available')
if not PIL_imported:
warnings.append('PIL not installed - image manipulations disabled')
if not PLACELESS:
warnings.append('PlacelessTranslationService not installed - translation disabled')
if not ZWIKI_imported:
warnings.append('ZWiki not installed - some parts of IVA might even not work.')
if not id:
errors.append('No id specified')
if id:
used = getattr(shere.aq_inner, id, 0)
#print self
if used:
errors.append('ID is already in use')
if not used:
from input_checks import is_valid_id
valid = is_valid_id(id)
if not valid:
errors.append('ID is not valid - do not use any special symbols')
return {'errors':errors, 'warnings':warnings}
#def_passwd = REQUEST.get('def_passwd',0)
#def_not_change = REQUEST.get('def_not_change',0)
#def_not_aff = REQUEST.get('def_not_aff',0)
fle = FLE(
id, title,
smtp_host, smtp_port, lang, quota, mfrom,
def_passwd,def_not_change,def_not_aff)
self._setObject(id, fle)
return 1
#manage_addFLEForm = Globals.HTMLFile('ui/IVA_creation_form', globals())
manage_addFLEForm = PageTemplateFile('ui/IVA_creation_form.zpt', globals())
# EOF
iva-0.7.4/GroupFolder.py 0000644 0000000 0000000 00000007537 10345616031 0016163 0 ustar viewcvs viewcvs 0000001 0000000 # -*- coding: utf-8
# $Id$
#
# Copyright 2001, 2002 by IVA Team and contributors
#
# This file is part of IVA.
#
# IVA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# IVA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with IVA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""Contains class GroupFolder, which is the root object for group folders
in Knowledge Building."""
__version__ = "$Revision$"[11:-2]
import Globals
#from Globals import Persistent, HTMLFile
import AccessControl
from common import reload_dtml, add_dtml
#import TraversableWrapper
import WebtopFolder
import WebtopTrash
from WebtopItem import WebtopItem
from TraversableWrapper import TWFolder
from TempObjectManager import TempObjectManager
from common import perm_view, perm_edit, perm_manage, perm_add_lo
# This object is the root of a group folder inside a Course or
# a CourseContext.
#
# A group folder contains a trash folder and any
# WebtopItems the users have created. WebtopItem is a superclass, and
# actually the group folder will contain specific subclass instances, like
# WebtopFolder, WebtopFile, WebtopLink and WebtopMemo.
#
class GroupFolder(
WebtopFolder.WebtopFolder,
):
"""Group folder."""
meta_type = "GroupFolder"
list_of_types=('WebtopFolder', 'WebtopLink', 'WebtopMemo', 'WebtopFile','GroupFolder')
security = AccessControl.ClassSecurityInfo()
def __init__(self,parent,name):
"""Construct the group folder root object."""
WebtopItem.__init__(self,parent,name)
TempObjectManager.__init__(self)
self.id = 'gf' + self.id[2:]
self.__id_counter = long(self.id[2:])
security.declarePrivate('manage_afterAdd')
def manage_afterAdd(self, item, container):
"""Create trash and clipboard and call superclass
initialization code."""
WebtopFolder.WebtopFolder.manage_afterAdd(self, item, container)
security.declarePrivate('generate_id')
def generate_id(self):
"""Return a unique (within this webtop) id.
These ids are used for any and all WebtopItems created
instead of their visible names so we avoid any problems with
visible name conflicts and can use more complex visible names
for items."""
self.__id_counter += 1L
return "gf"+str(self.__id_counter)
security.declareProtected(perm_view, 'get_list_item_name')
def get_list_item_name(self, REQUEST=None):
"""Return the name of Groupfolder."""
return self.get_name()
def get_name(self):
"""Return the name of the course."""
try:
if hasattr(self.parent().aq_base, 'toplevel'):
return self.parent().get_name()
except AttributeError:
pass
return WebtopFolder.WebtopFolder.get_name(self)
## security.declarePrivate('add_folder')
## def add_folder(self,name):
## """Implementation of add_folder_handler without http code."""
## f = GroupFolder(self,name)
## self._setObject(f.id,f)
## return f
security.declareProtected(perm_view, 'get_trash')
def get_trash(self):
"""Return trash (an instance of WebtopTrash)"""
#raise 'foo',str(self.aq_chain)
if hasattr(self.parent().aq_base, 'toplevel'):
return self.get_child('trash')
else:
return self.parent().get_trash()
Globals.InitializeClass(GroupFolder)
# EOF
iva-0.7.4/GroupFolderProxy.py 0000644 0000000 0000000 00000015122 10345616031 0017212 0 ustar viewcvs viewcvs 0000001 0000000 # -*- coding: utf-8
# $Id$
#
# Copyright 2001, 2002 by IVA Team and contributors
#
# This file is part of IVA.
#
# IVA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# IVA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with IVA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
__version__ = "$Revision$"[11:-2]
"""Contains class WebTopGroupFolderProxy."""
import Globals
import AccessControl
from common import course_level_roles
from common import reload_dtml, add_dtml
import WebtopFolder
from WebtopItem import WebtopItem
from common import perm_view, perm_edit, perm_manage, perm_add_lo
class GroupFolderProxy(
WebtopFolder.WebtopFolder,
):
"""GroupFolderProxy"""
meta_type = "GroupFolderProxy"
security = AccessControl.ClassSecurityInfo()
def __init__(self, parent, name, course_id):
"""Construct GroupFolderProxy"""
self.__course_id = course_id
WebtopItem.__init__(self, parent, name)
self.set_icon('images/group_folder')
security.declarePrivate('manage_afterAdd')
def manage_afterAdd(self,item,container):
"""..."""
WebtopFolder.WebtopFolder.manage_afterAdd(self, item, container)
for role in course_level_roles:
self._addRole(role)
from common import roles_admin, roles_staff, roles_user
from common import roles_student, roles_tutor, roles_teacher
security.declareProtected(perm_view, 'get_list_item_name')
def get_list_item_name(self, REQUEST=None):
"""Return the name of Groupfolder."""
if REQUEST:
uname = str(REQUEST.AUTHENTICATED_USER)
language = self.fle_users.get_child(uname).get_language()
else:
language = 'en'
d = {}
self.get_lang_given(('webtop',), d, language)
return self.get_name() + ' (' + d['L_shared'] + ')'
security.declareProtected(perm_view, 'get_trash')
def get_trash(self):
"""Return trash (an instance of WebtopTrash)"""
return self.__get_group_folder().get_trash()
security.declareProtected(perm_view, 'has_content')
def has_content(self):
"""Any WebtopItems in this folder?"""
return self.__get_group_folder().has_content()
security.declareProtected(perm_view, 'list_contents')
def list_contents(self, criteria=''):
"""Returns a list of all different WebtopItems in this folder."""
return self.__get_group_folder().list_contents()
security.declareProtected(perm_edit, 'add_folder_handler')
def add_folder_handler(
self, REQUEST, my_name,
submit = '', # form buttons
cancel = '', #
):
"""Handles the input from folder add form."""
return self.__get_group_folder().add_folder_handler(
REQUEST, my_name, submit, cancel)
security.declareProtected(perm_edit, 'add_link_handler')
def add_link_handler(
self, REQUEST, my_name, url,
type = '',
submit = '', # form buttons
cancel = '', #
back_link = '', # 'add link to webtop' feature outside webtop
):
"""Handles the input from link add form."""
return self.__get_group_folder().add_link_handler(
REQUEST, my_name, url, type, submit, cancel, back_link)
security.declareProtected(perm_edit, 'add_file_handler')
def add_file_handler(
self, REQUEST, my_name, file=None,
key = '',
submit = '', # form buttons
cancel = '', #
):
"""Handles the input from upload form."""
return self.__get_group_folder().add_file_handler(
REQUEST, my_name, file, key, submit, cancel)
security.declareProtected(perm_edit, 'add_memo_handler')
def add_memo_handler(
self,
REQUEST,
my_name,
contents,
submit='',
cancel=''):
"""Handles the input from memo add form."""
return self.__get_group_folder().add_memo_handler(
REQUEST, my_name, contents, submit, cancel)
security.declareProtected(perm_edit, 'form_handler')
def form_handler(
self,
item_ids=None,
copy='', cut='', paste='', remove='', rename='', # submit buttons
REQUEST=None):
"""Handles the input from folder default form:
item copy/cut/paste, remove and rename operations."""
return self.__get_group_folder().form_handler(
item_ids, copy, cut, paste, remove, rename, REQUEST)
security.declareProtected(perm_edit, 'rename_helper')
def rename_helper(self, expr1, expr2=None):
"""Helper function for DTML method wt_rename.dtml"""
return self.__get_group_folder().rename_helper(expr1, expr2)
security.declareProtected(perm_edit, 'rename_handler')
def rename_handler(
self, REQUEST,
item_id_list,
new_name_list,
submit = '', # form buttons
cancel = '', #
):
"""Handles rename_form submission."""
return self.__get_group_folder().rename_handler(
REQUEST, item_id_list, new_name_list, submit, cancel)
security.declareProtected(perm_view, 'get_size')
def get_size(self):
"""Return size of the object."""
return self.__get_group_folder().get_size()
security.declarePublic('get_child')
def get_child(self, _id):
"""Override get_child() of TraversableWrapper."""
return self.__get_group_folder().get_child(_id)
def is_proxy_for(self, group_folder):
return self.__get_group_folder() == group_folder
security.declarePublic('get_course_this_belongs_to')
def get_course_this_belongs_to(self):
"""Return the course to which the actual group folder belongs to."""
return self.courses.get_child(self.__course_id)
def __get_group_folder(self):
return self.courses.get_child(self.__course_id).gf
def __bobo_traverse__(self, REQUEST, entry_name=None):
if entry_name[:2] == 'gf' or entry_name == 'trash':
ob = getattr(self.__get_group_folder(), entry_name).aq_base
return ob.__of__(self)
else:
return getattr(self, entry_name)
Globals.InitializeClass(GroupFolderProxy)
#EOF
iva-0.7.4/INSTALL 0000644 0000000 0000000 00000014513 10345616031 0014402 0 ustar viewcvs viewcvs 0000001 0000000 INSTRUCTIONS TO INSTALL IVA 0.7.4
===================================
IVA Installation guide
Required software:
Zope http://www.zope.org (prefer Zope 2.8)
Recommended software:
PyXML http://pyxml.sourceforge.net/
PlacelessTranslationService http://sourceforge.net/projects/collective/
PIL http://www.pythonware.com/products/pil/ (with jpeg support)
jpeg-6b libraries can be found at ftp://ftp.uu.net/graphics/jpeg/
ZWiki http://www.zwiki.org (Currently, ZWiki 0.36.2 recommended)
CMF http://cmf.zope.org (Very optional)
BTreeFolders2 http://hathawaymix.org/Software/BTreeFolder2/BTreeFolder2-1.0.1.tar.gz
Software needed by WordMaps:
TeX 3.14159 (Web2C 7.3.1)
LaTeX2e <2000/06/01> (Included with most TeX distributions)
dvips dvipsk 5.86 (Included with most TeX distributions)
GhostScript 6.52 (2001-10-20)
Netpbm 9.24
If you don't install these then only one little part of wordmaps don't work otherwise it's ok.
General installation procedure consists of four steps:
See that your system has installed Python (preferrably ver.2.3) and Zope (preferrably ver. 2.8.1).
Install IVA product on your Zope server.
Install an instance of IVA on your Zope server.
Configure IVA
If you have already Zope installed on your system, skip the step 1 (however, need to check the version compatibility as with Python).
Detailed guidelines for installation:
Step 1. Install Zope and all required software
Download Zope from http://www.zope.org/Products
Please see zope installation instructions.
Install recommended software. You'll have to consult with each package's installation instructions but
general rule: Zope products go into zope's products directory and others are installed into system.
Note that IVA works fine without PIL, PyXML and CMF but then some features may give errors or are disabled.
PIL is used in various places all over IVA, PyXML is only for import-export functionality.
Step 2. Install IVA product
Download the latest IVA tarball at http://www.htk.tpu.ee/iva
Unpack it to a temporary directory - tar xfzv iva-0.7.1.tgz
Move created directories to zope products directory (typically /usr/local/zope/lib/python/Products)
Restart Zope: inside the Zope Management Interface, or ZMI (typically http://localhost:8080/manage), click on Restart button under Control Panel.
Step 3. Install an instance of IVA
Log into Zope Management Interface (typically http://localhost:8080/manage) as manager.
Create an instance of IVA by selecting IVA from pull-down menu Select type to add...
Select settings for new IVA instance and click Add.
Add users to your IVA system:
Go to Course management > Add users.
Enter the list of usernames and system generates the passwords. If a proposed username already exists on this Zope server, IVA adds a number to it (e.g. john1).
Create a course: go to Course management and create a new course by clicking on the Add course link.
Add users to course: Enter the course environment in Lobby if aren't already. Then go to Management area and clock User Management link in the left menu. Enroll selected users to the course as teachers (or students). Teachers can later add (more) students or teachers by themselves.
Step 4.
Setting up sessions.
--------------------
From IVA 0.7, statistics machinery is changed and is using session to store user actions in IVA.
First statistics is stored in user session. When user logs out or closes browser it's session hangs around
until it times out and then it will be stored. By default Zope will just drop timed out session so you'll
have to set it up.
1. First you'll have to create python script in zope. Add Script (Python) from dropdown menu anywhere you like.
I'm using this script:
Parameter List: sess,sessContainer
--- Script start ---
iva_paths = sess.get('iva_paths', [])
if iva_paths:
# it's IVA. otherwise it's something else and should be handled differently
for x in iva_paths:
path = x.split('/')
iva = context
for y in path:
if not y:
continue
iva = getattr(iva, y)
iva.Statistics.saveStats(sess.get(x, {}))
--- Script end ---
You have to set proxy role to Manager in Proxy tab
Note that you have to keep indent otherwise it will not work.
If you already have some session delete script then you'll propably know what to do.
2. In /temp_folder/session_data fill in "Script to call when objects are deleted" box. Put the created script's full path in there.
From there you can also change the value in minutes in which the session is expired and deleted ( and data populated to IVA )
3. temp_folder and session_data are objects that aren't saved when zope restarts so your settings will also be lost.
To make settings persistent, put them in zope.conf.
Directives session-delete-notify-script-path, session-timeout-minutes, session-resolution-seconds and maximum-number-of-session-objects are then ones you're propably interested in. don't set maximum-number-of-session-objects too low or you'll lose data.
Edit textogif.py.
-----------------
Edit textogif.py file inside iva directory and modify these statements as needed.
latexcommand="/usr/local/teTeX/bin/i686-pc-linux-gnu/latex " - where is latex command
pscommand="/usr/local/teTeX/bin/i686-pc-linux-gnu/dvips " - where is dvips command
gscommand="/usr/local/bin/gs " - where is gs command
netpbmdir="/usr/local/netpbm/bin/" - where are netpbm commands
First three are commands and if your system has these you can find them with 'which' command.
netpbmdir is a place where netpbm binaries are located. In most cases it's /usr/bin/ if you cannot
find it, try to locate some binaries eg. ppmtogif, pngtopnm, pnmtogif or giftopnm.
You can use which or find command here. Note that directory is needed here, with trailing slash.
Setting up cronjob
------------------
1. In util folder you find script "save_iva_stats".
Modify this script to match your set up.
2. Keep in mind that this file will contain manager's password so you should most propably copy this file somewhere so that unauthorized persons cannot view it's contents.
3. Then set up a cronjob so that this script would be executed periodically.
4. You should always try to run this script before restarting or shuting down zope server.
5. For example, a crontab line which invokes python script in every 15 minutes.
*/15 * * * * root /etc/save_iva_stats
In this example, I've copied this script into /etc folder and gave permissions 0750 ( chmod 0750 save_iva_stats)
iva-0.7.4/ITempObjectManager.py 0000644 0000000 0000000 00000002556 10345616031 0017367 0 ustar viewcvs viewcvs 0000001 0000000 # -*- coding: utf-8
# $Id$
#
# Copyright 2001, 2002 by IVA Team and contributors
#
# This file is part of IVA.
#
# IVA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# IVA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with IVA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""Contains an interface for TempObjectManager."""
__version__ = "$Revision$"[11:-2]
from Interface import Base
class ITempObjectManager(Base):
"""Interface for TempObjectManater"""
def add_tmp_object(self, ob_ref):
"""Store given object as a temp object."""
def get_tmp_object(self, toid):
"""Return reference to given (id) temporary object."""
def remove_tmp_object(self, toid):
"""Remove given (id) temporary object."""
# retval: [toid1, toid2, toid3, ...]
def get_tmp_object_ids(self):
"""Return list of temporary object ids."""
# EOF
iva-0.7.4/IUserInfo.py 0000644 0000000 0000000 00000006534 10345616031 0015572 0 ustar viewcvs viewcvs 0000001 0000000 # -*- coding: utf-8
# $Id$
#
# Copyright 2001, 2002 by IVA Team and contributors
#
# This file is part of IVA.
#
# IVA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# IVA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with IVA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""Contains an interface for UserInfo."""
__version__ = "$Revision$"[11:-2]
from Interface import Base
class IUserInfo(Base):
"""Interface for UserInfo."""
def set_first_name(self, name):
"""Set the first name of the user."""
def set_last_name(self, name):
"""Set the last name of the user."""
def set_email(self, email):
"""Set the email address of the user."""
def set_language(self, language):
"""Set the users language. (Languages are handled by Language.py)."""
def set_photo(self, photo):
"""Set the user photo."""
def set_group(self, group):
"""Set the users group."""
def set_address(self, address):
"""Set the users address."""
def set_country(self, country):
"""Set the users country."""
def set_homepage(self, homepage):
"""Set the users homepage."""
def set_phone(self, phone):
"""Set the phonenumber of the user."""
def set_gsm(self, gsm):
"""Set the gsm (mobile phone) number of the user."""
def set_quote(self, quote):
"""Set the user quote."""
def set_background(self, background):
"""Set the user background."""
def set_personal_interests(self, p_i):
"""Set the users personal interests."""
def set_professional_interests(self, p_i):
"""Set the users professional interests."""
def get_first_name(self, name):
"""Get the first name of the user."""
def get_last_name(self, name):
"""Get the last name of the user."""
def get_email(self, email):
"""Get the email address of the user."""
def get_language(self, language):
"""Get the users language."""
def get_photo_url(self):
"""Get the url to user's photo."""
def get_photo_tag(self):
"""Get photo tag"""
def get_group(self, group):
"""Get the users group."""
def get_address(self, address):
"""Get the users address."""
def get_country(self, country):
"""Get the users country."""
def get_homepage(self, homepage):
"""Get the users homepage."""
def get_phone(self, phone):
"""Get the phonenumber of the user."""
def get_gsm(self, gsm):
"""Get the gsm (mobile phone) number of the user."""
def get_quote(self, quote):
"""Get the user quote."""
def get_background(self, background):
"""Get the user background."""
def get_personal_interests(self, p_i):
"""Get the users personal interests."""
def get_professional_interests(self, p_i):
"""Get the users professional interests."""
# EOF
iva-0.7.4/ImportExport.py 0000644 0000000 0000000 00000154676 10345616031 0016416 0 ustar viewcvs viewcvs 0000001 0000000 # -*- coding: utf-8
# $Id$
#
# Copyright 2001, 2002 by IVA Team and contributors
#
# This file is part of IVA.
#
# IVA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# IVA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with IVA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
__version__ = "$Revision$"[11:-2]
"""Contains classes responsible for importing and exporting the data to and from an FLE installation. Uses XML for data storage."""
import sys, time
import xml.dom.minidom
from xml.dom.minidom import Document
import zipfile
from types import UnicodeType
from common import FakeRequest, FakeUpload
class Counter:
def __init__(self):
self.__counter=0
def get_next_counter(self):
self.__counter+=1
return self.__counter
def get_counter(self):
"""Returns the value of the automatic counter."""
return self.__counter
def set_counter(self,val):
self.__counter=val
class DataTable(Counter):
"""Auxiliary class for storing binary data needed for
XML export."""
def __init__(self):
Counter.__init__(self)
self.__cache={}
self.names = []
def get_size(self):
"""Returns the size of the binary cache (in items)."""
return len(self.__cache)
def storeData(self,data,nimi='data',suffix=''):
import random
"""Stores a new binary data into the storage and
assigns it a unique name. The name is returned."""
#name = 'data'+str(self.get_next_counter())
name = nimi+"_"+str(random.randint(1,9999))+"_"+str(random.randint(1,9999))+suffix
self.names.append(name)
self.__cache[name]=data
return name
def restoreData(self,name,data):
"""Re-stores binary data into the storage. The name
is given as a parameter, but should be of the form
'dataN' where N is an integer (of any length). The
restoration process should make sure that all numbers
from 1 to the highest number are filled."""
self.__cache[name]=data
#num = int(name[4:])
#Vahur
num = int(4)
if self.get_counter()',xmlstring).group(1)
print "Transforming from %s to utf-8..." % encoding
xmlstring = unicode(xmlstring,encoding).encode("utf-8")
self.dom = xml.dom.minidom.parseString(xmlstring)
self.root = self.dom.firstChild
for name in zip.namelist():
#if name[:4]=='data':
if not re.search('imsmanifest.xml',name):
self.binarydata.restoreData(name,zip.read(name))
zip.close()
def exportGlobalTypes(self,globals):
"""Exports globally available knowledge types."""
elem = self.dom.createElement("GlobalKnowledgeTypes")
for set in globals.objectValues('ThinkingTypeSet'):
elem.appendChild(self.exportTypeSet(set))
if hasattr(globals,'tmp_objects'):
for set in globals.tmp_objects.objectValues('ThinkingTypeSet'):
elem.appendChild(self.exportTypeSet(set))
return elem
def importGlobalTypes(self,elem,fle_root):
"""Imports globally available knowledge types."""
for telem in elem.childNodes:
self.importTypeSet(telem,fle_root.typesets)
def exportKB(self,courses):
"""Exports the entire knowledge building.
Parameter should point to the CourseManager."""
kb = self.dom.createElement("KnowledgeBuilding")
for c in courses.get_children('Course'):
kb.appendChild(self.exportCourse(c))
return kb
def importKB(self,elem,fle_root):
"""Import knowledge building.
- elem: The XML element containing the data.
- obj: The Zope object containing CourseManager."""
# All children should be course objects
for child in elem.getElementsByTagName('Course'):
self.importCourse(child,fle_root.courses)
#get_transaction().commit()
def exportCourse(self,course):
"""Exports the given course."""
elem = self.dom.createElement("Course")
name = course.get_name()
make_attr(elem,"Name",name)
make_attr(elem,"Teacher",course.get_teacher())
make_attr(elem,"Organisation",course.get_organisation())
make_attr(elem,"StartDate",str(int(round(course.get_start_date()))))
make_attr(elem,"EndDate",str(int(round(course.get_end_date()))))
if course.get_description():
desc=self.dom.createElement("Descr")
make_text(desc,course.get_description())
elem.appendChild(desc)
if course.get_methods():
meth = self.dom.createElement("Methods")
make_text(meth,course.get_methods())
elem.appendChild(meth)
## for set in course.objectValues('ThinkingTypeSet'):
## elem.appendChild(self.exportTypeSet(set))
for fol in course.get_children('GroupFolder'):
elem.appendChild(self.exportGroupFolder(fol))
for ctx in course.get_children("CourseContext"):
elem.appendChild(self.exportContext(ctx))
return elem
def importCourse(self,elem,courses):
"""Imports a course under the given CourseManager."""
id = courses.add_course_impl(get_attr(elem,'Teacher'))
course = courses.get_child(str(id))
descr = ''
if elem.getElementsByTagName("Descr"):
descr = get_text(elem.getElementsByTagName("Descr")[0])
methods = ''
if elem.getElementsByTagName("Methods"):
methods = get_text(elem.getElementsByTagName("Methods")[0])
course.update(
get_attr(elem,"Name"),
descr,
get_attr(elem,"Organisation"),
methods,
int(get_attr(elem,"StartDate")),
int(get_attr(elem,"EndDate")))
# Set local roles to users
for uelem in elem.ownerDocument.firstChild.getElementsByTagName("User"):
try:
user = course.fle_users.get_user_info(
get_attr(uelem,"Name"))
except:
continue # If the user doesn't exist, we'll just skip
for celem in uelem.getElementsByTagName("ACL")[0].\
getElementsByTagName("CourseRole"):
if get_attr(celem,"CourseName") != \
course.get_name():
continue
roles = []
for relem in celem.childNodes:
roles.append(get_attr(relem,"Name"))
if roles:
course.set_roles(user.get_uname(),tuple(roles))
for fol in elem.childNodes:
if fol.nodeName != 'GroupFolder':
continue
self.importGroupFolder(fol,course.__of__(courses),toplevel=1)
for ctx in elem.childNodes:
if ctx.nodeName != 'Context':
continue
self.importContext(ctx,course.__of__(courses))
def exportContext(self,ctx,startonly=0):
"""Exports the given course context."""
elem = self.dom.createElement("Context")
make_attr(elem,"Name",ctx.get_name())
make_attr(elem,"Author",ctx.get_author())
descr = self.dom.createElement("Descr")
make_text(descr,ctx.get_description())
elem.appendChild(descr)
descr = self.dom.createElement("LongDescr")
make_text(descr,ctx.get_long_description())
elem.appendChild(descr)
elem.appendChild(self.exportTypeSet(ctx.get_thinking_type_set()))
for fol in ctx.get_children('GroupFolder'):
elem.appendChild(self.exportGroupFolder(fol))
for note in ctx.get_children('Note'):
elem.appendChild(self.exportNote(note,startonly))
return elem
def importContext(self,elem,course):
"""Imports a context into a course."""
desc = get_text(elem.getElementsByTagName("Descr")[0])
ldesc = get_text(elem.getElementsByTagName("LongDescr")[0])
from CourseContext import CourseContext
ctx = CourseContext(
course,
get_attr(elem,"Name"),
desc,
ldesc,
None, # tt_set not given
get_attr(elem,"Author"))
course._setObject(ctx.get_id(),ctx)
set = elem.getElementsByTagName('KnowledgeTypeSet')[0]
self.importTypeSet(set,ctx.__of__(course))
ctx._tt_set_id=get_attr(set,'ID')
for nelem in elem.childNodes:
if nelem.nodeName != 'GroupFolder':
continue
self.importGroupFolder(nelem,ctx.__of__(course),toplevel=1)
for nelem in elem.childNodes:
if nelem.nodeName != 'Note':
continue
self.importNote(nelem,ctx.__of__(course))
def exportNote(self,note,startonly):
"""Exports the given note."""
if not hasattr(note,'censored'):
note.censored=0
elem = self.dom.createElement("Note")
make_attr(elem,"KnowledgeTypeRef",note.get_tt_id())
make_attr(elem,"ID",note.get_id())
make_attr(elem,"Date",str(int(round(note.get_creation_time()))))
if hasattr(note,'get_real_subject'):
make_attr(elem,"Subject",note.get_real_subject())
else:
make_attr(elem,"Subject",note.get_subject())
make_attr(elem,"Author",note.get_author())
if hasattr(note,'censored') and note.censored:
make_attr(elem,"CensoredBy",note.censorer)
make_attr(elem,"CensoredTime",str(note.censored))
body = self.dom.createElement("NoteBody")
make_text(body,note.get_body())
elem.appendChild(body)
reader_list = self.dom.createElement("ReaderList")
try:
if not startonly:
for (uname, date_data) in note.get_readers_with_all_dates().items():
reader = self.dom.createElement("Reader")
make_attr(reader,"Name", uname)
try:
for date in date_data['when']:
d = self.dom.createElement("Event")
make_attr(d,"Type","ReadTime")
make_attr(d,"Value",str(date))
reader.appendChild(d)
except TypeError:
# This will come up if the 'when' item isn't a list
d = self.dom.createElement("Event")
make_attr(d,"Type","ReadCount")
make_attr(d,"Value",str(date_data))
reader.appendChild(d)
reader_list.appendChild(reader)
except AttributeError:
# This will rise if Thread.py is an old versio.
# In this case we'll just have to skip the reader information.
pass
elem.appendChild(reader_list)
if note.get_url()!='':
link = self.dom.createElement("Link")
make_attr(link,"Src",note.get_url())
make_attr(link,"Name",note.get_url_name())
elem.appendChild(link)
if note.has_image():
name = self.binarydata.storeData(
note.get_image_data())
link = self.dom.createElement("DataLink")
make_attr(link,"LocalName",name)
make_attr(link,
"ContentType",
note.get_image_content_type())
make_attr(link,"Name",note.get_image_name())
elem.appendChild(link)
if not startonly:
for reply in note.get_children('Note'):
elem.appendChild(self.exportNote(reply,startonly))
return elem
def importNote(self,elem,parent):
"""Imports a note into a context or note."""
s_time=time.time()
url=''
url_name=''
image=None
image_name=''
for lelem in elem.childNodes:
if lelem.nodeName=="Link":
url=get_attr(lelem,"Src")
url_name=get_attr(lelem,"Name")
break
for delem in elem.childNodes:
if delem.nodeName=='DataLink':
image_data=self.binarydata.getData(get_attr(delem,"LocalName"),self.prefix)
image_name=get_attr(delem,"Name")
image_content_type = get_attr(delem,"ContentType")
image = FakeUpload('image',image_data,image_content_type)
break
self.timecounters[0]+=(time.time()-s_time)
s_time=time.time()
# We suppose that each Note has a NoteBody.
body = get_text(elem.getElementsByTagName("NoteBody")[0])
## body=''
## for line in elem.getElementsByTagName("NoteBody")[0].childNodes:
## snippet = to_utf8(line.nodeValue)
## if snippet == '\n':
## body += '\r\n'
## else:
## body += snippet
self.timecounters[1]+=(time.time()-s_time)
s_time=time.time()
note = parent.add_reply(
get_attr(elem,"KnowledgeTypeRef"),
get_attr(elem,"Author"),
get_attr(elem,"Subject"),
body,
url,
url_name,
image,
image_name,
creation_time=float(get_attr(elem,"Date")))
self.timecounters[2]+=(time.time()-s_time)
s_time=time.time()
note.set_temporary(0)
parent._setObject(note.id,note)
note=note.__of__(parent)
self.idmap[get_attr(elem,"ID")]=note
self.timecounters[3]+=(time.time()-s_time)
s_time=time.time()
censored = get_attr(elem,"CensoredTime")
if censored:
note.do_censor(float(str(censored)),
get_attr(elem,"CensoredBy"))
# readers (read/unread status)
for rlelem in elem.childNodes:
if rlelem.nodeName == 'ReaderList':
for relem in rlelem.childNodes:
uname = get_attr(relem,'Name')
dates = []
for delem in relem.childNodes:
if delem.nodeName == 'Event' and \
get_attr(delem,"Type")=="ReadTime":
dates.append(float(get_attr(delem,"Value")))
elif delem.nodeName == 'Event' and \
get_attr(delem,"Type")=="ReadCount":
dates.append(time.time())
note.set_exported_reader(uname, dates)
self.timecounters[4]+=(time.time()-s_time)
s_time=time.time()
#get_transaction().commit()
for nelem in elem.childNodes:
if nelem.nodeName != 'Note':
continue
self.importNote(nelem,note.__of__(parent))
def exportTypeSet(self,set):
"""Exports the given knowledgetypeset."""
elem = self.dom.createElement("KnowledgeTypeSet")
make_attr(elem,"ID", set.get_id())
make_attr(elem,"Name", set.get_name())
if set.is_in_tmp(set):
make_attr(elem,"Status",'Unfinished')
delem = self.dom.createElement("Description")
make_text(delem,set.get_description())
elem.appendChild(delem)
starting = self.dom.createElement("StartingTypes")
for start in set.get_thinking_type_thread_start():
starting.appendChild(self.exportTypeRef(start))
elem.appendChild(starting)
for type in set.get_thinking_types():
felem = self.dom.createElement("FollowupRule")
ffelem = self.dom.createElement("KnowledgeTypeRef")
make_attr(ffelem,"ID-REF",type.get_id())
felem.appendChild(ffelem)
for followup in set.get_possible_follow_ups(type):
ffelem = self.dom.createElement("KnowledgeTypeRef")
make_attr(ffelem,"ID-REF", followup.get_id())
felem.appendChild(ffelem)
elem.appendChild(felem)
for type in set.get_thinking_types():
elem.appendChild(self.exportType(type))
return elem
def importTypeSet(self,elem,parent,force_update=0):
"""Imports a knowledge type set into a ThinkingTypeSetManager
or a course."""
from ThinkingTypeSet import ThinkingTypeSet
from ThinkingType import ThinkingType
my_id = get_attr(elem,"ID")
# If the ID of this set is not of the form "ttsNN", then it's a
# predefined set (installed from the file system).
# We check if the set by the same ID already is created and:
# if the set is of the form "ttsNN", we change its id
# else if force_update is activated, we remove the previous version
# else we skip this import.
if my_id in parent.objectIds('ThinkingTypeSet'):
if my_id[:3]=='tts':
# We must assume now that the parent
# is a ThinkingTypeSetManager. Importing several sets
# into course contexts shouldn't happen.
my_id = parent.get_new_valid_tts_id()
elif force_update:
parent.manage_delObjects(my_id)
else:
return
types = []
for telem in elem.getElementsByTagName("KnowledgeType"):
try:
desc=get_text(telem.getElementsByTagName("Description")[0])
except IndexError:
desc=''
try:
checklist=get_text(telem.getElementsByTagName("Checklist")[0])
except IndexError:
checklist=''
try:
phrase=get_text(telem.getElementsByTagName("StartingPhrase")[0])
except IndexError:
phrase=''
type = {
'id': get_attr(telem,"ID"),
'name': get_attr(telem,"Name"),
'starting_phrase': phrase,
'description': desc,
'colour': get_attr(telem,"Colour"),
'icon': None,
# No image file - we'll store the data directly
'icondata': self.binarydata.getData(get_attr(telem.getElementsByTagName("Icon")[0],"LocalName"),self.prefix),
'checklist': checklist,
}
types.append(type)
starters = []
selem = elem.getElementsByTagName("StartingTypes")[0]
for stelem in selem.childNodes:
starters.append(get_attr(stelem,"ID-REF"))
relations = {}
for felem in elem.getElementsByTagName("FollowupRule"):
orig = None
list = []
for ffelem in felem.childNodes:
if orig:
list.append(get_attr(ffelem,"ID-REF"))
else:
orig=get_attr(ffelem,"ID-REF")
relations[orig]=list
descr = get_text(elem.getElementsByTagName("Description")[0])
tts = ThinkingTypeSet(
my_id,
get_attr(elem,"Name"),
descr,
types, # list of pairs (name,obj)
starters, # list of names
relations) # list of pairs (orig_name,reply_name)
parent._setObject(
my_id,
tts)
if get_attr(elem,"Status")=='Unfinished':
parent.move_to_tmp(tts)
#get_transaction().commit()
def exportTypeRef(self,type):
"""Exports the given knowledgetypeset reference."""
elem = self.dom.createElement("KnowledgeTypeRef")
make_attr(elem,"ID-REF",type.get_id())
return elem
def exportType(self,type):
"""Exports the given knowledgetype."""
elem = self.dom.createElement("KnowledgeType")
make_attr(elem,"ID",type.get_id())
make_attr(elem,"Name",type.get_name())
make_attr(elem,"Colour",type.get_colour())
icon = self.dom.createElement("Icon")
make_attr(icon,
"LocalName",
self.binarydata.storeData(type.get_icon().data))
make_attr(icon,"ContentType",type.get_icon().getContentType())
elem.appendChild(icon)
expl = self.dom.createElement("StartingPhrase")
make_text(expl,type.get_starting_phrase())
elem.appendChild(expl)
instr = self.dom.createElement("Description")
make_text(instr,type.get_description())
elem.appendChild(instr)
cl = self.dom.createElement("Checklist")
make_text(cl,type.get_checklist())
elem.appendChild(cl)
return elem
def exportJamming(self, courses):
"""Exports the entire jamming stuff.
Parameter should point to the CourseManager."""
jamming = self.dom.createElement('Jamming')
try:
#for c in courses.get_children('Course'):
for js in courses.get_child('jamming').get_children('JamSession'):
jamming.appendChild(self.exportJamSession(courses, js))
return jamming
except AttributeError:
# We are exporting old FLE version where Course
# objects don't have Jamming object.
return None
def importJamming(self, elem, course):
"""Import Jamming."""
for js in elem.getElementsByTagName('JamSession'):
self.importJamSession(js, course)
#get_transaction().commit()
def exportJamSession(self, course, jam_session,startonly=0):
"""Export the given jam session (on a given course)."""
elem = self.dom.createElement("JamSession")
make_attr(elem, 'CourseName', course.get_name())
make_attr(elem, 'Name', jam_session.get_name())
make_attr(elem, 'Type', jam_session.get_type())
make_attr(elem, 'Descr', jam_session.get_description())
make_attr(elem, 'ID', jam_session.get_id())
make_attr(elem, 'StartingArtefactIDRef',
jam_session.get_starting_artefact_id())
for ja in jam_session.get_children('JamArtefact'):
if startonly:
if ja.get_id() == jam_session.get_starting_artefact_id():
elem.appendChild(self.exportJamArtefact(ja))
else:
elem.appendChild(self.exportJamArtefact(ja))
return elem
def importJamSession(self, elem, courses):
"""Import a jam session (under jamming (under course)) under
the given CourseManager."""
#course_name = get_attr(elem, 'CourseName')
#for course in courses.get_courses():
# if course.get_name() == course_name:
jamming = courses.get_child('jamming')
# break
starting_artefact_id = get_attr(elem, 'StartingArtefactIDRef')
for ja_elem in elem.childNodes:
# if ja_elem.nodeName == 'Artefact' and \
if ja_elem.nodeName == 'JamArtefact' and \
get_attr(ja_elem, 'ID') == starting_artefact_id:
ja_name = get_attr(ja_elem, 'Name')
for delem in ja_elem.childNodes:
if delem.nodeName == 'DataLink':
ja_data = self.binarydata.getData(
get_attr(delem, 'LocalName'),self.prefix)
ja_content_type = get_attr(delem, 'ContentType')
break
break
# Create a jam session with starting artefact.
jam_session = jamming.form_handler(
get_attr(elem, 'Name'),
get_attr(elem, 'Type'),
get_attr(elem, 'Descr'),
ja_name,
FakeUpload('some name', ja_data, ja_content_type),
submit=1,
)
self.idmap[get_attr(elem, 'ID')] = jam_session
# Add annotations to the starting artefact.
starting_artefact = jam_session.get_children('JamArtefact')[0]
self.idmap[get_attr(ja_elem, 'ID')] = starting_artefact
for e in ja_elem.childNodes:
if e.nodeName == 'Annotations':
i = 0
for a in e.childNodes:
if a.nodeName == 'Annotation':
starting_artefact.add_annotation(
get_attr(a, 'Author'),
float(get_attr(a, 'Date')),
get_text(a.getElementsByTagName('Text')[0]))
censored = get_attr(a, 'Censored')
if censored:
starting_artefact.do_censor_annotations((i,), float(censored), get_attr(a, 'Censorer'))
i += 1
break
# readers (read/unread status of the starting artefact)
for rlelem in ja_elem.childNodes:
if rlelem.nodeName == 'ReaderList':
for relem in rlelem.childNodes:
uname = get_attr(relem,'Name')
dates = []
for delem in relem.childNodes:
if delem.nodeName == 'Event' and \
get_attr(delem,"Type")=="ReadTime":
dates.append(float(get_attr(delem,"Value")))
elif delem.nodeName == 'Event' and \
get_attr(delem,"Type")=="ReadCount":
dates.append(time.time())
starting_artefact.set_exported_reader(uname, dates)
# Import the rest of the jam artefacts in this jam session
for ja_elem in elem.childNodes:
if ja_elem.nodeName == 'JamArtefact' and \
get_attr(ja_elem, 'ID') != starting_artefact_id:
self.importJamArtefact(ja_elem, jam_session)
# set parent ids
for ja_elem in elem.childNodes:
id_ = get_attr(ja_elem, 'ID')
if ja_elem.nodeName == 'JamArtefact' and \
id_ != starting_artefact_id:
parent_ids = []
for pelem in ja_elem.childNodes:
if pelem.nodeName == 'Parents':
for prelem in pelem.childNodes:
if prelem.nodeName == 'ParentRef':
parent_ids.append(get_attr(prelem, 'ID-REF'))
break
real_parent_ids = []
for pid in parent_ids:
real_parent_ids.append(self.idmap[pid].get_id())
self.idmap[id_].set_parent_ids(real_parent_ids)
jam_session.update_drawing()
def exportJamArtefact(self, jam_artefact):
"""Export the given JamArtefact."""
elem = self.dom.createElement('JamArtefact')
make_attr(elem, 'Name', jam_artefact.get_real_name())
make_attr(elem, 'Author', str(jam_artefact.get_author()))
make_attr(elem, 'ID', jam_artefact.get_id())
annotations = self.dom.createElement('Annotations')
for tple \
in jam_artefact.get_real_annotations():
try:
(uname, a_time, a_text, censored, censorer) = tple
except ValueError:
# This comes up with versions 1.1betaX
(uname, a_time, a_text) = tple
censored=0
censorer=''
a_elem = self.dom.createElement('Annotation')
make_attr(a_elem, 'Author', uname)
make_attr(a_elem, 'Date', repr(a_time))
text = self.dom.createElement('Text')
make_text(text, a_text)
a_elem.appendChild(text)
make_attr(a_elem, 'Censored', repr(censored))
make_attr(a_elem, 'Censorer', censorer)
annotations.appendChild(a_elem)
elem.appendChild(annotations)
parents = self.dom.createElement('Parents')
for p_id in jam_artefact.get_parent_ids():
p_elem = self.dom.createElement('ParentRef')
make_attr(p_elem, 'ID-REF', p_id)
parents.appendChild(p_elem)
elem.appendChild(parents)
name = self.binarydata.storeData(jam_artefact.get_real_data())
link = self.dom.createElement('DataLink')
make_attr(link, 'LocalName', name)
make_attr(link, 'ContentType', jam_artefact.get_content_type())
elem.appendChild(link)
reader_list = self.dom.createElement("ReaderList")
for (uname, date_data) in \
jam_artefact.get_readers_with_all_dates().items():
reader = self.dom.createElement("Reader")
make_attr(reader,"Name", uname)
try:
for date in date_data['when']:
d = self.dom.createElement("Event")
make_attr(d,"Type","ReadTime")
make_attr(d,"Value",repr(date))
reader.appendChild(d)
except TypeError:
# This will come up if the 'when' item isn't a list
d = self.dom.createElement("Event")
make_attr(d,"Type","ReadCount")
make_attr(d,"Value",repr(date_data))
reader.appendChild(d)
reader_list.appendChild(reader)
elem.appendChild(reader_list)
return elem
def importJamArtefact(self, ja_elem, jam_session):
"""Import a jam artefact under given jam session."""
for delem in ja_elem.childNodes:
if delem.nodeName == 'DataLink':
ja_data = self.binarydata.getData(
get_attr(delem, 'LocalName'),self.prefix)
ja_content_type = get_attr(delem, 'ContentType')
break
artefact = jam_session.add_artefact(get_attr(ja_elem, 'Name'),
ja_data,
ja_content_type,
'temp value')
self.idmap[get_attr(ja_elem, 'ID')] = artefact
for e in ja_elem.childNodes:
if e.nodeName == 'Annotations':
i = 0
for a in e.childNodes:
if a.nodeName == 'Annotation':
artefact.add_annotation(
get_attr(a, 'Author'),
float(get_attr(a, 'Date')),
get_text(a.getElementsByTagName('Text')[0]))
censored = get_attr(a, 'Censored')
if censored:
artefact.do_censor_annotations((i,), float(censored), get_attr(a, 'Censorer'))
i += 1
break
# readers (read/unread status)
for rlelem in ja_elem.childNodes:
if rlelem.nodeName == 'ReaderList':
for relem in rlelem.childNodes:
uname = get_attr(relem,'Name')
dates = []
for delem in relem.childNodes:
if delem.nodeName == 'Event' and \
get_attr(delem,"Type")=="ReadTime":
dates.append(float(get_attr(delem,"Value")))
elif delem.nodeName == 'Event' and \
get_attr(delem,"Type")=="ReadCount":
dates.append(time.time())
artefact.set_exported_reader(uname, dates)
def exportUsers(self,users):
"""Exports FLE users. Parameter should point to the
UserManager."""
elem = self.dom.createElement("Users")
for user in users.objectValues('UserInfo'):
elem.appendChild(self.exportUser(user))
return elem
def exportUserList(self,userlist,do_webtop=0,do_passwd=0):
"""Export a given set of FLE users. Parameter should be
a list of UserInfo objects. By default doesn't export
the webtop or the user's password."""
elem = self.dom.createElement("Users")
for user in userlist:
elem.appendChild(self.exportUser(user,do_webtop,do_passwd))
#get_transaction().commit()
return elem
def importUsers(self,elem,fle_root):
"""Import all users into the given FLE root."""
for user in elem.childNodes:
self.importUser(user,fle_root.fle_users,do_user=1,do_webtop=0)
#get_transaction().commit()
def importUsersWebtops(self,elem,fle_root):
"""Import all users into the given FLE root."""
for user in elem.childNodes:
self.importUser(user,fle_root.fle_users,do_user=0,do_webtop=1)
def exportUserACL(self,fle_user,do_passwd=1):
"""Export a user's Zope ACL information.
User parameter is an FLE UserInfo instance."""
elem = self.dom.createElement("ACL")
#user = fle_user.acl_users.getUser(fle_user.get_uname())
if do_passwd:
try:
passwd = fle_user.getPassword()
except:
passwd = fle_user.getFrozenPassword()
make_attr(elem,"Password",passwd)
try:
domains = fle_user.getDomains()
except:
domains = fle_user.getFrozenDomains()
for dom in domains:
delem = self.dom.createElement("Domain")
dmake_attr(elem,"Name",dom)
elem.appendChild(delem)
if fle_user.is_frozen():
roles = fle_user.getFrozenRoles()
else:
roles = fle_user.getRoles()
for role in roles:
# Skip role 'Authenticated' since that is added
# to a user's roles supefluously and does not need
# to be saved.
if role == 'Authenticated':
continue
relem = self.dom.createElement("Role")
make_attr(relem,"Name",role)
elem.appendChild(relem)
for course in fle_user.courses.objectValues('Course'):
roles = fle_user.getRolesInObject(course)
relem = self.dom.createElement("CourseRole")
make_attr(relem,"CourseName",course.get_name())
for role in roles:
relem2 = self.dom.createElement("Role")
make_attr(relem2,"Name",role)
relem.appendChild(relem2)
elem.appendChild(relem)
return elem
def retrieveUserACL(self,elem):
"""Retrieves a user's ACL information.
Returns password, domains and roles."""
# If the Password attribute doesn't exist, will return
# an empty string (at least xml.dom.minidom does), which
# is ok.
password = get_attr(elem,"Password")
domains = []
for delem in elem.getElementsByTagName("Domain"):
domains.append(get_attr(delem,"Name"))
roles = []
for delem in elem.childNodes:
if delem.nodeName != 'Role':
continue
roles.append(get_attr(delem,"Name"))
return (password, domains, roles)
def exportUser(self,user,do_webtop=1,do_passwd=1):
"""Exports the given user."""
elem = self.dom.createElement("User")
elem.appendChild(self.exportUserACL(user,do_passwd))
make_attr(elem,"Name",user.get_uname())
make_attr(elem,"FirstName",user.get_first_name())
make_attr(elem,"LastName",user.get_last_name())
make_attr(elem,"Organisation",user.get_organization())
make_attr(elem,"Lang",user.get_language())
make_attr(elem,"Email",user.get_email())
make_attr(elem,"Group",user.get_group())
make_attr(elem,"Address1",user.get_address1())
make_attr(elem,"Address2",user.get_address2())
make_attr(elem,"City",user.get_city())
make_attr(elem,"Country",user.get_country())
make_attr(elem,"Homepage",user.get_homepage())
make_attr(elem,"Phone",user.get_phone())
make_attr(elem,"Mobile",user.get_gsm())
make_attr(elem,"WebtopBgImagePath", user.get_webtop_bg_image_path())
if user.is_frozen():
make_attr(elem,"Frozen","1")
if user.get_webtop_bg_image_path()[:len('images')] != 'images':
bg_image = self.dom.createElement("WebtopBackgroundImage")
make_attr(bg_image,
"LocalName",
self.binarydata.storeData(
getattr(user.own_styles,
user.get_webtop_bg_name()).data))
make_attr(bg_image,
"ContentType",
getattr(user.own_styles,
user.get_webtop_bg_name()).getContentType())
elem.appendChild(bg_image)
if user.get_photo() and len(user.get_photo())>0:
photo = self.dom.createElement("Photo")
make_attr(photo,
"LocalName",
self.binarydata.storeData(user.get_photo()))
if user.get_photo_type():
make_attr(photo,
"ContentType",user.get_photo_type())
elem.appendChild(photo)
if len(user.get_quote())>0:
quote = self.dom.createElement("Quote")
make_text(quote,user.get_quote())
elem.appendChild(quote)
if len(user.get_background())>0:
back = self.dom.createElement("Background")
make_text(back,user.get_background())
elem.appendChild(back)
if len(user.get_personal_interests())>0:
personal = self.dom.createElement("Personal")
make_text(personal,user.get_personal_interests())
elem.appendChild(personal)
if len(user.get_professional_interests())>0:
pro = self.dom.createElement("Professional")
make_text(pro,user.get_professional_interests())
elem.appendChild(pro)
if do_webtop:
elem.appendChild(self.exportWebtop(user.webtop))
return elem
def importUser(self,elem,fle_users,do_user,do_webtop):
"""Import a user into the UserManager.
If the user already exists, we'll just skip user creation."""
uname = get_attr(elem,"Name")
if not do_user:
try:
user = fle_users.get_child(uname)
except AttributeError:
return
else:
try:
fle_users.get_user_info(uname)
except:
pass
else:
print "Skipping import of pre-existing user "+uname
return
(password, domains, roles) = \
self.retrieveUserACL(elem.getElementsByTagName("ACL")[0])
# If the user has no roles and no password, we'll just skip.
if not password and not roles:
return
try:
user = fle_users.add_user(
uname,
password,
roles,
domains)
except:
# Error adding user - just skip
return
if not user:
# OK, user adding failed more nicely. Skip again
return
photo=None
try:
photo_data = self.binarydata.getData(
get_attr(elem.getElementsByTagName("Photo")[0],"LocalName"),self.prefix)
photo_content = get_attr(elem.getElementsByTagName("Photo")[0],"ContentType")
photo = FakeUpload('image',photo_data,photo_content)
except IndexError:
pass
try:
web_bg_image_data = self.binarydata.getData(
get_attr(elem.getElementsByTagName("WebtopBackgroundImage")[0],"LocalName"),self.prefix)
except IndexError:
web_bg_image_data = ''
try:
quote=get_text(elem.getElementsByTagName("Quote")[0])
except IndexError:
quote=''
try:
background=get_text(elem.getElementsByTagName("Background")[0])
except IndexError:
background=''
try:
personal=get_text(elem.getElementsByTagName("Personal")[0])
except IndexError:
personal=''
try:
professional=get_text(elem.getElementsByTagName("Professional")[0])
except IndexError:
professional=''
user.edit_info(
first_name = get_attr(elem,"FirstName"),
last_name = get_attr(elem,"LastName"),
email = get_attr(elem,"Email"),
organization = get_attr(elem,"Organisation"),
language = get_attr(elem,"Lang"),
photo_upload = photo,
# photo_url = '',
group = get_attr(elem,"Group"),
address1 = get_attr(elem,"Address1"),
address2 = get_attr(elem,"Address2"),
city = get_attr(elem,"City"),
country = get_attr(elem,"Country"),
homepage = get_attr(elem,"Homepage"),
phone = get_attr(elem,"Phone"),
gsm = get_attr(elem,"Mobile"),
quote = quote,
background = background,
personal_interests = personal,
professional_interests = professional,
)
if web_bg_image_data:
user.set_webtop_bg_from_image_data(web_bg_image_data)
else:
image_name = get_attr(elem,"WebtopBgImagePath")[len('images/'):]
if image_name:
user.set_webtop_bg_from_default_image(image_name)
if get_attr(elem,"Frozen"):
fle_users.freeze_user(user.get_uname())
if do_webtop:
wtelems = elem.getElementsByTagName("Webtop")
if len(wtelems)>0:
webtop=user.__of__(fle_users).webtop
self.importWebtop(wtelems[0],webtop)
def exportWebtop(self,webtop):
"""Export a user's webtop."""
elem = self.dom.createElement("Webtop")
self.exportWebtopFolderContents(webtop,elem)
return elem
def importWebtop(self,elem,webtop):
"""Import a user's webtop."""
self.importWebtopFolderContents(elem,webtop)
def exportWebtopItemAttrs(self,item,elem):
"""Export attributes common to all webtop items
into a predefined XML element."""
#make_attr(elem,"Name",item.get_name())
make_attr(elem,"identifier",item.get_id())
make_attr(elem,"identifierref",item.aq_parent.get_id())
itemname = self.dom.createElement('title')
itemname.appendChild(self.dom.createTextNode(item.get_name()))
elem.appendChild(itemname)
#make_attr(elem,"Date",str(int(item.get_timestamp())))
#make_attr(elem,"Owner",str(item.get_author_name()))
def importWebtopItemAttrs(self,elem,item):
"""Import attributes common to all WebtopItems."""
item.set_timestamp(int(get_attr(elem,"Date")))
owner = get_attr(elem,"Owner")
if owner:
item.set_author(owner)
## elif hasattr(item,'get_uname'):
## item.set_author(item.get_uname()) # Acquired from UserInfo
def exportWebtopFolderStrukt(self, folder):
""" kaustade/stuktuuri exportija kaustas"""
elem = self.dom.createElement("item")
self.exportWebtopItemAttrs(folder,elem)
self.exportWebtopFolderStructure(folder,elem)
return elem
def exportWebtopFolder(self,folder):
"""Export a folder from a user's webtop."""
""" resource, Vahur """
elem = self.dom.createElement("resource")
elem.appendChild(self.dom.createTextNode(folder.aq_parent.get_id()))
self.exportWebtopItemAttrs(folder,elem)
self.exportWebtopFolderContents(folder,elem)
return elem
def exportGroupFolder(self,folder):
"""Export a group folder."""
elem = self.dom.createElement("GroupFolder")
self.exportWebtopItemAttrs(folder,elem)
self.exportWebtopFolderContents(folder,elem)
make_attr(elem,"ID",folder.get_id())
return elem
def importWebtopFolder(self,elem,parent):
"""Imports a webtop folder into the specified parent folder."""
name = get_attr(elem,"Name")
folder = parent.add_folder(name)
self.importWebtopItemAttrs(elem,folder)
self.importWebtopFolderContents(elem,folder)
return folder
def importGroupFolder(self,elem,parent,toplevel=0):
folder = self.importWebtopFolder(elem,parent)
if toplevel:
self.idmap[get_attr(elem,'ID')]=folder
def exportWebtopFolderStructure(self, folder, elem):
"expordi struktuur/kaustad"
for fol in folder.objectValues('WebtopFolder'):
elem.appendChild(self.exportWebtopFolderStrukt(fol))
return elem
def exportWebtopFolderContents(self,folder,elem):
"""Export a folder's contents from a webtop, into
a predefined XML element. This method is called from
both exportWebtop and exportWebtopFolder."""
for fol in folder.objectValues('WebtopFolder'):
elem.appendChild(self.exportWebtopFolder(fol))
for file in folder.objectValues('WebtopFile'):
elem.appendChild(self.exportWebtopFile(file))
for link in folder.objectValues('WebtopLink'):
elem.appendChild(self.exportWebtopLink(link))
for memo in folder.objectValues('WebtopMemo'):
elem.appendChild(self.exportWebtopMemo(memo))
for fol in folder.objectValues('GroupFolder'):
elem.appendChild(self.exportGroupFolder(fol))
return elem
def exportWebtopFolderitemid(self,folder,elem):
""" ekspordi riiul ilma folderiteta"""
for file in folder.objectValues('WebtopFile'):
elem.appendChild(self.exportWebtopFile(file))
for link in folder.objectValues('WebtopLink'):
elem.appendChild(self.exportWebtopLink(link))
for memo in folder.objectValues('WebtopMemo'):
elem.appendChild(self.exportWebtopMemo(memo))
for fol in folder.objectValues('WebtopFolder'):
self.exportWebtopFolderitemid(fol, elem)
return elem
def importWebtopFolderContents(self,elem,folder):
"""Import a webtop folder's contents."""
for celem in elem.childNodes:
if celem.nodeName == 'WebtopFolder':
self.importWebtopFolder(celem,folder)
elif celem.nodeName == 'WebtopFile':
self.importWebtopFile(celem,folder)
elif celem.nodeName == 'Link':
self.importWebtopLink(celem,folder)
elif celem.nodeName == 'WebtopMemo':
self.importWebtopMemo(celem,folder)
elif celem.nodeName == 'GroupFolder':
self.importGroupFolder(celem,folder)
def exportWebtopFile(self,file):
"""Export a file from a user's webtop."""
elem = self.dom.createElement("resource")
#self.exportWebtopItemAttrs(file,elem)
make_attr(elem, "identifier",file.aq_parent.get_id())
make_attr(elem, "type","file")
fnimi = self.binarydata.storeData(file.data)
make_attr(elem,
"href",
fnimi)
elem2 = self.dom.createElement("file")
make_attr(elem2, "href",fnimi)
elem.appendChild(elem2)
elem3 = self.dom.createElement("imsmd:title")
elem3.appendChild(self.dom.createTextNode(file.get_name()))
elem2.appendChild(elem3)
#make_attr(elem,"ContentType",file.getContentType())
return elem
def importWebtopFile(self,elem,folder):
"""Imports a webtop file into the given folder."""
data = self.binarydata.getData(get_attr(elem,"LocalName"),self.prefix)
name = get_attr(elem,"Name")
file = folder.add_file(
name,
FakeUpload(name,data,get_attr(elem,"ContentType")))
self.importWebtopItemAttrs(elem,file)
def exportWebtopLink(self,link):
"""Export a link from a user's webtop."""
elem = self.dom.createElement("resource")
make_attr(elem, "identifier",link.aq_parent.get_id())
make_attr(elem, "type","URL")
make_attr(elem, "href",link.get_url())
elem2 = self.dom.createElement("file")
make_attr(elem2, "href",link.get_url())
elem.appendChild(elem2)
elem3 = self.dom.createElement("imsmd:title")
elem3.appendChild(self.dom.createTextNode(link.get_name()))
elem2.appendChild(elem3)
return elem
#self.exportWebtopItemAttrs(link,elem)
# try:
# if link.is_internal_link():
# make_attr(elem,"IDRef",link.get_obj_ref().get_id())
# return elem
# except TypeError:
# We get this if is_internal_link requires parameters.
# Exporting from older versions may cause this.
# We'll just handle those links as external.
# pass
# except AttributeError:
# This means a link is broken (doesn't point to an
# existing object). Let's just skip export.
# pass
# make_attr(elem,"Src",link.get_url())
def importWebtopLink(self,elem,folder):
"""Imports a webtop link into the given folder."""
name = get_attr(elem,"Name")
src = get_attr(elem,"Src")
objref = get_attr(elem,"IDRef")
if objref:
try:
obj = self.idmap[objref]
link = folder.add_link(name, obj, 1)
except KeyError:
# We get a keyerror if the id is not found.
print "WebtopLink %s with target id %s doesn't exist!" % (name,objref)
return
else:
link = folder.add_link(name, src)
self.importWebtopItemAttrs(elem,link)
def exportWebtopMemo(self,memo):
"""Export a memo from a user's webtop."""
elem = self.dom.createElement("resource")
make_attr(elem, "identifier", memo.aq_parent.get_id())
make_attr(elem, "type", "memo")
#self.exportWebtopItemAttrs(memo,elem)
tit = self.dom.createElement("imsmd:title")
make_text(tit,memo.get_name())
elem.appendChild(tit)
celem = self.dom.createElement("imsmd:description")
make_text(celem,memo.get_body())
elem.appendChild(celem)
return elem
def importWebtopMemo(self,elem,folder):
"""Imports a webtop memo into the given folder."""
name = get_attr(elem,"Name")
contents=get_text(elem.getElementsByTagName("Contents")[0])
memo = folder.add_memo(name, contents)
self.importWebtopItemAttrs(elem,memo)
#EOF
iva-0.7.4/ImportExportEML.py 0000644 0000000 0000000 00000033056 10345616031 0016740 0 ustar viewcvs viewcvs 0000001 0000000 # -*- coding: utf-8
# $Id$
#
# Copyright 2001, 2002 by IVA Team and contributors
#
# This file is part of IVA.
#
# IVA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# IVA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with IVA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
__version__ = "$Revision$"[11:-2]
"""Contains classes responsible for importing and exporting the data to and from an FLE installation. Uses XML formatted EML documents for storage."""
import sys
import xml.dom.minidom
from xml.dom.minidom import Document
import zipfile
import time
from types import FloatType
from ImportExport import Counter, DataTable, to_utf8
def date2str(date):
if not type(date)==type(()):
date = time.gmtime(date)
return time.strftime('%Y/%m/%d',date)
def str2date(str):
return time.mktime(time.strptime(str,'%Y/%m/%d'))
def to_id(id):
id=str(id)
if id[0]>='0' and id[0]<='9':
id='id'+id
return id.replace('_','-')
class Exporter:
"""Class that handles the exporting (but not yet importing) of data
to EML and also holds the XMLized content."""
# If the parameter 'file' is specified, it is assumed to be
# an uploaded zip file containing exported data and it is
# loaded into memory. Otherwise an empty Exporter is created.
def __init__(self,file=None):
"""Creates a new Exporter."""
# Add a binary data hash table
self.binarydata = DataTable()
self.idmap = {}
if file:
self.loadZip(file)
else:
# Document: unlink, writexml(writer), toxml()
self.dom = Document()
type=xml.dom.minidom.DocumentType('"Unit-of-study PUBLIC "-//OUNL//DTD EML/XML binding 1.0/1.0//EN" "eml10.dtd"')
self.dom.doctype=type
self.root = self.dom.createElement("unit-of-study")
self.root.setAttribute("encoding","utf-8")
self.dom.appendChild(self.root)
def createZip(self,file):
"""Dumps the currently exported data
(XML document and binary files) into a zip file.
- file: name of the file to create"""
zip = zipfile.ZipFile(file,"w",zipfile.ZIP_DEFLATED)
zip.writestr(zipfile.ZipInfo("fle_eml.xml"),self.dom.toxml())
for name in self.binarydata.getNames():
zip.writestr(
zipfile.ZipInfo(name),
str(self.binarydata.getData(name)))
zip.close()
def loadZip(self,file):
"""Loads a zipped FLE content file.
- file: the file name to load."""
zip = zipfile.ZipFile(file,"r",zipfile.ZIP_DEFLATED)
xmlstring = unicode(
zip.read("imsmanifest.xml"), 'iso-8859-1').encode("utf-8")
self.dom = xml.dom.minidom.parseString(xmlstring)
self.root = self.dom.firstChild
for name in zip.namelist():
if name[:4]=='data':
self.binarydata.restoreData(name,zip.read(name))
zip.close()
def exportCourse(self,course):
"""Exports the given course into an EML unit of study."""
newElem = self.dom.createElement
newText = self.dom.createTextNode
elem = newElem("metadata")
elem2 = newElem("title")
elem2.appendChild(newText(course.get_name()))
elem.appendChild(elem2)
elem2 = newElem("creator")
elem2.appendChild(newText(course.get_teacher()))
elem.appendChild(elem2)
elem2 = newElem("description")
elem3 = newElem("p")
elem3.appendChild(newText(course.get_description()))
elem2.appendChild(elem3)
elem.appendChild(elem2)
elem2 = newElem("copyright")
elem3 = newElem("copyright-year")
elem3.appendChild(newText(date2str(course.get_end_date())[:4]))
elem2.appendChild(elem3)
elem3 = newElem("copyright-owner")
elem3.appendChild(newText(course.get_organisation()))
elem2.appendChild(elem3)
elem.appendChild(elem2)
elem2 = newElem("extra-meta")
elem3 = newElem("creation-date")
elem3.appendChild(newText(date2str(course.get_start_date())))
elem2.appendChild(elem3)
elem3 = newElem("date-last-change")
elem3.appendChild(newText(date2str(course.get_end_date())))
elem2.appendChild(elem3)
elem3 = newElem("meta")
elem3.setAttribute("base","FLE3")
elem3.setAttribute("description","metatype")
elem4 = newElem("unstructured-source")
elem4.appendChild(newText("Course"))
elem3.appendChild(elem4)
elem2.appendChild(elem3)
elem.appendChild(elem2)
self.root.appendChild(elem)
elem = newElem("roles")
elem2 = newElem("learner")
elem2.setAttribute("id","learner")
## elem3 = newElem("role")
## elem3.setAttribute("name","student")
## elem2.appendChild(elem3)
## elem3 = newElem("role")
## elem3.setAttribute("name","tutor")
## elem2.appendChild(elem3)
## elem3 = newElem("role")
## elem3.setAttribute("type","Facilitator")
## elem3.setAttribute("name","teacher")
## elem2.appendChild(elem3)
elem.appendChild(elem2)
elem2 = newElem("staff")
elem2.setAttribute("id","staff")
## elem3 = newElem("role")
## elem3.setAttribute("name","student")
## elem2.appendChild(elem3)
## elem3 = newElem("role")
## elem3.setAttribute("name","tutor")
## elem2.appendChild(elem3)
## elem3 = newElem("role")
## elem3.setAttribute("type","Facilitator")
## elem3.setAttribute("name","Teacher")
## elem2.appendChild(elem3)
elem.appendChild(elem2)
self.root.appendChild(elem)
elem = newElem("content")
elem2 = newElem("activity")
elem2.setAttribute("reusability","reusable")
elem2.setAttribute("id","act0")
elem3 = newElem("activity-description")
elem4 = newElem("what")
elem5 = newElem("p")
elem5.appendChild(newText("Reflection on already completed knowledge building."))
elem4.appendChild(elem5)
elem3.appendChild(elem4)
elem4 = newElem("completed")
elem4.appendChild(newElem("unrestricted"))
elem3.appendChild(elem4)
elem2.appendChild(elem3)
elem.appendChild(elem2)
for ctx in course.get_children("CourseContext"):
elem2 = elem.appendChild(self.exportContext(ctx))
elem.appendChild(elem2)
elem.appendChild(elem2)
self.root.appendChild(elem)
elem = newElem("method")
elem2 = newElem("play")
elem3 = newElem("comment")
elem3.appendChild(newText("The original methods for building this knowledge were as follows:\n"+course.get_methods()))
elem2.appendChild(elem3)
elem3 = newElem("role-ref")
elem3.setAttribute("id-ref","learner")
elem2.appendChild(elem3)
elem3 = newElem("activity-ref")
elem3.setAttribute("id-ref","act0")
elem2.appendChild(elem3)
elem.appendChild(elem2)
self.root.appendChild(elem)
return elem
def exportContext(self,ctx):
"""Exports the given course context."""
newElem = self.dom.createElement
newText = self.dom.createTextNode
elem = newElem("environment")
elem.setAttribute("id",to_id(ctx.get_id()))
elem2 = newElem("metadata")
elem3 = newElem("title")
elem3.appendChild(newText(ctx.get_name()))
elem2.appendChild(elem3)
elem3 = newElem("creator")
elem3.appendChild(newText(ctx.get_author()))
elem2.appendChild(elem3)
elem3 = newElem("description")
elem4 = newElem("p")
elem4.appendChild(newText(ctx.get_description()+"\n\n"+ctx.get_long_description()))
elem3.appendChild(elem4)
elem2.appendChild(elem3)
elem3 = newElem("extra-meta")
elem4 = newElem("meta")
elem4.setAttribute("base","FLE3")
elem4.setAttribute("description","metatype")
elem5 = newElem("unstructured-source")
elem5.appendChild(newText("CourseContext"))
elem4.appendChild(elem5)
elem3.appendChild(elem4)
elem2.appendChild(elem3)
elem.appendChild(elem2)
elem.appendChild(self.exportTTS(ctx.get_thinking_type_set()))
frag = self.dom.createDocumentFragment()
for note in ctx.get_children('Note'):
self.exportNote(frag,note)
elem.appendChild(frag)
return elem
def exportTTS(self,set):
"""Exports the given knowledgetypeset."""
newElem = self.dom.createElement
newText = self.dom.createTextNode
elem = newElem("knowledge-object")
elem2 = newElem("metadata")
elem3 = newElem("title")
elem3.appendChild(newText(set.get_name()))
elem2.appendChild(elem3)
elem3 = newElem("description")
elem4 = newElem("p")
elem4.appendChild(newText(set.get_description()))
elem3.appendChild(elem4)
elem2.appendChild(elem3)
elem3 = newElem("extra-meta")
elem4 = newElem("meta")
elem4.setAttribute("base","FLE3")
elem4.setAttribute("description","metatype")
elem5 = newElem("unstructured-source")
elem5.appendChild(newText("ThinkingTypeSet"))
elem4.appendChild(elem5)
elem3.appendChild(elem4)
elem2.appendChild(elem3)
elem.appendChild(elem2)
elem2 = newElem("source")
for type in set.get_thinking_types():
elem3 = newElem("section")
elem3.setAttribute("id",to_id(set.parent().get_id()+'-'+type.get_id()))
elem4 = self.exportTT(type)
elem3.appendChild(elem4)
elem2.appendChild(elem3)
elem.appendChild(elem2)
return elem
def exportTT(self,type):
"""Exports the given knowledgetype."""
newElem = self.dom.createElement
newText = self.dom.createTextNode
elem = newElem("source")
elem2 = newElem("figure")
elem3 = newElem("figure-source")
elem3.setAttribute(
"entity",
self.binarydata.storeData(type.get_icon().data))
elem2.appendChild(elem3)
elem.appendChild(elem2)
elem2 = newElem("p")
elem2.appendChild(newText(type.get_name()))
elem.appendChild(elem2)
elem2 = newElem("p")
elem2.appendChild(newText(type.get_description()))
elem.appendChild(elem2)
return elem
def exportNote(self,frag,note):
"""Exports the given note."""
newElem = self.dom.createElement
newText = self.dom.createTextNode
elem = newElem("knowledge-object")
elem.setAttribute("id",to_id(note.get_id()))
elem2 = newElem("metadata")
elem3 = newElem("title")
elem3.appendChild(newText(note.get_real_subject()))
elem2.appendChild(elem3)
elem3 = newElem("creator")
elem3.appendChild(newText(note.get_author()))
elem2.appendChild(elem3)
elem3 = newElem("extra-meta")
elem4 = newElem("creation-date")
elem4.appendChild(newText(date2str(note.get_creation_time())))
elem3.appendChild(elem4)
elem4 = newElem("meta")
elem4.setAttribute("base","FLE3")
elem4.setAttribute("description","metatype")
elem5 = newElem("unstructured-source")
elem5.appendChild(newText("Note"))
elem4.appendChild(elem5)
elem3.appendChild(elem4)
elem4 = newElem("meta")
elem4.setAttribute("base","FLE3")
elem4.setAttribute("description","parent")
elem5 = newElem("unstructured-source")
elem5.appendChild(newText(note.parent().get_id()))
elem4.appendChild(elem5)
elem3.appendChild(elem4)
elem4 = newElem("meta")
elem4.setAttribute("base","FLE3")
elem4.setAttribute("description","type")
elem5 = newElem("unstructured-source")
elem5.appendChild(newText(note.get_tt_id()))
elem4.appendChild(elem5)
elem3.appendChild(elem4)
elem2.appendChild(elem3)
elem.appendChild(elem2)
elem2 = newElem("source")
elem3 = newElem("p")
elem3.appendChild(newText(note.get_body()))
elem2.appendChild(elem3)
if note.get_url()!='':
elem3 = newElem("internet-source")
elem3.setAttribute("url",note.get_url())
elem3.setAttribute("link-name",note.get_url_name())
elem2.appendChild(elem3)
if note.has_image():
name = self.binarydata.storeData(
note.get_image_data())
elem3 = newElem("figure")
elem4 = newElem("figure-source")
elem4.setAttribute("entity",name)
elem3.appendChild(elem4)
elem4 = newElem("figure-text")
elem5 = newElem("p")
elem5.appendChild(newText(note.get_image_name()))
elem4.appendChild(elem5)
elem3.appendChild(elem4)
elem2.appendChild(elem3)
elem.appendChild(elem2)
frag.appendChild(elem)
for reply in note.get_children('Note'):
self.exportNote(frag,reply)
#EOF
iva-0.7.4/ImportExportIMS.py 0000644 0000000 0000000 00000454676 10345616031 0016772 0 ustar viewcvs viewcvs 0000001 0000000 # -*- coding: utf-8
# $Id$
#
import zipfile
import xml.dom.minidom
import xml.sax
from xml.dom.minidom import Document
import string
from xml.sax import saxutils
from xml.dom.ext.reader import Sax2
from ImportExport import Counter, DataTable, to_utf8, Exporter, Dump
from common import FakeRequest, FakeUpload
from xml.dom import implementation
from xml.dom import EMPTY_NAMESPACE, XML_NAMESPACE
from xml.dom.ext import PrettyPrint
from Products.ZWiki.ZWikiPage import ZWikiPage
from types import UnicodeType
from input_checks import strip_non_xml
import OFS.Image
import types
import re, time
__version__ = "$Revision$"[11:-2]
class User_export:
def __init__(self):
self.binarydata = DataTable()
self.sisegrupid = []
doctype = implementation.createDocumentType("enterprise", "http://www.htk.tpu.ee/%7Evahur/ims_epv1p1.dtd", "http://www.htk.tpu.ee/%7Evahur/ims_epv1p1.dtd")
self.user = implementation.createDocument(EMPTY_NAMESPACE, "enterprise", doctype)
self.userelem = self.user.documentElement
prop = self.user.createElement('properties')
self.userelem.appendChild(prop)
source = self.user.createElement('datasource')
source_data = self.user.createTextNode('IVA')
source.appendChild(source_data)
prop.appendChild(source)
datetime = self.user.createElement('datetime')
datetime_data = self.user.createTextNode('kuupaev')
datetime.appendChild(datetime_data)
prop.appendChild(datetime)
def kirjutaKasutaja(self,kasutaja,kursus=''):
person = self.user.createElement('person')
self.userelem.appendChild(person)
sourcedid = self.user.createElement('sourcedid')
person.appendChild(sourcedid)
source = self.user.createElement('source')
source_data = self.user.createTextNode('IVA')
source.appendChild(source_data)
sourcedid.appendChild(source)
id = self.user.createElement('id')
id_data = self.user.createTextNode(kasutaja.get_uname())
id.appendChild(id_data)
sourcedid.appendChild(id)
userid = self.user.createElement('userid')
try:
userid.setAttribute('password',kasutaja.getPassword())
except:
userid.setAttribute('password','nipitiri')
userid_name = self.user.createTextNode(kasutaja.get_uname())
userid.appendChild(userid_name)
person.appendChild(userid)
name = self.user.createElement('name')
person.appendChild(name)
fn = self.user.createElement('fn')
fn_data = self.user.createTextNode(kasutaja.get_first_name()+' '+kasutaja.get_last_name())
fn.appendChild(fn_data)
name.appendChild(fn)
n = self.user.createElement('n')
name.appendChild(n)
family = self.user.createElement('family')
family_data = self.user.createTextNode(kasutaja.get_last_name())
family.appendChild(family_data)
n.appendChild(family)
given = self.user.createElement('given')
given_data = self.user.createTextNode(kasutaja.get_first_name())
given.appendChild(given_data)
n.appendChild(given)
partname = self.user.createElement('partname')
partname.setAttribute('partnametype','First')
partname.setAttribute('lang',kasutaja.get_language())
partname_data = self.user.createTextNode(kasutaja.get_first_name())
partname.appendChild(partname_data)
n.appendChild(partname)
demogr = self.user.createElement('demographics')
email = self.user.createElement('email')
email_data = self.user.createTextNode(kasutaja.get_email())
email.appendChild(email_data)
person.appendChild(email)
url = self.user.createElement('url')
url_data = self.user.createTextNode(kasutaja.get_homepage())
url.appendChild(url_data)
person.appendChild(url)
tel_t = self.user.createElement('tel')
tel_t.setAttribute('teltype','Voice')
tel_t_data = self.user.createTextNode(kasutaja.get_phone())
tel_t.appendChild(tel_t_data)
person.appendChild(tel_t)
tel_gsm = self.user.createElement('tel')
tel_gsm.setAttribute('teltype','Mobile')
tel_gsm_data = self.user.createTextNode(kasutaja.get_gsm())
tel_gsm.appendChild(tel_gsm_data)
person.appendChild(tel_gsm)
adr = self.user.createElement('adr')
person.appendChild(adr)
extadd = self.user.createElement('extadd')
extadd_data = self.user.createTextNode(kasutaja.get_address2())
extadd.appendChild(extadd_data)
adr.appendChild(extadd)
street = self.user.createElement('street')
street_data = self.user.createTextNode(kasutaja.get_address1())
street.appendChild(street_data)
adr.appendChild(street)
locality = self.user.createElement('locality')
locality_data = self.user.createTextNode(kasutaja.get_city())
locality.appendChild(locality_data)
adr.appendChild(locality)
country = self.user.createElement('country')
country_data = self.user.createTextNode(kasutaja.get_country())
country.appendChild(country_data)
adr.appendChild(country)
try:
if kasutaja.has_photo():
photo = self.user.createElement('photo')
real_photo = kasutaja.get_photo_obj()
#XXX: image type
#photo.setAttribute('imgtype',kasutaja.get_photo_type())
photo.setAttribute('imgtype', real_photo.getContentType())
extref = self.user.createElement('extref')
#XXX: data - needs testing!
photo_name = self.binarydata.storeData(real_photo.data,'user')
extref_data = self.user.createTextNode(photo_name)
extref.appendChild(extref_data)
photo.appendChild(extref)
person.appendChild(photo)
except:
pass
systemrole = self.user.createElement('systemrole')
kas_admin = kasutaja.getRoles()
if 'Manager' in kas_admin:
systemrole.setAttribute('systemroletype','SysAdmin')
else:
systemrole.setAttribute('systemroletype','User')
person.appendChild(systemrole)
try:
instrole = self.user.createElement('institutionrole')
instrole.setAttribute('primaryrole','No')
instrole.setAttribute('institutionroletype','Learner')
for abc in kursus.get_local_roles():
if abc[0]==kasutaja.get_uname() and 'Teacher' in abc[1]:
instrole.setAttribute('institutionroletype','Instructor')
person.appendChild(instrole)
except:
pass
extension = self.user.createElement('extension')
person.appendChild(extension)
org = self.user.createElement('org')
extension.appendChild(org)
orgname = self.user.createElement('orgname')
orgname_data = self.user.createTextNode(kasutaja.get_organization())
orgname.appendChild(orgname_data)
org.appendChild(orgname)
comment = self.user.createElement('comments')
comment_data = self.user.createTextNode(kasutaja.get_background())
comment.appendChild(comment_data)
extension.appendChild(comment)
desc = self.user.createElement('description')
extension.appendChild(desc)
short = self.user.createElement('short')
short_data = self.user.createTextNode(kasutaja.get_personal_interests())
short.appendChild(short_data)
desc.appendChild(short)
long = self.user.createElement('long')
long_data = self.user.createTextNode(kasutaja.get_professional_interests())
long.appendChild(long_data)
desc.appendChild(long)
label = self.user.createElement('label')
label_data = self.user.createTextNode(kasutaja.get_quote())
label.appendChild(label_data)
extension.appendChild(label)
return "valmis"
def pakiFaili(self,kursusega,failinimi="userexport.zip"):
"Pakitakse kasutajad faili"
if kursusega=="/":
kursusega = ''
if zipfile.is_zipfile(failinimi):
zip = zipfile.ZipFile(failinimi,"a",zipfile.ZIP_DEFLATED)
else:
zip = zipfile.ZipFile(failinimi,"w",zipfile.ZIP_DEFLATED)
dump = Dump()
PrettyPrint(self.user,stream=dump)
zip.writestr(zipfile.ZipInfo(kursusega+"users.xml"),dump.getdata())
for name in self.binarydata.names:
zip.writestr(
zipfile.ZipInfo(kursusega+name),
str(self.binarydata.getData(name)))
zip.close()
def kirjutaKursusGrupina(self,kursus):
# Kirjutab grupi mis omab kursuse funktsiooni. Kőik kes selles grupis on
# student vői teacher
krupp = self.user.createElement('group')
krupp_s = self.user.createElement('sourcedid')
krupp_source = self.user.createElement('source')
krupp_source_data = self.user.createTextNode('IVA')
krupp_source.appendChild(krupp_source_data)
krupp_s.appendChild(krupp_source)
krupp_id = self.user.createElement('id')
krupp_id_data = self.user.createTextNode(kursus.get_name())
krupp_id.appendChild(krupp_id_data)
krupp_s.appendChild(krupp_id)
krupp.appendChild(krupp_s)
krupp_type = self.user.createElement('grouptype')
type_value = self.user.createElement('typevalue')
type_value.setAttribute('level','1')
krupp_type.appendChild(type_value)
krupp.appendChild(krupp_type)
description = self.user.createElement('description')
desc_short = self.user.createElement('short')
desc_short_data = self.user.createTextNode(kursus.getQuote())
desc_short.appendChild(desc_short_data)
description.appendChild(desc_short)
desc_long = self.user.createElement('long')
desc_long_data = self.user.createTextNode(kursus.get_methods())
desc_long.appendChild(desc_long_data)
description.appendChild(desc_long)
desc_full = self.user.createElement('full')
desc_full_data = self.user.createTextNode(kursus.get_description())
desc_full.appendChild(desc_long_data)
description.appendChild(desc_full)
krupp.appendChild(description)
org = self.user.createElement('org')
orgname = self.user.createElement('orgname')
orgname_data = self.user.createTextNode(kursus.get_name())
orgname.appendChild(orgname_data)
org.appendChild(orgname)
orgunit = self.user.createElement('orgunit')
orgunit_data = self.user.createTextNode(kursus.get_organisation())
orgunit.appendChild(orgunit_data)
org.appendChild(orgunit)
krupp.appendChild(org)
enrollcontrol = self.user.createElement('enrollcontrol')
enroll_accept = self.user.createElement('enrollaccept')
enroll_allowed = self.user.createElement('enrollallowed')
try:
if str(kursus.getStatus()) == str('0') or int(kursus.getStatus())>1:
enroll_accept_data = self.user.createTextNode('0')
else:
enroll_accept_data = self.user.createTextNode('1')
except:
enroll_accept_data = self.user.createTextNode('0')
enroll_allowed_data = self.user.createTextNode('1')
enroll_accept.appendChild(enroll_accept_data)
enroll_allowed.appendChild(enroll_allowed_data)
enrollcontrol.appendChild(enroll_accept)
enrollcontrol.appendChild(enroll_allowed)
krupp.appendChild(enrollcontrol)
self.userelem.appendChild(krupp)
def kirjutaSisegrupid(self,kursus,sisegrupp):
krupp = self.user.createElement('group')
sourcedid = self.user.createElement('sourcedid')
source = self.user.createElement('source')
source_data = self.user.createTextNode('IVA')
source.appendChild(source_data)
sourcedid.appendChild(source)
id = self.user.createElement('id')
# id_data = self.user.createTextNode(str(kursus.get_id())+":"+str(sisegrupp.id))
id_data = self.user.createTextNode(str(sisegrupp.id))
id.appendChild(id_data)
sourcedid.appendChild(id)
krupp.appendChild(sourcedid)
description = self.user.createElement('description')
short = self.user.createElement('short')
short_data = self.user.createTextNode(sisegrupp.title)
short.appendChild(short_data)
description.appendChild(short)
krupp.appendChild(description)
#relationship
relationship = self.user.createElement('relationship')
relationship.setAttribute('relation','2')
sourcedid = self.user.createElement('sourcedid')
source = self.user.createElement('source')
source_data = self.user.createTextNode('IVA')
source.appendChild(source_data)
sourcedid.appendChild(source)
id = self.user.createElement('id')
id_data = self.user.createTextNode(kursus.get_name())
id.appendChild(id_data)
sourcedid.appendChild(id)
relationship.appendChild(sourcedid)
label = self.user.createElement('label')
label_data = self.user.createTextNode('Course sub-group')
label.appendChild(label_data)
relationship.appendChild(label)
krupp.appendChild(relationship)
self.userelem.appendChild(krupp)
return
def kirjutaMembership(self,kogum,tyyp='kursus'):
# write tag
if tyyp == 'kursus':
sortsu_id = kogum.get_name()
kasutajad = kogum.get_all_users()
comment_data = self.user.createTextNode('KURSUS')
else:
sortsu_id = kogum.id
kasutajad = kogum.kasutajad_sisegrupis(sortsu_id,objektina=1)
comment_data = self.user.createTextNode('SISEGRUPP')
membership = self.user.createElement('membership')
comment = self.user.createElement('comments')
comment.appendChild(comment_data)
membership.appendChild(comment)
sourcedid = self.user.createElement('sourcedid')
source = self.user.createElement('source')
source_data = self.user.createTextNode('IVA')
source.appendChild(source_data)
sourcedid.appendChild(source)
id = self.user.createElement('id')
id_data = self.user.createTextNode(str(sortsu_id))
id.appendChild(id_data)
sourcedid.appendChild(id)
membership.appendChild(sourcedid)
for juuser in kasutajad:
member = self.user.createElement('member')
sourcedid = self.user.createElement('sourcedid')
source = self.user.createElement('source')
source_data = self.user.createTextNode('IVA')
source.appendChild(source_data)
sourcedid.appendChild(source)
id = self.user.createElement('id')
id_data = self.user.createTextNode(juuser.get_uname())
id.appendChild(id_data)
sourcedid.appendChild(id)
member.appendChild(sourcedid)
idtype = self.user.createElement('idtype')
idtype_data = self.user.createTextNode('1')
idtype.appendChild(idtype_data)
member.appendChild(idtype)
role = self.user.createElement('role')
role.setAttribute('roletype','Learner')
for abc in kogum.get_local_roles():
if abc[0]==juuser.get_uname() and 'Teacher' in abc[1]:
role.setAttribute('roletype','Instructor')
status = self.user.createElement('status')
status_data = self.user.createTextNode('1')
status.appendChild(status_data)
role.appendChild(status)
if tyyp == 'kursus':
self.kirjutaHinded(role,kogum,juuser)
member.appendChild(role)
membership.appendChild(member)
# self.userelem.appendChild(membership)
self.sisegrupid.append(membership)
return
def kirjutaHinded(self,base_elem,kogum,kasutaja):
# kirjutab kasutaja hinded
#XXX: teacher comment, total points comment, total grade & comment, are not exported!
uname = kasutaja.get_uname()
for abc in kogum.kodutood.listAssignments():
punktid = -1
komm = ""
punktid = abc.getGrades(uname, 'points')
komm = abc.getGrades(uname, 'comment')
abc.getGrades(uname, 'teacherComment')
# if abc.tyyp == 0:
# if hasattr(kc, 'testivastused'):
# try:
# vk = getattr(kc.testivastused, abc.testiID)
# komm = vk.objectValues()[0].annaKoguKommentaar()
# except:
# pass
self.kirjutaInter(base_elem, abc, punktid, komm)
koondHinne = kogum.kodutood.getOverallDetails(uname, 'TotPoints')
koondKomm = kogum.kodutood.getOverallDetails(uname, 'overallComment')
self.kirjutaInter(base_elem, 'abc', koondHinne, koondKomm,'finalresult')
return
def kirjutaInter(self,base_elem, too, punktid, komm, mida='interimresult'):
if punktid == -1:
punktid = 0
interim = self.user.createElement(mida)
if mida == 'interimresult':
interim.setAttribute('resulttype',too.id)
mode = self.user.createElement('mode')
if mida == 'interimresult':
mode_data = self.user.createTextNode('Letter Grade')
else:
mode_data = self.user.createTextNode('protsent')
mode.appendChild(mode_data)
interim.appendChild(mode)
values = self.user.createElement('values')
values.setAttribute('valuetype','1')
val_min = self.user.createElement('min')
val_min_data = self.user.createTextNode('0')
val_min.appendChild(val_min_data)
values.appendChild(val_min)
val_max = self.user.createElement('max')
try:
pp = str(too.getPoints())
except:
pp = '9999'
val_max_data = self.user.createTextNode(pp)
val_max.appendChild(val_max_data)
values.appendChild(val_max)
interim.appendChild(values)
result = self.user.createElement('result')
result_data = self.user.createTextNode(str(punktid))
result.appendChild(result_data)
interim.appendChild(result)
comments = self.user.createElement('comments')
comments_data = self.user.createTextNode(str(komm))
comments.appendChild(comments_data)
interim.appendChild(comments)
base_elem.appendChild(interim)
return
def lisaMembership(self):
for abc in self.sisegrupid:
self.userelem.appendChild(abc)
return
class Importer:
def __init__(self, uname,ivajuur,prefix='', kursus='',binaryd='',testonly=0,userwikionly=0,kasuta_jooksvat=0):
"""Creates impoter"""
self.idmap = {}
self.uname = uname
self.prefix = prefix
self.iva = ivajuur
self.kasuta_jooksvat = kasuta_jooksvat
if kursus:
self.kursus = kursus
else:
self.kursus = ''
if binaryd:
self.binarydata = binaryd
else:
self.binarydata = DataTable()
self.timecounters=[0,0,0,0,0,0,0,0,0,0]
self.processed = []
self.testonly = testonly
self.userwikionly = userwikionly
def importTestAnswers(self,elem,tid,map):
from YlTest import TestiVastused
for r in elem.getElementsByTagName('response'):
owner = self.get_attr(r,'owner')
# get userobject. Vastuse omanik
try:
wt = getattr(self.iva.fle_users, owner).webtop
wtc = getattr(wt, 'c'+self.kursus.get_id())
except:
continue
if not hasattr(wtc.aq_self, 'testivastused'):
wtc.manage_addProduct['OFSP'].manage_addFolder('testivastused')
wtc.testivastused.id='testivastused'
tv = getattr(wtc, 'testivastused')
if not hasattr(tv, tid):
tv.manage_addProduct['OFSP'].manage_addFolder(tid)
tvx = getattr(tv, tid)
tvx.id = tid
else:
tvx = getattr(tv,tid)
#käiakse läbi erinevad testilahenduse variandid
for ver in r.getElementsByTagName('version'):
# lahendusvariandi id
id = self.get_attr(ver,'id')
if not hasattr(tvx.aq_self, id):
t = TestiVastused()
t.testinimi = id
t.id = id
tvx._setObject(id,t)
verk = getattr(tvx, id)
comment = self.get_attr(ver,'comment') #anna kogu kommentaar
try:
verk.seaKoguKommentaar(comment)
except AttributeError:
#XXX:weird
pass
for yl in ver.getElementsByTagName('yl'):
#testi ülesande (objekti) id
id = self.get_attr(yl,'id')
comment = self.get_attr(yl,'comment')
score = self.get_attr(yl,'score')
tupe = self.get_attr(yl,'type')
answer = self.get_text(yl)
if answer == 'None': answer = None
if tupe == 'List': answer = eval(answer)
if not score: score = None
if hasattr(verk,id):
#XXX: I don't know if this is reasonable
continue
try:
verk._setObject(id, map[id].koopia())
except KeyError:
continue
ylobj = getattr(verk,id)
ylobj.pakutudAndmed = answer
ylobj.opetajaPunktid = score
ylobj.seaOpetajaKommentaar(comment)
def importQT(self, elem, course, uname):
import YlTyybid
from YlAlus import YlAlus
from YlTyybid import ValikYlesanne, TekstivastusegaYlesanne, OigeTekstivastusegaYlesanne, MitmikvalikYlesanne, YksikvalikYlesanne, ArvuvahemikuliseVastusegaYlesanne, ProtsentYlesanne, VastavusYlesanne
from YlTest import YlTest, LahendusLoad, LahendusLuba, TestiVastused
id_map = {}
comment = self.get_text(elem.getElementsByTagName("qticomment")[0])
t_tyybid = ('ValikYlesanne','MitmikvalikYlesanne','YksikvalikYlesanne','OigeTekstivastusegaYlesanne','TekstivastusegaYlesanne','ArvuvahemikuliseVastusegaYlesanne','VastavusYlesanne')
for abc in elem.getElementsByTagName("section"):
# get id and title
sekt_title = self.get_attr(abc,'title')
id = self.get_attr(abc, 'ident')
if not hasattr(course.testid,'nr'):
course.testid.nr=0
# add test. XXX: move this to top and start adding metadata
course.testid.nr = course.testid.nr+1
qt=YlTest()
qt.pealkiri = sekt_title
# qt.id = "test"+str(course.testid.nr)
# course.testid._setObject(qt.id, qt)
qt.id = id
if hasattr(course.testid, qt.id):
qt.id = "test"+str(course.testid.nr)
# harvest data
answers = self.get_attr(abc, 'answers')
if not answers:
answers=0
qt.seaVastusteNahtavus(answers)
open = self.get_attr(abc, 'open')
if not open:
open=0
qt.avatudTaitmiseks = int(open)
randomize = self.get_attr(abc, 'randomize')
qt.seaKysimusteJuhuslikJarjekord(randomize)
type = self.get_attr(abc, 'type')
if not type:
type=0
qt.tyyp = int(type)
try:
md = abc.getElementsByTagName('metadata')[0]
desc = self.get_text(md.getElementsByTagName('description')[0])
qt.kirjeldus = desc
# permission options!
#timelimit and repeats
tstart = float(self.get_attr(md.getElementsByTagName('timelimit')[0],'start'))
tend = float(self.get_attr(md.getElementsByTagName('timelimit')[0],'end'))
repeat = self.get_attr(md.getElementsByTagName('timelimit')[0],'repeat')
qt.koigiLuba.algusAeg = tstart
qt.koigiLuba.loppAeg = tend
qt.koigiLuba.kordadeArv = int(repeat)
from YlTest import LahendusLuba
#groups
for gr in md.getElementsByTagName('person'):
try:
name = self.get_attr(gr,'name')
except:
continue
dm = LahendusLuba()
#if name == 'DuMmY67891': continue
tstart = float(self.get_attr(gr,'start'))
tend = float(self.get_attr(gr,'end'))
repeat = self.get_attr(gr,'repeat')
dm.id = name
dm.algusAeg = tstart
dm.loppAeg = tend
dm.kordadeArv = int(repeat)
qt.isikuLoad._setObject(dm.id,dm)
#persion
for pr in md.getElementsByTagName('group'):
try:
name = self.get_attr(pr,'name')
except:
continue
dm = LahendusLuba()
#if name == 'DuMmY67891': continue
tstart = float(self.get_attr(pr,'start'))
tend = float(self.get_attr(pr,'end'))
repeat = self.get_attr(pr,'repeat')
dm.id = name
dm.algusAeg = tstart
dm.loppAeg = tend
dm.kordadeArv = int(repeat)
qt.grupiLoad._setObject(dm.id,dm)
#limited solving time!?
#finally, add object
except IndexError:
pass
course.testid._setObject(qt.id, qt)
test_map = {}
for bcd in abc.getElementsByTagName("item"):
try:
qt_tyyp = self.get_attr(bcd,'title')
except IndexError:
qt_tyyp = ''
try:
qt_id = self.get_attr(bcd,'ident')
except IndexError:
qt_id = ''
try:
qt_story = self.get_text(bcd.getElementsByTagName("qticomment")[0])
except IndexError:
qt_story = ''
pelem = bcd.getElementsByTagName("presentation")[0]
try:
qt_quiz = self.get_text(pelem.getElementsByTagName("mattext")[0])
except IndexError:
qt_quiz = ''
try:
photo_data = self.binarydata.getData(
self.get_attr(pelem.getElementsByTagName("matimage")[0],'uri'),self.prefix)
except IndexError:
photo_data = None
try:
qt_link = self.get_text(pelem.getElementsByTagName("matemtext")[0])
qt_linkd = self.get_attr(pelem.getElementsByTagName("matemtext")[0],'uri')
except IndexError:
qt_link = ''
qt_linkd = ''
try:
r_grp = pelem.getElementsByTagName("response_grp")[0]
r_grp1 = 1
except IndexError:
r_grp1 = 0
try:
r_lid = pelem.getElementsByTagName("response_lid")[0]
r_lid1 = 1
except IndexError:
r_lid1 = 0
try:
r_xy = pelem.getElementsByTagName("response_xy")[0]
r_xy1 = 1
except IndexError:
r_xy1 = 0
try:
r_str = pelem.getElementsByTagName("response_str")[0]
r_str1 = 1
except IndexError:
r_str1 = 0
try:
r_num = pelem.getElementsByTagName("response_num")[0]
r_num1 = 1
except IndexError:
r_num1 = 0
if r_lid1:
try:
r_render = pelem.getElementsByTagName("render_choice")[0]
rend = 1
except:
rend = 0
if rend and qt_tyyp not in t_tyybid:
qt_tyyp = 'MitmikvalikYlesanne'
if r_str1:
r_fib1 = 0
try:
r_fib = pelem.getElementsByTagName("render_fib")[0]
r_fib1 = 1
except:
r_fib1 = 0
if r_fib1:
if qt_tyyp not in t_tyybid:
try:
xx = bcd.getElementsByTagName("varequal")[0]
tmp = 1
except:
tmp = 0
if tmp:
qt_tyyp = 'OigeTekstivastusegaYlesanne'
else:
qt_tyyp = 'TekstivastusegaYlesanne'
if qt_tyyp == 'ValikYlesanne':
vastus = self.get_text(bcd.getElementsByTagName("varequal")[0])
if vastus == 'T':
vastus =1
else:
vastus =0
punkte = self.get_text(bcd.getElementsByTagName("setvar")[0])
qt_test = ValikYlesanne(qt_quiz)
yl = qt.lisaYlesanne(qt_test)
qt_test.seaKirjeldavTekst('',qt_story)
qt_test.normPunktid=float(punkte)
qt_test.viiteURL = qt_linkd
qt_test.viiteTekst = qt_link
qt_test.vastus = vastus
qt_test.pilt = photo_data
# pistame testi hoidlasse
pass
if qt_tyyp == 'MitmikvalikYlesanne':
punkte = self.get_text(bcd.getElementsByTagName("setvar")[0])
qt_test = MitmikvalikYlesanne(qt_quiz)
yl = qt.lisaYlesanne(qt_test)
qt_test.seaKirjeldavTekst('',qt_story)
qt_test.normPunktid=float(punkte)
qt_test.viiteURL = qt_linkd
qt_test.viiteTekst = qt_link
qt_test.pilt = photo_data
oiged = []
v_text = []
v_id = []
s_text = []
s_id = []
for xbc in bcd.getElementsByTagName("varequal"):
oiged.append(self.get_text(xbc))
for vastused in bcd.getElementsByTagName("response_label"):
v_id.append(self.get_attr(vastused,'ident'))
v_text.append(self.get_text(vastused.getElementsByTagName("mattext")[0]))
for seletused in bcd.getElementsByTagName("itemfeedback"):
s_id.append(self.get_attr(seletused, 'ident'))
s_text.append(self.get_text(seletused.getElementsByTagName("mattext")[0]))
v_sisse = []
s_sisse = []
o_sisse = []
j = 0
for vmass in v_id:
i = 0
for smass in s_id:
if vmass == smass:
v_sisse.append(v_text[j])
s_sisse.append(s_text[i])
i = i + 1
try:
if str(vmass) in oiged:
o_sisse.append(int(j))
except:
pass
j = j + 1
qt_test.valikud = v_sisse
qt_test.selgitused = s_sisse
qt_test.oigedValikud = o_sisse
pass
if qt_tyyp == 'YksikvalikYlesanne':
vastus = self.get_text(bcd.getElementsByTagName("varequal")[0])
punkte = self.get_text(bcd.getElementsByTagName("setvar")[0])
qt_test = YksikvalikYlesanne(qt_quiz)
yl = qt.lisaYlesanne(qt_test)
qt_test.seaKirjeldavTekst('',qt_story)
qt_test.normPunktid=float(punkte)
qt_test.viiteURL = qt_linkd
qt_test.viiteTekst = qt_link
qt_test.pilt = photo_data
v_text = []
v_id = []
s_text = []
s_id = []
for vastused in pelem.getElementsByTagName("response_label"):
v_id.append(self.get_attr(vastused,'ident'))
v_text.append(self.get_text(vastused.getElementsByTagName("mattext")[0]))
for seletused in bcd.getElementsByTagName("itemfeedback"):
s_id.append(self.get_attr(seletused, 'ident'))
s_text.append(self.get_text(seletused.getElementsByTagName("mattext")[0]))
v_sisse = []
s_sisse = []
s_id.reverse()
s_text.reverse()
j = 0
for vmass in v_id:
i = 0
for smass in s_id:
if vmass == smass:
v_sisse.append(v_text[j])
s_sisse.append(s_text[i])
i = i + 1
if vmass == str(vastus):
qt_test.oigeValik = j
j = j + 1
qt_test.valikud = v_sisse
qt_test.selgitused = s_sisse
pass
if qt_tyyp == 'OigeTekstivastusegaYlesanne':
try:
punkte = self.get_text(bcd.getElementsByTagName("setvar")[0])
except:
punkte = 0
qt_test = OigeTekstivastusegaYlesanne(qt_quiz)
yl = qt.lisaYlesanne(qt_test)
qt_test.seaKirjeldavTekst('',qt_story)
qt_test.normPunktid=float(punkte)
qt_test.viiteURL = qt_linkd
qt_test.viiteTekst = qt_link
qt_test.pilt = photo_data
oiged = []
for xbc in bcd.getElementsByTagName("varequal"):
oiged.append(self.get_text(xbc))
qt_test.variandid = oiged
pass
if qt_tyyp == 'TekstivastusegaYlesanne':
try:
punkte = self.get_text(bcd.getElementsByTagName("setvar")[0])
except:
punkte = 0
qt_test = TekstivastusegaYlesanne(qt_quiz)
yl = qt.lisaYlesanne(qt_test)
qt_test.seaKirjeldavTekst('',qt_story)
qt_test.normPunktid=float(punkte)
qt_test.viiteURL = qt_linkd
qt_test.viiteTekst = qt_link
qt_test.pilt = photo_data
pass
if qt_tyyp == 'ArvuvahemikuliseVastusegaYlesanne':
punkte = self.get_text(bcd.getElementsByTagName("setvar")[0])
qt_test = ArvuvahemikuliseVastusegaYlesanne(qt_quiz)
yl = qt.lisaYlesanne(qt_test)
qt_test.seaKirjeldavTekst('',qt_story)
qt_test.normPunktid=float(punkte)
qt_test.viiteURL = qt_linkd
qt_test.viiteTekst = qt_link
qt_test.pilt = photo_data
arv_tyyp = bcd.getElementsByTagName("outcomes")[0]
q_arv_tyyp = self.get_text(arv_tyyp.getElementsByTagName("qticomment")[0])
q_alam = self.get_text(bcd.getElementsByTagName("vargte")[0])
q_oige = self.get_text(bcd.getElementsByTagName("varequal")[0])
q_ylem = self.get_text(bcd.getElementsByTagName("varlte")[0])
qt_test.alamPiir = float(q_alam)
qt_test.ylemPiir = float(q_ylem)
qt_test.oigeVastus = float(q_oige)
try:
qt_test.arvutusTyyp = int(q_arv_tyyp)
except:
pass
pass
if qt_tyyp == 'VastavusYlesanne':
import random
punkte = self.get_text(bcd.getElementsByTagName("setvar")[0])
qt_test = VastavusYlesanne(qt_quiz)
yl = qt.lisaYlesanne(qt_test)
qt_test.seaKirjeldavTekst('',qt_story)
qt_test.normPunktid=float(punkte)
qt_test.viiteURL = qt_linkd
qt_test.viiteTekst = qt_link
qt_test.pilt = photo_data
v_id = []
v_text = []
for xbc in bcd.getElementsByTagName("response_label"):
v_id.append(self.get_attr(xbc,'ident'))
v_text.append(self.get_text(xbc.getElementsByTagName("mattext")[0]))
s_vastused = []
s_kysimused = []
for xbc in bcd.getElementsByTagName("varsubset"):
paar = string.split(self.get_text(xbc),",")
koht_v = v_id.index(paar[0])
koht_p = v_id.index(paar[1])
s_kysimused.append(v_text[koht_v])
s_vastused.append(v_text[koht_p])
s_jarjestus = []
for i in range(len(s_kysimused)):
s_jarjestus.append(i)
random.shuffle(s_jarjestus)
qt_test.kysimused = s_kysimused
qt_test.vastused = s_vastused
qt_test.jarjestus = s_jarjestus
pass
try:
test_map[qt_id] = qt_test
except UnboundLocalError:
#XXX:some test is missing!
pass
self.importTestAnswers(abc,id,test_map)
return
def importAffliationCodes(self, elem):
""" import affiliation codes """
elem.normalize()
for x in elem.getElementsByTagName('affiliation'):
self.iva.fle_users.addAffiliation(self.get_text(x))
return 0
def importServerSettings(self, elem):
""" import server settings """
elem.normalize()
auto = eval(self.get_text(elem.getElementsByTagName('auto_register')[0]).strip())
use_quota = eval(self.get_text(elem.getElementsByTagName('quota')[0]).strip())
quota_amount = self.get_text(elem.getElementsByTagName('quota_amount')[0])
mail_host = self.get_text(elem.getElementsByTagName('mail_host')[0])
mail_port = self.get_attr(elem.getElementsByTagName('mail_host')[0], 'port')
mail_from = self.get_text(elem.getElementsByTagName('mail_from')[0])
def_lang = self.get_text(elem.getElementsByTagName('default_language')[0])
force_pass_change = eval(self.get_text(elem.getElementsByTagName('force_change')[0]).strip())
deny_pass_change = eval(self.get_text(elem.getElementsByTagName('deny_password_change')[0]).strip())
deny_aff_change = eval(self.get_text(elem.getElementsByTagName('deny_affiliation_change')[0]).strip())
self.iva.manage_iva_setup_handler(1, 1, auto, use_quota, quota_amount, mail_host, mail_port, mail_from, def_lang, force_pass_change, deny_pass_change, deny_aff_change)
return 0
def importCourseCats(self, element):
""" import course categories """
element.normalize()
cats = element.getElementsByTagName('categories')[0]
cats_text = self.get_text(cats).strip()
print "cats_text", cats_text, "<<"
cats_eval = eval(cats_text)
cm = self.iva.courses
cm.cCategories = cats_eval
cm._p_changed = True
return 1
def importMailMessages(self,element):
# import inner-mail messages
um = self.iva.fle_users
for cat in element.getElementsByTagName('catalog'):
owner = self.get_attr(cat,'owner')
try:
ui = getattr(um, owner)
except:
# print "kasutajat %s ei leitnud, jätan vahele" % owner
continue
box = ui.kysiKirjadeKataloog()
for mess in cat.getElementsByTagName('message'):
read = int(self.get_attr(mess,'read'))
owncopy = self.get_attr(mess,'owncopy')
title = self.get_text(mess.getElementsByTagName('title')[0])
body = self.get_text(mess.getElementsByTagName('body')[0])
sender = self.get_text(mess.getElementsByTagName('sender')[0])
receiver = self.get_text(mess.getElementsByTagName('receiver')[0])
date = self.get_text(mess.getElementsByTagName('date')[0])
mail = box.lisaKiri(None,title,body,sender,receiver,99999)
mail.loomisaeg = float(date)
if owncopy: mail.omakopi = 1
if read:
mail.loetud = 1
else:
mail.loetud = 0
def importKodutood(self,element):
# impordime kodutööd
kt_koht = getattr(self.kursus,'kodutood')
grupid = []
for assign in element.getElementsByTagName('Assignment'):
try:
orgID = self.get_attr(assign,'originalID')
except:
orgID = ''
tyyp = int(self.get_text(assign.getElementsByTagName('type')[0]))
pkiri = str(self.get_text(assign.getElementsByTagName('title')[0]))
kirjeldus = str(self.get_text(assign.getElementsByTagName('description')[0]))
punkt = float(self.get_text(assign.getElementsByTagName('points')[0]))
try:
res = str(self.get_text(assign.getElementsByTagName('resource')[0]))
except:
res = ''
loppaeg = self.get_text(assign.getElementsByTagName('end')[0])
try:
testiID = str(self.get_text(assign.getElementsByTagName('test')[0]))
except:
testiID = None
try:
for gr in assign.getElementsByTagName('group'):
gnimi = self.get_text(gr)
grupid.append(gnimi)
except:
grupid = None
if res:
sisu = res.split('/')
try:
res = '/courses/'+str(self.kursus.id)+"/"+sisu[3]+"/"+sisu[4]
except:
res = ''
too = kt_koht.lisaKodutoo('request',tyyp,orgID)
too.pealkiri = pkiri
too.kirjeldus = kirjeldus
too.normPunkte = punkt
too.juhend = res
if loppaeg != 'None':
too.loppaeg = float(loppaeg)
# New parameter
too.lockingFolder = 0
if testiID != None:
too.testiID = testiID
if grupid != None:
too.grupid = grupid
return
def handleGrades(self,isik,uid):
for x in isik.getElementsByTagName('interimresult'):
workid = self.get_attr(x, 'resulttype')
try:
points = float(self.get_text(x.getElementsByTagName('result')[0]))
except:
points = ''
try:
s_com = self.get_text(x.getElementsByTagName('comments')[0])
except:
s_com = ''
try:
t_com = self.get_text(x.getElementsByTagName('tcomment')[0])
except:
t_com = ''
if points:
self.kursus.kodutood.setUserPoints(workid,uid,'points',points)
self.kursus.kodutood.setUserPoints(workid,uid,'comment',s_com)
self.kursus.kodutood.setUserPoints(workid,uid,'teacherComment',t_com)
f = isik.getElementsByTagName('finalresult')[0]
try:
grade = float(self.get_text(f.getElementsByTagName('result')[0]))
if grade:
self.kursus.kodutood.setUserOverall(uid,'TotPoints',grade) # TotPoints
except:
pass
try:
comment = self.get_text(f.getElementsByTagName('comments')[0]) #overall comment
self.kursus.kodutood.setUserOverall(uid,'overallComment',comment)
except:
pass
try:
t_com = self.get_text(f.getElementsByTagName('tcomment')[0])
self.kursus.kodutood.setUserOverall(uid,'TotPointsCom',t_com) # TotPointsCom
except:
pass
try:
modpoints = self.get_text(f.getElementsByTagName('grade')[0]) # grade
if modpoints:
self.kursus.kodutood.setUserOverall(uid,'grade',modpoints)
except:
pass
try:
modcomment = self.get_text(f.getElementsByTagName('grade_com')[0]) # gradeCom
self.kursus.kodutood.setUserOverall(uid,'gradeCom',modcomment)
except:
pass
def lisaIsik(self,isik,tyyp,grupinimi=''):
uid = self.get_text(isik.getElementsByTagName('id')[0])
print uid
roll = self.get_attr(isik.getElementsByTagName('role')[0],'roletype')
if tyyp == 'kursus':
try:
self.kursus.add_student(uid)
#handle grades here! interimresult, finalresult
self.handleGrades(isik,uid)
if roll == 'Instructor':
self.kursus.set_roles(uid,('Teacher',))
#else:
#XXX:we already set Student in add_student
#self.kursus.set_roles(uid,('Student',))
except:
pass
else:
sgs = self.kursus.subgroups.getSubgroupByName(grupinimi)
if not sgs:
raise 'IVA import error:', 'Couldn\'t find subgroup %s' % grupinimi
sgs.add_to_subgroup(uid)
#self.kursus.lisa_sisegruppi(grupinimi,uid)
return
def restoreMembership(self,failisisu):
sisegr = self.kursus.subgroups.getSubgroups()
sisegrupid = []
for grupid in sisegr:
sisegrupid.append(grupid.get_name())
for group in failisisu.getElementsByTagName('group'):
id = self.get_text(group.getElementsByTagName('id')[0])
try:
typevalue = self.get_attr(group.getElementsByTagName('typevalue')[0],'level')
except:
typevalue = ''
if str(typevalue) == '1':
try:
orgname = self.get_text(group.getElementsByTagName('orgname')[0])
except:
orgname = 'orgnameorgnameorgname'
# if self.kursus:
# if str(orgname) == str(self.kursus.get_name()):
# pass
for ship in failisisu.getElementsByTagName('membership'):
try:
komm = self.get_text(ship.getElementsByTagName('comments')[0])
except:
komm = ''
ship_id = self.get_text(ship.getElementsByTagName('id')[0])
# k_nimi = self.kursus.get_name()+' *'
# if ship_id+' *' == str(self.kursus.get_name()) == id+' *' and str(komm) == 'KURSUS':
if ship_id == str(self.kursus.get_name()) == id and str(komm) == 'KURSUS':
for isik in ship.getElementsByTagName('member'):
self.lisaIsik(isik,'kursus')
else:
id = self.get_text(group.getElementsByTagName('id')[0])
if not id in sisegrupid:
try:
sgr = self.kursus.subgroups.add_subgroup(id)
sgr.manage_delLocalRoles((self.uname,))
except:
pass
for ship in failisisu.getElementsByTagName('membership'):
try:
komm = self.get_text(ship.getElementsByTagName('comments')[0])
except:
komm = ''
if str(komm) == 'SISEGRUPP':
ship_id = self.get_text(ship.getElementsByTagName('id')[0])
if ship_id == id:
for isik in ship.getElementsByTagName('member'):
self.lisaIsik(isik,'sisegrupp',id)
return
def importUsers(self,element):
um = getattr(self.iva, 'fle_users')
tulem = ""
us_alg = time.time()
for person in element.getElementsByTagName('person'):
print "PERSON!"
roles = []
userid = self.get_text(person.getElementsByTagName('userid')[0])
# if userid=='admin':
# continue
password = self.get_attr(person.getElementsByTagName('userid')[0],'password')
try:
family = self.get_text(person.getElementsByTagName('family')[0])
except:
family = ''
try:
given = self.get_text(person.getElementsByTagName('given')[0])
except:
given = ''
try:
email = self.get_text(person.getElementsByTagName('email')[0])
except:
email = ''
try:
url = self.get_text(person.getElementsByTagName('url')[0])
except:
url = ''
try:
for telephones in person.getElementsByTagName('tel'):
if self.get_attr(telephones,'teltype') == 'Voice':
voice = self.get_text(telephones)
else:
mobile = self.get_text(telephones)
except:
voice = ''
mobile = ''
try:
addr2 = self.get_text(person.getElementsByTagName('extadd')[0])
except:
addr2 = ''
try:
street = self.get_text(person.getElementsByTagName('street')[0])
except:
street = ''
try:
locality = self.get_text(person.getElementsByTagName('locality')[0])
except:
locality = ''
try:
country = self.get_text(person.getElementsByTagName('country')[0])
except:
country = ''
try:
photo_tag = person.getElementsByTagName('photo')[0]
except:
photo_tag = None
print "fotot pole"
if photo_tag:
photo_type = self.get_attr(photo_tag,'imgtype')
photo_location = self.get_text(photo_tag.getElementsByTagName('extref')[0])
photo = self.binarydata.getData(photo_location, self.prefix)
print "sain foto", len(photo)
else:
photo = None
try:
s_r = person.getElementsByTagName('systemrole')[0]
systemrole = self.get_attr(s_r,'systemroletype')
if systemrole == 'SysAdmin':
roles.append('Manager')
except:
systemrole = ''
try:
i_r = self.get_text(person.getElementsByTagName('institutionrole')[0])
inst_role = self.get_attr(i_r,'institutionroletype')
except:
instrole = ''
try:
eriala = self.get_text(person.getElementsByTagName('orgname')[0])
except:
eriala = ''
try:
comm = self.get_text(person.getElementsByTagName('comments')[0])
except:
comm = ''
try:
huvid = self.get_text(person.getElementsByTagName('short')[0])
except:
huvid = ''
try:
amet_huvid = self.get_text(person.getElementsByTagName('long')[0])
except:
amet_huvid = ''
try:
label = self.get_text(person.getElementsByTagName('label')[0])
except:
label = ''
try:
if um.kasKasutajaOlemas(userid) and hasattr(um, userid):
tulem = "kasutaja "+userid+" olemas"
print "kasutaja "+userid+" olemas"
#continue
except AttributeError:
pass
#XXX: we need to do something clever here since acl_users folder does not support some function.
if not um.kasKasutajaOlemas(userid):
um.acl_users._doAddUser(userid,password,[],())
if not hasattr(um, userid):
kasutaja = um.add_user_fle(userid,('Member',))
kasutaja = getattr(um, userid)
print "kasutaja", kasutaja, kasutaja.absolute_url(), um.absolute_url(), "<"
#FIXME: keel
kasutaja.edit_info(given,family,email,eriala,'keel',0,photo,'','',street,addr2,
locality,country,url,voice,mobile,label,comm,huvid,amet_huvid)
print "sättisin info!"
if photo != None:
print "sätin foto"
kasutaja.set_photo(photo,photo_type)
else:
print "kasutaja pole fotot", kasutaja.get_uname()
us_lopp = time.time()
print "Users:",us_lopp-us_alg
return
def test(self,elem, folder, uname, indeks,loop=0):
for bcd in elem.childNodes:
if bcd.nodeType == 1 and bcd.nodeName == 'resource':
pid = self.get_attr(bcd,"identifier")
if indeks[self.eemalda(pid)] == self.eemalda(folder.id):
tyyp = self.get_attr(bcd,'type')
name = self.get_text(bcd.getElementsByTagName("title")[0])
if tyyp == 'file':
data_name = self.get_attr(bcd.getElementsByTagName("file")[0],'href')
data = self.binarydata.getData(data_name,self.prefix)
file = folder.add_file(name,
FakeUpload(name,data,'application/msword'))
if tyyp == 'memo':
sisu = self.get_text(bcd.getElementsByTagName("description")[0])
memo = folder.add_memo(name,sisu)
if tyyp == 'URL':
sisu = self.get_attr(bcd,'href')
link = folder.add_link(name, sisu)
if loop==0:
folder = getattr(folder,folder.id)
self.importItems(elem,folder,uname,indeks)
return folder
def importItems(self, elem, course, uname, indeks,loop=0):
if loop:
self.test(elem,course,uname,indeks,loop=1)
for abc in course.objectValues():
if abc.meta_type == 'WebtopFolder':
folder = getattr(course,abc.id)
self.test(elem,folder,uname, indeks)
return "kala"
def get_text(self,elem):
res=u''
for line in elem.childNodes:
res += line.nodeValue
return to_utf8(res)
def get_attr(self,elem,name):
return to_utf8(elem.getAttribute(name))
def eemalda(self,pid):
try:
number = int(re.sub('[a-zA-Z]','',pid))
except ValueError:
number = 0
return number
def importOrg(self,elem,course):
for abc in elem.getElementsByTagName("organization"):
if self.get_text(abc.getElementsByTagName("title")[0]) == "Raamaturiiul":
nelem = abc
abc = nelem.getElementsByTagName("item")[0]
return abc
def createCourse(self,elem,courses,teacher):
""" creates an empty course, other functions fill this with data
course will be named imported_+exported course name """
vigu = 0
vead = []
try:
title = elem.getElementsByTagName("imsmd:title")[0]
title_c = self.get_text(title.getElementsByTagName("imsmd:langstring")[0])
except:
vigu = vigu +1
vead.append('title')
try:
c_organisation = self.get_text(elem.getElementsByTagName("ivamd:organisation")[0])
except:
c_organisation = ""
vigu = vigu+1
vead.append('c_org')
try:
c_method = self.get_text(elem.getElementsByTagName("ivamd:methods")[0])
except:
c_method = ""
vigu = vigu+1
vead.append('c_method')
try:
c_quote = self.get_text(elem.getElementsByTagName("ivamd:quote")[0])
except:
c_quote = ""
vigu = vigu+1
vead.append('c_quote')
try:
c_status = int(self.get_text(elem.getElementsByTagName("ivamd:status")[0]))
except:
c_status = 0
vigu = vigu+1
vead.append('c_stat')
try:
c_picture_name = self.get_attr(elem.getElementsByTagName("ivamd:picture")[0],"href")
c_picture = self.binarydata.getData(c_picture_name,self.prefix)
except:
c_picture = None
vigu = vigu+1
vead.append('c_pict')
try:
cat = int(self.get_text(elem.getElementsByTagName("organization_sec")[0]))
except:
cat = 0
vigu = vigu + 1
vead.append('cat')
try:
score = self.get_text(elem.getElementsByTagName("score")[0])
except:
score = ""
vigu = vigu + 1
vead.append('score')
try:
code = self.get_text(elem.getElementsByTagName("code")[0])
except:
code = ""
vigu = vigu + 1
vead.append('code')
try:
start_time = self.get_text(elem.getElementsByTagName("start_time")[0])
except:
start_time = ""
vigu = vigu + 1
vead.append('start')
try:
end_time = self.get_text(elem.getElementsByTagName("end_time")[0])
except:
end_time = ""
vigu = vigu + 1
vead.append('end')
try:
desk = elem.getElementsByTagName("imsmd:description")[0]
desk_c = self.get_text(desk.getElementsByTagName("imsmd:langstring")[0])
# title_c = "imported_"+title_c
except:
desk = ''
vigu = vigu+1
vead.append('desk')
try:
uniq_id = self.get_text(elem.getElementsByTagName("uniqID")[0])
except:
uniq_id = None
#vigu = vigu + 1 don't count vigu here
vead.append('uniq_id')
if vigu < 3:
# don't change the below line in haste
# title_c += " *"
id = courses.add_course_impl(teacher)
course = courses.get_child(str(id))
course.remove_person(teacher)
course.update(title_c,desk_c,c_organisation,c_method,float(start_time),float(end_time),c_quote,c_picture,c_status, cCat=cat, credits=score, courseID=code)
#course.kontrolliRyhmaLaud()
course.add_folder('CourseFolder')
return course
else:
#pass
print "vigu:", vigu
print "vead:", vead
print "vigu tekkis liialt palju, jätan kursuse tegemise katki"
#raise 'IVA Error:', 'BLAAH!'
return 0
def lisaSyndmus(self,resource,tiitel):
from Kalender import KalendriSyndmus, KalendriSyndmusteKataloog
import time
for fail in resource.getElementsByTagName('file'):
href = self.get_attr(fail,'href')
syndmused = self.binarydata.getData(str(self.prefix+href))
synd = syndmused.split('\r\n')
synd_p = []
for abc in synd:
try:
if abc[0] == ' ':
eelmine = synd_p.pop()
synd_p.append(eelmine + " "+abc)
else:
synd_p.append(abc)
except:
pass
final = []
for abc in synd_p:
uu = abc.split(':',1)
final.append(uu)
v_cal = 0
v_event = 0
v_loend = 0
for syndmus in final:
# XXX:FIX: need testing
summary = ""
#Time 2005/05/25 10:56:36.475 GMT+3
#User Name (User Id) KristaEskla (KristaEskla)
#Request URL http://iva.htk.tpu.ee/courses/4767/gf/teacher_import_handler
#Exception Type UnboundLocalError
#Exception Value local variable 'summary' referenced before assignment
#
#Traceback (innermost last):
#
#* Module ZPublisher.Publish, line 101, in publish
#* Module ZPublisher.mapply, line 88, in mapply
#* Module ZPublisher.Publish, line 39, in call_object
#* Module Products.iva.Course, line 1236, in teacher_import_handler
#* Module Products.iva.ImportExportIMS, line 2051, in processFile
#* Module Products.iva.ImportExportIMS, line 1915, in otsiTOC
#* Module Products.iva.ImportExportIMS, line 1852, in otsiTarget
#* Module Products.iva.ImportExportIMS, line 1781, in leiaLahendus
#* Module Products.iva.ImportExportIMS, line 2051, in processFile
#* Module Products.iva.ImportExportIMS, line 1915, in otsiTOC
#* Module Products.iva.ImportExportIMS, line 1852, in otsiTarget
#* Module Products.iva.ImportExportIMS, line 1775, in leiaLahendus
#* Module Products.iva.ImportExportIMS, line 1443, in lisaSyndmus
#UnboundLocalError: local variable 'summary' referenced before assignment
if syndmus[0] == 'BEGIN' and syndmus[1] == 'VCALENDAR':
v_cal = 1
if not v_cal:
continue
if syndmus[0] == 'BEGIN' and syndmus[1] == 'VEVENT':
v_event = 1
if not v_event: # no point to collect data
continue # if we don't have event
if syndmus[0] == 'DTSTART' or syndmus[0] == 'DTEND':
temp = syndmus[1]
aeg = []
aeg.append(int(temp[0:4]))
aeg.append(int(temp[4:6]))
aeg.append(int(temp[6:8]))
aeg.append(int(temp[9:11]))
aeg.append(int(temp[11:13]))
aeg.append(int(temp[13:15]))
aeg.append(int(0))
aeg.append(int(0))
aeg.append(int(0))
if syndmus[0] == 'DTSTART':
v_loend = v_loend +1
dtstart = time.mktime(aeg)
if syndmus[0] == 'DTEND':
v_loend = v_loend +1
dtend = time.mktime(aeg)
if syndmus[0] == 'N':
v_loend = v_loend +1
n = syndmus[1]
if syndmus[0] == 'DESCRIPTION':
v_loend = v_loend +1
desc = syndmus[1]
if syndmus[0] == 'SUMMARY':
v_loend = v_loend +1
summary = syndmus[1]
if syndmus[0] == 'STATUS':
v_loend = v_loend +1
status = int(syndmus[1])
if syndmus[0] == 'CUTYPE':
v_loend = v_loend +1
cutype = syndmus[1]
if syndmus[0] == 'URL':
v_loend = v_loend +1
url = syndmus[1]
if syndmus[0] == 'X-PROPERTY;VALUE=NAME':
v_loend = v_loend +1
name = syndmus[1]
if syndmus[0] == 'RESOURCES':
v_loend = v_loend +1
res = syndmus[1]
if syndmus[0] == 'END' and syndmus[1] == 'VCALENDAR':
break
if not v_cal:
continue
if syndmus[0] == 'END' and syndmus[1] == 'VEVENT':
if v_loend > 5:
# try make an event
koht = None
if cutype == 'INDIVIDUAL':
try:
temp = getattr(self.iva.fle_users, n)
koht = getattr(temp, 'syndmused')
except:
pass
if cutype == 'GROUP':
try:
temp = getattr(self.iva.courses, str(self.kursus.get_id()))
except AttributeError:
print "XXXX: we couldn't find a course we should have made!"
continue
if n == 'kursus':
try:
koht = getattr(temp, 'syndmused')
except AttributeError:
print koht
print temp
print temp.absolute_url(), self.kursus.get_id()
#koht = temp.kysiSyndmusteKataloog()
else:
try:
temp2 = getattr(temp.subgroups, n)
koht = getattr(temp2, 'syndmused')
except:
loodud = self.kursus.subgroups.add_subgroup(n)
loodud.manage_delLocalRoles((self.uname,))
koht = getattr(loodud, 'syndmused')
if not koht:
break # no place to event
syndmus = koht.lisaSyndmusKohe(name, desc, dtstart, dtend, url, res, status)
self.set_omanik(syndmus, self.owner)
v_event = 0
v_loend = 0
if not v_event:
continue
return
def ImportUserEvents(self,resource,tiitel):
for org in resource.getElementsByTagName('organization'):
id = self.get_attr(org,'identifier')
temp = id.split('_')
juuser = temp[1]
self.owner = juuser
for item in org.getElementsByTagName('item'):
idref = self.get_attr(item,'identifierref')
tiitel = self.get_text(item.getElementsByTagName('title')[0])
self.otsiTarget(idref,resource,tiitel)
self.owner = self.uname
return
def add_file_metadata(self,object,element):
""" file metadata extraction and handling here only """
try:
md = element.getElementsByTagName('metadata')[0]
creationtime = float(self.get_attr(md,'creationtime'))
object.set_timestamp(creationtime)
except:
pass
for an in element.getElementsByTagName('annotation'):
type = self.get_attr(an, 'parameters')
if type != 'comment':
continue
person = self.get_text(an.getElementsByTagName('person')[0])
date = float(self.get_text(an.getElementsByTagName('date')[0]))
desc = self.get_text(an.getElementsByTagName('description')[0])
status = int(self.get_text(an.getElementsByTagName('status')[0]))
value = self.get_text(an.getElementsByTagName('value')[0])
object.postComment(None,'add',desc,value,status,person,date)
try:
p = element.getElementsByTagName('permission')[0]
except:
return
status = int(self.get_text(p.getElementsByTagName('status')[0])) #permission status actually
object.setObjPermission(status)
position = int(self.get_text(p.getElementsByTagName('position')[0]))
object.weight = position
tl = p.getElementsByTagName('timelimits')[0]
tend = float(self.get_attr(tl, 'end'))
tstart = float(self.get_attr(tl, 'start'))
object.setTimeLimits(tstart,tend)
tfunc = int(self.get_text(tl))
object.setTimeFunc(tfunc)
docstatus = int(self.get_text(p.getElementsByTagName('docstatus')[0]))
object.setStatus(docstatus)
commentable = int(self.get_text(p.getElementsByTagName('commentable')[0]))
object.setCommentable(commentable)
comment_view = int(self.get_attr(p.getElementsByTagName('commentable')[0],'view'))
object.setCommentsVisible(comment_view)
rateable = int(self.get_text(p.getElementsByTagName('rateable')[0]))
object.setRateable(rateable)
rate_view = int(self.get_attr(p.getElementsByTagName('rateable')[0],'view'))
object.setRatingVisible(rate_view)
return
def add_folder_metadata(self,object,element):
""" folder metadata extraction here ONLY! """
#try:
# pres = self.get_attr(element,'presentation')
# if pres == '1':
# object.seaEsitluskaust(int(pres))
#except AttributeError:
# pass
try:
md = element.getElementsByTagName('metadata')[0]
#XXX: We don't have any metadata. Happened when exported just a wiki
except IndexError:
return
try:
creationtime = float(self.get_attr(md,'creationtime'))
object.set_timestamp(creationtime)
except:
pass
for an in element.getElementsByTagName('annotation'):
type = self.get_attr(an, 'parameters')
if type != 'visit':
continue
person = self.get_text(an.getElementsByTagName('person')[0])
date = float(self.get_text(an.getElementsByTagName('date')[0]))
# TODO:XXX: viewedObject()
#object.kylastus(None,person,date)
try:
p = element.getElementsByTagName('permission')[0]
except:
return
status = int(self.get_text(p.getElementsByTagName('status')[0])) #permission status actually
object.setObjPermission(status)
position = int(self.get_text(p.getElementsByTagName('position')[0]))
object.weight = position
tl = p.getElementsByTagName('timelimits')[0]
tend = float(self.get_attr(tl, 'end'))
tstart = float(self.get_attr(tl, 'start'))
object.setTimeLimits(tstart,tend)
tfunc = int(self.get_text(tl))
object.setTimeFunc(tfunc)
return
def handleMetadata(self,element):
try:
format = self.get_text(element.getElementsByTagName('imsmd:format')[0])
except:
format = 'application/msword'
return format
def set_omanik(self,obj,omanik):
try:
obj.manage_setLocalRoles(omanik, ('Owner',))
acl = self.iva.fle_users.leiaKasutajaKataloog(omanik)
acl_user = acl.aq_inner.getUser(omanik)
obj.changeOwnership(self.iva.acl_users.getUser(omanik).__of__(self.iva.acl_users))
except:
return 0
return 1
def handleResource(self,resource,asukoht,resour,tiitel=''):
tyyp = self.get_attr(resource,'type')
for element in resource.childNodes:
# otsi ja leia failid, memod jms
if element.nodeName == 'dependency':
idref = self.get_attr(element, 'identifierref')
self.otsiTarget(idref,resour,'MISC STUFF',asukoht)
if element.nodeName != 'file':
#vőib vajada fixi.
continue
else:
tekst = ''
orgID = ''
xml_real_name = ''
try:
href = self.get_attr(element,'href')
except:
pass
try:
tekst = self.get_text(element.getElementsByTagName('imsmd:title')[0])
except:
pass
try:
if not tekst:
tekst = self.get_text(element.getElementsByTagName('title')[0])
except:
pass
try:
xml_real_name = self.get_attr(element.getElementsByTagName('imsmd:title')[0],'realname')
except:
pass
try:
orgID = self.get_attr(element.getElementsByTagName('imsmd:title')[0],'originalID')
except:
pass
try:
orgID = self.get_attr(element.getElementsByTagName('title')[0],'originalID')
except:
pass
try:
orgOwner = self.get_attr(element.getElementsByTagName('imsmd:title')[0],'originalOwner')
except:
pass
try:
orgOwner = self.get_attr(element.getElementsByTagName('title')[0],'originalOwner')
except:
pass
if tyyp == 'file' or tyyp == 'webcontent':
fail_alg = time.time()
# FIXFIXFIX: faili formatt
try:
format = self.handleMetadata(element.getElementsByTagName('metadata')[0])
except:
format = 'application/msword'
href = self.get_attr(element,'href')
data_alg = time.time()
data = self.binarydata.getData(str(self.prefix+href))
data_lopp = time.time()
print "Faili lugemine",data_lopp-data_alg
# FIX: file type
number = 1
if not tekst:
tekst = tiitel
number = 0
lisa_alg = time.time()
if len(orgID)>3:
if orgID[-4] == '.': # .doc or something
realname = orgID
if xml_real_name:
realname = xml_real_name
else:
realname = ''
fail = asukoht.add_file(tekst,FakeUpload(tekst,data,format),realname)
lisa_lopp = time.time()
print "lisa fail:",lisa_lopp-lisa_alg
result = self.set_omanik(fail,orgOwner)
if not result:
self.set_omanik(fail,self.owner)
self.add_file_metadata(fail,element)
fail_lopp = time.time()
print "Fail:",fail_lopp-fail_alg
if tyyp == 'memo':
data = self.binarydata.getData(str(self.prefix+href))
memo = asukoht.add_memo(tekst,data)
# memo.set_author(self.owner)
memo.manage_delLocalRoles((self.uname,))
result = self.set_omanik(memo,orgOwner)
if not result:
self.set_omanik(memo,self.owner)
self.add_file_metadata(memo,element)
if tyyp == 'URL':
link = asukoht.add_link(tekst,href)
# link.set_author(self.owner)
link.manage_delLocalRoles((self.uname,))
result = self.set_omanik(link,orgOwner)
if not result:
self.set_omanik(link,self.owner)
self.add_file_metadata(link,element)
#XXX:wikipages and owners
if tyyp == 'wikipage':
if hasattr(asukoht.aq_inner.aq_self, tiitel):
# wikipage = getattr(asukoht, tiitel)
asukoht._delObject(tiitel)
data = self.binarydata.getData(str(self.prefix+href))
# wikipage = ZWikiPage(source_string=data, __name__=tiitel)
wikipage = ZWikiPage(source_string=data, __name__=tiitel)
parent = [self.wikiparent]
wikipage.parents = parent
#XXX: we d'nt catalog wikis.
# wikipage.index_object()
asukoht._setObject(tiitel,wikipage)
# wikipage += 'lammas tuli külla!!'
if tyyp == 'wikiimage' or tyyp == 'wikifile':
if hasattr(asukoht.aq_inner.aq_self, tiitel):
asukoht._delObject(tiitel)
data = self.binarydata.getData(str(self.prefix+href))
if tyyp == 'wikiimage':
asukoht._setObject(tiitel, OFS.Image.Image(tiitel,tiitel,''))
else:
asukoht._setObject(tiitel, OFS.Image.File(tiitel,tiitel,''))
asukoht._getOb(tiitel).manage_upload(data)
return
def createFolder(self,asukoht,nimi,orgID='',orgOwner=''):
#XXX: we should try to handle real object id here somehow!
# loo kaust
# try:
print ">>>>>>>>>>>> KAUSTA <<<"
print asukoht.absolute_url()
print nimi, asukoht.meta_type
if 1==1:
# handle folder with id "esitlused" - it's Portfolio() now.
if orgID == 'esitlused':
print "tegin esitlised"
kaust = asukoht.add_portfolio()
else:
if asukoht.meta_type == 'Portfolio' and orgID.startswith('too'):
# if we're in portfolio, add AssignmentProxy.
kaust = asukoht.createAssignmentProxy(orgID, self.kursus.get_id())
else:
kaust = asukoht.add_folder(nimi,orgID)
if orgOwner:
self.set_omanik(kaust, orgOwner)
else:
self.set_omanik(kaust, self.owner)
# except:
return kaust
def otsiItemid(self,item,tiitel,asukoht,resour,start=0):
# resources tagi ka siia tooma
try:
params = self.get_attr(item,'parameters')
except:
params = ''
tit = self.get_text(item.getElementsByTagName('title')[0])
try:
orgID = self.get_attr(item.getElementsByTagName('title')[0],'originalID')
except:
orgID = ''
try:
orgOwner = self.get_attr(item.getElementsByTagName('title')[0],'originalOwner')
except:
orgOwner = ''
if not start:
if not self.testonly:
uusfolder = self.createFolder(asukoht,tit,orgID,orgOwner)
self.add_folder_metadata(uusfolder,item)
# asukoht = getattr(asukoht,tit)
idref = self.get_attr(item,'identifierref')
try:
self.otsiTarget(idref,resour,'MISC STUFF',getattr(asukoht,uusfolder.id),params)
except:
self.otsiTarget(idref,resour,'MISC STUFF',asukoht,params)
for bcd in item.childNodes:
if bcd.nodeType == 1 and bcd.nodeName == 'item':
#otsi itemi tiitel
#otsi identifierref
try:
temp = getattr(asukoht,uusfolder.id)
except:
temp = asukoht
self.otsiItemid(bcd,tiitel,temp,resour)
return
def otsiWikid(self,item,tiitel,asukoht,resour,start=0,vanem=''):
tit = self.get_text(item.getElementsByTagName('title')[0])
self.wikiparent = ''
idref = self.get_attr(item,'identifierref')
start = 0
if not start:
self.wikiparent = vanem
self.otsiTarget(idref,resour,tit,asukoht)
for bcd in item.childNodes:
if bcd.nodeType == 1 and bcd.nodeName == 'item':
temp = tit
self.otsiWikid(bcd,tiitel,asukoht,resour,vanem=temp)
return
def leiaLahendus(self,target,tiitel,asukoht='',resour='',params=''):
try:
xmlbase = self.get_attr(target,'xml:base')
except:
xmlbase = ''
type = self.get_attr(target,'type')
href = self.get_attr(target,'href')
if params == 'wikifolder' and not self.testonly:
wiki_resour = target.getElementsByTagName('resources')[0]
# for wiki_items in target.getElementsByTagName('item'):
#XXX: we try and except since something happened here what should not happen
try:
wiki_items = target.getElementsByTagName('item')[0]
except IndexError:
return
self.otsiWikid(wiki_items,tiitel,asukoht,wiki_resour,start=1)
return
if re.search('webcontent',type) and not self.testonly: # läheb raamaturiiulile
# temp = getattr(self.iva.courses, self.kursus.get_id())
# asukoht = getattr(temp, 'gf')
self.handleResource(target,asukoht,resour,tiitel)
if re.search('file',type) or re.search('memo',type) or re.search('URL',type) or re.search('wiki',type):
if not self.testonly:
print "testonly: ",self.testonly
self.handleResource(target,asukoht,resour,tiitel)
if re.search('Calenda',type) and not self.testonly:
self.lisaSyndmus(target,tiitel)
if re.search('imscp',type):
if not self.kursus:
self.kursus = self.coursemanager
abc = Importer(self.uname,self.iva,xmlbase,self.kursus,self.binarydata,userwikionly=self.userwikionly,kasuta_jooksvat=self.kasuta_jooksvat,testonly=self.testonly)
try:
failisisu = abc.loadFile(self.prefix+xmlbase+href)
except KeyError:
return
abc.processFile(self.kursus,failisisu)
self.processed.append(target)
if re.search('imsqti',type):
abc = Importer(self.uname,self.iva,self.prefix+xmlbase,self.kursus,self.binarydata,userwikionly=self.userwikionly,kasuta_jooksvat=self.kasuta_jooksvat,testonly=self.testonly)
failisisu = abc.loadFile(self.prefix+xmlbase+href)
abc.processFile(self.kursus,failisisu)
self.processed.append(target)
if re.search('meediapaja',type) or re.search('teadmuspaja',type) or params == 'Assignments' and not self.testonly:
abc = Importer(self.uname,self.iva,self.prefix+xmlbase,self.kursus,self.binarydata,userwikionly=self.userwikionly,kasuta_jooksvat=self.kasuta_jooksvat,testonly=self.testonly)
failisisu = abc.loadFile(self.prefix+xmlbase+href)
abc.processFile(self.kursus,failisisu)
self.processed.append(target)
if re.search('SYNDMUSED',tiitel) and not self.testonly:
self.ImportUserEvents(target,tiitel)
if params == 'RAAMATURIIUL' and not self.testonly:
r_res = target.getElementsByTagName('resources')[0]
for r_org in target.getElementsByTagName('organization'):
self.otsiTOC(r_org, r_res)
if params == 'RYHMALAUAD' and not self.testonly:
tmpasukoht = self.riiuliasukoht
self.riiuliasukoht = getattr(self.kursus,'subgroups')
r_res = target.getElementsByTagName('resources')[0]
for r_org in target.getElementsByTagName('organization'):
self.otsiTOC(r_org, r_res,subgroup=1)
self.riiuliasukoht = tmpasukoht
if params == 'SISEGRUPP' and not self.testonly:
tmpasukoht = self.riiuliasukoht
self.riiuliasukoht = getattr(self.kursus,'subgroups')
s_res = target.getElementsByTagName('resources')[0]
for s_org in target.getElementsByTagName('organization'):
s_nimi = self.get_attr(s_org,'identifier').split(':')[1]
sgs = self.riiuliasukoht.getSubgroupByName(s_nimi)
if not sgs:
print "teen gruppi!",s_nimi
ssg = self.riiuliasukoht.add_subgroup(s_nimi)
ssg.manage_delLocalRoles((self.uname,))
#XXX:subgroup name mapping!
self.riiuliasukoht = self.riiuliasukoht.getSubgroupByName(s_nimi)
if not self.riiuliasukoht:
self.riiuliasukoht = self.kursus.subgroups.add_subgroup(s_nimi)
self.riiuliasukoht.manage_delLocalRoles((self.uname,))
if not self.riiuliasukoht:
print self.kursus.subgroups.objectValues()
raise 'IVA import Error:', 'Subgroup creation failed.'
self.otsiTOC(s_org,s_res)
self.riiuliasukoht = tmpasukoht
if params == 'KASUTAJATE WEBTOPID' or params == 'KASUTAJATE SAHTLID' and not self.testonly:
tmpasukoht = self.riiuliasukoht
u_res = target.getElementsByTagName('resources')[0]
for u_org in target.getElementsByTagName('organization'):
u_ident = self.get_attr(u_org,'identifier').split('_')[1]
self.owner = u_ident
#XXX: we didn't export admin in previous versions and we're in
# trouble now ;(
if not hasattr(self.kursus.fle_users, u_ident):
continue
if params == 'KASUTAJATE SAHTLID':
tmp = getattr(self.kursus.fle_users, u_ident).webtop
else:
tmp = getattr(self.kursus.fle_users, u_ident).webtop
if not hasattr(tmp, 'c'+str(self.kursus.id)):
#cf = tmp.lisa_kursuse_kaust_ilma_requestita(self.owner,str('c'+str(self.kursus.id)))
cf = tmp.add_folder( str('c'+str(self.kursus.id)), str('c'+str(self.kursus.id)) )
cf.set_author(self.owner)
self.set_omanik(cf,self.owner)
self.riiuliasukoht = getattr(tmp, 'c'+str(self.kursus.id))
self.otsiTOC(u_org, u_res)
self.owner = self.uname
self.riiuliasukoht = tmpasukoht
return
def otsiTarget(self,identifier,ressursid,tiitel,asukoht='',params=''):
for target in ressursid.getElementsByTagName("resource"):
id = self.get_attr(target,'identifier')
if id == identifier and not self.vaataKasTehtud(target):
self.leiaLahendus(target,tiitel,asukoht,ressursid,params)
self.processed.append(target)
return
if id == identifier and self.vaataKasTehtud(target):
#print "---------------- leidsime sobiva kuid see oli juba tehtud :( jama!!!! target1"
pass
for target in self.root.getElementsByTagName("manifest"):
id = self.get_attr(target,'identifier')
if id == identifier and not self.vaataKasTehtud(target):
self.leiaLahendus(target,tiitel,asukoht,ressursid,params=params)
self.processed.append(target)
return
if id == identifier and self.vaataKasTehtud(target):
#print "---------------- leidsime sobiva kuid see oli juba tehtud :( jama!!!! target2"
pass
for target in self.root.getElementsByTagName("organization"):
id = self.get_attr(target,'identifier')
if id == identifier and not self.vaataKasTehtud(target):
self.leiaLahendus(target,tiitel,asukoht,ressursid,params=params)
self.processed.append(target)
return
if id == identifier and self.vaataKasTehtud(target):
pass
#print "---------------- leidsime sobiva kuid see oli juba tehtud :( jama!!!!otsiTarget3"
#print "identifieri " + identifier + " pole vőimalik leida"
return
def otsiTOC(self,element,ressursid,subgroup=0):
#XXX:keyword subgroup should go away, it's needed to import iva ver 0.4.2 subgroup portfolios
for target in element.childNodes:
if not target.nodeName == 'item':
continue
identifier = self.get_attr(target,'identifier')
try:
identifierref = self.get_attr(target,'identifierref')
except:
identifierref = ''
try:
params = self.get_attr(target,'parameters')
except:
params = ''
tiitel = self.get_text(target.getElementsByTagName('title')[0])
try:
orgID = self.get_attr(target.getElementsByTagName('title')[0],'originalID')
except:
orgID = ''
try:
orgOwner = self.get_attr(target.getElementsByTagName('title')[0],'originalOwner')
except:
orgOwner = ''
if self.vaataKasTehtud(target):
continue
else:
self.processed.append(target)
if identifierref:
if params == 'wikifolder':
tmp = self.riiuliasukoht
self.riiuliasukoht = self.riiuliasukoht.add_wiki(tiitel, 1)
self.add_folder_metadata(self.riiuliasukoht,target)
if orgOwner:
self.set_omanik(self.riiuliasukoht, orgOwner)
else:
self.set_omanik(self.riiuliasukoht, self.owner)
self.otsiTarget(identifierref, ressursid, tiitel,asukoht=self.riiuliasukoht,params=params)
if params == 'wikifolder':
self.riiuliasukoht = tmp
else:
#XXX:That's freaky stuff.
if not subgroup:
if not self.testonly:
self.riiuliasukoht = self.createFolder(self.riiuliasukoht, tiitel,orgID,orgOwner)
self.add_folder_metadata(self.riiuliasukoht,target)
else:
m = self.riiuliasukoht.objectValues()
korras = 0
sgs = self.riiuliasukoht.getSubgroupByName(tiitel)
if not sgs:
self.kursus.subgroups.add_subgroup(tiitel)
sgp = self.riiuliasukoht.getSubgroupByName(tiitel)
sgp.manage_delLocalRoles((self.uname,))
korras = 1
if sgs:
korras = 1
self.riiuliasukoht = self.kursus.subgroups.getSubgroupByName(tiitel)
#for x in m:
# if x.get_id() == tiitel:
# self.riiuliasukoht = getattr(self.riiuliasukoht, x.get_id())
# korras = 1
# break
if not korras:
self.riiuliasukoht = self.kursus.subgroups.add_subgroup(tiitel)
self.riiuliasukoht.manage_delLocalRoles((self.uname,))
#self.riiuliasukoht = getattr(self.riiuliasukoht, kaust)
self.otsiTOC(target, ressursid)
if not self.testonly:
self.riiuliasukoht = self.riiuliasukoht.aq_parent
return
def processZip2(self):
""" ... """
kaustad = []
abc = self.root.getElementsByTagName("organizations")[0]
for i in abc.getElementsByTagName("organization"):
kaustad.append(self.get_attr(i,'xml:base'))
return kaustad
def vaataKasTehtud(self,element):
for abc in self.processed:
if element.isSameNode(abc):
return 1
return 0
def otsiKasKasutajaid(self,element):
try:
res_xmlbase = self.get_attr(element,'xml:base')
except:
res_xmlbase = ''
for res in element.getElementsByTagName('resource'):
if re.search('imsent',self.get_attr(res,'type')) and not self.vaataKasTehtud(res):
try:
xmlbase = self.get_attr(res,'xml:base')
except:
xmlbase = ''
try:
href = self.get_attr(res.getElementsByTagName('file')[0],'href')
except:
return
abc = Importer(self.uname,self.iva,self.prefix+xmlbase,self.kursus,self.binarydata,userwikionly=self.userwikionly,kasuta_jooksvat=self.kasuta_jooksvat,testonly=self.testonly)
failisisu = abc.loadFile(self.prefix+xmlbase+href)
abc.processFile(self.kursus,failisisu)
# self.importUsers(res)
self.processed.append(res)
if not failisisu:
failisisu = ''
return failisisu
for res in self.root.getElementsByTagName('resource'):
if re.search('imsent',self.get_attr(res,'type')) and not self.vaataKasTehtud(res):
# self.importUsers(res)
# self.processed.append(res)
abc = Importer(self.uname,self.iva,self.prefix+xmlbase,self.kursus,self.binarydata,userwikionly=self.userwikionly,kasuta_jooksvat=self.kasuta_jooksvat,testonly=self.testonly)
failisisu = abc.loadFile(self.prefix+xmlbase+href)
abc.processFile(self.kursus,failisisu)
self.processed.append(res)
return failisisu
return
def otsiAlgandmed(self,elem):
try:
metadata = elem.getElementsByTagName("metadata")[0]
except:
pass
#raise 'IVA Error','Missing toplevel-manifest metadata element'
try:
resources = elem.getElementsByTagName("resources")[0]
except:
pass
#raise 'IVA Error','Missing toplevel-manifest resources element'
try:
organizations = elem.getElementsByTagName("organizations")[0]
except:
raise 'IVA Error','Missing toplevel-manifest organizations element'
return metadata, organizations, resources
def processFile(self,coursemanager,element):
""" process zip and find anything usable. """
proc_alg = time.time()
self.owner = self.uname
self.coursemanager = coursemanager
i = 0
kas_kursus = 0
#for organizations in self.root.getElementsByTagName("organizations"):
#self.kursus = self.createCourse(self.root.getElementsByTagName('metadata')[0],coursemanager,uname)
st_elem = element.firstChild
self.root = element.firstChild
# return
success = self.kontrolliEsimeneElement(st_elem,coursemanager)
if success:
return
# Siit edasi eeldame, et tegemist on CP-ga
ok = 0
j = 0
try:
st_elem = element.getElementsByTagName("manifest")[0]
except IndexError:
print "XXX:for now, we totally failed reading file."
return
self.root = st_elem
metadata,orgnz, resources = self.otsiAlgandmed(st_elem)
if not self.userwikionly and not self.testonly and not self.kasuta_jooksvat:
kas_kursus = self.createCourse(metadata,coursemanager,self.uname)
if kas_kursus:
self.kursus = kas_kursus
self.riiuliasukoht = getattr(self.kursus, 'gf')
else:
self.riiuliasukoht = ''
#print "sellest failist ei saanud kursust teha\nProovin kasutada jooksvat kursust"
if self.userwikionly:
self.riiuliasukoht = self.userwikionly
if self.kasuta_jooksvat:
self.riiuliasukoht = getattr(self.kursus, 'gf')
failisisu = self.otsiKasKasutajaid(resources)
for org in orgnz.childNodes:
if org.nodeName == 'organization':
self.otsiTOC(org,resources)
# kursus ja sisegrupid peaksid olema nüüd loodud. paigutan kasutajad.
if failisisu and not self.userwikionly and not self.testonly and not self.kasuta_jooksvat:
self.restoreMembership(failisisu)
proc_lopp = time.time()
print "Process Zip:",proc_lopp-proc_alg
def loadZip(self,file):
zip = zipfile.ZipFile(file,"r",zipfile.ZIP_DEFLATED)
for name in zip.namelist():
# if not re.search('imsmanifest.xml',name):
self.binarydata.restoreData(name,zip.read(name))
zip.close()
def loadFile(self,nimi):
xmlstring = self.binarydata.getData(nimi)
print "loen faili: ",nimi
try:
fish = xml.dom.minidom.parseString(xmlstring)
except UnicodeError, ExpatError:
print "XML data is not utf-8 encoded! Detecting encoding..."
encoding = re.search('encoding="([-a-zA-Z0-9]*)">',xmlstring).group(1)
print "Transforming from %s to utf-8..." % encoding
xmlstring = unicode(xmlstring,encoding).encode("utf-8")
fish = xml.dom.minidom.parseString(xmlstring)
return fish
def kontrolliEsimeneElement(self,element,courses):
if self.testonly and element.nodeName!='questestinterop':
try:
element = element.getElementsByTagName("questestinterop")[0]
except:
pass
if element.nodeName =='MailMessages':
if self.userwikionly or self.testonly:
return "kala"
self.importMailMessages(element)
return "MM"
if element.nodeName == 'CourseCats':
if self.userwikionly or self.testonly:
return "kala"
self.importCourseCats(element)
return "CC"
if element.nodeName == 'Affiliations':
if self.userwikionly or self.testonly:
return "kala"
self.importAffliationCodes(element)
return "AC"
if element.nodeName == 'Settings':
if self.userwikionly or self.testonly:
return "kala"
self.importServerSettings(element)
return "IS"
if element.nodeName == 'questestinterop':
if self.userwikionly:
return "kala"
#Jump to qti import
self.importQT(element,self.kursus,self.uname)
return "QT"
if element.nodeName == 'enterprise':
if self.userwikionly or self.testonly:
return "kala"
#FIX: 1st element is DocumentType
abc = element.nextSibling
if not self.kasuta_jooksvat:
self.importUsers(abc)
else:
print "users not imported"
#Jump to user import
return "EP"
if element.nodeName == 'Assignments':
if self.userwikionly or self.testonly:
return "kala"
self.importKodutood(element)
return "Ass"
if element.nodeName == 'Jamming':
if self.userwikionly or self.testonly:
return "kala"
print " import Jamming"
kala = Exporter(self.iva,prefix=self.prefix)
kala.binarydata = self.binarydata
kala.importJamming(element,self.kursus)
return "MP"
if element.nodeName == 'KnowledgeBuilding':
if self.userwikionly or self.testonly:
return "kala"
print " import KnowledgeBuilding"
kala = Exporter(self.iva,prefix=self.prefix)
kala.binarydata = self.binarydata
for ctx in element.childNodes:
kala.importContext(ctx,self.kursus)
return "TP"
return 0
class kirjutaYldM:
def __init__(self):
self.mainmani = Document()
self.root_element = self.mainmani.createElement("manifest")
self.root_element.setAttribute('identifier','IVA')
self.root_element.setAttribute('version','1')
self.root_element.setAttribute('xmlns','http://www.imsproject.org/xsd/ims_cp_rootv1p1')
self.root_element.setAttribute('xmlns:imsmd','http://www.imsproject.org/xsd/ims_md_rootv1p1.xsd')
self.root_element.setAttribute('xmlns:xsi','http://www.w3.org/2000/10/XMLSchema-instance')
self.root_element.setAttribute('xsi:schemaLocation','http://www.imsproject.org/xsd/ims_cp_rootv1p1 http://www.imsproject.org/xsd/ims_cp_rootv1p1.xsd http://www.imsproject.org/xsd/ims_md_rootv1p1 http://www.imsproject.org/xsd/ims_md_rootv1p1.xsd')
self.mainmani.appendChild(self.root_element)
md=self.mainmani.createElement("metadata")
self.root_element.appendChild(md)
mds=self.mainmani.createElement('schema')
md.appendChild(mds)
text = self.mainmani.createTextNode('IMS Content')
mds.appendChild(text)
mdv=self.mainmani.createElement('schemaversion')
md.appendChild(mdv)
mdv.appendChild(self.mainmani.createTextNode('1.1'))
rek = self.mainmani.createElement('imsmd:record')
md.appendChild(rek)
gen = self.mainmani.createElement('imsmd:general')
rek.appendChild(gen)
tit = self.mainmani.createElement('imsmd:title')
gen.appendChild(tit)
lang = self.mainmani.createElement('imsmd:langstring')
lang.setAttribute('xml:lang','en-US')
lang.appendChild(self.mainmani.createTextNode('Data exported from IVA. See http://www.htk.tpu.ee/iva'))
tit.appendChild(lang)
self.organizations = self.mainmani.createElement("organizations")
self.root_element.appendChild(self.organizations)
self.organization = self.mainmani.createElement("organization")
self.organization.setAttribute('identifier','courses')
self.organizations.appendChild(self.organization)
self.ress = self.mainmani.createElement("resources")
self.root_element.appendChild(self.ress)
def kirjutaYldmanifest(self, kursusenr=0, kirjeldus='kirjeldus',tyyp='imscp_xmlv1p1p3',base='course/',href='imsmanifest.xml'):
m = self.mainmani.createElement("item")
m.setAttribute('identifier','item_'+str(kursusenr))
m.setAttribute('identifierref','resource_'+str(kursusenr))
# m.setAttribute('identifier','course'+str(kursusenr))
self.organization.appendChild(m)
title = self.mainmani.createElement("title")
title.appendChild(self.mainmani.createTextNode(kirjeldus))
m.appendChild(title)
item = self.mainmani.createElement("resource")
item.setAttribute('identifier','resource_'+str(kursusenr))
item.setAttribute('type',tyyp)
if base != "":
item.setAttribute('xml:base',base)
item.setAttribute('href',href)
item_title = self.mainmani.createElement('file')
item_title.setAttribute('href',href)
item.appendChild(item_title)
self.ress.appendChild(item)
return m
def lisaFaili(self, failinimi="ivaarhiiv.zip"):
"Lisatakse yldmanifest zip'i"
if zipfile.is_zipfile(failinimi):
zip = zipfile.ZipFile(failinimi,"a",zipfile.ZIP_DEFLATED)
else:
zip = zipfile.ZipFile(failinimi,"w",zipfile.ZIP_DEFLATED)
dump = Dump()
self.mainmani.writexml(dump)
zip.writestr(zipfile.ZipInfo("imsmanifest.xml"),dump.getdata())
zip.close()
class Kirjutus:
import string
def __init__(self, ivajuur, kursusenr):
""" Uue eksportkirjutaja loomine. Parameetrina eksporditava iva juurobjekt """
self.generateID() # just in case
self.iva = ivajuur
if kursusenr != None and kursusenr != 0:
self.kursus = getattr(ivajuur.courses, str(kursusenr))
self.kursusenr = kursusenr
else:
self.kursusenr = 0
self.kursus = None
return
def looKursuseFail(self,metadata=1):
# kursuse faili loomine
# must be called before other functions
self.binarydata = DataTable()
self.idmap = {}
self.dom=Document()
self.loendur=Counter()
# valmistame ette dokumendi
self.root=self.dom.createElement("manifest")
self.dom.appendChild(self.root)
self.root.setAttribute('identifier','IVA')
self.root.setAttribute('version','1')
self.root.setAttribute('xmlns','http://www.imsproject.org/xsd/ims_cp_rootv1p1')
self.root.setAttribute('xmlns:imsmd','http://www.imsproject.org/xsd/ims_md_rootv1p1.xsd')
self.root.setAttribute('xmlns:xsi','http://www.w3.org/2000/10/XMLSchema-instance')
self.root.setAttribute('xmlns:ivamd','http://www.htk.tpu.ee/%7Evahur/ivaplus.xsd')
self.root.setAttribute('xsi:schemaLocation','http://www.imsproject.org/xsd/ims_cp_rootv1p1 http://www.imsproject.org/xsd/ims_cp_rootv1p1.xsd http://www.imsproject.org/xsd/ims_md_rootv1p1 http://www.imsproject.org/xsd/ims_md_rootv1p1.xsd http://www.htk.tpu.ee/%7Evahur/ivaplus http://www.htk.tpu.ee/%7Evahur/ivaplus.xsd')
if metadata:
metadata = self.dom.createElement("metadata")
schema = self.dom.createElement("schema")
schema_data = self.dom.createTextNode("IMS Content")
schema.appendChild(schema_data)
schema_ver = self.dom.createElement("schemaversion")
schema_ver_data = self.dom.createTextNode("1.1")
schema_ver.appendChild(schema_ver_data)
metadata.appendChild(schema)
metadata.appendChild(schema_ver)
md_methods = self.dom.createElement('ivamd:methods')
md_methods_data = self.dom.createTextNode(self.kursus.get_methods())
md_methods.appendChild(md_methods_data)
metadata.appendChild(md_methods)
md_organisation = self.dom.createElement('ivamd:organisation')
md_organisation_data = self.dom.createTextNode(self.kursus.get_organisation())
md_organisation.appendChild(md_organisation_data)
metadata.appendChild(md_organisation)
md_quote = self.dom.createElement('ivamd:quote')
md_quote_data = self.dom.createTextNode(self.kursus.getQuote())
md_quote.appendChild(md_quote_data)
metadata.appendChild(md_quote)
#XXX this needs to be corrected. get
if self.kursus.hasLogo():
md_picture = self.dom.createElement('ivamd:picture')
name = self.binarydata.storeData(self.kursus.getLogoTag().data)
md_picture.setAttribute('href',name)
metadata.appendChild(md_picture)
md_status = self.dom.createElement('ivamd:status')
try:
md_status_data = self.dom.createTextNode(str(self.kursus.staatus))
except:
md_status_data = self.dom.createTextNode(str(0))
md_status.appendChild(md_status_data)
metadata.appendChild(md_status)
record = self.dom.createElement('imsmd:record')
general = self.dom.createElement('imsmd:general')
record.appendChild(general)
title = self.dom.createElement('imsmd:title')
general.appendChild(title)
lang = self.dom.createElement('imsmd:langstring')
lang.setAttribute('xml:lang','en-US')
lang_data = self.dom.createTextNode(self.kursus.get_name())
lang.appendChild(lang_data)
title.appendChild(lang)
descr = self.dom.createElement('imsmd:description')
descrlang = self.dom.createElement('imsmd:langstring')
descrlang.setAttribute('xml:lang','en-US')
descrlang_data = self.dom.createTextNode(self.kursus.get_description())
descrlang.appendChild(descrlang_data)
descr.appendChild(descrlang)
general.appendChild(descr)
metadata.appendChild(record)
org = self.dom.createElement('organization_sec')
org_data = self.dom.createTextNode(str(self.kursus.getCourseCategory()))
org.appendChild(org_data)
metadata.appendChild(org)
score = self.dom.createElement('score')
score_data = self.dom.createTextNode(self.kursus.get_credits())
score.appendChild(score_data)
metadata.appendChild(score)
code = self.dom.createElement('code')
code_data = self.dom.createTextNode(self.kursus.get_courseID())
code.appendChild(code_data)
metadata.appendChild(code)
start = self.dom.createElement('start_time')
start_data = self.dom.createTextNode(str(self.kursus.get_start_date()))
start.appendChild(start_data)
metadata.appendChild(start)
end = self.dom.createElement('end_time')
end_data = self.dom.createTextNode(str(self.kursus.get_end_date()))
end.appendChild(end_data)
metadata.appendChild(end)
uniq_id = self.dom.createElement('uniqID')
uniq_id_data = self.dom.createTextNode(str(self.kursus.getUniqId()))
uniq_id.appendChild(uniq_id_data)
metadata.appendChild(uniq_id)
self.root.appendChild(metadata)
self.organizations = self.dom.createElement('organizations')
self.organization = self.dom.createElement('organization')
self.organization.setAttribute('identifier','IVA_CONTENT'+str(self.idnumber))
self.organizations.appendChild(self.organization)
self.resources = self.dom.createElement('resources')
self.root.appendChild(self.organizations)
self.root.appendChild(self.resources)
def generateID(self):
# generates idnumber. used as identifer and identifierref
# used as 'ITEM'+str(self.idnumber) and 'TARGET'+str(self.idnumber)
import random
self.idnumber = str(random.randint(1,9999))+"_"+str(random.randint(1,9999))
return self.idnumber
def lisaMetadata(self,vanem,objekt,technical='',annotations=''):
metadata = self.dom.createElement('metadata')
try:
metadata.setAttribute('creationtime',str(objekt.get_timestamp()))
except AttributeError:
pass
if technical:
technical = self.dom.createElement('imsmd:technical')
format = self.dom.createElement('imsmd:format')
try:
format_data = self.dom.createTextNode(str(objekt.content_type))
except:
format_data = self.dom.createTextNode('text/plain')
format.appendChild(format_data)
technical.appendChild(format)
perm = self.dom.createElement('permission')
technical.appendChild(perm)
status = self.dom.createElement('status')
status.appendChild(self.dom.createTextNode(str(objekt.getObjPermission())))
perm.appendChild(status)
order = self.dom.createElement('position')
order.appendChild(self.dom.createTextNode(str(objekt.weight)))
perm.appendChild(order)
docStatus = self.dom.createElement('docstatus')
docStatus.appendChild(self.dom.createTextNode(str(objekt.getDocStatus())))
perm.appendChild(docStatus)
#userRating!?
uca = self.dom.createElement('commentable')
uca.setAttribute('view',str(objekt.isCommentsVisible()))
uca.appendChild(self.dom.createTextNode(str(objekt.isCommentable())))
perm.appendChild(uca)
ura = self.dom.createElement('rateable')
ura.setAttribute('view',str(objekt.isRatingVisible()))
ura.appendChild(self.dom.createTextNode(str(objekt.isRateable())))
perm.appendChild(ura)
time = self.dom.createElement('timelimits')
time.setAttribute('start',str(objekt.getStartTime()))
time.setAttribute('end',str(objekt.getEndTime()))
time.appendChild(self.dom.createTextNode(str(objekt.getTimeFunc())))
perm.appendChild(time)
for up in objekt.listLocalUserRoles('Items'):
granted = self.dom.createElement('granted')
granted.appendChild(self.dom.createTextNode(str(up)))
perm.appendChild(granted)
metadata.appendChild(technical)
if annotations:
for x in objekt.getComments():
an = self.dom.createElement('annotation')
an.setAttribute('parameters','comment')
metadata.appendChild(an)
person = self.dom.createElement('person')
person.appendChild(self.dom.createTextNode(str(x[0])))
an.appendChild(person)
date = self.dom.createElement('date')
date.appendChild(self.dom.createTextNode(str(x[2])))
an.appendChild(date)
desc = self.dom.createElement('description')
desc.appendChild(self.dom.createTextNode(str(x[4])))
an.appendChild(desc)
#XXX:not compilant
stat = self.dom.createElement('status')
stat.appendChild(self.dom.createTextNode(str(x[1])))
an.appendChild(stat)
value = self.dom.createElement('value')
value.appendChild(self.dom.createTextNode(str(x[3])))
an.appendChild(value)
vanem.appendChild(metadata)
return metadata
def kirjutaItem(self,vanem,isvisible='',parameters='',tiitel='',no_ref=0,originalID='',originalOwner='',realObject=None, realname=''):
# writes an item tag and appends to vanem
item = self.dom.createElement('item')
item.setAttribute('identifier','ITEM'+str(self.idnumber))
#if realObject is not None and realObject.kasEsitluskaust():
# item.setAttribute('presentation',str(realObject.kasEsitluskaust()))
if not no_ref:
item.setAttribute('identifierref','TARGET'+str(self.idnumber))
if realObject:
md = self.dom.createElement('metadata')
try:
md.setAttribute('creationtime',str(realObject.get_timestamp()))
except AttributeError:
pass
item.appendChild(md)
if hasattr(realObject.aq_self, 'kylastused'):
for x in realObject.aq_self.kylastused.keys():
an = self.dom.createElement('annotation')
an.setAttribute('parameters','visit')
md.appendChild(an)
ps = self.dom.createElement('person')
ps.appendChild(self.dom.createTextNode(str(x)))
an.appendChild(ps)
dt = self.dom.createElement('date')
dt.appendChild(self.dom.createTextNode(str(realObject.aq_self.kylastused[x])))
an.appendChild(dt)
perm = self.dom.createElement('permission')
md.appendChild(perm)
status = self.dom.createElement('status')
status.appendChild(self.dom.createTextNode(str(realObject.getObjPermission())))
perm.appendChild(status)
order = self.dom.createElement('position')
order.appendChild(self.dom.createTextNode(str(realObject.weight)))
perm.appendChild(order)
time = self.dom.createElement('timelimits')
time.setAttribute('start',str(realObject.getStartTime()))
time.setAttribute('end',str(realObject.getEndTime()))
time.appendChild(self.dom.createTextNode(str(realObject.getTimeFunc())))
perm.appendChild(time)
for up in realObject.listLocalUserRoles('Items'):
granted = self.dom.createElement('granted')
granted.appendChild(self.dom.createTextNode(str(up)))
perm.appendChild(granted)
if isvisible != '':
item.setAttribute('isvisible',isvisible)
if parameters != '':
item.setAttribute('parameters',parameters)
if tiitel != '':
self.kirjutaTitle(item,tiitel,originalID=originalID,originalOwner=originalOwner, realname=realname)
vanem.appendChild(item)
return item
def kirjutaResource(self,vanem,tyyp='webcontent',fail='', href='',base=''):
# writes resource tag and appends to vanem
resource = self.dom.createElement('resource')
resource.setAttribute('identifier','TARGET'+str(self.idnumber))
resource.setAttribute('type',tyyp)
if base != '':
resource.setAttribute('xml:base',base)
if href != '':
resource.setAttribute('href',str(href))
if fail != '':
self.kirjutaFile(resource,fail)
vanem.appendChild(resource)
return resource
def kirjutaTitle(self,vanem,tiitel,namespace='',originalID='',originalOwner='', realname=''):
title = self.dom.createElement(namespace+'title')
if originalID:
#XXX: THIS IS NOT IMS VALID!
title.setAttribute('originalID',originalID)
if originalOwner:
#XXX: THIS IS NOT IMS VALID!
title.setAttribute('originalOwner',originalOwner)
if realname:
title.setAttribute('realname', realname)
title_data = self.dom.createTextNode(tiitel)
title.appendChild(title_data)
vanem.appendChild(title)
return title
def kirjutaFile(self,vanem,fail):
fail_elem = self.dom.createElement('file')
fail_elem.setAttribute('href',fail)
vanem.appendChild(fail_elem)
return fail_elem
def kirjutaDependency(self,vanem,targetid):
dep = self.dom.createElement('dependency')
dep.setAttribute('identifierref','TARGET'+str(targetid))
vanem.appendChild(dep)
return dep
def kirjutaManifest(self,base=''):
# creates sub-manifest, returns 3 elements: metadata, organizations and resources
manifest = self.dom.createElement('manifest')
manifest.setAttribute('identifier','TARGET'+str(self.idnumber))
if base != '':
manifest.setAttribute('xml:base',base)
metadata = self.dom.createElement('metadata')
manifest.appendChild(metadata)
organizations = self.dom.createElement('organizations')
manifest.appendChild(organizations)
resources = self.dom.createElement('resources')
manifest.appendChild(resources)
self.root.appendChild(manifest)
return metadata,organizations,resources
def otsiWebtopItemid(self,folder,itemid,resource,start=0):
targetid = self.generateID()
prms = ''
if folder.kasWikiKaust():
prms = 'wikifolder'
if not start:
item = self.kirjutaItem(itemid,parameters=prms,no_ref=1,realObject=folder)
self.kirjutaTitle(item,folder.get_name(),originalID=folder.getId(),originalOwner=folder.getOwnerTuple()[1])
else:
item = itemid
for obj in folder.list_contents(criteria='weight'):
print obj.absolute_url()
targetid = self.generateID()
if obj.meta_type != 'WebtopFolder':
ii = self.kirjutaItem(item)
self.kirjutaTitle(ii, obj.get_name(),originalID=obj.getId(),originalOwner=obj.getOwnerTuple()[1])
if obj.meta_type == 'WebtopFile':
res = self.kirjutaResource(resource,tyyp='file')
fnimi = self.binarydata.storeData(obj.data,'file')
fail = self.kirjutaFile(res,fnimi)
metadata = self.lisaMetadata(fail,obj, technical=1,annotations=1)
self.kirjutaTitle(metadata,obj.get_name(),'imsmd:',originalID=obj.getId(),originalOwner=obj.getOwnerTuple()[1], realname=obj.get_realname())
if obj.meta_type == 'WebtopLink':
res = self.kirjutaResource(resource,tyyp='URL')
fail = self.kirjutaFile(res,obj.get_url())
metadata = self.lisaMetadata(fail,obj,technical=1,annotations=1)
self.kirjutaTitle(fail,obj.get_name(),'imsmd:',originalID=obj.getId(),originalOwner=obj.getOwnerTuple()[1])
if obj.meta_type == 'WebtopMemo':
res = self.kirjutaResource(resource,tyyp='memo')
mnimi = self.binarydata.storeData(obj.get_body(),'memo')
file = self.kirjutaFile(res,mnimi)
metadata = self.lisaMetadata(file,obj,technical=1,annotations=1)
self.kirjutaTitle(file,obj.get_name(),'imsmd:',originalID=obj.getId(),originalOwner=obj.getOwnerTuple()[1])
if obj.meta_type == 'WebtopFolder':
targetid = self.generateID()
if obj.kasWikiKaust():
self.kirjutaWiki(obj, 'ident',obj.aq_inner.get_name(),obj.wikiKaustEsimeneLeht(),item)
else:
self.otsiWebtopItemid(obj,item,resource)
# for fol in folder.objectValues('WebtopFolder'):
#if fol.kasWikiKaust():
# XXX wiki kirjutamine!?
# self.kirjutaWiki(fol, 'ident', fol.get_name(),fol.wikiKaustEsimeneLeht(),item)
#else:
# self.otsiWebtopItemid(fol,item,resource)
return
def kirjutaWebtop(self,point,misc='ident',tiitel='SISEGRUPP'):
# exports webtop style components
self.generateID()
self.kirjutaItem(self.organization,tiitel=tiitel, parameters=tiitel)
e_metadata,e_organizations,e_resources = self.kirjutaManifest()
organization = self.dom.createElement('organization')
# organization.setAttribute('identifier',misc+str(self.idnumber))
organization.setAttribute('identifier',misc)
e_organizations.appendChild(organization)
self.otsiWebtopItemid(point,organization,e_resources,start=1)
return
def kirjutaKasutajaWebtop(self,kasutajad):
self.generateID()
self.kirjutaItem(self.organization,tiitel='KASUTAJATE WEBTOPID',parameters='KASUTAJATE WEBTOPID')
w_metadata,w_organizations,w_resources = self.kirjutaManifest()
# self.generateID()
# self.kirjutaItem(self.organization,tiitel='KASUTAJATE SAHTLID',parameters='KASUTAJATE SAHTLID')
# s_metadata,s_organizations,s_resources = self.kirjutaManifest()
for user in kasutajad:
uname = user.get_uname()
try:
pp = getattr(self.iva.fle_users, uname)
point = getattr(pp.webtop, 'c'+self.kursusenr)
webtop_ation = self.dom.createElement('organization')
webtop_ation.setAttribute('identifier','user_'+str(uname)+'_webtop')
w_organizations.appendChild(webtop_ation)
self.otsiWebtopItemid(point,webtop_ation,w_resources,start=1)
except:
pass
# try:
# point = getattr(pp.sahtel, 'c'+self.kursusenr)
# sahtel_ation = self.dom.createElement('organization')
# sahtel_ation.setAttribute('identifier','user_'+str(uname)+'_sahtel')
# s_organizations.appendChild(sahtel_ation)
# self.otsiWebtopItemid(point,sahtel_ation,s_resources,start=1)
# except:
# pass
return
def pakiKursusFaili(self,failinimi,path='ABCDE'):
import string
if path == 'ABCDE':
path = str(self.kursusenr)
if path != '':
path += '/'
if zipfile.is_zipfile(failinimi):
zip = zipfile.ZipFile(failinimi,"a",zipfile.ZIP_DEFLATED)
else:
zip = zipfile.ZipFile(failinimi,"w",zipfile.ZIP_DEFLATED)
dump = Dump()
self.dom.writexml(dump)
zip.writestr(zipfile.ZipInfo(path+"imsmanifest.xml"),dump.getdata())
for name in self.binarydata.names:
zip.writestr(
zipfile.ZipInfo(path+name),
str(self.binarydata.getData(name)))
zip.close()
def otsiWikiLapsed(self,point,resources,organization,start='WikiStart',sygavus=99999):
#puudub koht muutjate jaoks
for wiki in self.wikid:
wiki_vanemad = wiki[1]
if start in wiki_vanemad:
self.generateID()
wikileht = getattr(point, wiki[0])
item = self.kirjutaItem(organization,parameters='ZWiki',tiitel=wikileht.name())
wname = self.binarydata.storeData(wikileht,'wiki')
self.kirjutaResource(resources,'wikipage',wname)
if not self.wikilevel == sygavus:
self.wikilevel = self.wikilevel+1
self.otsiWikiLapsed(point, resources, item, wikileht.name(),sygavus)
self.wikilevel = self.wikilevel-1
for wiki in self.wiki_pildid:
self.generateID()
wiki_pilt = getattr(point, wiki)
if wiki_pilt.meta_type == 'Image':
tyyp = 'wikiimage'
if wiki_pilt.meta_type == 'File':
tyyp = 'wikifile'
item = self.kirjutaItem(organization, parameters='ZWiki',tiitel=wiki_pilt.id())
wname = self.binarydata.storeData(wiki_pilt.data,tyyp)
res = self.kirjutaResource(resources,tyyp=tyyp)
fail = self.kirjutaFile(res,wname)
metadata = self.lisaMetadata(fail,wiki_pilt, technical=1)
#print wiki_pilt.getContentType()
self.wiki_pildid = []
return
def indekseeriWikid(self,point):
self.wikid = []
self.wiki_pildid = []
temp = []
#for wiki in point.objectValues('ZWiki Page'):
for wiki in point.objectValues():
if wiki.meta_type == 'ZWiki Page':
try:
temp.append(wiki.name())
temp.append(wiki.parents)
self.wikid.append(temp)
temp = []
except:
pass
if wiki.meta_type == 'Image' or wiki.meta_type == 'File':
self.wiki_pildid.append(wiki.id())
#print wiki.__name__+" "+wiki.meta_type
return
def kirjutaWiki(self,point,misc='ident',tiitel='ZWIKI',start='WikiStart',toc='',palju=''):
self.generateID()
if toc:
self.kirjutaItem(toc,parameters='wikifolder',tiitel=tiitel,originalID=point.getId(),originalOwner=point.getOwnerTuple()[1],realObject=point)
else:
self.kirjutaItem(self.organization,tiitel=tiitel,parameters='wikifolder')
w_metadata,w_organizations,w_resources = self.kirjutaManifest()
organization = self.dom.createElement('organization')
organization.setAttribute('identifier',misc+str(self.idnumber))
w_organizations.appendChild(organization)
#kirjutame esieme wiki-lehe
self.generateID()
try:
item = self.kirjutaItem(organization,parameters='ZWiki',tiitel=getattr(point,start).name())
except:
start = 'WikiAvaLeht'
item = self.kirjutaItem(organization,parameters='ZWiki',tiitel=getattr(point,'WikiAvaLeht').name())
wnimi = self.binarydata.storeData(getattr(point, start),'wiki')
self.kirjutaResource(w_resources,'wikipage', wnimi)
self.indekseeriWikid(point)
self.wikilevel = 1
if palju:
self.otsiWikiLapsed(point,w_resources,item,start,palju)
else:
self.otsiWikiLapsed(point,w_resources,item,start)
return
def kirjutaKasutajaWiki(self,kasutajad,start='WikiStart'):
self.generateID()
self.kirjutaItem(self.organization,tiitel='KASUTAJA WIKI')
w_metadata,w_organizations,w_resources = self.kirjutaManifest()
self.generateID()
for kasutaja in kasutajad:
uname = kasutaja.get_uname()
try:
pp = getattr(self.iva.fle_users, uname)
point = getattr(pp.webtop, 'c'+self.kursusenr)
wiki_organization = self.dom.createElement('organization')
wiki_organization.setAttribute('identifier','user_'+str(uname)+'_wiki')
self.generateID()
try:
item = self.kirjutaItem(wiki_organization,tiitel=getattr(point,start).name())
except:
start = 'WikiAvaLeht'
try:
item = self.kirjutaItem(wiki_organization,tiitel=getattr(point,start).name())
except:
continue
w_organizations.appendChild(wiki_organization)
wnimi = self.binarydata.storeData(getattr(point, start),'wiki')
self.kirjutaResource(w_resources,'wikipage', wnimi)
self.indekseeriWikid(point)
self.otsiWikiLapsed(point,w_resources,item,start)
except:
pass
return
def vCalTime(self, aeg):
import time
vaeg = time.localtime(aeg)
v_aeg = ""
v_aeg += str(vaeg[0])
if len(str(vaeg[1])) == 1:
v_aeg += "0" +str(vaeg[1])
else:
v_aeg += str(vaeg[1])
if len(str(vaeg[2])) == 1:
v_aeg += "0" +str(vaeg[2])
else:
v_aeg += str(vaeg[2])
v_aeg += "T"
if len(str(vaeg[3])) == 1:
v_aeg += "0"+str(vaeg[3])
else:
v_aeg += str(vaeg[3])
if len(str(vaeg[4])) == 1:
v_aeg += "0"+str(vaeg[4])
else:
v_aeg += str(vaeg[4])
if len(str(vaeg[5])) == 1:
v_aeg += "0"+str(vaeg[5])
else:
v_aeg += str(vaeg[5])
return v_aeg
def format(self,sisend):
temp = re.sub('\r\n',' ',sisend)
pikkus = len(temp)
tulem = ""
if pikkus>60:
abc = ""
for taht in temp:
abc += taht
if len(abc)>59:
tulem += abc
tulem += "\r\n"
tulem += " "
abc = ""
tulem += abc
#tulem += "\r\n"
else:
tulem = temp
return tulem
def kirjutaEvent(self,point,omanik='mina',kat='kursus'):
tulem = ""
for syndmus in point.objectValues():
tulem += "BEGIN:VEVENT\r\n"
tulem += "DTSTART:"+self.vCalTime(syndmus.algus)+"\r\n"
tulem += "DTEND:"+self.vCalTime(syndmus.lopp)+"\r\n"
tulem += "N:"+omanik+"\r\n"
tulem += "DESCRIPTION:"+self.format(syndmus.getContent())+"\r\n"
#tulem += "SUMMARY:"+self.format(syndmus.lyhi)+"\r\n"
tulem += "STATUS:"+str(syndmus.olek)+"\r\n"
tulem += "CUTYPE:"+kat+"\r\n"
tulem += "URL:"+syndmus.viide+"\r\n"
tulem += "X-PROPERTY;VALUE=NAME:"+self.format(syndmus.nimi)+"\r\n"
# tulem += "X-COMPONENT;VALUE=NAME:"+self.format(oma)+"\r\n"
tulem += "RESOURCES:"+self.format(syndmus.siseviide)+"\r\n"
tulem += "END:VEVENT\r\n"
return tulem
def has_events(self,point):
for syndmus in point.objectValues():
return 1
return 0
def kirjutavCal(self,point,omanik,kat,organiz='', resour=''):
if organiz == '':
organiz = self.organization
if resour == '':
resour = self.resources
if self.has_events(point):
vCal = "BEGIN:VCALENDAR\r\n"
vCal += "METHOD:PUBLISH\r\n"
vCal += "VERSION:2.0\r\n"
vCal += "PRODID:IVA\r\n"
vCal += self.kirjutaEvent(point,omanik,kat)
vCal += "END:VCALENDAR\r\n"
nimi = self.binarydata.storeData(vCal,'vcal','.ics')
self.generateID()
self.kirjutaItem(organiz,tiitel='iCalendar - '+omanik+' - syndmused',parameters='iCalendar - '+omanik+' - syndmused')
# self.kirjutaItem(self.organization,tiitel='iCalendar - '+omanik+' syndmused')
self.kirjutaResource(resour,'iCalendar',nimi)
# self.kirjutaResource(self.resources,'iCalendar',nimi)
return
def kirjutaKasutajaSyndmus(self,kasutajad):
self.generateID()
self.kirjutaItem(self.organization, tiitel="KASUTAJATE SYNDMUSED",parameters="KASUTAJATE SYNDMUSED")
s_metadata,s_organizations,s_resources = self.kirjutaManifest()
for user in kasutajad:
try:
uname = user.get_uname()
point = getattr(self.iva.fle_users, uname)
if self.has_events(point.syndmused):
syndmus_organization = self.dom.createElement('organization')
syndmus_organization.setAttribute('identifier','user_'+str(uname)+'_events')
s_organizations.appendChild(syndmus_organization)
self.kirjutavCal(point.syndmused, uname, 'INDIVIDUAL',syndmus_organization,s_resources)
except:
pass
return
def exportMail(self,failinimi,palju=''):
mmdoc = Document()
mm = mmdoc.createElement('MailMessages')
mmdoc.appendChild(mm)
users = []
if not palju:
users = self.iva.fle_users.get_users()
else:
users = eval(palju)
for x in users:
if not hasattr(x, 'kirjad'):
continue
point = getattr(x, 'kirjad')
cat = mmdoc.createElement('catalog')
cat.setAttribute('owner', x.get_uname())
mm.appendChild(cat)
for kiri in point.objectValues():
mess = mmdoc.createElement('message')
mess.setAttribute('read',str(kiri.kasLoetud()))
if kiri.kasOmaKoopia():
mess.setAttribute('owncopy','1')
cat.appendChild(mess)
title = mmdoc.createElement('title')
tekst = kiri.kysiPealkiri()
tekst = re.sub(']]>',']] >',tekst)
# decode and then encode
try:
tekst = tekst.decode('utf-8')
except UnicodeDecodeError:
tekst = tekst.decode('iso-8859-15')
tekst = tekst.encode('utf-8')
title.appendChild(mmdoc.createCDATASection(strip_non_xml(tekst)))
mess.appendChild(title)
body = mmdoc.createElement('body')
tekst = kiri.kysiSisu()
tekst = re.sub(']]>',']] >',tekst)
try:
tekst = tekst.decode('utf-8')
except UnicodeDecodeError:
tekst = tekst.decode('iso-8859-13')
tekst = tekst.encode('utf-8')
body.appendChild(mmdoc.createCDATASection(strip_non_xml(tekst)))
mess.appendChild(body)
sender = mmdoc.createElement('sender')
sender.appendChild(mmdoc.createTextNode(str(kiri.kysiSaatja())))
mess.appendChild(sender)
receiver = mmdoc.createElement('receiver')
receiver.appendChild(mmdoc.createTextNode(str(kiri.saaja)))
mess.appendChild(receiver)
date = mmdoc.createElement('date')
date.appendChild(mmdoc.createTextNode(str(kiri.kysiAeg())))
mess.appendChild(date)
if zipfile.is_zipfile(failinimi):
zip = zipfile.ZipFile(failinimi,"a",zipfile.ZIP_DEFLATED)
else:
zip = zipfile.ZipFile(failinimi,"w",zipfile.ZIP_DEFLATED)
# mmdoc.dump = Dump()
# mmdoc.writexml(mmdoc.dump)
# zip.writestr(zipfile.ZipInfo("messages.xml"),mmdoc.dump.getdata())
zip.writestr(zipfile.ZipInfo("messages.xml"),mmdoc.toprettyxml())
zip.close()
return
def exportCourseCategories(self, failinimi):
""" export course categories """
cm = self.iva.courses
mmdoc = Document()
mm = mmdoc.createElement('CourseCats')
mmdoc.appendChild(mm)
course_cat = cm.cCategories
c = mmdoc.createElement('categories')
c_data = mmdoc.createTextNode(str(course_cat))
c.appendChild(c_data)
mm.appendChild(c)
if zipfile.is_zipfile(failinimi):
zip = zipfile.ZipFile(failinimi,"a",zipfile.ZIP_DEFLATED)
else:
zip = zipfile.ZipFile(failinimi,"w",zipfile.ZIP_DEFLATED)
zip.writestr(zipfile.ZipInfo("course_cat.xml"),mmdoc.toprettyxml())
zip.close()
return
def exportAffiliations(self, failinimi):
""" export affiliation codes """
mmdoc = Document()
mm = mmdoc.createElement('Affiliations')
mmdoc.appendChild(mm)
e = self.iva.fle_users.getAffiliations()
for x in e:
aff = mmdoc.createElement('affiliation')
aff_data = mmdoc.createTextNode(x)
aff.appendChild(aff_data)
mm.appendChild(aff)
if zipfile.is_zipfile(failinimi):
zip = zipfile.ZipFile(failinimi,"a",zipfile.ZIP_DEFLATED)
else:
zip = zipfile.ZipFile(failinimi,"w",zipfile.ZIP_DEFLATED)
zip.writestr(zipfile.ZipInfo("affiliations.xml"),mmdoc.toprettyxml())
zip.close()
return
def exportServerSettings(self, failinimi):
""" export iva settings """
mmdoc = Document()
mm = mmdoc.createElement('Settings')
mmdoc.appendChild(mm)
# allow user registration
auto = mmdoc.createElement('auto_register')
auto_data = mmdoc.createTextNode(str(self.iva.get_allow_autoregister()))
auto.appendChild(auto_data)
mm.appendChild(auto)
# quota
quota = mmdoc.createElement('quota')
quota_data = mmdoc.createTextNode(str(self.iva.webtop_quota))
quota.appendChild(quota_data)
mm.appendChild(quota)
# quota amount
quota_amount = mmdoc.createElement('quota_amount')
quota_amount_data = mmdoc.createTextNode(str(self.iva.webtop_quota_amount))
quota_amount.appendChild(quota_amount_data)
mm.appendChild(quota_amount)
# mailhost & port
mail_host = mmdoc.createElement('mail_host')
mail_host.setAttribute('port', str(self.iva.MailHost.smtp_port))
mail_host_data = mmdoc.createTextNode(str(self.iva.MailHost.smtp_host))
mail_host.appendChild(mail_host_data)
mm.appendChild(mail_host)
# mail from
mail_from = mmdoc.createElement('mail_from')
mail_from_data = mmdoc.createTextNode(str(self.iva.MFROM))
mail_from.appendChild(mail_from_data)
mm.appendChild(mail_from)
# default language
def_lang = mmdoc.createElement('default_language')
def_lang_data = mmdoc.createTextNode(str(self.iva.get_default_language()))
def_lang.appendChild(def_lang_data)
mm.appendChild(def_lang)
# must change password
def_change = mmdoc.createElement('force_change')
def_change_data = mmdoc.createTextNode(str(self.iva.def_passwd))
def_change.appendChild(def_change_data)
mm.appendChild(def_change)
# cannot change affiliation
def_aff = mmdoc.createElement('deny_affiliation_change')
def_aff_data = mmdoc.createTextNode(str(self.iva.def_not_aff))
def_aff.appendChild(def_aff_data)
mm.appendChild(def_aff)
# cannot change password
def_password = mmdoc.createElement('deny_password_change')
def_password_data = mmdoc.createTextNode(str(self.iva.def_not_change))
def_password.appendChild(def_password_data)
mm.appendChild(def_password)
if zipfile.is_zipfile(failinimi):
zip = zipfile.ZipFile(failinimi,"a",zipfile.ZIP_DEFLATED)
else:
zip = zipfile.ZipFile(failinimi,"w",zipfile.ZIP_DEFLATED)
zip.writestr(zipfile.ZipInfo("settings.xml"),mmdoc.toprettyxml())
zip.close()
return
def exportKodutood(self, point,failinimi,path):
# expordime kodutööd
kt_doc = Document()
kt = kt_doc.createElement('Assignments')
kt_doc.appendChild(kt)
kt.setAttribute('identifier','IVA')
kt.setAttribute('version','1')
for kodu in point.listAssignments():
too = kt_doc.createElement('Assignment')
too.setAttribute('originalID',kodu.get_id())
kt.appendChild(too)
tyyp = kt_doc.createElement('type')
tyyp_data = kt_doc.createTextNode(str(kodu.tyyp))
tyyp.appendChild(tyyp_data)
too.appendChild(tyyp)
pkiri = kt_doc.createElement('title')
pkiri_data = kt_doc.createTextNode(str(kodu.getTitle()))
pkiri.appendChild(pkiri_data)
too.appendChild(pkiri)
kirjeldus = kt_doc.createElement('description')
kirjeldus_data = kt_doc.createTextNode(str(kodu.kirjeldus))
kirjeldus.appendChild(kirjeldus_data)
too.appendChild(kirjeldus)
punkt = kt_doc.createElement('points')
punkt_data = kt_doc.createTextNode(str(kodu.getPoints()))
punkt.appendChild(punkt_data)
too.appendChild(punkt)
try:
resour = kt_doc.createElement('resource')
resour_data = kt_doc.createTextNode(str(kodu.juhend))
resour.appendChild(resour_data)
too.appendChild(resour)
except:
pass
try:
aeg = kt_doc.createElement('end')
aeg_data = kt_doc.createTextNode(str(kodu.loppaeg))
aeg.appendChild(aeg_data)
too.appendChild(aeg)
except:
pass
try:
grupp = kt_doc.createElement('groups')
for abc in kodu.getGroups():
gr = kt_doc.createElement('group')
grupp_data = kt_doc.createTextNode(str(abc))
gr.appendChild(grupp_data)
grupp.appendChild(gr)
too.appendChild(grupp)
except:
pass
try:
test = kt_doc.createElement('test')
test_data = kt_doc.createTextNode(str(kodu.testiID))
test.appendChild(test_data)
too.appendChild(test)
except:
pass
self.generateID()
self.kirjutaItem(self.organization,tiitel='Assignments',parameters='Assignments')
self.kirjutaResource(self.resources,'assignments','assignments.xml','assignments.xml')
if zipfile.is_zipfile(failinimi):
zip = zipfile.ZipFile(failinimi,"a",zipfile.ZIP_DEFLATED)
else:
zip = zipfile.ZipFile(failinimi,"w",zipfile.ZIP_DEFLATED)
kt_doc.dump = Dump()
kt_doc.writexml(kt_doc.dump)
zip.writestr(zipfile.ZipInfo(path+"assignments.xml"),kt_doc.dump.getdata())
zip.close()
return
def exportPajad(self,failinimi,path,startonly=0):
self.generateID()
TP = Document()
MP = Document()
kala = Exporter(self.iva)
tp_elem = TP.createElement('KnowledgeBuilding')
for ctx in self.kursus.get_children("CourseContext"):
tp_elem.appendChild(kala.exportContext(ctx,startonly))
TP.appendChild(tp_elem)
mp_elem = MP.createElement('Jamming')
try:
#for c in courses.get_children('Course'):
for js in self.kursus.get_child('jamming').get_children('JamSession'):
mp_elem.appendChild(kala.exportJamSession(self.kursus, js,startonly))
except:
pass
MP.appendChild(mp_elem)
self.kirjutaItem(self.organization,tiitel='TEADMUSPAJA',parameters='TEADMUSPAJA')
self.kirjutaResource(self.resources,'teadmuspaja','teadmuspaja.xml','teadmuspaja.xml')
self.generateID()
self.kirjutaItem(self.organization,tiitel='MEEDIAPAJA',parameters='MEEDIAPAJA')
self.kirjutaResource(self.resources,'meediapaja','meediapaja.xml','meediapaja.xml')
if zipfile.is_zipfile(failinimi):
zip = zipfile.ZipFile(failinimi,"a",zipfile.ZIP_DEFLATED)
else:
zip = zipfile.ZipFile(failinimi,"w",zipfile.ZIP_DEFLATED)
TP.dump = Dump()
MP.dump = Dump()
TP.writexml(TP.dump)
MP.writexml(MP.dump)
zip.writestr(zipfile.ZipInfo(path+"teadmuspaja.xml"),TP.dump.getdata())
zip.writestr(zipfile.ZipInfo(path+"meediapaja.xml"),MP.dump.getdata())
for name in kala.binarydata.names:
zip.writestr(
zipfile.ZipInfo(path+name),
str(kala.binarydata.getData(name)))
zip.close()
return
def exportQTI(self,failinimi,path,teacherExporting=0):
# function for going all necessary to export tests
self.generateID()
self.kirjutaItem(self.organization,tiitel='QTI',parameters='QTI')
self.kirjutaResource(self.resources,'imsqti_xmlv1p1','qti.xml','qti.xml')
element = self.looTestiFail()
self.kirjutaTestid(element,teacherExporting=teacherExporting)
self.kirjutaTestidZipi(failinimi,path)
def looTestiFail(self):
self.generateID()
self.qti = Document()
self.qtibin = DataTable()
self.qtiroot = self.qti.createElement("questestinterop")
self.qtiroot.setAttribute('xmlns','http://www.imsglobal.org/xsd/ims_qtiasiv1p2')
self.qtiroot.setAttribute('xmlns:xsi','http://www.w3.org/2000/10/XMLSchema-instance')
self.qtiroot.setAttribute('xsi:schemaLocation','http://www.imsglobal.org/xsd/ims_qtiasiv1p2 http://www.imsglobal.org/xsd/ims_qtiasiv1p2.xsd')
self.qti.appendChild(self.qtiroot)
return self.qtiroot
def kirjutaTestidZipi(self,failinimi,path=''):
if zipfile.is_zipfile(failinimi):
zip = zipfile.ZipFile(failinimi,"a",zipfile.ZIP_DEFLATED)
else:
zip = zipfile.ZipFile(failinimi,"w",zipfile.ZIP_DEFLATED)
self.qti.dump = Dump()
self.qti.writexml(self.qti.dump)
zip.writestr(zipfile.ZipInfo(path+"qti.xml"),self.qti.dump.getdata())
for name in self.qtibin.names:
zip.writestr(
zipfile.ZipInfo(path+name),
str(self.qtibin.getData(name)))
zip.close()
return
def testiPilt(self,vanem, varamu):
if varamu.pilt is not None:
mat_pilt = self.qti.createElement('matimage')
name = self.qtibin.storeData(varamu.pilt,'qti')
mat_pilt.setAttribute('uri',name)
vanem.appendChild(mat_pilt)
return vanem
def testiViide(self,vanem, varamu):
if varamu.viiteURL != '':
matem = self.qti.createElement('matemtext')
matem.setAttribute('uri',varamu.viiteURL)
matem.appendChild(self.qti.createTextNode(varamu.viiteTekst))
vanem.appendChild(matem)
return vanem
def testiKirjeldavTekst(self,vanem,varamu):
if varamu.kirjeldavTekst != '':
komm = self.qti.createElement('qticomment')
komm.appendChild(self.qti.createTextNode(varamu.kirjeldavTekst))
vanem.appendChild(komm)
return vanem
def testiItem(self,vanem,varamu):
elem = self.qti.createElement('item')
elem.setAttribute('ident',varamu.get_id())
elem.setAttribute('title',varamu.meta_type)
vanem.appendChild(elem)
return elem
def exportUserResponses(self,vanem,hoidla,users=''):
if not users:
users = self.kursus.get_all_users()
else:
users = eval(users)
for x in users:
try:
tmpx = getattr(self.iva.fle_users, x.get_uname()).webtop
tmpy = getattr(tmpx, 'c'+self.kursus.get_id()).testivastused
z = getattr(tmpy.aq_self, hoidla.get_id())
except AttributeError:
continue
elem = self.qti.createElement('response')
elem.setAttribute('owner',x.get_uname())
for i in z.aq_self.objectValues():
ver = self.qti.createElement('version')
ver.setAttribute('id',str(i.get_id()))
try:
ver.setAttribute('comment',str(i.annaKoguKommentaar()))
except AttributeError:
pass
elem.appendChild(ver)
for j in i.objectValues():
yl = self.qti.createElement('yl')
yl.setAttribute('id',j.get_id())
try:
if j.annaOpetajaPunktid() is not None:
yl.setAttribute('score',str(j.annaOpetajaPunktid()))
except AttributeError:
pass
try:
yl.setAttribute('comment',str(j.annaOpetajaKommentaar()))
except AttributeError:
pass
try:
if type(j.pakutud())==types.ListType:
yl.setAttribute('type','List')
yl.appendChild(self.qti.createTextNode(str(j.pakutud())))
except AttributeError:
pass
ver.appendChild(yl)
vanem.appendChild(elem)
return
def kirjutaTestid(self,vanem,testinimi='',users='',teacherExporting=0):
if testinimi != '':
ainult_yks_test = 1
else:
ainult_yks_test = 0
qticomment = self.qti.createElement("qticomment")
qticomment_data = self.qti.createTextNode('Here is a set of questions and tests from IVA')
qticomment.appendChild(qticomment_data)
vanem.appendChild(qticomment)
# export all tests and questions within course
for hoidla in self.kursus.testid.objectValues():
if hoidla.get_id() == testinimi or not ainult_yks_test:
sektion = self.qti.createElement('section')
sektion.setAttribute('title',str(hoidla.pealkiri))
sektion.setAttribute('ident',str(hoidla.get_id()))
sektion.setAttribute('type',str(hoidla.kysiTyyp()))
sektion.setAttribute('randomize',str(hoidla.kasKysimusteJuhuslikJarjekord()))
sektion.setAttribute('answers',str(hoidla.kysiVastusteNahtavus()))
sektion.setAttribute('open',str(hoidla.avatudTaitmiseks))
md = self.qti.createElement('metadata')
sektion.appendChild(md)
tl = self.qti.createElement('timelimit')
tl.setAttribute('repeat',str(hoidla.koigiLuba.kordadeArv))
tl.setAttribute('start',str(hoidla.koigiLuba.algusAeg))
tl.setAttribute('end',str(hoidla.koigiLuba.loppAeg))
md.appendChild(tl)
grs = self.qti.createElement('groups')
md.appendChild(grs)
for x in hoidla.grupiLoad.objectValues():
gr = self.qti.createElement('group')
gr.setAttribute('repeat',str(x.kordadeArv))
gr.setAttribute('start',str(x.algusAeg))
gr.setAttribute('end',str(x.loppAeg))
gr.setAttribute('name',str(x.id))
grs.appendChild(gr)
prs = self.qti.createElement('persons')
md.appendChild(prs)
for x in hoidla.isikuLoad.objectValues():
pr = self.qti.createElement('person')
pr.setAttribute('repeat',str(x.kordadeArv))
pr.setAttribute('start',str(x.algusAeg))
pr.setAttribute('end',str(x.loppAeg))
pr.setAttribute('name',str(x.id))
prs.appendChild(pr)
desc = self.qti.createElement('description')
desc.appendChild(self.qti.createTextNode(str(hoidla.annaKirjeldus())))
md.appendChild(desc)
uresp = self.qti.createElement('userresponses')
sektion.appendChild(uresp)
if not teacherExporting:
self.exportUserResponses(uresp,hoidla,users)
#print hoidla.get_id()
for yled in hoidla.objectValues():
#print "->>"+yled.get_id()
#print yled.get_id()+" - "+ yled.meta_type
tyyp = yled.meta_type
if tyyp=='ValikYlesanne':
elem = self.testiItem(sektion,yled)
self.testiKirjeldavTekst(elem,yled)
present = self.qti.createElement('presentation')
elem.appendChild(present)
flo = self.qti.createElement('flow')
present.appendChild(flo)
mat = self.qti.createElement('material')
flo.appendChild(mat)
mattext = self.qti.createElement('mattext')
mattext.appendChild(self.qti.createTextNode(yled.kysimus))
mat.appendChild(mattext)
self.testiViide(mat,yled)
self.testiPilt(mat,yled)
resp_lid = self.qti.createElement('response_lid')
resp_lid.setAttribute('ident',yled.get_id())
resp_lid.setAttribute('rcardinality',"Single")
flo.appendChild(resp_lid)
render = self.qti.createElement('render_choice')
resp_lid.appendChild(render)
flow_l = self.qti.createElement('flow_label')
render.appendChild(flow_l)
resp_lab = self.qti.createElement('response_label')
resp_lab.setAttribute('ident','T')
flow_l.appendChild(resp_lab)
mat2 = self.qti.createElement('material')
resp_lab.appendChild(mat2)
mattext2 = self.qti.createElement('mattext')
mattext2.appendChild(self.qti.createTextNode('True'))
mat2.appendChild(mattext2)
resp_lab = self.qti.createElement('response_label')
resp_lab.setAttribute('ident','F')
flow_l.appendChild(resp_lab)
mat2 = self.qti.createElement('material')
resp_lab.appendChild(mat2)
mattext2 = self.qti.createElement('mattext')
mattext2.appendChild(self.qti.createTextNode('False'))
mat2.appendChild(mattext2)
resproc = self.qti.createElement('resprocessing')
elem.appendChild(resproc)
out = self.qti.createElement('outcomes')
resproc.appendChild(out)
muut = self.qti.createElement('decvar')
muut.setAttribute('vartype','Integer')
muut.setAttribute('maxvalue',str(yled.normPunktid))
out.appendChild(muut)
kond = self.qti.createElement('respcondition')
kond.setAttribute('title','Correct')
resproc.appendChild(kond)
kond_var = self.qti.createElement('conditionvar')
kond.appendChild(kond_var)
varequal = self.qti.createElement('varequal')
varequal.setAttribute('respident',yled.get_id())
if yled.vastus:
varequal.appendChild(self.qti.createTextNode('T'))
else:
varequal.appendChild(self.qti.createTextNode('F'))
kond_var.appendChild(varequal)
setvar = self.qti.createElement('setvar')
setvar.setAttribute('action','Add')
setvar.appendChild(self.qti.createTextNode(str(yled.normPunktid)))
kond.appendChild(setvar)
pass
if tyyp=='OigeTekstivastusegaYlesanne':
elem = self.testiItem(sektion,yled)
self.testiKirjeldavTekst(elem,yled)
present = self.qti.createElement('presentation')
elem.appendChild(present)
flo = self.qti.createElement('flow')
present.appendChild(flo)
mat = self.qti.createElement('material')
flo.appendChild(mat)
mattext = self.qti.createElement('mattext')
mattext.appendChild(self.qti.createTextNode(yled.kysimus))
mat.appendChild(mattext)
self.testiViide(mat,yled)
self.testiPilt(mat,yled)
resp_lid = self.qti.createElement('response_str')
resp_lid.setAttribute('ident',yled.get_id())
resp_lid.setAttribute('rcardinality',"Single")
flo.appendChild(resp_lid)
render = self.qti.createElement('render_fib')
render.setAttribute('fibtype','String')
render.setAttribute('encoding','UTF_8')
resp_lid.appendChild(render)
resp_lab = self.qti.createElement('response_label')
resp_lab.setAttribute('ident','A')
render.appendChild(resp_lab)
resproc = self.qti.createElement('resprocessing')
elem.appendChild(resproc)
out = self.qti.createElement('outcomes')
resproc.appendChild(out)
muut = self.qti.createElement('decvar')
muut.setAttribute('vartype','Integer')
muut.setAttribute('maxvalue',str(yled.normPunktid))
out.appendChild(muut)
kond = self.qti.createElement('respcondition')
kond.setAttribute('title','Correct')
resproc.appendChild(kond)
kond_var = self.qti.createElement('conditionvar')
kond.appendChild(kond_var)
for abc in yled.variandid:
varequal = self.qti.createElement('varequal')
varequal.setAttribute('respident',yled.get_id())
varequal.appendChild(self.qti.createTextNode(str(abc)))
kond_var.appendChild(varequal)
setvar = self.qti.createElement('setvar')
setvar.setAttribute('action','Add')
setvar.appendChild(self.qti.createTextNode(str(yled.normPunktid)))
kond.appendChild(setvar)
pass
if tyyp=='YksikvalikYlesanne':
elem = self.testiItem(sektion,yled)
self.testiKirjeldavTekst(elem,yled)
present = self.qti.createElement('presentation')
elem.appendChild(present)
flo = self.qti.createElement('flow')
present.appendChild(flo)
mat = self.qti.createElement('material')
flo.appendChild(mat)
mattext = self.qti.createElement('mattext')
mattext.appendChild(self.qti.createTextNode(yled.kysimus))
mat.appendChild(mattext)
self.testiViide(mat,yled)
self.testiPilt(mat,yled)
resp_lid = self.qti.createElement('response_lid')
resp_lid.setAttribute('ident',yled.get_id())
resp_lid.setAttribute('rcardinality',"Single")
flo.appendChild(resp_lid)
render = self.qti.createElement('render_choice')
render.setAttribute('shuffle','Yes')
resp_lid.appendChild(render)
i=0
for abc in yled.valikud:
resp_lab = self.qti.createElement('response_label')
resp_lab.setAttribute('ident',str(i))
render.appendChild(resp_lab)
flow_mat = self.qti.createElement('flow_mat')
resp_lab.appendChild(flow_mat)
mat2 = self.qti.createElement('material')
flow_mat.appendChild(mat2)
mattext2 = self.qti.createElement('mattext')
mattext2.appendChild(self.qti.createTextNode(abc))
mat2.appendChild(mattext2)
i=i+1
resproc = self.qti.createElement('resprocessing')
elem.appendChild(resproc)
out = self.qti.createElement('outcomes')
resproc.appendChild(out)
muut = self.qti.createElement('decvar')
muut.setAttribute('vartype','Integer')
muut.setAttribute('maxvalue',str(yled.normPunktid))
out.appendChild(muut)
kond = self.qti.createElement('respcondition')
kond.setAttribute('title','Correct')
resproc.appendChild(kond)
kond_var = self.qti.createElement('conditionvar')
kond.appendChild(kond_var)
varequal = self.qti.createElement('varequal')
varequal.setAttribute('respident',yled.get_id())
varequal.appendChild(self.qti.createTextNode(str(yled.oigeValik)))
kond_var.appendChild(varequal)
setvar = self.qti.createElement('setvar')
setvar.setAttribute('action','Add')
setvar.appendChild(self.qti.createTextNode(str(yled.normPunktid)))
kond.appendChild(setvar)
i=0
if not hasattr(yled,'selgitused'):
selgitused = []
for abc in yled.selgitused:
itemfeed = self.qti.createElement('itemfeedback')
itemfeed.setAttribute('ident',str(i))
elem.appendChild(itemfeed)
flow_m = self.qti.createElement('flow_mat')
itemfeed.appendChild(flow_m)
mat = self.qti.createElement('material')
flow_m.appendChild(mat)
mattext = self.qti.createElement('mattext')
mattext.appendChild(self.qti.createTextNode(abc))
mat.appendChild(mattext)
i=i+1
pass
if tyyp=='TekstivastusegaYlesanne':
elem = self.testiItem(sektion,yled)
self.testiKirjeldavTekst(elem,yled)
present = self.qti.createElement('presentation')
elem.appendChild(present)
flo = self.qti.createElement('flow')
present.appendChild(flo)
mat = self.qti.createElement('material')
flo.appendChild(mat)
mattext = self.qti.createElement('mattext')
mattext.appendChild(self.qti.createTextNode(yled.kysimus))
mat.appendChild(mattext)
self.testiViide(mat,yled)
self.testiPilt(mat,yled)
resp_lid = self.qti.createElement('response_str')
resp_lid.setAttribute('ident',yled.get_id())
resp_lid.setAttribute('rcardinality',"Ordered")
flo.appendChild(resp_lid)
render = self.qti.createElement('render_fib')
render.setAttribute('fibtype','String')
render.setAttribute('enconding','UTF_8')
render.setAttribute('prompt','Box')
resp_lid.appendChild(render)
resp_lab = self.qti.createElement('response_label')
resp_lab.setAttribute('ident','A')
render.appendChild(resp_lab)
pass
if tyyp=='MitmikvalikYlesanne':
elem = self.testiItem(sektion,yled)
self.testiKirjeldavTekst(elem,yled)
present = self.qti.createElement('presentation')
elem.appendChild(present)
flo = self.qti.createElement('flow')
present.appendChild(flo)
mat = self.qti.createElement('material')
flo.appendChild(mat)
mattext = self.qti.createElement('mattext')
mattext.appendChild(self.qti.createTextNode(yled.kysimus))
mat.appendChild(mattext)
self.testiViide(mat,yled)
self.testiPilt(mat,yled)
resp_lid = self.qti.createElement('response_lid')
resp_lid.setAttribute('ident',yled.get_id())
resp_lid.setAttribute('rcardinality',"Multiple")
flo.appendChild(resp_lid)
render = self.qti.createElement('render_choice')
render.setAttribute('shuffle','Yes')
resp_lid.appendChild(render)
i=0
for abc in yled.valikud:
resp_lab = self.qti.createElement('response_label')
resp_lab.setAttribute('ident',str(i))
render.appendChild(resp_lab)
flow_mat = self.qti.createElement('flow_mat')
resp_lab.appendChild(flow_mat)
mat2 = self.qti.createElement('material')
flow_mat.appendChild(mat2)
mattext2 = self.qti.createElement('mattext')
mattext2.appendChild(self.qti.createTextNode(abc))
mat2.appendChild(mattext2)
i=i+1
resproc = self.qti.createElement('resprocessing')
elem.appendChild(resproc)
out = self.qti.createElement('outcomes')
resproc.appendChild(out)
muut = self.qti.createElement('decvar')
muut.setAttribute('vartype','Integer')
muut.setAttribute('maxvalue',str(yled.normPunktid))
out.appendChild(muut)
kond = self.qti.createElement('respcondition')
kond.setAttribute('title','Correct')
resproc.appendChild(kond)
kond_var = self.qti.createElement('conditionvar')
kond.appendChild(kond_var)
for abc in yled.oigedValikud:
varequal = self.qti.createElement('varequal')
varequal.setAttribute('respident',yled.get_id())
varequal.appendChild(self.qti.createTextNode(str(abc)))
kond_var.appendChild(varequal)
setvar = self.qti.createElement('setvar')
setvar.setAttribute('action','Add')
setvar.appendChild(self.qti.createTextNode(str(yled.normPunktid)))
kond.appendChild(setvar)
i=0
for abc in yled.selgitused:
itemfeed = self.qti.createElement('itemfeedback')
itemfeed.setAttribute('ident',str(i))
elem.appendChild(itemfeed)
flow_m = self.qti.createElement('flow_mat')
itemfeed.appendChild(flow_m)
mat = self.qti.createElement('material')
flow_m.appendChild(mat)
mattext = self.qti.createElement('mattext')
mattext.appendChild(self.qti.createTextNode(abc))
mat.appendChild(mattext)
i=i+1
pass
if tyyp=='ArvuvahemikuliseVastusegaYlesanne':
elem = self.testiItem(sektion,yled)
self.testiKirjeldavTekst(elem,yled)
present = self.qti.createElement('presentation')
elem.appendChild(present)
flo = self.qti.createElement('flow')
present.appendChild(flo)
mat = self.qti.createElement('material')
flo.appendChild(mat)
mattext = self.qti.createElement('mattext')
mattext.appendChild(self.qti.createTextNode(yled.kysimus))
mat.appendChild(mattext)
self.testiViide(mat,yled)
self.testiPilt(mat,yled)
resp_lid = self.qti.createElement('response_num')
resp_lid.setAttribute('ident',yled.get_id())
resp_lid.setAttribute('rcardinality',"Single")
resp_lid.setAttribute('numtype','Decimal')
flo.appendChild(resp_lid)
render = self.qti.createElement('render_fib')
render.setAttribute('fibtype','Decimal')
render.setAttribute('prompt','Box')
resp_lid.appendChild(render)
resp_lab = self.qti.createElement('response_label')
resp_lab.setAttribute('ident','A')
render.appendChild(resp_lab)
resproc = self.qti.createElement('resprocessing')
elem.appendChild(resproc)
out = self.qti.createElement('outcomes')
resproc.appendChild(out)
komm = self.qti.createElement('qticomment')
komm.appendChild(self.qti.createTextNode(str(yled.arvutusTyyp)))
out.appendChild(komm)
muut = self.qti.createElement('decvar')
muut.setAttribute('vartype','Integer')
muut.setAttribute('maxvalue',str(yled.normPunktid))
out.appendChild(muut)
kond = self.qti.createElement('respcondition')
kond.setAttribute('title','Correct')
resproc.appendChild(kond)
kond_var = self.qti.createElement('conditionvar')
kond.appendChild(kond_var)
varless = self.qti.createElement('vargte')
varless.setAttribute('respident',yled.get_id())
varless.appendChild(self.qti.createTextNode(str(yled.alamPiir)))
kond_var.appendChild(varless)
varequal = self.qti.createElement('varequal')
varequal.setAttribute('respident',yled.get_id())
varequal.appendChild(self.qti.createTextNode(str(yled.oigeVastus)))
kond_var.appendChild(varequal)
varover = self.qti.createElement('varlte')
varover.setAttribute('respident',yled.get_id())
varover.appendChild(self.qti.createTextNode(str(yled.ylemPiir)))
kond_var.appendChild(varover)
setvar = self.qti.createElement('setvar')
setvar.setAttribute('action','Add')
setvar.appendChild(self.qti.createTextNode(str(yled.normPunktid)))
kond.appendChild(setvar)
pass
if tyyp=='ProtsentYlesanne':
elem = self.testiItem(sektion,yled)
self.testiKirjeldavTekst(elem,yled)
present = self.qti.createElement('presentation')
elem.appendChild(present)
flo = self.qti.createElement('flow')
present.appendChild(flo)
mat = self.qti.createElement('material')
flo.appendChild(mat)
mattext = self.qti.createElement('mattext')
mattext.appendChild(self.qti.createTextNode(yled.kysimus))
mat.appendChild(mattext)
self.testiViide(mat,yled)
self.testiPilt(mat,yled)
points = self.qti.createElement('points')
points_data = self.qti.createTextNode(str(yled.normPunktid))
points.appendChild(points_data)
elem.appendChild(points)
searching = self.qti.createElement('searching')
searching.appendChild(self.qti.createTextNode(str(yled.kysitav)))
elem.appendChild(searching)
solvent = self.qti.createElement('solvent') #lahus
min = self.qti.createElement('min')
min.appendChild(self.qti.createTextNode(str(yled.lahustiAlamPiir)))
max = self.qti.createElement('max')
max.appendChild(self.qti.createTextNode(str(yled.lahustiYlemPiir)))
names = self.qti.createElement('names')
names.appendChild(self.qti.createTextNode(str(yled.lahustiTekst)))
stype = self.qti.createElement('type')
stype.appendChild(self.qti.createTextNode(str(yled.lahustiYhik)))
solvent.appendChild(min)
solvent.appendChild(max)
solvent.appendChild(names)
solvent.appendChild(stype)
elem.appendChild(solvent)
soluble = self.qti.createElement('soluble') #aine
min = self.qti.createElement('min')
min.appendChild(self.qti.createTextNode(str(yled.aineAlamPiir)))
max = self.qti.createElement('max')
max.appendChild(self.qti.createTextNode(str(yled.aineYlemPiir)))
names = self.qti.createElement('names')
names.appendChild(self.qti.createTextNode(str(yled.aineTekst)))
stype = self.qti.createElement('type')
stype.appendChild(self.qti.createTextNode(str(yled.aineYhik)))
soluble.appendChild(min)
soluble.appendChild(max)
soluble.appendChild(names)
soluble.appendChild(stype)
elem.appendChild(soluble)
accuracy = self.qti.createElement('accuracy')
accuracy.appendChild(self.qti.createTextNode(str(yled.vastuseTapsusProtsent)))
elem.appendChild(accuracy)
scoring = self.qti.createElement('scoring')
scoring.appendChild(self.qti.createTextNode(str(yled.arvutusTyyp)))
elem.appendChild(scoring)
if tyyp=='VastavusYlesanne':
elem = self.testiItem(sektion,yled)
self.testiKirjeldavTekst(elem,yled)
present = self.qti.createElement('presentation')
elem.appendChild(present)
flo = self.qti.createElement('flow')
present.appendChild(flo)
mat = self.qti.createElement('material')
flo.appendChild(mat)
mattext = self.qti.createElement('mattext')
mattext.appendChild(self.qti.createTextNode(yled.kysimus))
mat.appendChild(mattext)
self.testiViide(mat,yled)
self.testiPilt(mat,yled)
resp_grp = self.qti.createElement('response_grp')
resp_grp.setAttribute('ident',yled.get_id())
resp_grp.setAttribute('rcardinality',"Multiple")
flo.appendChild(resp_grp)
render = self.qti.createElement('render_choice')
render.setAttribute('shuffle','Yes')
resp_grp.appendChild(render)
i=0
krupp = ''
for abc in yled.vastused:
resp_lab = self.qti.createElement('response_label')
ident = 'p'+str(i)
if krupp != '':
krupp = krupp+','
krupp = krupp + ident
resp_lab.setAttribute('ident',ident)
resp_lab.setAttribute('rshuffle','Yes')
resp_lab.setAttribute('rrange','Exact')
render.appendChild(resp_lab)
rmat = self.qti.createElement('material')
resp_lab.appendChild(rmat)
rmattext = self.qti.createElement('mattext')
rmattext.setAttribute('texttype','text/plain')
rmattext.appendChild(self.qti.createTextNode(abc))
rmat.appendChild(rmattext)
i=i+1
i=0
for abc in yled.kysimused:
resp_lab = self.qti.createElement('response_label')
resp_lab.setAttribute('ident','v'+str(i))
resp_lab.setAttribute('match_max','1')
resp_lab.setAttribute('match_group',krupp)
resp_lab.setAttribute('rshuffle','Yes')
resp_lab.setAttribute('rrange','Exact')
render.appendChild(resp_lab)
rmat = self.qti.createElement('material')
resp_lab.appendChild(rmat)
rmattext = self.qti.createElement('mattext')
rmattext.setAttribute('texttype','text/plain')
rmattext.appendChild(self.qti.createTextNode(abc))
rmat.appendChild(rmattext)
i=i+1
resproc = self.qti.createElement('resprocessing')
elem.appendChild(resproc)
out = self.qti.createElement('outcomes')
resproc.appendChild(out)
muut = self.qti.createElement('decvar')
muut.setAttribute('vartype','Integer')
muut.setAttribute('maxvalue',str(yled.normPunktid))
out.appendChild(muut)
kond = self.qti.createElement('respcondition')
kond.setAttribute('title','Correct')
resproc.appendChild(kond)
kond_var = self.qti.createElement('conditionvar')
kond.appendChild(kond_var)
jah = self.qti.createElement('and')
kond_var.appendChild(jah)
i=0
for abc in yled.vastused:
varsub = self.qti.createElement('varsubset')
varsub.setAttribute('respident',yled.get_id())
varsub.setAttribute('setmatch','Exact')
varsub.appendChild(self.qti.createTextNode('v'+str(i)+','+'p'+str(i)))
jah.appendChild(varsub)
i=i+1
setvar = self.qti.createElement('setvar')
setvar.setAttribute('action','Add')
setvar.appendChild(self.qti.createTextNode(str(yled.normPunktid)))
kond.appendChild(setvar)
pass
vanem.appendChild(sektion)
return
iva-0.7.4/JamArtefact.py 0000644 0000000 0000000 00000041146 10345616031 0016106 0 ustar viewcvs viewcvs 0000001 0000000 # -*- coding: utf-8
# $Id$
# Copyright 2001, 2002 by IVA Team and contributors
#
# This file is part of IVA.
#
# IVA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# IVA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with IVA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
__version__ = '$Revision$'[11:-2]
from types import StringType
import time
try:
from PIL import Image
PIL_imported = 1
except ImportError:
PIL_imported = 0
import cStringIO
import OFS
import Globals
from Globals import Persistent
from AccessControl import ClassSecurityInfo
from Thread import EventManager
from TraversableWrapper import Traversable
from common import add_dtml, reload_dtml, intersect_bool, get_roles
from common import perm_view, perm_edit, perm_manage, perm_add_lo, translate
from common import roles_admin
from common import roles_student, roles_tutor, roles_teacher
from input_checks import render, normal_entry_tags
class JamArtefact(
Traversable,
Persistent,
EventManager,
OFS.Folder.Folder,
OFS.SimpleItem.Item
):
"""JamArtefact"""
meta_type = 'JamArtefact'
security= ClassSecurityInfo()
security.declareObjectPublic()
def __init__(self, id_, parent_ids, name, data, content_type):
self.id = id_
self.title = name
EventManager.__init__(self)
self.__name = name
self.__data = data
self.__censored = 0
self.__content_type = content_type
# generate suitable thumbnail/icon depending on content_type
subtype = content_type[content_type.find('/')+1:]
content_type = content_type[:content_type.find('/')]
if content_type == 'image':
if not PIL_imported:
print "Can't create thumbnail image. PIL not installed."
try:
s = cStringIO.StringIO(data)
im = Image.open(s)
im.thumbnail((60, 60))
if im.mode != 'RGB':
im = im.convert('RGB')
s = cStringIO.StringIO()
im.save(s, "JPEG")
s.seek(0)
self.__thumbnail = s.read()
except:
self.__icon = 'images/jam_type_img'
elif content_type == 'audio':
self.__icon = 'images/jam_type_sound'
elif content_type == 'text':
if subtype == 'html':
self.__icon = 'images/jam_type_html'
else:
self.__icon = 'images/jam_type_text'
elif content_type == 'video':
self.__icon = 'images/jam_type_video'
elif content_type == 'application':
# Ideally, we should have all archive format MIME types here..
if subtype in ('gnutar', 'zip', 'x-compress', 'x-compressed',
'x-gtar', 'x-tar', 'x-zip', 'x-zip-compressed',
'x-shar', 'x-bzip', 'x-bzip2', 'x-cpio'):
self.__icon = 'images/jam_type_arch'
else:
self.__icon = 'images/jam_type_no'
else:
self.__icon = 'images/jam_type_no'
self.__annotations = []
if type(parent_ids) == StringType:
parent_ids = (parent_ids,)
self.__parent_ids = parent_ids
security.declarePrivate('manage_afterAdd')
def manage_afterAdd(self, item, container):
"""Set default permissions for roles."""
self.manage_permission(perm_manage, roles_admin, 0)
self.manage_permission(perm_edit, roles_teacher, 0)
self.manage_permission(perm_add_lo, roles_student, 0)
self.manage_permission(perm_view, roles_student, 0)
security.declareProtected(perm_view, 'index_html')
def index_html(self, REQUEST):
"""Update reader status before showing the page."""
uname = repr(REQUEST.AUTHENTICATED_USER)
self.update_reader(uname)
self.uncache_unread_artefacts(uname)
return REQUEST.RESPONSE.redirect('jam_artefact_index_html')
# return self.jam_artefact_index_html(self, REQUEST)
security.declareProtected(perm_view, 'get_children_artefacts')
def get_children_artefacts(self):
"""Return a list of children artefacts."""
children = []
for ja in self.parent().get_children('JamArtefact'):
if self.get_id() in ja.get_parent_ids():
children.append(ja)
return children
security.declareProtected(perm_view, 'get_name')
def get_name(self, REQUEST=None):
"""Return name of the artefact."""
prefix = ''
if self.__censored:
if REQUEST:
uname = str(REQUEST.AUTHENTICATED_USER)
prefix = translate(self,'Censored',target=self.giveLanguage(REQUEST))
else:
prefix = 'CENSORED'
uname=''
# If the person is not the author and is not a teacher,
# we only show the prefix (the censored notice)
if uname!=self.get_author() and \
not self.may_censor_jam_artefact(uname):
return prefix
prefix = prefix + ' / '
return prefix + self.__name
# Return real name of the artefact, even when the artefact is censored.
security.declarePrivate('get_real_name')
def get_real_name(self):
"""Return name of the artefact."""
return self.__name
security.declareProtected(perm_view, 'get_data')
def get_data(self, REQUEST=None, RESPONSE=None):
"""Return actual data."""
if self.__censored:
if not REQUEST or \
not self.may_censor_jam_artefact(
str(REQUEST.AUTHENTICATED_USER)): return None
if REQUEST:
self.update_reader(repr(REQUEST.AUTHENTICATED_USER))
if REQUEST and RESPONSE:
RESPONSE.setHeader('Content-Type', self.__content_type)
return self.__data
security.declarePrivate('get_real_data')
def get_real_data(self):
"""Return actual data."""
return self.__data
security.declareProtected(perm_view, 'get_content_type')
def get_content_type(self):
"""Return content type."""
return self.__content_type
security.declareProtected(perm_view, 'get_icon')
def get_icon(self, REQUEST, RESPONSE):
"""Return icon."""
if self.__censored:
return self.unrestrictedTraverse('images/jam_type_censored').data
elif hasattr(self, '_' + self.__class__.__name__+ '__icon'):
return self.unrestrictedTraverse(self.__icon).data
else:
RESPONSE.setHeader('Content-Type', 'image/jpeg')
return self.__thumbnail
security.declareProtected(perm_view, 'get_author')
def get_author(self):
"""Return author (owner) of this item."""
return self.getOwner()
security.declareProtected(perm_view, 'get_n_annotations')
def get_n_annotations(self):
"""Return the number of annotations."""
return len(self.__annotations)
security.declareProtected(perm_view, 'get_n_censored_annotations')
def get_n_censored_annotations(self):
"""Return the number of censored annotations."""
n = 0
for t in self.__annotations:
if t[3]: n += 1
return n
security.declareProtected(perm_view, 'get_n_uncensored_annotations')
def get_n_uncensored_annotations(self):
"""Return the number of uncensored annotations."""
n = 0
for t in self.__annotations:
if not t[3]: n += 1
return n
security.declareProtected(perm_view, 'get_annotations')
def get_annotations(self, REQUEST):
"""Return list of annotation tuples."""
if self.__censored and \
not self.may_censor_jam_artefact(str(REQUEST.AUTHENTICATED_USER)):
return []
# FIXME: This have to be changed when we have censoring
# FIXME: on the annotation level.
anns = []
for (who, when, what, censored, censorer) in self.__annotations:
if censored:
stamp = time.strftime(translate(self,'short_date_format',default="%Y-%m-%d",target=self.giveLanguage(REQUEST)),
time.localtime(censored))
prefix = 'censored %s %s' % (censorer, stamp)
uname = str(REQUEST.AUTHENTICATED_USER)
if uname != self.get_author() and \
not self.may_censor_jam_artefact(uname):
what = prefix
else:
what = prefix + \
'' + render(what,
legal_tags=normal_entry_tags,
do_horizontal_space=1)
else:
what = render(what,
legal_tags=normal_entry_tags,
do_horizontal_space=1)
anns.append((who, when, what, censored, censorer))
return anns
security.declarePrivate('get_real_annotations')
def get_real_annotations(self):
"""Return list of annotation tuples."""
return self.__annotations
security.declarePrivate('add_annotation')
def add_annotation(self, uname, annotation_time, annotation_text):
"""Add annotation to JamArtefact."""
# annotation censorship
censored = 0
censorer = ''
# uname and annotation_time can be used as a key attribute
self.__annotations.append((uname, annotation_time, annotation_text,
censored, censorer))
self._p_changed = 1
security.declarePrivate('do_censor_annotations')
def do_censor_annotations(self, annotation_indexes, time, user):
"""Censor annotation."""
for i in [int(x) for x in annotation_indexes]:
t = self.__annotations[i]
self.__annotations[i] = (t[0], t[1], t[2], time, user)
self._p_changed = 1
security.declarePrivate('do_uncensor_annotations')
def do_uncensor_annotations(self, annotation_indexes):
"""Uncensor annotation."""
for i in [int(x) for x in annotation_indexes]:
t = self.__annotations[i]
self.__annotations[i] = (t[0], t[1], t[2], 0, '')
self._p_changed = 1
security.declareProtected(perm_add_lo, 'add_annotation_form_handler')
def add_annotation_form_handler(
self,
REQUEST,
annotation_text,
submit = '', # form buttons
cancel = '', #
):
"""Add annotation form handler."""
user = str(REQUEST.AUTHENTICATED_USER)
if self.__censored and not self.may_censor_jam_artefact(user):
raise 'FLE Error', "I don't want to anything."
if submit:
time_now = time.time()
# FIXME: report that annotation_text doesn't work
if annotation_text:
self.add_annotation(user, time_now, annotation_text)
self.updateStat(REQUEST, 'postedArtefactAnnos')
self.updateStat(REQUEST, 'jamming')
elif cancel:
pass
else:
raise 'FLE Error', 'Unknown button.' # Should never happen.
REQUEST.RESPONSE.redirect('index_html')
security.declareProtected(perm_view, 'get_parent_ids')
def get_parent_ids(self):
"""Return a list of parent ids."""
if type(self.__parent_ids) == StringType:
return (self.__parent_ids,)
else:
return self.__parent_ids
security.declarePrivate('set_parent_ids')
def set_parent_ids(self, parent_ids):
"""Set parent ids."""
self.__parent_ids = parent_ids
security.declareProtected(perm_view, 'may_censor_jam_artefact')
def may_censor_jam_artefact(self, person):
"""Return boolean depending on whether user may or may not
censor jam artefacts."""
from AccessControl.PermissionRole import rolesForPermissionOn
return intersect_bool(
get_roles(self, person),
rolesForPermissionOn(perm_edit, self))
security.declareProtected(perm_edit, 'censor_jam_artefact_handler')
def censor_jam_artefact_handler(
self, REQUEST,
censor=None, # buttons in jam artefact page
uncensor=None, #
censor_annotations=None, #
uncensor_annotations=None, #
verify=None, # buttons in verify page
verify_annotations=None, #
cancel=None, #
annotation_indexes=(),
):
"""Handles jam_artefact censorship."""
if type(annotation_indexes) == StringType:
annotation_indexes = (annotation_indexes,)
if verify:
import time
self.do_censor(time.time(),str(REQUEST.AUTHENTICATED_USER))
if REQUEST:
return self.message_dialog(
self, REQUEST,
title='Message is censored',
message='Message is censored',
action='index_html')
if verify_annotations:
import time
self.do_censor_annotations(annotation_indexes,
time.time(),
str(REQUEST.AUTHENTICATED_USER))
if REQUEST:
return self.message_dialog(
self, REQUEST,
title='Annotation is censored',
message='Annotation is censored',
action='index_html')
elif cancel:
if REQUEST:
REQUEST.RESPONSE.redirect('index_html')
elif uncensor:
self.do_uncensor()
if REQUEST:
REQUEST.RESPONSE.redirect('index_html')
elif uncensor_annotations:
self.do_uncensor_annotations(annotation_indexes)
if REQUEST:
REQUEST.RESPONSE.redirect('index_html')
elif censor:
if REQUEST:
return self.message_dialog2(
self, REQUEST,
title='Warning',
message='Are you sure you want to censor this artefact? Your name and this date will be stored and displayed along with the censorship notice to everyone viewing this artefact.',
handler='censor_jam_artefact_handler',
extra_value_name='jam_artefact',
extra_values=(str(self.get_id()),),
option1_value = 'cancel',
option1_name = 'cancel',
option2_value = 'ok',
option2_name = 'verify')
elif censor_annotations:
if REQUEST:
return self.message_dialog2(
self, REQUEST,
title="Warning",
message="Are you sure you want to censor the annotations you selected? Your name and this date will be stored and displayed along with the censorship notice to everyone viewing annotations.",
handler='censor_jam_artefact_handler',
extra_value_name='annotation_indexes',
extra_values=annotation_indexes,
option1_value = 'Cancel',
option1_name = 'cancel',
option2_value = 'Ok',
option2_name = 'verify_annotations')
else:
raise 'FLE Error', 'Unknown button'
def do_censor(self, time, user):
self.__censored = time
self.__censorer = user
def do_uncensor(self):
self.__censored = 0
del self.__censorer
security.declareProtected(perm_view, 'is_censored')
def is_censored(self):
"""Return whether this jam artefact is censored."""
return not not self.__censored
security.declareProtected(perm_view, 'get_censor_time')
def get_censor_time(self, REQUEST):
"""Return time when the artefact was censored."""
return time.strftime(translate(self,'short_date_format',default="%Y-%m-%d",target=self.giveLanguage(REQUEST)),
time.localtime(self.__censored))
security.declareProtected(perm_view, 'get_censorer')
def get_censorer(self):
"""Return person who censored the artefact."""
return self.__censorer
Globals.default__class_init__(JamArtefact)
# EOF
iva-0.7.4/JamSession.py 0000644 0000000 0000000 00000023770 10345616031 0016003 0 ustar viewcvs viewcvs 0000001 0000000 # -*- coding: utf-8
# $Id$
# Copyright 2001, 2002 by IVA Team and contributors
#
# This file is part of IVA.
#
# IVA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# IVA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with IVA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""Contains class JamSession, which is abstract base class for different
JamSession types."""
__version__ = '$Revision$'[11:-2]
from types import StringType
from urllib import quote_plus
import OFS, Globals, AccessControl
from Globals import Persistent
from AccessControl import ClassSecurityInfo
from JamArtefact import JamArtefact
from TraversableWrapper import TraversableWrapper
from input_checks import is_valid_title
from common import reload_dtml, add_dtml, intersect_bool, translate
from common import perm_view, perm_edit, perm_manage, perm_add_lo, \
roles_admin, roles_staff, roles_user
class JamSession(
TraversableWrapper,
OFS.Folder.Folder,
Persistent,
AccessControl.Role.RoleManager,
):
"""JamSession"""
meta_type = 'JamSession'
security= ClassSecurityInfo()
security.declareObjectPublic()
def __init__(self,
id_,
name,
description,
start_artefact_name,
start_artefact_data,
start_artefact_content_type):
"""Construct JamSession."""
self.id = id_
self.title = ''
self.__name = name
self.__description = description
# pass to manage_afterAdd
self._t_name = start_artefact_name
self._t_data = start_artefact_data
self._t_ct = start_artefact_content_type
security.declarePrivate('manage_afterAdd')
def manage_afterAdd(self, item, container):
"""Set default permissions for roles."""
self.add_artefact(self._t_name, self._t_data, self._t_ct)
del self._t_name
del self._t_data
del self._t_ct
self.update_drawing()
from common import roles_student, roles_tutor, roles_teacher
from common import roles_admin
self.manage_permission(perm_manage, roles_admin, 0)
self.manage_permission(perm_edit, roles_teacher, 0)
self.manage_permission(perm_add_lo, roles_student, 0)
security.declareProtected(perm_view, 'get_name')
def get_name(self):
"""Return name of the JamSession."""
return self.__name
security.declareProtected(perm_view, 'get_description')
def get_description(self):
"""Return desctiption of the JamSession."""
return self.__description
security.declarePrivate('uncache_artefacts')
def uncache_artefacts(self):
if hasattr(self,'__cached_n_artefacts'):
del self.__cached_n_artefacts
if hasattr(self,'__cached_n_unread_artefacts'):
del self.__cached_n_unread_artefacts
security.declareProtected(perm_view, 'get_n_artefacts')
def get_n_artefacts(self):
"""Return number of artefacts in this JamSession"""
if hasattr(self, '__cached_n_artefacts'):
return self.__cached_n_artefacts
else:
n = len(self.get_children('JamArtefact'))
self.__cached_n_artefacts = n
return n
security.declarePrivate('uncache_unread_artefacts')
def uncache_unread_artefacts(self, uname):
if hasattr(self, '__cached_n_unread_artefacts'):
if uname in self.__cached_n_unread_artefacts.keys():
del self.__cached_n_unread_artefacts.keys[uname]
security.declareProtected(perm_view, 'get_n_unread_artefacts')
def get_n_unread_artefacts(self, REQUEST):
"""Return number of unread artefacts in this JamSession"""
uname = str(REQUEST.AUTHENTICATED_USER)
if hasattr(self, '__cached_n_unread_artefacts'):
if uname in self.__cached_n_unread_artefacts.keys():
return
else:
self.__cached_n_unread_artefacts = {}
n = 0
for a in self.get_children('JamArtefact'):
if not a.is_reader(uname):
n += 1
self.__cached_n_unread_artefacts[uname] = n
return n
security.declareProtected(perm_view, 'get_starting_artefact_id')
def get_starting_artefact_id(self):
"""Return ID of the starting artefact."""
return self.__starting_artefact_id
security.declareProtected(perm_view, 'render')
# This is called from DTML, return a list of lists (DTML
# constructs a table using that information.)
def render(self):
"""Render JamSession."""
return self.drawing
security.declareProtected(perm_add_lo, 'add_artefact')
def add_artefact(self, name, data, content_type, parent_ids=(),
REQUEST=None):
"""Add new artefact to JamSession."""
# Jamming Course CourseManager
# | | |
id_ = 'ja' + self.parent().parent().parent().generate_id()
if len(parent_ids) == 0:
self.__starting_artefact_id = id_
self._setObject(id_, JamArtefact(id_, parent_ids, name,
data, content_type))
ja = self.get_child(id_)
if REQUEST: ja.update_reader(repr(REQUEST.AUTHENTICATED_USER))
return ja
security.declareProtected(perm_view, 'index_html')
def index_html(self, REQUEST):
""" index page of jamsession """
self.updateStat(REQUEST, 'visit_jamming')
return REQUEST.RESPONSE.redirect('jamsession_index_html')
security.declareProtected(perm_add_lo, 'index_html_form_handler')
def index_html_form_handler(
self, REQUEST,
parent_ids='invalid_id',
):
"""Redirect to add_artefact_form."""
if parent_ids == 'invalid_id':
return self.message_dialog_error(
self, REQUEST,
title='Invalid input',
message='Select some items first',
action='index_html')
from types import StringType
if type(parent_ids) == StringType:
parent_ids = (parent_ids,)
REQUEST.RESPONSE.redirect('jam_add_artefact_form?parent_ids=%s' % ','.join(parent_ids))
# REQUEST.RESPONSE.redirect(
# self.state_href(REQUEST,
# 'add_artefact_form?parent_ids=%s' %
# ','.join(parent_ids)
# )
# )
security.declareProtected(perm_add_lo, 'add_artefact_form_handler')
def add_artefact_form_handler(
self, REQUEST,
artefact_name = '',
artefact_upload = None,
parent_ids = (),
submit = '', # submit buttons
cancel = '',
):
"""Form handler for add_artefact_form."""
if submit:
parent_ids = parent_ids.split(',')
errors = []
artefact_name = artefact_name.strip()
if not is_valid_title(artefact_name):
errors.append(translate(self,'Name of the artefact',target=self.giveLanguage(REQUEST)))
if not artefact_upload or len(artefact_upload.filename) == 0:
errors.append(translate(self,'Upload file',target=self.giveLanguage(REQUEST)))
if type(parent_ids) == StringType:
parent_ids = (parent_ids,)
# Some sanity checks to make sure that
# a) there aren't errors in our code
# b) some evil cracker is not modifying input
if len(parent_ids) == 0:
raise 'FLE Error', 'no parent_ids given'
if self.get_type() in ('linear', 'tree'):
if len(parent_ids) != 1:
raise 'FLE Error', 'Only one parent should be given'
existing_ids = [a.get_id() for a in
self.get_children('JamArtefact')]
for pid in parent_ids:
if pid not in existing_ids:
raise 'FLE Error', \
'Trying to add artefact to non_existing artefact'
if self.get_type() == 'linear':
parent_id_list = []
for a in self.get_children('JamArtefact'):
for pid in a.get_parent_ids():
parent_id_list.append(pid)
if intersect_bool(parent_ids, parent_id_list):
raise 'FLE Error', \
'Trying to add artefact to non-last artefact.'
# FIXME: Add checks for 'tree' and 'graph' types
if len(errors) > 0:
return self.message_dialog_error(
self, REQUEST,
title='Invalid input',
message= translate(self,'Invalid fields',target=self.giveLanguage(REQUEST)) + ": '" + \
"' , '".join(errors) + "'",
parent_ids=''.join(parent_ids),
action='jam_add_artefact_form?parent_ids=%s' % ''.join(parent_ids))
data = artefact_upload.read()
try:
content_type = artefact_upload.headers['content-type']
except KeyError:
content_type = ''
self.add_artefact(artefact_name, data, content_type, parent_ids,
REQUEST)
self.updateStat(REQUEST, 'postedArtefacts')
self.updateStat(REQUEST, 'jamming')
self.update_drawing()
self.uncache_artefacts()
elif cancel:
pass
else:
raise 'FLE Error', 'Unknown button' # Should never happen
REQUEST.RESPONSE.redirect('index_html')
Globals.default__class_init__(JamSession)
# EOF
iva-0.7.4/JamSessionGraph.py 0000644 0000000 0000000 00000033517 10345616031 0016765 0 ustar viewcvs viewcvs 0000001 0000000 # -*- coding: utf-8
# $Id$
# Copyright 2001, 2002 by IVA Team and contributors
#
# This file is part of IVA.
#
# IVA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# IVA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with IVA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""Contains classes LayeredGraph and JamSessionGraph."""
__version__ = '$Revision$'[11:-2]
try:
from PIL import Image, ImageDraw
except ImportError:
pass
import cStringIO
import Globals
from AccessControl import ClassSecurityInfo
from JamSession import JamSession
from common import perm_view, perm_edit, perm_manage, perm_add_lo
# The sole purpose of this class is to help JamSessionGraph.
# The code does not probably make too much sense unless you know something
# about graph drawing. The information used to implement this class comes
# from the book "Graph Drawing: Algorithms for the Visualization of Graphs"
class LayeredGraph:
"""This class helps to draw DAG as a layered graph."""
def __init__(self, V, E):
destination_nodes = []
for (u,v) in E:
destination_nodes.append(v)
self.__nodes = {}
for node in V:
self.__nodes[node] = {}
for node in V:
if node not in destination_nodes:
self.__start_node = node
break
self.__edges = E
self.__to_layered_graph()
self.__to_proper()
self.__reduce_crossings()
def get_representation(self):
G = {}
G['nodes'] = self.__nodes
G['edges'] = self.__edges
G['layers'] = self.__layers
return G
def __to_layered_graph(self):
nodes = self.__nodes
edges = self.__edges
# At this point every node is real, i.e. there are not dummy nodes.
done = []
todo = []
for node_name in nodes.keys():
nodes[node_name]['real'] = 1
if node_name == self.__start_node:
nodes[node_name]['layer'] = 0
done.append(node_name)
else:
nodes[node_name]['layer'] = -1
todo.append(node_name)
# Assign nodes to layers.
while len(todo) > 0:
for (u,v) in edges:
if (u not in done) or (v not in todo):
continue
# Node u is assigned to some layer.
# Node v does not has layer yet.
# We can assign a layer to v, if for all (x,v) in
# edges, node x already has an assigned layer...
ok = 1
u_nodes = []
for (a,b) in edges:
if b is not v: continue
if a not in done:
ok = 0
break
else:
u_nodes.append(a)
# ... no, that is not the case.
if not ok:
continue
# Yes, we can assign a layer to v.
layer = max([nodes[n]['layer'] for n in u_nodes])
nodes[v]['layer'] = layer + 1
done.append(v)
todo.remove(v)
def __to_proper(self):
nodes = self.__nodes
edges = self.__edges
# Make dummy nodes
i = 0
to_remove = []
for (u,v) in edges:
difference = nodes[v]['layer'] - nodes[u]['layer']
# All egdes that span several layers are replaced with
# dummy layers and short edges, e.g:
#
# layer 0 N N
# |\ |\
# layer 1 N | N D
# | | ==> | |
# layer 2 N | N D
# | |
# layer 3 N N
#
# N = node, D = dummy node
if difference > 1:
to_remove.append((u,v)) # remove the original edge later
layer = nodes[u]['layer'] + 1
a = u
while difference > 1:
b = 'dummy' + str(i)
# make edge
edges.append((a,b))
# make dummy node
dummy_node = {'layer': layer, 'real': 0}
nodes[b] = dummy_node
# update for next loop
a = b; i += 1; difference -= 1; layer +=1
edges.append((b,v)) # the edge from the last dummy node
# Actual removing
for (u,v) in to_remove:
edges.remove((u,v))
# Order of nodes on each layer. (Cross reduction phase
# will re-order nodes on each layer...)
layers = []
for i in range(0, max([nodes[node_name]['layer'] for \
node_name in nodes.keys()]) + 1):
layers.append([])
for node_name in nodes.keys():
l = nodes[node_name]['layer']
layers[l].append(node_name)
self.__layers = layers
def __n_crossings(self):
n = 0
for i in range(1, len(self.__layers)):
n += self.__crossing_number(i-1, i)
return n
def __crossing_number(self, layer_1_index, layer_2_index):
if layer_1_index > layer_2_index:
layer_1_index, layer_2_index = layer_2_index, layer_1_index
layer_1 = self.__layers[layer_1_index]
layer_2 = self.__layers[layer_2_index]
number = 0
for u in range(0, len(layer_2)):
for v in range(u+1, len(layer_2)):
u_pos = []
v_pos = []
for (a,b) in self.__edges:
if (a not in layer_1) or (b not in layer_2): continue
if b == layer_2[u]:
u_pos.append(layer_1.index(a))
elif b == layer_2[v]:
v_pos.append(layer_1.index(a))
for i in v_pos:
for j in u_pos:
if j > i: number += 1
return number
# Median method (not perfect, odd and even degree stuff is
# not implemented.)
def __two_layer_crossing_reduce(self,
fixed_layer_index,
changing_layer_index):
nodes = self.__nodes
layers = self.__layers
fixed_layer = layers[fixed_layer_index]
changing_layer = layers[changing_layer_index]
pos = []
for node_name in changing_layer:
neighbour_pos = []
for neighbour in nodes[node_name]['neighbours']:
if nodes[neighbour]['layer'] != fixed_layer_index: continue
neighbour_pos.append(fixed_layer.index(neighbour))
if len(neighbour_pos) > 0:
pos.append(neighbour_pos[len(neighbour_pos)/2])
else:
pos.append(0)
for j in range(0, len(pos)):
min_val = pow(2,30)
index = 0
for k in range(0, len(pos)):
if pos[k] >= 0 and pos[k] < min_val:
min_val = pos[k]
index = k
pos[index] = -len(pos) + j
for j in range(0,len(pos)):
pos[j] += len(pos)
new_layer = []
for j in range(len(changing_layer)):
new_layer.append(changing_layer[pos[j]])
layers[changing_layer_index] = new_layer
def __reduce_crossings(self):
nodes = self.__nodes
edges = self.__edges
# Add explicit neigbourhood information to each node
for node_name in nodes.keys():
nodes[node_name]['neighbours'] = []
for (u,v) in edges:
u_neighbours = nodes[u]['neighbours']
v_neighbours = nodes[v]['neighbours']
if v not in u_neighbours:
u_neighbours.append(v)
if u not in v_neighbours:
v_neighbours.append(u)
# Crossing reduction
r = range(1, len(self.__layers))
n_a = 0 # number of crossing after top to bottom sweep
n_b = 0 # number of crossing after bottom to top sweep
n_loops = 0
tested = []
min_val = pow(2,30)
while n_loops < 10 and ((n_a, n_b) not in tested or n_b > min_val):
n_loops += 1
tested.append((n_a, n_b))
# sweep from top to bottom...
for i in r: self.__two_layer_crossing_reduce(i-1, i)
n_a = self.__n_crossings()
r.reverse()
# ... and back from bottom to top.
for i in r: self.__two_layer_crossing_reduce(i, i-1)
n_b = self.__n_crossings()
r.reverse()
if n_b < min_val:
min_val = n_b
class JamSessionGraph(JamSession):
"""JamSessionGraph"""
meta_type = 'JamSession'
security= ClassSecurityInfo()
security.declareObjectPublic()
security.declareProtected(perm_view, 'get_type')
def get_type(self):
"""Return type of the JamSession."""
return 'graph'
security.declareProtected(perm_view, 'get_printable_type')
def get_printable_type(self):
"""Return printable (localized) type of the JamSession."""
return "Diverge and converge"
security.declarePrivate('update_drawing')
def update_drawing(self):
G = self.build_graph().get_representation()
# Assign horizontal positions for nodes ( real and dummy ones)
# FIXME: This code just puts nodes next to each other starting
# FIXME: from left.
columns = []
max_width = 0
for layer in G['layers']:
width = 0
cols = 0
for node_name in layer:
node = G['nodes'][node_name]
if node['real'] == 1:
node['position'] = width + 30 + 60
width += 5 * 30
else:
node['position'] = width + 15
width += 30
if width > max_width: max_width = width
columns.append(width / 30)
# How much we have to pad each (layer) row of the table?
for i in range(0, len(G['layers'])):
columns[i] = max_width/30 - columns[i]
G['width'] = max_width
G['columns'] = columns
G['n_nodes'] = n_nodes = len(
filter(lambda key, G=G: \
G['nodes'][key]['real'] == 1, G['nodes'].keys()))
# Delete old images.
self.manage_delObjects(self.objectIds('Image'))
# Draw new ones.
for i in range(1, len(G['layers'])):
im = Image.new('L', (max_width, 40), 255)
draw = ImageDraw.Draw(im)
for node_name in G['layers'][i]:
# If one node has several parent nodes, we want that
# incoming edges are separated:
#
# BAD! GOOD!
#
# \ | / \ | /
# \|/ \ | /
# **node** **node**
#
# Therefore, we put edges to the dictionary so that
# we can handle one node at a time.
to_draw = {}
for (u,v) in G['edges']:
if v == node_name:
if to_draw.has_key(v):
to_draw[v].append(u)
else:
to_draw[v]=[u]
# Loop over nodes
for v in to_draw.keys():
# Sort edges (u,v) by x-coordinate of u node...
data = []
for u in to_draw[v]:
data.append( (u, v, G['nodes'][u]['position']) )
data.sort(lambda x,y: ((x[2] <= y[2]) and [-1] or [1])[0])
# .. and then draw them from left to right
delta_delta = min(10, 100 / len(data))
delta = ((len(data)-1) / 2) * -delta_delta
for (u,v, dummy) in data:
draw.line([(G['nodes'][u]['position'], 0),
(G['nodes'][v]['position']+delta, 30),
(G['nodes'][v]['position']+delta, 40)],
fill=0)
# Draw arrow?
if G['nodes'][v]['real'] == 1:
draw.line([(G['nodes'][v]['position']+delta, 39),
(G['nodes'][v]['position']+delta-4,35)],
fill=0)
draw.line([(G['nodes'][v]['position']+delta, 39),
(G['nodes'][v]['position']+delta+4,35)],
fill=0)
delta += delta_delta
del draw
s = cStringIO.StringIO()
im.save(s, 'GIF')
s.seek(0)
content = s.read()
name = 'layer_' + str(i) + '_' + str(n_nodes)
self.manage_addImage(name, content, '')
self.drawing = G
security.declarePrivate('build_graph')
def build_graph(self):
V = []
E = []
for ja in self.get_children('JamArtefact'):
v = ja.get_id()
V.append(v)
for u in ja.get_parent_ids():
E.append((u,v))
return LayeredGraph(V, E)
Globals.default__class_init__(JamSessionGraph)
iva-0.7.4/JamSessionLinear.py 0000644 0000000 0000000 00000004051 10345616031 0017125 0 ustar viewcvs viewcvs 0000001 0000000 # -*- coding: utf-8
# $Id$
# Copyright 2001, 2002 by IVA Team and contributors
#
# This file is part of IVA.
#
# IVA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# IVA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with IVA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
__version__ = '$Revision$'[11:-2]
import Globals
from AccessControl import ClassSecurityInfo
from JamSessionLinearOrTree import table
from JamSessionLinearOrTree import JamSessionLinearOrTree
from JamSession import JamSession
from common import perm_view, perm_edit, perm_manage, perm_add_lo
class JamSessionLinear(
JamSession,
JamSessionLinearOrTree,
):
"""JamSessionLinear"""
meta_type = 'JamSession'
security= ClassSecurityInfo()
security.declareObjectPublic()
security.declareProtected(perm_view, 'get_type')
def get_type(self):
"""Return type of the JamSession."""
return 'linear'
security.declareProtected(perm_view, 'get_printable_type')
def get_printable_type(self):
"""Return printable (localized) type of the JamSession."""
return "Mutate on previous"
security.declarePrivate(perm_view, 'update_drawing')
def update_drawing(self):
tree = self.build_tree(self.get_children('JamArtefact')[0])
t = table(('empty',None))
self.table_render_tree(tree, t, 1, 0)
for y in range(t.get_height()-2):
if t.get(0, y)[0] == '_selection':
t.set(0, y, ('empty', None))
self.drawing = t.get_repr()
Globals.default__class_init__(JamSessionLinear)
iva-0.7.4/JamSessionLinearOrTree.py 0000644 0000000 0000000 00000010307 10345616031 0020247 0 ustar viewcvs viewcvs 0000001 0000000 # -*- coding: utf-8
# $Id$
# Copyright 2001, 2002 by IVA Team and contributors
#
# This file is part of IVA.
#
# IVA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# IVA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with IVA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
__version__ = '$Revision$'[11:-2]
import Globals
"""Simple two dimensional table."""
class table:
def __init__(self, empty_val):
self._t = []
self._w = 0
self._h = 0
self._empty_val = empty_val
def get_repr(self):
return self._t
def get_width(self):
return self._w
def get_height(self):
return self._h
def set(self, x, y, data):
if y >= self._h:
for i in range(y - self._h + 1):
self._t.append([self._empty_val] * self._w)
self._h = y + 1
if x >= self._w:
for i in range(self._h):
for j in range(x - self._w + 1):
self._t[i].append(self._empty_val)
self._w = x + 1
self._t[y][x] = data
def get(self, x, y):
return self._t[y][x]
def debug_print(self):
for row in self._t:
for data in row:
print data,
print
class JamSessionLinearOrTree:
"""JamSessionLinearOrTree"""
def build_tree(self, root_artefact):
return {'artefact_id': root_artefact.get_id(),
'children': [self.build_tree(x) for x in \
root_artefact.get_children_artefacts()]
}
# Render tree depth first, from left to right.
# The letters in 'ns', 'nes', 'esw', 'ew', 'sw' correspond
# to north, east, south, and west.
def table_render_tree(self, tree, table, x, y):
"""Render table into table"""
# Render this node...
table.set(x-1, y, ('_selection', tree['artefact_id']))
table.set(x, y, ('artefact', tree['artefact_id']))
ret_dim_info = [x]
# .. and then all of its children, from left to right.
if len(tree['children']) > 0:
table.set(x, y+1, ('ns', None)) # may be modified later
# leftmost child
dim_info = \
self.table_render_tree(tree['children'][0], table, x, y+2)
for d in dim_info:
ret_dim_info.append(d)
# the rest of children
for node in tree['children'][1:]:
# Figure out horizontal position for this node.
m = x
for i in range(self.left_depth(node)):
try: m = max(m, dim_info[i])
except IndexError: break # current branch deeper
# Draw stuff between left sibling (of this node) and this node.
sx = ret_dim_info[1]
if sx == x:
table.set(sx, y+1, ('nes', None))
else:
table.set(sx, y+1, ('esw', None))
for i in range(sx+1, m+2):
table.set(i, y+1, ('ew', None))
table.set(m+2, y+1, ('sw', None))
# Draw recursively this node.
dim_info = self.table_render_tree(node, table, m+2, y+2)
# Update red_dim_info.
for i in range(len(dim_info)):
try:
ret_dim_info[i+1] = max(ret_dim_info[i+1], dim_info[i])
except IndexError:
ret_dim_info.append(dim_info[i])
return ret_dim_info
def left_depth(self, node):
if len(node['children']) > 0:
return self.left_depth(node['children'][0]) + 1
else:
return 1
Globals.default__class_init__(JamSessionLinearOrTree)
iva-0.7.4/JamSessionTree.py 0000644 0000000 0000000 00000003634 10345616031 0016620 0 ustar viewcvs viewcvs 0000001 0000000 # -*- coding: utf-8
# $Id$
# Copyright 2001, 2002 by IVA Team and contributors
#
# This file is part of IVA.
#
# IVA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# IVA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with IVA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
__version__ = '$Revision$'[11:-2]
import Globals
from AccessControl import ClassSecurityInfo
from JamSessionLinearOrTree import table
from JamSessionLinearOrTree import JamSessionLinearOrTree
from JamSession import JamSession
from common import perm_view, perm_edit, perm_manage, perm_add_lo
class JamSessionTree(
JamSession,
JamSessionLinearOrTree,
):
"""JamSessionTree"""
meta_type = 'JamSession'
security= ClassSecurityInfo()
security.declareObjectPublic()
security.declareProtected(perm_view, 'get_type')
def get_type(self):
"""Return type of the JamSession."""
return 'tree'
security.declareProtected(perm_view, 'get_printable_type')
def get_printable_type(self):
"""Return printable (localized) type of the JamSession."""
return "Explore possibilities"
security.declarePrivate(perm_view, 'update_drawing')
def update_drawing(self):
tree = self.build_tree(self.get_children('JamArtefact')[0])
t = table(('empty',None))
self.table_render_tree(tree, t, 1, 0)
self.drawing = t.get_repr()
Globals.default__class_init__(JamSessionTree)
iva-0.7.4/Jamming.py 0000644 0000000 0000000 00000020464 10345616031 0015307 0 ustar viewcvs viewcvs 0000001 0000000 # -*- coding: utf-8
# $Id$
#
# Copyright 2001, 2002 by IVA Team and contributors
#
# This file is part of IVA.
#
# IVA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# IVA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with IVA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""Contains class Jamming, which has a number of JamSessions."""
__version__ = '$Revision$'[11:-2]
import time
import OFS, Globals
from Globals import Persistent
from AccessControl import ClassSecurityInfo
from Cruft import Cruft
from JamSessionLinear import JamSessionLinear
from JamSessionTree import JamSessionTree
from JamSessionGraph import JamSessionGraph
from TraversableWrapper import Traversable
from common import add_dtml, reload_dtml, intersect_bool, make_action, translate
from common import perm_view, perm_edit, perm_manage, perm_add_lo
from input_checks import is_valid_title
"""A container for JamSessions. The only reason we really need this
class is for implementing Jamming tab by using own fle_html_header here."""
class Jamming(
Traversable,
Cruft, # for find_URL_of_fle_root()
Persistent,
OFS.Folder.Folder,
):
"""Jamming, contained within Course, represents jamming for
one course."""
meta_type = 'Jamming'
security = ClassSecurityInfo()
security.declareObjectPublic()
def __init__(self, id_):
"""Constructor of the Jamming."""
self.id = id_
self.title = 'Jamming, container for JamSessions'
# This is for group folder path listings - show path up to jamming.
self.toplevel = 1
security.declareProtected(perm_view, 'index_html')
def index_html(self,REQUEST):
""" index html """
return REQUEST.RESPONSE.redirect('jamming_index_html')
security.declareProtected(perm_view, 'get_bg_colour_name')
def get_bg_colour_name(self):
"""..."""
return 'bl'
def get_name(self):
"""Get course name."""
return "jamming"
security.declareProtected(perm_view, 'get_n_jam_sessions')
def get_n_jam_sessions(self):
"""Return number of JamSessions in (the jamming of) this course."""
return len(self.get_children('JamSession'))
security.declareProtected(perm_view, 'get_n_artefacts')
def get_n_artefacts(self):
"""Return total number of JamArtefact in this jamming."""
n = 0
for js in self.get_children('JamSession'):
n += js.get_n_artefacts()
return n
security.declareProtected(perm_view, 'get_n_unread_artefacts')
def get_n_unread_artefacts(self, REQUEST):
"""Return total number of unread JamArtefact in this jamming."""
n = 0
for js in self.get_children('JamSession'):
n += js.get_n_unread_artefacts(REQUEST)
return n
security.declareProtected(perm_edit, 'delete_jam_session_handler')
def delete_jam_sessions_handler(
self,
REQUEST,
jam_session_id_list):
"""Form handler for deleting JamSessions."""
return self.message_dialog2(
self, REQUEST,
title = 'Confirmation',
message = translate(self, 'Are you sure you want to delete the following jam sessions:', target=self.giveLanguage(REQUEST)) + ' ' + \
', '.join([self.get_child(js_id).get_name() for \
js_id in jam_session_id_list]),
handler = 'delete_jam_sessions_confirmation_form_handler',
extra_value_name = 'jam_session_id_list',
extra_values = jam_session_id_list,
option1_value = 'Cancel',
option1_name = 'cancel',
option2_value = 'Ok',
option2_name = 'delete'
)
security.declareProtected(perm_edit,
'delete_jam_sessions_confirmation__handler')
def delete_jam_sessions_confirmation_form_handler(
self,
REQUEST,
jam_session_id_list,
cancel='', # submit buttons
delete='',
):
"""Delete jam sessions."""
if delete:
for js_id in jam_session_id_list:
self._delObject(js_id)
elif cancel:
pass
else:
raise 'FLE Error', 'Unknown button'
REQUEST.RESPONSE.redirect('index_html')
security.declareProtected(perm_add_lo, 'form_handler')
def form_handler(
self,
my_name = '',
type = None, # 'linear', 'tree', or 'graph'
description = None,
artefact_name = None,
artefact_upload = None,
annotation = '',
submit = '', # submit buttons
cancel = '', #
REQUEST = None,
):
"""Form handler for creating new JamSession."""
if submit:
if type == 'graph' and not self.has_PIL():
# Users are not able to select graph type from UI if PIL is
# not installed so this never happens unless input is hacked.
raise 'FLE Error', 'PIL not installed'
error_fields = []
my_name = my_name.strip()
if not is_valid_title(my_name):
error_fields.append(translate(self,'Title of jam session:',target=self.giveLanguage(REQUEST)))
if not description:
error_fields.append(translate(self,'Description of jam session:',target=self.giveLanguage(REQUEST)))
if type not in ('linear', 'tree', 'graph'):
error_fields.append(translate(self,'Type of jam session:',target=self.giveLanguage(REQUEST)))
if not artefact_upload or len(artefact_upload.filename)==0:
error_fields.append(translate(self,'Upload the starting artefact:',target=self.giveLanguage(REQUEST)))
if not is_valid_title(artefact_name):
error_fields.append(translate(self,'Name of the starting artefact:',target=self.giveLanguage(REQUEST)))
import re
tmp = error_fields
error_fields = []
for x in tmp:
error_fields.append(re.sub(':','',x))
if len(error_fields) > 0:
msg = translate(self,'Invalid fields',target=self.giveLanguage(REQUEST)) + ": '" + \
"' , '".join(error_fields) + "'"
return self.message_dialog_error(
self, REQUEST,
title= 'Invalid input',
message=msg,
action=apply(
make_action,
['jam_add_session_form'] +
[(x, eval(x)) for x in
('my_name', 'description', 'type', 'artefact_name',
'annotation')]))
data = artefact_upload.read()
try:
content_type = artefact_upload.headers['content-type']
except KeyError:
content_type = ''
id_ = 'js' + self.parent().parent().generate_id()
jam_session_class = {'linear': JamSessionLinear,
'tree': JamSessionTree,
'graph': JamSessionGraph}[type]
self._setObject(id_, jam_session_class(
id_,
my_name,
description,
artefact_name, # starting artefact
data, #
content_type, #
))
if REQUEST:
self.updateStat(REQUEST, 'postedArtefacts')
self.updateStat(REQUEST, 'jamming')
ja = self._getOb(id_).get_children('JamArtefact')[0]
uname = repr(REQUEST.AUTHENTICATED_USER)
ja.update_reader(uname)
if annotation:
ja.add_annotation(uname, time.time(), annotation)
elif cancel:
pass
else:
raise 'FLE Error', 'Unknown button' # Should never happen.
if REQUEST:
REQUEST.RESPONSE.redirect('index_html')
else: # import code
return self.get_child(id_)
Globals.default__class_init__(Jamming)
# EOF
iva-0.7.4/Kalender.py 0000644 0000000 0000000 00000041114 10345616031 0015445 0 ustar viewcvs viewcvs 0000001 0000000 # -*- coding: utf-8
# $Id$
#
# Copyright 2001, 2002 by IVA Team and contributors
#
# This file is part of IVA.
#
# IVA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# IVA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with IVA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
__version__ = "$Revision$"[11:-2]
import AccessControl
import OFS, Globals
from OFS import SimpleItem
import types
import time
from TraversableWrapper import Traversable
from Globals import Persistent
from AccessControl import ClassSecurityInfo, getSecurityManager, Unauthorized
from Cruft import Cruft
from common import add_dtml, translate, perm_edit, perm_view
from Products.ZCatalog.CatalogPathAwareness import CatalogAware
from input_checks import strip_tags
from DateTime import DateTime
import calendar
calendar.setfirstweekday(0)
class KalendriSyndmus(
OFS.SimpleItem.Item,
Persistent,
AccessControl.Role.RoleManager,
Traversable,
Cruft,
CatalogAware
):
""" Teade kalendris """
meta_type = 'Event'
security = ClassSecurityInfo()
security.declareObjectPublic()
def __init__(self, nimi, pikk='', algus=-1, lopp=-1, viide="", siseviide="", olek=0,blokerid=[]):
"Alustus"
if algus == -1:
algus = time.time()
if lopp == -1:
lopp = time.time()
self.nimi=nimi
self.pikk=pikk
self.algus=algus
self.lopp=lopp
self.viide=viide
self.siseviide=siseviide
self.blokerid = []
self.olek=olek #0-ajatu sßndmus 1-lþpetamata tÜÜ 2-lþpetatud tÜÜ
self.icon_tag=None
self.default_catalog = 'catalog_events'
def manage_afterAdd(self, item, container):
""" index event """
self.index_object()
def manage_beforeDelete(self, item, container):
""" unindex catalog """
self.unindex_object()
security.declareProtected(perm_view,'getName')
def getName(self):
""" Event name """
return self.nimi
security.declareProtected(perm_view,'getIconTag')
def getIconTag(self):
if not hasattr(self,'icon_tag'):
self.icon_tag = None
if self.icon_tag is not None:
result = ""
else:
result = ""
return result
security.declareProtected(perm_view,'setIconTag')
def setIconTag(self,path):
self.icon_tag = path
self.icon_tag = self.icon_tag
return self.icon_tag
def getContent(self):
""" Event content """
return self.pikk
security.declarePublic('kysiAlgus')
def kysiAlgus(self):
"Syndmuse algusaeg"
return self.algus
def kysiLopp(self):
"Syndmuse lĂľppaeg"
return self.lopp
def get_start_time(self):
""" Event start time in DateTime format """
return DateTime(self.kysiAlgus()).ISO()
def get_end_time(self):
""" Event end time in DateTime format """
return DateTime(self.kysiLopp()).ISO()
def aegTekstina(self, REQUEST, aeg, timestamp=''):
"tekstiesitus"
if aeg==-1: return "*"
if not timestamp:
timestamp = translate(self,'timestamp_format',default="%H:%M %Y-%m-%d",target=self.giveLanguage(REQUEST))
else:
timestamp = REQUEST[timestamp]
return time.strftime(timestamp, time.localtime(aeg))
def tekstAjana(self, REQUEST, ajatekst):
"Tagasi ajaformaati"
return mktime(time.strptime(translate(self,'timestamp_format',default="%H:%M %Y-%m-%d",target=self.giveLanguage(REQUEST))), ajatekst)
def kysiViide(self):
"Välisviide"
return self.viide
def kysiSiseviide(self):
"Siseviide"
return self.siseviide
def kysiSiseviiteURL(self):
"Siseviide"
return self.fle_root().absolute_url()+self.siseviide
def siseviiteNimi(self):
"Nagu funktsiooni nime Ăźtleb"
import re
if self.siseviide=="": return ""
m=self.siseviide.split("/")
o=self.fle_root()
try:
for x in m:
if len(x)>0:
o=getattr(o, re.sub('%20',' ',x))
except:
return ""
return o.get_name()
def kysiSiseviiteLink(self):
"Koos"
return ""+self.siseviiteNimi()+""
def kysiOlek(self):
"SĂźndmuse olek"
if hasattr(self, 'olek'): return self.olek
return 0
def getPersonalStatus(self,REQUEST):
""" """
if hasattr(self, 'status_'+str(REQUEST.AUTHENTICATED_USER)):
return getattr(self,'status_'+str(REQUEST.AUTHENTICATED_USER))
else:
return 0
return 0
def olekuVarv(self, REQUEST):
"Olekut illustreeriv lahter"
if self.getPersonalStatus(REQUEST):
stat = self.getPersonalStatus(REQUEST)
else:
stat = self.kysiOlek()
if stat==0:
return "\"black\""
if stat==1: #pooleli
if time.time()>self.lopp: #Hilinenud
return "\"red\""
else: return "\"blue\""
return "\"green\""
def asukohaNimi(self):
"Kursuse nimi, kus sĂźndmus asub, muu sĂźndmuse puhul None"
aadress=self.absolute_url()
algus=aadress.find('courses')
if algus>=0:
nr=aadress[algus:].split("/")[1]
t=getattr(self.fle_root().courses, nr).get_name()
m=aadress[algus:].split("/")
for i in range(len(m)):
if m[i]=="subgroups" and i+1