From 26b8f7dffe928b54ca77d3012ffc34dbdc5a07ab Mon Sep 17 00:00:00 2001 From: Normann Lou Date: Fri, 23 Nov 2007 01:10:19 +0000 Subject: [PATCH] switch externals to trunk. Inform-merge: from the changeset: r32477: Merge 2.0-inform from trunk previously r32478: Merge 2.0-inform from trunk previously r32481: merge 2.0infom with lastes chunk r32483: merge 2.0infom with lastes chunk r33526: Final styling of all forms and combined communication form add/alter javascript for height adjustment of First / Second block r33580: styling for combined form communication in myinfom pages r33706: styling of combined form (communication) in Email r33881: made compatible to $extraClass r33885: added defaultVal r33887: fixed typo r34728: modified SmallFieldHolder?() r34729: added "validationError"-class r34914: WIP3866: Factfinder: Hide "self emplyed" block r34964: Change current plan upto TraumaInsurance? r35038: disabled friggin field focus r35230: #1032 Fixed hash-link insertion r35887: conditionally setting parameters in sourceID() - to avoid empty overrides r35892: Saving value in SQL-compatible format (YYYY-MM-DD instead of DD/MM/YYYY), with fallback for non-sql values (just passed through without conversion) r35928: Removed "create a" from PageType?-dropdown, sorting alphabetically, falling back to $singular_name r35990: branched off for membertablefield r35994: fix for membertablefield r36024: added array-condition needed for DMYDateField r36083: fix bug for compositeField -> dropDatalessField r36394: removed debug code r36826: change wrong indent format r36828: WIP 4262: Logging out of My Inform goes to blank page r36858: Fixed error caused in r12472 while merging to Session-class r37132: Merged partial changesets from branches/2.0-nzct, only adding childID to detailform when not in add-mode r40815: add an unsubscribe record when a member subscribe a newslettertype r41113: fix the bug described in http://support.silverstripe.com/info/ticket/31: CRM not showing search results r43226: fixed search (partial merge from trunk) r43268: merged createNewPassword() from trunk, was referencing a non-existinent global function randomString() git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@45473 467b73ca-7a2a-4603-9d3b-597d59a354a9 --- core/control/Director.php | 2 +- core/model/RedirectorPage.php | 2 +- core/model/SiteTree.php | 19 ++++++++++++++--- core/model/VirtualPage.php | 1 + core/model/fieldtypes/DBField.php | 18 +++++++++++++++- core/model/fieldtypes/Int.php | 13 ++++++++++-- forms/ComplexTableField.php | 22 ++++++++++++-------- forms/CompositeField.php | 34 +++++++++++++++++++++++++++++++ forms/DateField.php | 21 ++++++++++++++----- forms/FieldSet.php | 1 + forms/Form.php | 22 +++++++++++++++++++- forms/FormField.php | 9 +++++++- forms/HeaderField.php | 8 +++++--- forms/OptionsetField.php | 11 ++++++++-- forms/SelectionGroup.php | 18 ++++++++++++++++ javascript/CalendarDateField.js | 4 ++++ javascript/Validator.js | 10 +++++++++ security/Member.php | 22 +++++++++++++++++++- silverstripe_version | 2 +- 19 files changed, 209 insertions(+), 30 deletions(-) diff --git a/core/control/Director.php b/core/control/Director.php index b66af1a91..12383b3a9 100644 --- a/core/control/Director.php +++ b/core/control/Director.php @@ -314,7 +314,7 @@ class Director { } static function getAbsURL($url) { - return Director::baseURL() . '/' . $url; + return Director::baseURL() . $url; } static function getAbsFile($file) { diff --git a/core/model/RedirectorPage.php b/core/model/RedirectorPage.php index d0c45adbb..7df706dea 100755 --- a/core/model/RedirectorPage.php +++ b/core/model/RedirectorPage.php @@ -4,7 +4,7 @@ * A redirector page redirects when the page is visited. */ class RedirectorPage extends Page { - static $add_action = "a redirector to another page"; + static $add_action = "Redirector to another page"; static $icon = array("cms/images/treeicons/page-shortcut","file"); static $db = array( diff --git a/core/model/SiteTree.php b/core/model/SiteTree.php index bc9c5b3a3..e6ca2c52b 100644 --- a/core/model/SiteTree.php +++ b/core/model/SiteTree.php @@ -1211,13 +1211,26 @@ class SiteTree extends DataObject { if((($instance instanceof HiddenClass) || !$instance->canCreate()) && ($class != $this->class)) continue; $addAction = $instance->uninherited('add_action', true); - if(!$addAction) $addAction = "a $class"; + if(!$addAction) { + $addAction = $instance->singular_name(); + } - $result[$class] = ($class == $this->class) + if($class == $this->class) { + $currentClass = $class; + $currentAddAction = $addAction; + } else { + $result[$class] = ($class == $this->class) ? "Currently $addAction" : "Change to $addAction"; + } } - + + // sort alphabetically, and put current on top + asort($result); + $result = array_reverse($result); + $result[$currentClass] = "{$currentAddAction} (current)"; + $result = array_reverse($result); + return $result; } diff --git a/core/model/VirtualPage.php b/core/model/VirtualPage.php index b62887f70..6daf14f0b 100755 --- a/core/model/VirtualPage.php +++ b/core/model/VirtualPage.php @@ -6,6 +6,7 @@ * Note: This Only duplicates $db fields and not the $has_one etc.. */ class VirtualPage extends Page { + static $add_action = "Virtual page (another page's content)"; static $icon = array("cms/images/treeicons/page-shortcut-gold","file"); diff --git a/core/model/fieldtypes/DBField.php b/core/model/fieldtypes/DBField.php index a536f1071..b2f398b45 100644 --- a/core/model/fieldtypes/DBField.php +++ b/core/model/fieldtypes/DBField.php @@ -6,10 +6,20 @@ * the creation of the field in the database, */ abstract class DBField extends ViewableData { + protected $value; + protected $tableName; + protected $name; + /** + * @var $default mixed Default-value in the database. + * Might be overridden on DataObject-level, but still useful for setting defaults on + * already existing records after a db-build. + */ + protected $defaultVal; + function __construct($name) { $this->name = $name; @@ -29,12 +39,15 @@ abstract class DBField extends ViewableData { function setVal($value) { return $this->setValue($value); } + function setValue($value) { $this->value = $value; } + function setTable($tableName) { $this->tableName = $tableName; } + function forTemplate() { return $this->value; } @@ -45,15 +58,19 @@ abstract class DBField extends ViewableData { function ATT() { return Convert::raw2att($this->value); } + function RAW() { return $this->value; } + function JS() { return Convert::raw2js($this->value); } + function HTML(){ return Convert::raw2xml($this->value); } + function XML(){ return Convert::raw2xml($this->value); } @@ -93,5 +110,4 @@ abstract class DBField extends ViewableData { DBG; } } - ?> \ No newline at end of file diff --git a/core/model/fieldtypes/Int.php b/core/model/fieldtypes/Int.php index 8b2e8913b..d7eaf6df7 100644 --- a/core/model/fieldtypes/Int.php +++ b/core/model/fieldtypes/Int.php @@ -1,5 +1,7 @@ defaultVal = is_numeric($defaultVal) ? $defaultVal : 0; + + parent::__construct($name); + } + function Formatted() { return number_format($this->value); } @@ -35,4 +44,4 @@ class Int extends DBField { } } -?> \ No newline at end of file +?> diff --git a/forms/ComplexTableField.php b/forms/ComplexTableField.php index 75cdf5bd7..58f1db3e3 100755 --- a/forms/ComplexTableField.php +++ b/forms/ComplexTableField.php @@ -247,9 +247,8 @@ JS; } else { $detailFields = $childData->getCMSFields(); } - if($this->getParentClass()) { - $parentIdName = $this->getParentIdName( $this->getParentClass(), $this->sourceClass ); + $parentIdName = $this->getParentIdName($this->sourceClass,$this->getParentClass()); if(!$parentIdName) { user_error("ComplexTableField::DetailForm() Cannot automatically determine 'has-one'-relationship to parent, @@ -262,12 +261,15 @@ JS; $detailFields->push(new HiddenField("$parentIdName"," ",$ID)); } - // the ID field confuses the Controller-logic in finding the right view for ReferencedField $detailFields->removeByName('ID'); + // only add childID if we're not adding a record + if($this->methodName != 'add') { + $detailFields->push(new HiddenField("ctf[childID]","",$childID)); + } + // add a namespaced ID instead thats "converted" by saveComplexTableField() - $detailFields->push(new HiddenField("ctf[childID]","",$childID)); $detailFields->push(new HiddenField("ctf[ClassName]","",$this->sourceClass)); $readonly = ($this->methodName == "show"); @@ -399,9 +401,8 @@ JS; // we can't rely on $idField being populated, and fall back to the request-params. // this is a workaround for a bug where each subsequent popup-call didn't have ID // of the parent set, and so didn't properly save the relation - return ($idField->Value()) ? $idField->Value() : (isset($_REQUEST['ctf']['ID']) ? $_REQUEST['ctf']['ID'] : null); + return ($idField->Value()) ? $idField->Value() : $_REQUEST['ctf']['ID']; } - /** * ################################# @@ -409,7 +410,11 @@ JS; * ################################# */ function PopupBaseLink() { - return $this->FormAction() . "&action_callfieldmethod&fieldName={$this->Name()}&ctf[ID]={$this->sourceID()}"; + $link = $this->FormAction() . "&action_callfieldmethod&fieldName={$this->Name()}"; + if(!strpos($link,'ctf[ID]')) { + $link = HTTP::setGetVar('ctf[ID]',$this->sourceID(),$link); + } + return $link; } function PopupCurrentItem() { @@ -689,8 +694,9 @@ class ComplexTableField_Popup extends Form { $childObject = DataObject::get_by_id($this->sourceClass, $id); } else { $childObject = new $this->sourceClass(); - $childObject->write(); // Give it an ID prior to calling saveInto + $this->fields->removeByName('ID'); } + $this->saveInto($childObject); $childObject->write(); diff --git a/forms/CompositeField.php b/forms/CompositeField.php index d6678f68d..3d68ccfea 100755 --- a/forms/CompositeField.php +++ b/forms/CompositeField.php @@ -182,6 +182,40 @@ class CompositeField extends FormField { return $this; } + + /** + * Return a readonly version of this field. Keeps the composition but returns readonly + * versions of all the children + */ + public function dropDatalessField() { + $newChildren = new FieldSet(); + + foreach($this->children as $idx => $child) { + + if(is_object($child)){ + if(get_class($child)=='HeaderField'||get_class($child)=='LabelField'||get_class($child)=='TableListField'||is_subclass_of($child, 'TableListField')||get_class($field)=='SelectionGroup'||is_subclass_of($field, 'SelectionGroup')){ + $newChildren->push($child, $idx); + }elseif($child->isComposite()){ + $newChildren->push($child->dropDatalessField()); + }elseif((get_class($child)!='DatalessField'&&!is_subclass_of($child, 'DatalessField'))){ + if($this->hasClass('Undropable')||$child->Value()!==NULL){ + $newChildren->push($child, $idx); + } + } + }elseif(is_array($child)){ + foreach($child as $idx=>$subChild){ + if(is_object($subChild)){ + if($subChild->isComposite){ + $newChildren->push($subChild->dropDatalessField()); + } + } + } + } + } + $this->children = $newChildren; + return $this; + } + function IsReadonly() { return $this->readonly; } diff --git a/forms/DateField.php b/forms/DateField.php index 271b431f5..6ae537e31 100755 --- a/forms/DateField.php +++ b/forms/DateField.php @@ -4,16 +4,27 @@ * Default Value represented in the format */ class DateField extends TextField { + function setValue($val) { - if(preg_match('/^([\d]{1,2})\/([\d]{1,2})\/([\d]{2,4})/', $val, $parts)) { - $val = "$parts[3]-$parts[2]-$parts[1]"; + if($val && preg_match('/^([\d]{2,4})-([\d]{1,2})-([\d]{1,2})/', $val)) { + $this->value = preg_replace('/^([\d]{2,4})-([\d]{1,2})-([\d]{1,2})/','\\3/\\2/\\1', $val); + } else { + $this->value = $val; } - if($val) $this->value = date('d/m/Y', strtotime($val)); - else $this->value = null; } + function dataValue() { - return preg_replace('/^([0-9]{1,2})\/([0-9]{1,2})\/([0-90-9]{2,4})/', '\\3-\\2-\\1', $this->value); + if(is_array($this->value)) { + return $this->value['Year'] . '-' . $this->value['Month'] . '-' . $this->value['Day']; + } elseif(preg_match('/^([\d]{1,2})\/([\d]{1,2})\/([\d]{2,4})/', $this->value, $parts)) { + return "$parts[3]-$parts[2]-$parts[1]"; + } elseif(!empty($this->value)) { + return date('Y-m-d', strtotime($this->value)); + } else { + return null; + } } + function performReadonlyTransformation() { $field = new DateField_Disabled($this->name, $this->title, $this->value); $field->setForm($this->form); diff --git a/forms/FieldSet.php b/forms/FieldSet.php index 156bd5feb..30d0b0609 100755 --- a/forms/FieldSet.php +++ b/forms/FieldSet.php @@ -20,6 +20,7 @@ class FieldSet extends DataObjectSet { protected function collateDataFields(&$list) { foreach($this as $field) { + if($field->isComposite()) $field->collateDataFields($list); if($field->hasData()) { $name = $field->Name(); diff --git a/forms/Form.php b/forms/Form.php index 120604787..defd0b17e 100644 --- a/forms/Form.php +++ b/forms/Form.php @@ -147,6 +147,10 @@ class Form extends ViewableData { } } + function unsetValidator(){ + $this->validator = null; + } + /** * Remove the {@link Validator} from this from. */ @@ -673,7 +677,6 @@ class Form extends ViewableData { if($this->buttonClickedFunc == $action->actionName()) return $action; } } - /** * Return the default button that should be clicked when another one isn't available */ @@ -763,4 +766,21 @@ class Form extends ViewableData { $data['ajax'] = 1; return $this->testSubmission($action, $data); } + function dropDatalessField(){ + foreach($this->Fields() as $field){ + if(get_class($field)!='SelectionGroup'&&get_class($field)!='TableListField'&&!is_subclass_of($field, 'TableListField')){ + if((get_class($field)=='DatalessField' ||is_subclass_of($field, 'DatalessField'))&&get_class($field)!='HeaderField'&&get_class($field)!='LabelField'){ + $this->Fields()->removeByName($field->Name()); + }elseif($field->isComposite()){ + $field->dropDatalessField(); + }else{ + if(get_class($field) != "HeaderField" &&get_class($field) != "LabelField"&& $field->Value() === NULL){ + $this->Fields()->removeByName($field->Name()); + } + } + } + + + } + } } diff --git a/forms/FormField.php b/forms/FormField.php index ec1655e61..059b1a6d4 100644 --- a/forms/FormField.php +++ b/forms/FormField.php @@ -237,6 +237,8 @@ class FormField extends ViewableData { * a good idea to put the actual HTML for field holders into templates. The default field holder * is the DefaultFieldHolder template. This lets you override the HTML for specific sites, if it's * necessary. + * + * TODO Add "validationError" if needed. */ function FieldHolder() { $Title = $this->XML_val('Title'); @@ -262,7 +264,6 @@ HTML; */ function SmallFieldHolder() { $result = ''; - // set label if($title = $this->RightTitle()){ $result .= "\n"; @@ -326,6 +327,12 @@ HTML; return $trans->transform($this); } + function hasClass($class){ + $patten = '/'.strtolower($class).'/i'; + $subject = strtolower($this->class." ".$this->extraClass); + return preg_match($patten, $subject); + } + /** * Returns the field type - used by templates. * The field type is the class name with the word Field dropped off the end, all lowercase. diff --git a/forms/HeaderField.php b/forms/HeaderField.php index 7ea6b3a92..927b2cb47 100755 --- a/forms/HeaderField.php +++ b/forms/HeaderField.php @@ -13,10 +13,12 @@ class HeaderField extends DatalessField { parent::__construct(null, $title, null, $form); } function Field() { - if($this->allowHTML) $XML_title = $this->title; - else $XML_title = Convert::raw2xml($this->title); + $XML_title = ($this->allowHTML) ? $this->title : Convert::raw2xml($this->title); - return "headingLevel>$XML_titleheadingLevel>"; + // extraclass + $XML_class = ($this->extraClass()) ? " class=\"{$this->extraClass()}\"" : ''; + + return "headingLevel}{$XML_class}>$XML_titleheadingLevel>"; } } ?> \ No newline at end of file diff --git a/forms/OptionsetField.php b/forms/OptionsetField.php index 5f2cd7701..554a9e84a 100755 --- a/forms/OptionsetField.php +++ b/forms/OptionsetField.php @@ -38,12 +38,19 @@ class OptionsetField extends DropdownField { $odd = ($odd + 1) % 2; $extraClass = $odd ? "odd" : "even"; $extraClass .= " val" . str_replace(' ','',$key); + $this->disabled ? $disabled = " disabled=\"disabled\"" : $disable = ""; - $options .= "
  • name\" type=\"radio\" value=\"$key\"$checked />
  • \n"; + $options .= "
  • name\" type=\"radio\" value=\"$key\"$checked $disabled/>
  • \n"; } $id = $this->id(); - return "\n"; + return "\n"; } + + protected $disabled = false; + function setDisabled($val) { + $this->disabled = $val; + } + function performReadonlyTransformation() { diff --git a/forms/SelectionGroup.php b/forms/SelectionGroup.php index f75e26446..5ffad34b8 100755 --- a/forms/SelectionGroup.php +++ b/forms/SelectionGroup.php @@ -24,6 +24,24 @@ class SelectionGroup extends CompositeField { Requirements::css('sapphire/css/SelectionGroup.css'); } + /** + * Return a readonly version of this field. Keeps the composition but returns readonly + * versions of all the children + */ + public function performDisabledTransformation($trans) { + $newChildren = array(); + if($this->children) foreach($this->children as $idx => $child) { + if(is_object($child)) { + $child = $child->transform($trans); + } + $newChildren[$idx] = $child; + } + + $this->children = new FieldSet($newChildren); + $this->readonly = true; + return $this; + } + function FieldSet() { $items = parent::FieldSet()->toArray(); diff --git a/javascript/CalendarDateField.js b/javascript/CalendarDateField.js index af6a07c82..f3fb70ebe 100755 --- a/javascript/CalendarDateField.js +++ b/javascript/CalendarDateField.js @@ -49,8 +49,12 @@ NumericField.prototype = { if( testedOk ) { this.oldValue = this.value = testValue; + // DEBUG This produces weird javascript-errors, and is not very useable at all + // DONT MERGE + /* if( this.value.length == this.maxLength && this.nextField ) this.nextField.focus(); + */ if( this.callOnValidate ) this.callOnValidate(); diff --git a/javascript/Validator.js b/javascript/Validator.js index cab136ffa..bdc887a8f 100755 --- a/javascript/Validator.js +++ b/javascript/Validator.js @@ -42,12 +42,18 @@ function clearErrorMessage(holderDiv){ Element.hide(el); }); } + $$('div.validationError', holderDiv.parentNode).each(function(el) { + Element.removeClassName(el,'validationError'); + }); } function clearAllErrorMessages() { $$('span.message').each(function(el) { Element.hide(el); }); + $$('div.validationError').each(function(el) { + Element.removeClassName(el,'validationError'); + }); } function require(fieldName,cachedError) { @@ -249,6 +255,10 @@ function validationError(field,message, messageClass, cacheError) { validationMessage.className = "message " + messageClass; validationMessage.innerHTML = message; validationMessage.style.display = "block"; + + // Set Classname on holder + var holder = document.getParentOfElement(field,'div','field'); + Element.addClassName(holder, 'validationError'); } /** diff --git a/security/Member.php b/security/Member.php index 5c868b307..07153f2dd 100644 --- a/security/Member.php +++ b/security/Member.php @@ -414,14 +414,34 @@ class Member extends DataObject { * @return bool Returns TRUE if the member is in the given group, * otherwise FALSE. */ + public function inGroup($groupID) { foreach($this->Groups() as $group) { if($groupID == $group->ID) return true; - } + } return false; } + + static function createNewPassword() { + if(file_exists('/usr/share/silverstripe/wordlist.txt')) { + $words = file('/usr/share/silverstripe/wordlist.txt'); + + list($usec, $sec) = explode(' ', microtime()); + srand($sec + ((float) $usec * 100000)); + + $word = trim($words[rand(0,sizeof($words)-1)]); + $number = rand(10,999); + + return $word . $number; + } else { + $random = rand(); + $string = md5($random); + $output = substr($string, 0, 6); + return $output; + } + } /** diff --git a/silverstripe_version b/silverstripe_version index 03d27cc0b..426ac9cec 100644 --- a/silverstripe_version +++ b/silverstripe_version @@ -1 +1 @@ -$URL$ \ No newline at end of file +$URL:svn://svn.silverstripe.com/silverstripe/modules/sapphire/branches/2.0-inform/silverstripe_version $ \ No newline at end of file