diff --git a/core/Object.php b/core/Object.php index c619acdc5..63a725070 100755 --- a/core/Object.php +++ b/core/Object.php @@ -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; } } diff --git a/core/model/DataObject.php b/core/model/DataObject.php index bd41e4f4c..0ba1c75a3 100644 --- a/core/model/DataObject.php +++ b/core/model/DataObject.php @@ -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; + } - ?> + diff --git a/forms/DropdownField.php b/forms/DropdownField.php index 2b3c1692b..d651a79e6 100755 --- a/forms/DropdownField.php +++ b/forms/DropdownField.php @@ -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); } /** diff --git a/forms/FieldSet.php b/forms/FieldSet.php index 73ea48d9d..e39b73552 100755 --- a/forms/FieldSet.php +++ b/forms/FieldSet.php @@ -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); diff --git a/forms/PhoneNumberField.php b/forms/PhoneNumberField.php index d2078f8f7..9144f613c 100644 --- a/forms/PhoneNumberField.php +++ b/forms/PhoneNumberField.php @@ -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; } diff --git a/search/SearchContext.php b/search/SearchContext.php index d71873fb5..2ffec4303 100644 --- a/search/SearchContext.php +++ b/search/SearchContext.php @@ -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); + } } ?> \ No newline at end of file