ModelAdmin: How to get a CMS edit link url for a specific DataObject?


#1

Silverstripe Version: 4.3

Question:

Hi, I have created a ModelAdmin for let’s say a class called Library. Each Library has multiple Book instances. In the CMS I have a button in the left menu called Libraries. When I click on it, I will see a list of libraries, and when I click on a library, I can see a tab called Books which lists all the books. When I click on a book, I can edit/view details of a specific book. Quite a basic scenario.

What would be the most simplest way to generate the same URL to a specific Book page in PHP code? The link creating should be chainable so that it includes the URL for a library in the middle (and also makes it possible to extend the link even more if the books will have new relations in the future, for example pages).

So far I have created a new method called EditLink() for each of my DataObject and pasted the link there manually.

Here is a pseudo code which I haven’t tested but you get the idea what I’m talking about.

<?php

use SilverStripe\Admin\ModelAdmin;
use SilverStripe\ORM\DataObject;

class Library extends DataObject
{
	private static $table_name = 'Library';
	
	private static $has_many = [
		'Books' => Book::class,
	];
	
	public function EditLink($action = 'edit')
	{
		// This should be improved
		$library_admin = new LibraryAdmin;
		return $library_admin->Link('Library/EditForm/field/Library/item/' . $this->ID . '/' . $action);
	}
}

class Book extends DataObject
{
	private static $table_name = 'Book';
	
	private static $has_one = [
		'Library' => Library::class,
	];
	
	public function EditLink($action = 'edit')
	{
		// This should be improved
		return $this->Library()->EditLink('ItemEditForm/field/Books/item/' . $this->ID . '/' . $action);
	}
}

class LibraryAdmin extends ModelAdmin
{
	private static $menu_title = 'Libraries';
	
	private static $url_segment = 'libraries';
	
	private static $managed_models = [
		Library::class
	];
}

Thank you for your support! :slight_smile:


#6

Just for the record: I’ve now started to make a module for this: GitHub - Taitava/silverstripe-cmseditlink

It still needs testing and development.


#7

Nice, I will definitely keep an eye on this module (I have had to do this a lot recently)!

Just out of curiosity, does the module need to require “taitava/swiftmailer-imapsentfolder”?


#2

You are probably looking for

public function CMSEditLink() {
   // make correct link to your CMS page
}

#8

Whoops, no it does not require “taitava/swiftmailer-imapsentfolder” :D. I copied composer.json from my another module and forgot to remove that one. I’m actually not surprised if there are some other weird things too - I made it very quickly and haven’t yet even used it anywhere. I’ll improve it in a few days I hope :).


#3

Hi,

in which class is CMSEditLink() defined? I couldn’t find anything relevant when searching for CMSEditLink methods in PhpStorm.

Or do you mean that I should define this method in my DataObject classes? In that case I don’t think it will solve the problem as I don’t know what to put in that method :).

Thanks anyway! :slight_smile:


#4

I generally find you have to do this yourself, an example of getCMSEditLink that I have used is:

    public function getCMSEditLink()
    {
        $admin = Injector::inst()->get(MyModelAdmin::class);

        // Classname needs to be passeed as an action to ModelAdmin
        $classname = str_replace('\\', '-', $this->ClassName);

        return Controller::join_links(
            $admin->Link($classname),
            "EditForm",
            "field",
            $classname,
            "item",
            $this->ID,
            "edit"
        );
    }

#5

Thanks for this tip! :slight_smile:

I’m starting to think about that this would make a good new module - although a rather small one for just a simple feature. Controller::join_links() is already a step towards a more cleaner solution than what I have been using so far. Now I just need to plan how to implement the “chaining” feature that I mentioned above (= I’ll think about the easiest way to define a kind of notation for "get URL for this Book via its Library"). Maybe I should also take a look at how GridField scaffolds links to editable records.