Skip to content

Commit

Permalink
NEW Allowed link types
Browse files Browse the repository at this point in the history
  • Loading branch information
Sabina Talipova committed Dec 12, 2023
1 parent 7f65d4f commit 421a198
Show file tree
Hide file tree
Showing 24 changed files with 367 additions and 406 deletions.
72 changes: 72 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,78 @@ class ExternalLinkExtension extends Extension

```

The user can control and specify the links allowed for creation in each link field. The `setAllowedTypes` method only includes link types that have been provided as parameters.

```php
<?php
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\LinkField\ORM\DBLink;
use SilverStripe\LinkField\Models\Link;
use SilverStripe\LinkField\Form\LinkField;
use SilverStripe\LinkField\Form\MultiLinkField;
use SilverStripe\LinkField\Models\FileLink;
use SilverStripe\LinkField\Models\SiteTreeLink;

class Page extends SiteTree
{
...

public function getCMSFields()
{
$fields = parent::getCMSFields();

...

$fields->addFieldsToTab(
'Root.Main',
[
MultiLinkField::create('HasManyLinks')
->setAllowedTypes([ SiteTreeLink::class ]),
],
);

return $fields;
}
}
```


Additionally, users have the option to designate links for exclusion from the available choices in the specific field. The setDisabledTypes method omits link types provided as parameters from the complete list of link types.
By default, all types of links are available.

```php
<?php
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\LinkField\ORM\DBLink;
use SilverStripe\LinkField\Models\Link;
use SilverStripe\LinkField\Form\LinkField;
use SilverStripe\LinkField\Form\MultiLinkField;
use SilverStripe\LinkField\Models\FileLink;
use SilverStripe\LinkField\Models\SiteTreeLink;

class Page extends SiteTree
{
...

public function getCMSFields()
{
$fields = parent::getCMSFields();

...

$fields->addFieldsToTab(
'Root.Main',
[
LinkField::create('HasOneLink')
->setDisabledTypes([ FileLink::class ]),
],
);

return $fields;
}
}
```

## Unversioned links

The `Link` model has the `Versioned` extension applied to it by default. If you wish for links to not be versioned, then remove the extension from the `Link` model in the projects `app/_config.php` file.
Expand Down
8 changes: 0 additions & 8 deletions _config/graphql.yml

This file was deleted.

20 changes: 0 additions & 20 deletions _config/types.yml

This file was deleted.

3 changes: 0 additions & 3 deletions _graphql/queries.yml

This file was deleted.

5 changes: 0 additions & 5 deletions _graphql/types.yml

This file was deleted.

2 changes: 1 addition & 1 deletion client/dist/js/bundle.js

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions client/src/boot/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
/* global document */
/* eslint-disable */
import registerComponents from './registerComponents';
import registerQueries from './registerQueries';

document.addEventListener('DOMContentLoaded', () => {
registerComponents();
registerQueries();
});
8 changes: 0 additions & 8 deletions client/src/boot/registerQueries.js

This file was deleted.

1 change: 0 additions & 1 deletion client/src/components/LinkField/LinkField.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,6 @@ const mapDispatchToProps = (dispatch) => ({
});

export default compose(
injectGraphql('readLinkTypes'),
fieldHolder,
connect(null, mapDispatchToProps)
)(LinkField);
1 change: 1 addition & 0 deletions client/src/entwine/LinkField.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ jQuery.entwine('ss', ($) => {
value,
onChange: this.handleChange.bind(this),
isMulti: this.data('is-multi') ?? false,
types: this.data('types') ?? [],
};
},

Expand Down
48 changes: 0 additions & 48 deletions client/src/state/linkTypes/readLinkTypes.js

This file was deleted.

9 changes: 5 additions & 4 deletions src/Controllers/LinkFieldController.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
use SilverStripe\Forms\DefaultFormFactory;
use SilverStripe\Forms\Form;
use SilverStripe\LinkField\Models\Link;
use SilverStripe\LinkField\Type\Registry;
use SilverStripe\Security\SecurityToken;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\FormAction;
Expand All @@ -19,6 +18,8 @@
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Forms\HiddenField;
use SilverStripe\LinkField\Form\LinkField;
use SilverStripe\LinkField\Services\LinkTypeService;
use SilverStripe\ORM\DataList;

class LinkFieldController extends LeftAndMain
Expand Down Expand Up @@ -74,7 +75,7 @@ public function linkForm(): Form
}
} else {
$typeKey = $this->typeKeyFromRequest();
$link = Registry::create()->byKey($typeKey);
$link = LinkTypeService::create()->byKey($typeKey);
if (!$link) {
$this->jsonError(404, _t('LinkField.INVALID_TYPEKEY', 'Invalid typeKey'));
}
Expand Down Expand Up @@ -175,7 +176,7 @@ public function save(array $data, Form $form): HTTPResponse
// Creating a new Link
$operation = 'create';
$typeKey = $this->typeKeyFromRequest();
$className = Registry::create()->list()[$typeKey] ?? '';
$className = LinkTypeService::create()->byKey($typeKey) ?? '';
if (!$className) {
$this->jsonError(404, _t('LinkField.INVALID_TYPEKEY', 'Invalid typeKey'));
}
Expand Down Expand Up @@ -240,7 +241,7 @@ private function createLinkForm(Link $link, string $operation): Form
$form = $formFactory->getForm($this, $name, ['Record' => $link]);

// Set where the form is submitted to
$typeKey = Registry::create()->keyByClassName($link->ClassName);
$typeKey = LinkTypeService::create()->keyByClassName($link->ClassName);
$form->setFormAction($this->Link("linkForm/$id?typeKey=$typeKey"));

// Add save action button
Expand Down
3 changes: 3 additions & 0 deletions src/Form/LinkField.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\DataObjectInterface;
use SilverStripe\LinkField\Models\Link;
use SilverStripe\LinkField\Form\Traits\AllowedLinkClassesTrait;

/**
* Allows CMS users to edit a Link object.
*/
class LinkField extends FormField
{
use AllowedLinkClassesTrait;

protected $schemaComponent = 'LinkField';

protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_CUSTOM;
Expand Down
3 changes: 3 additions & 0 deletions src/Form/MultiLinkField.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use LogicException;
use SilverStripe\Forms\FormField;
use SilverStripe\LinkField\Form\Traits\AllowedLinkClassesTrait;
use SilverStripe\ORM\DataObjectInterface;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\Relation;
Expand All @@ -16,6 +17,8 @@
*/
class MultiLinkField extends FormField
{
use AllowedLinkClassesTrait;

protected $schemaComponent = 'LinkField';

protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_CUSTOM;
Expand Down
104 changes: 104 additions & 0 deletions src/Form/Traits/AllowedLinkClassesTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<?php

namespace SilverStripe\LinkField\Form\Traits;

use SilverStripe\Core\Injector\Injector;
use SilverStripe\LinkField\Models\Link;
use SilverStripe\LinkField\Services\LinkTypeService;

/**
* Trait to manage which Link type can be added to LinkField form field.
* This trait is used in LinkField and MultiLinkField classes.
*/
trait AllowedLinkClassesTrait
{
private $allowed_types = [];

/**
* Set allowed types for LinkField
*/
public function setAllowedTypes(array $types): static
{
if (empty($types) || !$this->validateTypes($types)) {
$this->allowed_types = $this->genarateAllowedTypes();
} else {
$this->allowed_types = $this->genarateAllowedTypes($types);
}

return $this;
}

/**
* Get allowed types for LinkField
*/
public function getAllowedTypes(): array
{
return $this->allowed_types;
}

/**
* Validate types that they are subclasses of Link
*/
private function validateTypes(array $types): bool
{
$validClasses = [];
foreach ($types as $type) {
if (is_subclass_of($type, Link::class)) {
$validClasses[] = $type;
}
}

return count($validClasses) > 0;
}

/**
* The method returns an associational array converted to a JSON string,
* of available link types with additional parameters necessary
* for full-fledged work on the client side.
* @throws InvalidArgumentException
*/
public function getTypesProps(): string
{
$types = [];
$typeDefinitions = $this->genarateAllowedTypes();

foreach ($typeDefinitions as $key => $class) {
$types[$key] = Injector::inst()->get($class);
}

$typesList = [];

array_map(function (Link $type, string $key) use (&$typesList) {
$typesList[$key] = [
'key' => $key,
'title' => $type->LinkTypeTile(),
'handlerName' => $type->LinkTypeHandlerName(),
];
}, $types, array_keys($types));

return json_encode($typesList);
}

/**
* Generate allowed types with key => value pair
* Example: ['cms' => SiteTreeLink::class]
*/
private function genarateAllowedTypes(array $types = []): array
{
$typeDefinitions = !empty($types) ? $types : $this->getAllowedTypes();

if (empty($typeDefinitions)) {
return LinkTypeService::create()->generateAllLinkTypes();
}

$result = array();
foreach ($typeDefinitions as $class) {
if (is_subclass_of($class, Link::class)) {
$type = Injector::inst()->get($class)->getShortCode();
$result[$type] = $class;
}
}

return $result;
}
}
Loading

0 comments on commit 421a198

Please sign in to comment.