""" TTW Object

a generic object for holding generic data :-)

(C) 2003 by Christian Scholz/MrTopf of COM.lounge

"""


from AccessControl import ClassSecurityInfo, getSecurityManager, Unauthorized
from Products.CMFCore.PortalContent import PortalContent
from Products.CMFCore import CMFCorePermissions
from Products.CMFCore.utils import getToolByName
from Products.CMFDefault.DublinCore import DefaultDublinCoreImpl
from Products.CMFDefault.SkinnedFolder  import SkinnedFolder
from Globals import PersistentMapping, InitializeClass
from Products.CMFCore.CMFCorePermissions import View, ManageProperties, ListFolderContents

# list of field types to be used for a fulltext index

SEARCHABLE_FIELD_TYPES=[
    'StringField',
    'TextAreaField',
    'EmailField',
    'RawTextAreaField',
    'LinkField'
]


class TTWFolder(SkinnedFolder, DefaultDublinCoreImpl):
    """ a generic object for ttw creation """

    __implements__ = ( PortalContent.__implements__
		     , DefaultDublinCoreImpl.__implements__
		     )
    
    security=ClassSecurityInfo()

    meta_type="TTWFolder"

    def __init__(self,id,portal_type,title=''):
	""" create a new type """
	DefaultDublinCoreImpl.__init__(self,title=title)
	
	self.portal_type=portal_type.id
	self.id=id
	self.title=title

	# get the field definition
	form=portal_type.form

	self._fieldnames=[]
	for field in form.get_fields():
	    self._fieldnames.append(field.id)

    ### DefaultDublinCoreImpl.editMetadata() has a very bad assumption
    ### which it does not declare in its interface which is 
    ### failIflocked
    def failIfLocked(self):
        """ failIfLocked is used for WEBDAV locking """
        plone=getToolByName(self, 'plone_utils')
        #log(self.absolute_url() + " failIfLocked called on Plone Folder" )
        return 0
    
    ### FIXME! SkinnedFolder Creator method doesnt work when creating
    ### objects via Python (eg: on a unittest) apparently because of
    ### a missing context
    Creator = DefaultDublinCoreImpl.Creator

    def set(self, field, value):
	""" set a value """
	setattr(self,field,value)

    def get(self,field,default=None):
	""" get a field value """
	return getattr(self,field,default)

    def getFields(self):
	""" return the list formulator field objects """
	return self.getTypeInfo().getForm().get_fields()

    def fieldNames(self):
	""" return list of field names """
	fields=self.getFields()
	return map(lambda x: x.id, fields)

    def store(self,field,value):
	""" a frontend to set in order to catch FileUploads """
	from ZPublisher.HTTPRequest import FileUpload
	from OFS.Image import File, Image
	from imghdr import what

	# this should be configurable at some point
	# to choose which object to create
	if isinstance(value,FileUpload):
	    # check for emptyness
	    value.seek(-1, 2)
	    size = value.tell()
	    value.seek(0)
	    if size == 0:
		return 
	    # test for image type
	    if what(value) in ('gif','jpeg','png'):
		# create an Image instance
		value=Image(field,field,value)
	    else:
		# create a File instance
		value=File(field,field,value)

	# now really store it
	self.set(field,value)

    def edit(self, **kwargs):
	""" update object data """
	keys=kwargs.keys()
	for field in self.fieldNames():
	    if field in keys:
		self.store(field,kwargs[field])
	
	# set Title
	if 'title' in keys:
	    self.title=kwargs['title']
	self.reindexObject()

    # make everything searchable
    def SearchableText(self):
	""" return an indexable text 

	a future idea might be to add pluggable indexers here
	e.g. as python scripts.
	
	"""
	index=[self.title_or_id()]
	for f in self.getFields():
	    if f.meta_type == 'LinesField':
		index.append(" ".join(self.get(f.id)))
	    elif f.meta_type in SEARCHABLE_FIELD_TYPES:
		index.append(self.get(f.id))
	index=map(str, index)
	index=' '.join(index)
	return index

    security.declareProtected( ListFolderContents, 'listFolderContents')
    def listFolderContents( self, spec=None, contentFilter=None, suppressHiddenFiles=0 ): 
        """
        Hook around 'contentValues' to let 'folder_contents'
        be protected.  Duplicating skip_unauthorized behavior of dtml-in.
        
        In the world of Plone we do not want to show objects that begin with a .
        So we have added a simply check.  We probably dont want to raise an
        Exception as much as we want to not show it.
        
        """

        items = self.contentValues(spec=spec, filter=contentFilter)
        l = []
        for obj in items:
            id = obj.getId()
            v = obj
            try:
                if suppressHiddenFiles and id[:1]=='.': 
                    raise Unauthorized(id, v)
                if getSecurityManager().validate(self, self, id, v):
                    if not (obj.effective_date and obj.effective_date.isFuture() and not _checkPermission('Access future content', obj)) and not (obj.expiration_date and obj.expiration_date.isPast() and not _checkPermission('Access inactive portal content', obj)):
                        l.append(obj)
            except (Unauthorized, 'Unauthorized'):
                pass
        return l

InitializeClass(TTWFolder)

def manage_addTTWFolder(self, id, portal_type, title=''):
    """ add a new TTW object """
    o=TTWFolder(id,portal_type,title)
    self._setObject(id,o)
