Commit 52bb15b6 by Bartosz Kubicki

Module init

parents
<?php
declare(strict_types=1);
/**
* File: ChannelFactoryInterface.php
*
* @author Bartosz Kubicki bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
*/
namespace LizardMedia\CommunicationChannel\Api;
/**
* Interface ChannelFactoryInterface
* @package LizardMedia\CommunicationChannel\Api
*/
interface ChannelFactoryInterface
{
/**
* @param string $type
* @param array $data
* @return ChannelInterface
*/
public function create(string $type, array $data = []): ChannelInterface;
}
<?php
declare(strict_types=1);
/**
* File: ChannelInterface.php
*
* @author Bartosz Kubicki bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
*/
namespace LizardMedia\CommunicationChannel\Api;
/**
* Interface ChannelInterface
* @package LizardMedia\CommunicationChannel\Api
*/
interface ChannelInterface
{
/**
* @return void
*/
public function advanceProgress(): void;
/**
* @param int $max
* @return void
*/
public function informAboutTotalCount(int $max): void;
/**
* @param string $message
* @return void
*/
public function inform(string $message): void;
/**
* @param string $error
* @return void
*/
public function informAboutError(string $error): void;
/**
* @return void
*/
public function informThatFinished(): void;
}
<?php
declare(strict_types=1);
/**
* File: Console.php
*
* @author Bartosz Kubicki bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
*/
namespace LizardMedia\CommunicationChannel\Model\Channel;
use LizardMedia\CommunicationChannel\Api\ChannelInterface;
use Symfony\Component\Console\Helper\FormatterHelper;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Helper\ProgressBarFactory;
use Symfony\Component\Console\Output\ConsoleOutput;
/**
* Class Console
* @package LizardMedia\CommunicationChannel\Model\Channel
*/
class Console implements ChannelInterface
{
/**
* @var float
*/
private $advanceStep;
/**
* @var FormatterHelper
*/
private $formatterHelper;
/**
* @var ProgressBar
*/
private $progressBar;
/**
* @var ProgressBar
*/
private $progressBarFactory;
/**
* @var ConsoleOutput
*/
private $consoleOutput;
/**
* Console constructor.
* @param FormatterHelper $formatterHelper
* @param ProgressBarFactory $progressBarFactory
* @param ConsoleOutput $consoleOutput
* @param float $advanceStep
*/
public function __construct(
FormatterHelper $formatterHelper,
ProgressBarFactory $progressBarFactory,
ConsoleOutput $consoleOutput,
float $advanceStep = 0.01
) {
$this->formatterHelper = $formatterHelper;
$this->progressBarFactory = $progressBarFactory;
$this->consoleOutput = $consoleOutput;
$this->advanceStep = $advanceStep;
}
/**
* @return void
*/
public function advanceProgress(): void
{
if ($this->progressBar instanceof ProgressBar) {
$this->progressBar->advance();
}
}
/**
* @param int $max
* @return void
*/
public function informAboutTotalCount(int $max): void
{
$this->progressBar = $this->instantiateProgressBar($max);
$this->progressBar->setFormat('verbose');
$this->progressBar->setRedrawFrequency((int) round($max * $this->advanceStep));
$this->progressBar->start();
}
/**
* @param string $error
* @return void
*/
public function informAboutError(string $error): void
{
$this->consoleOutput->writeln($this->formatterHelper->formatBlock($error, 'error'));
}
/**
* @param string $message
* @return void
*/
public function inform(string $message): void
{
$this->consoleOutput->writeln($this->formatterHelper->formatBlock($message, 'info'));
}
/**
* @return void
*/
public function informThatFinished(): void
{
if ($this->progressBar instanceof ProgressBar) {
$this->progressBar->finish();
}
}
/**
* @param int $max
* @return ProgressBar
*/
private function instantiateProgressBar(int $max): ProgressBar
{
return $this->progressBarFactory->create(
[
'output' => $this->consoleOutput,
'max' => $max
]
);
}
}
<?php
declare(strict_types=1);
/**
* File: Log.php
*
* @author Bartosz Kubicki bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
*/
namespace LizardMedia\CommunicationChannel\Model\Channel;
use LizardMedia\CommunicationChannel\Api\ChannelInterface;
use Psr\Log\LoggerInterface;
/**
* Class Log
* @package LizardMedia\CommunicationChannel\Model\Channel
*/
class Log implements ChannelInterface
{
/**
* @var float
*/
private $advanceStep;
/**
* @var int
*/
private $currentProgress = 0;
/**
* @var int
*/
private $nextRedrawStep = 1;
/**
* @var int
*/
private $redrawFrequency = 1;
/**
* @var float
*/
private $startTime;
/**
* @var int
*/
private $totalCount = 0;
/**
* @var LoggerInterface
*/
private $logger;
/**
* Log constructor.
* @param LoggerInterface $logger
* @param float $advanceStep
*/
public function __construct(LoggerInterface $logger, float $advanceStep = 0.01)
{
$this->logger = $logger;
$this->advanceStep = $advanceStep;
$this->startTime = microtime(true);
}
/**
* @return void
*/
public function advanceProgress(): void
{
$this->currentProgress++;
if ($this->redrawFrequency === 0 || $this->totalCount === 0) {
return;
}
if ($this->currentProgress === $this->nextRedrawStep
|| $this->currentProgress == $this->totalCount) {
$this->nextRedrawStep = $this->currentProgress + $this->redrawFrequency;
$this->logger->info(__('Migrated: %1 / %2', $this->currentProgress, $this->totalCount));
}
}
/**
* @param int $max
* @return void
*/
public function informAboutTotalCount(int $max) : void
{
$this->totalCount = $max;
$this->logger->info(__('Total count of migrated entities: %1', $this->totalCount));
$this->calculateRedrawFrequency();
}
/**
* @param string $error
* @return void
*/
public function informAboutError(string $error): void
{
$this->logger->error($error);
}
/**
* @param string $message
* @return void
*/
public function inform(string $message) : void
{
$this->logger->info($message);
}
/**
* @return void
*/
public function informThatFinished() : void
{
$this->logger->info(__('Migration has been finished'));
$this->logger->info(__('Total time: %1', $this->calculateTotalTime()));
}
/**
* @return void
*/
private function calculateRedrawFrequency() : void
{
$frequency = (int) round($this->advanceStep * $this->totalCount, 0);
if ($frequency < 1) {
$frequency = 1;
}
$this->redrawFrequency = $frequency;
$this->nextRedrawStep = $frequency;
}
/**
* @return float
*/
private function calculateTotalTime() : float
{
$endTime = microtime(true);
return $endTime - $this->startTime;
}
}
<?php
declare(strict_types=1);
/**
* File: Quiet.php
*
* @author Bartosz Kubicki bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
*/
namespace LizardMedia\CommunicationChannel\Model\Channel;
use LizardMedia\CommunicationChannel\Api\ChannelInterface;
/**
* Class Quiet
* @package LizardMedia\CommunicationChannel\Model\Channel
* @codeCoverageIgnore
*/
class Quiet implements ChannelInterface
{
/**
* @return void
*/
public function advanceProgress(): void
{
}
/**
* @param int $max
* @return void
*/
public function informAboutTotalCount(int $max) : void
{
}
/**
* @param string $error
* @return void
*/
public function informAboutError(string $error): void
{
}
/**
* @param string $message
* @return void
*/
public function inform(string $message) : void
{
}
/**
* @return void
*/
public function informThatFinished() : void
{
}
}
<?php
declare(strict_types=1);
/**
* File: ChannelFactory.php
*
* @author Bartosz Kubicki b.w.kubicki@gmail.com>
* Github: https://github.com/bartoszkubicki
*/
namespace LizardMedia\CommunicationChannel\Model;
use InvalidArgumentException;
use LizardMedia\CommunicationChannel\Api\ChannelFactoryInterface;
use LizardMedia\CommunicationChannel\Api\ChannelInterface;
use Magento\Framework\ObjectManager\ConfigInterface;
use Magento\Framework\ObjectManagerInterface;
use function in_array;
/**
* TODO: Unit test
* Class ChannelFactory
* @package LizardMedia\CommunicationChannel\Model
*/
class ChannelFactory implements ChannelFactoryInterface
{
/**
* @var ConfigInterface
*/
private $config;
/**
* @var ObjectManagerInterface
*/
private $objectManager;
/**
* ChannelAbstractFactory constructor.
*
* @param ConfigInterface $config
* @param ObjectManagerInterface $objectManager
*/
public function __construct(ConfigInterface $config, ObjectManagerInterface $objectManager)
{
$this->config = $config;
$this->objectManager = $objectManager;
}
/**
* @param string $type
* @param array $data
*
* @return ChannelInterface
* @throws InvalidArgumentException
*/
public function create(string $type, array $data = []): ChannelInterface
{
$this->validateType($type);
return $this->objectManager->create($type, $data);
}
/**
* @param string $type
* @return void
* @throws InvalidArgumentException
*/
private function validateType(string $type) : void
{
$realType = $this->config->getInstanceType(
$this->config->getPreference($type)
);
if (!in_array(
ChannelInterface::class,
array_unique(array_merge(class_parents($realType), class_implements($realType))),
true
)) {
$this->throwInvalidArgumentException($type);
}
}
/**
* @param string $type
*
* @return void
* @throws InvalidArgumentException
*/
private function throwInvalidArgumentException(string $type): void
{
throw new InvalidArgumentException(__('%1 is not instance of ChannelInterface', $type)->getText());
}
}
# Lizard Media Communication Channel
## Overview
Module offers abstraction layer for communication with end-user during long-running processes.
\ No newline at end of file
<?php
declare(strict_types=1);
/**
* File: ConsoleTest.php
*
* @author Bartosz Kubicki bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
*/
namespace LizardMedia\CommunicationChannel\Test\Unit\Model\CommunicationChannel;
use DG\BypassFinals;
use LizardMedia\CommunicationChannel\Model\Channel\Console;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use ReflectionClass;
use ReflectionException;
use Symfony\Component\Console\Helper\FormatterHelper;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Helper\ProgressBarFactory;
use Symfony\Component\Console\Output\ConsoleOutput;
/**
* Class ConsoleTest
* @package LizardMedia\CommunicationChannel\Test\Unit\Model\Channel
* @SuppressWarnings(PHPMD.LongVariable)
*/
class ConsoleTest extends TestCase
{
/**
* @var Console
*/
private $console;
/**
* @var MockObject|FormatterHelper
*/
private $formatterHelperMock;
/**
* @var MockObject|ProgressBar
*/
private $progressBarMock;
/**
* @var MockObject|ProgressBar
*/
private $progressBarFactoryMock;
/**
* @var MockObject|ConsoleOutput
*/
private $consoleOutputMock;
/**
* @return void
*/
protected function setUp(): void
{
parent::setUp();
//Dependencies mocks
$this->formatterHelperMock = $this->getMockBuilder(FormatterHelper::class)->getMock();
$this->progressBarFactoryMock = $this->getMockBuilder(ProgressBarFactory::class)
->disableOriginalConstructor()
->getMock();
$this->consoleOutputMock = $this->getMockBuilder(ConsoleOutput::class)
->disableOriginalConstructor()
->getMock();
BypassFinals::enable();
$this->progressBarMock = $this->getMockBuilder(ProgressBar::class)
->disableOriginalCOnstructor()
->getMock();
$this->console = new Console(
$this->formatterHelperMock,
$this->progressBarFactoryMock,
$this->consoleOutputMock
);
}
/**
* @return void
* @throws ReflectionException
*/
public function testAdvanceProgressIfProgressBarExist(): void
{
$this->expectationsForAlreadyExistingProgressBar();
$this->progressBarMock->expects($this->once())
->method('advance');
$this->console->advanceProgress();
}
/**
* @return void
*/
public function testInformAboutTotalCountCorrectlyProvidesInformation(): void
{
$this->progressBarFactoryMock->expects($this->once())
->method('create')
->with(
[
'output' => $this->consoleOutputMock,
'max' => 100
]
)
->willReturn($this->progressBarMock);
$this->progressBarMock->expects($this->once())
->method('setFormat')
->with('verbose');
$this->progressBarMock->expects($this->once())
->method('setRedrawFrequency')
->with(1);
$this->progressBarMock->expects($this->once())
->method('start');
$this->console->informAboutTotalCount(100);
$this->assertAttributeInstanceOf(ProgressBar::class, 'progressBar', $this->console);
}
/**
* @return void
*/
public function testInformAboutErrorCorrectlyProvidesErrorInformation(): void
{
$this->formatterHelperMock->expects($this->once())
->method('formatBlock')
->with('some error message', 'error')
->willReturn('<error>some error message</error>');
$this->consoleOutputMock->expects($this->once())
->method('writeln')
->with('<error>some error message</error>');
$this->console->informAboutError('some error message');
}
/**
* @return void
*/
public function testInformCorrectlyProvidesInformation(): void
{
$this->formatterHelperMock->expects($this->once())
->method('formatBlock')
->with('some info', 'info')
->willReturn('<info>some info</info>');
$this->consoleOutputMock->expects($this->once())
->method('writeln')
->with('<info>some info</info>');
$this->console->inform('some info');
}
/**
* @throws ReflectionException
*/
public function testInformThatFinishedIfProgressBarExists(): void
{
$this->expectationsForAlreadyExistingProgressBar();
$this->progressBarMock->expects($this->once())
->method('finish');
$this->console->informThatFinished();
}
/**
* @return void
* @throws ReflectionException
*/
private function expectationsForAlreadyExistingProgressBar(): void
{
$reflection = new ReflectionClass($this->console);
$reflectionProperty = $reflection->getProperty('progressBar');
$reflectionProperty->setAccessible(true);
$reflectionProperty->setValue($this->console, $this->progressBarMock);
}
}
<?php
declare(strict_types=1);
/**
* File: LogTest.php
*
* @author Bartosz Kubicki bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
*/
namespace LizardMedia\CommunicationChannel\Test\Unit\Model\Channel;
use LizardMedia\CommunicationChannel\Model\Channel\Log;
use PHPUnit\Framework\MockObject\MockObject as MockObject;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
use ReflectionException;
use ReflectionProperty;
/**
* Class LogTest
* @package LizardMedia\CommunicationChannel\Test\Unit\Model\Channel
*/
class LogTest extends TestCase
{
/**
* @var Log
*/
private $log;
/**
* @var MockObject|LoggerInterface
*/
private $loggerMock;
/**
* @return void
*/
protected function setUp(): void
{
parent::setUp();
$this->loggerMock = $this->getMockBuilder(LoggerInterface::class)->getMock();
$this->log = new Log($this->loggerMock);
}
/**
* @return void
*/
public function testAdvanceProgressCorrectlyInformsAboutProgressWhenTotalCountNotSet(): void
{
$this->loggerMock->expects($this->never())->method('info');
$this->log->advanceProgress();
}
/**
* @dataProvider provideEntityCountAndAdvanceProgressCallsCount
*
* @param int $totalCount
* @param int $advanceProgressCallsCount
* @return void
* @throws ReflectionException
* @SuppressWarnings(PHPMD.LongVariable)
*/
public function testAdvanceProgressCorrectlyInformsAboutProgress(
int $totalCount,
int $advanceProgressCallsCount
): void {
$reflection = new ReflectionProperty($this->log, 'totalCount');
$reflection->setAccessible(true);
$reflection->setValue($this->log, $totalCount);
$reflection = new ReflectionProperty($this->log, 'redrawFrequency');
$reflection->setAccessible(true);
$reflection->setValue($this->log, (int) round(0.01 * $totalCount));
$this->loggerMock->expects($this->exactly($advanceProgressCallsCount))
->method('info');
for ($i = 1; $i <= $totalCount; $i++) {
$this->log->advanceProgress();
}
}
/**
* @return array
*/
public function provideEntityCountAndAdvanceProgressCallsCount() : array
{
return [
[100, 100],
[333, 112],
[497, 101],
[863, 97]
];
}
/**
* @dataProvider provideDifferentEntitiesCount
*
* @param int $totalCount
* @param int $redrawFrequency
* @return void
*/
public function testInformAboutTotalCountWorksCorrectly(int $totalCount, int $redrawFrequency): void
{
$this->loggerMock->expects($this->once())
->method('info');
$this->log->informAboutTotalCount($totalCount);
$this->assertAttributeSame($redrawFrequency, 'redrawFrequency', $this->log);
}
/**
* @return array
*/
public function provideDifferentEntitiesCount() : array
{
return [
[10, 1],
[100, 1],
[333, 3],
[497, 5]
];
}
/**
* @return void
*/
public function testInformAboutErrorWorksCorrectly(): void
{
$this->loggerMock->expects($this->once())
->method('error')
->with('');
$this->log->informAboutError('');
}
/**
* @return void
*/
public function testInformWorksCorrectly(): void
{
$this->loggerMock->expects($this->once())
->method('info')
->with('');
$this->log->inform('');
}
/**
* @return void
*/
public function testInformThatFinishedWorksCorrectly(): void
{
$this->loggerMock->expects($this->exactly(2))
->method('info');
$this->log->informThatFinished();
}
}
<?php
declare(strict_types=1);
/**
* File: ChannelAbstractFactoryTest.php
*
* @author Bartosz Kubicki bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
*/
namespace LizardMedia\CommunicationChannel\Test\Unit\Model;
use InvalidArgumentException;
use LizardMedia\CommunicationChannel\Model\ChannelFactory;
use LizardMedia\CommunicationChannel\Test\Unit\Stub\Model\ChannelStub;
use Magento\Framework\ObjectManager\ConfigInterface;
use Magento\Framework\ObjectManagerInterface;
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\MockObject\MockObject;
use SplFileObject;
/**
* Class ChannelAbstractFactoryTest
* @package LizardMedia\CommunicationChannel\Test\Unit\Model
*/
class ChannelFactoryTest extends TestCase
{
/**
* @var ChannelFactory
*/
private $channelFactory;
/**
* @var MockObject | ConfigInterface
*/
private $configMock;
/**
* @var MockObject|ObjectManagerInterface
*/
private $objectManagerMock;
/**
* @return void
*/
protected function setUp() : void
{
parent::setUp();
//Dependencies mocks
$this->objectManagerMock = $this->getMockBuilder(ObjectManagerInterface::class)->getMock();
$this->configMock = $this->getMockBuilder(ConfigInterface::class)->getMock();
$this->channelFactory = new ChannelFactory($this->configMock, $this->objectManagerMock);
}
/**
* @return void
*/
public function testCreateWhenTypeIsValid(): void
{
$this->configMock->expects($this->once())
->method('getPreference')
->with(ChannelStub::class)
->willReturn(ChannelStub::class);
$this->configMock->expects($this->once())
->method('getInstanceType')
->with(ChannelStub::class)
->willReturn(ChannelStub::class);
$this->objectManagerMock->expects($this->once())
->method('create')
->with(ChannelStub::class, [])
->willReturn(new ChannelStub());
$this->assertInstanceOf(
ChannelStub::class,
$this->channelFactory->create(ChannelStub::class, [])
);
}
/**
* @return void
*/
public function testCreateWhenTypeIsInvalid(): void
{
$this->configMock->expects($this->once())
->method('getPreference')
->with(SplFileObject::class)
->willReturn(SplFileObject::class);
$this->configMock->expects($this->once())
->method('getInstanceType')
->with(SplFileObject::class)
->willReturn(SplFileObject::class);
$this->objectManagerMock->expects($this->never())->method('create');
$this->expectException(InvalidArgumentException::class);
$this->channelFactory->create(SplFileObject::class);
}
}
<?php
declare(strict_types=1);
/**
* File: ChannelStub.php
*
* @author Bartosz Kubicki bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
*/
namespace LizardMedia\CommunicationChannel\Test\Unit\Stub\Model;
use LizardMedia\CommunicationChannel\Api\ChannelInterface;
/**
* Class ChannelStub
* @package LizardMedia\CommunicationChannel\Test\Unit\Stub\Model
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
class ChannelStub implements ChannelInterface
{
/**
* @return void
*/
public function advanceProgress(): void
{
}
/**
* @param int $max
* @return void
*/
public function informAboutTotalCount(int $max): void
{
}
/**
* @param string $message
* @return void
*/
public function inform(string $message): void
{
}
/**
* @param string $error
* @return void
*/
public function informAboutError(string $error): void
{
}
/**
* @return void
*/
public function informThatFinished(): void
{
}
}
{
"name": "lizardmedia/module-communication-channel",
"description": "Abstraction for communication with end-user during long-running processes",
"require": {
"php": "~7.2.0||~7.3.0",
"magento/framework": "102.0.*"
},
"require-dev": {
"phpunit/phpunit": "~6.5.0",
"dg/bypass-finals": "*"
},
"type": "magento2-module",
"version": "1.0.0",
"autoload": {
"files": [
"registration.php"
],
"psr-4": {
"LizardMedia\\CommunicationChannel\\": ""
}
}
}
<?xml version="1.0"?>
<!--
/**
* @author Bartosz Kubicki <bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2019 Lizard Media (http://lizardmedia.pl)
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<!-- API section -->
<preference for="LizardMedia\CommunicationChannel\Api\ChannelFactoryInterface"
type="LizardMedia\CommunicationChannel\Model\ChannelFactory" />
<!-- End of API section -->
<!-- Logger virtual type section -->
<virtualType name="Virtual\CommunicationChannel\Logger\Handler\ProgressDefaultHandler"
type="Magento\Framework\Logger\Handler\Base">
<arguments>
<argument name="fileName" xsi:type="string">/var/log/process/progress_default.log</argument>
<argument name="loggerType" xsi:type="const">Monolog\Logger::DEBUG</argument>
</arguments>
</virtualType>
<virtualType name="Virtual\CommunicationChannel\Logger\ProgressDefaultLogger"
type="Magento\Framework\Logger\Monolog">
<arguments>
<argument name="handlers" xsi:type="array">
<item name="debug" xsi:type="object">Virtual\CommunicationChannel\Logger\Handler\ProgressDefaultHandler</item>
</argument>
</arguments>
</virtualType>
<!-- End of logger virtual type section -->
<!--Constructor parameter injection section-->
<type name="LizardMedia\CommunicationChannel\Model\CommunicationChannel\Log">
<arguments>
<argument name="logger" xsi:type="object">Virtual\CommunicationChannel\Logger\ProgressDefaultLogger</argument>
</arguments>
</type>
<!--End of constructor parameter injection section-->
</config>
\ No newline at end of file
<?xml version="1.0"?>
<!--
/**
* @author Bartosz Kubicki <bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2019 Lizard Media (http://lizardmedia.pl)
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="LizardMedia_CommunicationChannel" setup_version="1.0.0">
</module>
</config>
\ No newline at end of file
<?php
/**
* File: registration.php
*
* @author Bartosz Kubicki bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
*/
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'LizardMedia_CommunicationChannel',
__DIR__
);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment