7

In Silverstripe 4 a file that is uploaded must be published before it is visible to the public side of the site.

If I create a $Page with a $has_one Image::Class and then also assign that image to $owns[] the uploaded image will be published when I publish the page.

However If I create the following data object structure it will not.

Class Item extends DataObject{
    $has_one[
        'ItemImage'=>Image::Class,
        'Catalog'=>'Catalog'
    ];

    $owns[
        'ItemImage'
    ]
}

Class Catalog extend DataObject{
    $has_many[
        'Items'=>'Item'
    ]
    $owns[
        'Items'
    ]

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

        $fields->addFieldToTab('Root.Items', GridField::create('Items', 'Items', $this->Items(), GridFieldConfig_RecordEditor::create()));

        return $fields;

    }
}

If I create a catalog and within it create items with images and then save it, it will not publish the images that were uploaded. I will have to manually: 1. Select the image 2. Edit Original 3. Publish

There has to be an easier way for the user.

Daniel H.
  • 412
  • 2
  • 12

3 Answers3

4

Your dataobject needs to extend the Versioned extension. Pages already have this in the SiteTree object.

Class Item extends DataObject
{
    private static $has_one = [
        'ItemImage' => Image::Class,
        'Catalog' => 'Catalog'
    ];

    private static $owns = [
        'ItemImage'
    ];

    private static $extensions = [
        Versioned::class . '.versioned'
    ];
}

Edit

The above doesn't actually work for a ModelAdmin, only for objects related to an object that already is 'Versioned' (like SiteTree).
If you want to this from a ModelAdmin you could add the following:

private static $versioned_gridfield_extensions = true;

Which will create a few buttons in your ModelAdmin. After you click publish, the File will publish too.

Fatal Error
  • 1,014
  • 6
  • 12
4

This is currently discussed on GitHub on multiple repositories.

The solution at the moment, is either publish the images manually in onAfterWrite, or version your DataObject, preferably via YML:

My\Data\Object
  extensions:
    - Versioned
Simon Erkelens
  • 762
  • 4
  • 8
  • Why is it preferable to do it in YML as opposed to @Fatal Errors method? – Daniel H. Jan 08 '18 at 16:41
  • 1
    As YML is the primary source for configuration settings for SilverStripe, and PHP is the fallback method. As per the documentation: "SilverStripe comes with a comprehensive code based configuration system through the Config class. It primarily relies on declarative YAML files, and falls back to procedural PHP code, as well as PHP static variables." This means especially performance wise, YML is the better way to go. – Simon Erkelens Jan 10 '18 at 02:34
1

I'm a bit late, but unfortunately $owns still doesn't work on non-versioned DataObjects. I also didn't want to make it versioned, so here's how I am manually publishing them:

<?php

namespace app\foo;

use SilverStripe\ORM\DataObject;
use SilverStripe\Assets\Image;

class Bar extends DataObject {
    private static $has_one = [
        'MyImage' => Image::class
    ];

    protected function onAfterWrite() {
        parent::onAfterWrite();
        $img = $this->MyImage();
        if ($img && $img->exists()) {
            $img->publishRecursive();
        }
    }
}
Zauberfisch
  • 3,690
  • 15
  • 23