[gen] Changes in parameters of some basic field methods to enable field.languages to be defined dymanically via a method.
This commit is contained in:
parent
18afb4416c
commit
f8a7103c7a
|
@ -63,7 +63,7 @@ class Field:
|
|||
value=not isSearch and \
|
||||
field.getFormattedValue(zobj, rawValue, showChanges);
|
||||
requestValue=not isSearch and zobj.getRequestFieldValue(name);
|
||||
inRequest=field.valueIsInRequest(req, name);
|
||||
inRequest=field.valueIsInRequest(zobj, req, name);
|
||||
error=req.get('%s_error' % name);
|
||||
isMultiple=(field.multiplicity[1] == None) or \
|
||||
(field.multiplicity[1] > 1);
|
||||
|
@ -360,7 +360,7 @@ class Field:
|
|||
else:
|
||||
master, masterValue = masterData
|
||||
if masterValue and callable(masterValue): return True
|
||||
reqValue = master.getRequestValue(obj.REQUEST)
|
||||
reqValue = master.getRequestValue(obj)
|
||||
# reqValue can be a list or not
|
||||
if type(reqValue) not in sutils.sequenceTypes:
|
||||
return reqValue in masterValue
|
||||
|
@ -517,7 +517,7 @@ class Field:
|
|||
def getValue(self, obj):
|
||||
'''Gets, on_obj, the value conforming to self's type definition.'''
|
||||
value = getattr(obj.aq_base, self.name, None)
|
||||
if self.isEmptyValue(value):
|
||||
if self.isEmptyValue(obj, value):
|
||||
# If there is no value, get the default value if any: return
|
||||
# self.default, of self.default() if it is a method.
|
||||
if callable(self.default):
|
||||
|
@ -539,7 +539,7 @@ class Field:
|
|||
purposes. Needs to be overridden by some child classes. If
|
||||
p_showChanges is True, the result must also include the changes that
|
||||
occurred on p_value across the ages.'''
|
||||
if self.isEmptyValue(value): return ''
|
||||
if self.isEmptyValue(obj, value): return ''
|
||||
return value
|
||||
|
||||
def getIndexType(self):
|
||||
|
@ -573,7 +573,7 @@ class Field:
|
|||
res = str(res)
|
||||
return res
|
||||
|
||||
def valueIsInRequest(self, request, name):
|
||||
def valueIsInRequest(self, obj, request, name):
|
||||
'''Is there a value corresponding to this field in the request? p_name
|
||||
can be different from self.name (ie, if it is a field within another
|
||||
(List) field). In most cases, checking that this p_name is in the
|
||||
|
@ -581,7 +581,7 @@ class Field:
|
|||
for string multilingual fields.'''
|
||||
return request.has_key(name)
|
||||
|
||||
def getRequestValue(self, request, requestName=None):
|
||||
def getRequestValue(self, obj, requestName=None):
|
||||
'''Gets a value for this field as carried in the request object. In the
|
||||
simplest cases, the request value is a single value whose name in the
|
||||
request is the name of the field.
|
||||
|
@ -595,15 +595,15 @@ class Field:
|
|||
the container field). In this case, p_requestName must be used for
|
||||
searching into the request, instead of the field name (self.name).'''
|
||||
name = requestName or self.name
|
||||
return request.get(name, None)
|
||||
return obj.REQUEST.get(name, None)
|
||||
|
||||
def getStorableValue(self, value):
|
||||
def getStorableValue(self, obj, value):
|
||||
'''p_value is a valid value initially computed through calling
|
||||
m_getRequestValue. So, it is a valid string (or list of strings)
|
||||
representation of the field value coming from the request.
|
||||
This method computes the real (potentially converted or manipulated
|
||||
in some other way) value as can be stored in the database.'''
|
||||
if self.isEmptyValue(value): return
|
||||
if self.isEmptyValue(obj, value): return
|
||||
return value
|
||||
|
||||
def getMasterData(self):
|
||||
|
@ -634,11 +634,11 @@ class Field:
|
|||
return 'updateSlaves(this,null,%s,%s,null,null%s)' % \
|
||||
(q(zobj.absolute_url()), q(layoutType), cName)
|
||||
|
||||
def isEmptyValue(self, value, obj=None):
|
||||
def isEmptyValue(self, obj, value):
|
||||
'''Returns True if the p_value must be considered as an empty value.'''
|
||||
return value in self.nullValues
|
||||
|
||||
def isCompleteValue(self, value, obj=None):
|
||||
def isCompleteValue(self, obj, value):
|
||||
'''Returns True if the p_value must be considered as "complete". While,
|
||||
in most cases, a "complete" value simply means a "non empty" value
|
||||
(see m_isEmptyValue above), in some special cases it is more subtle.
|
||||
|
@ -648,7 +648,7 @@ class Field:
|
|||
a Date with the "hour" part required will not be considered as empty
|
||||
if the "day, month, year" part is present but will not be considered
|
||||
as complete without the "hour, minute" part.'''
|
||||
return not self.isEmptyValue(value, obj)
|
||||
return not self.isEmptyValue(obj, value)
|
||||
|
||||
def validateValue(self, obj, value):
|
||||
'''This method may be overridden by child classes and will be called at
|
||||
|
@ -673,7 +673,7 @@ class Field:
|
|||
definition. If it is the case, None is returned. Else, a translated
|
||||
error message is returned.'''
|
||||
# If the value is required, check that a (complete) value is present.
|
||||
if not self.isCompleteValue(value, obj):
|
||||
if not self.isCompleteValue(obj, value):
|
||||
if self.required and self.isClientVisible(obj):
|
||||
# If the field is required, but not visible according to
|
||||
# master/slave relationships, we consider it not to be required.
|
||||
|
@ -686,7 +686,7 @@ class Field:
|
|||
message = self.validateValue(obj, value)
|
||||
if message: return message
|
||||
# Evaluate the custom validator if one has been specified
|
||||
value = self.getStorableValue(value)
|
||||
value = self.getStorableValue(obj, value)
|
||||
if self.validator and (type(self.validator) in self.validatorTypes):
|
||||
obj = obj.appy()
|
||||
if type(self.validator) != self.validatorTypes[-1]:
|
||||
|
|
|
@ -117,8 +117,8 @@ class Boolean(Field):
|
|||
def getFormattedValue(self, obj, value, showChanges=False):
|
||||
return obj.translate(self.getValueLabel(value))
|
||||
|
||||
def getStorableValue(self, value):
|
||||
if not self.isEmptyValue(value):
|
||||
def getStorableValue(self, obj, value):
|
||||
if not self.isEmptyValue(obj, value):
|
||||
exec 'res = %s' % value
|
||||
return res
|
||||
|
||||
|
|
|
@ -207,7 +207,7 @@ class Date(Field):
|
|||
return obj.translate('bad_date')
|
||||
|
||||
def getFormattedValue(self, obj, value, showChanges=False):
|
||||
if self.isEmptyValue(value): return ''
|
||||
if self.isEmptyValue(obj, value): return ''
|
||||
tool = obj.getTool().appy()
|
||||
# A problem may occur with some extreme year values. Replace the "year"
|
||||
# part "by hand".
|
||||
|
@ -219,7 +219,8 @@ class Date(Field):
|
|||
res += ' %s' % value.strftime(tool.hourFormat)
|
||||
return res
|
||||
|
||||
def getRequestValue(self, request, requestName=None):
|
||||
def getRequestValue(self, obj, requestName=None):
|
||||
request = obj.REQUEST
|
||||
name = requestName or self.name
|
||||
# Manage the "date" part
|
||||
value = ''
|
||||
|
@ -238,8 +239,8 @@ class Date(Field):
|
|||
value = value[:-1]
|
||||
return value
|
||||
|
||||
def getStorableValue(self, value):
|
||||
if not self.isEmptyValue(value):
|
||||
def getStorableValue(self, obj, value):
|
||||
if not self.isEmptyValue(obj, value):
|
||||
import DateTime
|
||||
return DateTime.DateTime(value)
|
||||
|
||||
|
|
|
@ -327,16 +327,15 @@ class File(Field):
|
|||
historized, mapping, label, sdefault, scolspan, swidth,
|
||||
sheight, True)
|
||||
|
||||
def getRequestValue(self, request, requestName=None):
|
||||
def getRequestValue(self, obj, requestName=None):
|
||||
name = requestName or self.name
|
||||
return request.get('%s_file' % name)
|
||||
return obj.REQUEST.get('%s_file' % name)
|
||||
|
||||
def getDefaultLayouts(self): return {'view':'l-f','edit':'lrv-f'}
|
||||
|
||||
def isEmptyValue(self, value, obj=None):
|
||||
def isEmptyValue(self, obj, value):
|
||||
'''Must p_value be considered as empty?'''
|
||||
if not obj: return Field.isEmptyValue(self, value)
|
||||
if value: return False
|
||||
if value: return
|
||||
# If "nochange", the value must not be considered as empty
|
||||
return obj.REQUEST.get('%s_delete' % self.name) != 'nochange'
|
||||
|
||||
|
|
|
@ -94,8 +94,8 @@ class Float(Field):
|
|||
except ValueError:
|
||||
return obj.translate('bad_%s' % self.pythonType.__name__)
|
||||
|
||||
def getStorableValue(self, value):
|
||||
if not self.isEmptyValue(value):
|
||||
def getStorableValue(self, obj, value):
|
||||
if not self.isEmptyValue(obj, value):
|
||||
for sep in self.sep: value = value.replace(sep, '.')
|
||||
value = value.replace(self.tsep, '')
|
||||
return self.pythonType(value)
|
||||
|
|
|
@ -68,10 +68,10 @@ class Integer(Field):
|
|||
except ValueError:
|
||||
return obj.translate('bad_%s' % self.pythonType.__name__)
|
||||
|
||||
def getStorableValue(self, value):
|
||||
if not self.isEmptyValue(value): return self.pythonType(value)
|
||||
def getStorableValue(self, obj, value):
|
||||
if not self.isEmptyValue(obj, value): return self.pythonType(value)
|
||||
|
||||
def getFormattedValue(self, obj, value, showChanges=False):
|
||||
if self.isEmptyValue(value): return ''
|
||||
if self.isEmptyValue(obj, value): return ''
|
||||
return str(value)
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
@ -119,8 +119,9 @@ class List(Field):
|
|||
res.append(elem)
|
||||
return res
|
||||
|
||||
def getRequestValue(self, request, requestName=None):
|
||||
def getRequestValue(self, obj, requestName=None):
|
||||
'''Concatenates the list from distinct form elements in the request.'''
|
||||
request = obj.REQUEST
|
||||
name = requestName or self.name # A List may be into another List (?)
|
||||
prefix = name + '*' + self.fields[0][0] + '*'
|
||||
res = {}
|
||||
|
@ -133,7 +134,7 @@ class List(Field):
|
|||
if rowIndex == -1: continue # Ignore the template row.
|
||||
for subName, subField in self.fields:
|
||||
keyName = '%s*%s*%s' % (name, subName, rowIndex)
|
||||
v = subField.getRequestValue(request, requestName=keyName)
|
||||
v = subField.getRequestValue(obj, requestName=keyName)
|
||||
setattr(row, subName, v)
|
||||
res[rowIndex] = row
|
||||
# Produce a sorted list.
|
||||
|
@ -148,7 +149,7 @@ class List(Field):
|
|||
request.set(name, res)
|
||||
return res
|
||||
|
||||
def getStorableValue(self, value):
|
||||
def getStorableValue(self, obj, value):
|
||||
'''Gets p_value in a form that can be stored in the database.'''
|
||||
res = []
|
||||
for v in value:
|
||||
|
@ -156,11 +157,11 @@ class List(Field):
|
|||
for name, field in self.fields:
|
||||
subValue = getattr(v, name)
|
||||
try:
|
||||
setattr(sv, name, field.getStorableValue(subValue))
|
||||
setattr(sv, name, field.getStorableValue(obj, subValue))
|
||||
except ValueError:
|
||||
# The value for this field for this specific row is
|
||||
# incorrect. It can happen in the process of validating the
|
||||
# whole List field (a call to getStorableValue occurs at
|
||||
# whole List field (a call to m_getStorableValue occurs at
|
||||
# this time). We don't care about it, because later on we
|
||||
# will have sub-field specific validation that will also
|
||||
# detect the error and will prevent storing the wrong value
|
||||
|
|
|
@ -295,7 +295,7 @@ class Pod(Field):
|
|||
tool = obj.tool
|
||||
diskFolder = tool.getDiskFolder()
|
||||
# Get the path to the pod template.
|
||||
templatePath = os.path.join(diskFolder, template)
|
||||
templatePath = sutils.resolvePath(os.path.join(diskFolder, template))
|
||||
if not os.path.isfile(templatePath):
|
||||
raise Exception(self.TEMPLATE_NOT_FOUND % templatePath)
|
||||
# Get or compute the specific POD context
|
||||
|
|
|
@ -130,8 +130,8 @@ class String(Field):
|
|||
pxMultilingual = Px('''
|
||||
<!-- Horizontally-layouted multilingual field -->
|
||||
<table if="mLayout == 'horizontal'" width="100%"
|
||||
var="count=len(field.languages)">
|
||||
<tr valign="top"><x for="lg in field.languages"><x>:field.pxLanguage</x>
|
||||
var="count=len(languages)">
|
||||
<tr valign="top"><x for="lg in languages"><x>:field.pxLanguage</x>
|
||||
<td width=":'%d%%' % int(100.0/count)"
|
||||
var="requestValue=requestValue[lg]|None;
|
||||
value=value[lg]|emptyDefault">:field.subPx[layoutType][fmt]</td>
|
||||
|
@ -139,7 +139,7 @@ class String(Field):
|
|||
|
||||
<!-- Vertically-layouted multilingual field -->
|
||||
<table if="mLayout == 'vertical'">
|
||||
<tr valign="top" height="20px" for="lg in field.languages">
|
||||
<tr valign="top" height="20px" for="lg in languages">
|
||||
<x>:field.pxLanguage</x>
|
||||
<td var="requestValue=requestValue[lg]|None;
|
||||
value=value[lg]|emptyDefault">:field.subPx[layoutType][fmt]</td>
|
||||
|
@ -147,7 +147,8 @@ class String(Field):
|
|||
|
||||
pxView = Px('''
|
||||
<x var="fmt=field.format; isUrl=field.isUrl;
|
||||
multilingual=field.isMultilingual();
|
||||
languages=field.getAttribute(zobj, 'languages');
|
||||
multilingual=len(languages) > 1;
|
||||
mLayout=multilingual and field.getLanguagesLayout('view');
|
||||
mayAjaxEdit=not showChanges and field.inlineEdit and \
|
||||
zobj.mayEdit(field.writePermission)">
|
||||
|
@ -193,7 +194,8 @@ class String(Field):
|
|||
|
||||
pxEdit = Px('''
|
||||
<x var="fmt=field.format;
|
||||
multilingual=field.isMultilingual();
|
||||
languages=field.getAttribute(zobj, 'languages');
|
||||
multilingual=len(languages) > 1;
|
||||
mLayout=multilingual and field.getLanguagesLayout('edit')">
|
||||
<select if="field.isSelect"
|
||||
var2="possibleValues=field.getPossibleValues(zobj, \
|
||||
|
@ -447,7 +449,7 @@ class String(Field):
|
|||
def checkParameters(self):
|
||||
'''Ensures this String is correctly defined.'''
|
||||
error = None
|
||||
if self.isMultilingual():
|
||||
if self.isMultilingual(None):
|
||||
if self.isSelect:
|
||||
error = "A selection field can't be multilingual."
|
||||
elif self.format in (String.PASSWORD, String.CAPTCHA):
|
||||
|
@ -468,7 +470,11 @@ class String(Field):
|
|||
res = False
|
||||
return res
|
||||
|
||||
def isMultilingual(self): return len(self.languages) > 1
|
||||
def isMultilingual(self, obj):
|
||||
'''Is this field multilingual ?.'''
|
||||
# In the following case, impossible to know: we say no.
|
||||
if not obj and callable(self.languages): return
|
||||
return len(self.getAttribute(obj, 'languages')) > 1
|
||||
|
||||
def getDefaultLayouts(self):
|
||||
'''Returns the default layouts for this type. Default layouts can vary
|
||||
|
@ -507,45 +513,50 @@ class String(Field):
|
|||
value = list(value)
|
||||
return value
|
||||
|
||||
def valueIsInRequest(self, request, name):
|
||||
if not self.isMultilingual():
|
||||
return Field.valueIsInRequest(self, request, name)
|
||||
return request.has_key('%s_%s' % (name, self.languages[0]))
|
||||
def valueIsInRequest(self, obj, request, name):
|
||||
languages = self.getAttribute(obj, 'languages')
|
||||
if len(languages) == 1:
|
||||
return Field.valueIsInRequest(self, obj, request, name)
|
||||
# Is is sufficient to check that at least one of the language-specific
|
||||
# values is in the request.
|
||||
return request.has_key('%s_%s' % (name, languages[0]))
|
||||
|
||||
def getRequestValue(self, request, requestName=None):
|
||||
def getRequestValue(self, obj, requestName=None):
|
||||
'''The request value may be multilingual.'''
|
||||
request = obj.REQUEST
|
||||
name = requestName or self.name
|
||||
languages = self.getAttribute(obj, 'languages')
|
||||
# A unilingual field.
|
||||
if not self.isMultilingual(): return request.get(name, None)
|
||||
if len(languages) == 1: return request.get(name, None)
|
||||
# A multilingual field.
|
||||
res = {}
|
||||
for language in self.languages:
|
||||
for language in languages:
|
||||
res[language] = request.get('%s_%s' % (name, language), None)
|
||||
return res
|
||||
|
||||
def isEmptyValue(self, value, obj=None):
|
||||
def isEmptyValue(self, obj, value):
|
||||
'''Returns True if the p_value must be considered as an empty value.'''
|
||||
if not self.isMultilingual():
|
||||
return Field.isEmptyValue(self, value, obj)
|
||||
if not self.isMultilingual(obj):
|
||||
return Field.isEmptyValue(self, obj, value)
|
||||
# For a multilingual value, as soon as a value is not empty for a given
|
||||
# language, the whole value is considered as not being empty.
|
||||
if not value: return True
|
||||
for v in value.itervalues():
|
||||
if not Field.isEmptyValue(self, v, obj): return
|
||||
if not Field.isEmptyValue(self, obj, v): return
|
||||
return True
|
||||
|
||||
def isCompleteValue(self, value, obj=None):
|
||||
def isCompleteValue(self, obj, value):
|
||||
'''Returns True if the p_value must be considered as complete. For a
|
||||
unilingual field, being complete simply means not being empty. For a
|
||||
multilingual field, being complete means that a value is present for
|
||||
every language'''
|
||||
if not self.isMultilingual():
|
||||
return Field.isCompleteValue(self, value, obj)
|
||||
every language.'''
|
||||
if not self.isMultilingual(obj):
|
||||
return Field.isCompleteValue(self, obj, value)
|
||||
# As soon as a given language value is empty, the global value is not
|
||||
# complete.
|
||||
if not value: return True
|
||||
for v in value.itervalues():
|
||||
if Field.isEmptyValue(self, v, obj): return
|
||||
if Field.isEmptyValue(self, obj, v): return
|
||||
return True
|
||||
|
||||
def getDiffValue(self, obj, value, language):
|
||||
|
@ -581,7 +592,7 @@ class String(Field):
|
|||
m_getFormattedValue for getting a non-multilingual value (ie, in
|
||||
most cases). Else, this method returns a formatted value for the
|
||||
p_language-specific part of a multilingual value.'''
|
||||
if Field.isEmptyValue(self, value): return ''
|
||||
if Field.isEmptyValue(self, obj, value): return ''
|
||||
res = value
|
||||
if self.isSelect:
|
||||
if isinstance(self.validator, Selection):
|
||||
|
@ -609,13 +620,14 @@ class String(Field):
|
|||
return res
|
||||
|
||||
def getFormattedValue(self, obj, value, showChanges=False):
|
||||
if not self.isMultilingual():
|
||||
languages = self.getAttribute(obj, 'languages')
|
||||
if len(languages) == 1:
|
||||
return self.getUnilingualFormattedValue(obj, value, showChanges)
|
||||
# Return the dict of values whose individual, language-specific values
|
||||
# have been formatted via m_getUnilingualFormattedValue.
|
||||
if not value: return value
|
||||
res = {}
|
||||
for lg in self.languages:
|
||||
for lg in languages:
|
||||
res[lg] = self.getUnilingualFormattedValue(obj, value[lg],
|
||||
showChanges, lg)
|
||||
return res
|
||||
|
@ -631,7 +643,7 @@ class String(Field):
|
|||
'''Pure text must be extracted from rich content; multilingual content
|
||||
must be concatenated.'''
|
||||
isXhtml = self.format == String.XHTML
|
||||
if self.isMultilingual():
|
||||
if self.isMultilingual(obj):
|
||||
res = self.getValue(obj)
|
||||
if res:
|
||||
vals = []
|
||||
|
@ -775,9 +787,9 @@ class String(Field):
|
|||
elif self.transform == 'capitalize': return value.capitalize()
|
||||
return value
|
||||
|
||||
def getUnilingualStorableValue(self, value):
|
||||
def getUnilingualStorableValue(self, obj, value):
|
||||
isString = isinstance(value, basestring)
|
||||
isEmpty = Field.isEmptyValue(self, value)
|
||||
isEmpty = Field.isEmptyValue(self, obj, value)
|
||||
# Apply transform if required
|
||||
if isString and not isEmpty and (self.transform != 'none'):
|
||||
value = self.applyTransform(value)
|
||||
|
@ -804,21 +816,23 @@ class String(Field):
|
|||
value = [value]
|
||||
return value
|
||||
|
||||
def getStorableValue(self, value):
|
||||
if not self.isMultilingual():
|
||||
return self.getUnilingualStorableValue(value)
|
||||
def getStorableValue(self, obj, value):
|
||||
languages = self.getAttribute(obj, 'languages')
|
||||
if len(languages) == 1:
|
||||
return self.getUnilingualStorableValue(obj, value)
|
||||
# A multilingual value is stored as a dict whose keys are ISO 2-letters
|
||||
# language codes and whose values are strings storing content in the
|
||||
# language ~{s_language: s_content}~.
|
||||
if not value: return
|
||||
for lg in self.languages:
|
||||
value[lg] = self.getUnilingualStorableValue(value[lg])
|
||||
for lg in languages:
|
||||
value[lg] = self.getUnilingualStorableValue(obj, value[lg])
|
||||
return value
|
||||
|
||||
def store(self, obj, value):
|
||||
'''Stores p_value on p_obj for this field.'''
|
||||
if self.isMultilingual() and value and \
|
||||
(not isinstance(value, dict) or (len(value) != len(self.languages))):
|
||||
languages = self.getAttribute(obj, 'languages')
|
||||
if (len(languages) > 1) and value and \
|
||||
(not isinstance(value, dict) or (len(value) != len(languages))):
|
||||
raise Exception('Multilingual field "%s" accepts a dict whose '\
|
||||
'keys are in field.languages and whose ' \
|
||||
'values are strings.' % self.name)
|
||||
|
@ -832,16 +846,16 @@ class String(Field):
|
|||
requestValue = rq['fieldContent']
|
||||
# Remember previous value if the field is historized.
|
||||
previousData = obj.rememberPreviousData([self])
|
||||
if self.isMultilingual():
|
||||
if self.isMultilingual(obj):
|
||||
# We take a copy of previousData because it is mutable (dict).
|
||||
previousData[self.name] = previousData[self.name].copy()
|
||||
# We get a partial value, for one language only.
|
||||
language = rq['languageOnly']
|
||||
v = self.getUnilingualStorableValue(requestValue)
|
||||
v = self.getUnilingualStorableValue(obj, requestValue)
|
||||
getattr(obj.aq_base, self.name)[language] = v
|
||||
part = ' (%s)' % language
|
||||
else:
|
||||
self.store(obj, self.getStorableValue(requestValue))
|
||||
self.store(obj, self.getStorableValue(obj, requestValue))
|
||||
part = ''
|
||||
# Update the object history when relevant
|
||||
if previousData: obj.historizeData(previousData)
|
||||
|
@ -892,11 +906,12 @@ class String(Field):
|
|||
'fi': 'fi_FI', 'fr': 'fr_FR', 'de': 'de_DE', 'el': 'el_GR',
|
||||
'it': 'it_IT', 'nb': 'nb_NO', 'pt': 'pt_PT', 'es': 'es_ES',
|
||||
'sv': 'sv_SE'}
|
||||
def getCkLanguage(self, language):
|
||||
def getCkLanguage(self, obj, language):
|
||||
'''Gets the language for CK editor SCAYT. p_language is one of
|
||||
self.languages if the field is multilingual, None else. If p_language
|
||||
is not supported by CK, we use english.'''
|
||||
if not language: language = self.languages[0]
|
||||
if not language:
|
||||
language = self.getAttribute(obj, 'languages')[0]
|
||||
if language in self.ckLanguages: return self.ckLanguages[language]
|
||||
return 'en_US'
|
||||
|
||||
|
@ -904,7 +919,7 @@ class String(Field):
|
|||
'''Gets the base params to set on a rich text field.'''
|
||||
ckAttrs = {'toolbar': 'Appy',
|
||||
'format_tags': ';'.join(self.styles),
|
||||
'scayt_sLang': self.getCkLanguage(language)}
|
||||
'scayt_sLang': self.getCkLanguage(obj, language)}
|
||||
if self.width: ckAttrs['width'] = self.width
|
||||
if self.spellcheck: ckAttrs['scayt_autoStartup'] = True
|
||||
if self.allowImageUpload:
|
||||
|
|
|
@ -1246,12 +1246,27 @@ class ToolMixin(BaseMixin):
|
|||
return [f for f in self.getAllAppyTypes(contentType) \
|
||||
if (f.type == 'Pod') and (f.show == 'result')]
|
||||
|
||||
def formatDate(self, date, withHour=True):
|
||||
'''Returns p_date formatted as specified by tool.dateFormat.
|
||||
If p_withHour is True, hour is appended, with a format specified
|
||||
in tool.hourFormat.'''
|
||||
def formatDate(self, date, format=None, withHour=True, language=None):
|
||||
'''Returns p_date formatted as specified by p_format, or tool.dateFormat
|
||||
if not specified. If p_withHour is True, hour is appended, with a
|
||||
format specified in tool.hourFormat.'''
|
||||
tool = self.appy()
|
||||
res = date.strftime(tool.dateFormat)
|
||||
fmt = format or tool.dateFormat
|
||||
# Resolve appy-specific formatting symbols used for getting translated
|
||||
# names of days or months:
|
||||
# - %dt: translated name of day
|
||||
# - %DT: translated name of day, capitalized
|
||||
# - %mt: translated name of month
|
||||
# - %MT: translated name of month, capitalized
|
||||
if ('%dt' in fmt) or ('%DT' in fmt):
|
||||
day = self.translate('day_%s' % date._aday, language=language)
|
||||
fmt = fmt.replace('%dt', day.lower()).replace('%DT', day)
|
||||
if ('%mt' in fmt) or ('%MT' in fmt):
|
||||
month = self.translate('month_%s' % date._amon, language=language)
|
||||
fmt = fmt.replace('%mt', month.lower()).replace('%MT', month)
|
||||
# Resolve all other, standard, symbols
|
||||
res = date.strftime(fmt)
|
||||
# Append hour from tool.hourFormat
|
||||
if withHour: res += ' (%s)' % date.strftime(tool.hourFormat)
|
||||
return res
|
||||
|
||||
|
|
|
@ -337,12 +337,12 @@ class BaseMixin:
|
|||
rq = self.REQUEST
|
||||
for field in self.getAppyTypes('edit', rq.form.get('page')):
|
||||
if not field.validable or not field.isClientVisible(self): continue
|
||||
value = field.getRequestValue(rq)
|
||||
value = field.getRequestValue(self)
|
||||
message = field.validate(self, value)
|
||||
if message:
|
||||
setattr(errors, field.name, message)
|
||||
else:
|
||||
setattr(values, field.name, field.getStorableValue(value))
|
||||
setattr(values, field.name, field.getStorableValue(self, value))
|
||||
# Validate sub-fields within Lists
|
||||
if field.type != 'List': continue
|
||||
i = -1
|
||||
|
@ -634,7 +634,7 @@ class BaseMixin:
|
|||
if lg:
|
||||
isEmpty = not changes[name] or not changes[name].get(lg)
|
||||
else:
|
||||
isEmpty = field.isEmptyValue(changes[name], self)
|
||||
isEmpty = field.isEmptyValue(self, changes[name])
|
||||
if isEmpty:
|
||||
del changes[name]
|
||||
else:
|
||||
|
@ -664,10 +664,13 @@ class BaseMixin:
|
|||
# In some cases the old value must be formatted.
|
||||
if field.type == 'Ref':
|
||||
previousData[name] = [r.title for r in previousData[name]]
|
||||
elif (field.type == 'String') and field.isMultilingual():
|
||||
# Consider every language-specific value as a first-class value
|
||||
elif field.type == 'String':
|
||||
languages = field.getAttribute(self, 'languages')
|
||||
if len(languages) > 1:
|
||||
# Consider every language-specific value as a first-class
|
||||
# value.
|
||||
del previousData[name]
|
||||
for lg in field.languages:
|
||||
for lg in languages:
|
||||
lgPrev = prev and prev.get(lg) or None
|
||||
lgCurr = curr and curr.get(lg) or None
|
||||
if lgPrev == lgCurr: continue
|
||||
|
@ -714,7 +717,7 @@ class BaseMixin:
|
|||
'''Gets the value of field p_name as may be present in the request.'''
|
||||
# Return the request value for standard fields.
|
||||
if '*' not in name:
|
||||
return self.getAppyType(name).getRequestValue(self.REQUEST)
|
||||
return self.getAppyType(name).getRequestValue(self)
|
||||
# For sub-fields within Lists, the corresponding request values have
|
||||
# already been computed in the request key corresponding to the whole
|
||||
# List.
|
||||
|
@ -1083,7 +1086,11 @@ class BaseMixin:
|
|||
return True
|
||||
else:
|
||||
field = self.getAppyType(name)
|
||||
multilingual = (field.type == 'String') and field.isMultilingual()
|
||||
# Is this field a multilingual field ?
|
||||
languages = None
|
||||
if field.type == 'String':
|
||||
languages = field.getAttribute(self, 'languages')
|
||||
multilingual = len(languages) > 1
|
||||
for event in history:
|
||||
if event['action'] != '_datachange_': continue
|
||||
# Is there a value present for this field in this data change?
|
||||
|
@ -1093,7 +1100,7 @@ class BaseMixin:
|
|||
return True
|
||||
else:
|
||||
# At least one language-specific value must be present
|
||||
for lg in field.languages:
|
||||
for lg in languages:
|
||||
lgName = '%s-%s' % (field.name, lg)
|
||||
if (lgName in event['changes']) and \
|
||||
event['changes'][lgName][0]:
|
||||
|
@ -1142,7 +1149,7 @@ class BaseMixin:
|
|||
# previous value, we propose a diff with the next
|
||||
# version, excepted if the previous value is empty.
|
||||
if lg: isEmpty = not oldValue[0]
|
||||
else: isEmpty = field.isEmptyValue(oldValue[0])
|
||||
else: isEmpty = field.isEmptyValue(self, oldValue[0])
|
||||
if isEmpty:
|
||||
val = '-'
|
||||
else:
|
||||
|
|
|
@ -627,15 +627,6 @@ class ToolWrapper(AbstractWrapper):
|
|||
(user.o.absolute_url(), user.title,access))
|
||||
return res + '\n'.join(rows) + '</table>'
|
||||
|
||||
def getInitiator(self, field=False):
|
||||
'''Retrieves the object that triggered the creation of the object
|
||||
being currently created (if any), or the name of the field in this
|
||||
object if p_field is given.'''
|
||||
nav = self.o.REQUEST.get('nav', '')
|
||||
if not nav or not nav.startswith('ref.'): return
|
||||
if not field: return self.getObject(nav.split('.')[1])
|
||||
return nav.split('.')[2].split(':')[0]
|
||||
|
||||
def getObject(self, uid):
|
||||
'''Allow to retrieve an object from its unique identifier p_uid.'''
|
||||
return self.o.getObject(uid, appy=True)
|
||||
|
@ -666,10 +657,10 @@ class ToolWrapper(AbstractWrapper):
|
|||
'''Sends a mail. See doc for appy.gen.mail.sendMail.'''
|
||||
sendMail(self, to, subject, body, attachments=attachments)
|
||||
|
||||
def formatDate(self, date, withHour=True):
|
||||
def formatDate(self, date, format=None, withHour=True, language=None):
|
||||
'''Check doc @ToolMixin::formatDate.'''
|
||||
if not date: return
|
||||
return self.o.formatDate(date, withHour=withHour)
|
||||
return self.o.formatDate(date, format, withHour, language)
|
||||
|
||||
def getUserName(self, login=None, normalized=False):
|
||||
return self.o.getUserName(login=login, normalized=normalized)
|
||||
|
|
|
@ -43,10 +43,11 @@ class TranslationWrapper(AbstractWrapper):
|
|||
if field.type == 'Computed': name = field.name[:-6]
|
||||
else: name = field.name
|
||||
# Get the source message
|
||||
sourceLanguage = self.o.getProductConfig(True).sourceLanguage
|
||||
obj = self.o
|
||||
sourceLanguage = obj.getProductConfig(True).sourceLanguage
|
||||
sourceTranslation = getattr(tool.o, sourceLanguage).appy()
|
||||
sourceMsg = getattr(sourceTranslation, name)
|
||||
if field.isEmptyValue(sourceMsg): return False
|
||||
if field.isEmptyValue(obj, sourceMsg): return
|
||||
return True
|
||||
|
||||
poReplacements = ( ('\r\n', '<br/>'), ('\n', '<br/>'), ('"', '\\"') )
|
||||
|
|
|
@ -788,7 +788,7 @@ class AbstractWrapper(object):
|
|||
obj = self.o
|
||||
if hasattr(obj.aq_base, name):
|
||||
field = obj.getAppyType(name)
|
||||
return field.isEmptyValue(getattr(obj, name))
|
||||
return field.isEmptyValue(obj, getattr(obj, name))
|
||||
return True
|
||||
|
||||
def isTemp(self):
|
||||
|
|
|
@ -72,6 +72,17 @@ def cleanFolder(folder, exts=extsToClean, folders=(), verbose=False):
|
|||
if verbose: print('Removing folder %s...' % toDelete)
|
||||
FolderDeleter.delete(toDelete)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
def resolvePath(path):
|
||||
'''p_path is a file path that can contain occurences of "." and "..". This
|
||||
function resolves them and procuces a minimal path.'''
|
||||
res = []
|
||||
for elem in path.split(os.sep):
|
||||
if elem == '.': pass
|
||||
elif elem == '..': res.pop()
|
||||
else: res.append(elem)
|
||||
return os.sep.join(res)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
def copyFolder(source, dest, cleanDest=False):
|
||||
'''Copies the content of folder p_source to folder p_dest. p_dest is
|
||||
|
|
Loading…
Reference in a new issue