(merged from branches/roa. use "svn log -c <changeset> -g <module-svn-path>" for detailed commit message)

git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@59927 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
Ingo Schommer 2008-08-06 03:43:48 +00:00
parent 4fae9902e1
commit aeab0115a0
6 changed files with 135 additions and 15 deletions

View File

@ -387,20 +387,50 @@ class Object {
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// EXTENSION METHODS
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Invokes a method on the object itself, or proxied through a decorator.
*
* This method breaks the normal rules of inheritance, and aggregates everything
* in the returned result. If the invoked methods return void, they are still recorded as
* empty array keys.
*
* @todo find a better way of integrating inheritance rules
*
* @param unknown_type $funcName
* @param unknown_type $arg
*/
public function invokeWithExtensions($funcName, $arg=null) {
$results = array();
if (method_exists($this, $funcName)) {
$results[] = $this->$funcName($arg);
}
$extras = $this->extend($funcName, $arg);
if ($extras) {
return array_merge($results, $extras);
} else {
return $results;
}
}
/**
* Run the given function on all of this object's extensions
* Run the given function on all of this object's extensions. Note that this method
* originally returned void, so if you wanted to return results, you're hosed.
*
* Currently returns an array, with an index resulting every time the function is called.
*
* @param string $funcName The name of the function.
* @param mixed $arg An Argument to be passed to each of the extension functions.
*/
public function extend($funcName, &$arg) {
public function extend($funcName, &$arg=null) {
if($this->extension_instances) {
$return = array();
foreach($this->extension_instances as $extension) {
if($extension->hasMethod($funcName)) {
$extension->$funcName($arg);
$return[] = $extension->$funcName($arg);
}
}
return $return;
}
}

View File

@ -1148,11 +1148,18 @@ class DataObject extends ViewableData implements DataObjectInterface {
*/
public function scaffoldSearchFields() {
$fields = new FieldSet();
foreach($this->databaseFields() as $fieldName => $fieldType) {
foreach($this->searchableFields() as $fieldName => $fieldType) {
// @todo Pass localized title
$fields->push($this->dbObject($fieldName)->scaffoldSearchField());
}
$extras = $this->invokeWithExtensions('extraSearchFields');
if ($extras) {
foreach($extras as $result) {
foreach($result as $fieldName => $fieldType) {
$fields->push(new $fieldType($fieldName));
}
}
}
return $fields;
}
@ -1165,9 +1172,13 @@ class DataObject extends ViewableData implements DataObjectInterface {
*/
public function scaffoldFormFields() {
$fields = new FieldSet();
foreach($this->databaseFields() as $fieldName => $fieldType) {
foreach($this->inheritedDatabaseFields() as $fieldName => $fieldType) {
// @todo Pass localized title
$fields->addFieldToTab('Root.Main', $this->dbObject($fieldName)->scaffoldFormField());
// commented out, to be less of a pain in the ass
//$fields->addFieldToTab('Root.Main', $this->dbObject($fieldName)->scaffoldFormField());
$fields->push($this->dbObject($fieldName)->scaffoldFormField());
}
// @todo Add relation tabs
@ -1952,7 +1963,57 @@ class DataObject extends ViewableData implements DataObjectInterface {
return $def;
}
/**
* Returns fields bu traversing the class heirachy in a bottom-up direction.
*
* Needed to avoid getCMSFields being empty when customDatabaseFields overlooks
* the inheritance chain of the $db array, where a child data object has no $db array,
* but still needs to know the properties of its parent. This should be merged into databaseFields or
* customDatabaseFields.
*
* @todo integrate with pre-existing crap
*/
public function inheritedDatabaseFields() {
$fields = array();
$currentObj = $this;
while(get_class($currentObj) != 'DataObject') {
$fields = array_merge($fields, $currentObj->customDatabaseFields());
$currentObj = singleton($currentObj->parentClass());
}
return $fields;
}
/**
* Get the default searchable fields for this object,
* excluding any fields that are specifically overriden
* in the data object itself.
*
* @todo rename $searchable to $excluded
* @todo overcomplicated, should be simpler way of looking up whether specific fields are supposed to be searchable or not
*/
public function searchableFields() {
$parents = ClassInfo::dataClassesFor($this);
$fields = array();
$searchable = array();
foreach($parents as $class) {
$fields = array_merge($fields, singleton($class)->stat('db'));
$obj = singleton($class);
$results = $obj->invokeWithExtensions('excludeFromSearch');
if ($results) {
foreach($results as $result) {
if (is_array($result)) {
$searchable = array_merge($searchable, $result);
}
}
}
}
foreach($searchable as $field) {
unset($fields[$field]);
}
return $fields;
}
/**
* @return boolean True if the object is in the database
*/
@ -2082,7 +2143,8 @@ class DataObject extends ViewableData implements DataObjectInterface {
* @var string
*/
public static $default_sort = null;
}
?>

View File

@ -18,7 +18,7 @@ class DropdownField extends FormField {
* @param $emptyString mixed Add an empty selection on to of the {source}-Array
* (can also be boolean, which results in an empty string)
*/
function __construct($name, $title = "", $source = array(), $value = "", $form = null, $emptyString = null) {
function __construct($name, $title = null, $source = array(), $value = "", $form = null, $emptyString = null) {
if(is_string($emptyString)) {
$source = is_array($source) ? array(""=>$emptyString) + $source : array(""=>$emptyString);
} elseif($emptyString === true) {
@ -26,7 +26,7 @@ class DropdownField extends FormField {
}
$this->source = $source;
parent::__construct($name, $title, $value, $form);
parent::__construct($name, ($title===null) ? $name : $title, $value, $form);
}
/**

View File

@ -129,7 +129,7 @@ class FieldSet extends DataObjectSet {
*/
protected function findOrMakeTab($tabName) {
$parts = explode('.',$tabName);
// We could have made this recursive, but I've chosen to keep all the logic code within FieldSet rather than add it to TabSet and Tab too.
$currentPointer = $this;
foreach($parts as $part) {
@ -138,7 +138,7 @@ class FieldSet extends DataObjectSet {
// Create any missing tabs
if(!$currentPointer) {
if(is_a($parentPointer,'TabSet')) {
$currentPointer = new Tab($part);
$currentPointer = new Tab($tabName);
$parentPointer->push($currentPointer);
} else {
user_error("FieldSet::addFieldToTab() Tried to add a tab to a " . $parentPointer->class . " object - '$part' didn't exist.", E_USER_ERROR);

View File

@ -11,14 +11,14 @@ class PhoneNumberField extends FormField {
protected $countryCode;
protected $ext;
public function __construct( $name, $title, $value = '', $extension = null,
public function __construct( $name, $title = null, $value = '', $extension = null,
$areaCode = null, $countryCode = null, $form = null ) {
$this->areaCode = $areaCode;
$this->ext = $extension;
$this->countryCode = $countryCode;
parent::__construct( $name, $title, $value, $form );
parent::__construct( $name, ($title===null) ? $name : $title, $value, $form );
}
public function Field() {
@ -82,6 +82,8 @@ class PhoneNumberField extends FormField {
$parts = array_pad($parts, 4, false);
}
if(sizeof($parts) < 4) $parts[] = '';
return $parts;
}

View File

@ -148,6 +148,32 @@ class SearchContext extends Object {
$this->filters = $filters;
}
function clearEmptySearchFields($value) {
return ($value != '');
}
/**
* Placeholder, until I figure out the rest of the SQLQuery stuff
* and link the $searchable_fields array to the SearchContext
*/
public function getResultSet($fields) {
$filter = "";
$current = 1;
$fields = array_filter($fields, array($this,'clearEmptySearchFields'));
$length = count($fields);
foreach($fields as $key=>$val) {
if ($val != '') {
$filter .= "`$key`='$val'";
} else {
$length--;
}
if ($current < $length) {
$filter .= " AND ";
}
$current++;
}
return DataObject::get($this->modelClass, $filter);
}
}
?>