zsqlbrain.py 6.08 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
##############################################################################
#
# Copyright (c) 2002 Nexedi SARL. All Rights Reserved.
# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################

import Acquisition
16
import traceback
17 18 19
from ZODB.POSException import ConflictError
from AccessControl import ClassSecurityInfo
from AccessControl.SecurityInfo import allow_class
20
from zLOG import LOG, WARNING
21 22 23 24
try:
  from Products.CMFActivity.ActiveObject import DEFAULT_ACTIVITY
except ImportError:
  DEFAULT_ACTIVITY = None
25 26
_MARKER = []

27
class ZSQLBrain(Acquisition.Implicit):
28 29 30 31
  security = ClassSecurityInfo()
  security.declareObjectPublic()

  def _aq_dynamic(self, name):
32 33 34 35
    """Acquire an attribute from a real object.
    """
    if name.startswith('__') :
      return None
36
    return getattr(self.getObject(), name, None)
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54

  def getURL(self):
    return self.path

  def getUrl(self):
    return self.path

  def getPath(self):
    return self.path

  def getUid(self):
    return self.uid

  getRID = getUid

  def getObject(self, REQUEST=None):
    """Try to return the object for this record"""
    if 'path' not in dir(self) and 'PATH' not in dir(self):
55 56
      raise ValueError("Unable to getObject from ZSQLBrain if ZSQL Method does"
                       " not retrieve the `path` column from catalog table.")
57 58 59 60 61 62 63
    obj = self.aq_parent.unrestrictedTraverse(self.getPath())
    if obj is None:
      if REQUEST is None:
        REQUEST = self.REQUEST
      obj = self.aq_parent.portal_catalog.resolve_url(
                                self.getPath(), REQUEST)
    return obj
64

65 66 67 68 69 70 71 72 73 74 75 76 77
  def getProperty(self, name, d=_MARKER, **kw):
    value = None
    if hasattr(self, name):
      value = getattr(self, name)
    else:
      if d is not _MARKER:
        kw['d'] = d
      document = self.getObject()
      if document is None:
        raise AttributeError(name)
      value = document.getProperty(name, **kw)
    return value

78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
  def absolute_url(self, relative=0):
    """
      Default method used to return the path stored in the Catalog.
      However, if virtual hosting is implemented, we must return
      a value which is compatible with the standard absolute_url
      behaviour

      And if absolute_url is invoked within a Web Site,
      additional Web Site behaviour is required

      Implementation of absolute_url therefore consists in using
      physicalPathToURL defined in the REQUEST so that absolute_url
      is consistent with HTTPRequest implementation.
    """
    return self.REQUEST.physicalPathToURL(self.path, relative=relative)

  def resolve_url(self, path, REQUEST):
    """
      Taken from ZCatalog

      Attempt to resolve a url into an object in the Zope
      namespace. The url may be absolute or a catalog path
      style url. If no object is found, None is returned.
      No exceptions are raised.
    """
103
    script = REQUEST.script
104
    if not path.startswith(script):
105 106 107 108 109 110 111 112
      path='%s/%s' % (script, path)
    try:
      return REQUEST.resolve_url(path)
    except ConflictError:
      raise
    except:
      pass

113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
  # If CMFActivity is available, we add ZSQLBrain.activate() that does
  # not call getObject() for better performance and less memory usage.
  if DEFAULT_ACTIVITY is not None:
    def activate(self, activity=DEFAULT_ACTIVITY, active_process=None,
                 activate_kw=None, **kw):
      """
      This method returns an ActiveWrapper without calling getObject().

      See CMFActivity.ActiveObject.activate() for the detail of API.
      """
      try:
        activity_tool = self.aq_parent.getPortalObject().portal_activities
      except AttributeError:
        return self # Do nothing if no portal_activities
      # here we cannot have local default_activate_parameter because
      # we don't want to access the object. if we really need local
      # one, we can just call like brain.getObject().activate()
      # instead.
      new_kw = activity_tool.getDefaultActivateParameterDict(inherit_placeless=False)
      if activate_kw:
        new_kw.update(activate_kw)
      new_kw.update(kw)

      # activate returns an ActiveWrapper
      # a queue can be provided as well as extra parameters
      # which can be used for example to define deferred tasks
      return activity_tool.activateObject(
140
        self.getPath(), activity, active_process, uid=self.getUid(), **new_kw)
141

142
allow_class(ZSQLBrain)
143 144 145 146

class ZSQLBrainNoObject(ZSQLBrain):
  security = ClassSecurityInfo()
  security.declareObjectPublic()
147

148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
  def getObject(self):
    stack = ''.join(traceback.format_stack())
    LOG('Products.ZSQLCatalog.Extentions.zsqlbrain.ZSQLBrainNoObject', WARNING,
        "Attempted direct access to object %r:\n%s" % (self.getPath(), stack))
    return None

  def getProperty(self, name, d=_MARKER, **kw):
    value = None
    if hasattr(self, name):
      value = getattr(self, name)
    else:
      stack = ''.join(traceback.format_stack())
      LOG('Products.ZSQLCatalog.Extentions.zsqlbrain.ZSQLBrainNoObject',
          WARNING,
          "Non-existing property %r on record for %r:\n%s" % (name,
163
                                                              self.getPath(),
164 165 166 167 168 169 170 171 172 173
                                                              stack))
      return None
    return value

  def _aq_dynamic(self, name):
    """Do not acquire an attribute from a real object.
    """
    stack = ''.join(traceback.format_stack(limit=5))
    LOG('Products.ZSQLCatalog.Extentions.zsqlbrain.ZSQLBrainNoObject', WARNING,
        "Non-existing attribute %r on record for %r:\n%s" % (name,
174
                                                             self.getPath(),
175 176 177
                                                             stack))
allow_class(ZSQLBrainNoObject)