0
votes

I am looking to make a DataObject class which injects fields into a Page object but I'm having a bit of trouble doing so. The only solutions I've found so far require me to do something within the Page (other than adding in a relationship between the two classes), I'm not all that certain as to what I'm doing wrong...

What I need would be for the DataObject to add a tab and some fields within Page and have the data for that Page to save to the DataObjects table.

In a sense I would like them to be somewhat independent of each other, so that I can link it to Article now and then some other page types at some later date.

This is what I have so far :

Article.php

 class Article extends Page {

     private static $description = 'An article page for writing and posting content';

     private static $has_many = array(
         'MyExtraFields' => 'MyExtraFields'
     );
 }

The DataObject

 class MyExtraFields extends DataObject {

     private static $db = array(
         'ExtraText' => 'Varchar(255)',
         'ExtraWYSIWYG' => 'HTMLText'
     );

     private static $has_many = array(
         'Article' => 'Article'
     );

     private static $summary_fields = array(
         'ExtraText' => 'ExtraText',
         'ExtraWYSIWYG' => 'ExtraWYSIWYG'
     );

     public function updateCMSFields(){

         $fields = parent::getCMSFields();

         $fields->addFieldsToTab('Root.Content.Translation', array(
             TextField::create('ExtraText'),
             HTMLEditorField::create('ExtraWYSIWYG')
             )
         );

         return $fields;
     }
 }
1
What is the goal exactly? Just add two additional fields to Page? If that's the case, just add them to the page directly? Or via an extension if you need to apply them to different pages. If you want to be able to add 0 - N ExtraFields to a Page, that's basically a content-blocks module (there are several existing modules for that purpose) - bummzack
In the class ExtraFields (I would rename that one to ExtraField, as each object only contains one), you have a has_many to the article page, which should be a has_one. If you want to make a many-many, then you should create a many_many relation on one side, and a belongs_many_many on the other (but that is not what you are trying to achieve I guess...) - jberculo

1 Answers

1
votes

If I understand it correctly, you want to be able to add the DataObject MyExtraField to the Pagetype Article. If the MyExtraField is dependent on the Article, then you need to change the Relation of the ExtraField to has_one like jberculo says:

class MyExtraField extends DataObject {

    ...

    private static $has_one = array(
        'Article' => 'Article'
    );
}

Then you have to add a GridField to the Article's CMS view manage the DataObject:

class Article extends Page {

    ...
    private static $has_many = array(
        'MyExtraFields' => 'MyExtraField'
    );

    public function getCMSFields() {
        $fields = parent::getCMSFields();

        $gridFieldConfig = GridFieldConfig_RecordEditor::create();
        $gridfield = new GridField( "MyExtraFields", "MyExtraField", $this->MyExtraField(), $gridFieldConfig );
        $fields->addFieldToTab( 'Root.ExtraFields', $gridfield );
        return $fields;
    }

If you want to reuse the DataObject in different Articles, you need to use a many to many relation and a different GridField-Configuration:

 $gridFieldConfig = GridFieldConfig_RelationEditor::create();

You will find the documentation of GridField here:

https://docs.silverstripe.org/en/3.4/developer_guides/forms/field_types/gridfield

If you want to manage has_one relation to be able to add just one optional instance of MyExtraField, you could use:

https://github.com/burnbright/silverstripe-hasonefield