SS4.2.2 - Getting $owned Files / Images to unpublish on deletion of parent object


#1

Silverstripe Version: 4.2.2

Question:
Is it possible to unpublish all $owned items when you delete the parent DataObject or Page?

This would be undesirable if the $owned items were used on multiple Objects. But in the cases where they are only used by one DataObject it would be handy to also Unpublish the owned assets.

I would also like it in the “unlink” or detach function in the UploadField would unpublish the asset as well. In SS3 we had a delete button build in. In SS4 this is gone and simply pressing the X on an UploadFiled does nothing to the linked file.

SS4 is making it really difficult to have a nice and tidy file system.

Maybe I have tidy-file OCD, I don’t know, but I see a 1GB of “tidy” assets on an existing website turning into a 2GB messy monster very quickly if I can’t setup some user accessible file controls or a way for admin users to find orphaned files and know if they are used and deal with them effectively.

I have successfully used this code on one DataObject and upgraded it to SS4.

I’m not 100% sure all the deleteFile, destroy and delete are needed as I had to add one of them for SS4 to work compared to the SS3 version of this code. I’ve no idea if it’s the most efficient method but it is working in SS4 and it also tidy’s up any cropped images as well.

Could I use this same idea to “Unpublish” the assets manually?

public function onBeforeDelete(){

if($this->FrontImageID) {
	$myFile = $this->FrontImage();
	$file = DataObject::get_by_id(File::class, $myFile->ID); //we have to make sure it is a Dataobject object
	if ($file) {
		$file->deleteFile();
		$file->destroy();
		$file->delete();
	}
}

}

#2

Okay, I think I’ve solved this one myself so I’m putting the answer up here for others. Maybe it’s a Tips & Tricks though?

public function onBeforeDelete(){
    parent::onBeforeDelete();
    
    if ($this->Image()->exists() && !$this->Image()->isPublished()) {
        $this->Image()->doUnpublish();
    }
}

Just change Image() to BrochureImage() or whatever your owned File / Image is called.

This interestingly moved the file and all cropped / resized __ files over to the .private directory in /assets which is an invisible folder on the file system where all unpublished files live.

I haven’t found an easy way to “view all unpublished” assets yet in the Asset Manger but I’m hopeful there will be away to do that.

Please add to this post below if you have any tips and tricks for “tidy” file management in SS4! Thanks.


#3

If your class with an Image() is used on a belongs many many Page say you can then put a count around the uses of the File / Image if you want to make sure an image isn’t unpublished when it is still used on another page. Handy in a lot of situations.

if ($this->Product()->count()<=1) {

on a belongs many many image

private static $belongs_many_many = array(
	'Product' => Product::class
);