Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIX / DOC Add support ElementalArea in DataObject #978

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
"silverstripe/vendor-plugin": "^1"
},
"require-dev": {
"silverstripe/recipe-testing": "^2"
"silverstripe/recipe-testing": "^2",
"silverstripe/frameworktest": "4.x-dev"
},
"suggest": {
"silverstripe/elemental-blocks": "Adds a set of common SilverStripe content block types",
Expand Down
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 the `CMSEditLink()` method in the class.\
`BaseElement::CMSEditLink()` relies on a valid CMS link being available in the parent `DataObject` - in this case, `BlogPost`. It is used to navigate directly to the editing section of the particular element.\
***Note:*** For nested `GridField`s this method can get more complicated. Similarly, if your class is used in multiple admins, you will have to choose one to be the canonical admin section for the purposes of this method. This example only shows the simplest case, where the `BlogPost` class is used directly in `BlogPostsAdmin`.

```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)
82 changes: 58 additions & 24 deletions src/Models/BaseElement.php
Original file line number Diff line number Diff line change
Expand Up @@ -243,13 +243,18 @@ public function canEdit($member = null)
public function canDelete($member = null)
{
$extended = $this->extendedCan(__FUNCTION__, $member);

if ($extended !== null) {
return $extended;
}

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 +573,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 +585,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 @@ -638,9 +643,10 @@ public function getAnchor()
*/
public function AbsoluteLink($action = null)
{
if ($page = $this->getPage()) {
$page = $this->getPage();

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

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

return $link;
Expand All @@ -657,9 +663,10 @@ public function AbsoluteLink($action = null)
*/
public function Link($action = null)
{
if ($page = $this->getPage()) {
$link = $page->Link($action) . '#' . $this->getAnchor();
$page = $this->getPage();

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

return $link;
Expand Down Expand Up @@ -712,35 +719,62 @@ 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();
sabina-talipova marked this conversation as resolved.
Show resolved Hide resolved

$link = null;
sabina-talipova marked this conversation as resolved.
Show resolved Hide resolved

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 instanceof SiteTree) {
$link = $page->CMSEditLink();
} elseif (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;
sabina-talipova marked this conversation as resolved.
Show resolved Hide resolved
}

Expand Down
Loading