Fetches an object that was persisted with persist()
Class Details
[line 63]
Abstract Form Field Class
basic implementation of an html form field. is never instanced alone, only extended by one of the classes in the directories: core/html/form/ core/html/form/specialfields core/html/form/domapi
all the given validating rules may not be enough for you. you need something handmade.
you can use this var for a peace of php code. it'll be evaluated. not language dependant, fork it in your code if needed.
if there's an error in your code, it will be treated as "check was ok". your code should return bool(true), which means check succeeded. or a string or array to indicate that it failed, thus the input won't be accepted. your return value then is the error message that'll be shown to the user. it can be a string, or a hash if you want to offer it in different languages. key=language, value=message.
'$v' and special case with explodable fields: to access the value in your code you could do it by using $this->valueInternal. but it could be an explodable field, which means valueInternal can be an array. if so, $this->validateAdditionalCheck() (which does the check) is called for each entry of the array. otherwise it is just called once. to have the right value (the one of the current array element) you always have 2 vars in your scope: $v (the value) and $vLength (the string length of $v). i don't mind if you access $this->valueInternal directly to do something with the whole array, but keep in mind that the method is called once for each element. hope you got that.
example I:
$additionalCheck = "
if ($v != 'foobar') {
return $this->errorMessage = array(
'en' => 'Input must be foobar.',
'de' => 'Eingabe muss foobar sein.'
);
} else {
return TRUE;
}
";
example II:
$additionalCheck = "
if (($this->hasFormObject()) && (isSet($this->_form->language))) {
$lang = $this->_form->language;
} else {
$lang = 'en'; //fallback
}
switch ($lang) {
case 'de':
if ($v != 'hallo welt') return $this->errorMessage = 'Irgend ein Fehler';
break;
default: //also case 'en'
if ($v != 'hello world') return $this->errorMessage = 'Some Error';
}
return TRUE;
";
NOTE: be sure to escape the $ vars when assigning code to a var, otherwise it will
be evaluated right away.
Tags:
var:
some php code.
todo:
add security stuff because of the eval.
see:
$this->_evalWrap(), var $codePostLoad, $this->validateAdditionalCheck()
CAUTION: you really can fuck up things here. be warned. these 2 example values are no good: value='tom's pizzaland' maxlength='15' value="my nickname is "tom" -> cool heh?" checked in the 1st example, the problem is the ' in the 2nd example, the problems are the " and the > you have to convert such characters first. please see/use Html/Bs_HtmlUtil.class.php->filterForHtml().
note I: it's *not* an associative array where you do key=value. note II: in the gui implementation, only the string version is supported (no vector).
some datatypes may be modified in some standard way. this depends on $bsDataType.
the manipulations are not visible to the user, which means $valueInternal is changed while $valueDisplay is not.
number =>
text =>
html => idea: tagsToUpper/tagsToLower
email =>
url =>
password =>
price => int: 1 = work around floating point
eg user submits "135.15", we do *100 = "13515". when displaying we do
/ 100 so it is "135.15" again.
date => int: 1 = to us format (eg '2001/12/31'), 2 = to eu format (eg '31.12.2001')
month =>
year =>
datetime => int: 1 = to us format (eg '2001/12/31 24:59:59'),
2 = to eu format (eg '31.12.2001 24:59:59'),
3 = to mysql format (eg '2001-12-31 24:59:59'),
4 = to mysql timestamp (eg '20011231245959'),
5 = to unix timestamp,
6 = to gmt
7 = 1 + 6
8 = 2 + 6
9 = 3 + 6
10 = 4 + 6
11 = 5 + 6
sometimes $bsDataManipulation needs additional information to know how to manipulate the data. that's what this var is for.
example: we've got a datetime value, and we should convert it to gmt. but what's the difference between the value we've got and gmt? this var should tell...
if used, $bsDataManipVar must be a vector with exactly 2 elements. element 0 tells the value type, element 1 is the (mixed) value. $bsDataManipVar[0] = ['hard'|'eval']; $bsDataManipVar[1] = 'something';
upper make a string all uppercase.
eg 'Hello World' => 'HELLO WORLD'
ucwords make the first character of words upper case (if it's a letter).
eg 'hellO worlD' => 'HellO WorlD'
ucwordsonly same as ucwords, but make everything else lowercase.
eg 'hellO worlD' => 'Hello World'
ucfirst make the first character of the string upper case (if it's a letter).
eg 'hellO worlD' => 'HellO worlD'
ucfirstonly same as ucfirst, but make everything else lowercase.
eg 'hellO worlD' => 'Hello world'
nospam1 change strings to ucfirst if they are all upper case. replace any number of ! and ?
signs with just one.
eg 'HELLO! CLICK HERE FOR SEX PICTURES!!!' => 'Hello! click here for sex pictures!!!'
nospam2 nospam1 + replace any number of ! signs with just one dot '.'.
eg 'HELLO! CLICK HERE FOR SEX PICTURES!!!' => 'Hello click here for sex pictures'
</pre>
note: setting is ignored for the types select, radio and checkbox.
this code is evaluated after the received value has been manipulated (case, replace, remove ...).
the vars valueDisplay and valueInternal have been assigned. the validation things come later. the code is executed in $this->evalWrap() (so you can use $this-> stuff).
Tags:
var:
some php code
since:
bs4.3
todo:
add security stuff because of the eval.
see:
$this->postManipulateTrigger(), $this->evalWrap(), vars $codePostLoad and $codePostReceive
this code is evaluated right after the content has been received from the client.
the vars valueDisplay and valueInternal have not been assigned yet. the manipulation and validation things come later. the code is executed in $this->evalWrap() (so you can use $this-> stuff).
change: until bs4.2 this code has been executed AFTER the manipulations have been done. one could argue that it was correct, it was AFTER the data has been received, but it was even AFTER the manipulations. now there is the $codePostManipulate.
note that this will only be done for the fields that were meant and used in this level.
Tags:
var:
some php code
todo:
add security stuff because of the eval.
see:
$this->postReceiveTrigger(), $this->evalWrap(), vars $codePostLoad and $codePostManipulate
i suggest you don't set anything here. if you don't, the var $this->name will be used with a prefix (so we don't get in troubles because of reserved names).
you may set something here, then exactly this name will be used instead. consider using the same value as for $this->name.
if not set or not an array or empty then it's not a foreign key.
the hash has the following keys:
KEY DATATYPE COMMENTS
multiple bool if it's a 1:x or n:x relation.
dns array hash with the following keys (just as every dns hash):
'host'
'port'
'syntax'
'type'
'user'
'pass'
if anything is set here then a new db connection will be opened.
be aware of the fact that this data has to be stored along with the
form settings, and that isn't very secure. ...
db string if not set then it's the same.
table string
field string that should be the field 'ID' but can be different in some cases.
showAs string if multiple is TRUE: one of 'select' (default), 'radio', 'flipflop'.
if multiple is FALSE: one of 'select' (default), 'checkbox', 'flipflop'.
caption mixed the field that should be used to display on the page (eg in the select field).
usually the field 'caption'.
this setting may be language dependant, thus it can be a string or a lang-hash.
value mixed the field that should be used as key on the page (eg in the select field).
should be the field 'ID'.
this setting may be language dependant, thus it can be a string or a lang-hash.
rules: if this field ends with 'ID' (eg 'carID') then it's a x:1 relation. (x of this one have 1 car each) if this field ends with 'IDs' (eg 'carIDs') then it's a x:n relation. (x of this have n cars each)
the direction in which the text is written in that field, as in <input dir="ltr"> one of ltr (left to right) <= default rtl (right to left) ie5+ only. not set means ltr, which won't be written to the browser.
is the field editable (now)? also depends on the state we're in.
one of [never|once|always] never => never :) once => only in 'add' mode, not in 'edit', 'delete' and unknown mode. always => always :) (in 'add' AND 'edit' mode) if it's not set, it's treated as editable for this time.
hash holding bool values. if a key/value pair is not set, it means FALSE.
every validating class var can have an entry in this array. these are: must, mustIf, mustOneOf, mustOneOfIf, onlyOneOf, onlyIf, minLength, maxLength, mustStartWith notStartWith, mustEndWith, notEndWith, mustContain, notContain, equalTo notEqualTo, mustBeUnique, regularExpression, additionalCheck
example code: $myField->enforce = array('must'=>TRUE, 'minLength'=>TRUE);
example: the user is asked to type in an url. $bsDataType is 'url' and $bsDataInfo is '2'. now he types in his website, but unfortunately the host check fails because a) the server is currently down or b) the domain will be activated tomorrow or whatever. the user doesn't want to wait and come back when the problem is fixed, he wants to do it now, and you want to allow it. what you do is you set $enforce['bsDataInfo'] to true so when he submits, he'll get the form again with the error shown, but with a checkbox that says "enforce" to allow the user to ignore the error.
take care: imagine an input field with minLength=10 and notStartWith='hello'. now if the user types in 'hello' and he's allowed to enforce the minLength check, this *may not* skip the notStartWith check!
Tags:
todo:
enforce is the wrong name for this. change it to $overlook. update text. 2002/11/10 --andrej
the field input has to be equal to the field(s) specified here.
may be useful for 2 password fields, one to confirm. usually a string, may also be a vector array of strings.
note I: we only compare the data, not the datatype. (== not ===)
note II: this could cause some headache. imagine that this field
has to equal another value, but for some reason, the other
field was not sent (not editable, not visible to this user, ...).
now what? we are not able to compare... we're going with
the following: accept the value, and log this case.
it could be fixed when $visibility=omit would send the value
in an encrypted way. see var $visibility. (seems to be on the todo --andrej)
note III: setting is ignored for the types select, checkbox and radio. (seems to be on the todo --andrej)
note IV: if one of the fields is not a must field, then it is accepted that one field has an input
and the other stays empty. so they are not equal, and still accpeted.
may not be obvious, think about it.
- onFocus - onClick - onMouseOver - onKeyDown
- onBlur - onDblClick - onMouseMove - onKeyUp
- onSelect - onMouseDown - onMouseOut
- onChange - onMouseUp - onKeyPress
note: some field types do not support all events.
set the keys exactly like written above (case). otherwise we get in trouble when merging more events into one, and there may be bugs.
example: $events['onClick'] = "javascript:someFunction();"; will look like: <input onClick="javascript:someFunction();"> that means: if you want the word "javascript:" included, *you* have to add it yourself. because it could also be vbscript or whatever.
tells if the field is used in the form. will be set to true if the field value will be used on the server side, means if Bs_FormElement->visibility evaluates to 'normal', 'read' or 'invisible'. not if it's 'readonly' cause the value won't be used, and not if it's 'omit' of course. default is FALSE.
if the form tag supports it, it will be directly added like this: <input maxlength=$maxLength> it will be checked serverside anyway. someone could hack it.
if not set, it'll be something that makes sense based on $bsDataType:
number => 20 username => 20 domain => 80 datetime => 19
text => 255 password => 20 host => 80 timestamp => 8
blob => 65535 zipcode => 10 date => 10
html => 65535 price => 20 time => 8
email => 80 creditcard => 16 month => 2
url => 200 ip => 15 year => 4
there's room for more logic: if the value is made up based on $bsDataType (list above) and $dbDataType is set, the value should be no bigger than the db field types max length, eg char/varchar=255, int=11, blob=65535, ...
note I: for the field types 'checkbox' and 'radio' this setting is ignored. because the user cannot do anything about it. it's up to the webmaster not to do shit. note II: for the field type 'select' it's the number of max. selectable elements. if it doesn't have the 'multiple' property the setting is ignored.
the min length the field value needs to be. if it's not a $must field, a value shorter than $minLength is not accepted while an empty value is.
note I: for the field types 'checkbox' and 'radio' this setting is ignored. because the user cannot do anything about it. it's up to the webmaster not to do shit. note II: for the field type 'select' it's the number of min. selectable elements. if it doesn't have the 'multiple' property the setting is ignored.
tells whether the field value must be unique in the db or not.
useful for usernames for example. the check is made non-case-sensitive.
if we cannot check the uniqueness because of missing or wrong db data, the value is accepted. (this happens on the first insert if the table doesn't exist yet.)
note: setting is ignored for the types select and checkbox. //comment: hrm... review this. maybe this line is here because of a copy/paste error. 2002/03/04 --andrej
Tags:
var:
(not set = false)
deprecated:
(all things that use a db are deprecated as of bs4.3)
the field turns into a must field if the condition evaluates to true.
the vector holds hashes with these 4 elements:
1) operator => one of '&' or '|'. & means AND while | means OR.
default is '|'.
2) field => the input field.
3) compare => the way we compare the value. one of =, >, <, >=, <=, !=, s, !s (s = soundex equal, !s = not soundex equal).
default is '='.
the compare is made like "field >= value" so the field is on the left,
the value is on the right side. this matters.
4) value => the value to be compared.
if not set, anything != '' is treated as "matches". this is useful
especially for cases where you want to have a field filled out when
another field is - or is not. for example a checkbox where you are not
sure if the value will be 1, '1' or TRUE.
example: we absolutely need the email address of a person filling out a form if the person either wants to receive our newsletter or orders one of our products. $mustIf = array(array('operator'=>'|', 'field'=>'wantNewsletter', 'compare'=>'=', 'value'=>'yes'), array('operator'=>'|', 'field'=>'orderAmount', 'compare'=>'>', 'value'=>'0'), ) in php code, this would be: (($wantNewsletter == 'yes') || ($orderAmount > 0))
ignored if $must is TRUE.
it's on purpose that this is not language dependant cause i cannot think of an example where it would be of any use and it would make things alot more complicated.
i can see problems with the fucked up php datatypes. compares are made == not ===. please test your code.
at least one of (the fields in that array + this field) have to be filled in IF the condition evaluates to true. otherwise none of the fields are mandatory.
this is a combination of mustIf and mustOneOf.
data structure: it's a hash with the two keys 'fields' => array, exactly the same as for the $mustOneOf var. 'condition' => array, exactly the same as for the $mustIf var.
ignored if $must, $mustIf or $mustOneOf is or evaluates to TRUE.
the field input may not be equal to the field(s) specified here.
may be useful for username/password fields where the password must be different from the username. usually a string, may also be a zero-based array of strings.
note I: we only compare the data, not the datatype. (== not ===)
note II: this could cause some headache. imagine that this field
has to differ from another value, but for some reason, the other
field was not sent (not editable, not visible to this user, ...).
now what? we are not able to compare... we're going with
the following: accept the value, (and log this case? todo).
it could be fixed when $visibility=omit would send the value
in an encrypted way. see var $visibility.
note III: setting is ignored for the types select, checkbox and radio.
remove string(s) from the user submitted value. language dependant. case sensitive.
examples:
$remove = array('abc');
$remove = array('abc', 'abc');
$remove = array('en'=>array('abc'), 'de'=>array('abc'), 'fr'=>array('abc'));
$remove = array('en'=>array('abc','abc'), 'de'=>'abc', 'fr'=>array('abc','abc'));
these structures are not allowed because they would make it hard to guess what is meant:
$remove = 'abc';
$remove = array('en'=>'abc', 'de'=>'abc', 'fr'=>'abc');
so the datatype is a vector or a hash holding vectors.
note: setting is ignored for the types select and radio and checkbox.
replaces strings with strings in the user submitted value. language dependant. case sensitive.
examples:
$replace = array('ä'=>'ae', 'hello'=>'hi');
$replace = array('fr'=>array('é'=>'e'), 'de'=>array('ä'=>'ae','ö'=>'oe','ü'=>'ue');
note: setting is ignored for the types select and radio and checkbox.
Tags:
var:
(associative array holding strings or associative arrays holding associative arrays. see examples)
associative array with style information. these keys can be used:
- string class
- string id
- string style
- (*) char accessKey[]
a char or an associative array cause it's language dependant.
- int tabIndex (ie4+)
- (*) mixed title[]
a string or an associative array cause it's language dependant.
appears as a tool tip over the field.
- (*) mixed label[] (ie4+)
a string or an associative array cause it's language dependant.
i really don't recommend to use that setting instead of the caption.
(*) these options are not available in the gui. problem with explodable holding explodable.
one of the php functions trim(), ltrim() and rtrim() is used, and so the following chars are considered white spaces: "\n", "\r", "\t", "\v", "\0", and a plain space. the value can be one of [none|left|right|both]
note: setting is ignored for the types select and radio and checkbox.
may be a string or a hash cause it's language dependant. for a multiple select field it's even worse. because of this, the following data structures are allowed: for all fields except select:
string and hash:
1) $valueDefault = 'foobar';
2) $valueDefault = array('en'=>'foobar', 'de'=>'hello world');
only for select: (no matter if they are multiple or not)
string, vector, hash (key=language), hash (key=language) holding vectors
1) $valueDefault = 'foobar';
2) $valueDefault = array('foo', 'bar');
3) $valueDefault = array('en'=>'foobar', 'de'=>'hello world');
4) $valueDefault = array('en'=>array('foo', 'bar'), 'de'=>array('hello', 'world'));
yes, this causes a problem cause 2) and 3) are both just arrays. but it can be done.
if this is an explodable field, the default value will be used in every exploded field. you cannot specify an array here to have another default value in each exploded field.
//if it's not a select field //--huh? what should that comment?
sometimes you may not be satisfied with a hardcoded default value for a field. you want some php code to execute to make up the default value. or, for multiple select fields, the default value may be an array. that's what this var is for.
the value (maybe inside a hash because of the language dependency) can be one of:
'text' => default. hardcoded default value.
'code' => some php code that returns a string. may return an array for multiple select
fields only. executed in the scope of this class ($this->_evalWrap()).
'field' => the user-supplied value of another field of a previous level (multi-level forms.)
'array' => only for multiple select fields: when the default value is changed in the gui
and the changes get submitted, the php code has to be executed so we can store
the php array in $valueDefault. this case is needed cause we (hardly) can't
submit a php array with an html form directly. example:
return array('yes'=>'Yes', 'no'=>'No', 'validate'=>'Validate');
a spreadsheet field needs an array aswell.
the value we will display to the user/browser when we show the form (again).
usually a string, may be a vector if it is a select field cause it can have multiple values. it's an array holding the same thing as usual if this is an explodable field.
the value we use internally, eg to store in the database.
usually a string, may be a vector if it is a select field cause it can have multiple values. it's an array holding the same thing as usual if this is an explodable field.
note: the $bsDataType is taken into account to make up this value. example: if the user does not fill in a radio button field, and the radio button field is of $bsDataType 'boolean', then this $valueInternal will be bool FALSE.
2002/04/15 --andrej: this used to be a bool, but it is a string now telling which must case said that it was a must case. possibilities: must, mustIf, mustOneOf, mustOneOfIf if it's not a must field then it's empty (not set or empty string).
Overrides Bs_FormElement::getCaptionForFormOutput() (returns the caption. here in Bs_FormElement it's the same getCaption() but in Bs_FormField which overwrites these methods it makes a difference.)
Parameters:
bool
$useAccessKey
if we should 'highlight' the access key in the returned caption. default = TRUE.
string
$lang
(default is null. if not given then the lang setting of the form is used.)
Return some html code to display all the exploded fields on a website in a form.
usually you want to use getField(), but if it is an explodable field, you need this. you may use getElement() instead of getField(), that's no problem.
validate the user inputs according to the object vars.
the order for data validation is:
1) must 5) mustStartWith 9) mustContain 13) bsDataType/bsDataInfo
2a) onlyOneOf 6) notStartWith 10) notContain 14) regularExpression
2b) onlyIf
3) minLength 7) mustEndWith 11) equalTo 15) additionalCheck
4) maxLength 8) notEndWith 12) notEqualTo 16) mustBeUnique
when the first check fails, the method returns. $this->errorMessage will be filled (or unset if no error).
all validating routines are in a separate method to make it isier for subclasses to overwrite and to just use the needed ones.
if this is an explodable field, this method calls itself for every element.
return: (bool)TRUE if the input passed all validation checks successfully. (string) an error message on failure.
note: some of the field implementations overwrite this method (checkbox, select, radio, maybe others) so if you update something here, don't forget those.
tells if the field has to be filled in according to the current settings.
param $returnString: the return of this method used to be bool. now the default is still bool. but you can change that by setting the param $returnString to TRUE. then you'll get one of 'must', 'mustIf', 'mustOneOf', 'mustOneOfIf' or an empty string '' if it's not a must field.
if used, $param should be a string holding some php code that returns an array. the string will be evaluated (in a separade scope) using eval(), so escape it as you should, rtfm on that. if a parse error occures on your code or if it doesn't return an array, it is ignored. you are allowed to access the filesystem and databases, but not issueing shell commands in your code.
example: (real world example) this is a caption field. but because your app supports different languages, just one string isn't enough. you want one for each supported language. thing is you don't know which languages are used. this information is in a global var: $APP['usedLanguages'] = array('en'=>'english', 'de'=>'deutsch', 'de_du'=>'deutsch du', 'de_si'=>'deutsch sie'); so every language used should have it's own caption field. your code for $param then looks like this: $param = "global \$APP; return \$APP['usedLanguages'];"; now for each element in that returned array, one form element is 'exploded'. the name for the form element is the key of the array, the caption is the value. for the submitted values, $this->valueReceived will be an array also, in this case a hash, where the key is 'en' for example, and the value is the user-submitted value. of course this also works with vecors.
note: you have 3 possibilities to call this method. one is described above, meaning that you pass some php code. the 2nd is that you pass an array directly. the 3rd is that you don't use $param. it will then update $_explodeArray from $explodeEval.
Tags:
see:
var $explodeEval, var $_explodeArray
Parameters:
mixed
$param
(php code as a string, or an array (vector or hash), or nothing. see above.)