Introducing the plugin cookbook

The plugin cookbook is a collection of recipes for plentymarkets plugin scenarios. On this page, you will find answers to questions that might arise when developing plentymarkets plugins.

Adding content categories in the Ceres navigation

By default, content categories are not displayed in the navigation bar of Ceres. If you want to display a category of the Content type in the navigation bar of the online store, you have to change a parameter in one of the Twig templates. You can do this in your own theme or fork of Ceres, or in the plentymarkets back end when using Ceres from plentyMarketplace.

  1. Go to Plugins » Plugin overview.
  2. Click on Ceres.
    → The plugin will open.
  3. Go to resources/views/PageDesign/PageDesign.twig.
  4. Search for the line of code {% set categories = services.category.getNavigationTree("item", lang, 6) %}.
  5. Replace the line of code with {% set categories = services.category.getNavigationTree("all", lang, 6) %}.
  6. Save the settings.
    → All category types can now be used in the navigation bar of the online store.
Important: Note that these changes will be overwritten when updating the plugin to a higher version. Repeat the steps above in order to make all category types available again.

After enabling the other category types in the Ceres online store, create a category of the Content type. The following steps must be taken into account:

  • Activate this category for your client.
  • Select Display in the In link list drop-down to display the category in the navigation.
  • Open the Template tab and enter the content that you want to display in the online store.
    → You can enter HTML and TWIG code in this tab.
  • Save everything.
    → When content is entered in the Template tab of a category, the CategoryTemplates plugin is created automatically. This plugin contains the HTML/TWIG code of your category.
  • Simply activate this plugin and deploy the plugin set by clicking Save & publish plugins. After a short period of time, the category will be visible in the navigation.

Adding scripts in Ceres

Scripts of your plugin defined using the HTML <script> tag can be added to the scripts of the template plugin Ceres without creating a data provider and linking the content with a template container. Simply extend the ServiceProvider of your plugin and import your script resource into Ceres.

Theme/src/Providers/ThemeServiceProvider.php
<?php

namespace Theme\Providers;

use IO\Helper\TemplateContainer;
use IO\Helper\ResourceContainer;
use Plenty\Plugin\Events\Dispatcher;
use Plenty\Plugin\ServiceProvider;
use Plenty\Plugin\Templates\Twig;

class ThemeServiceProvider extends ServiceProvider
{

	/**
	 * Register the service provider.
	 */
	public function register()
	{

	}

    /**
	 * Boot a template for the basket that will be displayed in the template plugin instead of the original basket.
	 */
	public function boot(Twig $twig, Dispatcher $eventDispatcher)
    {
        $eventDispatcher->listen('IO.Resources.Import', function (ResourceContainer $container)
        {
            // The script is imported in the Footer.twig of Ceres
            $container->addScriptTemplate('Theme::content.SingleItemScript');
        }, self::PRIORITY);
    }
}

Adding style in Ceres

Inline style of your plugin defined using the HTML <style> tag can be added to the style of the template plugin Ceres without creating a data provider and linking the content with a template container. Simply extend the ServiceProvider of your plugin and import your style resource into Ceres.

Theme/src/Providers/ThemeServiceProvider.php
<?php

namespace Theme\Providers;

use IO\Helper\TemplateContainer;
use IO\Helper\ResourceContainer;
use Plenty\Plugin\Events\Dispatcher;
use Plenty\Plugin\ServiceProvider;
use Plenty\Plugin\Templates\Twig;

class ThemeServiceProvider extends ServiceProvider
{

	/**
	 * Register the service provider.
	 */
	public function register()
	{

	}

    /**
	 * Boot a template for the basket that will be displayed in the template plugin instead of the original basket.
	 */
	public function boot(Twig $twig, Dispatcher $eventDispatcher)
    {
        $eventDispatcher->listen('IO.Resources.Import', function (ResourceContainer $container)
        {
            // The style is imported in the <head> on the PageDesign.twig of Ceres
            $container->addStyleTemplate('Theme::content.SingleItemStyle');
        }, self::PRIORITY);
    }
}

Changing contexts in Ceres

Contexts provided by your own theme plugin can overwrite and extend the PHP context classes of the template plugin Ceres without creating a data provider and linking the content with a template container. Simply extend the ServiceProvider of your plugin and import your context resource into Ceres.

Theme/Providers/ThemeServiceProvider.php

  namespace Theme\Providers;

  use IO\Helper\TemplateContainer;
  use Plenty\Plugin\Events\Dispatcher;
  use Plenty\Plugin\ServiceProvider;
  use Plenty\Plugin\Templates\Twig;
  use Theme\Contexts\MyContext;

  class ThemeServiceProvider extends ServiceProvider
  {

  	/**
  	 * Register the service provider.
  	 */
  	public function register()
  	{

  	}

  	public function boot(Twig $twig, Dispatcher $eventDispatcher)
      {
          /**
          * Extend the context for the basket template with MyContext.
          */
          $eventDispatcher->listen('IO.ctx.basket', function (TemplateContainer $templateContainer, $templateData = [])
          {
              $templateContainer->setContext( MyContext::class);
              return false;
          }, 0);
      }
  }

Theme/src/Contexts/MyContext.php

<?php

namespace Theme\Contexts;

use IO\Helper\ContextInterface;

class MyContext extends GlobalContext implements ContextInterface
{
    public $myVariable;

    public function init($params)
    {
        parent::init($params);

		$this->myVariable = “This is how you extend context classes.“;
    }
}

Executing code without authentication

If you want to execute individual code blocks in the plugin without being restricted by authentication, use the AuthHelper class. For further information, refer to the code example below:

<?php

/** @var \Plenty\Modules\Account\Address\Contracts\AddressRepositoryContract $addressRepo */
$addressRepo = pluginApp(AddressRepositoryContract::class);

/** @var \Plenty\Modules\Authorization\Services\AuthHelper $authHelper */
$authHelper = pluginApp(AuthHelper::class);

$address = null;

//guarded
$address = $authHelper->processUnguarded(
    function () use ($addressRepo, $address) {
        //unguarded
        return $addressRepo->findAddressById(42);
    }
);
//guarded

Adding a custom address field

If you want to add one or multiple custom address fields to the address form of the template plugin Ceres, you can use the template container Additional address fields. Create a plugin that provides the data to be displayed in the container, e.g. with the help of this tutorial. Then add the following code to the .twig template:

<div class="col-xs-12 col-sm-4">
    <div class="input-unit" data-validate="text">
        <input type="text" name="town" id="txtPackstationNo${_uid}" v-model="addressData.packstationNo">
        <label for="txtPackstationNo${_uid}">Packstation</label>
    </div>
</div>

Validating addresses in template plugins

Template plugins that want to validate address fields using the validators in IO must have a configuration file following certain rules. IO can get the configuration values set in the template plugin and validate addresses based on these settings. The easiest way to do this is to copy part of the config.json file of Ceres and edit the code. Then, the namespace of the template plugin must be specified in IO.

  1. Go to Plugins » Plugin overview.
  2. Click on IO.
    → The plugin will open.
  3. Click on Configuration in the directory tree.
    → The Template tab will open.
  4. Enter the namespace of your template plugin.
  5. Save the settings.

Example code of the configuration

...

{
    "tab"                                   : "Checkout and My account",
    "key"                                   : "billing_address.require",
        "label"                             : "Enable invoice address field validation",
        "type"                              : "multi_select",
        "possibleValues"                    :
            {
                "billing_address.name1"     : "Company",
                "billing_address.vatNumber" : "VAT number",
                "billing_address.birthday"  : "Date of birth",
                "billing_address.name4"     : "Name affix",
                "billing_address.address3"  : "Additional address 1 / Building name",
                "billing_address.address4"  : "Additional address 2",
                "billing_address.stateId"   : "State"

            },
        "default"                           : "billing_address.birthday, billing_address.name4, billing_address.address3, billing_address.address4"
},

...

Example code of the validator

<?php

namespace IO\Validators\Customer;

use Plenty\Validation\Validator;
use IO\Services\TemplateConfigService;

class BillingAddressValidator extends Validator
{
    private $requiredFields;

    public function defineAttributes()
    {
        /**
         * @var TemplateConfigService $templateConfigService
         */
        $templateConfigService = pluginApp(TemplateConfigService::class);
        $requiredFieldsString  = $templateConfigService->get('billing_address.require');
        $this->requiredFields  = explode(', ', $requiredFieldsString);
        foreach ($this->requiredFields as $key => $value)
        {
            $this->requiredFields[$key] = str_replace('billing_address.', '', $value);
        }

        $this->addString('name2',      true);
        $this->addString('name3',      true);
        $this->addString('address1',   true);
        $this->addString('address2',   true);
        $this->addString('postalCode', true);
        $this->addString('town',       true);

        if(count($this->requiredFields))
        {
            $this->addString('name1',     $this->isRequired('name1'));
            $this->addString('vatNumber', $this->isRequired('vatNumber'));
            $this->addString('birthday',  $this->isRequired('birthday'));
            $this->addString('name4',     $this->isRequired('name4'));
            $this->addString('address3',  $this->isRequired('address3'));
            $this->addString('address4',  $this->isRequired('address4'));
            $this->addString('stateId',  $this->isRequired('stateId'));
        }
    }

    private function isRequired($fieldName)
    {
        return in_array($fieldName, $this->requiredFields);
    }
}

Disabling lazy loading in Ceres item lists

If you want to disable the lazy load function in Ceres item lists, simply add a line of code to the <category-image-carousel> block:

<category-image-carousel template="#vue-category-image-carousel"
    :image-urls="itemData.images | itemImages imageUrlAccessor"
    :alt-text="texts | itemName "
    :item-url="itemData | itemURL"
    :show-dots="null"
    :show-nav="null"
    :disable-lazy-load="true">
</category-image-carousel>

Adding a custom value to the item sorting

If you want to add one or multiple custom sorting values to the item sorting drop-down menu of the template plugin Ceres, add the following code in the service provider of your plugin:

<?php

namespace Feedback\Providers;

...

use Plenty\Plugin\Events\Dispatcher;

/**
 * @param Dispatcher $dispatcher
 */
public function boot(Dispatcher $dispatcher)
{
    // Add sorting by customer reviews
    $dispatcher->listen('IO.initAdditionalSorting', function (ItemService $itemService) {

        // addAdditionalItemSorting(field name, translation key)
        $itemService->addAdditionalItemSorting('item.feedbackDecimal_desc', 'Feedback::Feedback.customerReviews');
    });
}