Background Image UploadField doesn't show in the CMS - php

On a SilverStripe CMS website I have a custom footer add-on code that I'd like to extend so I can upload a background image in the CMS. The code seems fine, but the added field is no where to be found in the CMS.
This is my code:
class CustomFooter extends DataExtension {
static $db = array(
'FooterContent' => 'HTMLText'
);
public static $has_one = array(
'Logo' => 'Image',
'BGImage' => 'Background Image'
);
public function getCMSFields() {
$this->extend('updateCMSFields', $fields);
return $fields;
}
public function updateCMSFields(FieldList $fields) {
$fields->addFieldToTab('Root.Footer', new HTMLEditorField('FooterContent', 'Footer Content'));
$fields->addFieldToTab('Root.Main', new UploadField('Logo', 'Company Logo'));
$fields->addFieldToTab('Root.Main', new UploadField('BGImage', 'Background image'));
}
}
Weirdly enough, both image upload fields don't show where as the Content tab show and functions as expected.
Why aren't the UploadFields displaying?

Your
public static $has_one = array(
"Logo"=>"Image",
"BGImage"=>"Background Image"
);
looks pretty weird. The $has_onearray has the relation name as key and the class name of the relation as value, I doubt a classname with space in the name is allowed. So I'd try something like
public static $has_one = array(
"Logo"=>"Image",
"BGImage"=>"Image"
);
then run a dev/build?flush and check in the database if your table has a LogoID column and a BGImageIDcolumn for the has one relations.
The field generation looks ok, it should work as is.

Related

How to change order of items in SilverStripe GridField

I use a GridField in SilverStripe to create HTML section items that are rendered on a page. This works so far but it always displays the sections in the order that I added them to the CMS or rather by the ID it gets when it's created.
So my question is: How can i change that order. I don't want to manually change the IDs but would rather do a simple drag and drop.
Edit: Could the use of Elemental be a solution to this problem?
Screenshot of the CMS view
The Page:
class HomePage extends Page
{
private static $has_many = [
'SectionObjects' => SectionObject::class
];
public function getCMSFields()
{
$fields = parent::getCMSFields();
$fields->addFieldToTab('Root.Sections',
$grid = GridField::create('SectionObjects', 'Sections', $this->SectionObjects(), GridFieldConfig_RecordEditor::create())
);
$config = $grid->getConfig();
$dataColumns = $config->getComponentByType(GridFieldDataColumns::class);
$dataColumns->setDisplayFields([
'ID' => 'ID',
'LastEdited' => 'Changed'
]);
return $fields;
}
}
The Section object
class SectionObject extends DataObject{
private static $db = [
'Content' => 'Text',
'BgColor' => Color::class
];
private static $has_one = [
'HomePage' => HomePage::class
];
public function getCMSFields(){
return new FieldList(
TextareaField::create('Content','SectionContent'),
ColorField::create('BgColor', 'Hintergrundfarbe')
);
}
}
Definitely using the elemental module would allow you to have the kind of behaviour you want - but if you don't want to go to the effort of refactoring your code to comply with that module, you could use either the gridfieldextensions or sortablegridfield module to allow you to sort the gridfield (with drag and drop) to your heart's content.

silverstripe-translatable: how to make dataobjects translatable (slideshow)?

I am creating a multilingual Website in Silverstripe, the goal is to have the whole content available in three languages. I am using the translatable module, works fine for now.
Some pages contains a slideshow, meaning that I am associating a bunch of images and captions to these pages. Looks like this:
class Slide extends DataObject {
private static $db = array(
'Caption' => 'Varchar(255)',
'SortIndex' => 'Int'
);
private static $has_one = array(
'ParentPage' => 'Page',
'Image' => 'Image'
);
public static $default_sort = 'SortIndex';
public function getCMSFields() {
// parent::getCMSFields() does all the hard work and creates the fields for Title, IsActive and Content.
$fields = parent::getCMSFields();
$fields->dataFieldByName('Caption')->setTitle('Titel');
$fields->dataFieldByName('Image')->setTitle('Bild');
$fields->dataFieldByName('Index')->setTitle('Reihenfolge');
$fields->push(new TextField('Caption', 'Titel'));
$fields->push(new UploadField('Image', 'Profile Image'));
// Apply Translatable modifications
$this->applyTranslatableFieldsUpdate($fields, 'updateCMSFields');
return $fields;
}
}
class SlideShowPage extends Page {
private static $has_many = array(
'Slides' => 'Slide'
);
public function getCMSFields() {
$fields = parent::getCMSFields();
$conf = GridFieldConfig_RelationEditor::create(10);
$conf->addComponent(new GridFieldSortableRows('SortIndex'));
$fields->addFieldToTab('Root.Slideshow', new GridField('Slide', 'Slides', $this->Slides(), $conf));
// Apply Translatable modifications
$this->applyTranslatableFieldsUpdate($fields, 'updateCMSFields');
return $fields;
}
}
I want to make these slideshows translatable as well. Meaning that I want to prepare the slide show once in the primary language, then hit the "create new translation" button, and get the slideshow available in the translated version as well, with the captions ready to be translated (similar as the main text content). According to the silverstripe-translatable docs this shall be possible. I have added these calls to applyTranslatableFieldsUpdate() (see in the code above) and added these lines to my _config.php file as well:
SlideShowPage::add_extension('Translatable');
Slide::add_extension('Translatable');
The table Slide_translationgroups is even created successfully and filled with new entries for each translation. But the content of table Slide is not copied.
What am I missing?
Thanks!
Sacher

Custom Silverstripe Meta Field not saving

I created a Meta Title using the code below but it works for majority of my websites but one particular website will not save the the Meta Title so when I edit it shows my previously entered title, same code for all websites but one is not saving?
class Page extends SiteTree {
private static $db = array(
'MetaTitle' => 'Varchar(255)'
);
private static $has_one = array(
);
public function getCMSFields() {
$fields = parent::getCMSFields();
$fields->addFieldToTab('Root.Main', TextField::create('MetaTitle')
->setRightTitle('Shown at the top of the browser window and used as the "linked text" by search engines.')
->addExtraClass('help')
, 'MetaDescription');
return $fields;
}
}
If you do not /dev/build after adding a new $db property, changes will not save properly.

Trying to remove/hide fields in custom tab in SilverStripe

I am trying to figure out a way (if possible) to remove or hide certain fields in a custom tab. The custom tab is labeled "Rotator" and it holds images that can be used for a rotating banner on a page. The home page banner is a little different in that it has 2 extra fields that aren't needed on the subpages: BackgroundImage and Body(which is meant to hold a variety of text). I want to make things simple for the content manager, so I want to hide these fields on the subpages.
I am aware of removeFieldFromTab and how it works, and I was thinking of using it on the Page.php file (since that is basically the main template for all page types in my SilverStripe file):
public function getCMSFields() {
$fields = parent::getCMSFields();
$gridFieldConfig = GridFieldConfig_RecordEditor::create();
$gridFieldConfig->addComponent(new GridFieldBulkImageUpload());
$gridFieldConfig->addComponent(new GridFieldSortableRows('SortOrder'));
$gridFieldConfig->getComponentByType('GridFieldDataColumns')->setDisplayFields(array(
// field from drawer class => label in UI
'ID' => 'ID',
'Title' => 'Title',
'Thumbnail' => 'Thumbnail',
'InternalURL.Link' => 'Internal URL',
));
$gridfield = new GridField(
"Rotator",
"Rotator",
$this->Rotator()->sort("SortOrder"),
$gridFieldConfig
);
$fields->addFieldToTab('Root.Rotator', $gridfield);
$fields->addFieldToTab("Root.Main", new TextField("H1"), "Content");
$fields->addFieldToTab("Root.Main", new TextField("Subheader"), "Content");
$fields->addFieldToTab('Root.Main', new TextField('PageTitle', 'Page Title'), 'MetaDescription');
$fields->removeFieldFromTab('Root.Rotator', 'Body');
$fields->removeFieldFromTab('Root.Rotator', 'BackgroundImage');
return $fields;
}
Here is the code for the Rotator class:
<?php
class RotatorImage extends DataObject {
public static $db = array(
'SortOrder' => 'Int',
'Header' => 'varchar',
'Body' => 'HTMLText',
);
// One-to-one relationship with gallery page
public static $has_one = array(
'Image' => 'Image',
'BackgroundImage' => 'Image',
'Page' => 'Page',
'InternalURL' => 'SiteTree',
);
// tidy up the CMS by not showing these fields
public function getCMSFields() {
$fields = parent::getCMSFields();
$fields->removeFieldFromTab("Root.Main","PageID");
$fields->removeFieldFromTab("Root.Main","SortOrder");
return $fields;
}
// Tell the datagrid what fields to show in the table
public static $summary_fields = array(
'ID' => 'ID',
'Title' => 'Title',
'Thumbnail' => 'Thumbnail',
'InternalURLID' => 'Internal URL',
);
// this function creates the thumnail for the summary fields to use
public function getThumbnail() {
return $this->Image()->CMSThumbnail();
}
public function canEdit() {
return true;
}
public function canDelete() {
return true;
}
public function canCreate(){
return true;
}
public function canPublish(){
return true;
}
public function canView(){
return true;
}
}
However this does not work, and I am sure that I have the fields names correct. I tried 'Root.Rotator.Main' and 'Root.Rotator.Content' just to see what would happen and those also did not work. What am I missing? Is it possible to hide fields on a custom tab this way, or do I need to try something else?
well, you want to hide the fields in the gridfield detail form? that cannot be done in your pages getCMSFields(), as the grid is responsible for generating the detail form. Two possible solutions:
1) tell the grid to hide that fields with a custom component. I dunno how to do it
2) tell your Rotator class to show the fields ONLY if the related page is a homepage:
public function getCMSFields() {
$fields = parent::getCMSFields();
//...other stuff....
$isOnHomePage = ($this->Page() && $this->Page()->ClassName == 'HomePage'); //put in your own classname or conditions
if(!$isOnHomePage) {
//remove the fields if you're not on the HomePage
$fields->removeByName('Body');
//we need to suffix with "ID" when we have a has_one relation!
$fields->removeByName('BackGroundImageID');
}
return $fields;
}
This will work...
$fields->removeByName('FieldName');

How to add many files with silverstripe uploadfield

Hello everyone,
I'm trying to add more than 1 file to my uploadfield with this code ->
class FileDo extends File {
static $has_one = array(
'DocumentsFile' => 'DocumentsFile',
);
}
class DocumentsFile extends DataObject {
static $has_one = array(
'DocumentPageAcces1' => 'DocumentPageAcces1'
);
static $has_many = array(
'Files' => 'FileDo'
);
public function getCMSFields() {
$fields = parent::getCMSFields();
$fields->removeByName('DocumentPageAcces1ID');
return $fields;
}
public function onBeforeWrite() {
parent::onBeforeWrite();
$page = DataObject::get_one('DocumentPageAcces1');
if($page) {
$this->DocumentPageAcces1ID = $page->ID;
}
}
}
class DocumentPageAcces1 extends Page {
static $has_many = array(
'DocumentsFiles' => 'DocumentsFile',
);
public function getCMSFields() {
$fields = parent::getCMSFields();
$fields->addFieldToTab('Root.Main', new TextareaField('DocumentsIntro_en', "Document Introduction"));
$fields->addFieldToTab('Root.Main', new TextareaField('PublicationsIntro_en', "Publication Introduction"));
$fields->addFieldToTab('Root.FR', new TextareaField('DocumentsIntro_fr', "Document Introduction"));
$fields->addFieldToTab('Root.FR', new TextareaField('PublicationsIntro_fr', "Publication Introduction"));
$fields->addFieldToTab('Root.NL', new TextareaField('DocumentsIntro_nl', "Document Introduction"));
$fields->addFieldToTab('Root.NL', new TextareaField('PublicationsIntro_nl', "Publication Introduction"));
$upload = new UploadField(
'DocumentsFile',
'Document',
$this->DocumentsFiles()
);
$fields->addFieldToTab('Root.DocumentsFile', $upload);
$fields->removeByName('Content');
$fields->removeByName('Metadata');
return $fields;
}
}
class DocumentPageAcces1_Controller extends Page_Controller {
}
So to make it clear: i'm trying to add some DocumentFile in my DocumentPageAcces1. When i execute this code, i have in my DocumentPageAcces1 the tab DocumentsFiles and in this tab i have the uploadfield.
THE PROBLEM is that the uploadfield doesn't want to keep my file so when i chose some file, i click OK in my finder and nothing happens......Could anyone help me?
Thanks Thomas.
UploadField isn't made to work with DataObjects but like you found with File or it's subclasses.
Although in your case, I don't think you need a subclass, so you could just remove your DocumentFileDo class that extend File and use this in your DocumentPageAcces1.php
static $has_many = array(
'DocumentFiles' => 'File',
);
In the case you want to have more control/details on the files you upload (i.e. add descriptions, titles etc...), in that case you can create a DataObject that has a $has_one relation to a File and then use that DataObject in the relation on your page with a GridField:
DocumentFile.php
class DocumentFile extend DataObject
{
static $db = array(
'Description' => 'HTMLText'
);
static $has_one = array(
'File' => 'File'
);
}
DocumentPageAcces1.php
static $has_many = array(
'DocumentFiles' => 'DocumentFile'
);
function getCMSFields()
{
$fields = parent::getCMSFields();
$c = new GridFieldConfig_RelationEditor();
$f = new GridField('Documents', 'DocumentFiles', $this->DocumentFiles(), $c);
$fields->addFieldToTab('Root.Documents', $f);
return $fields;
}
After some hours I found a solution, maybe it's not the best one but it works for me ->
I created a class that extends the File class for each document type i need so I have for example
class DocumentFileDo extends File {
static $has_one = array(
'DocumentPageAcces1' => 'DocumentPageAcces1'
);
}
In my DocumentPageAcces1.php I have a has_many relationship like this :
static $has_many = array(
'DocumentFileDos' => 'DocumentFileDo',
);
And I the getCMSFields function I have :
$fields->addFieldToTab('Root.Document', new UploadField('DocumentFileDos'));
It works well, you can add many file with just a has_many relationship and an UploadField. But it's not the best i think if you have a hundred different documents type..
PS: With UploadField you can drag and drop files but this function which works well on Chrome does not on Firefox!
I just struggled with the same thing. SilverStripe even has a (faulty*) developer guide on this matter (though it took me hours to find it) … Anyway, I found a solution. (assuming SilverStripe 4)
mysite/page/MyCustomPage.php
class MyCustomPage extends Page
{
private static $many_many = array(
'DocumentFiles' => File::class
);
public function getCMSFields(){
$fields = parent::getCMSFields();
$fields->addFieldToTab('Root.Main',
UploadField::create('DocumentFiles', 'My Documents')
);
return $fields;
}
}
mysite/extensions/DocumentFileExtension.php
class DocumentFileExtension extends DataExtension
{
private static $belongs_many_many = array(
'DocumentContainers' => MyCustomPage::class
);
// I actually don't know the purpose of the name "DocumentContainers"
// ("Galleries" in the guide); it is never referenced again.
}
mysite/_config/app.yml
SilverStripe\Assets\File:
extensions:
- DocumentFileExtension
themes/mytheme/templates/Layout/MyCustomPage.ss
<% loop $DocumentFiles %>
$Link
<% end_loop %>
You basically extend the native File class into a custom version of it, and "suddenly" the unchanged UploadField (that also does the same for single files) now allows multiple files; complete with a GUI and everything.
Hope this works for you.
* They keep using 'Foo' => 'Bar' all over their official documentation pages instead of 'Foo' => Bar::class, which you have to use in ss4 in order to avoid an Exception:
Uncaught InvalidArgumentException: many_many relation SilverStripe\Blog\Model\BlogPost.DownloadFiles references class File which doesn't exist

Categories