Create a custom content item
Edit on GitHubBy default, Spryker provides Banner
, Product Abstract List
, Product Set
and File List
content items.
If you need another type of content to display in a CMS page or bock content or even inside a Twig template file, you can create it on the project level.
You can do the following:
- Introduce a new entity with all the properties required by your project. For example, see
ContentBanner
andContentBannerGui
modules. - Use an entity that already exists in your shop database, like
Location
,Partner
, orEmployee
. For example, seeContentProduct
andContentProductGui
modules.
To create a new custom content item, implement the following plugins in the order they are described.
Content form plugin
To check the existing content form plugins, open \Pyz\Zed\ContentGui\ContentGuiDependencyProvider::getContentPlugins()
.
Such plugins implement \Spryker\Zed\ContentGuiExtension\Dependency\Plugin\ContentPluginInterface
.
To create a new content form plugin, follow these steps:
- Create a module for the new content type—for example,
src/Zed/ContentFooGui
, with a plugin inside. The following list represents the description of plugin methods:getTypeKey()
—returns a string with the name of your content item—for example, Foo.getTermKey()
—returns a string displaying the term for this content type in database—for example,Foo
,Foo List
orFoo Query
. In database, a content type can have different term representations. Correspondingly, there are different ways of getting information about content. For example:Foo List
—product list IDs.Foo Query
—product query as part of SQL/ElasticSearch query. This value is displayed in the Back Office, in Content Management > Content Items.
getForm()
—a form class name with a namespace which is displayed on the Content create or Content edit pages.getTransferObject()
—maps form data to a content term transfer object—for example,ContentFooTermTransfer
.
<?php
namespace Spryker\Zed\ContentFootGui\Communication\Plugin\ContentGui;
use Spryker\Shared\Kernel\Transfer\TransferInterface;
use Spryker\Zed\ContentGuiExtension\Dependency\Plugin\ContentPluginInterface;
use Spryker\Zed\ContentFooGui\Communication\Form\ContentFooTermForm;
use Spryker\Zed\Kernel\Communication\AbstractPlugin;
class ContentFooFormPlugin extends AbstractPlugin implements ContentPluginInterface
{
/**
* @return string
*/
public function getTermKey(): string
{
return 'Foo';
}
/**
* @return string
*/
public function getTypeKey(): string
{
return 'Foo';
}
/**
* @return string
*/
public function getForm(): string
{
return ContentFooTermForm::class;
}
/**
* @param array|null $params
*
* @return \Generated\Shared\Transfer\ContentFooTermTransfer
*/
public function getTransferObject(?array $params = null): TransferInterface
{
$contentFooTermTransfer = new ContentFooTermTransfer();
if ($params) {
$contentFooTermTransfer->fromArray($params);
}
return $contentFooTermTransfer;
}
}
- Create
ContentFooTermForm
. The main part of the plugin is theForm
class that implements\Symfony\Component\Form\FormBuilderInterface
.- For more information about Symfony forms, see Forms.
- To learn about form creation procedure in Spryker, see Creating forms
\Spryker\Zed\ContentBannerGui\Communication\Form\BannerContentTermForm
as an example of a simple form.\Spryker\Zed\ContentProductGui\Communication\Form\ProductAbstractListContentTermForm
as an example of a form with a dedicated template and complex Javascript functionality.
Each form shipped by default require at least one form field to be filled out before it can be submitted. However, you can add more form constraints with additional validation.
namespace Spryker\Zed\ContentFooGui\Communication\Form;
use Spryker\Zed\Kernel\Communication\Form\AbstractType;
class ContentFooTermForm extends AbstractType
{
/**
* @return string
*/
public function getBlockPrefix(): string
{
return 'foo';
}
**
* @param \Symfony\Component\Form\FormBuilderInterface $builder
* @param array $options
*
* @return void
*/
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->add('name', TextType::class, [
'label' => 'Name',
]);
$builder->add('city', TextType::class, [
'label' => 'City',
]);
$builder->add('address', TextType::class, [
'label' => 'Address',
]);
$builder->add('numberOfEmployees', IntegerType::class, [
'label' => 'Number of employees',
]);
}
/**
* User this method if you need to provide custom template path or additional data to template
*
* @param \Symfony\Component\Form\FormView $view
* @param \Symfony\Component\Form\FormInterface $form
* @param array $options
*
* @return void
*/
public function buildView(FormView $view, FormInterface $form, array $options): void
{
$view->vars['attr']['template_path'] = '@ContentFooGui/_includes/foo_form.twig';
}
}
After enabling the plugin, make sure there is a new content item in the Back Office, in Content Management > Content Items > Add Content Item.
Twig plugin
After enabling the content form plugin, you have your new content item data in Storage. To fetch the item data from Storage, use \Spryker\Client\ContentStorage\ContentStorageClientInterface::findContentTypeContextByKey(string $contentKey, string $localeName)
.
$contentKey
is generated automatically after content saving.$localeName
is an automatically provided locale by current Store.
The method returns ContentTypeContextTransfer
, where ContentTypeContextTransfer::$parameters
is the data saved by the form created in the previous section.
To create a new Twig plugin, follow these steps:
- Using
ContentTypeContextTransfer::$term
andContentTypeContextTransfer::$parameters
, fill in the properties of your new content transfer object—for example,ContentFooTransfer
, insrc/Shared/ContentFoo/Transfer/
. - Create a new module—for example,
src/Yves/ContentFooWidget
. - Implement a Twig function using
\Spryker\Shared\Twig\TwigFunction
—for example,\SprykerShop\Yves\ContentBannerWidget\Twig\ContentBannerTwigFunction
. - Implement a Twig plugin using
\Spryker\Shared\TwigExtension\Dependency\Plugin\TwigPluginInterface
—for example,\SprykerShop\Yves\ContentBannerWidget\Plugin\Twig\ContentBannerTwigPlugin
.
The $key
parameter is obligatory for the function—for example, function (string $key)
.
Optional: You can add the $templateIdentifier
parameter—for example, function (string $key, string $templateIdentifier)
.
- In
\Pyz\Yves\Twig\TwigDependencyProvider::getTwigPlugins()
, register your Twig plugin.
Now you can use your plugin as a function in Twig files. If you’ve named your plugin content_foo
, in a Twig file, the function looks like {{ content_foo('content-key', 'big-header') }}
.
WYSIWYG editor plugin
The CMS Block Glossary Edit and Placeholder Edit pages contain the WYSIWYG editor to put content into a CMS block or page. In the WYSIWYG toolbar, the Content Item drop-down menu contains all the content items which you can add. For more details, see Add content items to CMS blocks.
To add the new content item to that list, in src/Zed/ContentFooGui
, implement a new plugin using \Spryker\Zed\ContentGuiExtension\Dependency\Plugin\ContentGuiEditorPluginInterface
—for example, ContentFooContentGuiEditorPlugin
.
The following are the method descriptions:
getType()
: Returns a string displaying the content type—for example, Foo.getTemplates()
: Returns an array of templates supported by your Twig plugin created in the previous section. If there are no supported templates defined, returns an empty array.getTwigFunctionTemplate()
: Returns a Twig expression that is added into the content.
<?php
namespace Spryker\Zed\ContentFooGui\Communication\Plugin\ContentGui;
use Spryker\Zed\ContentGuiExtension\Dependency\Plugin\ContentGuiEditorPluginInterface;
use Spryker\Zed\Kernel\Communication\AbstractPlugin;
/**
* @method \Spryker\Zed\ContentProductGui\Communication\ContentProductGuiCommunicationFactory getFactory()
* @method \Spryker\Zed\ContentProductGui\ContentProductGuiConfig getConfig()
*/
class ContentFooContentGuiEditorPlugin extends AbstractPlugin implements ContentGuiEditorPluginInterface
{
/**
* @return string
*/
public function getType(): string
{
return 'Foo';
}
/**
* @return \Generated\Shared\Transfer\ContentWidgetTemplateTransfer[]
*/
public function getTemplates(): array
{
return [
(new ContentWidgetTemplateTransfer())
->setIdentifier('big-header') // $templateIdentifier from step 2
->setName('Big Header'), // is visible in UI.
(new ContentWidgetTemplateTransfer())
->setIdentifier('full-width')
->setName('Full Width'),
];
}
/**
* @return string
*/
public function getTwigFunctionTemplate(): string
{
return "{{ content_foo('%KEY%', '%TEMPLATE%') }}";
}
}
Thank you!
For submitting the form