How to extend Silverstripe Blog module? - silverstripe-4

I'm looking a using Siverstripe's blog module for a project. The blog has most of the features I want, but as the site is mostly book focused I's like to add some fields to the blogpost table to hold book data (title, author, rating, etc. It seems like this should be relatively simple but I can't seem to get it to work. I've created the following extension PHP file:
namespace SilverStripe\Blog\Model;
use SilverStripe\Blog\Model\BlogPost;
use SilverStripe\ORM\DataExtension;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\TextField;
use SilverStripe\Forms\TextareaField;
class BookDataExtension extends BlogPost
{
private static $db = [
'bookTitle' => 'Varchar',
'bookAuthor' => 'Varchar',
'bookSeries' => 'Varchar',
'bookISBN' => 'Varchar',
'bookSeriesNum' => 'Int',
'bookRating' => 'Decimal',
'bookCover' => 'Varchar'
];
}
And added the following to the mysite.yml file:
SilverStripe\Blog\BlogPost:
extensions:
- SilverStripe\Blog\BookDataExtension
I also tried adding the above to the config.yml file for the blog module itself. However, no matter what I try, when I rebuild the system it creates new table(s) for BookDataExtension rather than adding the fields to the BlogPost table. What am I doing wrong?

you subclassed BlogPost instead of plugging an extension to it, aka. extending it...
Your BlogPostExtension has to subclass DataExtension; it can be in your own namespace:
namespace MyProject\Extensions;
use SilverStripe\ORM\DataExtension;
class BookDataExtension extends DataExtension
{
private static $db = [
'bookTitle' => 'Varchar',
'bookAuthor' => 'Varchar',
'bookSeries' => 'Varchar',
'bookISBN' => 'Varchar',
'bookSeriesNum' => 'Int',
'bookRating' => 'Decimal',
'bookCover' => 'Varchar'
];
}
Then you can configure BlogPost to add your extension like you did before:
SilverStripe\Blog\BlogPost:
extensions:
- MyProject\Extensions\BookDataExtension

try this:
<?php
namespace {
use SilverStripe\ORM\DataExtension;
use SilverStripe\Forms\FieldList;
class BookDataExtension extends DataExtension {
private static $db = [
'db_field_example' => 'Varchar'
];
public function updateCMSFields(FieldList $fields) {
// Add fields here
}
}
}
add your extension to app/src/extensions/
and in your config:
SilverStripe\Blog\Model\BlogPost:
extensions:
- BookDataExtension

Related

Sonata admin send model_manager to custom field ModelAutocompleteType

Hello i am using symfony 5.4 with sonata admin. I created custom AppModelAutocopleteType
class AppModelAutocompleteType extends AbstractType
{
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'callback' => static function (AdminInterface $admin, array $property, $value) {
AutocompleteForIntegerAndString::execute($admin, $property, $value);
},
'to_string_callback' => function($entity, $property) {
return $entity->getLabel();
},
'minimum_input_length' => 1,
'delay' => 333,
]);
}
public function getParent()
{
return ModelAutocompleteType::class;
}
}
and in sonata admin class (Lead entity) in filter section i add this (networkProvider is relation to Lead entity)
->add('networkProvider', ModelFilter::class, [
'field_type' => AppModelAutocompleteType::class,
'field_options' => [
'property' => ['code', 'name'],
'class' => Lead::class,
'model_manager' => $this->getModelManager(),
],
])
thing is when i enable in frontend my filter it shows up correctly and when i type something i get error. In profiler (ajax request) i can see this problem
Could not find admin for code "".
Based on what i tried it looks like maybe something wrong with model_manager, i don't know if i sent it properly.
Any help how can i create custom ModelAutocompleteType which will work with sonata admin is really appreciate.

OroPlatform: Override core entity form builder

Context
I'm trying to change the form type of one field on one of the core entity: Business Unit
The default form field is TextField and I want to change it to ChoiceType.
Here is my custom field on Business Unit entity created with migration :
$table->addColumn('periodicite', 'string', [
'oro_options' => [
'extend' => ['owner' => ExtendScope::OWNER_CUSTOM],
'entity' => ['label' => 'Périodicité'],
],
]);
Issue
I've seen on the Oro documentation that entity_config.yml could solve my problem. I've tried to put these lines but it doesn't work :
entity_config:
business_unit:
entity:
items:
periodicite:
form:
type: Symfony\Component\Form\Extension\Core\Type\ChoiceType
options:
choices:
Mensuel: Mensuel
Trimestriel: Trimestriel
placeholder: false
required: true
label: "Périodicite"
I have also tried to create a new migration to change the field type on my custom field but it doesn't work
<?php
namespace Baltimore\Bundle\AppBundle\Migrations\Schema\v1_1;
use Doctrine\DBAL\Schema\Schema;
use Oro\Bundle\EntityConfigBundle\Migration\UpdateEntityConfigFieldValueQuery;
use Oro\Bundle\EntityExtendBundle\EntityConfig\ExtendScope;
use Oro\Bundle\EntityExtendBundle\Migration\Extension\ExtendExtension;
use Oro\Bundle\EntityExtendBundle\Migration\Extension\ExtendExtensionAwareInterface;
use Oro\Bundle\MigrationBundle\Migration\Migration;
use Oro\Bundle\MigrationBundle\Migration\QueryBag;
use Oro\Bundle\OrganizationBundle\Entity\BusinessUnit;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
class UpdateBusinessUnitField implements Migration, ExtendExtensionAwareInterface
{
/** #var ExtendExtension */
protected $extendExtension;
/**
* #inheritdoc
*/
public function setExtendExtension(ExtendExtension $extendExtension)
{
$this->extendExtension = $extendExtension;
}
public function up(Schema $schema, QueryBag $queries)
{
$queries->addQuery(
new UpdateEntityConfigFieldValueQuery(
BusinessUnit::class,
'periodicite',
'form',
'form_type',
ChoiceType::class
)
);
$queries->addQuery(
new UpdateEntityConfigFieldValueQuery(
BusinessUnit::class,
'periodicite',
'form',
'form_options',
[
'choices' => [
'Mensuel' => 'Mensuel',
'Trimestriel' => 'Trimestriel',
'Annuel' => 'Annuel',
],
]
)
);
}
}
I have found a solution with the changeColumn method in my migration file and it works like a charm.
By the way, these properties works also with the addColumn method.
public function up(Schema $schema, QueryBag $queries)
{
$table = $schema->getTable('oro_business_unit');
$table->changeColumn('periodicite', [
'oro_options' => [
'extend' => ['owner' => ExtendScope::OWNER_CUSTOM],
'entity' => ['label' => 'Périodicité'],
'form' => [
'form_type' => ChoiceType::class,
'form_options' => [
'choices' => [
'Mensuel' => 'Mensuel',
'Trimestriel' => 'Trimestriel',
'Semestriel' => 'Semestriel',
'Annuel' => 'Annuel'
]
]
],
],
]);
}
I don't know about the possibility to override entity config metadata using the YAML file. If there is - please share the documentation you used to implement it in the comments.
But for sure, you can manage the same using the schema migration, like in this example:
class UpdateOpportunityRelationFormType implements Migration
{
/**
* {#inheritdoc}
*/
public function up(Schema $schema, QueryBag $queries)
{
$queries->addQuery(
new UpdateEntityConfigFieldValueQuery(
Quote::class,
'opportunity',
'form',
'form_type',
OpportunitySelectType::class
)
);
$queries->addQuery(
new UpdateEntityConfigFieldValueQuery(
Quote::class,
'opportunity',
'form',
'form_options',
['attr' => ['readonly' => true]]
)
);
}
}

Customising filter for ModelAdmin to support date range in SilverStripe

I am developing a SilverStripe project. I am now struggling with customizing the filter/ search for the ModelAdmin entities, https://silverstripe.org/learn/lessons/v4/introduction-to-modeladmin-1. I am trying to add a date range filter as follows.
As you can see there are from and to fields. I have a class called Property and I am trying to customize the search/ filter for the CMS as follow to support the date range filtering.
class Property extends DataObject
{
public function searchableFields()
{
return [
//other fields go here
'Created' => [
'filter' => 'GreaterThanOrEqualFilter',
'title' => 'From',
'field' => DateField::class
],
'Created' => [
'filter' => 'To',
'title' => 'Decision date until',
'field' => DateField::class
],
];
}
}
Only one field is added to the pop up because the array key is overridden. How can I configure it to have the two date fields to specify the date range for the search form?
It might not be relevant now but I bumped to this issue today and I tried your code, you are right, only one field is created I think because you are using single DateField::class. I tried to look for a module that creates a Date Range field and I only can find this one but it looks like it's a project specific.
In my case I have 2 date fields (created and ended), using your code I can get good results by tweaking it to something like this:
public function searchableFields()
{
return [
//other fields go here
'StartDate' => [
'filter' => 'GreaterThanOrEqualFilter',
'title' => 'From',
'field' => DateField::class
],
'EndDate' => [
'filter' => 'LessThanOrEqualFilter',
'title' => 'To',
'field' => DateField::class
],
];
}
Hope it helps someone.
Using this example DataObject create a custom update function updateAdminSearchFields...
app/src/Test/MyDataObject.php
namespace MyVendor\MyNamespace;
use SilverStripe\Forms\DateField;
use SilverStripe\ORM\DataObject;
class MyDataObject extends DataObject {
private static $db = [
'Title' => 'Varchar',
'MyDateTimeField' => 'DBDatetime'
];
private static $summary_fields = ['Title','MyDateTimeField'];
public function updateAdminSearchFields($fields) {
$fields->removeByName('MyDateTimeField');//needed as added in summary field
$fields->push(DateField::create('MyDateTimeField:GreaterThanOrEqual', 'MyDateTimeField (Start)'));
$fields->push(DateField::create('MyDateTimeField:LessThanOrEqual', 'MyDateTimeField (End)'));
}
}
Then create an extension that can link that to a ModelAdmin...
app/src/Test/MyAdminExtension.php
namespace MyVendor\MyNamespace;
use SilverStripe\ORM\DataExtension;
class MyAdminExtension extends DataExtension {
public function updateSearchContext($context) {
$class = $context->getQuery([])->dataClass();
if (method_exists($class, 'updateAdminSearchFields'))
(new $class)->updateAdminSearchFields($context->getFields());
return $context;
}
}
app/_config/mysite.yml
MyVendor\MyNamespace\MyAdmin:
extensions:
- MyVendor\MyNamespace\MyAdminExtension
Lastly on the ModelAdmin apply these filters...
app/src/Test/MyAdmin.php
namespace MyVendor\MyNamespace;
use SilverStripe\Admin\ModelAdmin;
class MyAdmin extends ModelAdmin {
private static $menu_title = 'MyAdmin';
private static $url_segment = 'myadmin';
private static $managed_models = [MyDataObject::class];
public function getList() {
$list = parent::getList();
if ($params = $this->getRequest()->requestVar('filter'))
if ($filters = $params[$this->sanitiseClassName($this->modelClass)])
return $list->filter($filters);
return $list;
}
}
This example is working on latest stable version 4.7.2

How to modify Product in Silvershop (adding custom fields to $db)

I'm currently developing a shop using SilverShop. I want to add some specific fields to my products, such as what fabric my clothes are made of and an image. I know that we should not make these changes in the core SilverShop source code.
Should I extend the Product class in a new file such as app/src/ProductPage.php?
class Product extends Page implements Buyable
{
private static $db = [
'InternalItemID' => 'Varchar(30)', //ie SKU, ProductID etc (internal / existing recognition of product)
'Model' => 'Varchar(30)',
'BasePrice' => 'Currency(19,4)', // Base retail price the item is marked at.
//physical properties
// TODO: Move these to an extension (used in Variations as well)
'Weight' => 'Decimal(12,5)',
'Height' => 'Decimal(12,5)',
'Width' => 'Decimal(12,5)',
'Depth' => 'Decimal(12,5)',
'Featured' => 'Boolean',
'AllowPurchase' => 'Boolean',
'Popularity' => 'Float' //storage for CalculateProductPopularity task
];
...
Use DataExtension
For SilverStripe 4, it will be something like:
ProductExtension.php :
use SilverStripe\ORM\DataExtension;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\TextField;
class ProductExtension extends DataExtension
{
private static $db = [
'NewField' => 'Varchar(255)'
];
public function updateCMSFields(FieldList $fields)
{
$fields->addFieldsToTab('Root.Main', TextField::create('NewField', 'This is new field'));
}
}
And, add the next lines to mysite.yml
SilverShop\Page\Product:
extensions:
- ProductExtension
dev/build and it's done

Silverstripe Elemental trouble after creating related dataobjects

Facts: SS 4.0.1, dnadesign/silverstripe-elemental 2.x-dev, php 7.1 and Zauberfisches Vagrant box Jessy Version 3
I made an Elemental Element that is a holder for single elements:
namespace R12page\Elements;
use DNADesign\Elemental\Models\BaseElement;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\GridField\GridFieldConfig_RecordEditor;
use SilverStripe\Versioned\Versioned;
use UndefinedOffset\SortableGridField\Forms\GridFieldSortableRows;
class ImageRasterElement extends BaseElement
{
private static $singular_name = 'Image Raster Element';
private static $plural_name = 'Images Raster Elements';
private static $description = 'Generates an Image Raster for multiple single Elements';
private static $table_name = 'ImageRasterElement';
private static $has_many = [
'SingleElements' => SingleElement::class
];
private static $extensions = [
Versioned::class . '.stagedversioned',
];
public function getType()
{
return 'ImageRasterElement';
}
public function getCMSFields()
{
$fields = parent::getCMSFields();
$singleElements = $this->SingleElements();
$singleElementGridConfig = GridFieldConfig_RecordEditor::create();
$singleElementGridConfig->addComponent(new GridFieldSortableRows('SortOrder'));
$singleElementGrid = GridField::create('SingleElements', 'Single Elements of this Page', $singleElements, $singleElementGridConfig);
$fields->addFieldsToTab('Root.Main', $singleElementGrid);
return $fields;
}
}
This Element has_many single Elements: they look like:
namespace R12page\Elements;
use R12page\Model\News;
use R12page\Model\People;
use R12page\Model\References;
use SilverStripe\ORM\DataObject;
use SilverStripe\Versioned\Versioned;
class SingleElement extends DataObject
{
private static $table_name = 'SingleElement';
private static $db = [
'Reference' => 'Boolean',
'People' => 'Boolean',
'News' => 'Boolean',
'SortOrder' => 'Int'
];
private static $has_one = [
'News' => News::class,
'People' => People::class,
'Reference' => References::class,
'ImageRasterElements' => ImageRasterElement::class
];
private static $summary_fields = [
'News.Headline' => 'News',
'People.Name' => 'People',
'Reference.Headline' => 'Reference'
];
private static $extensions = [
Versioned::class . '.stagedversioned',
];
}
Each Single Element has an has_one to a Data Object. The look like:
namespace R12page\Model;
use R12page\Elements\SingleElement;
use SilverStripe\ORM\DataObject;
use SilverStripe\Versioned\Versioned;
class News extends DataObject
{
private static $table_name = 'News';
private static $db = [
'Headline' => 'Varchar',
'SubHeadline' => 'Varchar',
'Date' => 'Date',
'DatePublished' => 'Date',
'Content' => 'HTMLText',
'IsActiv' => 'Boolean',
'DisplayOnHomePage' => 'Boolean'
];
private static $has_one = [
'Mobile' => Size::class,
'Screen' => Size::Class
];
private static $has_many = [
'SingleElements' => SingleElement::class
];
private static $owns = [
'SingleElements'
];
private static $summary_fields = [
'Headline' => 'Headline',
'Mobile.Title' => 'Mobile',
'Screen.Title' => 'Screen'
];
private static $extensions = [
Versioned::class . '.stagedversioned',
];
}
So far so good. This is what it looks like in the admin Area.
The strange thing is if I add a single Element an try to create it i get this:
When i refresh the page i can see the content of the page and i can save it with out any problems. When if use php_debug everything looks good. I also don't have and error messages in the console which i think, are related to the problem i am having . I just get those to warnings:
But i think the warnings should not be the problem. To be precise i get an error because a font is not loading.
Please help me debug this. I tried the hole day to get this to work. I can not identify the problem i am having.
This is the response i am getting back:
To me it looks okay.
This is the response from the browser networktap:
A view things i can confirm:
Elemental works on a clean install.
If i switch to live mode nothing changes.
If i try to use the content element that ships with elemental it has the same behavior.

Resources