Robbie Averill Robbie Averill - 5 months ago 8
PHP Question

Find whether an Image is used anywhere

In my SilverStripe 3.4 environment I have a bunch of different models that have an attached Image, e.g.:


  • BlogPost
    has_one
    Image
    (via silverstripe/blog)

  • Widget
    has_one
    Image
    (via silverstripe/widgets)

  • MyWidget
    has_one
    Image
    (custom module)



I want to prevent an Image e.g. ID 123 from being deleted in the CMS admin if it's used in any of the above (as examples - this should be system wide).

Is there a way that I can check all models that have a related Image at once, maybe via a
Image belongs_many_many
lookup or something?

Answer

You'd prob need to decorate Image via a DataExtension subclass and declare a $belongs_to static array with a custom onBeforeDelete() or possibly validate().

Regardless, within either is where you'd call a routine that checks your database for the necessary conditions. Your choice of which method to use is dictated by the scenarios under which an Image record might be deleted in your system (e.g you may have some automated, non-Human tasks where the scenario you wish to avoid is played out - so you'd avoid validate() and use onBeforeDelete())

Something like this (Totally untested!)

class MyImageExtension extends DatExtension
{

    public function onBeforeDelete()
    {
        if (!$this->imagesExistThatShouldNotBeDeleted()) {
            parent::onBeforeDelete();
        }
    }

    /**
     * @return boolean True if images exist that shouldn't be deleted, false otherwise.
     */
    private function imagesExistThatShouldNotBeDeleted()
    {
        $owner = $this->getOwner();
        $dataObjectSubClasses = ClassInfo::getValidSubClasses('DataObject');
        $classesWithImageHasOne = [];
        foreach ($dataObjectSubClasses as $subClass) {
            if ($classHasOneImage = $subClass::create()->hasOneComponent('Image')) {
                $classesWithImageHasOne[] = $classHasOneImage;
            }
        }

        if (in_array($owner->class, $classesWithImageHasOne)) {
            return true;
        }

        return false;
    }

}
Comments