1 # -*- coding: utf-8 -*-
4 ## This file is part of Indico.
5 ## Copyright (C) 2002 - 2012 European Organization for Nuclear Research (CERN).
7 ## Indico is free software; you can redistribute it and/or
8 ## modify it under the terms of the GNU General Public License as
9 ## published by the FreeSoftware Foundation; either version 3 of the
10 ## License, or (at your option) any later version.
12 ## Indico is distributed in the hope that it will be useful, but
13 ## WITHOUT ANY WARRANTY; without even the implied warranty of
14 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 ## General Public License for more details.
17 ## You should have received a copy of the GNU General Public License
18 ## along with Indico;if not, see <http://www.gnu.org/licenses/>.
21 from MaKaC
.plugins
import PluginsHolder
, Observable
22 from MaKaC
.common
.utils
import formatDateTime
23 from MaKaC
.fossils
.subcontribution
import ISubContribParticipationFossil
,\
24 ISubContribParticipationFullFossil
, ISubContributionFossil
, ISubContributionWithSpeakersFossil
25 from MaKaC
.fossils
.contribution
import IContributionParticipationFossil
,\
26 IContributionFossil
, IContributionWithSpeakersFossil
, IContributionParticipationMinimalFossil
, \
27 IContributionWithSubContribsFossil
,\
28 IContributionParticipationTTDisplayFossil
, \
29 IContributionParticipationTTMgmtFossil
30 from MaKaC
.fossils
.conference
import IConferenceMinimalFossil
, \
31 IConferenceEventInfoFossil
, IConferenceFossil
,\
32 ISessionFossil
, ISessionSlotFossil
, IMaterialMinimalFossil
,\
33 IMaterialFossil
, IConferenceParticipationFossil
,\
34 IResourceMinimalFossil
, ILinkMinimalFossil
, ILocalFileMinimalFossil
,\
35 IResourceFossil
, ILinkFossil
, ILocalFileFossil
,\
36 ILocalFileExtendedFossil
, IConferenceParticipationMinimalFossil
,\
37 ICategoryFossil
, ILocalFileAbstractMaterialFossil
38 from MaKaC
.common
.fossilize
import fossilizes
, Fossilizable
39 from MaKaC
.common
.url
import ShortURLMapper
40 from MaKaC
.contributionReviewing
import Review
41 from MaKaC
.rb_location
import CrossLocationQueries
, CrossLocationDB
42 from indico
.util
.i18n
import L_
49 from datetime
import datetime
, timedelta
, time
51 from MaKaC
.contributionReviewing
import ReviewManager
52 from MaKaC
.paperReviewing
import ConferencePaperReview
as ConferencePaperReview
53 from MaKaC
.abstractReviewing
import ConferenceAbstractReview
as ConferenceAbstractReview
55 from pytz
import timezone
56 from pytz
import all_timezones
58 from persistent
import Persistent
59 from BTrees
.OOBTree
import OOBTree
, OOTreeSet
, OOSet
60 from BTrees
.OIBTree
import OIBTree
,OISet
,union
62 import MaKaC
.common
.indexes
as indexes
63 from MaKaC
.common
.timezoneUtils
import nowutc
, maxDatetime
64 import MaKaC
.fileRepository
as fileRepository
65 from MaKaC
.schedule
import ConferenceSchedule
, SessionSchedule
,SlotSchedule
,\
66 PosterSlotSchedule
, SlotSchTypeFactory
, ContribSchEntry
, \
67 LinkedTimeSchEntry
, BreakTimeSchEntry
68 import MaKaC
.review
as review
69 from MaKaC
.common
import Config
, DBMgr
, utils
70 from MaKaC
.common
.Counter
import Counter
71 from MaKaC
.common
.ObjectHolders
import ObjectHolder
72 from MaKaC
.common
.Locators
import Locator
73 from MaKaC
.accessControl
import AccessController
, AdminList
74 from MaKaC
.errors
import MaKaCError
, TimingError
, ParentTimingError
, EntryTimingError
, NoReportError
75 from MaKaC
import registration
,epayment
76 from MaKaC
.evaluation
import Evaluation
77 from MaKaC
.trashCan
import TrashCanManager
78 from MaKaC
.user
import AvatarHolder
79 from MaKaC
.common
import pendingQueues
80 from MaKaC
.common
.info
import HelperMaKaCInfo
81 from MaKaC
.participant
import Participation
82 from MaKaC
.common
.log
import LogHandler
83 import MaKaC
.task
as task
84 import MaKaC
.common
.info
as info
85 from MaKaC
.badge
import BadgeTemplateManager
86 from MaKaC
.poster
import PosterTemplateManager
87 from MaKaC
.common
.cache
import CategoryCache
, EventCache
88 from MaKaC
.common
import mail
89 from MaKaC
.common
.utils
import getHierarchicalId
90 from MaKaC
.i18n
import _
91 from MaKaC
.common
.PickleJar
import Updates
92 from MaKaC
.common
.PickleJar
import if_else
94 from MaKaC
.webinterface
import urlHandlers
96 from MaKaC
.common
.logger
import Logger
97 from MaKaC
.common
.contextManager
import ContextManager
100 from indico
.modules
.scheduler
import Client
, tasks
101 from indico
.util
.date_time
import utc_timestamp
102 from indico
.core
.index
import IIndexableByStartDateTime
, IUniqueIdProvider
, Catalog
103 from MaKaC
.webinterface
.common
.tools
import escape_html
106 class CoreObject(Persistent
):
108 CoreObjects are Persistent objects that are employed by Indico's core
111 zope
.interface
.implements(IUniqueIdProvider
,
112 IIndexableByStartDateTime
)
114 def setModificationDate(self
, date
= None):
116 Method called to notify the current object has been modified.
120 self
._modificationDS
= date
122 def __conform__(self
, proto
):
124 if proto
== IIndexableByStartDateTime
:
125 return utc_timestamp(self
.getStartDate())
132 Inherited by objects that imply a physical location:
140 def getLocationParent(self
):
142 Returns the object the location info should be inherited from
145 raise Exception("Unimplemented method")
147 def getLocation(self
):
148 if self
.getOwnLocation():
149 return self
.getOwnLocation()
150 return self
.getInheritedLocation()
152 def getOwnLocation(self
):
153 if len(self
.places
) > 0:
154 return self
.places
[0]
157 def getInheritedLocation(self
):
158 return self
.getLocationParent().getLocation()
160 def getOwnRoom(self
):
161 if len(self
.rooms
) > 0:
166 if self
.getOwnRoom():
167 return self
.getOwnRoom()
168 return self
.getInheritedRoom()
170 def getInheritedRoom(self
):
171 return self
.getLocationParent().getRoom()
173 def setLocation(self
, newLocation
):
174 oldLocation
= self
.getOwnLocation()
175 if newLocation
== None:
176 if len(self
.places
) > 0:
178 elif len(self
.places
) > 0:
179 self
.places
[0] = newLocation
181 self
.places
.append( newLocation
)
182 self
.notifyModification()
184 def setRoom(self
, newRoom
):
185 oldRoom
= self
.getOwnRoom()
187 if len(self
.rooms
) > 0:
189 elif len(self
.rooms
) > 0:
190 self
.rooms
[0] = newRoom
192 self
.rooms
.append( newRoom
)
193 self
.notifyModification()
196 class CommonObjectBase(CoreObject
, Observable
, Fossilizable
):
198 This class is for holding commonly used methods that are used by several classes.
199 It is inherited by the following classes:
209 def getRecursiveManagerList(self
):
212 # Get the AccessProtectionLevel for this
213 apl
= self
.getAccessProtectionLevel()
218 for av
in self
.getManagerList():
220 for av
in self
.getOwner().getRecursiveManagerList():
223 for av
in self
.getManagerList():
227 for av
in self
.getOwner().getRecursiveManagerList():
232 def getRecursiveAllowedToAccessList(self
, onlyManagers
=False):
233 """Returns a set of Avatar resp. CERNGroup objects for those people resp.
234 e-groups allowed to access this object as well as all parent objects.
237 # Initialize set of avatars/groups: this will hold those
238 # people/groups explicitly
239 # allowed to access this object
242 # Get the AccessProtectionLevel for this
243 apl
= self
.getAccessProtectionLevel()
245 # If this object is "absolutely public", then return an empty set
249 # If this object is protected "all by itself", then get the list of
250 # people/groups allowed to access it, plus managers of owner(s)
252 al
= self
.getAllowedToAccessList() + self
.getManagerList() + \
253 self
.getOwner().getRecursiveManagerList()
258 # If access settings are inherited (and PRIVATE) from its owners, look at those.
259 elif apl
== 0 and self
.isProtected():
260 # If event is protected, then get list of people/groups allowed
261 # to access, and add that to the set of avatars.
262 al
= self
.getAllowedToAccessList() + self
.getManagerList()
267 # Add list of avatars/groups allowed to access parents objects.
268 owner
= self
.getOwner()
269 if owner
is not None:
270 owner_al
= owner
.getRecursiveAllowedToAccessList(onlyManagers
=True)
271 if owner_al
is not None:
275 # return set containing whatever avatars/groups we may have collected
279 class CategoryManager( ObjectHolder
):
280 idxName
= "categories"
281 counterName
= "CATEGORY"
283 def add(self
, category
):
284 ObjectHolder
.add(self
, category
)
285 # Add category to the name index
286 nameIdx
= indexes
.IndexesHolder().getIndex('categoryName')
287 nameIdx
.index(category
.getId(), category
.getTitle().decode('utf-8'))
289 def remove(self
, category
):
290 ObjectHolder
.remove(self
, category
)
291 # remove category from the name index
292 nameIdx
= indexes
.IndexesHolder().getIndex('categoryName')
293 nameIdx
.unindex(category
.getId())
294 Catalog
.getIdx('categ_conf_sd').remove_category(category
.getId())
298 returns a new id for the category
299 the id must not already exist in the collection
301 id = ObjectHolder
._newId
( self
)
302 while self
.hasKey(id):
303 id = ObjectHolder
._newId
( self
)
307 root
= DBMgr
.getInstance().getDBConnection().root()
308 if not root
.has_key("rootCategory"):
312 root
["rootCategory"] = r
313 return root
["rootCategory"]
315 def getDefaultConference( self
):
316 dconf
= HelperMaKaCInfo
.getMaKaCInfoInstance().getDefaultConference()
318 return HelperMaKaCInfo
.getMaKaCInfoInstance().setDefaultConference(DefaultConference())
324 class Category(CommonObjectBase
):
326 fossilizes(ICategoryFossil
)
328 def __init__( self
):
332 self
.description
= ""
333 self
.subcategories
= {}
335 self
.conferences
= OOTreeSet()
336 self
._numConferences
= 0
338 self
._defaultStyle
= { "simple_event":"","meeting":"" }
340 self
.__ac
= AccessController(self
)
341 self
.__confCreationRestricted
= 1
342 self
.__confCreators
= []
343 self
._visibility
= 999
344 self
._statistics
= {"events":None,"contributions":None,"resources":None,\
348 #self._materials = {}
350 self
._tasksAllowed
= False
352 self
._taskIdGenerator
= 0
353 self
._tasksPublic
= True
354 self
._tasksCommentPublic
= True
355 self
._tasksManagers
= []
356 self
._tasksCommentators
= []
357 self
._taskAccessList
= []
359 self
.__materialGenerator
= Counter()
360 self
._notifyCreationList
= ""
363 return "<Category %s@%s>" % (self
.getId(), hex(id(self
)))
365 def getAccessController(self
):
368 def updateFullyPublic( self
):
371 def getNotifyCreationList( self
):
372 """ self._notifyCreationList is a string containing the list of
373 email addresses to send an email to when a new event is created"""
375 return self
._notifyCreationList
377 self
._notifyCreationList
= ""
378 return self
._notifyCreationList
380 def setNotifyCreationList( self
, value
):
381 self
._notifyCreationList
= value
383 def getUniqueId( self
):
384 return "cat%s" % self
.getId()
386 def setPaper( self
, newPaper
):
387 if self
.getPaper() != None:
388 raise MaKaCError( _("The paper for this conference has already been set"), _("Conference"))
390 self
.paper
.setOwner( self
)
391 self
.notifyModification()
393 def cleanCache( self
):
394 """ delete cache files of this category and its fathers
395 usually used when an object in the category has changed """
396 minfo
= info
.HelperMaKaCInfo
.getMaKaCInfoInstance()
397 if minfo
.isCacheActive():
398 for id in self
.getCategoryPath():
399 cache
= CategoryCache({"categId":id})
402 def clearCache( self
):
403 """ delete cache file of this category. usually used for
405 cache
= CategoryCache({"categId":self
.getId()})
408 def clearConferenceCaches( self
):
409 """ delete cache files of all conferences in the category
410 usually used for admin purposes """
411 for conf
in self
.getConferenceList():
414 def removePaper( self
):
415 if self
.paper
is None:
418 self
.paper
.setOwner(None)
420 self
.notifyModification()
422 def recoverPaper(self
, p
):
426 def getPaper( self
):
430 except AttributeError:
434 def setSlides( self
, newSlides
):
435 if self
.getSlides() != None:
436 raise MaKaCError( _("The slides for this conference have already been set"), _("Conference"))
437 self
.slides
=newSlides
438 self
.slides
.setOwner( self
)
439 self
.notifyModification()
441 def removeSlides( self
):
442 if self
.slides
is None:
445 self
.slides
.setOwner( None )
447 self
.notifyModification()
449 def recoverSlides(self
, s
):
453 def getSlides( self
):
457 except AttributeError:
461 def setVideo( self
, newVideo
):
462 if self
.getVideo() != None:
463 raise MaKaCError( _("The video for this conference has already been set"), _("Conference"))
465 self
.video
.setOwner( self
)
466 self
.notifyModification()
468 def removeVideo( self
):
469 if self
.getVideo() is None:
472 self
.video
.setOwner(None)
474 self
.notifyModification()
476 def recoverVideo(self
, v
):
480 def getVideo( self
):
484 except AttributeError:
488 def setPoster( self
, newPoster
):
489 if self
.getPoster() != None:
490 raise MaKaCError( _("the poster for this conference has already been set"), _("Conference"))
491 self
.poster
=newPoster
492 self
.poster
.setOwner( self
)
493 self
.notifyModification()
495 def removePoster( self
):
496 if self
.getPoster() is None:
499 self
.poster
.setOwner(None)
501 self
.notifyModification()
503 def recoverPoster(self
, p
):
507 def getPoster( self
):
511 except AttributeError:
515 def setMinutes( self
, newMinutes
):
516 if self
.getMinutes() != None:
517 raise MaKaCError( _("The Minutes for this conference has already been set"))
518 self
.minutes
=newMinutes
519 self
.minutes
.setOwner( self
)
520 self
.notifyModification()
522 def createMinutes( self
):
523 if self
.getMinutes() != None:
524 raise MaKaCError( _("The minutes for this conference have already been created"), _("Conference"))
525 self
.minutes
= Minutes()
526 self
.minutes
.setOwner( self
)
527 self
.notifyModification()
530 def removeMinutes( self
):
531 if self
.getMinutes() is None:
533 self
.minutes
.delete()
534 self
.minutes
.setOwner( None )
536 self
.notifyModification()
538 def recoverMinutes(self
, min):
539 self
.removeMinutes() # To ensure that the current minutes are put in
542 self
.minutes
.setOwner( self
)
544 self
.notifyModification()
547 def getMinutes( self
):
552 except AttributeError, e
:
556 def addMaterial( self
, newMat
):
558 newMat
.setId( str(self
.__materialGenerator
.newCount()) )
560 self
.__materialGenerator
= Counter()
561 newMat
.setId(self
.__materialGenerator
.newCount() )
562 newMat
.setOwner( self
)
563 self
.materials
[ newMat
.getId() ] = newMat
564 self
.notifyModification()
566 def removeMaterial( self
, mat
):
567 if mat
.getId() in self
.materials
.keys():
568 self
.materials
[mat
.getId()].setOwner(None)
569 del self
.materials
[ mat
.getId() ]
571 self
.notifyModification()
572 return "done: %s"%mat
.getId()
573 elif mat
.getId().lower() == 'minutes':
575 return "done: %s"%mat
.getId()
576 elif mat
.getId().lower() == 'paper':
578 return "done: %s"%mat
.getId()
579 elif mat
.getId().lower() == 'slides':
581 return "done: %s"%mat
.getId()
582 elif mat
.getId().lower() == 'video':
584 return "done: %s"%mat
.getId()
585 elif mat
.getId().lower() == 'poster':
587 return "done: %s"%mat
.getId()
588 return "not done: %s"%mat
.getId()
590 def recoverMaterial(self
, recMat
):
591 # Id must already be set in recMat.
592 recMat
.setOwner( self
)
593 self
.materials
[ recMat
.getId() ] = recMat
595 self
.notifyModification()
597 def getMaterialRegistry(self
):
599 Return the correct material registry for this type
601 from MaKaC
.webinterface
.materialFactories
import CategoryMFRegistry
602 return CategoryMFRegistry
604 def getMaterialById( self
, matId
):
605 if matId
.lower() == 'paper':
606 return self
.getPaper()
607 elif matId
.lower() == 'slides':
608 return self
.getSlides()
609 elif matId
.lower() == 'video':
610 return self
.getVideo()
611 elif matId
.lower() == 'poster':
612 return self
.getPoster()
613 elif matId
.lower() == 'minutes':
614 return self
.getMinutes()
615 elif self
.materials
.has_key(matId
):
616 return self
.materials
[ matId
]
619 def getMaterialList( self
):
621 return self
.materials
.values()
624 return self
.materials
.values()
626 def getAllMaterialList( self
):
627 l
= self
.getMaterialList()
629 l
.append( self
.getPaper() )
631 l
.append( self
.getSlides() )
633 l
.append( self
.getVideo() )
635 l
.append( self
.getPoster() )
636 if self
.getMinutes():
637 l
.append( self
.getMinutes() )
640 def getTaskList(self
):
642 return self
._tasks
.values()
645 return self
._tasks
.values()
657 def getTask(self
, taskId
):
658 return self
.getTasks().get(taskId
,None)
660 def _getTasksAllowed(self
):
662 return self
._tasksAllowed
664 self
._tasksAllowed
= False
665 return self
._tasksAllowed
667 def tasksAllowed(self
):
668 if self
.hasSubcategories():
670 return self
._getTasksAllowed
()
672 def setTasksAllowed(self
):
673 if self
.hasSubcategories() :
675 self
._getTasksAllowed
()
676 self
._tasksAllowed
= True
677 self
.notifyModification()
680 def setTasksForbidden(self
):
681 if len(self
.getTaskList()) > 0 :
683 self
._getTasksAllowed
()
684 self
._tasksAllowed
= False
685 self
.notifyModification()
688 def _getNewTaskId(self
):
690 if self
._taskIdGenerator
:
693 self
._taskIdGenerator
= 0
694 self
._taskIdGenerator
= self
._taskIdGenerator
+ 1
695 return self
._taskIdGenerator
697 def newTask(self
, user
):
700 newTask
= task
.Task(self
, self
._getNewTaskId
(), user
)
701 self
.getTasks()["%s"%newTask
.getId()] = newTask
702 self
.notifyModification()
705 def tasksPublic(self
):
707 return self
._tasksPublic
709 self
._tasksPublic
= True
710 return self
._tasksPublic
712 def setTasksPublic(self
):
714 self
._tasksPublic
= True
716 def setTasksPrivate(self
):
718 self
._tasksPublic
= False
720 def tasksCommentPublic(self
):
722 return self
._tasksCommentPublic
724 self
._tasksCommentPublic
= True
725 return self
._tasksCommentPublic
727 def setTasksCommentPublic(self
):
728 self
.tasksCommentPublic()
729 self
._tasksCommentPublic
= True
731 def setTasksCommentPrivate(self
):
732 self
.tasksCommentPublic()
733 self
._tasksCommentPublic
= False
735 def getTasksManagerList(self
):
737 return self
._tasksManagers
739 self
._tasksManagers
= []
741 return self
._tasksManagers
743 def getTasksManager(self
, index
):
744 length
= len(self
.getTasksManagerList())
745 if index
< 0 or index
>= length
:
747 return self
._tasksManagers
[index
]
749 def addTasksManager(self
,user
):
752 self
.getTasksManagerList().append(user
)
756 def removeTasksManager(self
, index
):
757 length
= len(self
.getTasksManagerList())
758 if index
< 0 or index
>= length
:
760 del self
.getTasksManagerList()[index
]
764 def getTasksCommentatorList(self
):
766 return self
._tasksCommentators
768 self
._tasksCommentators
= []
770 return self
._tasksCommentators
772 def getTasksCommentator(self
, index
):
773 length
= len(self
.getTasksCommentatorList())
774 if index
< 0 or index
>= length
:
776 return self
._tasksCommentators
[index
]
778 def addTasksCommentator(self
,user
):
781 self
.getTasksCommentatorList().append(user
)
785 def removeTasksCommentator(self
, index
):
786 length
= len(self
.getTasksCommentatorList())
787 if index
< 0 or index
>= length
:
789 del self
._tasksCommentators
[index
]
794 def getTasksAccessList(self
):
796 return self
._tasksAccessList
798 self
._tasksAccessList
= []
800 return self
._tasksAccessList
802 def getTasksAccessPerson(self
, index
):
803 length
= len(self
.getTasksAccessList())
804 if index
< 0 or index
>= length
:
806 return self
._tasksAccessList
[index
]
808 def addTasksAccessPerson(self
,user
):
811 self
.getTasksAccessList().append(user
)
815 def removeTasksAccessPerson(self
, index
):
816 length
= len(self
.getTasksAccessList())
817 if index
< 0 or index
>= length
:
819 del self
.getTasksAccessList()[index
]
823 def hasSubcategories(self
):
824 return len(self
.subcategories
.values()) > 0
826 def getVisibility ( self
):
828 Returns category visibility, considering that it can be
829 restricted by parent categories
831 owner
= self
.getOwner()
832 visibility
= int(self
._visibility
)
834 # visibility can be restricted by parent categories
836 return max(0, min(visibility
, owner
.getVisibility() + 1))
840 def setVisibility( self
, visibility
=999 ):
841 self
._visibility
= int(visibility
)
844 def _reindex( self
):
845 catIdx
= indexes
.IndexesHolder().getIndex('category')
846 catIdx
.reindexCateg(self
)
847 catDateIdx
= indexes
.IndexesHolder().getIndex('categoryDate')
848 catDateIdx
.reindexCateg(self
)
849 catDateAllIdx
= indexes
.IndexesHolder().getIndex('categoryDateAll')
850 catDateAllIdx
.reindexCateg(self
)
854 return self
.owner
== None
856 def getDefaultStyle( self
, type ):
858 return self
._defaultStyle
[type]
862 def setDefaultStyle( self
, type, style
, subcatsStyle
=False ):
864 self
._defaultStyle
[type] = style
866 self
._defaultStyle
= { "simple_event":"","meeting":"" }
867 self
._defaultStyle
[type] = style
868 self
.notifyModification()
869 #raise str(subcatsStyle)
872 categ
=self
.getSubCategoryList()
875 cat
.setDefaultStyle(type, style
, subcatsStyle
)
877 ##################################
878 # Fermi timezone awareness #
879 ##################################
880 def getTimezone(self
):
882 if self
._timezone
not in all_timezones
:
883 self
.setTimezone('UTC')
884 return self
._timezone
886 self
.setTimezone('UTC')
889 def setTimezone(self
,tz
):
893 def changeConfTimezones(self
, tz
):
894 for conference
in self
.getConferenceList():
895 conference
.moveToTimezone(tz
)
897 ##################################
898 # Fermi timezone awareness(end) #
899 ##################################
901 def getOrder( self
):
908 def setOrder( self
, order
):
914 def setId( self
, newId
):
915 self
.id = str( newId
.strip() )
917 def getLocator( self
):
918 """Gives back (Locator) a globaly unique identification encapsulated
919 in a Locator object for the category instance """
921 d
["categId"] = self
.getId()
924 def getCategory(self
):
927 def getOwner( self
):
930 def setOwner( self
, newOwner
):
931 if self
.getOwner() != None and newOwner
!= None and self
.getOwner() != newOwner
:
932 self
.move( newOwner
)
934 self
.owner
= newOwner
936 def getCategoryPath(self
):
938 return [self
.getId()]
940 l
= self
.getOwner().getCategoryPath()
941 l
.append(self
.getId())
944 def getCategoryPathTitles(self
):
949 breadcrumbs
.insert(0, cat
.getTitle())
953 def delete( self
, deleteConferences
=0 ):
954 """removes completely a category (and all its sub-items) from the
957 oldOwner
= self
.getOwner()
960 raise MaKaCError( _("Root category cannot be deleted"), _("Category"))
961 if not deleteConferences
:
962 if self
.getNumConferences()>0:
963 raise MaKaCError( _("This category still contains some conferences, please remove them first"), _("Category"))
965 for subcateg
in self
.getSubCategoryList():
966 subcateg
.delete( deleteConferences
)
967 for conference
in self
.getConferenceList():
968 self
.removeConference( conference
, delete
= True )
969 self
.getOwner()._removeSubCategory
( self
)
970 CategoryManager().remove( self
)
971 TrashCanManager().add(self
)
973 self
._notify
('deleted', oldOwner
)
977 def move( self
, newOwner
):
978 oldOwner
= self
.getOwner()
979 catDateIdx
= indexes
.IndexesHolder().getIndex('categoryDate')
980 catDateAllIdx
= indexes
.IndexesHolder().getIndex('categoryDateAll')
982 catDateIdx
.unindexCateg(self
)
983 catDateAllIdx
.unindexCateg(self
)
985 self
.getOwner()._removeSubCategory
( self
)
986 newOwner
._addSubCategory
( self
)
988 catDateIdx
.indexCateg(self
)
989 catDateAllIdx
.indexCateg(self
)
991 self
._notify
('moved', oldOwner
, newOwner
)
996 def setName( self
, newName
):
998 self
.name
= newName
.strip()
1000 # Reindex when name changes
1001 nameIdx
= indexes
.IndexesHolder().getIndex('categoryName')
1002 nameIdx
.unindex(self
.getId())
1003 nameIdx
.index(self
.getId(), self
.getTitle().decode('utf-8'))
1005 self
._notify
('categoryTitleChanged', oldName
, newName
)
1009 def getDescription( self
):
1010 return self
.description
1012 def setDescription( self
, newDesc
):
1013 self
.description
= newDesc
.strip()
1016 def moveConference(self
, conf
, toCateg
):
1018 Moves a conference from this category to another one
1020 self
.removeConference( conf
)
1021 toCateg
._addConference
( conf
)
1022 conf
._notify
('moved', self
, toCateg
)
1024 def _addSubCategory( self
, newSc
):
1025 #categories can only contain either conferences either other categories
1026 # but can never contain both. For the moment an exception is raised
1027 # but this could be replaced by the following policy: if a
1028 # sub-category is to be added to a category already containing
1029 # conferences then the conferes are moved into the new sub-category
1030 # and it is added to target category.
1031 #first, check that the category is registered if not raise an exception
1032 if len(self
.conferences
)>0:
1033 for conf
in self
.getConferenceList():
1034 self
.moveConference(conf
, newSc
)
1036 if len(self
.conferences
)>0:
1037 raise MaKaCError( _("Cannot add subcategory: the current category already contains events"), _("Category"))
1038 newSc
.setOwner( self
)
1039 self
.subcategories
[ newSc
.getId() ] = newSc
1040 self
._incNumConfs
(newSc
.getNumConferences())
1043 def _removeSubCategory( self
, sc
):
1044 """if the given subcategory belongs to the current category it removes
1045 it from the subcategories list (don't use this method, use delete
1048 if sc
in self
.getSubCategoryList():
1049 self
._decNumConfs
(sc
.getNumConferences())
1050 del self
.subcategories
[ sc
.getId() ]
1054 def newSubCategory(self
, protection
):
1055 cm
= CategoryManager()
1059 # set the protection
1060 sc
.setProtection(protection
)
1062 Catalog
.getIdx('categ_conf_sd').add_category(sc
.getId())
1063 sc
._notify
('created', self
)
1065 self
._addSubCategory
( sc
)
1070 def _incNumConfs(self
, num
=1):
1071 """Increases the number of conferences for the current category in a given number.
1072 WARNING: Only Categories must use this method!!!"""
1073 self
._numConferences
= self
.getNumConferences()
1074 self
._numConferences
+=num
1075 if self
.getOwner() is not None:
1076 self
.getOwner()._incNumConfs
(num
)
1078 def _decNumConfs(self
, num
=1):
1079 """Decreases the number of conferences for the current category in a given number.
1080 WARNING: Only Categories must use this method!!!"""
1081 self
._numConferences
= self
.getNumConferences()
1082 self
._numConferences
-=num
1083 if self
.getOwner() is not None:
1084 self
.getOwner()._decNumConfs
(num
)
1086 def _addConference( self
, newConf
):
1087 if len(self
.subcategories
)>0:
1088 raise MaKaCError( _("Cannot add event: the current category already contains some sub-categories"), _("Category"))
1089 if newConf
.getId() == "":
1090 raise MaKaCError( _("Cannot add to a category an event which is not registered"), _("Category"))
1091 self
.conferences
.insert(newConf
)
1092 newConf
.addOwner(self
)
1093 self
._incNumConfs
(1)
1094 self
.indexConf(newConf
)
1097 def getAccessKey(self
):
1100 def getModifKey(self
):
1103 def indexConf( self
, conf
):
1104 # Specific for category changes, calls Conference.indexConf()
1105 # (date-related indexes)
1106 catIdx
= indexes
.IndexesHolder().getIndex('category')
1107 catIdx
.indexConf(conf
)
1110 def unindexConf( self
, conf
):
1111 catIdx
= indexes
.IndexesHolder().getIndex('category')
1112 catIdx
.unindexConf(conf
)
1115 def newConference( self
, creator
, id="", creationDate
=None, modificationDate
=None ):
1116 conf
= Conference( creator
, id, creationDate
, modificationDate
)
1117 ConferenceHolder().add( conf
)
1118 self
._addConference
( conf
)
1120 conf
._notify
('created', self
)
1124 def removeConference( self
, conf
, notify
=True, delete
= False ):
1125 if not (conf
in self
.conferences
):
1128 self
.unindexConf( conf
)
1130 self
.conferences
.remove(conf
)
1133 conf
.removeOwner( self
, notify
)
1134 self
._decNumConfs
(1)
1137 def getSubCategoryList( self
):
1138 subcategs
= self
.subcategories
.values()
1140 for categ
in subcategs
:
1141 cl
.append("%04s%s-%s" % (categ
.getOrder(),categ
.getName().replace("-",""),categ
.getId()))
1145 id = c
.split("-")[1]
1146 res
.append(self
.subcategories
[id])
1149 def iteritems(self
, *args
):
1150 return self
.conferences
.iteritems(*args
)
1152 def itervalues(self
, *args
):
1153 return self
.conferences
.itervalues(*args
)
1155 def getConferenceList( self
, sortType
=1 ):
1156 """returns the list of conferences included in the current category.
1157 Thanks to the used structure the list is sorted by date.
1158 We can choose other sorting types:
1160 sortType=1--> By date
1161 sortType=2--> Alphabetically
1162 sortType=3--> Alphabetically - Reversed
1165 res
= sorted(self
.conferences
, cmp=Conference
._cmpByDate
)
1168 res
.sort(Conference
._cmpTitle
)
1170 res
.sort(Conference
._cmpTitle
)
1174 def iterConferences( self
):
1175 """returns the iterator for conferences.
1177 return self
.conferences
1179 def iterAllConferences( self
):
1180 """returns the iterator for conferences in all subcategories.
1182 for conf
in self
.conferences
:
1185 for subcateg
in self
.subcategories
.itervalues():
1186 for conf
in subcateg
.iterAllConferences():
1189 def getAllConferenceList( self
):
1190 """returns the list of all conferences included in the current category
1191 and in all its subcategories"""
1192 res
= self
.getConferenceList()
1193 subcategs
= self
.getSubCategoryList()
1195 for subcateg
in subcategs
:
1196 res
.extend(subcateg
.getAllConferenceList())
1199 def getRelativeEvent(self
, which
, conf
=None):
1200 index
= Catalog
.getIdx('categ_conf_sd').getCategory(self
.getId())
1201 if which
== 'first':
1202 return list(index
[index
.minKey()])[0]
1203 elif which
== 'last':
1204 return list(index
[index
.maxKey()])[-1]
1205 elif which
in ('next', 'prev'):
1206 categIter
= index
.itervalues()
1213 nextEvt
= next(categIter
, None)
1219 raise AttributeError("'conf' parameter missing")
1221 raise AttributeError("Unknown argument value: '%s'" % which
)
1223 def _setNumConferences(self
):
1224 self
._numConferences
= 0
1225 if self
.conferences
:
1226 self
._incNumConfs
(len(self
.conferences
))
1228 for sc
in self
.getSubCategoryList():
1229 self
._incNumConfs
(sc
.getNumConferences())
1231 def getNumConferences( self
):
1232 """returns the total number of conferences contained in the current
1233 category and all its sub-categories (if any)"""
1234 #this new approach will speed up considerably the counting of category
1235 # conferences. However, it will give non accurate results for
1236 # conferences within many categories (a conference will be counted
1237 # twice in parent categories).
1238 # Besides this approach will generate much more conflict errors. This
1239 # can be reduced by simply isolating the counter in a separate object.
1241 if self
._numConferences
:
1243 except AttributeError:
1244 self
._setNumConferences
()
1245 return self
._numConferences
1247 def _getRepository( self
):
1248 dbRoot
= DBMgr
.getInstance().getDBConnection().root()
1250 fr
= dbRoot
["local_repositories"]["main"]
1252 fr
= fileRepository
.MaterialLocalRepository()
1253 dbRoot
["local_repositories"] = OOBTree()
1254 dbRoot
["local_repositories"]["main"] = fr
1257 def removeResource( self
, res
):
1260 def setIcon( self
, iconFile
):
1261 iconFile
.setOwner( self
)
1262 iconFile
.setId( "icon" )
1263 iconFile
.archive( self
._getRepository
() )
1264 iconFile
.setProtection( -1 )
1265 if self
.getIcon() != None:
1267 self
._icon
= iconFile
1268 self
.notifyModification()
1270 def getIcon( self
):
1274 except AttributeError, e
:
1278 def getIconURL( self
):
1279 if self
.getIcon() is None:
1281 return self
._icon
.getURL()
1283 def removeIcon(self
):
1284 if self
.getIcon() is None:
1288 self
.notifyModification()
1290 def recoverIcon(self
, icon
):
1292 if self
.getIcon() != None:
1296 self
.notifyModification()
1298 def getManagerList( self
):
1299 return self
.__ac
.getModifierList()
1301 def grantModification( self
, prin
):
1302 self
.__ac
.grantModification( prin
)
1303 if isinstance(prin
, MaKaC
.user
.Avatar
):
1304 prin
.linkTo(self
, "manager")
1307 def revokeModification( self
, prin
):
1308 self
.__ac
.revokeModification( prin
)
1309 if isinstance(prin
, MaKaC
.user
.Avatar
):
1310 prin
.unlinkTo(self
, "manager")
1313 def canModify( self
, aw
):
1314 return self
.canUserModify( aw
.getUser() )
1316 def canUserModify( self
, av
):
1318 if self
.getOwner() != None:
1319 inherited
= self
.getOwner().canUserModify( av
)
1320 return inherited
or self
.__ac
.canModify( av
)
1323 def getAllowedToAccessList( self
):
1324 return self
.__ac
.getAccessList()
1326 def canKeyAccess( self
, aw
):
1327 # Categories don't allow access keys
1330 def canIPAccess( self
, ip
):
1331 if not self
.__ac
.canIPAccess( ip
):
1334 return self
.getOwner().canIPAccess(ip
)
1337 def isProtected( self
):
1338 return self
.__ac
.isProtected()
1340 def getAccessProtectionLevel( self
):
1341 return self
.__ac
.getAccessProtectionLevel()
1343 def isItselfProtected( self
):
1344 return self
.__ac
.isItselfProtected()
1346 def hasAnyProtection( self
):
1347 if self
.__ac
.isProtected() or len(self
.getDomainList())>0:
1349 if self
.getAccessProtectionLevel() == -1: #PUBLIC
1351 if self
.getOwner() is not None:
1352 return self
.getOwner().hasAnyProtection()
1355 def setProtection( self
, private
):
1357 Allows to change the category's access protection
1360 oldProtection
= 1 if self
.isProtected() else -1
1362 self
.__ac
.setProtection( private
)
1363 self
._notify
('protectionChanged', oldProtection
, private
)
1366 def hasProtectedOwner( self
):
1367 return self
.__ac
._getFatherProtection
()
1369 def isAllowedToAccess( self
, av
):
1370 """Says whether an avatar can access a category independently of it is
1371 or not protected or domain filtered
1373 if self
.__ac
.canUserAccess( av
) or self
.canUserModify( av
):
1375 if not self
.isItselfProtected() and self
.getOwner():
1376 return self
.getOwner().isAllowedToAccess( av
)
1378 def canView(self
,aw
):
1379 if self
.canAccess( aw
):
1381 for conf
in self
.getConferenceList():
1382 if conf
.canView( aw
):
1384 for subcateg
in self
.getSubCategoryList():
1385 if subcateg
.canView( aw
):
1389 def canAccess( self
, aw
):
1390 if not self
.hasAnyProtection():
1392 if not self
.isProtected():
1393 #domain checking only triggered if the category is PUBLIC
1394 return self
.canIPAccess( aw
.getIP() ) or \
1395 self
.isAllowedToCreateConference(aw
.getUser()) or \
1396 self
.isAllowedToAccess(aw
.getUser())
1397 return self
.isAllowedToCreateConference(aw
.getUser()) or \
1398 self
.isAllowedToAccess(aw
.getUser())
1400 def grantAccess( self
, prin
):
1401 self
.__ac
.grantAccess( prin
)
1402 if isinstance(prin
, MaKaC
.user
.Avatar
):
1403 prin
.linkTo(self
, "access")
1405 def revokeAccess( self
, prin
):
1406 self
.__ac
.revokeAccess( prin
)
1407 if isinstance(prin
, MaKaC
.user
.Avatar
):
1408 prin
.unlinkTo(self
, "access")
1410 def isConferenceCreationRestricted( self
):
1411 return self
.__confCreationRestricted
1413 def restrictConferenceCreation( self
):
1414 self
.__confCreationRestricted
= 1
1416 def allowConferenceCreation( self
):
1417 self
.__confCreationRestricted
= 0
1419 def grantConferenceCreation( self
, prin
):
1420 if prin
not in self
.__confCreators
:
1421 self
.__confCreators
.append( prin
)
1422 if isinstance(prin
, MaKaC
.user
.Avatar
):
1423 prin
.linkTo(self
, "creator")
1426 def revokeConferenceCreation( self
, prin
):
1427 if prin
in self
.__confCreators
:
1428 self
.__confCreators
.remove( prin
)
1429 if isinstance(prin
, MaKaC
.user
.Avatar
):
1430 prin
.unlinkTo(self
, "creator")
1433 def getConferenceCreatorList( self
):
1434 return self
.__confCreators
1436 def isAllowedToCreateConference( self
, av
):
1438 if self
.canUserModify( av
):
1441 # Avatar is directly in the list
1442 if av
in self
.__confCreators
:
1445 # Otherwise, if it is a member of one of the groups in the list...
1446 for group
in self
.__confCreators
:
1447 if isinstance(group
, MaKaC
.user
.Group
):
1448 if group
.containsUser(av
):
1454 def canCreateConference( self
, av
):
1455 if not self
.isConferenceCreationRestricted():
1457 return self
.isAllowedToCreateConference( av
)
1459 def requireDomain( self
, dom
):
1460 self
.__ac
.requireDomain( dom
)
1461 self
._notify
('accessDomainAdded', dom
)
1463 def freeDomain( self
, dom
):
1464 self
.__ac
.freeDomain( dom
)
1465 self
._notify
('accessDomainRemoved', dom
)
1467 def getDomainList( self
):
1468 return self
.__ac
.getRequiredDomainList()
1470 def getStatistics( self
):
1472 if self
._statistics
:
1474 except AttributeError, e
:
1475 self
._statistics
= {}
1476 return self
._statistics
1478 def notifyModification( self
):
1479 """Method called to notify the current category has been modified.
1481 self
._notify
('infoChanged')
1486 class CustomLocation(Persistent
):
1488 def __init__(self
, **locationData
):
1493 def setValues(self
, data
):
1494 self
.setName(data
.get("name",""))
1495 self
.setAddress(data
.get("address",""))
1496 self
.setRoom(data
.get("room",""))
1498 def getValues(self
):
1500 d
["name"]=self
.getName()
1501 d
["address"]=self
.getAddress()
1502 d
["room"]=self
.getRoom()
1506 newCL
=CustomLocation()
1507 newCL
.setValues(self
.getValues())
1510 def setName(self
, newName
):
1516 def setAddress(self
, newAddress
):
1517 self
.address
= newAddress
1519 def getAddress(self
):
1522 def setRoom(self
, newRoom
):
1529 class CustomRoom(Persistent
):
1531 def __init__( self
):
1534 def setValues(self
, data
):
1535 self
.setName(data
.get("name",""))
1536 self
.setFullName(data
.get("fullName"))
1538 def getValues(self
):
1540 d
["name"]=self
.getName()
1541 d
["fullName"]=self
.getFullName()
1549 newCR
.setValues(self
.getValues())
1552 def setName( self
, newName
):
1553 self
.name
= newName
.strip()
1555 def getName( self
):
1558 def retrieveFullName(self
, location
):
1561 room
= CrossLocationQueries
.getRooms(roomName
=self
.name
, location
=location
)
1562 self
.fullName
= room
.getFullName() if room
else None
1564 def setFullName(self
, newFullName
):
1565 self
.fullName
= newFullName
1567 def getFullName(self
):
1568 if not hasattr(self
, 'fullName'):
1569 self
.fullName
= None
1570 return self
.fullName
1573 class ConferenceParticipation(Persistent
, Fossilizable
, Observable
):
1575 fossilizes(IConferenceParticipationFossil
, IConferenceParticipationMinimalFossil
)
1581 self
._affiliation
=""
1587 def _notifyModification( self
):
1590 def setValues(self
, data
):
1591 self
.setFirstName(data
.get("firstName", ""))
1592 self
.setFamilyName(data
.get("familyName",""))
1593 self
.setAffiliation(data
.get("affilation",""))
1594 self
.setAddress(data
.get("address",""))
1595 self
.setEmail(data
.get("email",""))
1596 self
.setFax(data
.get("fax",""))
1597 self
.setTitle(data
.get("title",""))
1598 self
.setPhone(data
.get("phone",""))
1599 self
._notifyModification
()
1601 def getValues(self
):
1603 data
["firstName"]=self
.getFirstName()
1604 data
["familyName"]=self
.getFamilyName()
1605 data
["affilation"]=self
.getAffiliation()
1606 data
["address"]=self
.getAddress()
1607 data
["email"]=self
.getEmail()
1608 data
["fax"]=self
.getFax()
1609 data
["title"]=self
.getTitle()
1610 data
["phone"]=self
.getPhone()
1613 def setId(self
, newId
):
1619 def setDataFromAvatar(self
,av
):
1620 # av is an Avatar object.
1623 self
.setFirstName(av
.getName())
1624 self
.setFamilyName(av
.getSurName())
1625 self
.setEmail(av
.getEmail())
1626 self
.setAffiliation(av
.getOrganisation())
1627 self
.setAddress(av
.getAddress())
1628 self
.setPhone(av
.getTelephone())
1629 self
.setTitle(av
.getTitle())
1630 self
.setFax(av
.getFax())
1631 self
._notifyModification
()
1633 def setDataFromOtherCP(self
,cp
):
1634 # cp is a ConferenceParticipation object.
1637 self
.setFirstName(cp
.getFirstName())
1638 self
.setFamilyName(cp
.getFamilyName())
1639 self
.setEmail(cp
.getEmail())
1640 self
.setAffiliation(cp
.getAffiliation())
1641 self
.setAddress(cp
.getAddress())
1642 self
.setPhone(cp
.getPhone())
1643 self
.setTitle(cp
.getTitle())
1644 self
.setFax(cp
.getFax())
1645 self
._notifyModification
()
1648 TrashCanManager().add(self
)
1651 TrashCanManager().remove(self
)
1653 @Updates (['MaKaC.conference.ConferenceParticipation',
1654 'MaKaC.conference.SessionChair',
1655 'MaKaC.conference.SlotChair'], 'firstName')
1656 def setFirstName(self
,newName
):
1658 if tmp
==self
._firstName
:
1661 self
._notifyModification
()
1663 def getFirstName( self
):
1664 return self
._firstName
1666 @Updates (['MaKaC.conference.ConferenceParticipation',
1667 'MaKaC.conference.SessionChair',
1668 'MaKaC.conference.SlotChair'], 'familyName')
1669 def setFamilyName(self
,newName
):
1671 if tmp
==self
._surName
:
1674 self
._notifyModification
()
1676 def getFamilyName( self
):
1677 return self
._surName
1679 @Updates (['MaKaC.conference.ConferenceParticipation',
1680 'MaKaC.conference.SessionChair',
1681 'MaKaC.conference.SlotChair'], 'email')
1682 def setEmail(self
,newMail
):
1684 if tmp
==self
._email
:
1686 self
._email
=newMail
.strip()
1687 self
._notifyModification
()
1689 def getEmail( self
):
1692 @Updates (['MaKaC.conference.ConferenceParticipation',
1693 'MaKaC.conference.SessionChair',
1694 'MaKaC.conference.SlotChair'], 'affiliation')
1695 def setAffiliation(self
,newAffil
):
1696 self
._affiliation
=newAffil
.strip()
1697 self
._notifyModification
()
1699 def getAffiliation(self
):
1700 return self
._affiliation
1702 @Updates (['MaKaC.conference.ConferenceParticipation',
1703 'MaKaC.conference.SessionChair',
1704 'MaKaC.conference.SlotChair'], 'address')
1705 def setAddress(self
,newAddr
):
1706 self
._address
=newAddr
.strip()
1707 self
._notifyModification
()
1709 def getAddress(self
):
1710 return self
._address
1712 @Updates (['MaKaC.conference.ConferenceParticipation',
1713 'MaKaC.conference.SessionChair',
1714 'MaKaC.conference.SlotChair'], 'phone')
1715 def setPhone(self
,newPhone
):
1716 self
._phone
=newPhone
.strip()
1717 self
._notifyModification
()
1722 @Updates (['MaKaC.conference.ConferenceParticipation',
1723 'MaKaC.conference.SessionChair',
1724 'MaKaC.conference.SlotChair'], 'title')
1725 def setTitle(self
,newTitle
):
1726 self
._title
=newTitle
.strip()
1727 self
._notifyModification
()
1732 @Updates (['MaKaC.conference.ConferenceParticipation',
1733 'MaKaC.conference.SessionChair',
1734 'MaKaC.conference.SlotChair'], 'fax')
1735 def setFax(self
,newFax
):
1736 self
._fax
=newFax
.strip()
1737 self
._notifyModification
()
1742 def getFullName( self
):
1743 res
= self
.getFamilyName()
1744 if self
.getFirstName() != "":
1745 if res
.strip() != "":
1746 res
= "%s, %s"%( res
, self
.getFirstName() )
1748 res
= self
.getFirstName()
1749 if self
.getTitle() != "":
1750 res
= "%s %s"%( self
.getTitle(), res
)
1753 def getFullNameNoTitle( self
):
1754 res
= self
.getFamilyName()
1755 if self
.getFirstName() != "":
1756 if res
.strip() != "":
1757 res
= "%s, %s"%( res
, self
.getFirstName() )
1759 res
= self
.getFirstName()
1762 def getDirectFullName( self
):
1763 res
= "%s %s"%( self
.getFirstName(), self
.getFamilyName() )
1765 if self
.getTitle() != "":
1766 res
= "%s %s"%( self
.getTitle(), res
)
1769 def getAbrName(self
):
1770 res
= self
.getFamilyName()
1771 if self
.getFirstName() != "":
1774 res
= "%s%s."%(res
, self
.getFirstName()[0].upper())
1777 def _cmpFamilyName( cp1
, cp2
):
1778 o1
= "%s %s"%(cp1
.getFamilyName(), cp1
.getFirstName())
1779 o2
= "%s %s"%(cp2
.getFamilyName(), cp2
.getFirstName())
1780 o1
=o1
.lower().strip()
1781 o2
=o2
.lower().strip()
1782 return cmp( o1
, o2
)
1783 _cmpFamilyName
=staticmethod(_cmpFamilyName
)
1786 class ConferenceChair(ConferenceParticipation
, Fossilizable
):
1788 fossilizes(IConferenceParticipationFossil
)
1793 ConferenceParticipation
.__init
__(self
)
1795 def _notifyModification( self
):
1796 if self
._conf
!= None:
1797 self
._conf
.notifyModification()
1800 newCC
=ConferenceChair()
1801 newCC
.setValues(self
.getValues())
1804 def getConference(self
):
1810 def includeInConference(self
,conf
,id):
1811 if self
.getConference()==conf
and self
.getId()==id.strip():
1818 ConferenceParticipation
.delete(self
)
1820 def getLocator(self
):
1821 if self
.getConference() is None:
1823 loc
=self
.getConference().getLocator()
1824 loc
["chairId"]=self
.getId()
1827 class SubmitterIndex(Persistent
):
1828 """Index for contribution submitters.
1830 This class allows to index users with submission privileges over the
1831 conference contributions so the owner can answer optimally to the query
1832 if a user has any submission privilege over any contribution
1834 It is implemented by simply using a BTree where the Avatar id is used
1835 as key (because it is unique and non variable) and a list of
1836 contributions over which he has submission privileges is kept as values.
1837 It is the responsability of the index owner (conference contributions)
1838 to keep it up-to-date i.e. notify conference sumitters additions and
1842 def __init__( self
):
1843 self
._idx
= OOBTree()
1844 self
._idxEmail
= OOBTree()
1846 def _getIdxEmail(self
):
1848 return self
._idxEmail
1850 self
._idxEmail
= OOBTree()
1851 return self
._idxEmail
1853 def getContributions(self
,av
):
1854 """Gives a list with the contributions over which a user has
1855 coordination privileges
1859 ret
= self
._idx
.get(av
.getId(),[])
1861 self
._moveEmailtoId
(av
)
1862 ret
= self
._idx
.get(av
.getId(),[])
1865 def index(self
,av
,contrib
):
1866 """Registers in the index a submitter of a contribution.
1868 if av
==None or contrib
==None:
1870 if not self
._idx
.has_key(av
.getId()):
1872 self
._idx
[av
.getId()]=l
1874 l
=self
._idx
[av
.getId()]
1875 if contrib
not in l
:
1877 self
._idx
[av
.getId()]=l
1879 def indexEmail(self
, email
, contrib
):
1880 if not email
or not contrib
:
1882 if not self
._getIdxEmail
().has_key(email
):
1884 self
._getIdxEmail
()[email
] = l
1886 l
= self
._getIdxEmail
()[email
]
1887 if not contrib
in l
:
1889 self
._getIdxEmail
()[email
] = l
1892 def unindex(self
,av
,contrib
):
1893 if av
==None or contrib
==None:
1895 l
=self
._idx
.get(av
.getId(),[])
1898 self
._idx
[av
.getId()]=l
1900 def unindexEmail(self
, email
, contrib
):
1901 if not email
or not contrib
:
1903 if self
._getIdxEmail
().has_key(email
):
1904 l
= self
._getIdxEmail
()[email
]
1908 del self
._getIdxEmail
()[email
]
1910 self
._getIdxEmail
()[email
] = l
1912 def _moveEmailtoId(self
, av
):
1914 email
= av
.getEmail()
1915 if not self
._idx
.has_key(id):
1916 if self
._getIdxEmail
().has_key(email
):
1917 self
._idx
[id] = self
._getIdxEmail
()[email
]
1918 del self
._getIdxEmail
()[email
]
1921 class ReportNumberHolder(Persistent
):
1923 def __init__(self
, owner
):
1930 def addReportNumber(self
, system
, number
):
1931 if system
in self
.getReportNumberKeys() or system
in Config
.getInstance().getReportNumberSystems().keys():
1933 if not number
in self
._reports
[system
]:
1934 self
._reports
[system
].append(number
)
1936 self
._reports
[system
]=[ number
]
1937 self
.notifyModification()
1939 def removeReportNumber(self
, system
, number
):
1940 if self
.hasReportNumber(system
):
1941 if number
in self
._reports
[system
]:
1942 self
._reports
[system
].remove(number
)
1943 self
.notifyModification()
1945 def removeReportNumberById(self
, id):
1947 rn
= self
.listReportNumbers()[int(id)]
1948 self
.removeReportNumber(rn
[0], rn
[1])
1952 def hasReportNumber(self
, system
):
1953 return self
._reports
.has_key(system
)
1955 def getReportNumber(self
, system
):
1956 if self
.hasReportNumber(system
):
1957 return self
._reports
[system
]
1960 def getReportNumberKeys(self
):
1961 return self
._reports
.keys()
1963 def listReportNumbersOnKey(self
, key
):
1965 if key
in self
._reports
.keys():
1966 # compatibility with previous versions
1967 if type(self
._reports
[key
]) is str:
1968 self
._reports
[key
] = [ self
._reports
[key
] ]
1969 for number
in self
._reports
[key
]:
1970 reports
.append([key
, number
])
1973 def listReportNumbers(self
):
1975 keys
= self
._reports
.keys()
1978 # compatibility with previous versions
1979 if type(self
._reports
[key
]) is str:
1980 self
._reports
[key
] = [ self
._reports
[key
] ]
1981 for number
in self
._reports
[key
]:
1982 reports
.append([key
, number
])
1985 def clone(self
, owner
):
1986 newR
=ReportNumberHolder(owner
)
1987 for key
in self
._reports
.keys():
1988 for number
in self
._reports
[key
]:
1989 newR
.addReportNumber(key
, number
)
1992 def notifyModification(self
):
1994 if self
.getOwner() != None:
1995 self
.getOwner().notifyModification()
1997 class Conference(CommonObjectBase
, Locatable
):
1998 """This class represents the real world conferences themselves. Objects of
1999 this class will contain basic data about the confence and will provide
2000 access to other objects representing certain parts of the conferences
2001 (ex: contributions, sessions, ...).
2004 fossilizes(IConferenceFossil
, IConferenceMinimalFossil
, IConferenceEventInfoFossil
)
2006 def __init__(self
, creator
, id="", creationDate
= None, modificationDate
= None):
2007 """Class constructor. Initialise the class attributes to the default
2010 confData -- (Dict) Contains the data the conference object has to
2013 #IndexedObject.__init__(self)
2015 raise MaKaCError( _("A creator must be specified when creating a new Event"), _("Event"))
2016 self
.__creator
= creator
2017 self
.__creator
.linkTo(self
, "creator")
2020 self
.description
= ""
2023 ###################################
2024 # Fermi timezone awareness #
2025 ###################################
2026 self
.startDate
= nowutc()
2027 self
.endDate
= nowutc()
2029 ###################################
2030 # Fermi timezone awareness(end) #
2031 ###################################
2032 self
._screenStartDate
= None
2033 self
._screenEndDate
= None
2034 self
.contactInfo
=""
2035 self
.chairmanText
= ""
2037 self
._chairGen
=Counter()
2040 self
.__sessionGenerator
= Counter() # Provides session unique
2041 # identifiers for this conference
2042 self
.contributions
= {}
2043 self
.__contribGenerator
= Counter() # Provides contribution unique
2044 # identifiers for this conference
2045 self
.programDescription
= ""
2047 self
.__programGenerator
= Counter() # Provides track unique
2048 # identifiers for this conference
2049 self
.__ac
= AccessController(self
)
2051 self
.__materialGenerator
= Counter() # Provides material unique
2052 # identifiers for this conference
2058 self
.__schedule
=None
2061 self
._creationDS
= creationDate
2063 self
._creationDS
= nowutc() #creation timestamp
2064 if modificationDate
:
2065 self
._modificationDS
= modificationDate
2067 self
._modificationDS
= nowutc() #modification timestamp
2070 self
.__alarmCounter
= Counter()
2072 self
.abstractMgr
= review
.AbstractMgr(self
)
2074 self
._trackCoordinators
= TCIndex() #index for the track coordinators
2075 self
._supportEmail
= "" #Support email for the conference
2076 self
._contribTypes
= {}
2077 self
.___contribTypeGenerator
= Counter()
2078 self
._authorIdx
=AuthorIndex()
2079 self
._speakerIdx
=AuthorIndex()
2080 self
._primAuthIdx
=_PrimAuthIdx(self
)
2081 self
._sessionCoordinators
=SCIndex()
2082 self
._sessionCoordinatorRights
= []
2083 self
._submitterIdx
=SubmitterIndex()
2084 self
._boa
=BOAConfig(self
)
2085 self
._registrationForm
= registration
.RegistrationForm(self
)
2086 self
._evaluationCounter
= Counter()
2087 self
._evaluations
= [Evaluation(self
)]
2088 self
._registrants
= {} #key=registrantId; value=Registrant
2090 self
._registrantGenerator
= Counter()
2093 self
._closed
= False
2094 self
._visibility
= 999
2095 self
._pendingQueuesMgr
=pendingQueues
.ConfPendingQueuesMgr(self
)
2097 self
._participation
= Participation(self
)
2098 self
._logHandler
= LogHandler()
2099 self
._reportNumberHolder
=ReportNumberHolder(self
)
2100 self
._enableSessionSlots
= False
2101 self
._enableSessions
= False
2102 self
._autoSolveConflict
= True
2103 self
.__badgeTemplateManager
= BadgeTemplateManager(self
)
2104 self
.__posterTemplateManager
= PosterTemplateManager(self
)
2106 self
._confPaperReview
= ConferencePaperReview(self
)
2107 self
._confAbstractReview
= ConferenceAbstractReview(self
)
2110 self
._sortUrlTag
= ""
2112 self
._observers
= []
2114 if PluginsHolder().hasPluginType("Collaboration"):
2115 from MaKaC
.plugins
.Collaboration
.base
import CSBookingManager
2116 self
._CSBookingManager
= CSBookingManager(self
)
2119 return "<Conference %s@%s>" % (self
.getId(), hex(id(self
)))
2122 def _cmpByDate(self
, toCmp
):
2123 res
= cmp(self
.getStartDate(), toCmp
.getStartDate())
2127 return cmp(self
, toCmp
)
2129 def __cmp__(self
, toCmp
):
2130 if isinstance(toCmp
, Conference
):
2131 return cmp(self
.getId(), toCmp
.getId())
2133 return cmp(hash(self
), hash(toCmp
))
2135 def __eq__(self
, toCmp
):
2136 return self
is toCmp
2138 def __ne__(self
, toCmp
):
2139 return not(self
is toCmp
)
2141 def setUrlTag(self
, tag
):
2142 self
._sortUrlTag
= tag
2144 def getUrlTag(self
):
2146 return self
._sortUrlTag
2148 self
._sortUrlTag
= ""
2149 return self
._sortUrlTag
2151 def setComments(self
,comm
=""):
2152 self
._comments
= comm
.strip()
2154 def getComments(self
):
2158 except AttributeError,e
:
2160 return self
._comments
2162 def getConfPaperReview(self
):
2163 if not hasattr(self
, "_confPaperReview"):
2164 self
._confPaperReview
= ConferencePaperReview(self
)
2165 return self
._confPaperReview
2167 def getConfAbstractReview(self
):
2168 if not hasattr(self
, "_confAbstractReview"):
2169 self
._confAbstractReview
= ConferenceAbstractReview(self
)
2170 return self
._confAbstractReview
2172 def getOrgText( self
):
2174 return self
._orgText
2179 def setOrgText( self
, org
="" ):
2182 def cleanCache( self
):
2183 minfo
= info
.HelperMaKaCInfo
.getMaKaCInfoInstance()
2184 if minfo
.isCacheActive():
2185 cache
= EventCache({"id":self
.getId(), "type": "normal"})
2187 cache
= EventCache({"id":self
.getId(), "type": "manager"})
2189 cache
= EventCache({"id":self
.getId(), "type": "static"})
2192 def cleanCategoryCache( self
):
2193 if len(self
.getOwnerList()) > 0:
2194 self
.getOwnerList()[0].cleanCache()
2196 def isFullyPublic( self
):
2197 """ determines whether an event (or any part of it) is private or not"""
2198 if hasattr(self
, "_fullyPublic"):
2199 return self
._fullyPublic
2201 self
.setFullyPublic()
2202 return self
._fullyPublic
2204 def setFullyPublic( self
):
2205 """ This function calculates the self._fullyPublic attribute"""
2206 if self
.isProtected():
2207 self
._fullyPublic
= False
2210 for mat
in self
.getAllMaterialList():
2211 if not mat
.isFullyPublic():
2212 self
._fullyPublic
= False
2215 for cont
in self
.getContributionList():
2216 if not cont
.isFullyPublic():
2217 self
._fullyPublic
= False
2220 for ses
in self
.getSessionList():
2221 if not ses
.isFullyPublic():
2222 self
._fullyPublic
= False
2225 self
._fullyPublic
= True
2228 def updateFullyPublic( self
):
2229 self
.setFullyPublic()
2231 # Room booking related
2232 #self.__roomBookingGuids = []
2235 def getKeywords(self
):
2237 return self
._keywords
2242 def setKeywords(self
, keywords
):
2243 self
._keywords
= keywords
2245 def _setCreator(self
, av
):
2248 # Room booking related ===================================================
2250 def getRoomBookingList( self
):
2252 Returns list of bookings for this conference.
2254 from MaKaC
.plugins
.RoomBooking
.default
.dalManager
import DALManager
2256 if not DALManager
.isConnected():
2260 for resvGuid
in self
.getRoomBookingGuids():
2261 r
= resvGuid
.getReservation()
2263 self
.removeRoomBookingGuid( resvGuid
)
2268 def getBookedRooms( self
):
2270 Returns list of rooms booked for this conference.
2271 Returns [] if room booking module is off.
2275 for r
in self
.getRoomBookingList():
2276 if not r
.room
in rooms
:
2277 rooms
.append( r
.room
)
2280 def getRoomBookingGuids( self
):
2282 self
.__roomBookingGuids
2283 except AttributeError:
2284 self
.__roomBookingGuids
= []
2285 return self
.__roomBookingGuids
2287 def setRoomBookingGuids( self
, guids
):
2288 self
.__roomBookingGuids
= guids
2290 def addRoomBookingGuid( self
, guid
):
2291 self
.getRoomBookingGuids().append( guid
)
2292 self
._p
_changed
= True
2294 def removeRoomBookingGuid( self
, guid
):
2295 self
.getRoomBookingGuids().remove( guid
)
2296 self
._p
_changed
= True
2298 def __TMP_PopulateRoomBookings( self
):
2299 # TEMPORARY GENERATION OF RESERVATIONS FOR CONFERENCE
2300 from MaKaC
.rb_reservation
import ReservationBase
2301 from MaKaC
.rb_location
import ReservationGUID
, Location
2303 resvs
.append( ReservationBase
.getReservations( resvID
= 395887 ) )
2304 resvs
.append( ReservationBase
.getReservations( resvID
= 381406 ) )
2305 resvs
.append( ReservationBase
.getReservations( resvID
= 387688 ) )
2306 resvs
.append( ReservationBase
.getReservations( resvID
= 383459 ) )
2310 resvGuids
.append( ReservationGUID( Location
.getDefaultLocation(), resv
.id ) )
2312 self
.__roomBookingGuids
= resvGuids
2315 # ========================================================================
2317 def getParticipation(self
):
2319 if self
._participation
:
2321 except AttributeError :
2322 self
._participation
= Participation(self
)
2323 return self
._participation
2325 def getType( self
):
2326 import MaKaC
.webinterface
.webFactoryRegistry
as webFactoryRegistry
2327 wr
= webFactoryRegistry
.WebFactoryRegistry()
2328 wf
= wr
.getFactory(self
)
2335 def getVerboseType( self
):
2336 # Like getType, but returns "Lecture" instead of "simple_type"
2337 type = self
.getType()
2338 if type == "simple_event":
2340 return type.capitalize()
2343 def getLogHandler(self
):
2345 if self
._logHandler
:
2347 except AttributeError :
2348 self
._logHandler
= LogHandler()
2349 return self
._logHandler
2352 def getEnableSessionSlots(self
):
2354 # if self._enableSessionSlots :
2356 #except AttributeError :
2357 # self._enableSessionSlots = True
2358 #if self.getType() == "conference":
2360 #return self._enableSessionSlots
2363 def getEnableSessions(self
):
2365 if self
._enableSessions
:
2367 except AttributeError :
2368 self
._enableSessions
= True
2369 if self
.getType() == "conference":
2371 return self
._enableSessions
2373 def enableSessionSlots(self
):
2374 self
._enableSessionSlots
= True
2376 def disableSessionSlots(self
):
2377 self
._enableSessionSlots
= False
2379 def enableSessions(self
):
2380 self
._enableSessions
= True
2382 def disableSessions(self
):
2383 self
._enableSessions
= False
2385 def setValues(self
, confData
):
2387 Sets SOME values of the current conference object from a dictionary
2388 containing the following key-value pairs:
2394 locationName-(str) => name of the location, if not specified
2395 it will be set to the conference location name.
2396 locationAddress-(str)
2397 roomName-(str) => name of the room, if not specified it will
2398 be set to the conference room name.
2399 Please, note that this method sets SOME values which means that if
2400 needed it can be completed to set more values. Also note that if
2401 the given dictionary doesn't contain all the values, the missing
2402 ones will be set to the default values.
2404 self
.setVisibility(confData
.get("visibility", "999"))
2405 self
.setTitle(confData
.get("title", _("NO TITLE ASSIGNED")))
2406 self
.setDescription(confData
.get("description", ""))
2407 self
.setSupportEmail(confData
.get("supportEmail", ""))
2408 self
.setContactInfo(confData
.get("contactInfo", ""))
2409 if confData
.get("locationName", "").strip() == "":
2410 self
.setLocation(None)
2412 #if the location name is defined we must set a new location (or
2413 # modify the existing one) for the conference
2414 loc
= self
.getLocation()
2416 loc
= CustomLocation()
2417 self
.setLocation(loc
)
2418 loc
.setName(confData
["locationName"])
2419 loc
.setAddress(confData
.get("locationAddress", ""))
2420 #same as for the location
2421 if confData
.get("roomName", "").strip() == "":
2424 room
= self
.getRoom()
2428 room
.setName(confData
["roomName"])
2429 self
.notifyModification()
2431 def getVisibility ( self
):
2433 return int(self
._visibility
)
2435 self
._visibility
= 999
2438 def getFullVisibility( self
):
2439 return max(0,min(self
.getVisibility(), self
.getOwnerList()[0].getVisibility()))
2441 def setVisibility( self
, visibility
=999 ):
2442 self
._visibility
= int(visibility
)
2443 catIdx
= indexes
.IndexesHolder().getIndex('category')
2444 catIdx
.reindexConf(self
)
2445 catDateIdx
= indexes
.IndexesHolder().getIndex('categoryDate')
2446 catDateAllIdx
= indexes
.IndexesHolder().getIndex('categoryDateAll')
2447 catDateIdx
.reindexConf(self
)
2448 catDateAllIdx
.reindexConf(self
)
2450 def isClosed( self
):
2454 self
._closed
= False
2457 def setClosed( self
, closed
=True ):
2458 self
._closed
= closed
2460 def indexConf( self
):
2461 # called when event dates change
2462 # see also Category.indexConf()
2464 calIdx
= indexes
.IndexesHolder().getIndex('calendar')
2465 calIdx
.indexConf(self
)
2466 catDateIdx
= indexes
.IndexesHolder().getIndex('categoryDate')
2467 catDateAllIdx
= indexes
.IndexesHolder().getIndex('categoryDateAll')
2468 catDateIdx
.indexConf(self
)
2469 catDateAllIdx
.indexConf(self
)
2471 Catalog
.getIdx('categ_conf_sd').index_obj(self
)
2473 def unindexConf( self
):
2474 calIdx
= indexes
.IndexesHolder().getIndex('calendar')
2475 calIdx
.unindexConf(self
)
2476 catDateIdx
= indexes
.IndexesHolder().getIndex('categoryDate')
2477 catDateAllIdx
= indexes
.IndexesHolder().getIndex('categoryDateAll')
2478 catDateIdx
.unindexConf(self
)
2479 catDateAllIdx
.unindexConf(self
)
2481 Catalog
.getIdx('categ_conf_sd').unindex_obj(self
)
2483 def __generateNewContribTypeId( self
):
2484 """Returns a new unique identifier for the current conference sessions
2487 return str(self
.___contribTypeGenerator
.newCount())
2489 self
.___contribTypeGenerator
= Counter()
2490 return str(self
.___contribTypeGenerator
.newCount())
2492 def addContribType(self
, ct
):
2494 if self
._contribTypes
:
2497 self
._contribTypes
= {}
2498 if ct
in self
._contribTypes
.values():
2502 id = self
.__generateNewContribTypeId
()
2504 self
._contribTypes
[id] = ct
2505 self
.notifyModification()
2507 def newContribType(self
, name
, description
):
2508 ct
= ContributionType(name
, description
, self
)
2509 self
.addContribType(ct
)
2512 def getContribTypeList(self
):
2514 return self
._contribTypes
.values()
2516 self
._contribTypes
= {}
2517 self
.notifyModification()
2518 return self
._contribTypes
.values()
2520 def getContribTypeById(self
, id):
2522 if self
._contribTypes
:
2525 self
._contribTypes
= {}
2526 self
.notifyModification()
2527 if id in self
._contribTypes
.keys():
2528 return self
._contribTypes
[id]
2531 def removeContribType(self
, ct
):
2533 if self
._contribTypes
:
2536 self
._contribTypes
= {}
2537 if not ct
in self
._contribTypes
.values():
2539 del self
._contribTypes
[ct
.getId()]
2540 for cont
in self
.getContributionList():
2541 if cont
.getType() == ct
:
2544 self
.notifyModification()
2546 def recoverContribType(self
, ct
):
2547 ct
.setConference(self
)
2548 self
.addContribType(ct
)
2551 def _getRepository( self
):
2552 dbRoot
= DBMgr
.getInstance().getDBConnection().root()
2554 fr
= dbRoot
["local_repositories"]["main"]
2556 fr
= fileRepository
.MaterialLocalRepository()
2557 dbRoot
["local_repositories"] = OOBTree()
2558 dbRoot
["local_repositories"]["main"] = fr
2561 def removeResource( self
, res
):
2565 cid
= self
.getUrlTag()
2568 return Config
.getInstance().getShortEventURL() + cid
2570 def setLogo( self
, logoFile
):
2571 logoFile
.setOwner( self
)
2572 logoFile
.setId( "logo" )
2573 logoFile
.archive( self
._getRepository
() )
2574 if self
._logo
!= None:
2576 self
._logo
= logoFile
2577 self
.notifyModification()
2579 def getLogo( self
):
2582 def getLogoURL( self
):
2584 if self
._logo
== None:
2586 return self
._logo
.getURL()
2587 except AttributeError:
2591 def removeLogo(self
):
2592 if self
._logo
is None:
2596 self
.notifyModification()
2598 def recoverLogo(self
, logo
):
2600 if self
._logo
!= None:
2604 self
.notifyModification()
2606 def getSession(self
):
2609 def getContribution(self
):
2612 def getSubContribution(self
):
2615 def getAbstractMgr(self
):
2616 return self
.abstractMgr
2618 def notifyModification( self
, date
= None, raiseEvent
= True):
2619 """Method called to notify the current conference has been modified.
2621 self
.setModificationDate()
2624 self
._notify
('infoChanged')
2629 def getModificationDate( self
):
2630 """Returns the date in which the conference was last modified"""
2631 return self
._modificationDS
2633 def getAdjustedModificationDate( self
, tz
):
2634 """Returns the date in which the conference was last modified"""
2635 return self
._modificationDS
.astimezone(timezone(tz
))
2637 def getCreationDate( self
):
2638 """Returns the date in which the conference was created"""
2639 return self
._creationDS
2641 def getAdjustedCreationDate( self
, tz
):
2642 """Returns the date in which the conference was created"""
2643 return self
._creationDS
.astimezone(timezone(tz
))
2645 def getCreator( self
):
2646 return self
.__creator
2648 def setCreator( self
, creator
):
2650 self
.__creator
.unlinkTo(self
, "creator")
2651 creator
.linkTo(self
, "creator")
2652 self
.__creator
= creator
2655 """returns (string) the unique identifier of the conference"""
2658 def getUniqueId( self
):
2659 """returns (string) the unique identiffier of the item"""
2660 """used mainly in the web session access key table"""
2661 return "a%s" % self
.id
2663 def setId(self
, newId
):
2664 """changes the current unique identifier of the conference to the
2665 one which is specified"""
2666 self
.id = str(newId
)
2668 def getLocator( self
):
2669 """Gives back (Locator) a globaly unique identification encapsulated in
2670 a Locator object for the conference instance """
2672 d
["confId"] = self
.getId()
2675 def getOwner( self
):
2676 if self
.getOwnerList() == []:
2678 return self
.getOwnerList()[0]
2680 def getOwnerList( self
):
2681 return self
.__owners
2683 def getOwnerPath( self
):
2685 owner
= self
.getOwnerList()[0]
2686 while owner
!= None and owner
.getId() != "0":
2688 owner
= owner
.getOwner()
2691 def getOwnerById( self
, key
):
2692 """Returns one specific category which contains the conference.
2694 - key: The "id" of the category.
2696 for owner
in self
.__owners
:
2697 if key
== owner
.getId():
2701 def addOwner( self
, newOwner
):
2702 if newOwner
== None:
2704 self
.__owners
.append( newOwner
)
2705 self
.notifyModification()
2707 def removeOwner( self
, owner
, notify
=True ):
2708 if not (owner
in self
.__owners
):
2710 self
.__owners
.remove( owner
)
2711 owner
.removeConference( self
)
2713 self
.notifyModification()
2715 def getCategoriesPath(self
):
2716 return [self
.getOwnerList()[0].getCategoryPath()]
2718 def notifyContributions(self
):
2720 for c
in self
.getContributionList():
2721 # take care of subcontributions
2722 for sc
in c
.getSubContributionList():
2723 sc
._notify
('deleted', c
)
2725 c
._notify
('deleted', self
)
2728 """deletes the conference from the system.
2730 #we notify the observers that the conference has been deleted
2732 self
._notify
('deleted', self
.getOwner())
2733 except Exception, e
:
2735 Logger
.get('Conference').error("Exception while notifying the observer of a conference deletion for conference %s: %s" %
2736 (self
.getId(), str(e
)))
2737 except Exception, e2
:
2738 Logger
.get('Conference').error("Exception while notifying a conference deletion: %s (origin: %s)" % (str(e2
), str(e
)))
2740 self
.notifyContributions()
2742 #will have to remove it from all the owners (categories) and the
2743 # conference registry
2744 ConferenceHolder().remove( self
)
2745 for owner
in self
.__owners
:
2746 owner
.removeConference( self
, notify
=False )
2748 for alarm
in self
.getAlarmList():
2749 if not alarm
.getEndedOn():
2750 self
.removeAlarm(alarm
)
2752 self
.removeAllEvaluations()
2754 #Delete the RoomBooking associated reservations
2755 minfo
= info
.HelperMaKaCInfo
.getMaKaCInfoInstance()
2756 if minfo
.getRoomBookingModuleActive() and CrossLocationDB
.isConnected():
2757 for resv
in self
.getRoomBookingList():
2760 #For each conference we have a list of managers. If we delete the conference but we don't delete
2761 #the link in every manager to the conference then, when the manager goes to his "My profile" he
2762 #will see a link to a conference that doesn't exist. Therefore, we need to delete that link as well
2763 for manager
in self
.getManagerList():
2764 if isinstance(manager
, MaKaC
.user
.Avatar
):
2765 manager
.unlinkTo(self
, "manager")
2767 # Remote short URL mappings
2768 sum = ShortURLMapper()
2771 TrashCanManager().add(self
)
2773 def getConference( self
):
2776 def getObservers(self
):
2777 if not hasattr(self
, "_observers"):
2778 self
._observers
= []
2779 return self
._observers
2781 def setDates( self
, sDate
, eDate
=None, check
=1, moveEntries
=0):
2783 Set the start/end date for a conference
2786 oldStartDate
= self
.getStartDate()
2787 oldEndDate
= self
.getEndDate()
2789 # do some checks first
2792 raise MaKaCError( _("Start date cannot be after the end date"), _("Event"))
2794 elif sDate
== oldStartDate
and eDate
== oldEndDate
:
2795 # if there's nothing to do (yet another obvious case)
2798 # if we reached this point, it means either the start or
2799 # the end date (or both) changed
2800 # If only the end date was changed, moveEntries = 0
2801 if sDate
== oldStartDate
:
2804 # Pre-check for moveEntries
2805 if moveEntries
== 1:
2806 # in case the entries are to be simply shifted
2807 # we should make sure the interval is big enough
2808 # just store the old values for later
2810 oldInterval
= oldEndDate
- oldStartDate
2811 newInterval
= eDate
- sDate
2813 entries
= self
.getSchedule().getEntries()
2814 if oldInterval
> newInterval
and entries
:
2815 eventInterval
= entries
[-1].getEndDate() - entries
[0].getStartDate()
2816 diff
= entries
[0].getStartDate() - oldStartDate
2817 if sDate
+ diff
+ eventInterval
> eDate
:
2819 _("The start/end dates were not changed since the selected "
2820 "timespan is not large enough to accomodate the contained "
2821 "timetable entries and spacings."),
2822 explanation
=_("You should try using a larger timespan."))
2824 # so, we really need to try changing something
2829 self
.setStartDate(sDate
, check
=0, moveEntries
= moveEntries
, index
=False, notifyObservers
= False)
2830 self
.setEndDate(eDate
, check
=0, index
=False, notifyObservers
= False)
2833 self
._checkInnerSchedule
()
2835 # reindex the conference
2838 # clear the category cache
2839 self
.cleanCategoryCache()
2843 self
._notify
('dateChanged', {'oldStartDate': oldStartDate
, 'newStartDate': self
.getStartDate(), 'oldEndDate': oldEndDate
, 'newEndDate': self
.getEndDate()})
2844 except Exception, e
:
2846 Logger
.get('Conference').error("Exception while notifying the observer of a start and end date change from %s - %s to %s - %s for conference %s: %s" %
2847 (formatDateTime(oldStartDate
), formatDateTime(oldEndDate
),
2848 formatDateTime(self
.getStartDate()), formatDateTime(self
.getEndDate()), self
.getId(), str(e
)))
2849 except Exception, e2
:
2850 Logger
.get('Conference').error("Exception while notifying a start and end date change: %s (origin: %s)" % (str(e2
), str(e
)))
2853 def _checkInnerSchedule( self
):
2854 self
.getSchedule().checkSanity()
2856 def setStartDate(self
, sDate
, check
= 1, moveEntries
= 0, index
= True, notifyObservers
= True):
2857 """ Changes the current conference starting date/time to the one specified by the parameters.
2859 if not sDate
.tzname():
2860 raise MaKaCError("date should be timezone aware")
2861 if sDate
== self
.getStartDate():
2863 ###################################
2864 # Fermi timezone awareness #
2865 ###################################
2866 if sDate
.year
< 1900:
2867 sDate
= timezone('UTC').localize(1900,sDate
.month
, \
2868 sDate
.day
,sDate
.hour
,sDate
.minute
)
2869 ###################################
2870 # Fermi timezone awareness #
2871 ###################################
2873 self
.verifyStartDate(sDate
)
2874 oldSdate
= self
.getStartDate()
2875 diff
= sDate
- oldSdate
2879 self
.startDate
= sDate
2880 if moveEntries
and diff
is not None:
2881 # If the start date changed, we move entries inside the timetable
2882 self
.getSchedule()._startDate
=None
2883 self
.getSchedule()._endDate
=None
2884 #if oldSdate.date() != sDate.date():
2885 # entries = self.getSchedule().getEntries()[:]
2887 # entries = self.getSchedule().getEntriesOnDay(sDate.astimezone(timezone(self.getTimezone())))[:]
2888 entries
= self
.getSchedule().getEntries()[:]
2889 self
.getSchedule().moveEntriesBelow(diff
, entries
)
2890 #datetime object is non-mutable so we must "force" the modification
2891 # otherwise ZODB won't be able to notice the change
2892 self
.notifyModification()
2896 # update the time for the alarms to be sent
2897 self
._updateAlarms
()
2899 #if everything went well, we notify the observers that the start date has changed
2902 self
._notify
('startDateChanged', {'newDate': sDate
, 'oldDate': oldSdate
})
2903 except Exception, e
:
2905 Logger
.get('Conference').error("Exception while notifying the observer of a start date change from %s to %s for conference %s: %s" %
2906 (formatDateTime(oldSdate
), formatDateTime(sDate
), self
.getId(), str(e
)))
2907 except Exception, e2
:
2908 Logger
.get('Conference').error("Exception while notifying a start date change: %s (origin: %s)" % (str(e2
), str(e
)))
2911 def _updateAlarms(self
):
2913 # are there any alarms? if so, update the relative ones
2914 for alarm
in self
.getAlarmList():
2915 tbef
= alarm
.getTimeBefore()
2917 # only relative alarms
2918 c
.moveTask(alarm
, self
.getStartDate() - tbef
)
2920 def verifyStartDate(self
, sdate
, check
=1):
2921 if sdate
>self
.getEndDate():
2922 raise MaKaCError( _("End date cannot be before the Start date"), _("Event"))
2924 def setStartTime(self
, hours
=0, minutes
=0, notifyObservers
= True):
2925 """ Changes the current conference starting time (not date) to the one specified by the parameters.
2928 sdate
= self
.getStartDate()
2929 self
.startDate
= datetime( sdate
.year
, sdate
.month
, sdate
.day
,
2930 int(hours
), int(minutes
) )
2931 self
.verifyStartDate(self
.startDate
)
2932 self
.notifyModification()
2934 #if everything went well, we notify the observers that the start date has changed
2937 self
._notify
('startTimeChanged', sdate
)
2938 #for observer in self.getObservers():
2939 #observer.notifyEventDateChanges(sdate, self.startDate, None, None)
2940 except Exception, e
:
2942 Logger
.get('Conference').error("Exception while notifying the observer of a start date change from %s to %s for conference %s: %s"%
2943 (formatDateTime(sdate
), formatDateTime(self
.startDate
), self
.getId(), str(e
)))
2944 except Exception, e2
:
2945 Logger
.get('Conference').error("Exception while notifying a start time change: %s (origin: %s)"%(str(e2
), str(e
)))
2947 def getStartDate(self
):
2948 """returns (datetime) the starting date of the conference"""
2949 return self
.startDate
2951 ###################################
2952 # Fermi timezone awareness #
2953 ###################################
2955 def getAdjustedStartDate(self
,tz
=None):
2957 tz
= self
.getTimezone()
2958 if tz
not in all_timezones
:
2960 return self
.getStartDate().astimezone(timezone(tz
))
2962 ###################################
2963 # Fermi timezone awareness(end) #
2964 ###################################
2966 def setScreenStartDate(self
, date
):
2967 if date
== self
.getStartDate():
2969 self
._screenStartDate
= date
2970 self
.notifyModification()
2972 def getScreenStartDate(self
):
2974 date
= self
._screenStartDate
2976 date
= self
._screenStartDate
= None
2980 return self
.getStartDate()
2982 def getAdjustedScreenStartDate(self
, tz
=None):
2984 tz
= self
.getTimezone()
2985 return self
.getScreenStartDate().astimezone(timezone(tz
))
2987 def calculateDayStartTime(self
, day
):
2988 """returns (date) the start date of the conference on a given day
2989 day is a tz aware datetime"""
2990 if self
.getStartDate().astimezone(day
.tzinfo
).date() == day
.date():
2991 return self
.getStartDate().astimezone(day
.tzinfo
)
2992 return self
.getSchedule().calculateDayStartDate(day
)
2994 def verifyEndDate(self
, edate
):
2995 if edate
<self
.getStartDate():
2996 raise TimingError( _("End date cannot be before the start date"), _("Event"))
2997 if self
.getSchedule().hasEntriesAfter(edate
):
2998 raise TimingError(_("Cannot change end date to %s: some entries in the timetable would be outside this date (%s)") % (edate
,self
.getSchedule().getEntries()[-1].getStartDate()), _("Event"))
3000 def setEndDate(self
, eDate
, check
= 1, index
= True, notifyObservers
= True):
3001 """ Changes the current conference end date/time to the one specified by the parameters.
3003 if not eDate
.tzname():
3004 raise MaKaCError("date should be timezone aware")
3005 if eDate
== self
.getEndDate():
3007 if eDate
.year
< 1900:
3008 eDate
= datetime(1900,eDate
.month
,eDate
.day
,eDate
.hour
,eDate
.minute
)
3010 self
.verifyEndDate(eDate
)
3014 oldEdate
= self
.endDate
3015 self
.endDate
= eDate
3016 #datetime object is non-mutable so we must "force" the modification
3017 # otherwise ZODB won't be able to notice the change
3018 self
.notifyModification()
3022 #if everything went well, we notify the observers that the start date has changed
3025 self
._notify
('endDateChanged', {'newDate': eDate
, 'oldDate': oldEdate
})
3026 except Exception, e
:
3028 Logger
.get('Conference').error("Exception while notifying the observer of a end date change from %s to %s for conference %s: " %
3029 (formatDateTime(oldEdate
), formatDateTime(eDate
), self
.getId(), str(e
)))
3030 except Exception, e2
:
3031 Logger
.get('Conference').error("Exception while notifying a end date change: %s (origin: %s)" % (str(e2
), str(e
)))
3034 def setEndTime(self
, hours
= 0, minutes
= 0, notifyObservers
= True):
3035 """ Changes the current conference end time (not date) to the one specified by the parameters.
3037 edate
= self
.getEndDate()
3038 self
.endDate
= datetime( edate
.year
, edate
.month
, edate
.day
, int(hours
), int(minutes
) )
3039 self
.verifyEndDate(self
.endDate
)
3040 self
.notifyModification()
3042 #if everything went well, we notify the observers that the start date has changed
3045 self
._notify
('endTimeChanged', edate
)
3046 #for observer in self.getObservers():
3047 except Exception, e
:
3048 #observer.notifyEventDateChanges(None, None, edate, self.endDate)
3050 Logger
.get('Conference').error("Exception while notifying the observer of a end timet change from %s to %s for conference %s: %s" %
3051 (formatDateTime(edate
), formatDateTime(self
.endDate
), self
.getId(), str(e
)))
3052 except Exception, e2
:
3053 Logger
.get('Conference').error("Exception while notifying a end time change: %s (origin: %s)"%(str(e2
), str(e
)))
3055 def getEndDate(self
):
3056 """returns (datetime) the ending date of the conference"""
3059 ##################################
3060 # Fermi timezone awareness #
3061 ##################################
3063 def getAdjustedEndDate(self
,tz
=None):
3065 tz
= self
.getTimezone()
3066 if tz
not in all_timezones
:
3068 return self
.getEndDate().astimezone(timezone(tz
))
3070 ##################################
3071 # Fermi timezone awareness(end) #
3072 ##################################
3074 def setScreenEndDate(self
, date
):
3075 if date
== self
.getEndDate():
3077 self
._screenEndDate
= date
3078 self
.notifyModification()
3080 def getScreenEndDate(self
):
3082 date
= self
._screenEndDate
3084 date
= self
._screenEndDate
= None
3088 return self
.getEndDate()
3090 def getAdjustedScreenEndDate(self
, tz
=None):
3092 tz
= self
.getTimezone()
3093 return self
.getScreenEndDate().astimezone(timezone(tz
))
3095 def isEndDateAutoCal( self
):
3096 """Says whether the end date has been explicitely set for the session
3097 or it must be calculated automatically
3099 return self
._endDateAutoCal
3101 ####################################
3102 # Fermi timezone awareness #
3103 ####################################
3104 def setTimezone(self
, tz
):
3106 oldTimezone
= self
.timezone
3107 except AttributeError:
3110 #for observer in self.getObservers():
3112 #observer.notifyTimezoneChange(oldTimezone, tz)
3113 self
._notify
('timezoneChanged', oldTimezone
)
3114 except Exception, e
:
3116 Logger
.get('Conference').error("Exception while notifying the observer of a timezone change from %s to %s for conference %s: %s" %
3117 (str(oldTimezone
), str(tz
), self
.getId(), str(e
)))
3118 except Exception, e2
:
3119 Logger
.get('Conference').error("Exception while notifying a timezone change: %s (origin: %s)"%(str(e2
), str(e
)))
3121 def getTimezone(self
):
3123 return self
.timezone
3127 def moveToTimezone(self
, tz
):
3128 if self
.getTimezone() == tz
:
3130 sd
=self
.getAdjustedStartDate()
3131 ed
=self
.getAdjustedEndDate()
3132 self
.setTimezone(tz
)
3134 sDate
= timezone(tz
).localize(datetime(sd
.year
, \
3139 eDate
= timezone(tz
).localize(datetime(ed
.year
, \
3144 except ValueError,e
:
3145 raise MaKaCError("Error moving the timezone: %s"%e)
3146 self
.setDates( sDate
.astimezone(timezone('UTC')), \
3147 eDate
.astimezone(timezone('UTC')),
3152 ####################################
3153 # Fermi timezone awareness(end) #
3154 ####################################
3157 """returns (String) the title of the conference"""
3160 def setTitle(self
, title
):
3161 """changes the current title of the conference to the one specified"""
3162 oldTitle
= self
.title
3165 self
.cleanCategoryCache()
3166 self
.notifyModification()
3168 #we notify the observers that the conference's title has changed
3170 self
._notify
('eventTitleChanged', oldTitle
, title
)
3171 except Exception, e
:
3172 Logger
.get('Conference').exception("Exception while notifying the observer of a conference title change for conference %s: %s" %
3173 (self
.getId(), str(e
)))
3176 def getDescription(self
):
3177 """returns (String) the description of the conference"""
3178 return self
.description
3180 def setDescription(self
, desc
):
3181 """changes the current description of the conference"""
3182 self
.description
= desc
3183 self
.notifyModification()
3185 def getSupportEmail(self
, returnNoReply
=False, caption
=False):
3187 Returns the support email address associated with the conference
3188 :param returnNoReply: Return no-reply address in case there's no support e-mail (default True)
3189 :type returnNoReply: bool
3193 if self
._supportEmail
:
3195 except AttributeError:
3196 self
._supportEmail
= ""
3197 if self
._supportEmail
.strip() == "" and returnNoReply
:
3198 # In case there's no conference support e-mail, return the no-reply
3199 # address, and the 'global' support e-mail if there isn't one
3200 return Config
.getInstance().getNoReplyEmail()
3202 supportCaption
= self
.getDisplayMgr().getSupportEmailCaption()
3204 if caption
and supportCaption
:
3205 return '"%s" <%s>' % (supportCaption
, self
._supportEmail
)
3207 return self
._supportEmail
3209 def setSupportEmail( self
, newSupportEmail
):
3210 self
._supportEmail
= newSupportEmail
.strip()
3212 def hasSupportEmail( self
):
3214 if self
._supportEmail
:
3216 except AttributeError, e
:
3217 self
._supportEmail
= ""
3218 return self
._supportEmail
!= "" and self
._supportEmail
!= None
3220 def getChairmanText( self
):
3222 if self
.chairmanText
:
3224 except AttributeError, e
:
3225 self
.chairmanText
= ""
3226 return self
.chairmanText
3228 def setChairmanText( self
, newText
):
3229 self
.chairmanText
= newText
.strip()
3231 def appendChairmanText( self
, newText
):
3232 self
.setChairmanText( "%s, %s"%(self
.getChairmanText(), newText
.strip()) )
3233 self
._chairGen
=Counter()
3236 def _resetChairs(self
):
3240 except AttributeError:
3242 for oc
in self
.chairmans
:
3243 newChair
=ConferenceChair()
3244 newChair
.setDataFromAvatar(oc
)
3245 self
._addChair
(newChair
)
3247 def getChairList(self
):
3248 """Method returning a list of the conference chairmans (Avatars)
3253 def _addChair(self
,newChair
):
3254 for chair
in self
._chairs
:
3255 if newChair
.getEmail() != "" and newChair
.getEmail() == chair
.getEmail():
3260 except AttributeError:
3261 self
._chairGen
=Counter()
3262 id = newChair
.getId()
3264 id=int(self
._chairGen
.newCount())
3265 if isinstance(newChair
,ConferenceChair
):
3266 newChair
.includeInConference(self
,id)
3267 self
._chairs
.append(newChair
)
3268 if isinstance(newChair
, MaKaC
.user
.Avatar
):
3269 newChair
.linkTo(self
, "chair")
3270 self
.notifyModification()
3272 def addChair(self
,newChair
):
3273 """includes the specified user in the list of conference
3276 self
._addChair
(newChair
)
3278 def removeChair(self
,chair
):
3279 """removes the specified user from the list of conference
3282 if chair
not in self
._chairs
:
3284 self
._chairs
.remove(chair
)
3285 if isinstance(chair
, MaKaC
.user
.Avatar
):
3286 chair
.unlinkTo(self
, "chair")
3288 self
.notifyModification()
3290 def recoverChair(self
, ch
):
3294 def getChairById(self
,id):
3296 for chair
in self
._chairs
:
3297 if chair
.getId()==id:
3301 def getAllSessionsConvenerList(self
) :
3303 for session
in self
.getSessionList() :
3304 for convener
in session
.getConvenerList() :
3305 key
= convener
.getEmail()+" "+convener
.getFirstName().lower()+" "+convener
.getFamilyName().lower()
3306 dictionary
.setdefault(key
, set()).add(convener
)
3307 for slot
in session
.getSlotList():
3308 for convener
in slot
.getConvenerList() :
3309 key
= convener
.getEmail()+" "+convener
.getFirstName().lower()+" "+convener
.getFamilyName().lower()
3310 dictionary
.setdefault(key
, set()).add(convener
)
3314 def getContactInfo(self
):
3315 return self
.contactInfo
3317 def setContactInfo(self
, contactInfo
):
3318 self
.contactInfo
= contactInfo
3319 self
.notifyModification()
3321 def getLocationParent( self
):
3323 Returns the object from which the room/location
3324 information should be inherited.
3325 For Conferences, it's None, since they can't inherit
3330 def getLocation( self
):
3331 return self
.getOwnLocation()
3333 def getRoom( self
):
3334 return self
.getOwnRoom()
3336 def getLocationList(self
):
3337 """Method returning a list of "location" objects which contain the
3338 information about the different places the conference is gonna
3343 def getFavoriteRooms(self
):
3345 roomList
.extend(self
.getRoomList())
3346 #roomList.extend(map(lambda x: x._getName(), self.getBookedRooms()))
3350 def addLocation(self
, newPlace
):
3351 self
.places
.append( newPlace
)
3352 self
.notifyModification()
3354 def setAccessKey(self
, accessKey
=""):
3355 """sets the access key of the conference"""
3356 self
._accessKey
= accessKey
3357 self
.notifyModification()
3359 def getAccessKey(self
):
3361 return self
._accessKey
3362 except AttributeError:
3363 self
._accessKey
= ""
3364 return self
._accessKey
3366 def setModifKey(self
, modifKey
=""):
3367 """sets the modification key of the conference"""
3368 self
._modifKey
= modifKey
3369 self
.notifyModification()
3371 def getModifKey(self
):
3373 return self
._modifKey
3374 except AttributeError:
3376 return self
._modifKey
3378 def __generateNewSessionId( self
):
3379 """Returns a new unique identifier for the current conference sessions
3381 return str(self
.__sessionGenerator
.newCount())
3383 def addSession(self
,newSession
, check
= 2, id = None):
3384 """Adds a new session object to the conference taking care of assigning
3385 a new unique id to it
3389 1: check and raise error in case of problem
3390 2: check and adapt the owner dates"""
3392 if self
.hasSession(newSession
):
3394 if self
.getSchedule().isOutside(newSession
):
3396 MaKaCError( _("Cannot add this session (Start:%s - End:%s) Outside of the event's time table(Start:%s - End:%s)") % (newSession
.getStartDate(),newSession
.getEndDate(),self
.getSchedule().getStartDate(), self
.getSchedule().getEndDate()),"Event")
3398 if self
.getSchedule().getStartDate() > newSession
.getStartDate():
3399 self
.setStartDate(newSession
.getStartDate())
3400 if self
.getSchedule().getEndDate() < newSession
.getEndDate():
3401 self
.setEndDate(newSession
.getEndDate())
3405 sessionId
=self
.__generateNewSessionId
()
3406 self
.sessions
[sessionId
]=newSession
3407 newSession
.includeInConference(self
,sessionId
)
3408 #keep the session coordinator index updated
3409 for sc
in newSession
.getCoordinatorList():
3410 self
.addSessionCoordinator(newSession
,sc
)
3411 self
.notifyModification()
3413 def hasSession(self
,session
):
3414 if session
!= None and session
.getConference()==self
and \
3415 self
.sessions
.has_key(session
.getId()):
3419 def removeSession(self
,session
, deleteContributions
=False):
3420 if self
.hasSession(session
):
3421 for sc
in session
.getCoordinatorList():
3422 self
.removeSessionCoordinator(session
,sc
)
3424 if deleteContributions
:
3425 for contrib
in session
.getContributionList():
3428 del self
.sessions
[session
.getId()]
3431 self
.notifyModification()
3433 def recoverSession(self
, session
, check
, isCancelled
):
3434 self
.addSession(session
, check
, session
.getId())
3435 session
.recover(isCancelled
)
3437 def getSessionById( self
, sessionId
):
3438 """Returns the session from the conference list corresponding to the
3439 unique session id specified
3441 return self
.sessions
.get(sessionId
,None)
3443 def getRoomList(self
):
3445 for session
in self
.sessions
.values():
3446 if session
.getRoom()!=None:
3447 roomname
= session
.getRoom().getName()
3448 if roomname
not in roomList
:
3449 roomList
.append(roomname
)
3452 def getSessionList( self
):
3453 """Retruns a list of the conference session objects
3455 return self
.sessions
.values()
3457 def getSessionListSorted( self
):
3458 """Retruns a sorted list of the conference sessions
3461 for entry
in self
.getSchedule().getEntries():
3462 if isinstance(entry
,LinkedTimeSchEntry
) and \
3463 isinstance(entry
.getOwner(),SessionSlot
):
3464 session
=entry
.getOwner().getSession()
3465 if session
not in res
:
3469 def getNumberOfSessions( self
):
3470 return len(self
.sessions
)
3472 def _generateNewContributionId( self
):
3473 """Returns a new unique identifier for the current conference
3476 return str(self
.__contribGenerator
.newCount())
3478 def genNewAbstractId(self
):
3479 return str(self
.__contribGenerator
.newCount())
3481 def syncContribCounter(self
):
3482 self
.__contribGenerator
.sync(self
.getAbstractMgr()._getOldAbstractCounter
())
3483 return self
.__contribGenerator
._getCount
()
3485 def addContribution(self
,newContrib
,id=""):
3486 """Adds a new contribution object to the conference taking care of
3487 assigning a new unique id to it
3489 if self
.hasContribution(newContrib
):
3491 if isinstance(newContrib
.getCurrentStatus(),ContribStatusWithdrawn
):
3492 raise MaKaCError( _("Cannot add a contribution which has been withdrawn"), _("Event"))
3493 if id is None or id=="":
3494 contribId
=self
._generateNewContributionId
()
3495 while self
.contributions
.has_key(contribId
):
3496 contribId
=self
._generateNewContributionId
()
3499 if self
.contributions
.has_key(contribId
):
3500 raise MaKaCError( _("Cannot add this contribution id:(%s) as it has already been used")%contribId
, _("Event"))
3501 newContrib
.includeInConference(self
,contribId
)
3502 self
.contributions
[contribId
]=newContrib
3503 for auth
in newContrib
.getAuthorList():
3504 self
.indexAuthor(auth
)
3505 for spk
in newContrib
.getSpeakerList():
3506 self
.indexSpeaker(spk
)
3507 for sub
in newContrib
.getSubmitterList():
3508 self
.addContribSubmitter(newContrib
,sub
)
3510 newContrib
._notify
('created', self
)
3511 self
.notifyModification()
3513 def hasContribution(self
,contrib
):
3514 return contrib
.getConference()==self
and \
3515 self
.contributions
.has_key(contrib
.getId())
3517 def removeContribution( self
, contrib
, callDelete
=True ):
3518 if not self
.contributions
.has_key( contrib
.getId() ):
3520 for sub
in contrib
.getSubmitterList()[:]:
3521 self
.removeContribSubmitter(contrib
,sub
)
3522 for auth
in contrib
.getPrimaryAuthorList()[:]:
3523 contrib
.removePrimaryAuthor(auth
)
3524 for auth
in contrib
.getCoAuthorList()[:]:
3525 contrib
.removeCoAuthor(auth
)
3526 for spk
in contrib
.getSpeakerList()[:]:
3527 contrib
.removeSpeaker(spk
)
3528 del self
.contributions
[ contrib
.getId() ]
3533 self
.notifyModification()
3535 def recoverContribution(self
, contrib
):
3536 self
.addContribution(contrib
, contrib
.getId())
3539 # Note: this kind of factories should never be used as they only allow to
3540 # create a single type of contributions
3541 def newContribution( self
, id=None ):
3542 """Creates and returns a new contribution object already added to the
3543 conference list (all its data is set to the default)
3546 self
.addContribution( c
, id )
3549 def getOwnContributionById( self
, id ):
3550 """Returns the contribution from the conference list corresponding to
3551 the unique contribution id specified
3553 if self
.contributions
.has_key( id ):
3554 return self
.contributions
[ id ]
3557 def getContributionById( self
, id ):
3558 """Returns the contribution corresponding to the id specified
3560 return self
.contributions
.get(str(id).strip(),None)
3562 def getContributionList(self
):
3563 """Returns a list of the conference contribution objects
3565 return self
.contributions
.values()
3567 def iterContributions(self
):
3568 return self
.contributions
.itervalues()
3570 def getContributionListWithoutSessions(self
):
3571 """Returns a list of the conference contribution objects which do not have a session
3573 return [c
for c
in self
.contributions
.values() if not c
.getSession()]
3575 def getContributionListSortedById(self
, includeWithdrawn
=True):
3576 """Returns a list of the conference contribution objects, sorted by their id
3578 contributions
= self
.contributions
.values()
3579 if not includeWithdrawn
:
3580 contributions
= filter(lambda c
: not isinstance(c
.getCurrentStatus(), ContribStatusWithdrawn
), contributions
)
3581 contributions
.sort(key
= lambda c
: c
.getId())
3582 return contributions
3584 def getNumberOfContributions(self
, only_scheduled
=False):
3586 return len(filter(lambda c
: c
.isScheduled(), self
.contributions
.itervalues()))
3588 return len(self
.contributions
)
3590 def getProgramDescription(self
):
3592 return self
.programDescription
3594 self
.programDescription
= ""
3595 return self
.programDescription
3597 def setProgramDescription(self
, txt
):
3598 self
.programDescription
= txt
3600 def _generateNewTrackId( self
):
3603 return str(self
.__programGenerator
.newCount())
3605 def addTrack( self
, newTrack
):
3608 #XXX: The conference program shoul be isolated in a separated object
3609 if newTrack
in self
.program
:
3612 trackId
= newTrack
.getId()
3613 if trackId
== "not assigned":
3614 trackId
= self
._generateNewTrackId
()
3615 self
.program
.append( newTrack
)
3616 newTrack
.setConference( self
)
3617 newTrack
.setId( trackId
)
3618 self
.notifyModification()
3620 def removeTrack( self
, track
):
3621 if track
in self
.program
:
3623 if track
in self
.program
:
3624 self
.program
.remove( track
)
3625 self
.notifyModification()
3627 def recoverTrack(self
, track
):
3628 self
.addTrack(track
)
3631 def newTrack( self
):
3638 def getTrackById( self
, id ):
3641 for track
in self
.program
:
3642 if track
.getId() == id.strip():
3646 def getTrackList( self
):
3651 def isLastTrack(self
,track
):
3654 return self
.getTrackPos(track
)==(len(self
.program
)-1)
3656 def isFirstTrack(self
,track
):
3659 return self
.getTrackPos(track
)==0
3661 def getTrackPos(self
,track
):
3664 return self
.program
.index(track
)
3666 def moveTrack(self
,track
,newPos
):
3669 self
.program
.remove(track
)
3670 self
.program
.insert(newPos
,track
)
3671 self
.notifyModification()
3673 def moveUpTrack(self
,track
):
3676 if self
.isFirstTrack(track
):
3678 newPos
=self
.getTrackPos(track
)-1
3679 self
.moveTrack(track
,newPos
)
3681 def moveDownTrack(self
,track
):
3684 if self
.isLastTrack(track
):
3686 newPos
=self
.getTrackPos(track
)+1
3687 self
.moveTrack(track
,newPos
)
3689 def _cmpTracks( self
, t1
, t2
):
3690 o1
= self
.program
.index(t1
)
3691 o2
= self
.program
.index(t2
)
3692 return cmp( o1
, o2
)
3694 def sortTrackList( self
, l
):
3695 """Sorts out a list of tracks according to the current programme order.
3705 res
.sort( self
._cmpTracks
)
3708 def canIPAccess( self
, ip
):
3709 if not self
.__ac
.canIPAccess( ip
):
3711 for owner
in self
.getOwnerList():
3712 if not owner
.canIPAccess(ip
):
3716 def requireDomain( self
, dom
):
3717 self
.__ac
.requireDomain( dom
)
3718 self
._notify
('accessDomainAdded', dom
)
3720 def freeDomain( self
, dom
):
3721 self
.__ac
.freeDomain( dom
)
3722 self
._notify
('accessDomainRemoved', dom
)
3724 def getDomainList( self
):
3725 return self
.__ac
.getRequiredDomainList()
3727 def isProtected( self
):
3728 """Tells whether a conference is protected for accessing or not
3730 return self
.__ac
.isProtected()
3732 def getAccessProtectionLevel( self
):
3733 return self
.__ac
.getAccessProtectionLevel()
3735 def isItselfProtected( self
):
3736 return self
.__ac
.isItselfProtected()
3738 def hasAnyProtection( self
):
3739 """Tells whether a conference has any kind of protection over it:
3740 access or domain protection.
3742 if self
.isProtected():
3744 if self
.getDomainList():
3747 if self
.getAccessProtectionLevel() == -1:
3750 for owner
in self
.getOwnerList():
3751 if owner
.hasAnyProtection():
3756 def hasProtectedOwner( self
):
3757 return self
.__ac
._getFatherProtection
()
3759 def setProtection( self
, private
):
3761 Allows to change the conference access protection
3764 oldValue
= 1 if self
.isProtected() else -1
3766 self
.__ac
.setProtection( private
)
3767 self
.updateFullyPublic()
3768 self
.cleanCategoryCache()
3770 if oldValue
!= private
:
3772 self
._notify
('protectionChanged', oldValue
, private
)
3774 def grantAccess( self
, prin
):
3775 self
.__ac
.grantAccess( prin
)
3776 if isinstance(prin
, MaKaC
.user
.Avatar
):
3777 prin
.linkTo(self
, "access")
3779 def revokeAccess( self
, prin
):
3780 self
.__ac
.revokeAccess( prin
)
3781 if isinstance(prin
, MaKaC
.user
.Avatar
):
3782 prin
.unlinkTo(self
, "access")
3784 def canView( self
, aw
):
3785 """tells whether the specified access wrappers has access to the current
3786 object or any of its parts"""
3787 if self
.canAccess( aw
):
3789 for session
in self
.getSessionList():
3790 if session
.canView( aw
):
3792 for contrib
in self
.getContributionList():
3793 if contrib
.canView( aw
):
3797 def isAllowedToAccess( self
, av
):
3798 """tells if a user has privileges to access the current conference
3799 (independently that it is protected or not)
3803 if (av
in self
.getChairList()) or (self
.__ac
.canUserAccess( av
)) or (self
.canUserModify( av
)):
3806 # if the conference is not protected by itself
3807 if not self
.isItselfProtected():
3808 # then inherit behavior from parent category
3809 for owner
in self
.getOwnerList():
3810 if owner
.isAllowedToAccess( av
):
3813 # track coordinators are also allowed to access the conference
3814 for track
in self
.getTrackList():
3815 if track
.isCoordinator( av
):
3818 # paper reviewing team should be also allowed to access
3819 if self
.getConfPaperReview().isInReviewingTeam(av
):
3822 # video services managers are also allowed to access the conference
3823 if PluginsHolder().hasPluginType("Collaboration"):
3824 if self
.getCSBookingManager().isPluginManagerOfAnyPlugin(av
):
3826 from MaKaC
.webinterface
.rh
.collaboration
import RCCollaborationAdmin
, RCCollaborationPluginAdmin
3827 if RCCollaborationAdmin
.hasRights(user
=av
) or \
3828 RCCollaborationPluginAdmin
.hasRights(user
=av
, plugins
='any'):
3833 def canAccess( self
, aw
):
3834 """Tells whether an access wrapper is allowed to access the current
3835 conference: when the conference is protected, only if the user is a
3836 chair or is granted to access the conference, when the client ip is
3839 # Allow harvesters (Invenio, offline cache) to access
3841 if self
.__ac
.isHarvesterIP(aw
.getIP()):
3844 # Managers have always access
3845 if self
.canUserModify(aw
.getUser()):
3848 if self
.isProtected():
3849 if self
.isAllowedToAccess( aw
.getUser() ):
3852 return self
.canKeyAccess(aw
)
3854 # Domain control is triggered just for PUBLIC events
3855 return self
.canIPAccess(aw
.getIP())
3857 def canKeyAccess( self
, aw
, key
=None ):
3858 sess
= aw
.getSession()
3859 accessKey
= self
.getAccessKey()
3860 if accessKey
!= "" and sess
:
3861 if key
and key
== accessKey
:
3863 keys
= sess
.getVar("accessKeys")
3865 if keys
.has_key(self
.getUniqueId()):
3866 if keys
[self
.getUniqueId()] == accessKey
:
3870 def canKeyModify( self
, aw
):
3871 sess
= aw
.getSession()
3872 modifKey
= self
.getModifKey()
3873 if modifKey
!= "" and sess
:
3874 keys
= sess
.getVar("modifKeys")
3876 if keys
.has_key(self
.id):
3877 if keys
[self
.id] == modifKey
:
3881 def grantModification( self
, prin
, sendEmail
=True ):
3883 if isinstance(prin
, ConferenceChair
):
3884 email
= prin
.getEmail()
3885 elif isinstance(prin
, str):
3891 results
=ah
.match({"email":email
}, exact
=1)
3892 #No registered user in Indico with that email
3893 if len(results
) == 0:
3894 self
.__ac
.grantModificationEmail(email
)
3895 if sendEmail
and isinstance(prin
, ConferenceChair
):
3896 notif
= pendingQueues
._PendingConfManagerNotification
( [prin
] )
3897 mail
.GenericMailer
.sendAndLog( notif
, self
.getConference() )
3898 #The user is registered in Indico and is activated as well
3899 elif len(results
) == 1 and results
[0] is not None and results
[0].isActivated():
3900 self
.__ac
.grantModification(results
[0])
3901 results
[0].linkTo(self
, "manager")
3903 self
.__ac
.grantModification( prin
)
3904 if isinstance(prin
, MaKaC
.user
.Avatar
):
3905 prin
.linkTo(self
, "manager")
3907 def revokeModification( self
, prin
):
3908 self
.__ac
.revokeModification( prin
)
3909 if isinstance(prin
, MaKaC
.user
.Avatar
):
3910 prin
.unlinkTo(self
, "manager")
3912 def canUserModify( self
, av
):
3915 if ( av
== self
.getCreator()) or self
.getAccessController().canModify( av
):
3917 for owner
in self
.getOwnerList():
3918 if owner
.canUserModify( av
):
3922 def canModify( self
, aw
):
3923 """Tells whether an access wrapper is allowed to modify the current
3924 conference: only if the user is granted to modify the conference and
3925 he is accessing from an IP address which is not restricted.
3927 return self
.canUserModify( aw
.getUser() ) or self
.canKeyModify( aw
)
3929 def getManagerList( self
):
3930 return self
.__ac
.getModifierList()
3932 def addToRegistrars(self
, av
):
3933 self
.getRegistrarList().append(av
)
3934 self
.notifyModification()
3935 if isinstance(av
, MaKaC
.user
.Avatar
):
3936 av
.linkTo(self
, "registrar")
3938 def removeFromRegistrars(self
, av
):
3939 self
.getRegistrarList().remove(av
)
3940 self
.notifyModification()
3941 if isinstance(av
, MaKaC
.user
.Avatar
):
3942 av
.unlinkTo(self
, "registrar")
3944 def isRegistrar(self
, av
):
3948 return av
in self
.getRegistrarList()
3949 except AttributeError:
3952 def getRegistrarList(self
):
3954 return self
.__registrars
3955 except AttributeError:
3956 self
.__registrars
= []
3957 return self
.__registrars
3959 def canManageRegistration(self
, av
):
3960 return self
.isRegistrar(av
) or self
.canUserModify(av
)
3962 def getAllowedToAccessList( self
):
3963 return self
.__ac
.getAccessList()
3965 def addMaterial( self
, newMat
):
3966 newMat
.setId( str(self
.__materialGenerator
.newCount()) )
3967 newMat
.setOwner( self
)
3968 self
.materials
[ newMat
.getId() ] = newMat
3969 self
.notifyModification()
3971 def removeMaterial( self
, mat
):
3972 if mat
.getId() in self
.materials
.keys():
3974 self
.materials
[mat
.getId()].setOwner(None)
3975 del self
.materials
[ mat
.getId() ]
3976 self
.notifyModification()
3977 elif mat
.getId().lower() == 'paper':
3979 self
.notifyModification()
3980 elif mat
.getId().lower() == 'slides':
3982 self
.notifyModification()
3983 elif mat
.getId().lower() == 'minutes':
3984 self
.removeMinutes()
3985 self
.notifyModification()
3986 elif mat
.getId().lower() == 'video':
3988 self
.notifyModification()
3989 elif mat
.getId().lower() == 'poster':
3991 self
.notifyModification()
3993 def recoverMaterial(self
, recMat
):
3994 # Id must already be set in recMat.
3995 recMat
.setOwner(self
)
3996 self
.materials
[recMat
.getId()] = recMat
3998 self
.notifyModification()
4000 def getMaterialRegistry(self
):
4002 Return the correct material registry for this type
4004 from MaKaC
.webinterface
.materialFactories
import ConfMFRegistry
4005 return ConfMFRegistry
4007 def getMaterialById( self
, matId
):
4008 if matId
.lower() == 'paper':
4009 return self
.getPaper()
4010 elif matId
.lower() == 'slides':
4011 return self
.getSlides()
4012 elif matId
.lower() == 'video':
4013 return self
.getVideo()
4014 elif matId
.lower() == 'poster':
4015 return self
.getPoster()
4016 elif matId
.lower() == 'minutes':
4017 return self
.getMinutes()
4018 elif self
.materials
.has_key(matId
):
4019 return self
.materials
[ matId
]
4022 def getMaterialList( self
):
4023 return self
.materials
.values()
4025 def getAllMaterialList( self
):
4026 l
= self
.getMaterialList()
4028 l
.append( self
.getPaper() )
4029 if self
.getSlides():
4030 l
.append( self
.getSlides() )
4032 l
.append( self
.getVideo() )
4033 if self
.getPoster():
4034 l
.append( self
.getPoster() )
4035 if self
.getMinutes():
4036 l
.append( self
.getMinutes() )
4037 l
.sort(lambda x
,y
: cmp(x
.getTitle(),y
.getTitle()))
4040 def _getMaterialFiles(self
, material
):
4042 Adaption of _getMaterialFiles in WPTPLConferenceDisplay for desired format, objects
4043 seemed mutually exclusive hence use of similar logic here specific to Conference.
4048 for res
in material
.getResourceList():
4050 ftype
= res
.getFileType()
4051 fname
= res
.getFileName()
4052 furl
= urlHandlers
.UHFileAccess
.getURL(res
)
4054 if fname
in processed
:
4055 fname
= "%s - %s" % (fname
, processed
.count(fname
))
4057 processed
.append(res
.getFileName())
4059 # If we are here then the resource is a Link object.
4060 fname
, ftype
, furl
= str(res
.getURL()), "link", str(res
.getURL())
4061 fdesc
= res
.getDescription()
4062 files
.append({'title': fname
,
4063 'description': fdesc
,
4068 def getAllMaterialDict(self
, child
=None):
4070 This method iterates through the children of the conference, creating
4071 a dictionary which maps type to material link URLs.
4074 child
= self
if child
is None else child
4077 node
['title'] = child
.getTitle()
4080 node
['type'] = child
.getType()
4082 # If we land here, it's a session which doesn't have 'getType'
4083 node
['type'] = 'session'
4085 node
['children'] = []
4086 node
['material'] = []
4088 if node
['type'] in ['conference', 'meeting']:
4089 for session
in child
.getSessionList():
4090 node
['children'].append(self
.getAllMaterialDict(session
))
4092 for contrib
in child
.getContributionList():
4093 node
['children'].append(self
.getAllMaterialDict(contrib
))
4095 for material
in child
.getAllMaterialList():
4096 files
= self
._getMaterialFiles
(material
)
4100 materialNode
['type'] = 'material'
4101 materialNode
['title'] = material
.getTitle()
4103 if material
.getTitle() != 'Minutes':
4104 materialNode
['title'] += ' - ' + f
['title']
4106 materialNode
['materialType'] = f
['type']
4107 materialNode
['url'] = str(f
['url'])
4109 node
['material'].append(materialNode
)
4113 def setPaper( self
, newPaper
):
4114 if self
.getPaper() != None:
4115 raise MaKaCError( _("The paper for this conference has already been set"), _("Conference"))
4117 self
.paper
.setOwner( self
)
4118 self
.notifyModification()
4120 def removePaper( self
):
4121 if self
.paper
is None:
4124 self
.paper
.setOwner(None)
4126 self
.notifyModification()
4128 def recoverPaper(self
, p
):
4132 def getPaper( self
):
4136 except AttributeError:
4140 def setSlides( self
, newSlides
):
4141 if self
.getSlides() != None:
4142 raise MaKaCError( _("The slides for this conference have already been set"), _("Conference"))
4143 self
.slides
=newSlides
4144 self
.slides
.setOwner( self
)
4145 self
.notifyModification()
4147 def removeSlides( self
):
4148 if self
.slides
is None:
4150 self
.slides
.delete()
4151 self
.slides
.setOwner( None )
4153 self
.notifyModification()
4155 def recoverSlides(self
, s
):
4159 def getSlides( self
):
4163 except AttributeError:
4167 def setVideo( self
, newVideo
):
4168 if self
.getVideo() != None:
4169 raise MaKaCError( _("The video for this conference has already been set"), _("Conference"))
4171 self
.video
.setOwner( self
)
4172 self
.notifyModification()
4174 def removeVideo( self
):
4175 if self
.getVideo() is None:
4178 self
.video
.setOwner(None)
4180 self
.notifyModification()
4182 def recoverVideo(self
, v
):
4186 def getVideo( self
):
4190 except AttributeError:
4194 def setPoster( self
, newPoster
):
4195 if self
.getPoster() != None:
4196 raise MaKaCError( _("the poster for this conference has already been set"), _("Conference"))
4197 self
.poster
=newPoster
4198 self
.poster
.setOwner( self
)
4199 self
.notifyModification()
4201 def removePoster( self
):
4202 if self
.getPoster() is None:
4204 self
.poster
.delete()
4205 self
.poster
.setOwner(None)
4207 self
.notifyModification()
4209 def recoverPoster(self
, p
):
4213 def getPoster( self
):
4217 except AttributeError:
4221 def setMinutes( self
, newMinutes
):
4222 if self
.getMinutes() != None:
4223 raise MaKaCError( _("The Minutes for this conference has already been set"))
4224 self
.minutes
=newMinutes
4225 self
.minutes
.setOwner( self
)
4226 self
.notifyModification()
4228 def createMinutes( self
):
4229 if self
.getMinutes() != None:
4230 raise MaKaCError( _("The minutes for this conference have already been created"), _("Conference"))
4231 self
.minutes
= Minutes()
4232 self
.minutes
.setOwner( self
)
4233 self
.notifyModification()
4236 def removeMinutes( self
):
4237 if self
.getMinutes() is None:
4239 self
.minutes
.delete()
4240 self
.minutes
.setOwner( None )
4242 self
.notifyModification()
4244 def recoverMinutes(self
, min):
4245 self
.removeMinutes() # To ensure that the current minutes are put in
4248 self
.minutes
.setOwner( self
)
4250 self
.notifyModification()
4253 def getMinutes( self
):
4258 except AttributeError, e
:
4262 def _setSchedule( self
, sch
=None ):
4263 self
.__schedule
=ConferenceSchedule(self
)
4264 for session
in self
.getSessionList():
4265 for slot
in session
.getSlotList():
4266 self
.__schedule
.addEntry(slot
.getConfSchEntry())
4268 def getSchedule( self
):
4270 if not self
.__schedule
:
4272 except AttributeError, e
:
4274 return self
.__schedule
4277 sch
= self
.getSchedule()
4279 sDate
= sch
.calculateStartDate()
4280 eDate
= sch
.calculateEndDate()
4281 self
.setStartDate(sDate
)
4282 self
.setEndDate(eDate
)
4284 def fitSlotsOnDay( self
, day
):
4285 for entry
in self
.getSchedule().getEntriesOnDay(day
) :
4286 if isinstance(entry
.getOwner(), SessionSlot
) :
4287 entry
.getOwner().fit()
4289 def getDisplayMgr(self
):
4291 Return the display manager for the conference
4293 from MaKaC
.webinterface
import displayMgr
4294 return displayMgr
.ConfDisplayMgrRegistery().getDisplayMgr(self
)
4296 def getDefaultStyle( self
):
4297 return self
.getDisplayMgr().getDefaultStyle()
4299 def clone( self
, startDate
, options
, eventManager
=None, userPerformingClone
= None ):
4300 # startDate must be in the timezone of the event (to avoid problems with daylight-saving times)
4301 cat
= self
.getOwnerList()[0]
4302 managing
= options
.get("managing",None)
4303 if managing
is not None:
4306 creator
= self
.getCreator()
4307 conf
= cat
.newConference(creator
)
4308 if managing
is not None :
4309 conf
.grantModification(managing
)
4310 conf
.setTitle(self
.getTitle())
4311 conf
.setDescription(self
.getDescription())
4312 conf
.setTimezone(self
.getTimezone())
4313 for loc
in self
.getLocationList():
4315 conf
.addLocation(loc
.clone())
4316 if self
.getRoom() is not None:
4317 conf
.setRoom(self
.getRoom().clone())
4318 startDate
= timezone(self
.getTimezone()).localize(startDate
).astimezone(timezone('UTC'))
4319 timeDelta
= startDate
- self
.getStartDate()
4320 endDate
= self
.getEndDate() + timeDelta
4321 conf
.setDates( startDate
, endDate
, moveEntries
=1 )
4322 conf
.setContactInfo(self
.getContactInfo())
4323 conf
.setChairmanText(self
.getChairmanText())
4324 conf
.setVisibility(self
.getVisibility())
4325 conf
.setSupportEmail(self
.getSupportEmail())
4326 conf
.setReportNumberHolder(self
.getReportNumberHolder().clone(self
))
4327 for ch
in self
.getChairList():
4328 conf
.addChair(ch
.clone())
4329 ContextManager
.setdefault("clone.unique_id_map", {})[self
.getUniqueId()] = conf
.getUniqueId()
4331 from MaKaC
.webinterface
import displayMgr
4332 selfDispMgr
=displayMgr
.ConfDisplayMgrRegistery().getDisplayMgr(self
)
4333 selfDispMgr
.clone(conf
)
4334 # Contribution Types' List (main detailes of the conference)
4335 for t
in self
.getContribTypeList() :
4336 conf
.addContribType(t
.clone(conf
))
4337 for item
in self
.getSections() :
4338 conf
._sections
.append(item
)
4339 if options
.get("sessions", False):
4340 for entry
in self
.getSchedule().getEntries():
4341 if isinstance(entry
,BreakTimeSchEntry
):
4342 conf
.getSchedule().addEntry(entry
.clone(conf
))
4343 db_root
= DBMgr
.getInstance().getDBConnection().root()
4344 if db_root
.has_key( "webfactoryregistry" ):
4345 confRegistry
= db_root
["webfactoryregistry"]
4347 confRegistry
= OOBTree
.OOBTree()
4348 db_root
["webfactoryregistry"] = confRegistry
4350 # if the event is a meeting or a lecture
4351 if confRegistry
.get(str(self
.getId()), None) is not None :
4353 confRegistry
[str(conf
.getId())] = confRegistry
[str(self
.getId())]
4354 # if it's a conference, no web factory is needed
4355 # Tracks in a conference
4356 if options
.get("tracks",False) :
4357 for tr
in self
.getTrackList() :
4358 conf
.addTrack(tr
.clone(conf
))
4359 # Meetings' and conferences' sessions cloning
4360 if options
.get("sessions",False) :
4361 for s
in self
.getSessionList() :
4362 newSes
= s
.clone(timeDelta
, conf
, options
)
4363 ContextManager
.setdefault("clone.unique_id_map", {})[s
.getUniqueId()] = newSes
.getUniqueId()
4364 conf
.addSession(newSes
)
4365 # Materials' cloning
4366 if options
.get("materials",False) :
4367 for m
in self
.getMaterialList() :
4368 conf
.addMaterial(m
.clone(conf
))
4369 if self
.getPaper() is not None:
4370 conf
.setPaper(self
.getPaper().clone(conf
))
4371 if self
.getSlides() is not None:
4372 conf
.setSlides(self
.getSlides().clone(conf
))
4373 if self
.getVideo() is not None:
4374 conf
.setVideo(self
.getVideo().clone(conf
))
4375 if self
.getPoster() is not None:
4376 conf
.setPoster(self
.getPoster().clone(conf
))
4377 if self
.getMinutes() is not None:
4378 conf
.setMinutes(self
.getMinutes().clone(conf
))
4379 # access and modification keys
4380 if options
.get("keys", False) :
4381 conf
.setAccessKey(self
.getAccessKey())
4382 conf
.setModifKey(self
.getModifKey())
4383 # Access Control cloning
4384 if options
.get("access",False) :
4385 conf
.setProtection(self
.getAccessController()._getAccessProtection
())
4386 for mgr
in self
.getManagerList() :
4387 conf
.grantModification(mgr
)
4388 for user
in self
.getAllowedToAccessList() :
4389 conf
.grantAccess(user
)
4390 for right
in self
.getSessionCoordinatorRights():
4391 conf
.addSessionCoordinatorRight(right
)
4392 for domain
in self
.getDomainList():
4393 conf
.requireDomain(domain
)
4394 # conference's registration form
4395 if options
.get("registration",False) :
4396 conf
.setRegistrationForm(self
.getRegistrationForm().clone(conf
))
4398 # conference's evaluation
4399 if options
.get("evaluation",False) :
4400 #Modify this, if you have now many evaluations.
4401 #You will have to clone every evaluations of this conference.
4402 conf
.setEvaluations([self
.getEvaluation().clone(conf
)])
4404 #conference's abstracts
4405 if options
.get("abstracts",False) :
4406 conf
.abstractMgr
= self
.abstractMgr
.clone(conf
)
4407 # conference's alerts
4408 if options
.get("alerts",False) :
4409 for alarm
in self
.getAlarmList() :
4410 # for absoulte alarms, only clone alarms that will happen in the future
4411 if alarm
._relative
is not None or alarm
.getStartOn() > nowutc():
4412 # .clone takes care of enqueuing it
4414 # Meetings' and conferences' contributions cloning
4415 if options
.get("contributions",False) :
4416 sch
= conf
.getSchedule()
4417 for cont
in self
.getContributionList():
4418 if cont
.getSession() is None :
4420 nc
= cont
.clone(conf
, options
, timeDelta
)
4421 conf
.addContribution(nc
)
4422 if cont
.isScheduled() :
4423 sch
.addEntry(nc
.getSchEntry())
4424 ContextManager
.setdefault("clone.unique_id_map", {})[cont
.getUniqueId()] = nc
.getUniqueId()
4425 elif cont
.isScheduled():
4426 # meetings...only scheduled
4427 nc
= cont
.clone(conf
, options
, timeDelta
)
4428 conf
.addContribution(nc
)
4429 sch
.addEntry(nc
.getSchEntry())
4430 ContextManager
.setdefault("clone.unique_id_map", {})[cont
.getUniqueId()] = nc
.getUniqueId()
4431 # Participants' module settings and list cloning
4432 if options
.get("participants",False) :
4433 self
.getParticipation().clone(conf
, options
, eventManager
)
4434 conf
.notifyModification()
4436 #we inform the plugins in case they want to add anything to the new conference
4437 self
._notify
('cloneEvent', {'conf': conf
, 'user': userPerformingClone
, 'options': options
})
4440 def newAlarm(self
, when
, enqueue
=True):
4442 if type(when
) == timedelta
:
4449 confRelId
= self
._getNextAlarmId
()
4450 al
= tasks
.AlarmTask(self
, confRelId
,
4451 startDateTime
=dtStart
,
4454 self
.addAlarm(al
, enqueue
)
4457 def removeAlarm(self
, alarm
):
4458 confRelId
= alarm
.getConfRelativeId()
4460 if confRelId
in self
.alarmList
:
4461 del self
.alarmList
[confRelId
]
4467 raise Exception("alarm not in list!")
4469 def _getNextAlarmId(self
):
4470 return self
.__alarmCounter
.newCount()
4472 def addAlarm(self
, alarm
, enqueue
= True):
4477 self
.alarmList
[alarm
.getConfRelativeId()] = alarm
4480 def recoverAlarm(self
, alarm
):
4481 self
.addAlarm(alarm
)
4485 def getAlarmList(self
):
4486 return self
.alarmList
.values()
4488 def getAlarmById(self
, id):
4489 """For given id returns corresponding Alarm or None if not found."""
4490 return self
.alarmList
.get(id, None)
4492 def getCoordinatedTracks( self
, av
):
4493 """Returns a list with the tracks for which a user is coordinator.
4496 if self
._trackCoordinators
:
4498 except AttributeError:
4499 self
._trackCoordinators
= TCIndex()
4500 self
.notifyModification()
4501 return self
._trackCoordinators
.getTracks( av
)
4503 def addTrackCoordinator( self
, track
, av
):
4504 """Makes a user become coordinator for a track.
4507 if self
._trackCoordinators
:
4509 except AttributeError:
4510 self
._trackCoordinators
= TCIndex()
4511 self
.notifyModification()
4512 if track
in self
.program
:
4513 track
.addCoordinator( av
)
4514 self
._trackCoordinators
.indexCoordinator( av
, track
)
4515 self
.notifyModification()
4517 def removeTrackCoordinator( self
, track
, av
):
4518 """Removes a user as coordinator for a track.
4521 if self
._trackCoordinators
:
4523 except AttributeError:
4524 self
._trackCoordinators
= TCIndex()
4525 self
.notifyModification()
4526 if track
in self
.program
:
4527 track
.removeCoordinator( av
)
4528 self
._trackCoordinators
.unindexCoordinator( av
, track
)
4529 self
.notifyModification()
4531 def _rebuildAuthorIndex(self
):
4532 self
._authorIdx
=AuthorIndex()
4533 for contrib
in self
.getContributionList():
4534 if not isinstance(contrib
.getCurrentStatus(),ContribStatusWithdrawn
):
4535 for auth
in contrib
.getAuthorList():
4536 self
._authorIdx
.index(auth
)
4538 def getAuthorIndex(self
):
4542 except AttributeError:
4543 self
._rebuildAuthorIndex
()
4544 return self
._authorIdx
4546 def indexAuthor(self
,auth
):
4547 c
=auth
.getContribution()
4548 if c
.isAuthor(auth
):
4549 if not isinstance(c
.getCurrentStatus(),ContribStatusWithdrawn
):
4550 self
.getAuthorIndex().index(auth
)
4551 if c
.isPrimaryAuthor(auth
):
4552 self
._getPrimAuthIndex
().index(auth
)
4554 def unindexAuthor(self
,auth
):
4555 c
=auth
.getContribution()
4556 if c
.isAuthor(auth
):
4557 self
.getAuthorIndex().unindex(auth
)
4558 if c
.isPrimaryAuthor(auth
):
4559 self
._getPrimAuthIndex
().unindex(auth
)
4561 def _rebuildSpeakerIndex(self
):
4562 self
._speakerIdx
=AuthorIndex()
4563 for contrib
in self
.getContributionList():
4564 if not isinstance(contrib
.getCurrentStatus(),ContribStatusWithdrawn
):
4565 for auth
in contrib
.getSpeakerList():
4566 self
._speakerIdx
.index(auth
)
4567 for subcontrib
in contrib
.getSubContributionList():
4568 for auth
in subcontrib
.getSpeakerList():
4569 self
._speakerIdx
.index(auth
)
4571 def getSpeakerIndex(self
):
4573 if self
._speakerIdx
:
4575 except AttributeError:
4576 self
._rebuildSpeakerIndex
()
4577 return self
._speakerIdx
4579 def indexSpeaker(self
,auth
):
4580 c
=auth
.getContribution()
4581 if not isinstance(c
.getCurrentStatus(),ContribStatusWithdrawn
):
4582 self
.getSpeakerIndex().index(auth
)
4584 def unindexSpeaker(self
,auth
):
4585 c
=auth
.getContribution()
4586 if c
and not isinstance(c
.getCurrentStatus(),ContribStatusWithdrawn
):
4587 self
.getSpeakerIndex().unindex(auth
)
4589 def getRegistrationForm(self
):
4591 if self
._registrationForm
is None:
4592 self
._registrationForm
= registration
.RegistrationForm(self
)
4593 except AttributeError,e
:
4594 self
._registrationForm
= registration
.RegistrationForm(self
)
4595 return self
._registrationForm
4597 def setRegistrationForm(self
,rf
):
4598 self
._registrationForm
= rf
4599 rf
.setConference(self
)
4601 def removeRegistrationForm(self
):
4603 self
._registrationForm
.delete()
4604 self
._registrationForm
.setConference(None)
4605 self
._registrationForm
= None
4606 except AttributeError:
4607 self
._registrationForm
= None
4609 def recoverRegistrationForm(self
, rf
):
4610 self
.setRegistrationForm(rf
)
4613 def getEvaluation(self
, id=0):
4614 ############################################################################
4615 #For the moment only one evaluation per conference is used. #
4616 #In the future if there are more than one evaluation, modify this function.#
4617 ############################################################################
4618 """ Return the evaluation given by its ID or None if nothing found.
4620 id -- id of the wanted evaluation
4622 for evaluation
in self
.getEvaluations():
4623 if str(evaluation
.getId()) == str(id) :
4625 if HelperMaKaCInfo
.getMaKaCInfoInstance().isDebugActive():
4626 raise Exception(_("Error with id: expected '%s', found '%s'.")%(id, self
.getEvaluations()[0].getId()))
4628 return self
.getEvaluations()[0]
4630 def getEvaluations(self
):
4631 if not hasattr(self
, "_evaluations"):
4632 self
._evaluations
= [Evaluation(self
)]
4633 return self
._evaluations
4635 def setEvaluations(self
, evaluationsList
):
4636 self
._evaluations
= evaluationsList
4637 for evaluation
in self
._evaluations
:
4638 evaluation
.setConference(self
)
4640 def removeEvaluation(self
, evaluation
):
4641 """remove the given evaluation from its evaluations."""
4642 evaluations
= self
.getEvaluations()
4643 if evaluations
.count(evaluation
)>0:
4644 evaluations
.remove(evaluation
)
4645 evaluation
.removeReferences()
4646 self
.notifyModification()
4648 def removeAllEvaluations(self
):
4649 for evaluation
in self
.getEvaluations():
4650 evaluation
.removeReferences()
4651 self
._evaluations
= []
4652 self
.notifyModification()
4654 def _getEvaluationCounter(self
):
4655 if not hasattr(self
, "_evaluationCounter"):
4656 self
._evaluationCounter
= Counter()
4657 return self
._evaluationCounter
4659 ## Videoconference bookings related
4660 def getBookings(self
):
4664 except AttributeError, e
:
4666 self
.notifyModification()
4667 return self
._bookings
4669 def getBookingsList(self
, sort
= False):
4670 bl
= self
.getBookings().values()
4675 def _getBookingGenerator(self
):
4677 return self
._bookingGenerator
4678 except AttributeError, e
:
4679 self
._bookingGenerator
= Counter()
4680 return self
._bookingGenerator
4682 def getNewBookingId(self
):
4683 return str(self
._getBookingGenerator
().newCount())
4685 def addBooking(self
, bp
):
4686 if (bp
.getId() == ""):
4687 bp
.setId(self
.getNewBookingId())
4688 self
.getBookings()[bp
.getId()] = bp
4689 self
.notifyModification()
4691 def hasBooking(self
,booking
):
4692 return booking
.getConference()==self
and \
4693 self
.getBookings().has_key(booking
.getId())
4695 def removeBooking(self
, booking
):
4696 if self
.hasBooking(booking
):
4697 deletion
= booking
.deleteBooking()
4698 if deletion
[0] != 1:
4699 del self
.getBookings()[booking
.getId()]
4700 self
.notifyModification()
4703 def getBookingByType(self
, type):
4704 if self
.getBookings().has_key(type):
4705 return self
.getBookings()[type]
4708 def getBookingById(self
, id):
4709 if self
.getBookings().has_key(id):
4710 return self
.getBookings()[id]
4713 ## End of Videoconference bookings related
4715 def getModPay(self
):
4717 if self
._modPay
is None:
4718 self
._modPay
= epayment
.EPayment(self
)
4719 except AttributeError,e
:
4720 self
._modPay
= epayment
.EPayment(self
)
4723 def getRegistrants(self
):
4725 if self
._registrants
:
4727 except AttributeError, e
:
4728 self
._registrants
= {}
4729 self
.notifyModification()
4730 return self
._registrants
4732 def getRegistrantsByEmail(self
):
4734 if self
._registrantsByEmail
:
4736 except AttributeError, e
:
4737 self
._registrantsByEmail
= self
._createRegistrantsByEmail
()
4738 self
.notifyModification()
4739 return self
._registrantsByEmail
4741 def _createRegistrantsByEmail(self
):
4743 for r
in self
.getRegistrantsList():
4744 dicByEmail
[r
.getEmail()] = r
4747 def getRegistrantsList(self
, sort
= False):
4748 rl
= self
.getRegistrants().values()
4750 rl
.sort(registration
.Registrant
._cmpFamilyName
)
4753 def _getRegistrantGenerator(self
):
4755 return self
._registrantGenerator
4756 except AttributeError, e
:
4757 self
._registrantGenerator
= Counter()
4758 return self
._registrantGenerator
4760 def addRegistrant(self
, rp
):
4761 rp
.setId( str(self
._getRegistrantGenerator
().newCount()) )
4763 self
.getRegistrants()[rp
.getId()] = rp
4764 self
.notifyModification()
4766 def updateRegistrantIndexByEmail(self
, rp
, newEmail
):
4767 oldEmail
= rp
.getEmail()
4768 if oldEmail
!= newEmail
:
4769 if self
.getRegistrantsByEmail().has_key(oldEmail
):
4770 del self
.getRegistrantsByEmail()[oldEmail
]
4771 self
.getRegistrantsByEmail()[newEmail
] = rp
4772 self
.notifyModification()
4774 def hasRegistrant(self
,rp
):
4775 return rp
.getConference()==self
and \
4776 self
.getRegistrants().has_key(rp
.getId())
4778 def hasRegistrantByEmail(self
, email
):
4779 # Return true if there is someone with the email of the param "email"
4780 return self
.getRegistrantsByEmail().has_key(email
)
4782 def removeRegistrant(self
, id):
4783 part
= self
.getRegistrants()[id]
4784 self
._registrationForm
.notifyRegistrantRemoval(self
.getRegistrants()[id])
4785 del self
.getRegistrantsByEmail()[self
.getRegistrantById(id).getEmail()]
4786 del self
.getRegistrants()[id]
4787 if part
.getAvatar() is not None:
4788 part
.getAvatar().removeRegistrant(part
)
4789 TrashCanManager().add(part
)
4790 self
.notifyModification()
4792 def getRegistrantById(self
, id):
4793 if self
.getRegistrants().has_key(id):
4794 return self
.getRegistrants()[id]
4797 def _getPrimAuthIndex(self
):
4799 if self
._primAuthIdx
:
4801 except AttributeError:
4802 self
._primAuthIdx
=_PrimAuthIdx(self
)
4803 return self
._primAuthIdx
4805 def getContribsMatchingAuth(self
,query
,onlyPrimary
=True):
4806 if str(query
).strip()=="":
4807 return self
.getContributionList()
4808 res
=self
._getPrimAuthIndex
().match(query
)
4809 return [self
.getContributionById(id) for id in res
]
4811 def getCoordinatedSessions( self
, av
):
4812 """Returns a list with the sessions for which a user is coordinator.
4815 if self
._sessionCoordinators
:
4817 except AttributeError:
4818 self
._sessionCoordinators
= SCIndex()
4819 sessions
= self
._sessionCoordinators
.getSessions( av
)
4820 for session
in self
.getSessionList():
4821 if session
not in sessions
and av
!= None:
4822 for email
in av
.getEmails():
4823 if email
in session
.getCoordinatorEmailList():
4824 sessions
.append(session
)
4828 def getManagedSession( self
, av
):
4830 for session
in self
.getSessionList():
4833 for email
in av
.getEmails():
4834 if email
in session
.getAccessController().getModificationEmail():
4837 if av
in session
.getManagerList() or pending
:
4841 def addSessionCoordinator(self
,session
,av
):
4842 """Makes a user become coordinator for a session.
4845 if self
._sessionCoordinators
:
4847 except AttributeError:
4848 self
._sessionCoordinators
= SCIndex()
4849 if self
.sessions
.has_key(session
.getId()):
4850 session
.addCoordinator(av
)
4851 self
._sessionCoordinators
.index(av
,session
)
4853 def removeSessionCoordinator( self
, session
, av
):
4854 """Removes a user as coordinator for a session.
4857 if self
._sessionCoordinators
:
4859 except AttributeError:
4860 self
._sessionCoordinators
= SCIndex()
4861 if self
.sessions
.has_key(session
.getId()):
4862 session
.removeCoordinator( av
)
4863 self
._sessionCoordinators
.unindex(av
,session
)
4865 def _getSubmitterIdx(self
):
4867 return self
._submitterIdx
4868 except AttributeError:
4869 self
._submitterIdx
=SubmitterIndex()
4870 return self
._submitterIdx
4872 def addContribSubmitter(self
,contrib
,av
):
4873 self
._getSubmitterIdx
().index(av
,contrib
)
4875 def removeContribSubmitter(self
,contrib
,av
):
4876 self
._getSubmitterIdx
().unindex(av
,contrib
)
4878 def getContribsForSubmitter(self
,av
):
4879 return self
._getSubmitterIdx
().getContributions(av
)
4881 def getBOAConfig(self
):
4885 except AttributeError:
4886 self
._boa
=BOAConfig(self
)
4889 def getSessionCoordinatorRights(self
):
4891 if self
._sessionCoordinatorRights
:
4893 except AttributeError, e
:
4894 self
._sessionCoordinatorRights
= []
4895 self
.notifyModification()
4896 return self
._sessionCoordinatorRights
4898 def hasSessionCoordinatorRight(self
, right
):
4899 return right
in self
.getSessionCoordinatorRights()
4901 def addSessionCoordinatorRight(self
, right
):
4902 if SessionCoordinatorRights().hasRight(right
) and not self
.hasSessionCoordinatorRight(right
):
4903 self
._sessionCoordinatorRights
.append(right
)
4904 self
.notifyModification()
4906 def removeSessionCoordinatorRight(self
, right
):
4907 if SessionCoordinatorRights().hasRight(right
) and self
.hasSessionCoordinatorRight(right
):
4908 self
._sessionCoordinatorRights
.remove(right
)
4909 self
.notifyModification()
4911 def getSections(self
):
4915 except AttributeError, e
:
4916 self
._sections
= ConfSectionsMgr().getSectionKeys()
4917 self
.notifyModification()
4918 return self
._sections
4920 def hasEnabledSection(self
, section
):
4921 # This hack is there since there is no more enable/disable boxes
4922 # in the conference managment area corresponding to those features.
4923 # Until the managment area is improved to get a more user-friendly
4924 # way of enabling/disabling those features, we always make them
4925 # available for the time being, but we keep the previous code for
4926 # further improvements
4929 def enableSection(self
, section
):
4930 if ConfSectionsMgr().hasSection(section
) and not self
.hasEnabledSection(section
):
4931 self
._sections
.append(section
)
4932 self
.notifyModification()
4934 def disableSection(self
, section
):
4935 if ConfSectionsMgr().hasSection(section
) and self
.hasEnabledSection(section
):
4936 self
._sections
.remove(section
)
4937 self
.notifyModification()
4939 def getPendingQueuesMgr(self
):
4941 if self
._pendingQueuesMgr
:
4943 except AttributeError, e
:
4944 self
._pendingQueuesMgr
=pendingQueues
.ConfPendingQueuesMgr(self
)
4945 return self
._pendingQueuesMgr
4947 def getAccessController(self
):
4950 def _cmpTitle( c1
, c2
):
4951 o1
= c1
.getTitle().lower().strip()
4952 o2
= c2
.getTitle().lower().strip()
4953 return cmp( o1
, o2
)
4954 _cmpTitle
=staticmethod(_cmpTitle
)
4956 def getReportNumberHolder(self
):
4958 if self
._reportNumberHolder
:
4960 except AttributeError, e
:
4961 self
._reportNumberHolder
=ReportNumberHolder(self
)
4962 return self
._reportNumberHolder
4964 def setReportNumberHolder(self
, rnh
):
4965 self
._reportNumberHolder
=rnh
4967 def getBadgeTemplateManager(self
):
4969 if self
.__badgeTemplateManager
:
4971 except AttributeError:
4972 self
.__badgeTemplateManager
= BadgeTemplateManager(self
)
4973 return self
.__badgeTemplateManager
4975 def setBadgeTemplateManager(self
, badgeTemplateManager
):
4976 self
.__badgeTemplateManager
= badgeTemplateManager
4978 def getPosterTemplateManager(self
):
4980 if self
.__posterTemplateManager
:
4982 except AttributeError:
4983 self
.__posterTemplateManager
= PosterTemplateManager(self
)
4985 return self
.__posterTemplateManager
4987 def setPosterTemplateManager(self
, posterTemplateManager
):
4988 self
.__posterTemplateManager
= posterTemplateManager
4990 def getCSBookingManager(self
):
4992 if PluginsHolder().hasPluginType("Collaboration"):
4993 if not hasattr(self
, "_CSBookingManager"):
4994 from MaKaC
.plugins
.Collaboration
.base
import CSBookingManager
4995 self
._CSBookingManager
= CSBookingManager(self
)
4996 return self
._CSBookingManager
5001 class DefaultConference(Conference
):
5002 """ 'default' conference, which stores the
5003 default templates for posters and badges
5006 def indexConf(self
):
5010 """ Default constructor
5013 Conference
.__init
__(self
, AdminList
.getInstance().getList()[0], "default")
5015 raise MaKaCError(_("""There are no admin users. The "default" conference that stores the template cannot be created.
5016 Please add at least 1 user to the admin list."""))
5019 class ConferenceHolder( ObjectHolder
):
5020 """Specialised ObjectHolder dealing with conference objects. It gives a
5021 common entry point and provides simple methods to access and
5022 maintain the collection of stored conferences (DB).
5024 idxName
= "conferences"
5025 counterName
= "CONFERENCE"
5028 id = ObjectHolder
._newId
( self
)
5031 def getById( self
, id, quiet
=False ):
5032 """returns an object from the index which id corresponds to the one
5036 if (id == "default"):
5037 return CategoryManager().getDefaultConference()
5041 if self
._getIdx
().has_key(str(id)):
5042 return self
._getIdx
()[str(id)]
5046 raise NoReportError( _("The specified event with id \"%s\" does not exist or has been deleted.") % escape_html(str(id)) )
5048 class ConfSectionsMgr
:
5052 "cfa": "Call for abstracts",
5053 "paperReviewing" : "Paper Reviewing",
5054 "evaluation": "Evaluation Form",
5055 "videoconference": "Videoconference", # only for meetings
5056 "collaboration": "Collaboration", # only for meetings
5057 "regForm": "Registration Form"
5060 def hasSection(self
, s
):
5061 # This hack is there since there is no more enable/disable boxes
5062 # in the conference managment area corresponding to those features.
5063 # Until the managment area is improved to get a more user-friendly
5064 # way of enabling/disabling those features, we always make them
5065 # available in the side menu for the time being, but we keep
5066 # the previous code for further improvements
5067 #return self._sections.has_key(s)
5070 def getSections(self
):
5071 return self
._sections
5073 def getSectionList(self
, sort
=False):
5074 l
=self
._sections
.values()
5079 def getSectionKeys(self
, sort
=False):
5080 l
=self
._sections
.keys()
5085 def getSection(self
, id):
5086 if self
._sections
.has_key(id):
5087 return self
._sections
[id]
5091 class Observer(object):
5092 """ Base class for Observer objects.
5093 Inheriting classes should overload the following boolean class attributes:
5094 _shouldBeTitleNotified
5095 _shouldBeDateChangeNotified
5096 _shouldBeLocationChangeNotified
5097 _shouldBeDeletionNotified
5098 And set them to True if they want to be notified of the corresponding event.
5099 In that case, they also have to implement the corresponding methods:
5100 _notifyTitleChange (for title notification)
5101 _notifyEventDateChanges and _notifyTimezoneChange (for date / timezone notification)
5102 _shouldBeLocationChangeNotified (for location notification)
5103 _notifyDeletion (for deletion notification).
5104 The interface for those methods is also specified in this class. If the corresponding
5105 class attribute is set to False but the method is not implemented, an exception will be thrown.
5107 _shouldBeTitleNotified
= False
5108 _shouldBeDateChangeNotified
= False
5109 _shouldBeLocationChangeNotified
= False
5110 _shouldBeDeletionNotified
= False
5112 def getObserverName(self
):
5113 name
= "'Observer of class" + self
.__class
__.__name
__
5115 conf
= self
.getOwner()
5116 name
= name
+ " of event " + conf
.getId() + "'"
5117 except AttributeError:
5121 def notifyTitleChange(self
, oldTitle
, newTitle
):
5122 if self
._shouldBeTitleNotified
:
5123 self
._notifyTitleChange
(oldTitle
, newTitle
)
5125 def notifyEventDateChanges(self
, oldStartDate
= None, newStartDate
= None, oldEndDate
= None, newEndDate
= None):
5126 if self
._shouldBeDateChangeNotified
:
5127 self
._notifyEventDateChanges
(oldStartDate
, newStartDate
, oldEndDate
, newEndDate
)
5129 def notifyTimezoneChange(self
, oldTimezone
, newTimezone
):
5130 if self
._shouldBeDateChangeNotified
:
5131 self
._notifyTimezoneChange
(oldTimezone
, newTimezone
)
5133 def notifyLocationChange(self
, newLocation
):
5134 if self
._shouldBeLocationChangeNotified
:
5135 self
._notifyLocationChange
(newLocation
)
5137 def notifyDeletion(self
):
5138 if self
._shouldBeDeletionNotified
:
5139 self
._notifyDeletion
()
5141 def _notifyTitleChange(self
, oldTitle
, newTitle
):
5142 """ To be implemented by inheriting classes
5143 Notifies the observer that the Conference object's title has changed
5145 raise MaKaCError("Class " + str(self
.__class
__.__name
__) + " did not implement method _notifyTitleChange")
5147 def _notifyEventDateChanges(self
, oldStartDate
, newStartDate
, oldEndDate
, newEndDate
):
5148 """ To be implemented by inheriting classes
5149 Notifies the observer that the start and / or end dates of the object it is attached to has changed.
5150 If the observer finds any problems during whatever he needs to do as a consequence of
5151 the event dates changing, he should write strings describing the problems
5152 in the 'dateChangeNotificationProblems' context variable (which is a list of strings).
5154 raise MaKaCError("Class " + str(self
.__class
__.__name
__) + " did not implement method notifyStartDateChange")
5156 def _notifyTimezoneChange(self
, oldTimezone
, newTimezone
):
5157 """ To be implemented by inheriting classes.
5158 Notifies the observer that the end date of the object it is attached to has changed.
5159 This method has to return a list of strings describing problems encountered during
5160 whatever the DateChangeObserver object does as a consequence of the notification.
5161 If there are no problems, the DateChangeObserver should return an empty list.
5163 raise MaKaCError("Class " + str(self
.__class
__.__name
__) + " did not implement method notifyTimezoneChange")
5165 def _notifyLocationChange(self
):
5166 """ To be implemented by inheriting classes
5167 Notifies the observer that the location of the object it is attached to has changed.
5169 raise MaKaCError("Class " + str(self
.__class
__.__name
__) + " did not implement method notifyLocationChange")
5171 def _notifyDeletion(self
):
5172 """ To be implemented by inheriting classes
5173 Notifies the observer that the Conference object it is attached to has been deleted
5175 raise MaKaCError("Class " + str(self
.__class
__.__name
__) + " did not implement method notifyDeletion")
5177 class TitleChangeObserver(Observer
):
5178 """ Base class for objects who want to be notified of a Conference object being deleted.
5179 Inheriting classes have to implement the notifyTitleChange method, and probably the __init__ method too.
5182 def notifyTitleChange(self
, oldTitle
, newTitle
):
5183 """ To be implemented by inheriting classes
5184 Notifies the observer that the Conference object's title has changed
5186 raise MaKaCError("Class " + str(self
.__class
__.__name
__) + " did not implement method notifyTitleChange")
5189 class SessionChair(ConferenceParticipation
):
5194 ConferenceParticipation
.__init
__(self
)
5196 def _notifyModification( self
):
5197 if self
._session
!= None:
5198 self
._session
.notifyModification()
5201 chair
= SessionChair()
5202 chair
.setValues(self
.getValues())
5205 def getSession(self
):
5206 return self
._session
5208 def getConference(self
):
5212 return s
.getConference()
5214 def includeInSession(self
,session
,id):
5215 if self
.getSession()==session
and self
.getId()==id.strip():
5217 self
._session
=session
5222 ConferenceParticipation
.delete(self
)
5224 def getLocator(self
):
5225 if self
.getSession() is None:
5227 loc
=self
.getSession().getLocator()
5228 loc
["convId"]=self
.getId()
5231 def isSessionManager(self
):
5233 if self
.getEmail() in self
._session
.getAccessController().getModificationEmail():
5236 for manager
in self
._session
.getManagerList():
5237 if self
.getEmail() == manager
.getEmail():
5241 def isSessionCoordinator(self
):
5242 # pendings coordinators
5243 if self
.getEmail() in self
._session
.getConference().getPendingQueuesMgr().getPendingCoordinatorsKeys():
5246 for coord
in self
._session
.getCoordinatorList():
5247 if self
.getEmail() == coord
.getEmail():
5252 class SlotChair(ConferenceParticipation
):
5257 ConferenceParticipation
.__init
__(self
)
5259 def _notifyModification( self
):
5260 if self
._slot
!= None:
5261 self
._slot
.notifyModification()
5265 chair
.setValues(self
.getValues())
5271 def getSession(self
):
5275 return s
.getSession()
5277 def getConference(self
):
5281 return s
.getConference()
5283 def includeInSlot(self
,slot
,id):
5284 if self
.getSlot()==slot
and self
.getId()==id.strip():
5291 ConferenceParticipation
.delete(self
)
5293 def getLocator(self
):
5294 if self
.getSlot() is None:
5296 loc
=self
.getSlot().getLocator()
5297 loc
["convId"]=self
.getId()
5300 class SessionCoordinatorRights
:
5303 self
._rights
= {"modifContribs": "Modify the contributions",
5304 "unrestrictedSessionTT": "Unrestricted session timetable management"
5307 def hasRight(self
, r
):
5308 return self
._rights
.has_key(r
)
5310 def getRights(self
):
5313 def getRightList(self
, sort
=False):
5314 l
=self
._rights
.values()
5319 def getRightKeys(self
):
5320 return self
._rights
.keys()
5322 def getRight(self
, id):
5323 if self
._rights
.has_key(id):
5324 return self
._rights
[id]
5327 class SCIndex(Persistent
):
5328 """Index for conference session coordinators.
5330 This class allows to index conference session coordinators so the owner
5331 can answer optimally to the query if a user is coordinating
5332 any conference session.
5333 It is implemented by simply using a BTree where the Avatar id is used
5334 as key (because it is unique and non variable) and a list of
5335 coordinated sessions is kept as keys. It is the responsability of the
5336 index owner (conference) to keep it up-to-date i.e. notify session
5337 coordinator additions and removals.
5340 def __init__( self
):
5344 def getSessions(self
,av
):
5345 """Gives a list with the sessions a user is coordinating.
5349 return self
._idx
.get(av
.getId(),[])
5351 def index(self
,av
,session
):
5352 """Registers in the index a coordinator of a session.
5354 if av
== None or session
== None:
5356 if not self
._idx
.has_key(av
.getId()):
5358 self
._idx
[av
.getId()]=l
5360 l
=self
._idx
[av
.getId()]
5361 if session
not in l
:
5363 self
.notifyModification()
5365 def unindex(self
,av
,session
):
5366 if av
==None or session
==None:
5368 l
=self
._idx
.get(av
.getId(),[])
5371 self
.notifyModification()
5373 def notifyModification(self
):
5374 self
._idx
._p
_changed
=1
5377 class Session(CommonObjectBase
, Locatable
):
5378 """This class implements a conference session, being the different parts
5379 in which the conference can be divided and the contributions can be
5380 organised in. The class contains necessary attributes to store session
5381 basic data and provides the operations related to sessions. In
5382 principle, a session has no sense to exist without being related to a
5383 conference but it is allowed for flexibility.
5386 fossilizes(ISessionFossil
)
5389 def __init__(self
, **sessionData
):
5390 """Class constructor. Initialise the class attributes to the default
5393 sessionData -- (Dict) Contains the data the session object has to
5396 self
.conference
=None
5397 self
.id="not assigned"
5400 #################################
5401 # Fermi timezone awareness #
5402 #################################
5403 self
.startDate
= nowutc()
5404 #################################
5405 # Fermi timezone awareness(end) #
5406 #################################
5408 self
.duration
=timedelta(minutes
=1)
5411 self
.conveners
=[] # This attribute must not be used and should disappear someday
5413 self
._convenerGen
=Counter()
5414 self
.convenerText
=""
5415 self
.contributions
={}
5416 self
._contributionDuration
=timedelta(minutes
=20)
5417 self
.__ac
=AccessController(self
)
5419 self
.__materialGenerator
=Counter()
5423 self
.__slotGenerator
=Counter()
5425 self
._coordinators
=OOBTree()
5426 self
._coordinatorsEmail
= []
5428 self
._color
="#e3f2d3"
5429 self
._textColor
="#202020"
5430 self
._textColorToLinks
=False
5431 self
._ttType
=SlotSchTypeFactory
.getDefaultId()
5432 self
._closed
= False
5433 self
._registrationSession
= None
5434 self
._creationDS
= nowutc()
5435 self
._modificationDS
= nowutc()
5438 def getTimezone( self
):
5439 return self
.getConference().getTimezone()
5441 def isFullyPublic( self
):
5442 if hasattr(self
, "_fullyPublic"):
5443 return self
._fullyPublic
5445 self
.setFullyPublic()
5446 return self
._fullyPublic
5448 def setFullyPublic( self
):
5449 if self
.isProtected():
5450 self
._fullyPublic
= False
5453 for res
in self
.getAllMaterialList():
5454 if not res
.isFullyPublic():
5455 self
._fullyPublic
= False
5458 for res
in self
.getContributionList():
5459 if not res
.isFullyPublic():
5460 self
._fullyPublic
= False
5463 self
._fullyPublic
= True
5466 def updateFullyPublic( self
):
5467 self
.setFullyPublic()
5468 self
.getOwner().updateFullyPublic()
5470 def getKeywords(self
):
5472 return self
._keywords
5477 def setKeywords(self
, keywords
):
5478 self
._keywords
= keywords
5480 def notifyModification( self
, date
= None ):
5481 """Method called to notify the current session has been modified.
5483 self
.setModificationDate(date
)
5485 parent
= self
.getConference()
5487 parent
.setModificationDate(date
)
5490 def getModificationDate( self
):
5491 """Returns the date in which the session was last modified"""
5493 return self
._modificationDS
5495 self
._modificationDS
= nowutc()
5496 return self
._modificationDS
5498 def getCreationDate( self
):
5499 """Returns the date in which the session was created"""
5501 return self
._creationDS
5503 self
._creationDS
= nowutc()
5504 return self
._creationDS
5506 def getLogInfo(self
):
5508 data
["subject"] = self
.title
5509 data
["session id"] = self
.id
5510 data
["session code"] = self
._code
5511 data
["title"] = self
.title
5512 data
["description"] = self
.description
5513 data
["start date"] = self
.startDate
5514 data
["duration"] = self
.duration
5515 for p
in self
.places
:
5516 data
["place"] = p
.getName()
5517 for r
in self
.rooms
:
5518 data
["room"] = r
.getName()
5519 for sc
in self
.getConvenerList() :
5520 data
["convener %s"%sc.getId()] = sc
.getFullName()
5521 for co
in self
.getCoordinatorList() :
5522 data
["contribution %s"%co.getId()] = co
.getFullName()
5523 for s
in self
.getSlotList() :
5524 data
["contribution %s"%s.getId()] = s
.getTitle()
5525 for c
in self
.getContributionList() :
5526 data
["contribution %s"%c.getId()] = c
.getTitle()
5530 def getEnableSessionSlots(self
):
5532 return self
.getConference().getEnableSessionSlots()
5536 def cmpSessionByTitle(session1
, session2
):
5537 return cmp(session1
.getTitle(), session2
.getTitle())
5538 cmpSessionByTitle
= staticmethod(cmpSessionByTitle
)
5540 def hasRegistrationSession(self
):
5541 return self
.getRegistrationSession() is not None
5543 def getRegistrationSession(self
):
5545 if self
._registrationSession
:
5547 except AttributeError, e
:
5548 self
._registrationSession
= None
5549 return self
._registrationSession
5551 def setRegistrationSession(self
, rs
):
5552 self
._registrationSession
= rs
5554 def isClosed( self
):
5555 if self
.getConference().isClosed():
5560 self
._closed
= False
5563 def setClosed( self
, closed
=True ):
5564 self
._closed
= closed
5565 self
.notifyModification()
5567 def includeInConference(self
,conf
,newId
):
5568 self
.conference
=conf
5570 for slot
in self
.getSlotList():
5571 conf
.getSchedule().addEntry(slot
.getConfSchEntry(),2)
5572 self
.getConference().addSession(self
)
5573 self
.notifyModification()
5576 while len(self
.getConvenerList()) > 0:
5577 self
.removeConvener(self
.getConvenerList()[0])
5578 while len(self
.getMaterialList()) > 0:
5579 self
.removeMaterial(self
.getMaterialList()[0])
5580 self
.removeMinutes()
5581 for c
in self
.getCoordinatorList()[:]:
5582 self
.removeCoordinator(c
)
5583 while len(self
.contributions
.values())>0:
5584 self
.removeContribution(self
.contributions
.values()[0])
5585 while len(self
.slots
.values())>0:
5586 self
._removeSlot
(self
.slots
.values()[0])
5587 if self
.getConference() is not None:
5588 self
.getConference().removeSession(self
)
5589 if self
.hasRegistrationSession():
5590 self
.getConference().getRegistrationForm().getSessionsForm().removeSession(self
.getId())
5591 self
.getRegistrationSession().setRegistrationForm(None)
5592 TrashCanManager().add(self
.getRegistrationSession())
5593 self
.conference
=None
5594 TrashCanManager().add(self
)
5596 def recover(self
, isCancelled
):
5597 if self
.hasRegistrationSession():
5599 self
.getRegistrationSession().setRegistrationForm(self
.getConference().getRegistrationForm())
5600 self
.getConference().getRegistrationForm().getSessionsForm().addSession(self
.getRegistrationSession())
5601 TrashCanManager().remove(self
.getRegistrationSession())
5602 TrashCanManager().remove(self
)
5604 def getLocator( self
):
5605 """Gives back a globaly unique identification encapsulated in a Locator
5606 object for the session instance
5608 if self
.conference
== None:
5610 lconf
= self
.conference
.getLocator()
5611 lconf
["sessionId"] = self
.getId()
5614 def getConference( self
):
5615 return self
.conference
5617 def getSession( self
):
5620 def getOwner( self
):
5621 return self
.getConference()
5626 def getUniqueId( self
):
5627 """returns (string) the unique identiffier of the item"""
5628 """used mainly in the web session access key table"""
5629 return "%ss%s" % (self
.getConference().getUniqueId(),self
.id)
5631 def getModifKey( self
):
5632 return self
.getConference().getModifKey()
5634 def getAccessKey( self
):
5635 return self
.getConference().getAccessKey()
5637 def getContribDuration(self
):
5639 return self
._contributionDuration
5641 self
._contributionDuration
= timedelta(minutes
=20)
5642 return self
._contributionDuration
5644 def setContribDuration(self
, hour
=0, min=20, dur
=None):
5646 self
._contributionDuration
=dur
5648 self
._contributionDuration
= timedelta(hours
=hour
,minutes
=min)
5651 #if not self.getConference().getEnableSessionSlots():
5652 # self.getSlotList()[0].fit()
5653 self
.setStartDate(self
.getMinSlotStartDate(),0,0)
5654 self
.setEndDate(self
.getMaxSlotEndDate(),0)
5656 def addSlot(self
,newSlot
):
5657 id = newSlot
.getId()
5658 if id == "not assigned":
5659 newSlot
.setId(str(self
.__slotGenerator
.newCount()))
5660 self
.slots
[newSlot
.getId()]=newSlot
5662 self
.getSchedule().addEntry(newSlot
.getSessionSchEntry(),2)
5663 if self
.getConference() is not None:
5664 self
.getConference().getSchedule().addEntry(newSlot
.getConfSchEntry(),2)
5665 self
.notifyModification()
5667 def _removeSlot(self
,slot
):
5668 del self
.slots
[slot
.getId()]
5669 self
.getSchedule().removeEntry(slot
.getSessionSchEntry())
5670 if self
.getConference() is not None:
5671 self
.getConference().getSchedule().removeEntry(slot
.getConfSchEntry())
5674 def removeSlot(self
, slot
, force
=False):
5675 if self
.slots
.has_key(slot
.getId()):
5676 if len(self
.slots
)==1 and not force
:
5677 raise MaKaCError( _("A session must have at least one slot"), _("Session"))
5678 self
._removeSlot
(slot
)
5680 self
.notifyModification()
5682 def recoverSlot(self
, slot
):
5686 def getSlotById(self
,slotId
):
5687 return self
.slots
.get(slotId
,None)
5689 def getSlotList(self
):
5690 return self
.slots
.values()
5692 def getSortedSlotList(self
):
5693 sl
= self
.getSlotList()
5694 sl
.sort(utils
.sortSlotByDate
)
5697 def getMinSlotStartTime(self
):
5699 for slot
in self
.getSlotList():
5700 if slot
.isMoreThanDay():
5702 shour
= slot
.getStartDate().hour
5703 smin
= slot
.getStartDate().minute
5704 if (shour
, smin
) < min:
5708 def getMaxSlotEndTime(self
):
5710 for slot
in self
.getSlotList():
5711 if slot
.isMoreThanDay():
5713 endDate
= slot
.getEndDate()
5714 if (endDate
.hour
, endDate
.minute
) > max:
5715 newEndDate
= endDate
- timedelta(0, 0, 0)
5716 max = (newEndDate
.hour
, newEndDate
.minute
)
5719 def getMinSlotStartDate(self
):
5720 slotList
= self
.getSlotList()
5721 if len(slotList
)==0:
5722 return self
.getStartDate()
5724 sDate
= self
.getEndDate()
5725 for slot
in slotList
:
5726 if slot
.getStartDate() < sDate
:
5727 sDate
= slot
.getStartDate()
5730 def getMaxSlotEndDate(self
):
5731 slotList
= self
.getSlotList()
5732 if len(slotList
)==0:
5733 return self
.getEndDate()
5735 eDate
= self
.getStartDate()
5736 for slot
in slotList
:
5737 if slot
.getEndDate() > eDate
:
5738 eDate
= slot
.getEndDate()
5741 def _getCorrectColor(self
, color
):
5742 if not color
.startswith("#"):
5744 m
= re
.match("^#[0-9A-Fa-f]{6}$", color
)
5749 def _getCorrectBgColor(self
, color
):
5750 color
=self
._getCorrectColor
(color
)
5755 def _getCorrectTextColor(self
, color
):
5756 color
=self
._getCorrectColor
(color
)
5758 return self
._textColor
5761 def setValues( self
, sessionData
,check
=2,moveEntries
=0 ):
5762 """Sets all the values of the current session object from a dictionary
5763 containing the following key-value pairs:
5766 locationName-(str) => name of the location, if not specified
5767 it will be set to the conference location name.
5768 locationAddress-(str)
5769 roomName-(str) => name of the room, if not specified it will
5770 be set to the conference room name.
5771 sDate - (datetime) => starting date of the session, if not
5772 specified it will be set to now.
5773 eDate - (datetime) => ending date of the session, if not
5774 specified the end date will be set to the start one
5775 durHour - (int) => hours of duration for each entry in the session
5777 durMin - (int) => hours of duration for each entry in the session
5782 1: check and raise error in case of problem
5783 2: check and adapt the owner dates
5784 Please, note that this method sets ALL values which means that if
5785 the given dictionary doesn't contain any of the keys the value
5786 will set to a default value.
5789 self
.setTitle( sessionData
.get("title", "NO TITLE ASSIGNED") )
5790 self
.setDescription( sessionData
.get("description", "") )
5791 code
= sessionData
.get("code", "")
5792 if code
.strip() == "":
5793 if self
.getId()=="not assigned":
5794 self
.setCode("no code")
5796 self
.setCode(self
.getId())
5799 bgcolor
= sessionData
.get("backgroundColor", "")
5800 if bgcolor
.strip() != "":
5801 self
.setColor(self
._getCorrectBgColor
(bgcolor
))
5802 textcolor
= sessionData
.get("textColor", "")
5803 if textcolor
.strip() != "":
5804 if sessionData
.has_key("autotextcolor"):
5805 self
.setTextColor(utils
.getTextColorFromBackgroundColor(self
.getColor()))
5807 self
.setTextColor(self
._getCorrectTextColor
(textcolor
))
5808 self
.setTextColorToLinks(sessionData
.has_key("textcolortolinks"))
5810 if "locationName" in sessionData
:
5811 loc
= self
.getOwnLocation()
5813 loc
= CustomLocation()
5814 self
.setLocation( loc
)
5815 loc
.setName( sessionData
["locationName"] )
5816 loc
.setAddress( sessionData
.get("locationAddress", "") )
5818 self
.setLocation(None)
5820 #same as for the location
5821 if "roomName" in sessionData
:
5822 room
= self
.getOwnRoom()
5825 self
.setRoom( room
)
5826 room
.setName( sessionData
["roomName"] )
5830 if sessionData
.get("sDate",None) is not None:
5831 self
.setStartDate(sessionData
["sDate"],check
,moveEntries
=moveEntries
)
5832 if sessionData
.get("eDate",None) is not None:
5833 self
.setEndDate(sessionData
["eDate"],check
)
5834 self
._checkInnerSchedule
()
5835 if sessionData
.get("contribDuration","")!="":
5836 self
._contributionDuration
= sessionData
.get("contribDuration")
5838 self
._contributionDuration
= timedelta(hours
=int(sessionData
.get("durHour",0)), minutes
=int(sessionData
.get("durMin",20)))
5839 self
.notifyModification()
5841 def move(self
, sDate
):
5843 Move a session from the old start date to a new start date, and
5844 it moves all the entries of the session as well, without date validations.
5846 if sDate
is not None:
5847 oldStartDate
=self
.startDate
5848 self
.startDate
=copy
.copy(sDate
)
5849 diff
=self
.startDate
-oldStartDate
5850 # Check date to not be prior conference start date and to not surpass conference end date
5851 # The schedule is returning the datetime object as timezone aware relative to the conference
5852 # timezone. Must adjust the startdate accordingly for comparison. JMF
5853 conftz
= self
.getConference().getTimezone()
5854 if self
.getStartDate() < self
.getConference().getSchedule().getStartDate() or \
5855 self
.getEndDate() > self
.getConference().getSchedule().getEndDate():
5856 raise MaKaCError( _("Impossible to move the session because it would be out of the conference dates"))
5857 for entry
in self
.getSchedule().getEntries():
5858 if isinstance(entry
,LinkedTimeSchEntry
) and \
5859 isinstance(entry
.getOwner(), SessionSlot
):
5860 e
= entry
.getOwner()
5861 e
.move(e
.getStartDate() + diff
)
5862 self
.getSchedule().reSchedule()
5863 self
.getConference().getSchedule().reSchedule()
5864 self
.notifyModification()
5866 def clone(self
, deltaTime
, conf
, options
):
5868 conf
.addSession(ses
,check
=0)
5869 ses
.setTitle(self
.getTitle())
5870 ses
.setDescription(self
.getDescription())
5871 startDate
= self
.getStartDate() + deltaTime
5872 ses
.setStartDate(startDate
, check
=1)
5873 ses
.setDuration(dur
=self
.getDuration())
5875 if self
.getOwnLocation() is not None:
5876 ses
.addLocation(self
.getOwnLocation().clone())
5877 if self
.getOwnRoom() is not None:
5878 ses
.setRoom(self
.getOwnRoom().clone())
5879 ses
.setColor(self
.getColor())
5880 ses
.setTextColor(self
.getTextColor())
5881 ses
.setTextColorToLinks(self
.isTextColorToLinks())
5882 ses
.setCode(self
.getCode())
5883 ses
.setContribDuration(dur
=self
.getContribDuration())
5884 ses
.setScheduleType(self
.getScheduleType())
5885 ses
.setComments(self
.getComments())
5887 # Access Control cloning
5888 if options
.get("access", False) :
5889 ses
.setProtection(self
.getAccessController()._getAccessProtection
())
5890 for mgr
in self
.getManagerList() :
5891 ses
.grantModification(mgr
)
5892 for user
in self
.getAllowedToAccessList() :
5893 ses
.grantAccess(user
)
5894 for domain
in self
.getDomainList():
5895 ses
.requireDomain(domain
)
5896 for coord
in self
.getCoordinatorList():
5897 ses
.addCoordinator(coord
)
5899 #slots in timeschedule
5900 for slot
in self
.getSlotList() :
5901 newslot
= slot
.clone(ses
, options
)
5902 ses
.addSlot(newslot
)
5903 ContextManager
.setdefault("clone.unique_id_map", {})[slot
.getUniqueId()] = newslot
.getUniqueId()
5905 ses
.notifyModification()
5910 def setTitle( self
, newTitle
):
5911 self
.title
= newTitle
5912 self
.notifyModification()
5914 def getTitle( self
):
5917 def setDescription(self
, newDescription
):
5918 self
.description
= newDescription
5919 self
.notifyModification()
5921 def getDescription(self
):
5922 return self
.description
5928 except AttributeError:
5932 def setCode(self
,newCode
):
5933 self
._code
=str(newCode
).strip()
5939 except AttributeError:
5940 self
._color
="#e3f2d3"
5944 def setColor(self
,newColor
):
5945 self
._color
=str(newColor
).strip()
5948 def getTextColor(self
):
5952 except AttributeError:
5953 self
._textColor
="#202020"
5954 return self
._textColor
5956 def setTextColor(self
,newColor
):
5957 self
._textColor
=str(newColor
).strip()
5959 def isTextColorToLinks(self
):
5961 if self
._textColorToLink
:
5963 except AttributeError:
5964 self
._textColorToLink
=False
5965 return self
._textColorToLink
5967 def setTextColorToLinks(self
, v
):
5968 self
._textColorToLink
=v
5970 def getStartDate(self
):
5971 return self
.startDate
5973 def getAdjustedStartDate(self
,tz
=None):
5975 tz
= self
.getConference().getTimezone()
5976 if tz
not in all_timezones
:
5978 return self
.startDate
.astimezone(timezone(tz
))
5980 def verifyStartDate(self
, sdate
, check
=2):
5983 1: check and raise error in case of problem (default)
5984 2: check and adapt the owner dates
5987 conf
=self
.getConference()
5989 if conf
is not None and sdate
< conf
.getSchedule().getStartDate():
5991 raise ParentTimingError( _("The session starting date cannot be prior to the event starting date"), _("Session"))
5993 ContextManager
.get('autoOps').append((self
, "OWNER_START_DATE_EXTENDED",
5994 conf
, sdate
.astimezone(timezone(conf
.getTimezone()))))
5995 conf
.setStartDate(sdate
,check
=0,moveEntries
=0)
5997 def setStartDate(self
,newDate
,check
=2,moveEntries
=0):
5999 moveEntries parameter:
6000 0: do not move inner slots
6002 2: do not move but check that session is not out of the conference dates
6005 if not newDate
.tzname():
6006 raise MaKaCError("date should be timezone aware")
6008 self
.verifyStartDate(newDate
,check
)
6009 oldSdate
= self
.getStartDate()
6011 tz
= str(self
.getStartDate().tzinfo
)
6014 diff
= newDate
- oldSdate
6015 self
.startDate
=copy
.copy(newDate
)
6016 if moveEntries
== 1 and diff
is not None and diff
!= timedelta(0):
6017 # If the start date changed, we move entries inside the timetable
6018 newDateTz
= newDate
.astimezone(timezone(tz
))
6019 if oldSdate
.astimezone(timezone(tz
)).date() != newDateTz
.date():
6020 entries
= self
.getSchedule().getEntries()[:]
6022 entries
= self
.getSchedule().getEntriesOnDay(newDateTz
)[:]
6023 self
.getSchedule().moveEntriesBelow(diff
, entries
)
6025 if moveEntries
!= 0 and self
.getConference() and \
6026 not self
.getConference().getEnableSessionSlots() and \
6027 self
.getSlotList() != [] and \
6028 self
.getSlotList()[0].getStartDate() != newDate
:
6029 self
.getSlotList()[0].startDate
= newDate
6032 self
._checkInnerSchedule
()
6033 self
.notifyModification()
6035 def _checkInnerSchedule( self
):
6036 self
.getSchedule().checkSanity()
6038 def getEndDate(self
):
6039 return self
.startDate
+self
.duration
6041 ####################################
6042 # Fermi timezone awareness #
6043 ####################################
6045 def getAdjustedEndDate(self
,tz
=None):
6046 return self
.getAdjustedStartDate(tz
) + self
.duration
6048 ####################################
6049 # Fermi timezone awareness(end) #
6050 ####################################
6052 def verifyEndDate(self
, edate
,check
=1):
6055 1: check and raise error in case of problem
6056 2: check and adapt the owner dates
6059 tz
= timezone(self
.getConference().getTimezone())
6061 tz
= timezone('UTC')
6062 # compare end date with start date
6063 if edate
<=self
.getStartDate():
6065 raise MaKaCError( _("End date cannot be prior to the Start date"), _("Session"))
6067 self
.setStartDate(edate
)
6068 # check conference dates
6069 if (self
.getConference()):
6070 conf
=self
.getConference()
6071 confStartDate
= conf
.getSchedule().getStartDate()
6072 confEndDate
= conf
.getSchedule().getEndDate()
6073 if conf
is not None and (edate
>confEndDate
or edate
<=confStartDate
):
6075 raise ParentTimingError( _("The end date has to be between the event dates (%s - %s)")%\
6076 (confStartDate
.astimezone(tz
).strftime('%Y-%m-%d %H:%M'),\
6077 confEndDate
.astimezone(tz
).strftime('%Y-%m-%d %H:%M')),\
6080 if edate
>confEndDate
:
6081 ContextManager
.get('autoOps').append((self
, "OWNER_END_DATE_EXTENDED",
6082 self
.getConference(),
6083 edate
.astimezone(tz
)))
6084 self
.getConference().setEndDate(edate
)
6085 if edate
<=confStartDate
:
6086 ContextManager
.get('autoOps').append((self
, "OWNER_START_DATE_EXTENDED",
6087 self
.getConference(),
6088 edate
.astimezone(tz
)))
6089 self
.getConference().setStartDate(edate
)
6090 # check inner schedule
6091 if len(self
.getSlotList()) != 0 and self
.getSlotList()[-1].getSchedule().hasEntriesAfter(edate
):
6092 raise TimingError( _("Cannot change end date: some entries in the session schedule end after the new date"), _("Session"))
6094 def setEndDate(self
,newDate
,check
=2):
6095 if not newDate
.tzname():
6096 raise MaKaCError("date should be timezone aware")
6098 self
.verifyEndDate(newDate
,check
)
6099 self
.duration
=newDate
-self
.getStartDate()
6100 # A session is not always linked to a conference (for eg. at creation time)
6101 #if self.getConference() and not self.getConference().getEnableSessionSlots() and self.getSlotList()[0].getEndDate() != newDate:
6102 # self.getSlotList()[0].duration = self.duration
6103 self
.notifyModification()
6105 def setDates(self
,sDate
,eDate
,check
=1,moveEntries
=0):
6107 tz
= timezone(self
.getConference().getTimezone())
6108 raise MaKaCError(_("The end date (%s) cannot be prior to the start date (%s)") % (eDate
.astimezone(tz
).strftime('%Y-%m-%d %H:%M'),sDate
.astimezone(tz
).strftime('%Y-%m-%d %H:%M')),_("Session"))
6109 self
.setStartDate(sDate
,check
,moveEntries
)
6110 self
.setEndDate(eDate
,check
)
6111 self
._checkInnerSchedule
()
6113 def getDuration( self
):
6114 return self
.duration
6116 def setDuration(self
,hours
=0,minutes
=15,dur
=0):
6118 dur
= timedelta(hours
=int(hours
),minutes
=int(minutes
))
6119 if dur
.seconds
<= 0:
6120 raise MaKaCError( _("The duration cannot be less than zero"), _("Session"))
6122 self
.verifyEndDate(self
.getEndDate())
6123 self
.notifyModification()
6125 def getStartOnDay(self
, day
, tz
=None):
6127 tz
= self
.getConference().getTimezone()
6128 if type(day
) is datetime
:
6129 day
= day
.astimezone(timezone(tz
))
6130 if day
.date() < self
.getStartDate().astimezone(timezone(tz
)).date() or day
.date() > self
.getEndDate().astimezone(timezone(tz
)).date() :
6132 minTime
= self
.getEndDate()
6133 for e
in self
.getSchedule().getEntriesOnDay(day
) :
6134 if e
.getStartDate() < minTime
:
6135 minTime
= e
.getStartDate()
6136 if minTime
== self
.getEndDate() :
6137 minTime
= day
.replace(hour
=8, minute
=0)#datetime.combine(day,time(hour=8, minute=0))
6138 if minTime
< self
.getStartDate() :
6139 return self
.getStartDate()
6142 def getEndOnDay(self
, day
, tz
=None):
6144 tz
= self
.getConference().getTimezone()
6145 if type(day
) is datetime
:
6146 day
= day
.astimezone(timezone(tz
))
6147 if day
.date() < self
.getStartDate().astimezone(timezone(tz
)).date() or day
.date() > self
.getEndDate().astimezone(timezone(tz
)).date() :
6149 maxTime
= self
.getStartDate();
6150 for e
in self
.getSchedule().getEntriesOnDay(day
) :
6151 if e
.getEndDate() > maxTime
:
6152 maxTime
= e
.getEndDate()
6153 if maxTime
== self
.getStartDate() :
6154 maxTime
= day
.replace(hour
=19, minute
=0)#datetime.combine(day,time(19,0))
6155 if maxTime
> self
.getEndDate() :
6156 return self
.getEndDate()
6159 def getLocationParent( self
):
6161 Returns the object from which the room/location
6162 information should be inherited
6164 return self
.getConference()
6166 def getLocationList(self
):
6167 """Method returning a list of "location" objects which contain the
6168 information about the different places the conference is gonna
6173 def addLocation(self
, newPlace
):
6174 self
.places
.append( newPlace
)
6175 self
.notifyModification()
6177 def _resetConveners(self
):
6181 except AttributeError:
6183 for oc
in self
.conveners
:
6184 newConv
=SessionChair()
6185 newConv
.setDataFromAvatar(oc
)
6186 self
._addConvener
(newConv
)
6188 def getConvenerList(self
):
6189 self
._resetConveners
()
6190 return self
._conveners
6192 def getAllConvenerList(self
):
6193 convenerList
= set()
6194 for slot
in self
.getSlotList():
6195 for convener
in slot
.getConvenerList():
6196 convenerList
.add(convener
)
6199 def _addConvener(self
,newConv
):
6200 if newConv
in self
._conveners
:
6203 if self
._convenerGen
:
6205 except AttributeError:
6206 self
._convenerGen
=Counter()
6207 id = newConv
.getId()
6209 id=int(self
._convenerGen
.newCount())
6210 newConv
.includeInSession(self
,id)
6211 self
._conveners
.append(newConv
)
6212 self
.notifyModification()
6214 def addConvener(self
,newConv
):
6215 self
._resetConveners
()
6216 self
._addConvener
(newConv
)
6217 if isinstance(newConv
, MaKaC
.user
.Avatar
):
6218 conv
.unlinkTo(self
, "convener")
6220 def removeConvener(self
,conv
):
6221 self
._resetConveners
()
6222 if conv
not in self
._conveners
:
6224 #--Pending queue: remove pending Convener waiting to became manager if anything
6225 self
.getConference().getPendingQueuesMgr().removePendingManager(conv
)
6227 #--Pending queue: remove pending Convener waiting to became coordinator if anything
6228 self
.getConference().getPendingQueuesMgr().removePendingCoordinator(conv
)
6230 self
._conveners
.remove(conv
)
6231 if isinstance(conv
, MaKaC
.user
.Avatar
):
6232 conv
.linkTo(self
, "convener")
6234 self
.notifyModification()
6236 def recoverConvener(self
, con
):
6237 self
.addConvener(con
)
6240 def getConvenerById(self
,id):
6242 for conv
in self
._conveners
:
6243 if conv
.getId()==id:
6247 def getConvenerText( self
):
6250 if self
.convenerText
:
6252 except AttributeError, e
:
6253 self
.convenerText
= ""
6254 return self
.convenerText
6256 def setConvenerText( self
, newText
):
6257 self
.convenerText
= newText
.strip()
6259 def appendConvenerText( self
, newText
):
6260 self
.setConvenerText( "%s, %s"%(self
.getConvenerText(), newText
.strip()) )
6262 def addContribution(self
, newContrib
, id=None):
6263 """Registers the contribution passed as parameter within the session
6264 assigning it a unique id.
6266 if self
.hasContribution(newContrib
):
6268 self
.getConference().addContribution(newContrib
,id)
6269 self
.contributions
[newContrib
.getId()]=newContrib
6270 newContrib
.setSession(self
)
6271 self
.notifyModification()
6273 def hasContribution(self
,contrib
):
6274 return contrib
.getSession()==self
and \
6275 self
.contributions
.has_key(contrib
.getId())
6277 def removeContribution(self
,contrib
):
6278 """Removes the indicated contribution from the session
6280 if not self
.hasContribution(contrib
):
6282 if contrib
.isScheduled():
6283 # unschedule the contribution
6284 sch
=contrib
.getSchEntry().getSchedule()
6285 sch
.removeEntry(contrib
.getSchEntry())
6286 del self
.contributions
[contrib
.getId()]
6287 contrib
.setSession(None)
6289 self
.notifyModification()
6291 def newContribution( self
, params
= None, id=None ):
6295 self
.addContribution( c
, id )
6298 def getContributionById(self
,id):
6300 if self
.contributions
.has_key( id ):
6301 return self
.contributions
[ id ]
6304 def getContributionList( self
):
6305 return self
.contributions
.values()
6307 def getNumberOfContributions(self
, only_scheduled
=False):
6309 return len(filter(lambda c
: c
.isScheduled(), self
.contributions
.itervalues()))
6311 return len(self
.contributions
)
6313 def canIPAccess( self
, ip
):
6314 if not self
.__ac
.canIPAccess( ip
):
6316 if self
.getOwner() != None:
6317 return self
.getOwner().canIPAccess(ip
)
6320 def isProtected( self
):
6321 # tells if a session is protected or not
6322 return (self
.hasProtectedOwner() + self
.getAccessProtectionLevel()) > 0
6324 def getAccessProtectionLevel( self
):
6325 return self
.__ac
.getAccessProtectionLevel()
6327 def isItselfProtected( self
):
6328 return self
.__ac
.isItselfProtected()
6330 def hasAnyProtection( self
):
6331 """Tells whether a session has any kind of protection over it:
6332 access or domain protection.
6334 if self
.__ac
.isProtected():
6336 if self
.getDomainList():
6338 if self
.getAccessProtectionLevel() == -1:
6341 return self
.getOwner().hasAnyProtection()
6343 def hasProtectedOwner( self
):
6344 if self
.getOwner() != None:
6345 return self
.getOwner().isProtected()
6348 def setProtection( self
, private
):
6349 self
.__ac
.setProtection( private
)
6350 self
.updateFullyPublic()
6352 def grantAccess( self
, prin
):
6353 self
.__ac
.grantAccess( prin
)
6354 if isinstance(prin
, MaKaC
.user
.Avatar
):
6355 prin
.linkTo(self
, "access")
6357 def revokeAccess( self
, prin
):
6358 self
.__ac
.revokeAccess( prin
)
6359 if isinstance(prin
, MaKaC
.user
.Avatar
):
6360 prin
.unlinkTo(self
, "access")
6362 def canView( self
, aw
):
6363 """tells whether the specified user has access to the current object
6364 or any of its sub-objects
6366 if self
.canAccess( aw
):
6368 ### TODO: Replace this code when plugins allow extension points+notifications ##################
6369 from MaKaC
.webinterface
.rh
.collaboration
import RCCollaborationAdmin
, RCCollaborationPluginAdmin
6370 if RCCollaborationAdmin
.hasRights(user
= aw
.getUser()) or \
6371 RCCollaborationPluginAdmin
.hasRights(user
= aw
.getUser(), plugins
= "any"):
6373 ################################################################################################
6374 for contrib
in self
.getContributionList():
6375 if contrib
.canView( aw
):
6379 def isAllowedToAccess( self
, user
):
6382 if user
in self
.getCoordinatorList() or self
.__ac
.canUserAccess( user
) \
6383 or self
.canUserModify( user
) or (not self
.isItselfProtected() and self
.getOwner().isAllowedToAccess(user
)):
6387 def canAccess( self
, aw
):
6388 # Allow harvesters (Invenio, offline cache) to access
6390 if self
.__ac
.isHarvesterIP(aw
.getIP()):
6392 #####################################################
6394 if not self
.canIPAccess(aw
.getIP()) and not self
.canUserModify(aw
.getUser()) and not self
.isAllowedToAccess( aw
.getUser() ):
6396 if not self
.isProtected():
6398 flag
= self
.isAllowedToAccess( aw
.getUser() )
6399 return flag
or self
.conference
.canKeyAccess( aw
)
6401 def grantModification( self
, sb
, sendEmail
=True ):
6402 if isinstance(sb
, SessionChair
) or isinstance(sb
, SlotChair
):
6404 results
=ah
.match({"email":sb
.getEmail()}, exact
=1)
6407 if sb
.getEmail().lower().strip() in [j
.lower().strip() for j
in i
.getEmails()]:
6410 if r
is not None and r
.isActivated():
6411 self
.__ac
.grantModification( r
)
6412 r
.linkTo(self
, "manager")
6413 elif sb
.getEmail() != "":
6414 modificationEmailGranted
= self
.__ac
.grantModificationEmail(sb
.getEmail())
6415 if modificationEmailGranted
and sendEmail
:
6416 notif
= pendingQueues
._PendingManagerNotification
( [sb
] )
6417 mail
.GenericMailer
.sendAndLog( notif
, self
.getConference() )
6419 self
.__ac
.grantModification( sb
)
6420 if isinstance(sb
, MaKaC
.user
.Avatar
):
6421 sb
.linkTo(self
, "manager")
6423 def revokeModification( self
, prin
):
6424 self
.__ac
.revokeModification( prin
)
6425 if isinstance(prin
, MaKaC
.user
.Avatar
):
6426 prin
.unlinkTo(self
, "manager")
6428 def canModify( self
, aw
):
6429 return self
.canUserModify( aw
.getUser() ) or self
.getConference().canKeyModify( aw
)
6431 def canUserModify( self
, av
):
6432 """Tells whether a user is allowed to modify the current session:
6433 only if the user is granted to modify the session or the user
6434 can modify the corresponding conference.
6436 return self
.getConference().canUserModify( av
) or self
.__ac
.canModify( av
)
6438 def getManagerList( self
):
6439 return self
.__ac
.getModifierList()
6441 def getAllowedToAccessList( self
):
6442 return self
.__ac
.getAccessList()
6444 def addMaterial( self
, newMat
):
6445 newMat
.setId( str(self
.__materialGenerator
.newCount()) )
6446 newMat
.setOwner( self
)
6447 self
.materials
[ newMat
.getId() ] = newMat
6448 self
.notifyModification()
6450 def removeMaterial( self
, mat
):
6451 if mat
.getId() in self
.materials
.keys():
6452 self
.materials
[mat
.getId()].setOwner(None)
6453 del self
.materials
[ mat
.getId() ]
6455 self
.notifyModification()
6456 return "done: %s"%mat
.getId()
6457 elif mat
.getId().lower() == 'minutes':
6458 self
.removeMinutes()
6459 return "done: %s"%mat
.getId()
6460 return "not done: %s"%mat
.getId()
6462 def recoverMaterial(self
, recMat
):
6463 # Id must already be set in recMat.
6464 recMat
.setOwner( self
)
6465 self
.materials
[ recMat
.getId() ] = recMat
6467 self
.notifyModification()
6469 def getMaterialRegistry(self
):
6471 Return the correct material registry for this type
6473 from MaKaC
.webinterface
.materialFactories
import SessionMFRegistry
6474 return SessionMFRegistry
6476 def getMaterialById( self
, matId
):
6477 if matId
.lower() == 'minutes':
6478 return self
.getMinutes()
6479 elif self
.materials
.has_key(matId
):
6480 return self
.materials
[ matId
]
6483 def getMaterialList( self
):
6484 return self
.materials
.values()
6486 def getAllMaterialList( self
):
6487 l
= self
.getMaterialList()
6488 if self
.getMinutes():
6489 l
.append( self
.getMinutes() )
6490 l
.sort(lambda x
,y
: cmp(x
.getTitle(),y
.getTitle()))
6493 def _setSchedule(self
):
6494 self
.__schedule
=SessionSchedule(self
)
6495 sl
=self
.getSlotList()
6496 for slot
in self
.getSlotList():
6497 self
.__schedule
.addEntry(slot
.getSchEntry())
6499 def getSchedule( self
):
6501 if self
.__schedule
is None or not isinstance(self
.__schedule
,SessionSchedule
):
6503 except AttributeError, e
:
6505 return self
.__schedule
6507 def getMasterSchedule( self
):
6508 return self
.getOwner().getSchedule()
6510 def requireDomain( self
, dom
):
6511 self
.__ac
.requireDomain( dom
)
6513 def freeDomain( self
, dom
):
6514 self
.__ac
.freeDomain( dom
)
6516 def getDomainList( self
):
6517 return self
.__ac
.getRequiredDomainList()
6519 def setComments(self
,comm
):
6520 self
._comments
= comm
.strip()
6522 def getComments(self
):
6526 except AttributeError,e
:
6528 return self
._comments
6530 def createMinutes( self
):
6531 if self
.getMinutes() != None:
6532 raise MaKaCError( _("The minutes for this session have already been created"), _("Session"))
6533 self
.minutes
= Minutes()
6534 self
.minutes
.setOwner( self
)
6535 self
.notifyModification()
6538 def removeMinutes( self
):
6539 if self
.minutes
is None:
6541 self
.minutes
.delete()
6542 self
.minutes
.setOwner( None )
6544 self
.notifyModification()
6546 def recoverMinutes(self
, min):
6547 self
.removeMinutes() # To ensure that the current minutes are put in
6550 self
.minutes
.setOwner( self
)
6552 self
.notifyModification()
6555 def getMinutes( self
):
6560 except AttributeError, e
:
6565 def _addCoordinator(self
, av
):
6566 if av
is None or self
._coordinators
.has_key(av
.getId()):
6568 self
._coordinators
[av
.getId()]=av
6569 if self
.getConference() is not None:
6570 self
.getConference().addSessionCoordinator(self
,av
)
6572 def getCoordinatorEmailList(self
):
6574 return self
._coordinatorsEmail
6576 self
._coordinatorsEmail
= []
6577 return self
._coordinatorsEmail
6579 def _addCoordinatorEmail(self
, email
):
6580 if not email
in self
.getCoordinatorEmailList():
6581 self
.getCoordinatorEmailList().append(email
)
6583 def removeCoordinatorEmail(self
, email
):
6584 if email
in self
.getCoordinatorEmailList():
6585 if email
in self
.getCoordinatorEmailList():
6586 self
.getCoordinatorEmailList().remove(email
)
6589 def addCoordinator( self
, sb
, sendEmail
=True ):
6590 """Grants coordination privileges to user.
6593 sb -- It can be either:
6594 (MaKaC.user.Avatar) the user to which
6595 coordination privileges must be granted.
6597 (MaKaC.conference.SessionChair) a non-existing which
6598 has to become indico user before to be granted with privileges.
6601 if self
._coordinators
:
6603 except AttributeError, e
:
6604 self
._coordinators
=OOBTree()
6606 if isinstance(sb
, SessionChair
):
6608 results
=ah
.match({"email":sb
.getEmail()}, exact
=1)
6612 if sb
.getEmail().lower().strip() in [j
.lower().strip() for j
in i
.getEmails()]:
6616 if r
is not None and r
.isActivated():
6618 self
._addCoordinator
(r
)
6619 r
.linkTo(self
, "coordinator")
6621 self
.getConference().getPendingQueuesMgr().addPendingCoordinator(sb
)
6623 self
._addCoordinator
(sb
)
6624 if isinstance(sb
, MaKaC
.user
.Avatar
):
6625 sb
.linkTo(self
, "coordinator")
6627 def removeCoordinator( self
, av
):
6628 """Revokes coordination privileges to user.
6631 av -- (MaKaC.user.Avatar) user for which coordination privileges
6635 if self
._coordinators
:
6637 except AttributeError, e
:
6638 self
._coordinators
=OOBTree()
6640 if av
is None or not self
._coordinators
.has_key(av
.getId()):
6642 del self
._coordinators
[av
.getId()]
6643 if isinstance(av
, MaKaC
.user
.Avatar
):
6644 av
.unlinkTo(self
, "coordinator")
6645 if self
.getConference() is not None:
6646 self
.getConference().removeSessionCoordinator(self
,av
)
6648 def isCoordinator( self
, av
):
6649 """Tells whether the specified user is a coordinator of the session.
6652 av -- (MaKaC.user.Avatar) user to be checked
6654 Return value: (boolean)
6657 if self
._coordinators
:
6659 except AttributeError, e
:
6660 self
._coordinators
=OOBTree()
6661 if (av
is not None) and self
._coordinators
.has_key(av
.getId()):
6664 if isinstance(av
, MaKaC
.user
.Avatar
):
6665 for email
in av
.getEmails():
6666 if email
in self
.getCoordinatorEmailList():
6667 self
.addCoordinator(av
)
6668 self
.removeCoordinatorEmail(email
)
6672 def hasConvenerByEmail(self
, email
):
6673 for convener
in self
.getConvenerList():
6674 if email
== convener
.getEmail():
6679 def getCoordinatorList( self
):
6680 """Return all users which have privileges to coordinate the session.
6682 Return value: (list)
6685 if self
._coordinators
:
6687 except AttributeError, e
:
6688 self
._coordinators
=OOBTree()
6690 return self
._coordinators
.values()
6692 def canCoordinate(self
,aw
, right
=""):
6693 """Tells if a user has coordination privileges.
6695 Only session coordinators have coordination privileges over a
6699 aw -- (MaKaC.accessControl.AccessWrapper) User access
6700 information for which the coordination privileges must be
6703 Return value: (boolean)
6706 return self
.isCoordinator(aw
.getUser()) and self
.getConference().hasSessionCoordinatorRight(right
)
6707 return self
.isCoordinator(aw
.getUser())
6710 def getScheduleType(self
):
6714 except AttributeError:
6715 self
._ttType
=SlotSchTypeFactory
.getDefaultId()
6718 def setScheduleType(self
,t
):
6722 except AttributeError:
6723 self
._ttType
=SlotSchTypeFactory
.getDefaultId()
6724 t
=str(t
).strip().lower()
6725 if t
not in SlotSchTypeFactory
.getIdList() or t
==self
._ttType
:
6728 for slot
in self
.getSlotList():
6729 slot
.setScheduleType(t
)
6731 def getAccessController(self
):
6735 def _cmpTitle( s1
, s2
):
6736 s1
=s1
.getTitle().lower().strip()
6737 s2
=s2
.getTitle().lower().strip()
6738 return cmp( s1
, s2
)
6739 _cmpTitle
=staticmethod(_cmpTitle
)
6741 class SessionSlot(Persistent
, Fossilizable
, Locatable
):
6743 fossilizes(ISessionSlotFossil
)
6745 def __init__(self
,session
,**sessionSlotData
):
6746 self
.session
= session
6747 self
.id = "not assigned"
6750 self
.duration
= timedelta(minutes
=1)
6753 self
._conveners
= []
6754 self
._convenerGen
=Counter()
6755 self
._schedule
=SlotSchTypeFactory
.getDefaultKlass()(self
)
6756 self
._sessionSchEntry
=LinkedTimeSchEntry(self
)
6757 self
._confSchEntry
=LinkedTimeSchEntry(self
)
6758 self
._contributionDuration
= None
6760 def getTimezone( self
):
6761 return self
.getConference().getTimezone()
6763 def getLogInfo(self
):
6765 data
["id"] = self
.id
6766 data
["title"] = self
.title
6767 data
["session"] = self
.session
.getTitle()
6768 data
["start date"] = self
.startDate
6769 data
["duration"] = self
.duration
6771 for p
in self
.places
:
6772 data
["place %s"%i] = p
.getName()
6775 for r
in self
.rooms
:
6776 data
["room %s"%i] = r
.getName()
6778 for c
in self
._conveners
:
6779 data
["convener %s"%c.getId()] = c
.getFullName()
6782 def clone(self
,session
, options
):
6784 slot
= SessionSlot(session
)
6785 slot
.session
= session
6786 slot
.setTitle(self
.getTitle())
6787 timeDifference
= session
.getConference().getStartDate() - self
.getSession().getConference().getStartDate()
6788 slot
.setStartDate(self
.getStartDate() + timeDifference
)
6789 slot
.setDuration(dur
=self
.getDuration(), check
=2)
6792 if self
.getOwnLocation() is not None:
6793 slot
.setLocation(self
.getOwnLocation().clone())
6795 if self
.getOwnRoom() is not None:
6796 slot
.setRoom(self
.getOwnRoom().clone())
6799 for ch
in self
.getOwnConvenerList() :
6800 slot
.addConvener(ch
.clone())
6802 #populate the timetable
6803 if options
.get("contributions", False) :
6804 for entry
in self
.getEntries() :
6805 if isinstance(entry
, BreakTimeSchEntry
) :
6806 newentry
= entry
.clone(slot
)
6807 slot
.getSchedule().addEntry(newentry
,0)
6808 elif isinstance(entry
, ContribSchEntry
) :
6809 contrib
= entry
.getOwner()
6810 newcontrib
= contrib
.clone(session
, options
, timeDifference
)
6811 slot
.getSchedule().addEntry(newcontrib
.getSchEntry(),0)
6812 ContextManager
.setdefault("clone.unique_id_map", {})[contrib
.getUniqueId()] = newcontrib
.getUniqueId()
6814 slot
.setContribDuration(0, 0, self
.getContribDuration())
6815 slot
.notifyModification()
6821 sets the start date of the slot to the start date of the first son
6822 and the end date to the end date of the last son
6824 sch
= self
.getSchedule()
6825 entries
= sch
.getEntries()
6826 if len(entries
) > 0:
6827 self
.setStartDate(entries
[0].getStartDate(),0,0)
6828 self
.setEndDate(sch
.calculateEndDate(), check
=0)
6830 def recalculateTimes( self
, type, diff
):
6832 recalculate and reschedule the contributions of the session slot with a time "diff" of separation.
6834 if type=="duration":
6835 entries
= self
.getSchedule().getEntries()[:]
6837 while i
<len(entries
):
6839 if i
+1 == len(entries
):
6840 dur
=self
.getEndDate()-entry
.getStartDate()
6842 nextentry
=entries
[i
+1]
6843 dur
=nextentry
.getStartDate()-entry
.getStartDate()-diff
6844 if dur
<timedelta(0):
6845 raise EntryTimingError( _("""With the time between entries you've chosen, the entry "%s" will have a duration less than zero minutes. Please, choose another time""")%entry
.getTitle())
6846 entry
.setDuration(dur
=dur
)
6848 if len(entries
) != 0 and self
.getEndDate() < entry
.getEndDate():
6849 self
.setEndDate(entry
.getEndDate(),2)
6850 elif type=="startingTime":
6851 st
= self
.getStartDate()
6852 entries
= self
.getSchedule().getEntries()[:]
6853 for entry
in entries
:
6854 entry
.setStartDate(st
,0,0)
6855 # add diff to last item end date if and only if the item is
6857 #if not isinstance(entry, BreakTimeSchEntry):
6858 # st=entry.getEndDate()+diff
6860 # st=entry.getEndDate()
6861 st
=entry
.getEndDate()+diff
6862 if len(entries
) != 0 and self
.getEndDate() < st
:
6863 self
.setEndDate(st
,2)
6865 def setValues(self
,data
,check
=2, moveEntriesBelow
=0):
6868 1: check and raise error in case of problem
6869 2: check and adapt the owner dates
6872 # In order to move the entries below, it is needed to know the diff (we have to move them)
6873 # and the list of entries to move. It's is needed to take those datas in advance because they
6874 # are going to be modified before the moving.
6875 if moveEntriesBelow
== 1:
6876 oldStartDate
=copy
.copy(self
.getStartDate())
6877 oldDuration
=copy
.copy(self
.getDuration())
6878 i
=self
.getConfSchEntry().getSchedule().getEntries().index(self
.getConfSchEntry())+1
6879 entriesList
= self
.getConfSchEntry().getSchedule().getEntries()[i
:]
6880 self
.title
=data
.get("title", "NO TITLE ASSIGNED")
6881 # Do we move all entries in the slot
6882 move
= int(data
.get("move",0))
6884 if "locationName" in data
:
6885 loc
= self
.getOwnLocation()
6887 loc
= CustomLocation()
6888 self
.setLocation( loc
)
6889 loc
.setName( data
["locationName"] )
6890 loc
.setAddress( data
.get("locationAddress", "") )
6892 self
.setLocation( None )
6894 if "roomName" in data
:
6895 room
= self
.getOwnRoom()
6898 self
.setRoom( room
)
6899 room
.setName( data
["roomName"] )
6901 self
.setRoom( None )
6902 sDate
= eDate
= None
6903 confTZ
= self
.getOwner().getConference().getTimezone()
6904 if data
.get("sDate",None) is not None:
6905 sd
= data
.get("sDate")
6906 sDate
= timezone(confTZ
).localize(datetime(sd
.year
,sd
.month
,sd
.day
,sd
.hour
,sd
.minute
))
6907 elif data
.get("sYear","")!="" and data
.get("sMonth","")!="" and \
6908 data
.get("sDay","")!="" and data
.get("sHour","")!="" and \
6909 data
.get("sMinute","")!="":
6910 sDate
= timezone(confTZ
).localize(datetime(int(data
["sYear"]),int(data
["sMonth"]),
6911 int(data
["sDay"]),int(data
["sHour"]),
6912 int(data
["sMinute"])))
6913 if data
.get("eDate",None) is not None:
6914 ed
= data
.get("eDate")
6915 eDate
= timezone(confTZ
).localize(datetime(ed
.year
,ed
.month
,ed
.day
,ed
.hour
,ed
.minute
))
6916 elif data
.get("eYear","")!="" and data
.get("eMonth","")!="" and \
6917 data
.get("eDay","")!="" and data
.get("eHour","")!="" and \
6918 data
.get("eMinute","")!="":
6919 eDate
= timezone(confTZ
).localize(datetime(int(data
["eYear"]),int(data
["eMonth"]),
6920 int(data
["eDay"]),int(data
["eHour"]),
6921 int(data
["eMinute"])))
6922 if sDate
!= None and eDate
!= None:
6923 sDateUTC
= sDate
.astimezone(timezone('UTC'))
6924 eDateUTC
= eDate
.astimezone(timezone('UTC'))
6925 self
.setDates(sDateUTC
,eDateUTC
,check
,moveEntries
=move
)
6927 sDateUTC
= sDate
.astimezone(timezone('UTC'))
6928 self
.setStartDate(sDateUTC
,check
,moveEntries
=move
)
6929 if data
.get("durHours","")!="" and data
.get("durMins","")!="":
6930 self
.setDuration(hours
=data
["durHours"],minutes
=data
["durMins"],check
=check
)
6931 if data
.get("contribDurHours","")!="" and data
.get("contribDurMins","")!="":
6932 self
.setContribDuration(int(data
["contribDurHours"]),int(data
["contribDurMins"]))
6933 elif data
.get("contribDuration","")!="":
6934 self
.setContribDuration(dur
=data
.get("contribDuration"))
6936 self
.setContribDuration(None,None)
6937 conveners
= data
.get("conveners",None)
6938 if conveners
is not None:
6939 self
.clearConvenerList()
6940 for conv
in conveners
:
6942 sc
.setTitle(conv
.getTitle())
6943 sc
.setFirstName(conv
.getFirstName())
6944 sc
.setFamilyName(conv
.getFamilyName())
6945 sc
.setAffiliation(conv
.getAffiliation())
6946 sc
.setEmail(conv
.getEmail())
6947 self
.addConvener(sc
)
6948 if moveEntriesBelow
== 1:
6949 diff
= (self
.getStartDate() - oldStartDate
) + (self
.getDuration() - oldDuration
)
6950 self
.getSchedule().moveEntriesBelow(diff
, entriesList
)
6951 self
._checkInnerSchedule
()
6952 self
.notifyModification()
6954 def _checkInnerSchedule( self
):
6955 self
.getSchedule().checkSanity()
6957 def setContribDuration(self
, hour
=0, min=0, dur
=None):
6958 self
._contributionDuration
= None
6960 self
._contributionDuration
=dur
6961 elif hour
!= None and min != None:
6962 self
._contributionDuration
= timedelta(hours
=hour
,minutes
=min)
6964 def getContribDuration(self
):
6966 Duration by default for contributions within the slots.
6969 if self
._contributionDuration
:
6971 except AttributeError, e
:
6972 self
._contributionDuration
= None
6973 return self
._contributionDuration
6975 def notifyModification( self
):
6976 self
.getSession().notifyModification()
6979 def getLocator( self
):
6980 l
=self
.getSession().getLocator()
6981 l
["slotId"]=self
.getId()
6984 def getConference( self
):
6985 return self
.getSession().getConference()
6987 def getSession(self
):
6990 def getOwner( self
):
6993 def _setSchedule(self
,klass
):
6994 old_sch
=self
.getSchedule()
6995 self
._schedule
=klass(self
)
6996 #after removing old entries, one could try to fit them into the new
6997 # schedule, but there are several things to consider which are left
6998 # for later implementation (breaks, entries not fitting in the
7000 while len(old_sch
.getEntries())>0:
7001 entry
=old_sch
.getEntries()[0]
7002 old_sch
.removeEntry(entry
)
7003 self
.notifyModification()
7005 def getSchedule(self
):
7006 return self
._schedule
7008 def getMasterSchedule( self
):
7009 return self
.getOwner().getSchedule()
7011 def getConfSchEntry( self
):
7013 if self
._confSchEntry
:
7015 except AttributeError:
7016 self
._confSchEntry
=LinkedTimeSchEntry(self
)
7017 return self
._confSchEntry
7019 def getSessionSchEntry( self
):
7021 if self
._sessionSchEntry
:
7023 except AttributeError:
7024 self
._sessionSchEntry
=self
._schEntry
7025 return self
._sessionSchEntry
7027 def setId( self
, newId
):
7029 self
.notifyModification()
7034 def getUniqueId( self
):
7035 """Returns (string) the unique identiffier of the item.
7036 Used mainly in the web session access key table"""
7037 return "%sl%s" % (self
.getSession().getUniqueId(),self
.id)
7039 def setTitle( self
, newTitle
):
7041 self
.notifyModification()
7043 def getTitle( self
):
7047 except AttributeError,e
:
7051 def getFullTitle( self
):
7052 return self
.getSession().getTitle() + (": " + self
.getTitle() if self
.getTitle() else "")
7055 return "slot %s"%self
.getId()
7057 def getDescription(self
):
7058 return self
.getSession().getDescription()
7060 def setDates(self
,sDate
,eDate
,check
=2,moveEntries
=0):
7063 1: check and raise error in case of problem
7064 2: check and adapt the owner dates"""
7067 raise MaKaCError(_("End date cannot be prior to Start date"),_("Slot"))
7069 self
.setStartDate(sDate
, check
, moveEntries
, checkDuration
=False)
7070 self
.setDuration(0, 0, 0, eDate
-sDate
, check
)
7071 self
.notifyModification()
7073 def getEntries(self
):
7074 entriesList
= self
.getSchedule().getEntries()
7077 def move(self
, sDate
):
7078 diff
=sDate
-self
.startDate
7079 self
.startDate
= sDate
7080 for slotEntry
in self
.getSchedule().getEntries():
7081 if isinstance(slotEntry
, BreakTimeSchEntry
):
7082 slotEntry
.startDate
= slotEntry
.getStartDate() + diff
7084 se
= slotEntry
.getOwner()
7085 se
.startDate
= se
.getStartDate() + diff
7086 self
.getSchedule().reSchedule()
7088 def verifyStartDate(self
, sDate
,check
=2):
7091 1: check and raise error in case of problem
7092 2: check and adapt the owner dates"""
7094 tz
= timezone(self
.getConference().getTimezone())
7096 if sDate
< self
.getSession().getStartDate():
7098 raise ParentTimingError(_("The slot \"%s\" cannot start (%s) before its parent session starts (%s)")%\
7099 (self
.getTitle(), sDate
.astimezone(tz
).strftime('%Y-%m-%d %H:%M'),\
7100 self
.getSession().getStartDate().astimezone(tz
).strftime('%Y-%m-%d %H:%M')),\
7103 self
.getSession().setStartDate(sDate
, check
, 0)
7105 def setStartDate(self
,sDate
,check
=2,moveEntries
=0,checkDuration
=True):
7108 1: check and raise error in case of problem
7109 2: check and adapt the owner dates"""
7112 if not sDate
.tzname():
7113 raise MaKaCError("date should be timezone aware")
7115 #If not using .fit() at the end of this method, comment it out
7116 #if self.getSession().getStartDate() > sDate:
7117 # self.getSession().duration += self.getSession().getStartDate() - sDate
7118 self
.verifyStartDate(sDate
,check
)
7120 # calculate the difference betwwen old and new date
7122 if self
.startDate
is not None:
7123 difference
= sDate
- self
.getStartDate()
7125 self
.startDate
=copy
.copy(sDate
)
7127 if difference
!= None and difference
!= timedelta(0) and moveEntries
:
7128 ContextManager
.get('autoOps').append((self
, "ENTRIES_MOVED",
7129 self
, sDate
.astimezone(timezone(self
.getTimezone()))))
7130 self
.getSchedule().moveEntriesBelow(difference
,self
.getSchedule().getEntries()[:])
7132 if self
.getConference() and not self
.getConference().getEnableSessionSlots() and self
.getSession().getStartDate() != sDate
:
7133 self
.getSession().setStartDate(sDate
, check
, 0)
7134 if check
!= 0 and self
.getSession() and checkDuration
:
7135 self
.verifyDuration(self
.getDuration(), check
=check
)
7137 # synchronize with other timetables
7138 self
.getSessionSchEntry().synchro()
7139 self
.getConfSchEntry().synchro()
7140 self
.getSession().fit()
7141 self
.notifyModification()
7143 def setEndDate(self
,eDate
,check
=2):
7144 if not eDate
.tzname():
7145 raise MaKaCError("date should be timezone aware")
7147 self
.verifyDuration(eDate
-self
.startDate
, check
)
7148 self
.setDuration(dur
=eDate
-self
.startDate
,check
=check
)
7149 if self
.getConference() and not self
.getConference().getEnableSessionSlots() and self
.getSession().getEndDate() != eDate
:
7150 self
.getSession().setEndDate(eDate
, check
)
7151 self
.getSession().fit()
7152 self
.notifyModification()
7154 def getStartDate( self
):
7155 return self
.startDate
7157 def getAdjustedStartDate(self
,tz
=None):
7159 tz
= self
.getConference().getTimezone()
7160 if tz
not in all_timezones
:
7162 return self
.startDate
.astimezone(timezone(tz
))
7164 def getEndDate( self
):
7165 if self
.startDate
is None:
7167 return self
.startDate
+self
.duration
7169 def getAdjustedEndDate( self
, tz
=None ):
7171 tz
= self
.getConference().getTimezone()
7172 if tz
not in all_timezones
:
7174 if self
.getEndDate():
7175 return self
.getEndDate().astimezone(timezone(tz
))
7178 def getDuration( self
):
7179 return self
.duration
7181 def isMoreThanDay(self
):
7182 if self
.getDuration() >= timedelta(days
=1):
7186 def verifyDuration(self
, dur
, check
=1):
7189 1: check and raise error in case of problem
7190 2: check and adapt the owner dates"""
7192 tz
= timezone(self
.getConference().getTimezone())
7193 if dur
<= timedelta(0):
7194 raise MaKaCError( _("The duration cannot be less than zero"), _("Slot"))
7196 raise MaKaCError( _("The duration cannot be more than one day"), _("Slot"))
7197 if self
.startDate
is not None:
7198 sessionStartDate
= self
.getSession().getStartDate()
7199 sessionEndDate
= self
.getSession().getEndDate()
7200 # end date has to be between the session dates
7201 eDate
= self
.startDate
+ dur
7202 if eDate
> sessionEndDate
:
7204 raise EntryTimingError(_("The session slot cannot end (%s) after its parent session (%s)") \
7205 % (eDate
.astimezone(tz
).strftime('%Y-%m-%d %H:%M'),\
7206 sessionEndDate
.astimezone(tz
).strftime('%Y-%m-%d %H:%M')),\
7209 ContextManager
.get('autoOps').append((self
, "OWNER_END_DATE_EXTENDED",
7210 self
.getSession(), eDate
.astimezone(tz
)))
7211 self
.getSession().setEndDate(eDate
,check
)
7212 if eDate
.astimezone(tz
).date() > self
.startDate
.astimezone(tz
).date():
7213 raise TimingError( _("The time slot must end on the same day it has started"), _("Slot"))
7214 # do not modify if slot entries will be affected
7215 sch
= self
.getSchedule()
7216 entries
= sch
.getEntries()
7218 if eDate
< sch
.calculateEndDate():
7219 raise TimingError(_("The session slot cannot end at (%s) because there is a contribution (%s) ending after that time. ")%\
7220 (eDate
.astimezone(tz
).strftime('%Y-%m-%d %H:%M'),\
7221 sch
.calculateEndDate().astimezone(tz
).strftime('%Y-%m-%d %H:%M')),\
7224 def setDuration(self
, days
=0,hours
=0,minutes
=0,dur
=0,check
=1):
7227 1: check and raise error in case of problem
7228 2: check and adapt the owner dates"""
7231 dur
= timedelta(days
=int(days
),hours
=int(hours
),minutes
=int(minutes
))
7232 if dur
==0 and check
==2:
7233 ContextManager
.get('autoOps').append((self
, "DURATION_SET",
7235 dur
= timedelta(minutes
=1)
7236 if dur
> timedelta(days
=1) and check
==2:
7237 pass#dur = timedelta(days=1)
7239 self
.verifyDuration(dur
, check
)
7241 self
.getSessionSchEntry().synchro()
7242 self
.getConfSchEntry().synchro()
7243 self
.getSession().fit()
7244 self
.notifyModification()
7246 def getLocationParent( self
):
7248 Returns the object from which the room/location
7249 information should be inherited
7251 return self
.session
.conference
7254 self
.getSchedule().clear()
7255 if self
.getSession() is not None:
7256 self
.getSession().removeSlot(self
)
7258 TrashCanManager().add(self
)
7261 TrashCanManager().remove(self
)
7263 def canAccess(self
,aw
):
7264 return self
.getSession().canAccess(aw
)
7266 def canView(self
,aw
):
7267 return self
.getSession().canView(aw
)
7269 def isProtected(self
):
7270 return self
.getSession().isProtected()
7272 def getAccessKey( self
):
7273 return self
.getSession().getAccessKey()
7275 def setScheduleType(self
,id):
7276 id=str(id).strip().lower()
7277 currentId
=SlotSchTypeFactory
.getId(self
.getSchedule())
7278 if id not in SlotSchTypeFactory
.getIdList() or id==currentId
:
7280 self
._setSchedule
(SlotSchTypeFactory
.getScheduleKlass(id))
7282 def getConvenerList(self
):
7286 except AttributeError:
7287 self
._conveners
= []
7288 if self
._conveners
== []:
7289 return self
.getSession().getConvenerList()
7290 return self
._conveners
7292 def addConvener(self
,newConv
):
7293 if newConv
in self
._conveners
:
7296 if self
._convenerGen
:
7298 except AttributeError:
7299 self
._convenerGen
=Counter()
7300 id = newConv
.getId()
7302 id=int(self
._convenerGen
.newCount())
7303 newConv
.includeInSlot(self
,id)
7304 self
._conveners
.append(newConv
)
7305 self
.notifyModification()
7307 def removeConvener(self
,conv
):
7308 if conv
not in self
._conveners
:
7310 self
._conveners
.remove(conv
)
7312 self
.notifyModification()
7314 def recoverConvener(self
, con
):
7315 self
.addConvener(con
)
7318 def getConvenerById(self
,id):
7320 for conv
in self
._conveners
:
7321 if conv
.getId()==id:
7325 def getOwnConvenerList(self
):
7329 except AttributeError:
7330 self
._conveners
= []
7331 return self
._conveners
7333 def clearConvenerList(self
):
7334 while len(self
.getOwnConvenerList()) > 0:
7335 self
._conveners
.pop()
7336 self
.notifyModification()
7340 if self
.getSession() is not None:
7341 res
=self
.getSession().getColor()
7344 def getTextColor(self
):
7346 if self
.getSession() is not None:
7347 res
=self
.getSession().getTextColor()
7350 def getAllMaterialList(self
):
7351 return self
.getSession().getAllMaterialList()
7354 class ContributionParticipation(Persistent
, Fossilizable
):
7356 fossilizes(IContributionParticipationFossil
, IContributionParticipationMinimalFossil
,\
7357 IContributionParticipationTTDisplayFossil
,\
7358 IContributionParticipationTTMgmtFossil
)
7360 def __init__( self
):
7361 self
._contrib
= None
7363 self
._firstName
= ""
7366 self
._affiliation
= ""
7372 def _notifyModification( self
):
7373 if self
._contrib
!= None:
7374 self
._contrib
.notifyModification()
7376 def setValues(self
, data
):
7377 self
.setFirstName(data
.get("firstName", ""))
7378 self
.setFamilyName(data
.get("familyName",""))
7379 self
.setAffiliation(data
.get("affilation",""))
7380 self
.setAddress(data
.get("address",""))
7381 self
.setEmail(data
.get("email",""))
7382 self
.setFax(data
.get("fax",""))
7383 self
.setTitle(data
.get("title",""))
7384 self
.setPhone(data
.get("phone",""))
7385 self
._notifyModification
()
7387 def getValues(self
):
7389 data
["firstName"]=self
.getFirstName()
7390 data
["familyName"]=self
.getFamilyName()
7391 data
["affilation"]=self
.getAffiliation()
7392 data
["address"]=self
.getAddress()
7393 data
["email"]=self
.getEmail()
7394 data
["fax"]=self
.getFax()
7395 data
["title"]=self
.getTitle()
7396 data
["phone"]=self
.getPhone()
7400 part
= ContributionParticipation()
7401 part
.setValues(self
.getValues())
7404 def setDataFromAvatar(self
,av
):
7405 # av is an Avatar object.
7408 self
.setFirstName(av
.getName())
7409 self
.setFamilyName(av
.getSurName())
7410 self
.setEmail(av
.getEmail())
7411 self
.setAffiliation(av
.getOrganisation())
7412 self
.setAddress(av
.getAddress())
7413 self
.setPhone(av
.getTelephone())
7414 self
.setTitle(av
.getTitle())
7415 self
.setFax(av
.getFax())
7416 self
._notifyModification
()
7418 def setDataFromOtherCP(self
,cp
):
7419 # cp is a ContributionParticipation object.
7422 self
.setFirstName(cp
.getFirstName())
7423 self
.setFamilyName(cp
.getFamilyName())
7424 self
.setEmail(cp
.getEmail())
7425 self
.setAffiliation(cp
.getAffiliation())
7426 self
.setAddress(cp
.getAddress())
7427 self
.setPhone(cp
.getPhone())
7428 self
.setTitle(cp
.getTitle())
7429 self
.setFax(cp
.getFax())
7430 self
._notifyModification
()
7432 def includeInContribution( self
, contrib
, id ):
7433 if self
.getContribution() == contrib
and self
.getId()==id.strip():
7435 self
._contrib
= contrib
7439 self
._contrib
= None
7440 TrashCanManager().add(self
)
7443 TrashCanManager().remove(self
)
7445 def setId(self
, newId
):
7451 def getContribution( self
):
7452 return self
._contrib
7454 def getConference(self
):
7455 return self
._contrib
.getConference()
7457 def getLocator(self
):
7458 if self
.getContribution() is None:
7460 loc
=self
.getContribution().getLocator()
7461 loc
["authId"]=self
.getId()
7465 contrib
=self
.getContribution()
7466 if contrib
is not None:
7467 conf
=contrib
.getConference()
7468 if conf
is not None:
7469 conf
.unindexAuthor(self
)
7470 conf
.unindexSpeaker(self
)
7473 contrib
=self
.getContribution()
7474 if contrib
is not None:
7475 conf
=contrib
.getConference()
7476 if conf
is not None:
7477 conf
.indexAuthor(self
)
7478 conf
.indexSpeaker(self
)
7480 @Updates ('MaKaC.conference.ContributionParticipation', 'firstName')
7481 def setFirstName( self
, newName
):
7483 if tmp
==self
._firstName
:
7488 self
._notifyModification
()
7490 def getFirstName( self
):
7491 return self
._firstName
7493 def getName( self
):
7494 return self
._firstName
7497 @Updates ('MaKaC.conference.ContributionParticipation', 'familyName')
7498 def setFamilyName( self
, newName
):
7500 if tmp
==self
._surName
:
7505 self
._notifyModification
()
7507 def getFamilyName( self
):
7508 return self
._surName
7510 def getSurName( self
):
7511 return self
._surName
7514 @Updates ('MaKaC.conference.ContributionParticipation', 'email')
7515 def setEmail( self
, newMail
):
7517 if tmp
==self
._email
:
7520 self
._email
=newMail
.strip()
7522 self
._notifyModification
()
7524 def getEmail( self
):
7527 @Updates ('MaKaC.conference.ContributionParticipation', 'affiliation')
7528 def setAffiliation( self
, newAffil
):
7529 self
._affiliation
= newAffil
.strip()
7530 self
._notifyModification
()
7532 def getAffiliation( self
):
7533 if self
._affiliation
.lower() == "unknown":
7535 return self
._affiliation
7537 @Updates ('MaKaC.conference.ContributionParticipation', 'address')
7538 def setAddress( self
, newAddr
):
7539 self
._address
= newAddr
.strip()
7540 self
._notifyModification
()
7542 def getAddress( self
):
7543 return self
._address
7545 @Updates ('MaKaC.conference.ContributionParticipation', 'telephone')
7546 def setPhone( self
, newPhone
):
7547 self
._phone
= newPhone
.strip()
7548 self
._notifyModification
()
7550 def getPhone( self
):
7553 @Updates ('MaKaC.conference.ContributionParticipation', 'title')
7554 def setTitle( self
, newTitle
):
7555 self
._title
= newTitle
.strip()
7556 self
._notifyModification
()
7558 def getTitle( self
):
7561 @Updates ('MaKaC.conference.ContributionParticipation', 'fax')
7562 def setFax( self
, newFax
):
7563 self
._fax
= newFax
.strip()
7564 self
._notifyModification
()
7570 except AttributeError:
7574 def getDirectFullName( self
):
7575 res
= self
.getDirectFullNameNoTitle()
7576 if self
.getTitle() != "":
7577 res
= "%s %s"%( self
.getTitle(), res
)
7580 def getDirectFullNameNoTitle( self
, upper
= True ):
7581 return ("%s %s"%(self
.getFirstName(), self
.getFamilyName().upper() if upper
else self
.getFamilyName())).strip()
7583 def getFullName( self
):
7584 res
= self
.getFullNameNoTitle()
7585 if self
.getTitle() != "":
7586 res
= "%s %s"%( self
.getTitle(), res
)
7589 def getFullNameNoTitle( self
):
7590 res
= self
.getFamilyName().decode('utf-8').upper().encode('utf-8')
7591 if self
.getFirstName() != "":
7592 if res
.strip() != "":
7593 res
= "%s, %s"%( res
, self
.getFirstName() )
7595 res
= self
.getFirstName()
7598 def getAbrName(self
):
7599 res
= self
.getFamilyName()
7600 if self
.getFirstName() != "":
7603 res
= "%s%s."%(res
, self
.getFirstName()[0].upper())
7607 def isPendingSubmitter(self
):
7608 if self
.getContribution() is None:
7610 if self
.getContribution().getConference() is None:
7612 return self
.getContribution().getConference().getPendingQueuesMgr().isPendingSubmitter(self
)
7614 def _cmpFamilyName( cp1
, cp2
):
7615 o1
= "%s %s"%(cp1
.getFamilyName(), cp1
.getFirstName())
7616 o2
= "%s %s"%(cp2
.getFamilyName(), cp2
.getFirstName())
7617 o1
=o1
.lower().strip()
7618 o2
=o2
.lower().strip()
7619 return cmp( o1
, o2
)
7620 _cmpFamilyName
=staticmethod(_cmpFamilyName
)
7623 class AuthorIndex(Persistent
):
7628 def _getKey(self
,author
):
7629 k
= "%s %s %s"%(author
.getFamilyName().lower(),author
.getFirstName().lower(),author
.getEmail().lower())
7632 def index(self
,author
):
7633 key
=self
._getKey
(author
)
7634 if not self
._idx
.has_key(key
):
7639 self
.notifyModification()
7641 def unindex(self
,author
):
7642 key
=self
._getKey
(author
)
7643 if self
._idx
.has_key(key
):
7644 if author
in self
._idx
[key
]:
7648 if len(self
._idx
[key
])<=0:
7650 self
.notifyModification()
7652 def getParticipations(self
):
7653 return self
._idx
.values()
7655 def getById(self
, id):
7656 return self
._idx
.get(id,None)
7658 def getByAuthorObj(self
, auth
):
7659 return self
.getById(self
._getKey
(auth
))
7661 def getParticipationKeys(self
):
7662 return self
._idx
.keys()
7664 def notifyModification(self
):
7665 self
._idx
._p
_changed
= 1
7668 def iteritems(self
):
7669 return self
._idx
.iteritems()
7671 def match(self
, criteria
, exact
=0):
7672 self
._options
= ['organisation', 'surName', 'name', 'email']
7674 for item
in self
.getParticipations():
7677 for f
,v
in criteria
.items():
7678 if f
== 'organisation' and v
!= '':
7679 if (exact
== 0 and item
[0].getAffiliation().lower().find(v
.lower()) == -1) or (exact
== 1 and item
[0].getAffiliation().lower() != v
.lower()):
7683 if f
== 'surName' and v
!= '':
7684 if (exact
== 0 and item
[0].getSurName().lower().find(v
.lower()) == -1) or (exact
== 1 and item
[0].getSurName().lower() != v
.lower()):
7688 if f
== 'name' and v
!= '':
7689 if (exact
== 0 and item
[0].getName().lower().find(v
.lower()) == -1) or (exact
== 1 and item
[0].getName().lower() != v
.lower()):
7693 if f
== 'email' and v
!= '':
7694 if (exact
== 0 and item
[0].getEmail().lower().find(v
.lower()) == -1) or (exact
== 1 and item
[0].getEmail().lower() != v
.lower()):
7698 if len(ok
) > 0 and not False in ok
:
7702 class _AuthIdx(Persistent
):
7704 def __init__(self
,conf
):
7708 def _getKey(self
,auth
):
7709 return "%s %s"%(auth
.getFamilyName().lower(),auth
.getFirstName().lower())
7711 def index(self
,auth
):
7712 if auth
.getContribution() is None:
7713 raise MaKaCError( _("Cannot index an author of a contribution which has not been included in a Conference"), _("Author Index"))
7714 if auth
.getContribution().getConference()!=self
._conf
:
7715 raise MaKaCError( _("cannot index an author of a contribution which does not belong to this Conference"), _("Author Index"))
7716 key
=self
._getKey
(auth
)
7717 contribId
=str(auth
.getContribution().getId())
7718 if not self
._idx
.has_key(key
):
7719 self
._idx
[key
]=OIBTree()
7720 if not self
._idx
[key
].has_key(contribId
):
7721 self
._idx
[key
][contribId
]=0
7722 self
._idx
[key
][contribId
]+=1
7724 def unindex(self
,auth
):
7725 if auth
.getContribution() is None:
7726 raise MaKaCError( _("Cannot unindex an author of a contribution which is not included in a conference"), _("Author Index"))
7727 if auth
.getContribution().getConference()!=self
._conf
:
7728 raise MaKaCError( _("Cannot unindex an author of a contribution which does not belong to this conference"), _("Author Index"))
7729 key
=self
._getKey
(auth
)
7730 if not self
._idx
.has_key(key
):
7732 contribId
=str(auth
.getContribution().getId())
7733 self
._idx
[key
][contribId
]-=1
7734 if self
._idx
[key
][contribId
]<=0:
7735 del self
._idx
[key
][contribId
]
7736 if len(self
._idx
[key
])<=0:
7739 def match(self
,query
):
7740 query
=query
.lower().strip()
7742 for k
in self
._idx
.keys():
7743 if k
.find(query
)!=-1:
7744 res
=union(res
,self
._idx
[k
])
7748 class _PrimAuthIdx(_AuthIdx
):
7750 def __init__(self
,conf
):
7751 _AuthIdx
.__init
__(self
,conf
)
7752 for contrib
in self
._conf
.getContributionList():
7753 for auth
in contrib
.getPrimaryAuthorList():
7756 class Contribution(CommonObjectBase
, Locatable
):
7757 """This class implements a conference contribution, being the concrete
7758 contributes of the conference participants. The class contains
7759 necessary attributes to store contribution basic meta data and provides
7760 the useful operations to access and manage them. A contribution can be
7761 attached either to a session or to a conference.
7764 fossilizes(IContributionFossil
, IContributionWithSpeakersFossil
,\
7765 IContributionWithSubContribsFossil
)
7767 def __init__(self
,**contribData
):
7773 self
.description
= ""
7775 self
.duration
= timedelta(0)
7777 self
.speakerText
= ""
7780 self
._boardNumber
=""
7781 self
._resetSchEntry
()
7782 self
.__ac
= AccessController(self
)
7784 self
.__materialGenerator
= Counter()
7786 self
.__subContGenerator
= Counter()
7792 self
.reviewing
= None
7793 self
._authorGen
= Counter()
7794 self
._authors
= OOBTree()
7795 self
._primaryAuthors
= []
7796 self
._coAuthors
= []
7800 self
._status
=ContribStatusNotSch(self
)
7801 #List of allowed users to submit material
7803 self
._submittersEmail
=[]
7804 self
._modificationDS
= nowutc()
7806 self
._reviewManager
= ReviewManager(self
)
7810 parentId
= self
.parent
.getId()
7813 return "<Contribution %s:%s@%s>" % (parentId
, self
.getId(), hex(id(self
)))
7815 def getTimezone( self
):
7816 return self
.getConference().getTimezone()
7818 def getReviewManager(self
):
7819 if not hasattr(self
, "_reviewManager"):
7820 self
._reviewManager
= ReviewManager(self
)
7821 return self
._reviewManager
7823 def isFullyPublic( self
):
7824 if hasattr(self
, "_fullyPublic"):
7825 return self
._fullyPublic
7827 self
.setFullyPublic()
7828 return self
._fullyPublic
7830 def setFullyPublic( self
):
7831 if self
.isProtected():
7832 self
._fullyPublic
= False
7835 for res
in self
.getAllMaterialList():
7836 if not res
.isFullyPublic():
7837 self
._fullyPublic
= False
7840 for res
in self
.getSubContributionList():
7841 if not res
.isFullyPublic():
7842 self
._fullyPublic
= False
7845 self
._fullyPublic
= True
7848 def updateFullyPublic( self
):
7849 self
.setFullyPublic()
7850 self
.getOwner().updateFullyPublic()
7852 def getKeywords(self
):
7854 return self
._keywords
7859 def setKeywords(self
, keywords
):
7860 if type(keywords
) is list:
7861 self
._keywords
= keywords
[0]
7863 self
._keywords
= keywords
7864 self
.notifyModification()
7866 def getFields( self
):
7872 if self
.summary
!= "":
7873 self
._fields
["summary"] = self
.summary
7879 def removeField( self
, field
):
7880 if self
.getFields().has_key(field
):
7881 del self
.getFields()[field
]
7882 self
.notifyModification()
7884 def setField( self
, field
, value
):
7886 self
.getFields()[field
] = value
7887 self
.notifyModification()
7891 def getField( self
, field
):
7892 if self
.getFields().has_key(field
):
7893 value
= self
.getFields()[field
]
7894 if type(value
) is list:
7895 return "".join(value
)
7903 def getLogInfo(self
):
7905 data
["subject"] = self
.getTitle()
7906 data
["id"] = self
.id
7907 data
["title"] = self
.title
7908 data
["parent title"] = self
.parent
.getTitle()
7909 if self
._session
is not None :
7910 data
["session title"] = self
._session
.getTitle()
7911 data
["description"] = self
.description
7912 if self
.getConference():
7913 afm
= self
.getConference().getAbstractMgr().getAbstractFieldsMgr()
7914 for f
in afm
.getFields():
7916 data
[id] = self
.getField(id)
7917 data
["start date"] = "%s"%self
.startDate
7918 data
["duration"] = "%s"%self
.duration
7919 if self
._track
is not None :
7920 data
["track"] = self
._track
.getTitle()
7921 if self
._type
is not None :
7922 data
["type"] = self
._type
7923 data
["speaker text"] = self
.speakerText
7924 if self
.place
is not None :
7925 data
["place"] = self
.place
.getName()
7926 if self
.room
is not None :
7927 data
["room"] = self
.room
.getName()
7928 data
["board number"] = self
._boardNumber
7929 for sc
in self
.getSubContributionList() :
7930 data
["subcontribution %s"%sc.getId()] = sc
.getTitle()
7931 for pa
in self
._primaryAuthors
:
7932 data
["primary author %s"%pa
.getId()] = pa
.getFullName()
7933 for ca
in self
._coAuthors
:
7934 data
["co-author %s"%ca
.getId()] = ca
.getFullName()
7935 for sp
in self
._speakers
:
7936 data
["speaker %s"%sp
.getId()] = sp
.getFullName()
7937 for s
in self
._submitters
:
7938 if isinstance(s
, MaKaC
.user
.Avatar
):
7939 data
["submitter"] = s
.getFullName()
7941 data
["submitter"] = s
.getName()
7945 def setValues( self
, data
, check
=2, moveEntriesBelow
=0):
7946 """Sets all the values of the current contribution object from a
7947 dictionary containing the following key-value pairs:
7950 locationName-(str) => name of the location, if not specified
7951 it will be set to the parent location name.
7952 locationAddress-(str)
7953 roomName-(str) => name of the room, if not specified it will
7954 be set to the parent room name.
7955 year, month, day, sHour, sMinute - (str) => components of the
7956 starting date of the session, if not specified it will
7958 durationHours, durationMinutes - (str)
7962 1: check and raise error in case of problem
7963 2: check and adapt the owner dates
7966 1: moveEntries below the contribution
7967 Please, note that this method sets ALL values which means that if
7968 the given dictionary doesn't contain any of the keys the value
7969 will set to a default value.
7972 # In order to move the entries below, it is needed to know the diff (we have to move them)
7973 # and the list of entries to move. It's is needed to take those datas in advance because they
7974 # are going to be modified before the moving.
7975 if moveEntriesBelow
== 1:
7976 oldStartDate
=copy
.copy(self
.getStartDate())
7977 oldDuration
=copy
.copy(self
.getDuration())
7978 i
=self
.getSchEntry().getSchedule().getEntries().index(self
.getSchEntry())+1
7979 entriesList
= self
.getSchEntry().getSchedule().getEntries()[i
:]
7980 if data
.has_key("title"):
7981 self
.setTitle(data
["title"])
7982 if data
.has_key("keywords"):
7983 self
.setKeywords(data
["keywords"])
7984 if data
.has_key("description"):
7985 self
.setDescription(data
["description"])
7986 if data
.has_key("type") and self
.getConference():
7987 self
.setType(self
.getConference().getContribTypeById(data
["type"]))
7988 if self
.getConference():
7989 afm
= self
.getConference().getAbstractMgr().getAbstractFieldsMgr()
7990 for f
in afm
.getFields():
7992 if data
.has_key("f_%s"%id):
7993 self
.setField(id, data
["f_%s"%id])
7995 if "locationName" in data
:
7996 loc
=self
.getOwnLocation()
7998 loc
=CustomLocation()
7999 self
.setLocation(loc
)
8000 loc
.setName(data
["locationName"])
8001 loc
.setAddress(data
.get("locationAddress", ""))
8003 self
.setLocation(None)
8005 #same as for the location
8006 if "roomName" in data
:
8007 room
=self
.getOwnRoom()
8011 room
.setName(data
["roomName"])
8012 room
.retrieveFullName(data
.get("locationName", ""))
8017 if self
.getConference():
8018 tz
= self
.getConference().getTimezone()
8019 if data
.get("targetDay","")!="" and data
.get("sHour","")!="" and data
.get("sMinute","")!="" and check
==2:
8020 ############################################
8021 # Fermi timezone awareness #
8022 ############################################
8023 me
= timezone(tz
).localize(datetime(int(data
["targetDay"][0:4]), \
8024 int(data
["targetDay"][5:7]),int(data
["targetDay"][8:])))
8025 sdate
= timezone(tz
).localize(datetime(me
.year
,me
.month
, \
8026 me
.day
,int(data
["sHour"]),int(data
["sMinute"])))
8027 self
.setStartDate(sdate
.astimezone(timezone('UTC')),check
=2)
8028 if data
.get("sYear","")!="" and data
.get("sMonth","")!="" and \
8029 data
.get("sDay","")!="" and data
.get("sHour","")!="" and \
8030 data
.get("sMinute","")!="":
8031 self
.setStartDate(timezone(tz
).localize(datetime(int(data
["sYear"]),
8032 int(data
["sMonth"]), int(data
["sDay"]),
8033 int(data
["sHour"]), int(data
["sMinute"]))).astimezone(timezone('UTC')),
8035 ############################################
8036 # Fermi timezone awareness(end) #
8037 ############################################
8038 if data
.get("durTimedelta", "") != "":
8039 self
.setDuration(check
=check
, dur
=data
["durTimedelta"])
8040 elif data
.get("durHours","")!="" and data
.get("durMins","")!="":
8041 self
.setDuration(data
["durHours"],data
["durMins"],check
)
8043 h
=data
.get("durHours","").strip()
8044 m
=data
.get("durMins","").strip()
8048 if h
!="0" or m
!="0":
8049 self
.setDuration(int(h
), int(m
),check
)
8050 if data
.has_key("boardNumber"):
8051 self
.setBoardNumber(data
.get("boardNumber",""))
8052 if moveEntriesBelow
== 1:
8053 diff
= (self
.getStartDate() - oldStartDate
) + (self
.getDuration() - oldDuration
)
8054 self
.getConference().getSchedule().moveEntriesBelow(diff
, entriesList
)
8055 self
.notifyModification()
8057 def clone(self
, parent
, options
, deltaTime
= 0):
8058 cont
= Contribution()
8059 parent
.addContribution(cont
)
8060 cont
.setTitle( self
.getTitle() )
8061 cont
.setDescription( self
.getDescription() )
8062 for k
in self
.getFields().keys():
8063 cont
.setField(k
, self
.getField(k
))
8064 cont
.setKeywords( self
.getKeywords() )
8066 deltaTime
= parent
.getStartDate() - self
.getOwner().getStartDate()
8069 if self
.startDate
is not None :
8070 startDate
= self
.getStartDate() + deltaTime
8071 cont
.setStartDate( startDate
)
8073 cont
.setDuration( dur
=self
.getDuration() )
8075 if self
.getOwnLocation() is not None:
8076 cont
.setLocation(self
.getOwnLocation().clone())
8077 if self
.getOwnRoom() is not None:
8078 cont
.setRoom(self
.getOwnRoom().clone())
8079 cont
.setBoardNumber(self
.getBoardNumber())
8080 cont
.setReportNumberHolder(self
.getReportNumberHolder().clone(self
))
8082 cont
.setStatus(self
.getCurrentStatus())
8084 if self
.getType() is not None :
8085 for ct
in cont
.getConference().getContribTypeList() :
8086 if ct
.getName() == self
.getType().getName() :
8090 if options
.get("tracks", False) :
8091 if self
.getTrack() is not None :
8092 for tr
in cont
.getConference().getTrackList() :
8093 if tr
.getTitle() == self
.getTrack().getTitle() :
8099 if options
.get("access", False) :
8100 cont
.setProtection(self
.getAccessController()._getAccessProtection
())
8101 for u
in self
.getAllowedToAccessList() :
8103 for mgr
in self
.getManagerList() :
8104 cont
.grantModification(mgr
)
8105 for sub
in self
.getSubmitterList() :
8106 cont
.grantSubmission(sub
)
8107 for domain
in self
.getDomainList():
8108 cont
.requireDomain(domain
)
8110 if options
.get("authors", False) :
8111 for a
in self
.getPrimaryAuthorList() :
8112 cont
.addPrimaryAuthor(a
.clone())
8113 for ca
in self
.getCoAuthorList() :
8114 cont
.addCoAuthor(ca
.clone())
8115 for sp
in self
.getSpeakerList():
8116 cont
.newSpeaker(sp
.clone())
8117 cont
.setSpeakerText(self
.getSpeakerText())
8119 if options
.get("materials", False) :
8120 for m
in self
.getMaterialList() :
8121 cont
.addMaterial(m
.clone(cont
))
8122 if self
.getPaper() is not None:
8123 cont
.setPaper(self
.getPaper().clone(cont
))
8124 if self
.getSlides() is not None:
8125 cont
.setSlides(self
.getSlides().clone(cont
))
8126 if self
.getVideo() is not None:
8127 cont
.setVideo(self
.getVideo().clone(cont
))
8128 if self
.getPoster() is not None:
8129 cont
.setPoster(self
.getPoster().clone(cont
))
8130 if self
.getMinutes() is not None:
8131 cont
.setMinutes(self
.getMinutes().clone(cont
))
8132 if self
.getReviewing() is not None:
8133 cont
.setReviewing(self
.getReviewing().clone(cont
))
8135 if options
.get("subcontribs", False) :
8136 for sc
in self
.getSubContributionList() :
8137 cont
.addSubContribution(sc
.clone(cont
, self
, options
))
8140 def notifyModification( self
, date
= None, raiseEvent
= True):
8142 self
.setModificationDate(date
)
8145 self
._notify
('infoChanged')
8147 parent
= self
.getParent()
8149 parent
.setModificationDate()
8152 def getCategoriesPath(self
):
8153 return self
.getConference().getCategoriesPath()
8155 def getModifKey( self
):
8156 return self
.getConference().getModifKey()
8158 def getAccessKey( self
):
8159 return self
.getConference().getAccessKey()
8161 def getLocator( self
):
8162 """Gives back a globaly unique identification encapsulated in a Locator
8163 object for the contribution instance
8165 if self
.getConference() == None:
8167 lconf
= self
.getConference().getLocator()
8168 if self
.getSession() is not None:
8169 lconf
["sessionId"] = self
.getSession().getId()
8170 lconf
["contribId"] = self
.getId()
8173 def _setConference( self
, conf
):
8176 def _setId( self
, id ):
8179 def includeInConference( self
, conf
, id ):
8180 """sets the conference of a contribution
8182 if self
.getConference() is not None:
8183 #raise MaKaCError("the contribution is already included in a conference")
8186 self
._setConference
( conf
)
8190 """deletes a contribution and all of its subitems
8193 oldParent
= self
.getConference()
8195 if oldParent
!= None:
8196 self
._notify
('deleted', oldParent
)
8199 self
.setSession(None)
8200 for mat
in self
.getMaterialList():
8201 self
.removeMaterial(mat
)
8206 self
.removeMinutes()
8207 self
.removeReviewing()
8209 while len(self
.getSubContributionList()) > 0:
8211 sc
= self
.getSubContributionList()[0]
8213 self
.removeSubContribution(sc
)
8216 # delete it from parent session (if it exists)
8217 if self
.getOwner() != self
.getConference():
8219 self
.getOwner().removeContribution( self
)
8221 # (always) delete it from the parent conference
8222 self
.getConference().removeContribution( self
, callDelete
=False )
8224 self
._setConference
( None )
8226 self
.setStatus(ContribStatusNone(self
))
8227 TrashCanManager().add(self
)
8230 TrashCanManager().remove(self
)
8232 def setId( self
, newId
):
8238 def getUniqueId( self
):
8239 """returns (string) the unique identifier of the item"""
8240 """used mainly in the web session access key table"""
8241 return "%st%s" % (self
.getConference().getUniqueId(),self
.id)
8243 def setTitle( self
, newTitle
, notify
= True ):
8244 oldTitle
= self
.title
8245 self
.title
= newTitle
.strip()
8248 self
._notify
('contributionTitleChanged', oldTitle
, newTitle
)
8249 self
.notifyModification()
8251 def getTitle( self
):
8252 if self
.title
.strip() == "":
8256 #def setDescription( self, newDesc ):
8257 # self.description = newDesc.strip()
8258 # self.notifyModification()
8260 #def getDescription( self ):
8261 # return self.description
8263 def getDescription(self
):
8264 return self
.getField("content")
8266 def setDescription(self
, desc
):
8267 self
.setField("content", desc
)
8269 def setParent(self
,parent
):
8271 self
.notifyModification()
8272 if self
.parent
==None:
8275 def getParent( self
):
8276 if self
.getSession() is not None:
8277 return self
.getSession()
8278 return self
.getConference()
8280 def getOwner( self
):
8281 return self
.getParent()
8283 def setOwner(self
, owner
):
8284 self
.setParent(owner
)
8286 def getConference( self
):
8289 def getSession( self
):
8293 except AttributeError:
8295 return self
._session
8297 def setSession(self
,session
):
8298 if self
.getSession()==session
:
8300 if self
.isScheduled():
8301 schEntry
=self
.getSchEntry()
8302 schEntry
.getSchedule().removeEntry(schEntry
)
8303 oldSession
=self
.getSession()
8304 if oldSession
is not None:
8305 oldSession
.removeContribution(self
)
8306 self
._session
=session
8307 if session
is not None:
8308 session
.addContribution(self
)
8310 def getContribution(self
):
8313 def _resetSchEntry(self
):
8314 self
.__schEntry
=ContribSchEntry(self
)
8316 def getSchEntry(self
):
8317 if self
.__schEntry
is None or \
8318 not isinstance(self
.__schEntry
,ContribSchEntry
):
8319 self
._resetSchEntry
()
8320 return self
.__schEntry
8322 def isScheduled(self
):
8323 #For the moment we do it like this
8324 return self
.getSchEntry().getSchedule() is not None
8326 def isWithdrawn(self
):
8327 return isinstance(self
.getCurrentStatus(), ContribStatusWithdrawn
)
8329 def getLocationParent( self
):
8331 Returns the object from which the room/location
8332 information should be inherited
8334 if not self
.getConference().getEnableSessionSlots() and self
.getSession():
8335 return self
.getSession()
8336 if self
.isScheduled():
8337 return self
.getSchEntry().getSchedule().getOwner()
8338 return self
.getOwner()
8340 def getOwnLocation( self
):
8343 def setLocation( self
, newLocation
):
8344 oldLocation
= self
.place
8345 self
.place
= newLocation
8346 self
._notify
('locationChanged', oldLocation
, newLocation
)
8347 self
.notifyModification()
8349 def getOwnRoom( self
):
8352 def setRoom( self
, newRoom
):
8355 self
._notify
('roomChanged', oldRoom
, newRoom
)
8356 self
.notifyModification()
8358 def setBoardNumber(self
,newBoardNum
):
8359 self
._boardNumber
=str(newBoardNum
).strip()
8361 def getBoardNumber(self
):
8363 if self
._boardNumber
:
8365 except AttributeError:
8366 self
._boardNumber
=""
8367 return self
._boardNumber
8369 def verifyStartDate(self
, sDate
, check
=2):
8372 1: check and raise error in case of problem
8373 2: check and adapt the owner dates"""
8375 tz
= timezone(self
.getConference().getTimezone())
8376 if self
.getSchEntry().getSchedule():
8377 owner
= self
.getSchEntry().getSchedule().getOwner()
8379 owner
= self
.getOwner()
8380 if sDate
< owner
.getStartDate():
8382 raise ParentTimingError(_("The contribution <i>\"%s\"</i> cannot start before (%s) its parent (%s)") %\
8383 (self
.getTitle(), sDate
.astimezone(tz
).strftime('%Y-%m-%d %H:%M'),\
8384 owner
.getStartDate().astimezone(tz
).strftime('%Y-%m-%d %H:%M')),\
8387 ContextManager
.get('autoOps').append((self
, "OWNER_START_DATE_EXTENDED",
8388 owner
, sDate
.astimezone(tz
)))
8389 owner
.setDates(sDate
,owner
.getEndDate(), check
)
8390 if sDate
> owner
.getEndDate():
8392 raise ParentTimingError(_("The contribution <i>\"%s\"</i> cannot start after (%s) its parent end date(%s)") %\
8393 (self
.getTitle(), sDate
.astimezone(tz
).strftime('%Y-%m-%d %H:%M'),\
8394 owner
.getEndDate().astimezone(tz
).strftime('%Y-%m-%d %H:%M')),\
8397 owner
.setEndDate(sDate
+self
.getDuration(),check
)
8398 # Check that after modifying the start date, the end date is still within the limits of the slot
8399 if self
.getDuration() and sDate
+ self
.getDuration() > owner
.getEndDate():
8401 raise ParentTimingError("The contribution cannot end after (%s) its parent ends (%s)"%\
8402 ((sDate
+ self
.getDuration()).astimezone(tz
).strftime('%Y-%m-%d %H:%M'),\
8403 owner
.getAdjustedEndDate().strftime('%Y-%m-%d %H:%M')),\
8406 # update the schedule
8407 owner
.setEndDate(sDate
+ self
.getDuration(),check
)
8408 ContextManager
.get('autoOps').append((self
, "OWNER_END_DATE_EXTENDED",
8409 owner
, owner
.getAdjustedEndDate()))
8411 def setStartDate(self
, newDate
, check
=2, moveEntries
=0):
8414 1: check and raise error in case of problem
8415 2: check and adapt the owner dates"""
8419 if not newDate
.tzname():
8420 raise MaKaCError("date should be timezone aware")
8422 if newDate
!= None and check
!= 0:
8423 self
.verifyStartDate(newDate
, check
)
8424 self
._notify
("contributionUnscheduled")
8425 self
.startDate
=copy
.copy(newDate
)
8426 self
._notify
("contributionScheduled")
8427 self
.getSchEntry().synchro()
8428 self
.notifyModification()
8430 def getStartDate( self
):
8431 return self
.startDate
8433 def getAdjustedStartDate(self
,tz
=None):
8434 if self
.getStartDate() is None:
8437 tz
= self
.getConference().getTimezone()
8438 if tz
not in all_timezones
:
8440 return self
.getStartDate().astimezone(timezone(tz
))
8442 def getEndDate( self
):
8443 if self
.getStartDate() is None:
8445 return self
.getStartDate()+self
.getDuration()
8447 def getAdjustedEndDate(self
,tz
=None):
8449 tz
= self
.getConference().getTimezone()
8450 if tz
not in all_timezones
:
8452 if self
.getEndDate():
8453 return self
.getEndDate().astimezone(timezone(tz
))
8456 def getDuration( self
):
8457 return self
.duration
8459 def verifyDuration(self
, check
=2):
8462 1: check and raise error in case of problem
8463 2: check and adapt the owner dates"""
8465 tz
= timezone(self
.getConference().getTimezone())
8467 endDate
= self
.getEndDate()
8469 if self
.getSchEntry().getSchedule() is not None:
8470 owner
= self
.getSchEntry().getSchedule().getOwner()
8471 if endDate
> owner
.getEndDate():
8473 raise ParentTimingError(_("The contribution \"%s\" ending date (%s) has to fit between its parent's dates (%s - %s)") %\
8474 (self
.getTitle(), endDate
.astimezone(tz
).strftime('%Y-%m-%d %H:%M'),\
8475 owner
.getStartDate().astimezone(tz
).strftime('%Y-%m-%d %H:%M'),\
8476 owner
.getEndDate().astimezone(tz
).strftime('%Y-%m-%d %H:%M')),\
8479 ContextManager
.get('autoOps').append((self
, "OWNER_END_DATE_EXTENDED",
8480 owner
, self
.getAdjustedEndDate()))
8481 owner
.setEndDate(endDate
, check
)
8483 def setDuration(self
,hours
=0,minutes
=15,check
=2,dur
=0):
8486 1: check and raise error in case of problem
8487 2: check and adapt the owner dates"""
8492 self
.duration
=timedelta(hours
=int(hours
),minutes
=int(minutes
))
8494 self
.verifyDuration(check
)
8495 self
.getSchEntry().synchro()
8496 self
.notifyModification()
8498 def _addAuthor( self
, part
):
8504 except AttributeError:
8505 self
._authors
= OOBTree()
8509 except AttributeError:
8510 self
._authorGen
=Counter()
8511 newId
= part
.getId()
8513 newId
= str( self
._authorGen
.newCount() )
8514 self
._authors
[newId
] = part
8515 part
.includeInContribution( self
, newId
)
8517 def _removeAuthor( self
, part
):
8523 except AttributeError:
8524 self
._authors
= OOBTree()
8525 if not self
._authors
.has_key( part
.getId() ):
8527 del self
._authors
[ part
.getId() ]
8530 def addPrimaryAuthor( self
, part
, index
= None ):
8534 if self
._primaryAuthors
:
8536 except AttributeError:
8537 self
._primaryAuthors
= []
8538 self
._addAuthor
( part
)
8539 if index
is not None:
8540 self
._primaryAuthors
.insert(index
, part
)
8542 self
._primaryAuthors
.append( part
)
8543 if self
.getConference() is not None:
8544 self
.getConference().indexAuthor(part
)
8545 self
.notifyModification()
8547 def removePrimaryAuthor( self
, part
, removeSpeaker
=1, removePendingSubm
=True):
8551 if self
._primaryAuthors
:
8553 except AttributeError:
8554 self
._primaryAuthors
= []
8555 if part
not in self
._primaryAuthors
:
8557 if self
.getConference() is not None:
8558 self
.getConference().unindexAuthor(part
)
8559 self
._primaryAuthors
.remove( part
)
8561 self
.removeSpeaker( part
)
8562 self
._removeAuthor
( part
)
8563 if removePendingSubm
:
8564 #--Pending queue: remove pending participant waiting to became submitter if anything
8565 self
.getConference().getPendingQueuesMgr().removePendingSubmitter(part
)
8567 self
.notifyModification()
8569 def recoverPrimaryAuthor(self
, pa
, isPendingSubmitter
):
8570 self
.addPrimaryAuthor(pa
)
8572 if isPendingSubmitter
:
8573 self
.getConference().getPendingQueuesMgr().addPendingSubmitter(pa
, False)
8575 def isPrimaryAuthor( self
, part
):
8579 if self
._primaryAuthors
:
8581 except AttributeError:
8582 self
._primaryAuthors
= []
8583 return part
in self
._primaryAuthors
8585 def isCoAuthor(self
, part
):
8589 except AttributeError:
8590 self
._coAuthors
= []
8591 return part
in self
._coAuthors
8593 def isPrimaryAuthorByEmail(self
, email
):
8594 for prAuthor
in self
.getPrimaryAuthorList():
8595 if prAuthor
.getEmail() == email
:
8599 def isCoAuthorByEmail(self
, email
):
8600 for coAuthor
in self
.getCoAuthorList():
8601 if coAuthor
.getEmail() == email
:
8605 def isSpeakerByEmail(self
, email
):
8606 for speaker
in self
.getSpeakerList():
8607 if speaker
.getEmail() == email
:
8611 def changePosPrimaryAuthor(self
,part
,index
):
8615 if self
._primaryAuthors
:
8617 except AttributeError:
8618 self
._primaryAuthors
=[]
8619 if not part
in self
._primaryAuthors
:
8621 self
._primaryAuthors
.remove(part
)
8622 self
._primaryAuthors
.insert(index
,part
)
8623 self
.notifyModification()
8625 def upPrimaryAuthor(self
,part
):
8629 if self
._primaryAuthors
:
8631 except AttributeError:
8632 self
._primaryAuthors
=[]
8634 idx
=self
._primaryAuthors
.index(part
)
8639 self
._primaryAuthors
.remove(part
)
8640 self
._primaryAuthors
.insert(idx
-1,part
)
8641 self
.notifyModification()
8643 def downPrimaryAuthor(self
,part
):
8647 if self
._primaryAuthors
:
8649 except AttributeError:
8650 self
._primaryAuthors
=[]
8652 idx
=self
._primaryAuthors
.index(part
)
8655 if idx
>len(self
._primaryAuthors
):
8657 self
._primaryAuthors
.remove(part
)
8658 self
._primaryAuthors
.insert(idx
+1,part
)
8659 self
.notifyModification()
8661 def newAuthorsList(self
, prAuthors
, coAuthors
):
8662 ''' calculate new lists of both kind of authors, because something has
8663 been changed the position by drag and drop '''
8664 newPrList
= self
.calculateNewAuthorList(prAuthors
, "prAuthor")
8665 newCoList
= self
.calculateNewAuthorList(coAuthors
, "coAuthor")
8666 self
.setPrimaryAuthorList(newPrList
)
8667 self
.setCoAuthorList(newCoList
)
8669 def calculateNewAuthorList(self
, list, kind
):
8671 if kind
== "prAuthor":
8673 author
= self
.getPrimaryAuthorById(auth
['id'])
8675 result
.append(author
)
8677 author
= self
.getCoAuthorById(auth
['id'])
8679 result
.append(author
)
8681 elif kind
== "coAuthor":
8683 author
= self
.getCoAuthorById(auth
['id'])
8685 result
.append(author
)
8687 author
= self
.getPrimaryAuthorById(auth
['id'])
8689 result
.append(author
)
8693 def getPrimaryAuthorById(self
, authorId
):
8694 for author
in self
.getPrimaryAuthorList():
8695 if authorId
== author
.getId():
8699 def getCoAuthorById(self
, authorId
):
8700 for author
in self
.getCoAuthorList():
8701 if authorId
== author
.getId():
8705 def setPrimaryAuthorList(self
, l
):
8706 self
._primaryAuthors
= l
8707 self
.notifyModification()
8709 def setCoAuthorList(self
, l
):
8711 self
.notifyModification()
8713 def changePosCoAuthor(self
, part
, index
):
8719 except AttributeError:
8721 if not part
in self
._coAuthors
:
8723 self
._coAuthors
.remove(part
)
8724 self
._coAuthors
.insert(index
,part
)
8725 self
.notifyModification()
8728 def upCoAuthor(self
,part
):
8734 except AttributeError:
8737 idx
=self
._coAuthors
.index(part
)
8742 self
._coAuthors
.remove(part
)
8743 self
._coAuthors
.insert(idx
-1,part
)
8744 self
.notifyModification()
8746 def downCoAuthor(self
,part
):
8752 except AttributeError:
8755 idx
=self
._coAuthors
.index(part
)
8758 if idx
>len(self
._coAuthors
):
8760 self
._coAuthors
.remove(part
)
8761 self
._coAuthors
.insert(idx
+1,part
)
8762 self
.notifyModification()
8764 def getPrimaryAuthorList( self
):
8768 if self
._primaryAuthors
:
8770 except AttributeError:
8771 self
._primaryAuthors
= []
8772 return self
._primaryAuthors
8774 getPrimaryAuthorsList
= getPrimaryAuthorList
8776 def getAuthorList( self
):
8782 except AttributeError:
8783 self
._authors
= OOBTree()
8784 return self
._authors
.values()
8786 def getAllAuthors(self
):
8787 """ This method returns a list composed by the primary authors
8788 and co-authors. The different with getAuthorList() is the type
8791 return self
.getPrimaryAuthorList() + self
.getCoAuthorList()
8793 def addCoAuthor( self
, part
, index
=None ):
8799 except AttributeError:
8800 self
._coAuthors
= []
8801 self
._addAuthor
( part
)
8802 if index
is not None:
8803 self
._coAuthors
.insert(index
, part
)
8805 self
._coAuthors
.append( part
)
8806 if self
.getConference() is not None:
8807 self
.getConference().indexAuthor(part
)
8808 self
.notifyModification()
8810 def removeCoAuthor( self
, part
, removeSpeaker
=1, removePendingSubm
=True):
8816 except AttributeError:
8817 self
._coAuthors
= []
8818 if part
not in self
._coAuthors
:
8820 if self
.getConference() is not None:
8821 self
.getConference().unindexAuthor(part
)
8822 self
._coAuthors
.remove( part
)
8824 self
.removeSpeaker( part
)
8825 self
._removeAuthor
( part
)
8826 if removePendingSubm
:
8827 #--Pending queue: remove pending participant waiting to became submitter if anything
8828 self
.getConference().getPendingQueuesMgr().removePendingSubmitter(part
)
8830 self
.notifyModification()
8832 def recoverCoAuthor(self
, ca
, isPendingSubmitter
):
8833 self
.addCoAuthor(ca
)
8835 if isPendingSubmitter
:
8836 self
.getConference().getPendingQueuesMgr().addPendingSubmitter(ca
, False)
8838 def getCoAuthorList( self
):
8844 except AttributeError:
8845 self
._coAuthors
= []
8846 return self
._coAuthors
8848 def getAuthorById( self
, authorId
):
8854 except AttributeError:
8855 self
._authors
= OOBTree()
8856 return self
._authors
.get( authorId
.strip(), None )
8858 def isAuthor( self
, part
):
8864 except AttributeError:
8865 self
._authors
= OOBTree()
8866 return self
._authors
.has_key( part
.getId() )
8868 def getSpeakerById( self
, authorId
):
8874 except AttributeError:
8876 for spk
in self
._speakers
:
8877 if spk
.getId() == authorId
:
8881 def changePosSpeaker(self
,part
,index
):
8887 except AttributeError:
8889 if not part
in self
._speakers
:
8891 self
._speakers
.remove(part
)
8892 self
._speakers
.insert(index
,part
)
8893 self
.notifyModification()
8895 def addSpeaker( self
, part
, index
=None ):
8897 Adds a speaker (ContributionParticipation object) to the contribution
8898 forcing it to be one of the authors of the contribution
8903 except AttributeError:
8905 if not self
.isAuthor( part
):
8906 raise MaKaCError( _("The Specified speaker is not the Author"), _("Contribution"))
8907 if index
is not None:
8908 self
._speakers
.insert(index
, part
)
8910 self
._speakers
.append( part
)
8911 if self
.getConference() is not None:
8912 self
.getConference().indexSpeaker(part
)
8913 self
.notifyModification()
8915 def newSpeaker( self
, part
):
8917 Adds a new speaker (ContributionParticipation object) to the contribution
8918 setting the speakers ID and the fact it belongs to that contribution
8923 except AttributeError:
8928 except AttributeError:
8929 self
._authorGen
=Counter()
8930 self
._speakers
.append( part
)
8931 newId
= part
.getId()
8933 newId
= str( self
._authorGen
.newCount() )
8934 part
.includeInContribution(self
, newId
)
8935 if self
.getConference() is not None:
8936 self
.getConference().indexSpeaker(part
)
8937 self
.notifyModification()
8939 def removeSpeaker( self
, part
):
8945 except AttributeError:
8947 if part
not in self
._speakers
:
8949 self
._speakers
.remove( part
)
8950 if self
.getConference() is not None:
8951 self
.getConference().unindexSpeaker(part
)
8952 if part
not in self
.getAuthorList():
8954 #--Pending queue: remove pending participant waiting to became submitter if anything
8955 self
.getConference().getPendingQueuesMgr().removePendingSubmitter(part
)
8957 self
.notifyModification()
8959 def recoverSpeaker(self
, spk
, isPendingSubmitter
):
8960 self
.newSpeaker(spk
)
8962 if isPendingSubmitter
:
8963 self
.getConference().getPendingQueuesMgr().addPendingSubmitter(spk
, False)
8965 def isSpeaker( self
, part
):
8971 except AttributeError:
8973 return part
in self
._speakers
8975 def getSpeakerList ( self
):
8981 except AttributeError:
8983 return self
._speakers
8985 def getSpeakerText( self
):
8988 if self
.speakerText
:
8990 except AttributeError, e
:
8991 self
.speakerText
= ""
8992 return self
.speakerText
8994 def setSpeakerText( self
, newText
):
8995 self
.speakerText
= newText
.strip()
8997 def appendSpeakerText( self
, newText
):
8998 self
.setSpeakerText( "%s, %s"%(self
.getSpeakerText(), newText
.strip()) )
9000 def canIPAccess( self
, ip
):
9001 if not self
.__ac
.canIPAccess( ip
):
9003 if self
.getOwner() != None:
9004 return self
.getOwner().canIPAccess(ip
)
9007 def isProtected( self
):
9008 # tells if a contribution is protected or not
9009 return (self
.hasProtectedOwner() + self
.getAccessProtectionLevel()) > 0
9011 def getAccessProtectionLevel( self
):
9012 return self
.__ac
.getAccessProtectionLevel()
9014 def isItselfProtected( self
):
9015 return self
.__ac
.isItselfProtected()
9017 def hasAnyProtection( self
):
9018 """Tells whether a contribution has any kind of protection over it:
9019 access or domain protection.
9021 if self
.__ac
.isProtected():
9023 if self
.getDomainList():
9025 if self
.getAccessProtectionLevel() == -1:
9028 return self
.getOwner().hasAnyProtection()
9032 def hasProtectedOwner( self
):
9033 if self
.getOwner() != None:
9034 return self
.getOwner().isProtected()
9037 def setProtection( self
, private
):
9039 oldValue
= 1 if self
.isProtected() else -1
9041 self
.__ac
.setProtection( private
)
9042 self
.updateFullyPublic()
9044 if oldValue
!= private
:
9046 self
._notify
('protectionChanged', oldValue
, private
)
9048 def grantAccess( self
, prin
):
9049 self
.__ac
.grantAccess( prin
)
9050 if isinstance(prin
, MaKaC
.user
.Avatar
):
9051 prin
.linkTo(self
, "access")
9053 def revokeAccess( self
, prin
):
9054 self
.__ac
.revokeAccess( prin
)
9055 if isinstance(prin
, MaKaC
.user
.Avatar
):
9056 prin
.unlinkTo(self
, "access")
9058 def canView( self
, aw
):
9059 """tells whether the specified user has access to the current object
9060 or any of its sub-objects
9062 if self
.canAccess( aw
):
9064 ### TODO: Replace this code when plugins allow extension points+notifications ##################
9065 from MaKaC
.webinterface
.rh
.collaboration
import RCCollaborationAdmin
, RCCollaborationPluginAdmin
9066 if RCCollaborationAdmin
.hasRights(user
=aw
.getUser()) or \
9067 RCCollaborationPluginAdmin
.hasRights(user
=aw
.getUser(), plugins
='any'):
9069 ################################################################################################
9070 for sc
in self
.getSubContributionList():
9071 if sc
.canView( aw
):
9075 def isAllowedToAccess( self
, user
):
9078 return (not self
.isItselfProtected() and self
.getOwner().isAllowedToAccess( user
)) or\
9079 self
.__ac
.canUserAccess( user
) or\
9080 self
.canUserModify( user
) or \
9081 self
.canUserSubmit(user
)
9083 def canAccess( self
, aw
):
9084 # Allow harvesters (Invenio, offline cache) to access
9086 if self
.__ac
.isHarvesterIP(aw
.getIP()):
9088 #####################################################
9090 if self
.canModify(aw
):
9093 if not self
.canIPAccess(aw
.getIP()) and not self
.isAllowedToAccess( aw
.getUser() ):
9095 if not self
.isProtected():
9097 flag
= self
.isAllowedToAccess( aw
.getUser() )
9098 return flag
or self
.getConference().canKeyAccess(aw
)
9100 def grantModification( self
, prin
):
9101 self
.__ac
.grantModification( prin
)
9102 if isinstance(prin
, MaKaC
.user
.Avatar
):
9103 prin
.linkTo(self
, "manager")
9105 def revokeModification( self
, prin
):
9106 self
.__ac
.revokeModification( prin
)
9107 if isinstance(prin
, MaKaC
.user
.Avatar
):
9108 prin
.unlinkTo(self
, "manager")
9110 def canModify( self
, aw
):
9111 return self
.canUserModify( aw
.getUser() ) or self
.getConference().canKeyModify( aw
)
9113 def canUserModify( self
, av
):
9114 """Tells whether a user is allowed to modify the current contribution:
9115 only if the user is granted to modify the contribution or the user
9116 can modify any of its upper objects (i.e. conference or session).
9118 return self
.getParent().canUserModify( av
) or self
.__ac
.canModify( av
)
9120 def getManagerList( self
):
9121 return self
.__ac
.getModifierList()
9123 def getAllowedToAccessList( self
):
9124 return self
.__ac
.getAccessList()
9126 def addMaterial( self
, newMat
):
9127 newMat
.setId( str(self
.__materialGenerator
.newCount()) )
9128 newMat
.setOwner( self
)
9129 self
.materials
[ newMat
.getId() ] = newMat
9130 self
.notifyModification()
9132 def removeMaterial( self
, mat
):
9133 if mat
.getId() in self
.materials
.keys():
9134 self
.materials
[mat
.getId()].setOwner(None)
9135 del self
.materials
[ mat
.getId() ]
9137 self
.notifyModification()
9138 elif mat
.getId().lower() == 'paper':
9140 self
.notifyModification()
9141 elif mat
.getId().lower() == 'slides':
9143 self
.notifyModification()
9144 elif mat
.getId().lower() == 'minutes':
9145 self
.removeMinutes()
9146 self
.notifyModification()
9147 elif mat
.getId().lower() == 'video':
9149 self
.notifyModification()
9150 elif mat
.getId().lower() == 'poster':
9152 self
.notifyModification()
9154 def recoverMaterial(self
, recMat
):
9155 # Id must already be set in recMat.
9156 recMat
.setOwner( self
)
9157 self
.materials
[ recMat
.getId() ] = recMat
9159 self
.notifyModification()
9161 def getMaterialRegistry(self
):
9163 Return the correct material registry for this type
9165 from MaKaC
.webinterface
.materialFactories
import ContribMFRegistry
9166 return ContribMFRegistry
9168 def getMaterialById( self
, matId
):
9169 if matId
.lower() == 'paper':
9170 return self
.getPaper()
9171 elif matId
.lower() == 'slides':
9172 return self
.getSlides()
9173 elif matId
.lower() == 'video':
9174 return self
.getVideo()
9175 elif matId
.lower() == 'poster':
9176 return self
.getPoster()
9177 elif matId
.lower() == 'minutes':
9178 return self
.getMinutes()
9179 elif self
.materials
.has_key(matId
):
9180 return self
.materials
[ matId
]
9183 def getMaterialList( self
):
9184 return self
.materials
.values()
9186 def getAllMaterialList( self
):
9187 l
= self
.getMaterialList()
9189 l
.append( self
.getPaper() )
9190 if self
.getSlides():
9191 l
.append( self
.getSlides() )
9193 l
.append( self
.getVideo() )
9194 if self
.getPoster():
9195 l
.append( self
.getPoster() )
9196 if self
.getMinutes():
9197 l
.append( self
.getMinutes() )
9198 l
.sort(lambda x
,y
: cmp(x
.getTitle(),y
.getTitle()))
9201 def newSubContribution(self
):
9202 newSub
= SubContribution()
9203 self
.addSubContribution(newSub
)
9204 newSub
._notify
('created', self
)
9207 def addSubContribution( self
, newSubCont
):
9208 newSubCont
.setId(str( self
.__subContGenerator
.newCount()) )
9209 newSubCont
.setOwner( self
)
9210 self
._subConts
.append( newSubCont
)
9211 self
.notifyModification()
9213 def removeSubContribution( self
, subCont
):
9214 if subCont
in self
._subConts
:
9216 subCont
.setOwner(None)
9217 self
._subConts
.remove(subCont
)
9218 self
.notifyModification()
9220 def recoverSubContribution( self
, recSubCont
):
9221 # Id must already be set in recSubCont.
9222 recSubCont
.setOwner( self
)
9223 self
._subConts
.append( recSubCont
)
9224 recSubCont
.recover()
9225 self
.notifyModification()
9227 def getSubContributionById(self
, SCId
):
9228 for sb
in self
._subConts
:
9229 if sb
.getId() == SCId
:
9232 def getSubContributionList(self
):
9233 return self
._subConts
9235 def iterSubContributions(self
):
9236 return iter(self
._subConts
)
9238 def getNumberOfSubcontributions(self
):
9239 return len(self
._subConts
)
9241 def upSubContribution(self
, subcont
):
9242 if subcont
in self
._subConts
:
9243 if self
._subConts
.index(subcont
) != 0:
9244 index
= self
._subConts
.index(subcont
)
9245 sb
= self
._subConts
.pop(index
)
9246 self
._subConts
.insert(index
-1, sb
)
9247 self
.notifyModification()
9249 def downSubContribution(self
, subCont
):
9250 if subCont
in self
._subConts
:
9251 if self
._subConts
.index(subCont
) < len(self
._subConts
)-1:
9252 index
= self
._subConts
.index(subCont
)
9253 sb
= self
._subConts
.pop(index
)
9254 self
._subConts
.insert(index
+1, sb
)
9255 self
.notifyModification()
9257 def setPaper( self
, newPaper
):
9258 if self
.getPaper() != None:
9259 raise MaKaCError( _("The paper for this contribution has already been set"), _("Contribution"))
9261 self
.paper
.setOwner( self
)
9262 self
.notifyModification()
9264 def removePaper( self
):
9265 if self
.paper
is None:
9268 self
.paper
.setOwner(None)
9270 self
.notifyModification()
9272 def recoverPaper(self
, p
):
9276 def getPaper( self
):
9279 def setSlides( self
, newSlides
):
9280 if self
.getSlides() != None:
9281 raise MaKaCError( _("The slides for this contribution have already been set"), _("contribution"))
9282 self
.slides
=newSlides
9283 self
.slides
.setOwner( self
)
9284 self
.notifyModification()
9286 def removeSlides( self
):
9287 if self
.slides
is None:
9289 self
.slides
.delete()
9290 self
.slides
.setOwner( None )
9292 self
.notifyModification()
9294 def recoverSlides(self
, s
):
9298 def getSlides( self
):
9301 def setVideo( self
, newVideo
):
9302 if self
.getVideo() != None:
9303 raise MaKaCError( _("the video for this contribution has already been set"))
9305 self
.video
.setOwner( self
)
9306 self
.notifyModification()
9308 def removeVideo( self
):
9309 if self
.getVideo() is None:
9312 self
.video
.setOwner(None)
9314 self
.notifyModification()
9316 def recoverVideo(self
, v
):
9320 def getVideo( self
):
9324 except AttributeError:
9328 def setPoster( self
, newPoster
):
9329 if self
.getPoster() != None:
9330 raise MaKaCError( _("the poster for this contribution has already been set"))
9331 self
.poster
=newPoster
9332 self
.poster
.setOwner( self
)
9333 self
.notifyModification()
9335 def removePoster( self
):
9336 if self
.getPoster() is None:
9338 self
.poster
.delete()
9339 self
.poster
.setOwner(None)
9341 self
.notifyModification()
9343 def recoverPoster(self
, p
):
9347 def getPoster( self
):
9351 except AttributeError:
9355 def setMinutes( self
, newMinutes
):
9356 if self
.getMinutes() != None:
9357 raise MaKaCError( _("the Minutes for this contribution has already been set"))
9358 self
.minutes
=newMinutes
9359 self
.minutes
.setOwner( self
)
9360 self
.notifyModification()
9362 def createMinutes( self
):
9363 if self
.getMinutes() != None:
9364 raise MaKaCError( _("The minutes for this contribution have already been created"), _("Contribution"))
9365 self
.minutes
= Minutes()
9366 self
.minutes
.setOwner( self
)
9367 self
.notifyModification()
9370 def removeMinutes( self
):
9371 if self
.getMinutes() is None:
9373 self
.minutes
.delete()
9374 self
.minutes
.setOwner( None )
9376 self
.notifyModification()
9378 def recoverMinutes(self
, min):
9379 self
.removeMinutes() # To ensure that the current minutes are put in
9382 self
.minutes
.setOwner( self
)
9384 self
.notifyModification()
9387 def getMinutes( self
):
9392 except AttributeError, e
:
9396 def setReviewing( self
, newReviewing
):
9397 if self
.getReviewing() != None:
9398 raise MaKaCError( _("The reviewing maretial for this contribution has already been set"), _("Contribution"))
9399 self
.reviewing
=newReviewing
9400 self
.reviewing
.setOwner( self
)
9401 self
.notifyModification()
9403 def removeReviewing( self
):
9404 if self
.getReviewing() is None:
9406 self
.reviewing
.delete()
9407 self
.reviewing
.setOwner(None)
9408 self
.reviewing
= None
9409 self
.notifyModification()
9411 def recoverReviewing(self
, p
):
9412 self
.setReviewing(p
)
9415 def getReviewing( self
):
9419 except AttributeError, e
:
9420 self
.reviewing
= None
9421 return self
.reviewing
9423 def getMasterSchedule( self
):
9424 return self
.getOwner().getSchedule()
9426 def requireDomain( self
, dom
):
9427 self
.__ac
.requireDomain( dom
)
9428 self
._notify
('domainAdded', dom
)
9430 def freeDomain( self
, dom
):
9431 self
.__ac
.freeDomain( dom
)
9432 self
._notify
('domainRemoved', dom
)
9434 def getDomainList( self
):
9435 return self
.__ac
.getRequiredDomainList()
9437 def getTrack( self
):
9441 except AttributeError:
9445 def setTrack( self
, newTrack
):
9446 currentTrack
= self
.getTrack()
9447 if newTrack
== currentTrack
:
9450 currentTrack
.removeContribution( self
)
9451 self
._track
= newTrack
9453 self
._track
.addContribution( self
)
9455 def removeTrack(self
, track
):
9456 if track
== self
._track
:
9459 def setType( self
, newType
):
9460 self
._type
= newType
9462 def getType( self
):
9466 except AttributeError:
9470 def getModificationDate( self
):
9471 """Returns the date in which the contribution was last modified"""
9473 return self
._modificationDS
9475 if self
.getConference():
9476 self
._modificationDS
= self
.getConference().getModificationDate()
9478 self
._modificationDS
= nowutc()
9479 return self
._modificationDS
9481 def getCurrentStatus(self
):
9485 except AttributeError:
9486 self
._status
=ContribStatusNotSch(self
)
9488 getStatus
= getCurrentStatus
9490 def setStatus(self
,newStatus
):
9493 self
._status
=newStatus
9495 def withdraw(self
,resp
,comment
):
9496 """ Remove or put a contribution in a conference
9499 if self
.isWithdrawn():
9500 #put back the authors in the author index
9501 for auth
in self
.getAuthorList():
9502 self
.getConference().getAuthorIndex().index(auth
)
9503 for spk
in self
.getSpeakerList():
9504 self
.getConference().getSpeakerIndex().index(spk
)
9505 #change the status of the contribution
9506 self
._status
=ContribStatusNotSch(self
)
9509 #remove the authors from the author index
9510 if self
.getConference() is not None:
9511 for auth
in self
.getAuthorList():
9512 self
.getConference().getAuthorIndex().unindex(auth
)
9513 for spk
in self
.getSpeakerList():
9514 self
.getConference().unindexSpeaker(spk
)
9515 #remove the contribution from any schedule it is included
9516 if self
.isScheduled():
9517 self
.getSchEntry().getSchedule().removeEntry(self
.getSchEntry())
9518 self
.getCurrentStatus().withdraw(resp
,comment
)
9521 def _initSubmissionPrivileges(self
):
9522 """Initialises submission privileges list for a contribution.
9524 This is a temporary function used for creating the attribute in the
9525 case it does not exist into the DB
9528 if self
._submitters
:
9530 except AttributeError:
9531 self
._submitters
=[] #create the attribute
9532 self
.notifyModification(raiseEvent
= False)
9534 def _grantSubmission(self
,av
):
9535 if av
not in self
._submitters
:
9536 self
._submitters
.append(av
)
9537 if self
.getConference() is not None:
9538 self
.getConference().addContribSubmitter(self
,av
)
9539 if isinstance(av
, MaKaC
.user
.Avatar
):
9540 av
.linkTo(self
, "submission")
9541 self
.notifyModification(raiseEvent
= False)
9543 def _grantSubmissionEmail(self
, email
):
9545 Returns True if submission email was granted. False if email was already in the list.
9547 if not email
.lower() in map(lambda x
: x
.lower(), self
.getSubmitterEmailList()):
9548 self
.getSubmitterEmailList().append(email
)
9552 def revokeSubmissionEmail(self
, email
):
9553 if email
in self
.getSubmitterEmailList():
9554 self
.getSubmitterEmailList().remove(email
)
9557 def grantSubmission(self
,sb
, sendEmail
=True):
9558 """Grants a user with submission privileges for the contribution
9559 - sb: can be an Avatar or an Author (primary author, co-author, speaker)
9561 self
._initSubmissionPrivileges
()
9562 if isinstance(sb
, ContributionParticipation
) or isinstance(sb
, SubContribParticipation
):
9564 results
=ah
.match({"email":sb
.getEmail()}, exact
=1, forceWithoutExtAuth
=True)
9566 results
=ah
.match({"email":sb
.getEmail()}, exact
=1)
9569 if i
.hasEmail(sb
.getEmail()):
9572 if r
is not None and r
.isActivated():
9573 self
._grantSubmission
(r
)
9574 elif sb
.getEmail() != "":
9575 self
.getConference().getPendingQueuesMgr().addPendingSubmitter(sb
, False)
9576 submissionEmailGranted
= self
._grantSubmissionEmail
(sb
.getEmail())
9577 if submissionEmailGranted
and sendEmail
:
9578 notif
= pendingQueues
._PendingSubmitterNotification
( [sb
] )
9579 mail
.GenericMailer
.sendAndLog( notif
, self
.getConference() )
9580 if self
.getConference() is not None:
9581 self
.getConference()._getSubmitterIdx
().indexEmail(sb
.getEmail(),self
)
9583 self
._grantSubmission
(sb
)
9585 def _revokeSubmission(self
,av
):
9586 if av
in self
._submitters
:
9587 self
._submitters
.remove(av
)
9588 if self
.getConference() is not None:
9589 self
.getConference().removeContribSubmitter(self
,av
)
9590 if isinstance(av
, MaKaC
.user
.Avatar
):
9591 av
.unlinkTo(self
, "submission")
9592 self
.notifyModification(raiseEvent
= False)
9594 def revokeSubmission(self
,av
):
9595 """Removes submission privileges for the specified user
9597 self
._initSubmissionPrivileges
()
9598 self
._revokeSubmission
(av
)
9600 def revokeAllSubmitters(self
):
9602 self
.notifyModification(raiseEvent
= False)
9604 def getSubmitterList(self
):
9605 """Gives the list of users granted with submission privileges
9607 self
._initSubmissionPrivileges
()
9608 return self
._submitters
9610 def getSubmitterEmailList(self
):
9612 return self
._submittersEmail
9614 self
._submittersEmail
= []
9615 return self
._submittersEmail
9617 def canUserSubmit(self
,av
):
9618 """Tells whether a user can submit material for the current contribution
9622 self
._initSubmissionPrivileges
()
9623 for principal
in self
._submitters
:
9624 if principal
!= None and principal
.containsUser( av
):
9627 #TODO: Remove this and use pending list
9628 if isinstance(av
, MaKaC
.user
.Avatar
):
9629 for email
in av
.getEmails():
9630 if email
.lower() in self
.getSubmitterEmailList():
9631 self
.grantSubmission(av
)
9632 self
.revokeSubmissionEmail(email
)
9636 def getAccessController(self
):
9639 def getReportNumberHolder(self
):
9641 if self
._reportNumberHolder
:
9643 except AttributeError, e
:
9644 self
._reportNumberHolder
=ReportNumberHolder(self
)
9645 return self
._reportNumberHolder
9647 def setReportNumberHolder(self
, rnh
):
9648 self
._reportNumberHolder
=rnh
9651 def contributionStartDateForSort(cls
, contribution
):
9652 """ Function that can be used as "key" argument to sort a list of contributions by start date
9653 The contributions with no start date will be at the end with this sort
9655 if contribution
.getStartDate():
9656 return contribution
.getStartDate()
9658 return maxDatetime()
9662 if self
.getSession() is not None:
9663 res
=self
.getSession().getColor()
9666 def getTextColor(self
):
9668 if self
.getSession() is not None:
9669 res
=self
.getSession().getTextColor()
9672 def getCSBookingManager(self
):
9673 return self
.getConference().getCSBookingManager()
9675 class AcceptedContribution( Contribution
):
9676 """This class represents a contribution which has been created from an
9680 def __init__(self
,abstract
):
9681 Contribution
.__init
__(self
)
9682 abstract
.getConference().addContribution(self
,abstract
.getId())
9683 self
._abstract
= abstract
9684 self
.setTitle( abstract
.getTitle() )
9685 #self.setDescription(abstract.getField("content"))
9686 for key
in abstract
.getFields().keys():
9687 #if key != "content":
9688 self
.setField(key
, abstract
.getField(key
))
9689 if isinstance( abstract
.getCurrentStatus(),review
.AbstractStatusAccepted
):
9690 self
.setTrack( abstract
.getCurrentStatus().getTrack() )
9691 self
.setType( abstract
.getCurrentStatus().getType() )
9692 for auth
in abstract
.getAuthorList():
9693 c_auth
= ContributionParticipation()
9694 self
._setAuthorValuesFromAbstract
( c_auth
, auth
)
9695 if abstract
.isPrimaryAuthor( auth
):
9696 self
.addPrimaryAuthor( c_auth
)
9698 self
.addCoAuthor( c_auth
)
9699 if abstract
.isSpeaker( auth
):
9700 self
.addSpeaker( c_auth
)
9701 self
._grantSubmission
(self
.getAbstract().getSubmitter().getUser())
9703 def _setAuthorValuesFromAbstract( self
, cAuth
, aAuth
):
9704 cAuth
.setTitle( aAuth
.getTitle() )
9705 cAuth
.setFirstName( aAuth
.getFirstName() )
9706 cAuth
.setFamilyName( aAuth
.getSurName() )
9707 cAuth
.setEmail( aAuth
.getEmail() )
9708 cAuth
.setAffiliation( aAuth
.getAffiliation() )
9709 cAuth
.setAddress( aAuth
.getAddress() )
9710 cAuth
.setPhone( aAuth
.getTelephone() )
9712 def getAbstract( self
):
9713 return self
._abstract
9715 def setAbstract(self
, abs):
9716 self
._abstract
= abs
9718 def _initSubmissionPrivileges(self
):
9719 """Initialises submission privileges list for a contribution.
9721 In the case of an AcceptedContribution, the list of submitters
9722 must be initialised with the abstract's one.
9724 This is a temporary function used for creating the attribute in the
9725 case it does not exist into the DB
9728 if self
._submitters
:
9730 except AttributeError:
9731 self
._submitters
=[]#create the attribute
9732 self
._grantSubmission
(self
.getAbstract().getSubmitter().getUser())
9735 """deletes a contribution and all of their subitems
9737 abs = self
.getAbstract()
9739 cs
=abs.getCurrentStatus()
9740 if isinstance(cs
, review
.AbstractStatusAccepted
):
9741 if cs
.getTrack() is not None:
9742 abs.addTrack(cs
.getTrack())
9743 abs.setCurrentStatus(review
.AbstractStatusSubmitted(abs))
9744 abs._setContribution
(None)
9745 self
.setAbstract(None)
9746 Contribution
.delete(self
)
9750 class ContribStatus(Persistent
):
9754 def __init__(self
,contribution
,responsible
):
9755 self
._setContrib
(contribution
)
9756 self
._setResponsible
(responsible
)
9759 def clone(self
, contribution
, responsible
):
9760 cs
= ContribStatus(contribution
, responsible
)
9761 cs
.setDate(self
.getDate())
9764 def _setContrib(self
,newContrib
):
9765 self
._contrib
=newContrib
9767 def getContrib(self
):
9768 return self
._contrib
9770 def _setResponsible(self
,newResp
):
9771 self
._responsible
=newResp
9773 def getResponsible(self
):
9774 return self
._responsible
9779 def setDate(self
, date
):
9785 def withdraw(self
,resp
,comments
=""):
9786 self
._contrib
.setStatus(ContribStatusWithdrawn(self
.getContrib(),resp
,comments
))
9788 class ContribStatusNotSch(ContribStatus
):
9791 def __init__(self
,contrib
):
9792 ContribStatus
.__init
__(self
,contrib
,None)
9794 def clone(self
, contribution
):
9795 csns
= ContribStatusNotSch(contribution
)
9796 csns
.setDate(self
.getDate())
9799 ContribStatusSubmitted
=ContribStatusNotSch
9801 class ContribStatusSch(ContribStatus
):
9804 def __init__(self
,contrib
):
9805 ContribStatus
.__init
__(self
,contrib
,None)
9807 def clone(self
, contribution
):
9808 css
= ContribStatusSch(contribution
)
9809 css
.setDate(self
.getDate())
9812 class ContribStatusWithdrawn(ContribStatus
):
9815 def __init__(self
,contrib
,resp
,comments
):
9816 ContribStatus
.__init
__(self
,contrib
,resp
)
9817 self
._setComment
(comments
)
9819 def clone(self
, contribution
):
9820 csw
= ContribStatusWithdrawn(contribution
)
9821 csw
.setDate(self
.getDate())
9822 csw
.setComment(self
.getComment())
9825 def _setComment(self
,text
):
9826 self
._comment
=text
.strip()
9828 def getComment(self
):
9829 return self
._comment
9831 class ContribStatusNone(ContribStatus
):
9832 # This is a special status we assign to contributions that are put in the trash can.
9834 def __init__(self
,contrib
):
9835 ContribStatus
.__init
__(self
,contrib
,None)
9837 def clone(self
, contribution
):
9838 csn
= ContribStatusNone(contribution
)
9839 csn
.setDate(self
.getDate())
9842 class SubContribParticipation(Persistent
, Fossilizable
):
9844 fossilizes(ISubContribParticipationFossil
, ISubContribParticipationFullFossil
)
9846 def __init__( self
):
9847 self
._subContrib
= None
9849 self
._firstName
= ""
9852 self
._affiliation
= ""
9858 def getConference(self
):
9859 if self
._subContrib
is not None:
9860 return self
._subContrib
.getConference()
9863 def _notifyModification( self
):
9864 if self
._subContrib
!= None:
9865 self
._subContrib
.notifyModification()
9867 def setValues(self
, data
):
9868 self
.setFirstName(data
.get("firstName", ""))
9869 self
.setFamilyName(data
.get("familyName",""))
9870 self
.setAffiliation(data
.get("affilation",""))
9871 self
.setAddress(data
.get("address",""))
9872 self
.setEmail(data
.get("email",""))
9873 self
.setFax(data
.get("fax",""))
9874 self
.setTitle(data
.get("title",""))
9875 self
.setPhone(data
.get("phone",""))
9876 self
._notifyModification
()
9878 def getValues(self
):
9880 data
["firstName"]=self
.getFirstName()
9881 data
["familyName"]=self
.getFamilyName()
9882 data
["affilation"]=self
.getAffiliation()
9883 data
["address"]=self
.getAddress()
9884 data
["email"]=self
.getEmail()
9885 data
["fax"]=self
.getFax()
9886 data
["title"]=self
.getTitle()
9887 data
["phone"]=self
.getPhone()
9891 part
= SubContribParticipation()
9892 part
.setValues(self
.getValues())
9895 def setDataFromAvatar(self
,av
):
9896 # av is an Avatar object.
9899 self
.setFirstName(av
.getName())
9900 self
.setFamilyName(av
.getSurName())
9901 self
.setEmail(av
.getEmail())
9902 self
.setAffiliation(av
.getOrganisation())
9903 self
.setAddress(av
.getAddress())
9904 self
.setPhone(av
.getTelephone())
9905 self
.setTitle(av
.getTitle())
9906 self
.setFax(av
.getFax())
9907 self
._notifyModification
()
9909 def setDataFromAuthor(self
,au
):
9910 # au is a ContributionParticipation object.
9913 self
.setFirstName(au
.getFirstName())
9914 self
.setFamilyName(au
.getFamilyName())
9915 self
.setEmail(au
.getEmail())
9916 self
.setAffiliation(au
.getAffiliation())
9917 self
.setAddress(au
.getAddress())
9918 self
.setPhone(au
.getPhone())
9919 self
.setTitle(au
.getTitle())
9920 self
.setFax(au
.getFax())
9921 self
._notifyModification
()
9923 def setDataFromSpeaker(self
,spk
):
9924 # spk is a SubContribParticipation object.
9927 self
.setFirstName(spk
.getFirstName())
9928 self
.setFamilyName(spk
.getFamilyName())
9929 self
.setEmail(spk
.getEmail())
9930 self
.setAffiliation(spk
.getAffiliation())
9931 self
.setAddress(spk
.getAddress())
9932 self
.setPhone(spk
.getPhone())
9933 self
.setTitle(spk
.getTitle())
9934 self
.setFax(spk
.getFax())
9935 self
._notifyModification
()
9937 def includeInSubContrib( self
, subcontrib
, id ):
9938 if self
.getSubContrib() == subcontrib
and self
.getId()==id.strip():
9940 self
._subContrib
= subcontrib
9944 self
._subContrib
= None
9945 TrashCanManager().add(self
)
9948 TrashCanManager().remove(self
)
9950 @Updates ('MaKaC.conference.SubContribParticipation', 'id')
9951 def setId(self
, newId
):
9957 def getSubContrib( self
):
9958 return self
._subContrib
9960 def getContribution( self
):
9961 if self
._subContrib
is not None:
9962 return self
._subContrib
.getContribution()
9965 # def getLocator(self):
9966 # if self.getSubContrib() is None:
9968 # loc=self.getSubContrib().getLocator()
9969 # loc["authId"]=self.getId()
9973 contrib
=self
.getContribution()
9974 if contrib
is not None:
9975 conf
=contrib
.getConference()
9976 if conf
is not None:
9977 conf
.unindexAuthor(self
)
9978 conf
.unindexSpeaker(self
)
9981 contrib
=self
.getContribution()
9982 if contrib
is not None:
9983 conf
=contrib
.getConference()
9984 if conf
is not None:
9985 conf
.indexAuthor(self
)
9986 conf
.indexSpeaker(self
)
9988 @Updates ('MaKaC.conference.SubContribParticipation', 'firstName')
9989 def setFirstName( self
, newName
):
9991 if tmp
==self
._firstName
:
9996 self
._notifyModification
()
9998 def getFirstName( self
):
9999 return self
._firstName
10001 def getName( self
):
10002 return self
._firstName
10004 @Updates ('MaKaC.conference.SubContribParticipation', 'familyName')
10005 def setFamilyName( self
, newName
):
10006 tmp
=newName
.strip()
10007 if tmp
==self
._surName
:
10012 self
._notifyModification
()
10014 def getFamilyName( self
):
10015 return self
._surName
10017 def getSurName( self
):
10018 return self
._surName
10020 @Updates ('MaKaC.conference.SubContribParticipation', 'email')
10021 def setEmail( self
, newMail
):
10022 tmp
=newMail
.strip()
10023 if tmp
==self
._email
:
10026 self
._email
=newMail
.strip()
10028 self
._notifyModification
()
10030 def getEmail( self
):
10033 @Updates ('MaKaC.conference.SubContribParticipation', 'affiliation')
10034 def setAffiliation( self
, newAffil
):
10035 self
._affiliation
= newAffil
.strip()
10036 self
._notifyModification
()
10038 def getAffiliation( self
):
10039 return self
._affiliation
10041 @Updates ('MaKaC.conference.SubContribParticipation', 'address')
10042 def setAddress( self
, newAddr
):
10043 self
._address
= newAddr
.strip()
10044 self
._notifyModification
()
10046 def getAddress( self
):
10047 return self
._address
10049 @Updates ('MaKaC.conference.SubContribParticipation', 'phone')
10050 def setPhone( self
, newPhone
):
10051 self
._phone
= newPhone
.strip()
10052 self
._notifyModification
()
10054 def getPhone( self
):
10057 @Updates ('MaKaC.conference.SubContribParticipation', 'title')
10058 def setTitle( self
, newTitle
):
10059 self
._title
= newTitle
.strip()
10060 self
._notifyModification
()
10062 def getTitle( self
):
10065 def setFax( self
, newFax
):
10066 self
._fax
= newFax
.strip()
10067 self
._notifyModification
()
10069 def getFax( self
):
10073 except AttributeError:
10077 def getFullName( self
):
10078 res
= self
.getFullNameNoTitle()
10079 if self
.getTitle() != "":
10080 res
= "%s %s"%( self
.getTitle(), res
)
10083 def getFullNameNoTitle( self
):
10084 res
= self
.getFamilyName().decode('utf-8').upper().encode('utf-8')
10085 if self
.getFirstName() != "":
10086 if res
.strip() != "":
10087 res
= "%s, %s"%( res
, self
.getFirstName() )
10089 res
= self
.getFirstName()
10092 def getAbrName(self
):
10093 res
= self
.getFamilyName()
10094 if self
.getFirstName() != "":
10097 res
= "%s%s."%(res
, self
.getFirstName()[0].upper())
10100 def getDirectFullName( self
):
10101 res
= self
.getDirectFullNameNoTitle()
10102 if self
.getTitle() != "":
10103 res
= "%s %s"%( self
.getTitle(), res
)
10106 def getDirectFullNameNoTitle( self
, upper
= True ):
10107 return ("%s %s"%(self
.getFirstName(), self
.getFamilyName().upper() if upper
else self
.getFamilyName())).strip()
10109 class SubContribution(CommonObjectBase
, Locatable
):
10113 fossilizes(ISubContributionFossil
, ISubContributionWithSpeakersFossil
)
10115 def __init__( self
, **subContData
):
10119 self
.description
= ""
10120 self
.__schEntry
= None
10121 self
.duration
= timedelta( minutes
=15 )
10123 self
.speakerText
= ""
10125 self
.materials
= {}
10126 self
.__materialGenerator
= Counter() # Provides material unique
10127 # identifiers whithin the current
10128 self
.poster
= None # contribution
10133 self
.minutes
= None
10134 self
._authorGen
= Counter()
10135 self
._keywords
= ""
10139 parentId
= self
.parent
.getId()
10140 if self
.getConference():
10141 grandpaId
= self
.getConference().getId()
10147 return "<SubCont %s:%s:%s@%s>" % (grandpaId
, parentId
, self
.getId(), hex(id(self
)))
10149 def isFullyPublic( self
):
10150 if hasattr(self
, "_fullyPublic"):
10151 return self
._fullyPublic
10153 self
.setFullyPublic()
10154 return self
._fullyPublic
10156 def setFullyPublic( self
):
10157 for res
in self
.getAllMaterialList():
10158 if not res
.isFullyPublic():
10159 self
._fullyPublic
= False
10160 self
._p
_changed
= 1
10162 self
._fullyPublic
= True
10163 self
._p
_changed
= 1
10165 def updateFullyPublic( self
):
10166 self
.setFullyPublic()
10167 self
.getOwner().updateFullyPublic()
10169 def getAccessController(self
):
10170 return self
.getOwner().getAccessController()
10172 def getKeywords(self
):
10174 return self
._keywords
10176 self
._keywords
= ""
10179 def setKeywords(self
, keywords
):
10180 self
._keywords
= keywords
10182 def getLogInfo(self
):
10185 data
["subject"] = self
.getTitle()
10186 data
["id"] = self
.id
10187 data
["title"] = self
.title
10188 data
["parent title"] = self
.getParent().getTitle()
10189 data
["description"] = self
.description
10190 data
["duration"] = "%s"%self
.duration
10191 data
["minutes"] = self
.minutes
10193 for sp
in self
.speakers
:
10194 data
["speaker %s"%sp
.getId()] = sp
.getFullName()
10199 def clone(self
, deltaTime
, parent
, options
):
10200 sCont
= SubContribution()
10201 sCont
.setParent(parent
)
10202 sCont
.setTitle(self
.getTitle())
10203 sCont
.setDescription(self
.getDescription())
10204 sCont
.setKeywords(self
.getKeywords())
10205 dur
= self
.getDuration()
10206 hours
= dur
.seconds
/ 3600
10207 minutes
= (dur
.seconds
% 3600) / 60
10208 sCont
.setDuration(hours
, minutes
)
10209 sCont
.setReportNumberHolder(self
.getReportNumberHolder().clone(self
))
10211 # There is no _order attribute in this class
10213 if options
.get("authors", False) :
10214 for s
in self
.getSpeakerList() :
10215 sCont
.newSpeaker(s
.clone())
10216 sCont
.setSpeakerText(self
.getSpeakerText())
10218 if options
.get("materials", False) :
10219 for m
in self
.getMaterialList() :
10220 sCont
.addMaterial(m
.clone(sCont
))
10221 if self
.getPaper() is not None:
10222 sCont
.setPaper(self
.getPaper().clone(sCont
))
10223 if self
.getSlides() is not None:
10224 sCont
.setSlides(self
.getSlides().clone(sCont
))
10225 if self
.getVideo() is not None:
10226 sCont
.setVideo(self
.getVideo().clone(sCont
))
10227 if self
.getPoster() is not None:
10228 sCont
.setPoster(self
.getPoster().clone(sCont
))
10229 if self
.getMinutes() is not None:
10230 sCont
.setMinutes(self
.getMinutes().clone(sCont
))
10233 sCont
.notifyModification()
10236 def notifyModification( self
):
10237 parent
= self
.getParent()
10239 parent
.setModificationDate()
10240 self
._notify
('infoChanged')
10241 self
._p
_changed
= 1
10243 def getCategoriesPath(self
):
10244 return self
.getConference().getCategoriesPath()
10246 def getLocator( self
):
10247 """Gives back a globaly unique identification encapsulated in a Locator
10248 object for the contribution instance
10251 lconf
= self
.getOwner().getLocator()
10252 lconf
["subContId"] = self
.getId()
10256 def setId( self
, newId
):
10262 def getUniqueId( self
):
10263 """returns (string) the unique identifier of the item"""
10264 """used mainly in the web session access key table"""
10265 return "%ssc%s" % (self
.getParent().getUniqueId(),self
.id)
10267 def setTitle( self
, newTitle
):
10268 self
.title
= newTitle
.strip()
10269 self
.notifyModification()
10271 def getTitle( self
):
10272 if self
.title
.strip() == "":
10273 return "(no title)"
10276 def setDescription( self
, newDesc
):
10277 self
.description
= newDesc
.strip()
10278 self
.notifyModification()
10280 def getDescription( self
):
10281 return self
.description
10283 def setParent(self
,parent
):
10284 self
.parent
= parent
10285 if self
.parent
== None:
10288 def getParent( self
):
10291 def setOwner(self
, owner
):
10292 self
.setParent(owner
)
10294 def getOwner( self
):
10295 return self
.getParent()
10297 def getConference( self
):
10298 return self
.parent
.getConference()
10300 def getSession( self
):
10301 return self
.parent
.getSession()
10303 def getContribution(self
):
10306 def getDuration( self
):
10307 return self
.duration
10309 def setDuration( self
, hours
, minutes
=0, dur
=0 ):
10313 hours
= int( hours
)
10314 minutes
= int( minutes
)
10315 self
.duration
= timedelta(hours
=hours
,minutes
=minutes
)
10316 self
.notifyModification()
10318 def getLocation( self
):
10319 return self
.getOwner().getLocation()
10321 def getRoom( self
):
10322 return self
.getOwner().getRoom()
10324 def getSpeakerById( self
, id ):
10327 for spk
in self
.speakers
:
10328 if spk
.getId() == id:
10332 def newSpeaker( self
, spk
):
10335 self
.speakers
.append( spk
)
10337 if self
._authorGen
:
10339 except AttributeError:
10340 self
._authorGen
=Counter()
10341 newId
= spk
.getId()
10343 newId
= str( self
._authorGen
.newCount() )
10344 spk
.includeInSubContrib(self
, newId
)
10345 if self
.getConference() is not None:
10346 self
.getConference().indexSpeaker(spk
)
10347 self
.notifyModification()
10349 def removeSpeaker( self
, spk
):
10352 if spk
not in self
.speakers
:
10354 self
.speakers
.remove( spk
)
10355 if self
.getConference() is not None:
10356 self
.getConference().unindexSpeaker(spk
)
10358 self
.notifyModification()
10360 def recoverSpeaker(self
, spk
):
10361 self
.newSpeaker(spk
)
10364 def isSpeaker( self
, spk
):
10367 return spk
in self
._speakers
10369 def getSpeakerList ( self
):
10372 return self
.speakers
10374 def getSpeakerText( self
):
10377 if self
.speakerText
:
10379 except AttributeError, e
:
10380 self
.speakerText
= ""
10381 return self
.speakerText
10383 def setSpeakerText( self
, newText
):
10384 self
.speakerText
= newText
.strip()
10386 def appendSpeakerText( self
, newText
):
10387 self
.setSpeakerText( "%s, %s"%(self
.getSpeakerText(), newText
.strip()) )
10390 # There is no _order attribute in this class -
10391 # the methods below are either obsolate or the feature has not been implemented
10393 # def setOrder( self, order ):
10394 # self._order = order
10395 # self.notifyModification()
10397 # def getOrder(self):
10398 # return self._order
10400 def canIPAccess( self
, ip
):
10401 return self
.getOwner().canIPAccess(ip
)
10403 def isProtected( self
):
10404 return self
.hasProtectedOwner()
10406 def getAccessProtectionLevel( self
):
10407 return self
.getOwner().getAccessProtectionLevel()
10409 def hasAnyProtection( self
):
10410 """Tells whether a subContribution has any kind of protection over it:
10411 access or domain protection.
10413 return self
.getOwner().hasAnyProtection()
10415 def getManagerList( self
):
10416 return self
.parent
.getManagerList()
10418 def hasProtectedOwner( self
):
10419 if self
.getOwner() != None:
10420 return self
.getOwner().isProtected()
10423 def getAccessKey( self
):
10424 return self
.getOwner().getAccessKey()
10426 def getModifKey( self
):
10427 return self
.getConference().getModifKey()
10429 def canView( self
, aw
):
10430 """tells whether the specified user has access to the current object
10431 or any of its sub-objects
10433 if self
.canAccess( aw
):
10437 def isAllowedToAccess( self
, user
):
10438 return self
.parent
.isAllowedToAccess( user
)
10440 def canAccess( self
, aw
):
10441 return self
.getOwner().canAccess(aw
)
10443 def canModify( self
, aw
):
10444 return self
.canUserModify( aw
.getUser() ) or self
.getConference().canKeyModify( aw
)
10446 def canUserModify( self
, av
):
10447 """Tells whether a user is allowed to modify the current contribution:
10448 only if the user is granted to modify the contribution or the user
10449 can modify any of its upper objects (i.e. conference or session).
10451 return self
.getParent().canUserModify( av
)
10453 def canUserSubmit( self
, av
):
10454 return self
.getOwner().canUserSubmit( av
)
10456 def getAllowedToAccessList( self
):
10457 """Currently the SubContribution class has no access list.
10458 But instead of returning the owner Contribution's access list,
10459 I am returning an empty list. Methods such as getRecursiveAllowedToAccess()
10460 will call the owner Contribution anyway.
10464 def addMaterial( self
, newMat
):
10465 newMat
.setId( str(self
.__materialGenerator
.newCount()) )
10466 newMat
.setOwner( self
)
10467 self
.materials
[ newMat
.getId() ] = newMat
10468 self
.notifyModification()
10470 def removeMaterial( self
, mat
):
10471 if mat
.getId() in self
.materials
.keys():
10472 self
.materials
[mat
.getId()].setOwner(None)
10473 del self
.materials
[ mat
.getId() ]
10475 self
.notifyModification()
10476 elif mat
.getId().lower() == 'paper':
10478 self
.notifyModification()
10479 elif mat
.getId().lower() == 'slides':
10480 self
.removeSlides()
10481 self
.notifyModification()
10482 elif mat
.getId().lower() == 'minutes':
10483 self
.removeMinutes()
10484 self
.notifyModification()
10485 elif mat
.getId().lower() == 'video':
10487 self
.notifyModification()
10488 elif mat
.getId().lower() == 'poster':
10489 self
.removePoster()
10490 self
.notifyModification()
10492 def recoverMaterial(self
, recMat
):
10493 # Id must already be set in recMat.
10494 recMat
.setOwner( self
)
10495 self
.materials
[ recMat
.getId() ] = recMat
10497 self
.notifyModification()
10499 def getMaterialRegistry(self
):
10501 Return the correct material registry for this type
10503 from MaKaC
.webinterface
.materialFactories
import SubContributionMFRegistry
10504 return SubContributionMFRegistry
10506 def getMaterialById( self
, matId
):
10507 if matId
.lower() == 'paper':
10508 return self
.getPaper()
10509 elif matId
.lower() == 'slides':
10510 return self
.getSlides()
10511 elif matId
.lower() == 'video':
10512 return self
.getVideo()
10513 elif matId
.lower() == 'poster':
10514 return self
.getPoster()
10515 elif matId
.lower() == 'minutes':
10516 return self
.getMinutes()
10517 elif self
.materials
.has_key(matId
):
10518 return self
.materials
[ matId
]
10521 def getMaterialList( self
):
10522 return self
.materials
.values()
10524 def getAllMaterialList( self
):
10525 l
= self
.getMaterialList()
10526 if self
.getPaper():
10527 l
.append( self
.getPaper() )
10528 if self
.getSlides():
10529 l
.append( self
.getSlides() )
10530 if self
.getVideo():
10531 l
.append( self
.getVideo() )
10532 if self
.getMinutes():
10533 l
.append( self
.getMinutes() )
10534 if self
.getPoster():
10535 l
.append( self
.getPoster() )
10536 l
.sort(lambda x
,y
: cmp(x
.getTitle(),y
.getTitle()))
10539 def setPaper( self
, newPaper
):
10540 if self
.getPaper() != None:
10541 raise MaKaCError( _("The paper for this subcontribution has already been set"), _("Contribution"))
10542 self
.paper
=newPaper
10543 self
.paper
.setOwner( self
)
10544 self
.notifyModification()
10546 def removePaper( self
):
10547 if self
.getPaper() is None:
10549 self
.paper
.delete()
10550 self
.paper
.setOwner(None)
10552 self
.notifyModification()
10554 def recoverPaper(self
, p
):
10558 def getPaper( self
):
10561 def setSlides( self
, newSlides
):
10562 if self
.getSlides() != None:
10563 raise MaKaCError( _("The slides for this subcontribution have already been set"), _("Contribution"))
10564 self
.slides
=newSlides
10565 self
.slides
.setOwner( self
)
10566 self
.notifyModification()
10568 def removeSlides( self
):
10569 if self
.getSlides() is None:
10571 self
.slides
.delete()
10572 self
.slides
.setOwner( None )
10574 self
.notifyModification()
10576 def recoverSlides(self
, s
):
10580 def getSlides( self
):
10583 def setVideo( self
, newVideo
):
10584 if self
.getVideo() != None:
10585 raise MaKaCError( _("the video for this subcontribution has already been set"))
10586 self
.video
=newVideo
10587 self
.video
.setOwner( self
)
10588 self
.notifyModification()
10590 def removeVideo( self
):
10591 if self
.getVideo() is None:
10593 self
.video
.delete()
10594 self
.video
.setOwner(None)
10596 self
.notifyModification()
10598 def recoverVideo(self
, v
):
10602 def getVideo( self
):
10606 except AttributeError:
10610 def setPoster( self
, newPoster
):
10611 if self
.getPoster() != None:
10612 raise MaKaCError( _("the poster for this subcontribution has already been set"))
10613 self
.poster
=newPoster
10614 self
.poster
.setOwner( self
)
10615 self
.notifyModification()
10617 def removePoster( self
):
10618 if self
.getPoster() is None:
10620 self
.poster
.delete()
10621 self
.poster
.setOwner(None)
10623 self
.notifyModification()
10625 def recoverPoster(self
, p
):
10629 def getPoster( self
):
10633 except AttributeError:
10637 def setMinutes( self
, newMinutes
):
10638 if self
.getMinutes() != None:
10639 raise MaKaCError( _("the Minutes for this subcontribution has already been set"))
10640 self
.minutes
=newMinutes
10641 self
.minutes
.setOwner( self
)
10642 self
.notifyModification()
10644 def createMinutes( self
):
10645 if self
.getMinutes() != None:
10646 raise MaKaCError( _("The minutes for this subcontribution have already been created"), _("Sub Contribution"))
10647 self
.minutes
= Minutes()
10648 self
.minutes
.setOwner( self
)
10649 self
.notifyModification()
10650 return self
.minutes
10652 def removeMinutes( self
):
10653 if self
.getMinutes() is None:
10655 self
.minutes
.delete()
10656 self
.minutes
.setOwner( None )
10657 self
.minutes
= None
10658 self
.notifyModification()
10660 def recoverMinutes(self
, min):
10661 self
.removeMinutes() # To ensure that the current minutes are put in
10664 self
.minutes
.setOwner( self
)
10666 self
.notifyModification()
10667 return self
.minutes
10669 def getMinutes( self
):
10674 except AttributeError, e
:
10675 self
.minutes
= None
10676 return self
.minutes
10678 def getMasterSchedule( self
):
10679 return self
.getOwner().getSchedule()
10683 self
._notify
('deleted', self
.getOwner())
10685 while len(self
.getSpeakerList()) > 0:
10686 self
.removeSpeaker(self
.getSpeakerList()[0])
10687 for mat
in self
.getMaterialList():
10688 self
.removeMaterial(mat
)
10690 self
.removeSlides()
10692 self
.removePoster()
10693 self
.removeMinutes()
10694 TrashCanManager().add(self
)
10699 TrashCanManager().remove(self
)
10701 def getReportNumberHolder(self
):
10703 if self
._reportNumberHolder
:
10705 except AttributeError, e
:
10706 self
._reportNumberHolder
=ReportNumberHolder(self
)
10707 return self
._reportNumberHolder
10709 def setReportNumberHolder(self
, rnh
):
10710 self
._reportNumberHolder
=rnh
10712 class Material(CommonObjectBase
):
10713 """This class represents a set of electronic documents (resources) which can
10714 be attached to a conference, a session or a contribution.
10715 A material can be of several types (achieved by specialising this class)
10716 and is like a container of files which have some relation among them.
10717 It contains the minimal set of attributes to store basic meta data and
10718 provides useful operations to access and manage it.
10720 owner -- (Conference, Session or Contribution) Object to which the
10721 material is attached to
10722 id -- (string) Material unique identifier. Normally used to uniquely
10723 identify a material within a conference, session or contribution
10724 title -- (string) Material denomination
10725 description -- (string) Longer text describing in more detail material
10727 type -- (string) String identifying the material classification
10728 resources -- (PMapping) Collection of resouces grouped within the
10729 material. Dictionary of references to Resource objects indexed
10730 by their unique relative id.
10733 fossilizes(IMaterialMinimalFossil
, IMaterialFossil
)
10735 def __init__( self
, materialData
=None ):
10736 self
.id = "not assigned"
10737 self
.__resources
= {}
10738 self
.__resourcesIdGen
= Counter()
10740 self
.description
= ""
10743 self
.__ac
= AccessController(self
)
10744 self
._mainResource
= None
10746 def isFullyPublic( self
):
10747 if hasattr(self
, "_fullyPublic"):
10748 return self
._fullyPublic
10750 self
.setFullyPublic()
10751 return self
._fullyPublic
10753 def setFullyPublic( self
):
10754 if self
.isProtected():
10755 self
._fullyPublic
= False
10756 self
._p
_changed
= 1
10758 for res
in self
.getResourceList():
10759 if res
.isProtected():
10760 self
._fullyPublic
= False
10761 self
._p
_changed
= 1
10763 self
._fullyPublic
= True
10764 self
._p
_changed
= 1
10766 def updateFullyPublic( self
):
10767 self
.setFullyPublic()
10768 self
.getOwner().updateFullyPublic()
10770 def setValues( self
, params
):
10771 """Sets all the values of the current material object from a diccionary
10772 containing the following key-value pairs:
10775 Please, note that this method sets ALL values which means that if
10776 the given dictionary doesn't contain any of the keys the value
10777 will set to a default value.
10779 self
.setTitle(params
.get("title", "NO TITLE ASSIGNED"))
10780 self
.setDescription( params
.get( "description", "" ) )
10781 self
.notifyModification()
10783 def clone ( self
, owner
):
10785 mat
.setTitle(self
.getTitle())
10786 mat
.setDescription(self
.getDescription())
10787 mat
.notifyModification()
10789 mat
.setId(self
.getId())
10790 mat
.setOwner(owner
)
10791 mat
.setType(self
.getType())
10793 mat
.setProtection(self
.getAccessController()._getAccessProtection
())
10794 mat
.setAccessKey(self
.getAccessKey())
10795 rlist
= self
.getResourceList()
10797 newres
= r
.clone(mat
)
10798 mat
.addResource(newres
)
10800 mat
.setMainResource(self
.getMainResource())
10804 def notifyModification( self
):
10805 parent
= self
.getOwner()
10807 parent
.setModificationDate()
10808 self
._p
_changed
= 1
10810 def getLocator( self
):
10811 if self
.owner
== None:
10813 lconf
= self
.owner
.getLocator()
10814 lconf
["materialId"] = self
.getId()
10817 def setId( self
, newId
):
10818 self
.id = str(newId
).strip()
10823 def getUniqueId( self
):
10824 """returns (string) the unique identifier of the item"""
10825 """used mainly in the web session access key table"""
10826 return "%sm%s" % (self
.getOwner().getUniqueId(),self
.id)
10828 def setOwner( self
, newOwner
):
10829 self
.owner
= newOwner
10831 def getOwner( self
):
10834 def getCategory( self
):
10835 if isinstance(self
.getOwner(), Category
):
10836 return self
.getOwner()
10839 def getConference( self
):
10840 if type(self
.getOwner()) is Conference
:
10841 return self
.getOwner()
10842 if type(self
.getOwner()) is Category
:
10844 return self
.getOwner().getConference()
10846 def getSession( self
):
10847 if self
.getContribution():
10848 return self
.getContribution().getSession()
10849 if isinstance(self
.getOwner(), Session
):
10850 return self
.getOwner()
10851 if isinstance(self
.getOwner(), SubContribution
):
10852 return self
.getOwner().getSession()
10855 def getContribution( self
):
10856 if self
.getSubContribution():
10857 return self
.getSubContribution().getContribution()
10858 if isinstance(self
.getOwner(), Contribution
):
10859 return self
.getOwner()
10862 def getSubContribution( self
):
10863 if isinstance(self
.getOwner(), SubContribution
):
10864 return self
.getOwner()
10867 @Updates (['MaKaC.conference.Material',
10868 'MaKaC.conference.Minutes',
10869 'MaKaC.conference.Paper',
10870 'MaKaC.conference.Slides',
10871 'MaKaC.conference.Video',
10872 'MaKaC.conference.Poster',
10873 'MaKaC.conference.Reviewing'],'title')
10874 def setTitle( self
, newTitle
):
10875 self
.title
= newTitle
.strip()
10876 self
.notifyModification()
10878 def getTitle( self
):
10881 @Updates (['MaKaC.conference.Material',
10882 'MaKaC.conference.Minutes',
10883 'MaKaC.conference.Paper',
10884 'MaKaC.conference.Slides',
10885 'MaKaC.conference.Video',
10886 'MaKaC.conference.Poster',
10887 'MaKaC.conference.Reviewing'], 'description')
10888 def setDescription( self
, newDescription
):
10889 self
.description
= newDescription
.strip()
10890 self
.notifyModification()
10892 def getDescription( self
):
10893 return self
.description
10895 def setType( self
, newType
):
10896 self
.type = newType
.strip()
10897 self
.notifyModification()
10899 def getType( self
):
10902 def getReviewingState(self
):
10903 """ Returns the reviewing state of a material.
10904 The state is represented by an integer:
10905 0 : there's no reviewing state because the material does not belong to a contribution, or the conference
10906 has not reviewing module enabled, or the module is enabled but the mode is "no reviewing"
10907 1 : the material is not subject to reviewing, because this kind of material is not reviewable in the conference
10908 2 : the material is subject to reviewing, but has not been submitted yet by the author
10909 3 : the material is subject to reviewing, has been submitted by the author, but has not been judged yet
10910 4 : the material is subject to reviewing, has been submitted by the author, and has been judged as Accepted
10911 5 : the material is subject to reviewing, has been submitted by the author, and has been judged as Rejected
10913 if isinstance(self
.owner
, Contribution
):
10914 conference
= self
.owner
.getConference()
10915 if conference
.getConfPaperReview().getChoice() == ConferencePaperReview
.NO_REVIEWING
: #conference has no reviewing process
10917 else: #conference has reviewing
10918 #if self.id in reviewableMaterials: #material is reviewable
10919 if isinstance(self
, Reviewing
): #material is reviewable
10920 lastReview
= self
.owner
.getReviewManager().getLastReview()
10921 if lastReview
.isAuthorSubmitted(): #author has submitted
10922 refereeJudgement
= lastReview
.getRefereeJudgement()
10923 if refereeJudgement
.isSubmitted(): #referee has submitted judgement
10924 if refereeJudgement
.getJudgement() == "Accept":
10926 elif refereeJudgement
.getJudgement() == "Reject":
10929 #we should never arrive here because referee judgements that are 'To be corrected'
10930 #or a custom state should imply a new review being created, so the state is back to 2
10931 raise MaKaCError("RefereeJudgement should be 'Accept' or 'Reject' in this method")
10932 else: #referee has not submitted judgement
10934 else: #author has not submitted
10936 else: #material is not reviewable
10938 else: #material does not belong to a contribution
10941 def _getRepository( self
):
10942 dbRoot
= DBMgr
.getInstance().getDBConnection().root()
10944 fr
= dbRoot
["local_repositories"]["main"]
10945 except KeyError, e
:
10946 fr
= fileRepository
.MaterialLocalRepository()
10947 dbRoot
["local_repositories"] = OOBTree()
10948 dbRoot
["local_repositories"]["main"] = fr
10951 def hasFile( self
, name
):
10952 for f
in self
.getResourceList():
10953 if f
.getName() == name
:
10957 def addResource( self
, newRes
, forcedFileId
= None ):
10958 newRes
.setOwner( self
)
10959 newRes
.setId( str( self
.__resourcesIdGen
.newCount() ) )
10960 newRes
.archive( self
._getRepository
(), forcedFileId
= forcedFileId
)
10961 self
.__resources
[newRes
.getId()] = newRes
10962 self
.notifyModification()
10963 Logger
.get('storage').debug("Finished storing resource %s for material %s" % (newRes
.getId(), self
.getLocator()))
10965 def getResourceList( self
):
10966 list = self
.__resources
.values()
10967 list.sort(utils
.sortFilesByName
)
10970 def getNbResources(self
):
10971 return len(self
.__resources
)
10973 def getResourceById( self
, id ):
10974 return self
.__resources
[id]
10976 def removeResource( self
, res
):
10977 if res
.getId() in self
.__resources
.keys():
10978 del self
.__resources
[ res
.getId() ]
10980 self
.notifyModification()
10981 if self
.getMainResource() is not None and \
10982 self
._mainResource
.getId() == res
.getId():
10983 self
._mainResource
= None
10985 def recoverResource(self
, recRes
):
10986 recRes
.setOwner(self
)
10987 self
.__resources
[recRes
.getId()] = recRes
10989 self
.notifyModification()
10991 def getMainResource(self
):
10993 if self
._mainResource
:
10995 except AttributeError:
10996 self
._mainResource
= None
10997 return self
._mainResource
10999 def setMainResource(self
, mr
):
11000 self
._mainResource
= mr
11002 def delete( self
):
11003 for res
in self
.getResourceList():
11004 self
.removeResource( res
)
11005 TrashCanManager().add(self
)
11008 TrashCanManager().remove(self
)
11010 def canIPAccess( self
, ip
):
11011 if not self
.__ac
.canIPAccess( ip
):
11013 if self
.getOwner() != None:
11014 return self
.getOwner().canIPAccess(ip
)
11017 def isProtected( self
):
11018 # tells if a material is protected or not
11019 return (self
.hasProtectedOwner() + self
.getAccessProtectionLevel()) > 0
11021 def getAccessProtectionLevel( self
):
11022 return self
.__ac
.getAccessProtectionLevel()
11024 def isItselfProtected( self
):
11025 return self
.__ac
.isItselfProtected()
11028 def hasProtectedOwner( self
):
11029 if self
.getOwner() != None:
11030 return self
.getOwner().isProtected()
11034 @Updates (['MaKaC.conference.Material',
11035 'MaKaC.conference.Minutes',
11036 'MaKaC.conference.Paper',
11037 'MaKaC.conference.Slides',
11038 'MaKaC.conference.Video',
11039 'MaKaC.conference.Poster',
11040 'MaKaC.conference.Reviewing'], 'protection', lambda(x
): int(x
))
11042 def setProtection( self
, private
):
11043 self
.__ac
.setProtection( private
)
11044 self
.updateFullyPublic()
11045 self
._p
_changed
= 1
11047 def isHidden( self
):
11048 return self
.__ac
.isHidden()
11050 @Updates (['MaKaC.conference.Material',
11051 'MaKaC.conference.Minutes',
11052 'MaKaC.conference.Paper',
11053 'MaKaC.conference.Slides',
11054 'MaKaC.conference.Video',
11055 'MaKaC.conference.Poster',
11056 'MaKaC.conference.Reviewing'], 'hidden')
11057 def setHidden( self
, hidden
):
11058 self
.__ac
.setHidden( hidden
)
11059 self
._p
_changed
= 1
11062 @Updates (['MaKaC.conference.Material',
11063 'MaKaC.conference.Minutes',
11064 'MaKaC.conference.Paper',
11065 'MaKaC.conference.Slides',
11066 'MaKaC.conference.Video',
11067 'MaKaC.conference.Poster',
11068 'MaKaC.conference.Reviewing'], 'accessKey')
11070 def setAccessKey( self
, pwd
="" ):
11071 self
.__ac
.setAccessKey(pwd
)
11072 self
._p
_changed
= 1
11074 def getAccessKey( self
):
11075 return self
.__ac
.getAccessKey()
11077 def grantAccess( self
, prin
):
11078 self
.__ac
.grantAccess( prin
)
11079 if isinstance(prin
, MaKaC
.user
.Avatar
):
11080 prin
.linkTo(self
, "access")
11081 self
._p
_changed
= 1
11083 def revokeAccess( self
, prin
):
11084 self
.__ac
.revokeAccess( prin
)
11085 if isinstance(prin
, MaKaC
.user
.Avatar
):
11086 prin
.unlinkTo(self
, "access")
11087 self
._p
_changed
= 1
11089 def canView( self
, aw
):
11090 """tells whether the specified user has access to the current object
11091 or any of its sub-objects
11093 if self
.isHidden() and not self
.canAccess( aw
):
11098 def isAllowedToAccess( self
, user
):
11099 return (not self
.isItselfProtected() and self
.getOwner().isAllowedToAccess( user
)) or self
.__ac
.canUserAccess( user
) or self
.canUserModify(user
)
11101 def canAccess( self
, aw
):
11103 # Allow harvesters (Invenio, offline cache) to access
11105 if self
.__ac
.isHarvesterIP(aw
.getIP()):
11107 #####################################################
11109 from MaKaC
.webinterface
.rh
.collaboration
import RCCollaborationAdmin
, RCCollaborationPluginAdmin
11110 if RCCollaborationAdmin
.hasRights(user
= aw
.getUser()) or \
11111 RCCollaborationPluginAdmin
.hasRights(user
=aw
.getUser(), plugins
='any'):
11114 canUserAccess
= self
.isAllowedToAccess( aw
.getUser() )
11115 canIPAccess
= self
.canIPAccess( aw
.getIP() )
11116 if not self
.isProtected():
11117 return canUserAccess
or canIPAccess
11119 canKeyAccess
= self
.canKeyAccess(aw
)
11120 return canUserAccess
or canKeyAccess
11122 def canKeyAccess( self
, aw
):
11123 sess
= aw
.getSession()
11126 keys
= sess
.getVar("accessKeys")
11128 key
= keys
.get(self
.getUniqueId(),"")
11129 if self
.getAccessKey() != "":
11130 return self
.__ac
.canKeyAccess(key
)
11131 elif self
.getConference() != None:
11132 return self
.getConference().canKeyAccess(aw
, key
)
11135 def grantModification( self
, prin
):
11136 self
.__ac
.grantModification( prin
)
11137 if isinstance(prin
, MaKaC
.user
.Avatar
):
11138 prin
.linkTo(self
, "manager")
11139 self
._p
_changed
= 1
11141 def revokeModification( self
, prin
):
11142 self
.__ac
.revokeModification( prin
)
11143 if isinstance(prin
, MaKaC
.user
.Avatar
):
11144 prin
.unlinkTo(self
, "manager")
11145 self
._p
_changed
= 1
11147 def canModify( self
, aw
):
11148 return self
.canUserModify( aw
.getUser() ) or (self
.getConference() and self
.getConference().canKeyModify( aw
))
11150 def canUserModify( self
, user
):
11151 """Tells whether a user is allowed to modify the current contribution:
11152 only if the user is granted to modify the contribution or the user
11153 can modify any of its upper objects (i.e. conference or session).
11155 return self
.getOwner().canUserModify( user
)
11157 def getModifKey( self
):
11158 return self
.getConference().getModifKey()
11160 def getManagerList( self
):
11161 return self
.__ac
.getModifierList()
11163 def getAllowedToAccessList( self
):
11164 return self
.__ac
.getAccessList()
11166 def requireDomain( self
, dom
):
11167 self
.__ac
.requireDomain( dom
)
11168 self
._p
_changed
= 1
11170 def freeDomain( self
, dom
):
11171 self
.__ac
.freeDomain( dom
)
11172 self
._p
_changed
= 1
11174 def getDomainList( self
):
11175 return self
.__ac
.getRequiredDomainList()
11177 def getAccessController(self
):
11180 def isBuiltin(self
):
11183 class BuiltinMaterial(Material
):
11185 Non-customizable material types
11187 def isBuiltin(self
):
11191 class Reviewing(BuiltinMaterial
):
11193 def __init__( self
, materialData
= None ):
11194 Material
.__init
__( self
, materialData
)
11195 self
.id = "reviewing"
11197 def setId( self
, newId
):
11200 def getContribution(self
):
11201 if isinstance(self
.getOwner(), Review
):
11202 return self
.getOwner().getContribution()
11203 return Material
.getContribution(self
)
11205 class Paper(BuiltinMaterial
):
11207 def __init__( self
, materialData
= None ):
11208 Material
.__init
__( self
, materialData
)
11211 def setId( self
, newId
):
11216 class Slides(BuiltinMaterial
):
11218 def __init__( self
, materialData
= None ):
11219 Material
.__init
__( self
, materialData
)
11222 def setId( self
, newId
):
11227 class Video(BuiltinMaterial
):
11229 def __init__( self
, materialData
= None ):
11230 Material
.__init
__( self
, materialData
)
11233 def setId( self
, newId
):
11236 class Poster(BuiltinMaterial
):
11238 def __init__( self
, materialData
= None ):
11239 Material
.__init
__( self
, materialData
)
11242 def setId( self
, newId
):
11245 class Minutes(BuiltinMaterial
):
11247 def __init__( self
, materialData
= None ):
11248 Material
.__init
__( self
, materialData
)
11249 self
.id = "minutes"
11250 self
.title
= "Minutes"
11253 def clone ( self
, owner
):
11255 mat
.setTitle(self
.getTitle())
11256 mat
.setDescription(self
.getDescription())
11257 mat
.notifyModification()
11259 mat
.setId(self
.getId())
11260 mat
.setOwner(owner
)
11261 mat
.setType(self
.getType())
11263 mat
.setProtection(self
.getAccessController()._getAccessProtection
())
11264 mat
.setAccessKey(self
.getAccessKey())
11265 lrep
= self
._getRepository
()
11266 flist
= lrep
.getFiles()
11267 rlist
= self
.getResourceList()
11269 if r
.getId()=="minutes":
11270 mat
.setText(self
.getText())
11271 elif isinstance(r
,Link
):
11273 newlink
.setOwner(mat
)
11274 newlink
.setName(r
.getName())
11275 newlink
.setDescription(r
.getDescription())
11276 newlink
.setURL(r
.getURL())
11277 mat
.addResource(newlink
)
11278 elif isinstance(r
,LocalFile
):
11279 newfile
= LocalFile()
11280 newfile
.setOwner(mat
)
11281 newfile
.setName(r
.getName())
11282 newfile
.setDescription(r
.getDescription())
11283 newfile
.setFilePath(r
.getFilePath())
11284 newfile
.setFileName(r
.getFileName())
11285 mat
.addResource(newfile
)
11287 raise Exception( _("Unexpected object type in Resource List : ")+str(type(r
)))
11289 mat
.setMainResource(self
.getMainResource())
11293 def setId( self
, newId
):
11296 def setTitle( self
, newTitle
):
11297 self
.title
= newTitle
.strip()
11298 self
.notifyModification()
11300 def _setFile( self
, forcedFileId
= None ):
11301 #XXX: unsafe; it must be changed by mkstemp when migrating to python 2.3
11302 tmpFileName
= tempfile
.mktemp()
11303 fh
= open(tmpFileName
, "w")
11306 self
.file = LocalFile()
11307 self
.file.setId("minutes")
11308 self
.file.setName("minutes")
11309 self
.file.setFilePath(tmpFileName
)
11310 self
.file.setFileName("minutes.txt")
11311 self
.file.setOwner(self
)
11312 self
.file.archive(self
._getRepository
(), forcedFileId
= forcedFileId
)
11314 def setText( self
, text
, forcedFileId
= None ):
11317 self
._setFile
(forcedFileId
= forcedFileId
)
11318 self
.file.replaceContent( text
)
11319 self
.getOwner().notifyModification()
11321 def getText( self
):
11324 return self
.file.readBin()
11326 def getResourceList( self
):
11327 res
= Material
.getResourceList( self
)
11329 res
.insert(0, self
.file)
11332 def getResourceById( self
, id ):
11333 if id.strip() == "minutes":
11335 return Material
.getResourceById( self
, id )
11337 def removeResource(self
, res
):
11338 Material
.removeResource(self
, res
)
11339 if self
.file is not None and res
.getId().strip() == "minutes":
11342 self
.notifyModification()
11344 def recoverResource(self
, recRes
):
11345 if recRes
.getId() == "minutes":
11346 recRes
.setOwner(self
)
11349 self
.notifyModification()
11351 Material
.recoverResource(self
, recRes
)
11354 class Resource(CommonObjectBase
):
11355 """This is the base class for representing individual resources which can
11356 be included in material containers for lately being attached to
11357 conference objects (i.e. conferences, sessions or contributions). This
11358 class provides basic data and operations to handle this resources.
11359 Resources can be of serveral types (files, links, ...) which means
11360 different specialisations of this class.
11362 id -- (string) Allows to assign the resource a unique identifier. It
11363 is normally used to uniquely identify the resource among other
11364 resources included in a certain material.
11365 name -- (string) Short description about the purpose or the contents
11367 description - (string) detailed and varied information about the
11369 __owner - (Material) reference to the material object in which the
11370 current resource is included.
11373 fossilizes(IResourceMinimalFossil
, IResourceFossil
)
11375 def __init__( self
, resData
= None ):
11376 self
.id = "not assigned"
11378 self
.description
= ""
11380 self
.__ac
= AccessController(self
)
11381 self
.pdfConversionRequestDate
= None
11383 def clone( self
, conf
, protection
=True ):
11384 res
= self
.__class
__()
11385 res
.setName(self
.getName())
11386 res
.setDescription(self
.getDescription())
11388 res
.notifyModification()
11389 res
.setId(self
.getId())
11392 res
.setProtection(self
.getAccessController()._getAccessProtection
())
11393 #res.__ac = self.getAccessController()
11397 def notifyModification( self
):
11398 parent
= self
.getOwner()
11400 parent
.setModificationDate()
11401 self
._p
_changed
= 1
11403 def getLocator( self
):
11404 if self
._owner
== None:
11406 lconf
= self
._owner
.getLocator()
11407 lconf
["resId"] = self
.getId()
11410 def setId( self
, newId
):
11411 self
.id = newId
.strip()
11416 def getUniqueId( self
):
11417 """returns (string) the unique identifier of the item
11418 used mainly in the web session access key table
11419 for resources, it is the same as the father material since
11420 only the material can be protected with an access key"""
11421 return self
.getOwner().getUniqueId()
11423 def setOwner( self
, newOwner
):
11424 self
._owner
= newOwner
11426 def getOwner( self
):
11429 def getCategory( self
):
11430 #raise "%s:%s:%s"%(self.getOwner(), Material, isinstance(self.getOwner, Material))
11432 if isinstance(self
.getOwner(), Category
):
11433 return self
.getOwner()
11434 if isinstance(self
.getOwner(), Material
):
11435 return self
.getOwner().getCategory()
11438 def getConference( self
):
11439 # this check owes itself to the fact that some
11440 # protection checking functions call getConference()
11441 # directly on resources, without caring whether they
11442 # are owned by Conferences or Categories
11443 if isinstance(self
._owner
, Category
):
11446 return self
._owner
.getConference()
11448 def getSession( self
):
11449 return self
._owner
.getSession()
11451 def getContribution( self
):
11452 return self
._owner
.getContribution()
11454 def getSubContribution( self
):
11455 return self
._owner
.getSubContribution()
11457 @Updates (['MaKaC.conference.Link',
11458 'MaKaC.conference.LocalFile'], 'name')
11459 def setName( self
, newName
):
11460 self
.name
= newName
.strip()
11461 self
.notifyModification()
11463 def getName( self
):
11466 @Updates (['MaKaC.conference.Link',
11467 'MaKaC.conference.LocalFile'], 'description')
11468 def setDescription( self
, newDesc
):
11469 self
.description
= newDesc
.strip()
11470 self
.notifyModification()
11472 def getDescription( self
):
11473 return self
.description
11475 def archive( self
, repository
= None, forcedFileId
= None ):
11476 """performs necessary operations to ensure the archiving of the
11477 resource. By default is doing nothing as the persistence of the
11478 system already ensures the archiving of the basic resource data"""
11481 def delete( self
):
11482 if self
._owner
!= None:
11483 self
._owner
.removeResource( self
)
11485 TrashCanManager().add(self
)
11488 TrashCanManager().remove(self
)
11490 def canIPAccess( self
, ip
):
11491 if not self
.__ac
.canIPAccess( ip
):
11493 if self
.getOwner() != None:
11494 return self
.getOwner().canIPAccess(ip
)
11497 def isProtected( self
):
11498 # tells if a resource is protected or not
11499 return (self
.hasProtectedOwner() + self
.getAccessProtectionLevel()) > 0
11501 def getAccessProtectionLevel( self
):
11502 return self
.__ac
.getAccessProtectionLevel()
11504 def isItselfProtected( self
):
11505 return self
.__ac
.isItselfProtected()
11507 def hasProtectedOwner( self
):
11508 if self
.getOwner() != None:
11509 return self
.getOwner().isProtected()
11512 @Updates (['MaKaC.conference.Link',
11513 'MaKaC.conference.LocalFile'],'protection', lambda(x
): int(x
))
11514 def setProtection( self
, private
):
11515 self
.__ac
.setProtection( private
)
11516 self
.getOwner().updateFullyPublic()
11518 def grantAccess( self
, prin
):
11519 self
.__ac
.grantAccess( prin
)
11520 if isinstance(prin
, MaKaC
.user
.Avatar
):
11521 prin
.linkTo(self
, "access")
11523 def revokeAccess( self
, prin
):
11524 self
.__ac
.revokeAccess( prin
)
11525 if isinstance(prin
, MaKaC
.user
.Avatar
):
11526 prin
.unlinkTo(self
, "access")
11528 def canView( self
, aw
):
11529 """tells whether the specified user has access to the current object
11530 or any of its sub-objects
11532 return self
.canAccess( aw
)
11534 def isAllowedToAccess( self
, user
):
11535 return self
.__ac
.canUserAccess( user
) or self
.canUserModify( user
) or (not self
.isItselfProtected() and self
.getOwner().isAllowedToAccess( user
))
11537 def canAccess( self
, aw
):
11538 # Allow harvesters (Invenio, offline cache) to access
11540 if self
.__ac
.isHarvesterIP(aw
.getIP()):
11542 #####################################################
11544 from MaKaC
.webinterface
.rh
.collaboration
import RCCollaborationAdmin
, RCCollaborationPluginAdmin
11545 if RCCollaborationAdmin
.hasRights(user
= aw
.getUser()) or \
11546 RCCollaborationPluginAdmin
.hasRights(user
=aw
.getUser(), plugins
='any'):
11549 if not self
.canIPAccess(aw
.getIP()) and not self
.canUserModify(aw
.getUser()) and not self
.isAllowedToAccess( aw
.getUser() ):
11551 if not self
.isProtected():
11553 flag
= self
.isAllowedToAccess( aw
.getUser() )
11554 return flag
or self
.canKeyAccess(aw
) or self
.getOwner().canKeyAccess(aw
) or \
11555 (self
.getConference() != None and self
.getConference().canKeyAccess(aw
) and self
.getAccessKey() == "") or \
11556 (self
.getConference() != None and self
.getConference().canKeyAccess(aw
) and self
.getAccessKey() == self
.getConference().getAccessKey())
11558 def grantModification( self
, prin
):
11559 self
.__ac
.grantModification( prin
)
11561 def revokeModification( self
, prin
):
11562 self
.__ac
.revokeModification( prin
)
11564 def canModify( self
, aw
):
11565 return self
.canUserModify( aw
.getUser() ) or (self
.getConference() and self
.getConference().canKeyModify( aw
))
11567 def canUserModify( self
, user
):
11568 """Tells whether a user is allowed to modify the current contribution:
11569 only if the user is granted to modify the contribution or the user
11570 can modify any of its upper objects (i.e. conference or session).
11572 return self
.getOwner().canUserModify( user
)
11574 def getModifKey( self
):
11575 return self
.getConference().getModifKey()
11577 def getManagerList( self
):
11578 return self
.__ac
.getModifierList()
11580 def getAllowedToAccessList( self
):
11581 return self
.__ac
.getAccessList()
11583 def getURL( self
):
11586 def requireDomain( self
, dom
):
11587 self
.__ac
.requireDomain( dom
)
11589 def freeDomain( self
, dom
):
11590 self
.__ac
.freeDomain( dom
)
11592 def getDomainList( self
):
11593 return self
.__ac
.getRequiredDomainList()
11595 def getAccessController(self
):
11598 def getAccessKey(self
):
11599 if self
.getOwner() is not None:
11600 return self
.getOwner().getAccessKey()
11603 def canKeyAccess( self
, aw
):
11604 sess
= aw
.getSession()
11607 accessKey
= self
.getAccessKey()
11608 keys
= sess
.getVar("accessKeys")
11610 if keys
.has_key(self
.getUniqueId()):
11611 if (accessKey
!= "" and keys
[self
.getUniqueId()] == accessKey
) or (accessKey
== "" and self
.getConference().getAccessKey() != "" and keys
[self
.getUniqueId()] == self
.getConference().getAccessKey()):
11615 def getReviewingState(self
):
11616 """ Returns the reviewing state of a resource, which is the reviewing state of the material to which it belongs.
11617 The state is represented by an integer:
11618 0 : there's no reviewing state because the resource doesn't belong to a material,
11619 the material does not belong to a contribution, or the conference does not have reviewing.
11620 1 : the material is not subject to reviewing, because this kind of material is not reviewable in the conference
11621 2 : the material is subject to reviewing, but has not been submitted yet by the author
11622 3 : the material is subject to reviewing, has been submitted by the author, but has not been judged yet
11623 4 : the material is subject to reviewing, has been submitted by the author, and has been judged as Accepted
11624 5 : the material is subject to reviewing, has been submitted by the author, and has been judged as Rejected
11626 if isinstance(self
.getOwner(), Material
):
11627 return self
.getOwner().getReviewingState()
11628 else: #ressource does not belong to a material
11631 def setPDFConversionRequestDate( self
, newPdfConversionRequestDate
):
11632 self
.pdfConversionRequestDate
= newPdfConversionRequestDate
11634 def getPDFConversionStatus(self
):
11636 if not hasattr(self
, "pdfConversionRequestDate"):
11637 self
.pdfConversionRequestDate
= None
11639 if self
.pdfConversionRequestDate
is not None and self
.pdfConversionRequestDate
+ timedelta(seconds
=50) > nowutc() :
11640 return 'converting'
11644 class Link(Resource
):
11645 """Specialises Resource class in order to represent web links. Objects of
11646 this class will contain necessary information to include in a conference
11647 object links to internet resources through a URL.
11649 url -- (string) Contains the URL to the internet target resource.
11652 fossilizes(ILinkMinimalFossil
, ILinkFossil
)
11654 def __init__( self
, resData
= None ):
11655 Resource
.__init
__( self
, resData
)
11658 def clone( self
, conf
):
11659 link
= Resource
.clone(self
, conf
)
11660 link
.setURL(self
.getURL())
11663 @Updates ('MaKaC.conference.Link', 'url')
11664 def setURL( self
, newURL
):
11665 self
.url
= newURL
.strip()
11666 self
.notifyModification()
11668 def getURL( self
):
11672 class LocalFile(Resource
):
11673 """Specialises Resource class in order to represent files which can be
11674 stored in the system. The user can choose to use the system as an
11675 archive of electronic files so he may want to attach a file which is
11676 in his computer to a conference so it remains there and must be kept
11677 in the system. This object contains the file basic metadata and provides
11678 the necessary operations to ensure the corresponding file is archived
11679 (it uses one of the file repositories of the system to do so) and keeps
11680 the reference for being able to access it afterwards.
11682 fileName -- (string) Name of the file. Normally the original name of
11683 the user submitted file is kept.
11684 filePath -- (string) If it is set, it contains a local path to the
11685 file submitted by the user and uploaded in the system. This
11686 attribute is only temporary used so it keeps a pointer to a
11687 temporary uploaded file.
11688 __repository -- (FileRep) Once a file is archived, it is kept in a
11689 FileRepository for long term. This attribute contains a pointer
11690 to the file repository where the file is kept.
11691 __archivedId -- (string) It contains a unique identifier for the file
11692 inside the repository where it is archived.
11695 fossilizes(ILocalFileMinimalFossil
, ILocalFileFossil
, ILocalFileExtendedFossil
, ILocalFileAbstractMaterialFossil
)
11697 def __init__( self
, resData
= None ):
11698 Resource
.__init
__( self
, resData
)
11702 self
.__repository
= None
11703 self
.__archivedId
= ""
11705 def clone( self
, conf
, protection
=True ):
11706 localfile
= Resource
.clone(self
, conf
, protection
)
11707 localfile
.setFilePath(self
.getFilePath())
11708 localfile
.setFileName(self
.getFileName())
11711 def setFileName( self
, newFileName
, checkArchive
=True ):
11712 """While the file is not archived sets the file name of the current
11713 object to the one specified (if a full path is specified the
11714 base name is extracted) replacing on it blanks by underscores.
11716 if checkArchive
and self
.isArchived():
11717 raise MaKaCError( _("The file name of an archived file cannot be changed"), _("File Archiving"))
11718 #Using os.path.basename is not enough as it only extract filenames
11719 # correclty depending on the server platform. So we need to convert
11720 # to the server platform and apply the basename extraction. As I
11721 # couldn't find a python function for this this is done manually
11722 # although it can contain errors
11723 #On windows basename function seems to work properly with unix file
11725 if newFileName
.count("/"):
11727 newFileName
= newFileName
.split("/")[-1]
11729 #windows file path: there "/" is not allowed on windows paths
11730 newFileName
= newFileName
.split("\\")[-1]
11731 self
.fileName
= newFileName
.strip().replace(" ", "_")
11733 def getFileName( self
):
11734 return self
.fileName
11736 def getFileType( self
):
11737 fileExtension
= os
.path
.splitext( self
.getFileName() )[1]
11738 if fileExtension
!= "":
11739 fileExtension
= fileExtension
[1:]
11740 cfg
= Config
.getInstance()
11741 if cfg
.getFileType( fileExtension
) != "":
11742 return cfg
.getFileType( fileExtension
)
11744 return fileExtension
11746 def setFilePath( self
, filePath
):
11747 if self
.isArchived():
11748 raise MaKaCError( _("The path of an archived file cannot be changed"), _("File Archiving"))
11749 if not os
.access( filePath
.strip(), os
.F_OK
):
11750 raise Exception( _("File does not exist : %s")%filePath
.strip())
11751 self
.filePath
= filePath
.strip()
11753 def getCreationDate( self
):
11754 return self
.__repository
.getCreationDate(self
.__archivedId
)
11756 def getFilePath( self
):
11757 if not self
.isArchived():
11758 return self
.filePath
11759 return self
.__repository
.getFilePath(self
.__archivedId
)
11761 def getSize( self
):
11762 if not self
.isArchived():
11763 return int(os
.stat(self
.getFilePath())[stat
.ST_SIZE
])
11764 return self
.__repository
.getFileSize( self
.__archivedId
)
11766 def setArchivedId( self
, rep
, id ):
11767 self
.__repository
= rep
11768 self
.__archivedId
= id
11770 def getRepositoryId( self
):
11771 return self
.__archivedId
11773 def setRepositoryId(self
, id):
11774 self
.__archivedId
= id
11776 def isArchived( self
):
11777 return self
.__repository
!= None and self
.__archivedId
!= ""
11779 def readBin( self
):
11780 if not self
.isArchived():
11781 raise MaKaCError( _("File not available until it has been archived") , _("File Archiving"))
11782 return self
.__repository
.readFile( self
.__archivedId
)
11784 def replaceContent( self
, newContent
):
11785 if not self
.isArchived():
11786 raise MaKaCError( _("File not available until it has been archived") , _("File Archiving"))
11787 self
.__repository
.replaceContent( self
.__archivedId
, newContent
)
11789 def archive( self
, repository
=None, forcedFileId
= None ):
11790 if self
.isArchived():
11791 raise Exception( _("File is already archived"))
11793 raise Exception( _("Destination repository not set"))
11794 if self
.filePath
== "":
11795 return _("Nothing to archive")
11796 repository
.storeFile( self
, forcedFileId
= forcedFileId
)
11798 self
.notifyModification()
11800 def unArchive(self
):
11802 self
.__repository
= None
11803 self
.__archivedId
= ""
11806 if not self
.isArchived():
11807 raise Exception( _("File is not archived, so it cannot be recovered."))
11808 if not self
.__repository
:
11809 raise Exception( _("Destination repository not set."))
11810 self
.__repository
.recoverFile(self
)
11811 Resource
.recover(self
)
11812 self
.notifyModification()
11814 def delete( self
):
11815 if not self
.isArchived():
11816 os
.remove( self
.getFilePath() )
11818 self
.__repository
.retireFile( self
)
11819 except AttributeError, e
:
11821 Resource
.delete( self
)
11823 def getRepository(self
):
11824 return self
.__repository
11826 def __str__( self
):
11827 return self
.getFileName()
11829 #getURL is removed at the moment from the LocalFile and the file access
11830 # is completely delegated to the web interface; the web interface will
11831 # have to access the files locally (using the getFilePath) or the readBin
11833 #However, for the future it could be required to have several file
11834 # repositories so the file access will have to be reviewed.
11835 #def getURL( self ):
11836 # #XXX: Very bad!! We should find a better solution
11837 # c = Config.getInstance()
11838 # return c.getArchivedFileURL( self )
11841 class TCIndex( Persistent
):
11842 """Index for conference track coordinators.
11844 This class allows to index conference track coordinators so the owner
11845 can answer optimally to the query if a user is coordinating
11846 any conference track.
11847 It is implemented by simply using a BTree where the Avatar id is used
11848 as key (because it is unique and non variable) and a list of
11849 coordinated tracks is kept as keys. It is the responsability of the
11850 index owner (conference) to keep it up-to-date i.e. notify track
11851 coordinator additions and removals.
11854 def __init__( self
):
11855 self
._idx
= OOBTree()
11858 def getTracks( self
, av
):
11859 """Gives a list with the tracks a user is coordinating.
11863 return self
._idx
.get( av
.getId(), [] )
11865 def indexCoordinator( self
, av
, track
):
11866 """Registers in the index a coordinator of a track.
11868 if av
== None or track
== None:
11870 if not self
._idx
.has_key( av
.getId() ):
11873 l
= self
._idx
[av
.getId()]
11876 # necessary, otherwise ZODB won't know it needs to update the BTree
11877 self
._idx
[av
.getId()] = l
11878 self
.notifyModification()
11880 def unindexCoordinator( self
, av
, track
):
11881 if av
== None or track
== None:
11883 l
= self
._idx
.get( av
.getId(), [] )
11886 self
._idx
[av
.getId()] = l
11887 self
.notifyModification()
11889 def notifyModification(self
):
11890 self
._p
_changed
= 1
11893 class Track(CoreObject
):
11895 def __init__( self
):
11896 self
.conference
= None
11897 self
.id = "not assigned"
11899 self
.description
= ""
11900 self
.subTracks
= {}
11901 self
.__SubTrackGenerator
= Counter()
11902 self
._abstracts
= OOBTree()
11903 self
._coordinators
= []
11904 self
._contributions
= OOBTree()
11907 def clone(self
, conference
):
11909 tr
.setConference(conference
)
11910 tr
.setTitle(self
.getTitle())
11911 tr
.setCode(self
.getCode())
11912 tr
.setDescription(self
.getDescription())
11914 for co
in self
.getCoordinatorList() :
11915 tr
.addCoordinator(co
)
11917 for subtr
in self
.getSubTrackList() :
11918 tr
.addSubTrack(subtr
.clone())
11923 def delete( self
):
11924 """Deletes a track from the system. All the associated abstracts will
11925 also be notified so the track is no longer associated to them.
11927 #XXX: Should we allow to delete a track when there are some abstracts
11928 # or contributions submitted for it?!?!?!?!
11930 # we must notify each abstract in the track about the deletion of the
11932 while len(self
._abstracts
)>0:
11933 k
= self
._abstracts
.keys()[0]
11934 abstract
= self
._abstracts
[k
]
11935 del self
._abstracts
[k
]
11936 abstract
.removeTrack( self
)
11938 # we must notify each contribution in the track about the deletion of the
11940 while len(self
._contributions
)>0:
11941 k
= self
._contributions
.keys()[0]
11942 contrib
= self
._contributions
[k
]
11943 del self
._contributions
[k
]
11944 contrib
.removeTrack( self
)
11946 # we must delete and unindex all the possible track coordinators
11947 while len(self
._coordinators
)>0:
11948 self
.removeCoordinator(self
._coordinators
[0])
11950 # we must notify the conference about the track deletion
11951 if self
.conference
:
11952 conf
= self
.conference
11953 self
.conference
= None
11954 conf
.removeTrack( self
)
11956 TrashCanManager().add(self
)
11959 TrashCanManager().remove(self
)
11961 def canModify( self
, aw
):
11962 return self
.conference
.canModify( aw
)
11964 def canUserModify( self
, av
):
11965 return self
.conference
.canUserModify( av
)
11967 def canView( self
, aw
):
11968 return self
.conference
.canView( aw
)
11970 def notifyModification( self
):
11971 parent
= self
.getConference()
11973 parent
.setModificationDate()
11974 self
._p
_changed
= 1
11976 def getLocator( self
):
11977 """Gives back a globaly unique identification encapsulated in a Locator
11978 object for the track instance
11980 if self
.conference
== None:
11982 lconf
= self
.conference
.getLocator()
11983 lconf
["trackId"] = self
.getId()
11986 def setConference(self
, conference
):
11987 self
.conference
= conference
11989 def getConference( self
):
11990 return self
.conference
11992 def getOwner( self
):
11993 return self
.getConference()
11995 def setId( self
, newId
):
11996 self
.id = str(newId
)
12001 def setTitle( self
, newTitle
):
12002 self
.title
= newTitle
12003 self
.notifyModification()
12005 def getTitle( self
):
12008 def setDescription(self
, newDescription
):
12009 self
.description
= newDescription
12010 self
.notifyModification()
12012 def getDescription(self
):
12013 return self
.description
12019 except AttributeError:
12023 def setCode(self
,newCode
):
12024 self
._code
=str(newCode
).strip()
12026 def __generateNewSubTrackId( self
):
12027 return str(self
.__SubTrackGenerator
.newCount())
12029 def addSubTrack( self
, newSubTrack
):
12030 """Registers the contribution passed as parameter within the session
12031 assigning it a unique id.
12033 if newSubTrack
in self
.subTracks
.values():
12035 subTrackId
= newSubTrack
.getId()
12036 if subTrackId
== "not assigned":
12037 subTrackId
= self
.__generateNewSubTrackId
()
12038 self
.subTracks
[subTrackId
] = newSubTrack
12039 newSubTrack
.setTrack( self
)
12040 newSubTrack
.setId( subTrackId
)
12041 self
.notifyModification()
12043 def removeSubTrack( self
, subTrack
):
12044 """Removes the indicated contribution from the session
12046 if subTrack
in self
.subTracks
.values():
12047 del self
.subTracks
[ subTrack
.getId() ]
12048 subTrack
.setTrack( None )
12050 self
.notifyModification()
12052 def recoverSubTrack(self
, subTrack
):
12053 self
.addSubTrack(subTrack
)
12056 def newSubTrack( self
):
12058 self
.addSubTrack( st
)
12061 def getSubTrackById( self
, id ):
12062 if self
.subTracks
.has_key( id ):
12063 return self
.subTracks
[ id ]
12066 def getSubTrackList( self
):
12067 return self
.subTracks
.values()
12069 def getAbstractList( self
):
12073 if self
._abstracts
:
12075 except AttributeError:
12076 self
._abstracts
= OOBTree()
12077 return self
._abstracts
.values()
12079 def getAbstractById( self
, id ):
12081 if self
._abstracts
:
12083 except AttributeError:
12084 self
._abstracts
= OOBTree()
12085 return self
._abstracts
.get(str(id).strip())
12087 def hasAbstract( self
, abstract
):
12091 if self
._abstracts
:
12093 except AttributeError:
12094 self
._abstracts
= OOBTree()
12095 return self
._abstracts
.has_key( abstract
.getId() )
12097 def addAbstract( self
, abstract
):
12098 """Adds an abstract to the track abstract list.
12100 Notice that this method doesn't notify the abstract about the track
12103 if not self
.hasAbstract( abstract
):
12104 self
._abstracts
[ abstract
.getId() ] = abstract
12105 #abstract.addTrack( self )
12107 def removeAbstract( self
, abstract
):
12108 """Removes an abstract from the track abstract list.
12110 Notice that this method doesn't notify the abstract about the track
12113 if self
.hasAbstract( abstract
):
12114 del self
._abstracts
[ abstract
.getId() ]
12115 #abstract.removeTrack( self )
12117 def addCoordinator( self
, av
):
12118 """Grants coordination privileges to user.
12121 av -- (MaKaC.user.Avatar) the user to which
12122 coordination privileges must be granted.
12126 if self
._coordinators
:
12128 except AttributeError, e
:
12129 self
._coordinators
= []
12130 self
.notifyModification()
12132 if not (av
in self
._coordinators
):
12133 self
._coordinators
.append( av
)
12134 self
.getConference().addTrackCoordinator( self
, av
)
12135 av
.linkTo(self
, "coordinator")
12136 self
.notifyModification()
12138 def removeCoordinator( self
, av
):
12139 """Revokes coordination privileges to user.
12142 av -- (MaKaC.user.Avatar) user for which coordination privileges
12146 if self
._coordinators
:
12148 except AttributeError, e
:
12149 self
._coordinators
= []
12150 self
.notifyModification()
12152 if av
in self
._coordinators
:
12153 self
._coordinators
.remove( av
)
12154 self
.getConference().removeTrackCoordinator( self
, av
)
12155 av
.linkTo(self
, "coordinator")
12156 self
.notifyModification()
12158 def isCoordinator( self
, av
):
12159 """Tells whether the specified user is a coordinator of the track.
12162 av -- (MaKaC.user.Avatar) user to be checke
12164 Return value: (boolean)
12167 if self
._coordinators
:
12169 except AttributeError, e
:
12170 self
._coordinators
= []
12172 return av
in self
._coordinators
12174 def getCoordinatorList( self
):
12175 """Return all users which have privileges to coordinate the track.
12177 Return value: (list)
12180 if self
._coordinators
:
12182 except AttributeError, e
:
12183 self
._coordinators
= []
12185 return self
._coordinators
12187 def canCoordinate( self
, aw
):
12188 """Tells if a user has coordination privileges.
12190 Only track coordinators have coordination privileges over a track.
12193 aw -- (MaKaC.accessControl.AccessWrapper) User access
12194 information for which the coordination privileges must be
12197 Return value: (boolean)
12199 return self
.isCoordinator( aw
.getUser() ) or self
.canModify( aw
)
12201 def addContribution( self
, newContrib
):
12205 if self
._contributions
:
12207 except AttributeError:
12208 self
._contributions
= OOBTree()
12209 if self
._contributions
.has_key( newContrib
.getId() ):
12211 self
._contributions
[ newContrib
.getId() ] = newContrib
12212 newContrib
.setTrack( self
)
12214 def getModifKey( self
):
12215 return self
.getConference().getModifKey()
12217 def removeContribution( self
, contrib
):
12221 if self
._contributions
:
12223 except AttributeError:
12224 self
._contributions
= OOBTree()
12225 if not self
._contributions
.has_key( contrib
.getId() ):
12227 del self
._contributions
[ contrib
.getId() ]
12228 contrib
.setTrack( None )
12230 def hasContribution( self
, contrib
):
12232 if self
._contributions
:
12234 except AttributeError:
12235 self
._contributions
= OOBTree()
12236 return self
._contributions
.has_key( contrib
.getId() )
12238 def getContributionList(self
):
12240 if self
._contributions
:
12242 except AttributeError:
12243 self
._contributions
= OOBTree()
12244 return self
._contributions
.values()
12246 def canUserCoordinate( self
, av
):
12247 return self
.isCoordinator( av
) or self
.canUserModify( av
)
12250 class SubTrack(CoreObject
):
12252 def __init__( self
):
12254 self
.id = "not assigned"
12256 self
.description
= ""
12260 sub
.setDescription(self
.getDescription())
12261 sub
.setTitle(self
.getTitle())
12267 TrashCanManager().add(self
)
12270 TrashCanManager().remove(self
)
12272 def canModify( self
, aw
):
12273 return self
.track
.canModify( aw
)
12275 def canView( self
, aw
):
12276 return self
.track
.canView( aw
)
12278 def notifyModification( self
):
12279 parent
= self
.getTrack()
12281 parent
.setModificationDate()
12282 self
._p
_changed
= 1
12284 def getLocator( self
):
12285 """Gives back a globaly unique identification encapsulated in a Locator
12286 object for the session instance
12288 if self
.track
== None:
12290 lconf
= self
.track
.getLocator()
12291 lconf
["subTrackId"] = self
.getId()
12294 def setTrack(self
, track
):
12299 def getTrack( self
):
12302 def getOwner( self
):
12303 return self
.getTrack()
12305 def setId( self
, newId
):
12306 self
.id = str(newId
)
12311 def setTitle( self
, newTitle
):
12312 self
.title
= newTitle
12313 self
.notifyModification()
12315 def getTitle( self
):
12318 def setDescription(self
, newDescription
):
12319 self
.description
= newDescription
12320 self
.notifyModification()
12322 def getDescription(self
):
12323 return self
.description
12326 class ContributionType(Persistent
):
12328 def __init__(self
, name
, description
, conference
):
12331 self
._description
= description
12332 self
._conference
= conference
12337 def setId(self
, id):
12343 def setName(self
, name
):
12346 def getDescription(self
):
12347 return self
._description
12349 def setDescription(self
, desc
):
12350 self
._description
= desc
12352 def getConference(self
):
12353 return self
._conference
12355 def setConference(self
, conf
):
12356 self
._conference
= conf
12358 def getLocator( self
):
12359 if self
._conference
== None:
12361 lconf
= self
._conference
.getLocator()
12362 lconf
["contribTypeId"] = self
.getId()
12365 def canModify(self
, aw
):
12366 return self
._conference
.canModify(aw
)
12369 self
.setConference(None)
12370 TrashCanManager().add(self
)
12373 TrashCanManager().remove(self
)
12375 def clone(self
, conference
):
12376 type = ContributionType(self
.getName(), self
.getDescription(),conference
)
12380 class BOAConfig(Persistent
):
12381 """Contains the configuration of the Book of Abstracts of a conference
12383 sortByTypes
= {"number": L_("ID"),
12384 "name": L_("Title"),
12385 "sessionTitle": L_("Session title"),
12386 "speaker": L_("Presenter"),
12387 "schedule": L_("Schedule")}
12389 def __init__(self
,conf
):
12392 self
._showIds
= False
12393 self
._sortBy
= "number"
12394 self
._modificationDS
= nowutc()
12395 self
._cache
= False
12400 def setText(self
,newText
):
12401 self
._text
=newText
.strip()
12402 self
._notifyModification
()
12404 def getShowIds(self
):
12405 if not hasattr(self
, "_showIds"):
12406 self
._showIds
=False
12407 return self
._showIds
12409 def setShowIds(self
,showIds
):
12410 self
._showIds
=showIds
12411 self
._notifyModification
()
12413 def getSortBy(self
):
12414 if not hasattr(self
, "_sortBy"):
12415 self
._sortBy
="number"
12416 return self
._sortBy
12418 def setSortBy(self
,sortBy
):
12419 self
._sortBy
=sortBy
12420 self
._notifyModification
()
12423 def getSortByTypes():
12424 return BOAConfig
.sortByTypes
12426 def isCacheEnabled(self
):
12427 if not hasattr(self
, '_cache'):
12428 self
._cache
= False
12431 def setCache(self
, value
):
12432 self
._cache
= value
;
12434 def _notifyModification(self
):
12435 self
._modificationDS
= nowutc()
12438 def lastChanged(self
):
12439 if not hasattr(self
, '_modificationDS'):
12440 self
._modificationDS
= nowutc()
12441 return self
._modificationDS