PHPackages                             shopsys/plugin-interface - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. shopsys/plugin-interface

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

shopsys/plugin-interface
========================

General Shopsys Platform plugin interface

v19.0.0(2mo ago)3250.8k↓45.2%20MITPHPPHP ^8.5CI passing

Since Aug 17Pushed 1w ago7 watchersCompare

[ Source](https://github.com/shopsys/plugin-interface)[ Packagist](https://packagist.org/packages/shopsys/plugin-interface)[ RSS](/packages/shopsys-plugin-interface/feed)WikiDiscussions 20.0 Synced 1w ago

READMEChangelogDependencies (2)Versions (218)Used By (20)

Shopsys Plugin Interface
========================

[](#shopsys-plugin-interface)

[![Downloads](https://camo.githubusercontent.com/e1b247544b5a1d6445261c54fe009a396ebf4e3bdce65822908a9cbf288a242f/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f73686f707379732f706c7567696e2d696e746572666163652e737667)](https://packagist.org/packages/shopsys/plugin-interface)

Package of interfaces providing compatibility between [Shopsys Platform](https://www.shopsys-framework.com) and plugins.

This repository is maintained by shopsys/shopsys monorepo, information about changes is in its `CHANGELOG` file.

Features
--------

[](#features)

This package contains interfaces responsible for general functionality usable in almost any plugin. For specific functionality, such as generating product feeds, there are [separate repositories](https://github.com/search?q=topic%3Aplugin-interface+org%3Ashopsys&type=Repositories).

#### Example

[](#example)

For example usage see the `AcmeProductCrudExtension` in the CRUD extension section below.

### Storing data

[](#storing-data)

Best way to store your plugin data is to use Doctrine entities. Create a folder (e.g. `src/Entity`) in your plugin and put your entities there. Then you need to create `DoctrineOrmMappingPass` and add it as `CompilerPass` in your `YourBundleNameBundle` class. This can be done like this:

```
// vendor/your-bundle-name-bundle/src/YourBundleNameBundle.php

// ...

    /**
     * @inheritdoc
     */
    public function build(ContainerBuilder $container) {
        parent::build($container);

        $container->addCompilerPass(
            DoctrineOrmMappingsPass::createAttributeMappingDriver(
                [$this->getNamespace() . '\Entity'],
                [$this->getPath() . '/Entity']
            )
        );
    }

// ...
```

This tells Doctrine where to look for your entities. Now you can create `Repository` and manage your data as you are used to.

### CRUD extension

[](#crud-extension)

Sometimes your plugin needs some extra information to be included in an entity, for example, you need to track the weight of products. This can be solved by extending the entity CRUD model with your custom sub-form.

To do so you should implement [`PluginCrudExtensionInterface`](./src/PluginCrudExtensionInterface.php) and [tag the service in a DI container](http://symfony.com/doc/current/service_container/tags.html) with `shopsys.crud_extension` tag. The tag should have a `type` attribute defining which CRUD model should be extended (eg. `"product"`).

Each form extension has its label, form type and methods for managing the form data.

#### Example

[](#example-1)

```
services:
    acme.acme_product_crud_extension:
        class: AcmePlugin\AcmeProductCrudExtension
        tags:
            - { name: shopsys.crud_extension, type: product }

    acme.acme_data_form_type:
        class: AcmePlugin\AcmeProductFormType
        tags:
            - { name: form.type }
```

```
// ...
class AcmeProductCrudExtension implements PluginCrudExtensionInterface
{
    private $acmeProductFacade;

    public function __construct(AcmeProductFacade $acmeProductFacade) {
        $this->acmeProductFacade = $acmeProductFacade;
    }

    public function getFormTypeClass()
    {
        return AcmeProductFormType::class;
    }

    public function getFormLabel()
    {
        return 'ACME data';
    }

    public function getData($productId)
    {
        $acmeProduct = $this->acmeProductFacade->findByProductId($productId);

        $pluginData = [
            'attribute' => $acmeProduct->getAttribute(),
        ];

        return $pluginData;
    }

    public function saveData($productId, $data)
    {
        $acmeProductData = new AcmeProductData();
        $acmeProductData->attribute = $data['attribute'];

        $this->acmeProductFacade->save($productId, $acmeProductData);
    }

    public function removeData($productId)
    {
        $this->acmeProductFacade->remove($productId);
    }
}
```

[![ACME CRUD extension example](./docs/images/crud_extension_example.png)](./docs/images/crud_extension_example.png)

Demo Data
---------

[](#demo-data)

In order to enable easy testing or to demonstrate usage of your plugin, you might want to provide demonstrational data with it. In that case, you should implement [`PluginDataFixtureInterface`](./src/PluginDataFixtureInterface.php) that will take care of loading demonstrational data into the core.

All you got to do is to implement `PluginDataFixtureInterface::load()` method and [tag the service in a DI container](http://symfony.com/doc/current/service_container/tags.html) with `shopsys.data_fixture` tag.

#### Example

[](#example-2)

```
services:
    acme.acme_bundle.data_fixture:
        class: AcmePlugin\AcmeDataFixture
        tags:
            - { name: shopsys.data_fixture }
```

```
class AcmeDataFixture implements PluginDataFixtureInterface
{
    private $acmeProductFacade;

    public function __construct(AcmeProductFacade $acmeProductFacade) {
        $this->acmeProductFacade = $acmeProductFacade;
    }

    public function load() {
        $firstAcmeProductData = new AcmeProductData();
        $firstAcmeProductData->enableWeightCalculation = true;
        $firstAcmeProductData->weight = 42;
        $firstAcmeProductData->domainId = 1;

        $this->acmeProductFacade->save($firstAcmeProductData);

        $secondAcmeProductData = new AcmeProductData();
        $secondAcmeProductData->enableWeightCalculation = false;
        $secondAcmeProductData->weight = null;
        $secondAcmeProductData->domainId = 2;

        $this->acmeProductFacade->save($secondAcmeProductData);
    }

}
```

CRON modules
------------

[](#cron-modules)

When your plugin needs to execute some task periodically, for example downloading currency exchange rates every six hours, you can use a CRON module.

There are 2 types of CRON module interfaces:

- [`SimpleCronModuleInterface`](./src/Cron/SimpleCronModuleInterface.php)
    - for short tasks that do not take too long to execute
- [`IteratedCronModuleInterface`](./src/Cron/IteratedCronModuleInterface.php)
    - for long-running tasks that can be divided into smaller parts
    - if the module takes too long to run it will be suspended and will be woken up and re-run during the next opportunity

You can implement either one of these interfaces and [tag the service in a DI container](http://symfony.com/doc/current/service_container/tags.html) with `shopsys.cron` tag.

CRON modules are started automatically every time the current system time matches the specified mask in the tag attributes `hours` and `minutes`.

### Example

[](#example-3)

```
acme.data_download_cron_module:
    class: AcmePlugin\AcmeDataDownloadCronModule
    tags:
        - { name: shopsys.cron, hours: '*/6', minutes: '0' }
```

```
// ...
class AcmeDataDownloadCronModule implements SimpleCronModuleInterface
{
    /**
     * @var \Monolog\Logger
     */
    private $logger;

    public function setLogger(Logger $logger)
    {
        $this->logger = $logger;
    }

    public function run()
    {
        $data = $this->downloadData();
        $this->saveData($data);

        $this->logger->info(sprintf('Downloaded %d new records.', count($data)));
    }

    // ...
}
```

How to implement a plugin
-------------------------

[](#how-to-implement-a-plugin)

Plugins are implemented in a form of a [Symfony bundle](http://symfony.com/doc/current/bundles.html). For tips on how to write a new bundle see [Best Practices for Reusable Bundles](https://symfony.com/doc/current/bundles/best_practices.html).

Contributing
------------

[](#contributing)

Thank you for your contributions to Shopsys Plugin Interface package. Together we are making Shopsys Platform better.

This repository is READ-ONLY. If you want to [report issues](https://github.com/shopsys/shopsys/issues/new) and/or send [pull requests](https://github.com/shopsys/shopsys/compare), please use the main [Shopsys repository](https://github.com/shopsys/shopsys).

Please check our [Contribution Guide](https://github.com/shopsys/shopsys/blob/HEAD/CONTRIBUTING.md) before contributing.

Support
-------

[](#support)

What to do when you are in troubles or need some help? The best way is to join our [Slack](https://join.slack.com/t/shopsysframework/shared_invite/zt-11wx9au4g-e5pXei73UJydHRQ7nVApAQ).

If you want to [report issues](https://github.com/shopsys/shopsys/issues/new), please use the main [Shopsys repository](https://github.com/shopsys/shopsys).

###  Health Score

70

—

ExcellentBetter than 100% of packages

Maintenance93

Actively maintained with recent releases

Popularity37

Limited adoption so far

Community36

Small or concentrated contributor base

Maturity100

Battle-tested with a long release history

 Bus Factor3

3 contributors hold 50%+ of commits

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~38 days

Recently: every ~15 days

Total

84

Last Release

62d ago

Major Versions

14.0.x-dev → v16.0.02024-12-30

0.0.x-dev → 17.0.x-dev2025-09-10

v14.5.0 → v18.0.02025-12-29

14.5.x-dev → 19.0.x-dev2026-04-08

19.0.x-dev → 20.0.x-dev2026-04-08

PHP version history (6 changes)v0.1.0PHP ^7.0

v8.0.0PHP ^7.2

v9.1.0PHP ^7.4.1

v10.0.0PHP ^8.1

v14.0.0PHP ^8.3

19.0.x-devPHP ^8.5

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/5638367?v=4)[Tomáš Ludvik](/maintainers/TomasLudvik)[@TomasLudvik](https://github.com/TomasLudvik)

![](https://avatars.githubusercontent.com/u/1177414?v=4)[Martin Grossmann](/maintainers/grossmannmartin)[@grossmannmartin](https://github.com/grossmannmartin)

![](https://www.gravatar.com/avatar/8aee0045853dd983a2a4f291d2e21e7492e2d8c19d84cdb7a76dd16c3eb499f9?d=identicon)[rostislav.vitek@shopsys.com](/maintainers/rostislav.vitek@shopsys.com)

![](https://www.gravatar.com/avatar/0a44b48b2c3e7114fdf1cbdf9170494591abad48f5fc416d93b134abd771635f?d=identicon)[Miroslav Stopka](/maintainers/Miroslav%20Stopka)

---

Top Contributors

[![grossmannmartin](https://avatars.githubusercontent.com/u/1177414?v=4)](https://github.com/grossmannmartin "grossmannmartin (65 commits)")[![TomasLudvik](https://avatars.githubusercontent.com/u/5638367?v=4)](https://github.com/TomasLudvik "TomasLudvik (47 commits)")[![PetrHeinz](https://avatars.githubusercontent.com/u/10008612?v=4)](https://github.com/PetrHeinz "PetrHeinz (37 commits)")[![vitek-rostislav](https://avatars.githubusercontent.com/u/10401898?v=4)](https://github.com/vitek-rostislav "vitek-rostislav (37 commits)")[![pesektomas](https://avatars.githubusercontent.com/u/1737966?v=4)](https://github.com/pesektomas "pesektomas (8 commits)")[![boris-brtan](https://avatars.githubusercontent.com/u/39240194?v=4)](https://github.com/boris-brtan "boris-brtan (5 commits)")[![miroslav2stopka](https://avatars.githubusercontent.com/u/35224208?v=4)](https://github.com/miroslav2stopka "miroslav2stopka (5 commits)")[![s3tezsky](https://avatars.githubusercontent.com/u/53976269?v=4)](https://github.com/s3tezsky "s3tezsky (5 commits)")[![RobinDvorak](https://avatars.githubusercontent.com/u/7197178?v=4)](https://github.com/RobinDvorak "RobinDvorak (4 commits)")[![Miroslav-Stopka](https://avatars.githubusercontent.com/u/35930284?v=4)](https://github.com/Miroslav-Stopka "Miroslav-Stopka (4 commits)")[![DavidOstrozlik](https://avatars.githubusercontent.com/u/44843673?v=4)](https://github.com/DavidOstrozlik "DavidOstrozlik (3 commits)")[![LukasHeinz](https://avatars.githubusercontent.com/u/33071107?v=4)](https://github.com/LukasHeinz "LukasHeinz (2 commits)")[![msshopsys](https://avatars.githubusercontent.com/u/128610012?v=4)](https://github.com/msshopsys "msshopsys (1 commits)")[![sspooky13](https://avatars.githubusercontent.com/u/25614491?v=4)](https://github.com/sspooky13 "sspooky13 (1 commits)")[![henzigo](https://avatars.githubusercontent.com/u/1482966?v=4)](https://github.com/henzigo "henzigo (1 commits)")[![TomasVotruba](https://avatars.githubusercontent.com/u/924196?v=4)](https://github.com/TomasVotruba "TomasVotruba (1 commits)")

---

Tags

pluginplugin-interfaceshopsys-frameworkshopsys-platformssfwpluginSSFWShopsys Platform

### Embed Badge

![Health badge](/badges/shopsys-plugin-interface/health.svg)

```
[![Health](https://phpackages.com/badges/shopsys-plugin-interface/health.svg)](https://phpackages.com/packages/shopsys-plugin-interface)
```

###  Alternatives

[matomo/matomo

Matomo is the leading Free/Libre open analytics platform

21.6k38.2k](/packages/matomo-matomo)[ergebnis/composer-normalize

Provides a composer plugin for normalizing composer.json.

1.1k40.0M2.6k](/packages/ergebnis-composer-normalize)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
