Skip to content

Commit

Permalink
CMSEditLink method modified to support DataObject links and Example o…
Browse files Browse the repository at this point in the history
…f using ElemenatalArea with DataObject
  • Loading branch information
Sabina Talipova committed May 4, 2022
1 parent e2b8f18 commit 28c171e
Show file tree
Hide file tree
Showing 7 changed files with 387 additions and 31 deletions.
111 changes: 111 additions & 0 deletions docs/en/examples/elementalarea_with_dataobject.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Using ElementalArea with DataObject

## Creating Model and adding ElementalArea

In this example the class `BlogPost` will be created, it will extend the `DataObject` class. Also a new `BlogPost` Admin section will be created in the Admin panel where CMS users can manage the `BlogPost` objects.

Let's look at an example:

**app/src/Admins/BlogPostsAdmin.php**

```php
<?php

namespace App\Admins;

use App\Models\BlogPost;
use SilverStripe\Admin\ModelAdmin;

class BlogPostsAdmin extends ModelAdmin
{
private static string $url_segment = 'blog-posts-admin';

private static string $menu_title = 'Blog Posts';

private static string $menu_icon_class = 'font-icon-block-banner';

private static array $managed_models = [
BlogPost::class,
];
}
```

`$managed_models` - this static variable connects `BlogPostAdmin` with `BlogPost`, which will be created in the following code.\
When you create a `DataObject` you should define the connection between your `DataObject` and `ElementalArea` by adding `$has_one` relationship.\
In this example `BlogPost` will have one `ElementalArea`.

**app/src/Models/BlogPost.php**

```php
<?php

namespace App\Models;

use App\Admins\BlogPostsAdmin;
use DNADesign\Elemental\Models\ElementalArea;
use SilverStripe\Control\Controller;
use SilverStripe\ORM\DataObject;
use SilverStripe\Versioned\Versioned;

class BlogPost extends DataObject
{
private static string $table_name = 'BlogPost';

private static $has_one = [
'ElementalArea' => ElementalArea::class,
];

private static $owns = ['ElementalArea'];

// ...
}
```

If you are using `ElementalArea` together with `DataObject`, it is important to define a following method in the class.\
The `CMSEditLink()` method should be defined to generate a link for opening the editing section of the particular `BlogPost`.\
`BaseElement` uses a link, that was created in `CMSEditLink()` method in `BlogPost` class, to generate new links for opening the editing section of the particular element.

```php
// ...

class BlogPost extends DataObject
{
// ...

public function CMSEditLink()
{
// In this example we use BlogPostsAdmin class as Controller
$admin = BlogPostsAdmin::singleton();

// Makes link more readable. Instead App\Models\ BlogPost, we get App-Models-BlogPost
$sanitisedClassname = str_replace('\\', '-', $this->ClassName);

// Returns link to editing section with elements
return Controller::join_links(
$admin->Link($sanitisedClassname),
'EditForm/field/',
$sanitisedClassname,
'item',
$this->ID,
);
}

// ...
}

```

And finally, add `ElementalAreasExtension` to the `DataObject`

**app/_config/elemental.yml**

```yml
App\Models\BlogPost:
extensions:
- DNADesign\Elemental\Extensions\ElementalAreasExtension
```
## Related Documentation
* [Preview](https://docs.silverstripe.org/en/4/developer_guides/customising_the_admin_interface/preview/)\
(note that this requires at least `silverstripe/admin` 4.11.0 and `dnadesign/silverstripe-elemental` 4.9.0)
96 changes: 66 additions & 30 deletions src/Models/BaseElement.php
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,11 @@ public function canDelete($member = null)

if ($this->hasMethod('getPage')) {
if ($page = $this->getPage()) {
return $page->canArchive($member);
if ($page->hasExtension(Versioned::class)) {
return $page->canArchive($member);
} else {
return $page->canDelete($member);
}
}
}

Expand Down Expand Up @@ -568,7 +572,8 @@ public function getSimpleClassName()
}

/**
* @return null|SiteTree
* Despite the name of the method, getPage can return any type of DataObject
* @return null|DataObject
* @throws \Psr\Container\NotFoundExceptionInterface
* @throws \SilverStripe\ORM\ValidationException
*/
Expand All @@ -579,7 +584,6 @@ public function getPage()
return $this->cacheData['page'];
}


$class = DataObject::getSchema()->hasOneComponent($this, 'Parent');
$area = ($this->ParentID) ? DataObject::get_by_id($class, $this->ParentID) : null;
if ($area instanceof ElementalArea && $area->exists()) {
Expand Down Expand Up @@ -639,11 +643,12 @@ public function getAnchor()
public function AbsoluteLink($action = null)
{
if ($page = $this->getPage()) {
$link = $page->AbsoluteLink($action) . '#' . $this->getAnchor();

$this->extend('updateAbsoluteLink', $link);

return $link;
if (ClassInfo::hasMethod($page, 'AbsoluteLink')) {
$link = $page->AbsoluteLink($action) . '#' . $this->getAnchor();
$this->extend('updateAbsoluteLink', $link);

return $link;
}
}

return null;
Expand All @@ -658,11 +663,12 @@ public function AbsoluteLink($action = null)
public function Link($action = null)
{
if ($page = $this->getPage()) {
$link = $page->Link($action) . '#' . $this->getAnchor();

$this->extend('updateLink', $link);
if (ClassInfo::hasMethod($page, 'Link')) {
$link = $page->Link($action) . '#' . $this->getAnchor();
$this->extend('updateLink', $link);

return $link;
return $link;
}
}

return null;
Expand Down Expand Up @@ -712,35 +718,65 @@ public function CMSEditLink($directLink = false)
return $this->cacheData['cms_edit_link'];
}

$link = $this->getElementCMSLink($directLink);
$this->extend('updateCMSEditLink', $link);

if ($link) {
$this->cacheData['cms_edit_link'] = $link;
}

return $link;
}

/**
* @param bool $directLink
* @return null|string
*/
private function getElementCMSLink(bool $directLink)
{
$relationName = $this->getAreaRelationName();
$page = $this->getPage();

$link = null;

if (!$page) {
$link = null;
$this->extend('updateCMSEditLink', $link);
return $link;
}

if (!$page instanceof SiteTree && method_exists($page, 'CMSEditLink')) {
$link = Controller::join_links($page->CMSEditLink(), 'ItemEditForm');
} else {
// If $page is a Page
if ($page instanceof SiteTree) {
$link = $page->CMSEditLink();
} else {
// Envoke method only if it exists in the $page
if (ClassInfo::hasMethod($page, 'CMSEditLink')) {
$link = Controller::join_links($page->CMSEditLink(), 'ItemEditForm');
}
}

// In-line editable blocks should just take you to the page. Editable ones should add the suffix for detail form
// In-line editable blocks should just take you to the page.
// Editable ones should add the suffix for detail form.
if (!$this->inlineEditable() || $directLink) {
$link = Controller::join_links(
singleton(CMSPageEditController::class)->Link('EditForm'),
$page->ID,
'field/' . $relationName . '/item/',
$this->ID,
'edit'
);
if ($page instanceof SiteTree) {
return Controller::join_links(
singleton(CMSPageEditController::class)->Link('EditForm'),
$page->ID,
'field',
$relationName,
'item',
$this->ID,
'edit'
);
} else {
// If $page is not a Page, then generate $link base on $page->CMSEditLink()
return Controller::join_links(
$link,
'field',
$relationName,
'item',
$this->ID,
'edit'
);
}
}

$this->extend('updateCMSEditLink', $link);

$this->cacheData['cms_edit_link'] = $link;
return $link;
}

Expand Down
80 changes: 79 additions & 1 deletion tests/BaseElementTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@
use DNADesign\Elemental\Models\BaseElement;
use DNADesign\Elemental\Models\ElementalArea;
use DNADesign\Elemental\Models\ElementContent;
use DNADesign\Elemental\Tests\Src\TestDataObject;
use DNADesign\Elemental\Tests\Src\TestElement;
use DNADesign\Elemental\Tests\Src\TestElementDataObject;
use DNADesign\Elemental\Tests\Src\TestDataObjectWithCMSEditLink;
use DNADesign\Elemental\Tests\Src\TestPage;
use Page;
use ReflectionClass;
use SilverStripe\Control\Director;
use SilverStripe\Core\Config\Config;
use SilverStripe\Dev\FunctionalTest;
Expand All @@ -18,17 +22,29 @@

class BaseElementTest extends FunctionalTest
{
protected static $fixture_file = 'ElementalPageExtensionTest.yml';
protected static $fixture_file = [
'ElementalPageExtensionTest.yml',
'ElementalAreaDataObjectTest.yml'
];

protected static $required_extensions = [
Page::class => [
ElementalPageExtension::class,
],
TestDataObject::class => [
ElementalPageExtension::class,
],
TestDataObjectWithCMSEditLink::class => [
ElementalPageExtension::class,
],
];

protected static $extra_dataobjects = [
TestPage::class,
TestElement::class,
TestDataObject::class,
TestDataObjectWithCMSEditLink::class,
TestElementDataObject::class,
];

public function testSimpleClassName()
Expand Down Expand Up @@ -236,4 +252,66 @@ public function testOnBeforeWriteNoParent()

$this->assertEquals(0, (int) $element1->Sort);
}

public function getElementCMSLinkDataProvider()
{
return [
// Element in DataObject with $directLink === true
'element1' => [
TestElement::class,
'elementDataObject1',
'http://localhost/test/1/ItemEditForm/field/ElementalArea/item/4/edit',
true
],
// Element in DataObject with $inline_editable = false
'element2' => [
TestElementDataObject::class,
'testElementDataObject1',
'http://localhost/test/1/ItemEditForm/field/ElementalArea/item/5/edit',
],
// Element in DataObject with $inline_editable = true
'element3' => [
ElementContent::class,
'contentDataObject1',
'http://localhost/test/1/ItemEditForm',
],
// Element in Page with $inline_editable = true
'element4' => [
ElementContent::class,
'content1',
'http://localhost/admin/pages/edit/show/1',
],
// Element in DataObject with $directLink === true
'element5' => [
ElementContent::class,
'content1',
'admin/pages/edit/EditForm/1/field/ElementalArea/item/1/edit',
true
],
// Element without any Page or DataObject
'element6' => [
ElementContent::class,
'contentDataObject2',
null
],
// DataObject without CMSEditLink method
'element7' => [
TestElement::class,
'elementDataObject2',
null
],
];
}

/**
* @dataProvider getElementCMSLinkDataProvider
*/

public function testCMSEditLink(string $class, string $element, ?string $link, bool $directLink = false)
{
$object = $this->objFromFixture($class, $element);
$editLink = $object->CMSEditLink($directLink);

$this->assertEquals($link, $editLink);
}
}
Loading

0 comments on commit 28c171e

Please sign in to comment.