(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@60231 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
Ingo Schommer 2008-08-09 06:29:50 +00:00
parent 0362276b67
commit 4ec93162a0
9 changed files with 91 additions and 22 deletions

View File

@ -1061,7 +1061,7 @@ class DataObject extends ViewableData implements DataObjectInterface {
* Add the scaffold-generated relation fields to the given field set
*/
protected function addScaffoldRelationFields($fieldSet) {
if ($this->has_many() || $this->_many_many()) {
if ($this->has_many() || $this->many_many()) {
$oldFields = $fieldSet;
$fieldSet = new FieldSet(
new TabSet("Root", new Tab("Main"))
@ -1070,22 +1070,42 @@ class DataObject extends ViewableData implements DataObjectInterface {
$fieldSet->addFieldToTab("Root.Main", $field);
}
}
if($this->has_many()) {
// Add each relation as a separate tab
foreach($this->has_many() as $relationship => $component) {
$relationshipFields = singleton($component)->summary_fields();
$relationshipFields = singleton($component)->summaryFields();
$foreignKey = $this->getComponentJoinField($relationship);
$fieldSet->addFieldToTab("Root.$relationship", new ComplexTableField($this, $relationship, $component, $relationshipFields, "getCMSFields", "$foreignKey = $this->ID"));
$ctf = new ComplexTableField(
$this,
$relationship,
$component,
$relationshipFields,
"getCMSFields",
"$foreignKey = $this->ID"
);
$ctf->setPermissions(TableListField::permissions_for_object($component));
$fieldSet->addFieldToTab("Root.$relationship", $ctf);
}
}
if ($this->many_many()) {
foreach($this->many_many() as $relationship => $component) {
$relationshipFields = singleton($component)->summary_fields();
$relationshipFields = singleton($component)->summaryFields();
$filterWhere = $this->getManyManyFilter($relationship, $component);
$filterJoin = $this->getManyManyJoin($relationship, $component);
$tableField = new ComplexTableField($this, $relationship, $component, $relationshipFields, "getCMSFields", $filterWhere, '', $filterJoin);
$tableField->popupClass = "ScaffoldingComplexTableField_Popup";
$fieldSet->addFieldToTab("Root.$relationship", $tableField);
$ctf = new ComplexTableField(
$this,
$relationship,
$component,
$relationshipFields,
"getCMSFields",
$filterWhere,
'',
$filterJoin
);
$ctf->setPermissions(TableListField::permissions_for_object($component));
$ctf->popupClass = "ScaffoldingComplexTableField_Popup";
$fieldSet->addFieldToTab("Root.$relationship", $ctf);
}
}
return $fieldSet;
@ -1319,21 +1339,28 @@ class DataObject extends ViewableData implements DataObjectInterface {
* based on default {@link FormField} mapping in {@link DBField::scaffoldFormField()}
*
* @uses {@link DBField::scaffoldFormField()}
* @param array $fieldClasses Optional mapping of fieldnames to subclasses of {@link DBField}
* @return FieldSet
*/
public function scaffoldFormFields() {
public function scaffoldFormFields($fieldClasses = null) {
$fields = new FieldSet();
$fields->push(new HeaderField($this->singular_name()));
foreach($this->db() as $fieldName => $fieldType) {
// @todo Pass localized title
// 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());
if(isset($fieldClasses[$fieldName])) {
$fieldClass = $fieldClasses[$fieldName];
$fieldObject = new $fieldClass($fieldName);
} else {
$fieldObject = $this->dbObject($fieldName)->scaffoldFormField();
}
$fields->push($fieldObject);
}
foreach($this->has_one() as $relationship => $component) {
$model = singleton($component);
$records = DataObject::get($component);
$collect = ($model->hasMethod('customSelectOption')) ? 'customSelectOption' : current($model->summary_fields());
$collect = ($model->hasMethod('customSelectOption')) ? 'customSelectOption' : current($model->summaryFields());
$options = $records ? $records->filter_map('ID', $collect) : array();
$fields->push(new DropdownField($relationship.'ID', $relationship, $options));
}
@ -2227,7 +2254,7 @@ class DataObject extends ViewableData implements DataObjectInterface {
public function searchable_fields() {
$fields = $this->stat('searchable_fields');
if (!$fields) {
$fields = array_fill_keys(array_keys($this->summary_fields()), 'TextField');
$fields = array_fill_keys(array_keys($this->summaryFields()), 'TextField');
}
return $fields;
}
@ -2239,10 +2266,18 @@ class DataObject extends ViewableData implements DataObjectInterface {
*
* @return array
*/
public function summary_fields() {
public function summaryFields() {
$fields = $this->stat('summary_fields');
// if fields were passed in numeric array,
// convert to an associative array
if($fields && array_key_exists(0, $fields)) {
$fields = array_combine(array_values($fields), array_values($fields));
}
if (!$fields) {
$fields = array();
// try to scaffold a couple of usual suspects
if ($this->hasField('Name')) $fields['Name'] = 'Name';
if ($this->hasField('Title')) $fields['Title'] = 'Title';
if ($this->hasField('Description')) $fields['Description'] = 'Description';

View File

@ -66,7 +66,7 @@ class HTMLText extends Text {
}
public function scaffoldFormField($title = null) {
return new HTMLEditorField($this->name, $title);
return new HtmlEditorField($this->name, $title);
}
public function scaffoldSearchField($title = null) {

View File

@ -12,6 +12,7 @@ class Varchar extends DBField {
$this->size = $size ? $size : 50;
parent::__construct($name);
}
function requireField() {
DB::requireField($this->tableName, $this->name, "varchar($this->size) character set utf8 collate utf8_general_ci");
}

View File

@ -561,12 +561,12 @@ interface DebugReporter {
/**
* Render HTML markup for the header/top segment of debug report.
*/
abstract function writeHeader();
function writeHeader();
/**
* Render HTML markup for the footer and closing tags of debug report.
*/
abstract function writeFooter();
function writeFooter();
}
@ -576,7 +576,7 @@ interface DebugReporter {
*/
class SapphireDebugReporter implements DebugReporter {
function writeHeader() {
public function writeHeader() {
echo '<!DOCTYPE html><html><head><title>'. $_SERVER['REQUEST_METHOD'] . ' ' .$_SERVER['REQUEST_URI'] .'</title>';
echo '<style type="text/css">';
echo 'body { background-color:#eee; margin:0; padding:0; font-family:Helvetica,Arial,sans-serif; }';
@ -595,7 +595,7 @@ class SapphireDebugReporter implements DebugReporter {
echo '<div class="header"><img src="'. Director::absoluteBaseURL() .'cms/images/mainmenu/logo.gif" width="26" height="23"></div>';
}
function writeFooter() {
public function writeFooter() {
echo "</body></html>";
}

View File

@ -47,7 +47,7 @@ class TestRunner extends Controller {
function init() {
parent::init();
if (!self::$default_reporter) self::set_reporter('DebugView');
if (!self::$default_reporter) self::set_reporter('SapphireDebugReporter');
}
/**

View File

@ -896,7 +896,7 @@ class ScaffoldingComplexTableField_Popup extends Form {
protected $dataObject;
public static $allowed_actions = array(
'filter', 'record', 'httpSubmission', 'handleAction'
'filter', 'record', 'httpSubmission', 'handleAction', 'handleField'
);
function __construct($controller, $name, $fields, $validator, $readonly, $dataObject) {

View File

@ -291,6 +291,8 @@ JS
$SQL_limit = ($this->pageSize) ? "{$this->pageSize}" : "0";
if(isset($_REQUEST['ctf'][$this->Name()]['start']) && is_numeric($_REQUEST['ctf'][$this->Name()]['start'])) {
$SQL_start = (isset($_REQUEST['ctf'][$this->Name()]['start'])) ? intval($_REQUEST['ctf'][$this->Name()]['start']) : "0";
} else {
$SQL_start = 0;
}
if(isset($this->customSourceItems)) {
if($this->customSourceItems) {
@ -929,6 +931,29 @@ JS
}
return $idField->Value();
}
/**
* Helper method to determine permissions for a scaffolded
* TableListField (or subclasses) - currently used in {@link ModelAdmin} and {@link DataObject->scaffoldFormFields()}.
* Returns true for each permission that doesn't have an explicit getter.
*
* @todo Temporary method, implement directly in FormField subclasses with object-level permissions.
*
* @param string $class
* @param numeric $id
* @return array
*/
public static function permissions_for_object($class, $id = null) {
$permissions = array();
$obj = ($id) ? DataObject::get_by_id($class, $id) : singleton($class);
if(!$obj->hasMethod('canView') || $obj->canView()) $permissions[] = 'show';
if(!$obj->hasMethod('canEdit') || $obj->canEdit()) $permissions[] = 'edit';
if(!$obj->hasMethod('canDelete') || $obj->canDelete()) $permissions[] = 'delete';
if(!$obj->hasMethod('canCreate') || $obj->canCreate()) $permissions[] = 'add';
return $permissions;
}
@ -1075,6 +1100,7 @@ class TableListField_Item extends ViewableData {
function IsReadOnly() {
return $this->parent->Can('delete');
}
}
?>

View File

@ -17,6 +17,9 @@ ComplexTableField.prototype = {
rules['#'+this.id+' table.data tbody td'] = {onclick: this.openPopup.bind(this)};
Behaviour.register(rules);
// HACK If already in a popup, we can't allow add (doesn't save existing relation correctly)
if(window != top) $$('#'+this.id+' table.data a.addlink').each(function(el) {Element.hide(el);});
},
/**
@ -66,6 +69,10 @@ ComplexTableField.prototype = {
* @param href, table Optional dom object (use for external triggering without an event)
*/
openPopup: function(e, _popupLink, _table) {
// If already in a popup, simply open the link instead
// of opening a nested lightwindow
if(window != top) return true;
var el,type;
var popupLink = "";
if(_popupLink) {

View File

@ -19,15 +19,15 @@ class SearchContextTest extends SapphireTest {
function testSummaryIncludesDefaultFieldsIfNotDefined() {
$person = singleton('SearchContextTest_Person');
$this->assertContains('Name', $person->summary_fields());
$this->assertContains('Name', $person->summaryFields());
$book = singleton('SearchContextTest_Book');
$this->assertContains('Title', $book->summary_fields());
$this->assertContains('Title', $book->summaryFields());
}
function testAccessDefinedSummaryFields() {
$company = singleton('SearchContextTest_Company');
$this->assertContains('Industry', $company->summary_fields());
$this->assertContains('Industry', $company->summaryFields());
}
function testPartialMatchUsedByDefaultWhenNotExplicitlySet() {