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
This commit is contained in:
Normann Lou 2007-11-23 01:10:19 +00:00
parent 99e45e48c3
commit 26b8f7dffe
19 changed files with 209 additions and 30 deletions

View File

@ -314,7 +314,7 @@ class Director {
} }
static function getAbsURL($url) { static function getAbsURL($url) {
return Director::baseURL() . '/' . $url; return Director::baseURL() . $url;
} }
static function getAbsFile($file) { static function getAbsFile($file) {

View File

@ -4,7 +4,7 @@
* A redirector page redirects when the page is visited. * A redirector page redirects when the page is visited.
*/ */
class RedirectorPage extends Page { 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 $icon = array("cms/images/treeicons/page-shortcut","file");
static $db = array( static $db = array(

View File

@ -1211,13 +1211,26 @@ class SiteTree extends DataObject {
if((($instance instanceof HiddenClass) || !$instance->canCreate()) && ($class != $this->class)) continue; if((($instance instanceof HiddenClass) || !$instance->canCreate()) && ($class != $this->class)) continue;
$addAction = $instance->uninherited('add_action', true); $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" ? "Currently $addAction"
: "Change to $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; return $result;
} }

View File

@ -6,6 +6,7 @@
* Note: This Only duplicates $db fields and not the $has_one etc.. * Note: This Only duplicates $db fields and not the $has_one etc..
*/ */
class VirtualPage extends Page { class VirtualPage extends Page {
static $add_action = "Virtual page (another page's content)"; static $add_action = "Virtual page (another page's content)";
static $icon = array("cms/images/treeicons/page-shortcut-gold","file"); static $icon = array("cms/images/treeicons/page-shortcut-gold","file");

View File

@ -6,10 +6,20 @@
* the creation of the field in the database, * the creation of the field in the database,
*/ */
abstract class DBField extends ViewableData { abstract class DBField extends ViewableData {
protected $value; protected $value;
protected $tableName; protected $tableName;
protected $name; 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) { function __construct($name) {
$this->name = $name; $this->name = $name;
@ -29,12 +39,15 @@ abstract class DBField extends ViewableData {
function setVal($value) { function setVal($value) {
return $this->setValue($value); return $this->setValue($value);
} }
function setValue($value) { function setValue($value) {
$this->value = $value; $this->value = $value;
} }
function setTable($tableName) { function setTable($tableName) {
$this->tableName = $tableName; $this->tableName = $tableName;
} }
function forTemplate() { function forTemplate() {
return $this->value; return $this->value;
} }
@ -45,15 +58,19 @@ abstract class DBField extends ViewableData {
function ATT() { function ATT() {
return Convert::raw2att($this->value); return Convert::raw2att($this->value);
} }
function RAW() { function RAW() {
return $this->value; return $this->value;
} }
function JS() { function JS() {
return Convert::raw2js($this->value); return Convert::raw2js($this->value);
} }
function HTML(){ function HTML(){
return Convert::raw2xml($this->value); return Convert::raw2xml($this->value);
} }
function XML(){ function XML(){
return Convert::raw2xml($this->value); return Convert::raw2xml($this->value);
} }
@ -93,5 +110,4 @@ abstract class DBField extends ViewableData {
DBG; DBG;
} }
} }
?> ?>

View File

@ -1,5 +1,7 @@
<?php <?php
/**
* @param $defaultVal int
*/
class Int extends DBField { class Int extends DBField {
function __construct($name, $defaultVal = 0) { function __construct($name, $defaultVal = 0) {
@ -10,6 +12,13 @@ class Int extends DBField {
parent::__construct($name); parent::__construct($name);
} }
function __construct($name, $defaultVal = null) {
$this->defaultVal = is_numeric($defaultVal) ? $defaultVal : 0;
parent::__construct($name);
}
function Formatted() { function Formatted() {
return number_format($this->value); return number_format($this->value);
} }
@ -35,4 +44,4 @@ class Int extends DBField {
} }
} }
?> ?>

View File

@ -247,9 +247,8 @@ JS;
} else { } else {
$detailFields = $childData->getCMSFields(); $detailFields = $childData->getCMSFields();
} }
if($this->getParentClass()) { if($this->getParentClass()) {
$parentIdName = $this->getParentIdName( $this->getParentClass(), $this->sourceClass ); $parentIdName = $this->getParentIdName($this->sourceClass,$this->getParentClass());
if(!$parentIdName) { if(!$parentIdName) {
user_error("ComplexTableField::DetailForm() Cannot automatically user_error("ComplexTableField::DetailForm() Cannot automatically
determine 'has-one'-relationship to parent, determine 'has-one'-relationship to parent,
@ -262,12 +261,15 @@ JS;
$detailFields->push(new HiddenField("$parentIdName"," ",$ID)); $detailFields->push(new HiddenField("$parentIdName"," ",$ID));
} }
// the ID field confuses the Controller-logic in finding the right view for ReferencedField // the ID field confuses the Controller-logic in finding the right view for ReferencedField
$detailFields->removeByName('ID'); $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() // add a namespaced ID instead thats "converted" by saveComplexTableField()
$detailFields->push(new HiddenField("ctf[childID]","",$childID));
$detailFields->push(new HiddenField("ctf[ClassName]","",$this->sourceClass)); $detailFields->push(new HiddenField("ctf[ClassName]","",$this->sourceClass));
$readonly = ($this->methodName == "show"); $readonly = ($this->methodName == "show");
@ -399,9 +401,8 @@ JS;
// we can't rely on $idField being populated, and fall back to the request-params. // 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 // 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 // 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() { 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() { function PopupCurrentItem() {
@ -689,8 +694,9 @@ class ComplexTableField_Popup extends Form {
$childObject = DataObject::get_by_id($this->sourceClass, $id); $childObject = DataObject::get_by_id($this->sourceClass, $id);
} else { } else {
$childObject = new $this->sourceClass(); $childObject = new $this->sourceClass();
$childObject->write(); // Give it an ID prior to calling saveInto $this->fields->removeByName('ID');
} }
$this->saveInto($childObject); $this->saveInto($childObject);
$childObject->write(); $childObject->write();

View File

@ -182,6 +182,40 @@ class CompositeField extends FormField {
return $this; 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() { function IsReadonly() {
return $this->readonly; return $this->readonly;
} }

View File

@ -4,16 +4,27 @@
* Default Value represented in the format * Default Value represented in the format
*/ */
class DateField extends TextField { class DateField extends TextField {
function setValue($val) { function setValue($val) {
if(preg_match('/^([\d]{1,2})\/([\d]{1,2})\/([\d]{2,4})/', $val, $parts)) { if($val && preg_match('/^([\d]{2,4})-([\d]{1,2})-([\d]{1,2})/', $val)) {
$val = "$parts[3]-$parts[2]-$parts[1]"; $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() { 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() { function performReadonlyTransformation() {
$field = new DateField_Disabled($this->name, $this->title, $this->value); $field = new DateField_Disabled($this->name, $this->title, $this->value);
$field->setForm($this->form); $field->setForm($this->form);

View File

@ -20,6 +20,7 @@ class FieldSet extends DataObjectSet {
protected function collateDataFields(&$list) { protected function collateDataFields(&$list) {
foreach($this as $field) { foreach($this as $field) {
if($field->isComposite()) $field->collateDataFields($list); if($field->isComposite()) $field->collateDataFields($list);
if($field->hasData()) { if($field->hasData()) {
$name = $field->Name(); $name = $field->Name();

View File

@ -147,6 +147,10 @@ class Form extends ViewableData {
} }
} }
function unsetValidator(){
$this->validator = null;
}
/** /**
* Remove the {@link Validator} from this from. * Remove the {@link Validator} from this from.
*/ */
@ -673,7 +677,6 @@ class Form extends ViewableData {
if($this->buttonClickedFunc == $action->actionName()) return $action; if($this->buttonClickedFunc == $action->actionName()) return $action;
} }
} }
/** /**
* Return the default button that should be clicked when another one isn't available * 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; $data['ajax'] = 1;
return $this->testSubmission($action, $data); 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());
}
}
}
}
}
} }

View File

@ -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 * 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 * is the DefaultFieldHolder template. This lets you override the HTML for specific sites, if it's
* necessary. * necessary.
*
* TODO Add "validationError" if needed.
*/ */
function FieldHolder() { function FieldHolder() {
$Title = $this->XML_val('Title'); $Title = $this->XML_val('Title');
@ -262,7 +264,6 @@ HTML;
*/ */
function SmallFieldHolder() { function SmallFieldHolder() {
$result = ''; $result = '';
// set label // set label
if($title = $this->RightTitle()){ if($title = $this->RightTitle()){
$result .= "<label class=\"right\" for=\"" . $this->id() . "\">{$title}</label>\n"; $result .= "<label class=\"right\" for=\"" . $this->id() . "\">{$title}</label>\n";
@ -326,6 +327,12 @@ HTML;
return $trans->transform($this); 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. * Returns the field type - used by templates.
* The field type is the class name with the word Field dropped off the end, all lowercase. * The field type is the class name with the word Field dropped off the end, all lowercase.

View File

@ -13,10 +13,12 @@ class HeaderField extends DatalessField {
parent::__construct(null, $title, null, $form); parent::__construct(null, $title, null, $form);
} }
function Field() { function Field() {
if($this->allowHTML) $XML_title = $this->title; $XML_title = ($this->allowHTML) ? $this->title : Convert::raw2xml($this->title);
else $XML_title = Convert::raw2xml($this->title);
return "<h$this->headingLevel>$XML_title</h$this->headingLevel>"; // extraclass
$XML_class = ($this->extraClass()) ? " class=\"{$this->extraClass()}\"" : '';
return "<h{$this->headingLevel}{$XML_class}>$XML_title</h$this->headingLevel>";
} }
} }
?> ?>

View File

@ -38,12 +38,19 @@ class OptionsetField extends DropdownField {
$odd = ($odd + 1) % 2; $odd = ($odd + 1) % 2;
$extraClass = $odd ? "odd" : "even"; $extraClass = $odd ? "odd" : "even";
$extraClass .= " val" . str_replace(' ','',$key); $extraClass .= " val" . str_replace(' ','',$key);
$this->disabled ? $disabled = " disabled=\"disabled\"" : $disable = "";
$options .= "<li class=\"".$extraClass."\"><input id=\"$itemID\" name=\"$this->name\" type=\"radio\" value=\"$key\"$checked /> <label for=\"$itemID\">$value</label></li>\n"; $options .= "<li class=\"".$extraClass."\"><input id=\"$itemID\" name=\"$this->name\" type=\"radio\" value=\"$key\"$checked $disabled/> <label for=\"$itemID\">$value</label></li>\n";
} }
$id = $this->id(); $id = $this->id();
return "<ul id=\"$id\" class=\"optionset\">\n$options</ul>\n"; return "<ul id=\"$id\" class=\"optionset {$this->extraClass}\">\n$options</ul>\n";
} }
protected $disabled = false;
function setDisabled($val) {
$this->disabled = $val;
}
function performReadonlyTransformation() { function performReadonlyTransformation() {

View File

@ -24,6 +24,24 @@ class SelectionGroup extends CompositeField {
Requirements::css('sapphire/css/SelectionGroup.css'); 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() { function FieldSet() {
$items = parent::FieldSet()->toArray(); $items = parent::FieldSet()->toArray();

View File

@ -49,8 +49,12 @@ NumericField.prototype = {
if( testedOk ) { if( testedOk ) {
this.oldValue = this.value = testValue; 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 ) if( this.value.length == this.maxLength && this.nextField )
this.nextField.focus(); this.nextField.focus();
*/
if( this.callOnValidate ) if( this.callOnValidate )
this.callOnValidate(); this.callOnValidate();

View File

@ -42,12 +42,18 @@ function clearErrorMessage(holderDiv){
Element.hide(el); Element.hide(el);
}); });
} }
$$('div.validationError', holderDiv.parentNode).each(function(el) {
Element.removeClassName(el,'validationError');
});
} }
function clearAllErrorMessages() { function clearAllErrorMessages() {
$$('span.message').each(function(el) { $$('span.message').each(function(el) {
Element.hide(el); Element.hide(el);
}); });
$$('div.validationError').each(function(el) {
Element.removeClassName(el,'validationError');
});
} }
function require(fieldName,cachedError) { function require(fieldName,cachedError) {
@ -249,6 +255,10 @@ function validationError(field,message, messageClass, cacheError) {
validationMessage.className = "message " + messageClass; validationMessage.className = "message " + messageClass;
validationMessage.innerHTML = message; validationMessage.innerHTML = message;
validationMessage.style.display = "block"; validationMessage.style.display = "block";
// Set Classname on holder
var holder = document.getParentOfElement(field,'div','field');
Element.addClassName(holder, 'validationError');
} }
/** /**

View File

@ -414,14 +414,34 @@ class Member extends DataObject {
* @return bool Returns TRUE if the member is in the given group, * @return bool Returns TRUE if the member is in the given group,
* otherwise FALSE. * otherwise FALSE.
*/ */
public function inGroup($groupID) { public function inGroup($groupID) {
foreach($this->Groups() as $group) { foreach($this->Groups() as $group) {
if($groupID == $group->ID) if($groupID == $group->ID)
return true; return true;
} }
return false; 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;
}
}
/** /**

View File

@ -1 +1 @@
$URL$ $URL:svn://svn.silverstripe.com/silverstripe/modules/sapphire/branches/2.0-inform/silverstripe_version $