Is this article helpful?
 
(optional) let us know why:

My second plugin - List of top sellers

In this second tutorial, we will dive deeper into developing plugins. Before you continue, we recommend finishing the My first plugin tutorial.

In this tutorial, you will learn how to develop a plugin which renders your top-selling items in the browser. The top items will be displayed as bootstrap cards with the following item information:

  • Name
  • ID
  • First linked image
  • Item description
  • Price

Further reading

Step 1: Creating the plugin files

In the first tutorial, you learned how to set up the folder structure with a minimum of required files to create a working plugin. Our new plugin has a similar structure, but it also has additional content in the resources folder. Create the following basis for your plugin.

TopItems/
    ├-- resources/
    │   └── views/
    │       ├── content/
    │       │   └── TopItems.twig // actual content
    │       │
    │       └── PageDesign.twig // frame for the content
    │
    ├── src/
    │   ├── Controllers/
    │   │   └── ContentController.php
    │   │
    │   └── Providers/
    │       ├── TopItemsServiceProvider.php
    │       └── TopItemsRouteServiceProvider.php
    │
    └── plugin.json // plugin information

Step 2: Filling the source files

We start by creating the plugin.json file. We will also need a ServiceProvider, a RouteServiceProvider and a ContentController in the src folder of our plugin. Create these files and copy the code examples.

Code for the plugin.json

TopItems/plugin.json
{
    "name"              :"TopItems",
    "description"       :"Plugin to render a list of top items",
    "namespace"         :"TopItems",
    "author"            :"Your name",
    "type"              :"template",
    "serviceProvider"   :"TopItems\\Providers\\TopItemsServiceProvider"
}

Code for the ServiceProvider

TopItems/src/Providers/TopItemsServiceProvider.php
<?php

namespace TopItems\Providers;


use Plenty\Plugin\ServiceProvider;

class TopItemsServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->getApplication()->register(TopItemsRouteServiceProvider::class);
    }
}

Code for the RouteServiceProvider

TopItems/src/Providers/TopItemsRouteServiceProvider.php
<?php

namespace TopItems\Providers;


use Plenty\Plugin\RouteServiceProvider;
use Plenty\Plugin\Routing\Router;

class TopItemsRouteServiceProvider extends RouteServiceProvider
{
    public function map(Router $router)
    {
        $router->get('topitems', 'TopItems\Controllers\ContentController@showTopItems');
    }
}

Code for the ContentController

TopItems/src/Controllers/ContentController.php
<?php

namespace TopItems\Controllers;


use Plenty\Plugin\Controller;
use Plenty\Plugin\Templates\Twig;
use Plenty\Modules\Item\DataLayer\Contracts\ItemDataLayerRepositoryContract;

class ContentController extends Controller
{
    public function showTopItems(Twig $twig, ItemDataLayerRepositoryContract $itemRepository):string
    {
        $itemColumns = [
            'itemDescription' => [
                'name1',
                'description'
            ],
            'variationBase' => [
                'id'
            ],
            'variationRetailPrice' => [
                'price'
            ],
            'variationImageList' => [
                'path',
                'cleanImageName'
            ]
        ];

        $itemFilter = [
            'itemBase.isStoreSpecial' => [
                'shopAction' => [3]
            ]
        ];

        $itemParams = [
            'language' => 'en'
        ];

        $resultItems = $itemRepository
            ->search($itemColumns, $itemFilter, $itemParams);

        $items = array();
        foreach ($resultItems as $item)
        {
            $items[] = $item;
        }
        $templateData = array(
            'resultCount' => $resultItems->count(),
            'currentItems' => $items
        );

        return $twig->render('TopItems::content.TopItems', $templateData);
    }
}

Step 3: Creating the page design

In this step, we create the template file that contains the page design. This file is the HTML frame for our content retrieved from the database. The content itself and its layout will be discussed in step 4. Add a new twig file in the resources/views folder and name the file PageDesign.twig. Insert the code example below.

TopItems/resources/views/PageDesign.twig
<!DOCTYPE html>
<html lang="en">
    <head>
        <!-- Required meta tags always come first -->

        <title>Top items</title>

        <!-- CSS -->
        <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.2/css/bootstrap.min.css" rel="stylesheet" type="text/css">

    </head>
    <body>
        <div id="page-body">
            {% block PageBody %}
                <!-- inserts content of TopItems.twig here -->
            {% endblock %}
        </div>
    </body>
</html>

Step 4: Creating the output file

Last but not least, we need a file for the item information retrieved from the database. Create a new content subfolder in the resources/views folder and add a TopItems.twig file.

TopItems/resources/views/content/TopItems.twig
{% extends "TopItems::PageDesign" %}

{% block PageBody %}
    <h1 style="text-align: center">{{ resultCount }} top items found!</h1>
    <div class="col-xs-12 card-deck-wrapper" style="overflow: auto">
    <ul class="list-unstyled card-deck" style="height: 380px">
        {% if currentItems is not null %}
            {% for item in currentItems %}
                <li class="card" style="width: 280px">
                    <div class="card-block">
                        <h4 class="card-title">{{ item.itemDescription.name1 }}</h4>
                        <h6 class="card-subtitle text-muted">ID: {{ item.variationBase.id }}</h6>
                    </div>
                    {% set image = item.variationImageList | first %}
                    <img class="col-lg-12" src="{{ image.path }}" alt="{{ image.cleanImageName }}">
                    <div class="card-block">
                        <p class="card-text">{{ item.itemDescription.description }}</p>
                    </div>
                    <div class="card-footer bg-primary">
                        <h4 style="text-align: center">Price: {{ item.variationRetailPrice.price }} €</h4>
                    </div>
                </li>
            {% endfor %}

            {% else %}
                <li>No items found!</li>
        {% endif %}
    </ul>
    </div>
{% endblock %}

Playing your cards right

Provided that you have already set up some top items in your plentymarkets backend, the plugin will be filled with the requested data. To display the top item cards, open a new browser tab and type in your domain adding /topitems at the end. Don't forget to push your changes to GitHub. You also have to update the plugin in your plentymarkets inbox by pulling the changes from GitHub. Finally, you have to deploy the plugin again to display your top items in your browser. Good job!