diff --git a/hw19/.docker/nginx/Dockerfile b/hw19/.docker/nginx/Dockerfile
new file mode 100644
index 000000000..d19ea279d
--- /dev/null
+++ b/hw19/.docker/nginx/Dockerfile
@@ -0,0 +1,5 @@
+FROM nginx
+
+WORKDIR /var/www/html
+
+COPY ngnix.conf /etc/nginx/nginx.conf
diff --git a/hw19/.docker/nginx/ngnix.conf b/hw19/.docker/nginx/ngnix.conf
new file mode 100644
index 000000000..291af686f
--- /dev/null
+++ b/hw19/.docker/nginx/ngnix.conf
@@ -0,0 +1,25 @@
+worker_processes 1;
+
+events {
+ worker_connections 1024;
+}
+
+http {
+ server {
+ listen 80;
+ server_name localhost;
+ root /var/www/html/public/;
+
+ location / {
+ index index.php;
+ try_files $uri $uri/ /index.php?$query_string;
+ }
+
+ location ~ \.php$ {
+ fastcgi_pass php-fpm:9000;
+ fastcgi_index index.php;
+ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+ include fastcgi_params;
+ }
+ }
+}
diff --git a/hw19/.docker/php-fpm/Dockerfile b/hw19/.docker/php-fpm/Dockerfile
new file mode 100644
index 000000000..6e76f71c9
--- /dev/null
+++ b/hw19/.docker/php-fpm/Dockerfile
@@ -0,0 +1,11 @@
+FROM php:8.2-fpm
+
+RUN apt-get update && apt-get install -y \
+ libzip-dev \
+ && docker-php-ext-install zip sockets
+
+RUN chown -R www-data:www-data /var/www/html
+
+WORKDIR /var/www/html
+
+CMD ["php-fpm"]
diff --git a/hw19/README.md b/hw19/README.md
new file mode 100644
index 000000000..94fb65b7c
--- /dev/null
+++ b/hw19/README.md
@@ -0,0 +1,12 @@
+# Работа с очередью
+
+## Отправка данных
+1. Для генерации банковской выписки за указанные даты перейдите в браузере на главную страницу http://localhost/
+2. Выберите нужный интервал дат
+3. Нажмите кнопку отправить
+4. После чего форма вас переадресует на страницу обработчика формы /formHandler, в котором даты отправятся через RabbitMQ Producer в очередь
+
+## Получение данных
+1. Чтобы считать данную очередь, вам нужно зайти в консоль и запуcтить команду php bin/console rabbitmq:consumer
+2. Теперь в консоли вы можете видеть отправленные из браузерной формы даты
+3. Также в консольной команде после вывода данных на экран происходит отправка письма.
diff --git a/hw19/docker-compose.yml b/hw19/docker-compose.yml
new file mode 100644
index 000000000..ee7740850
--- /dev/null
+++ b/hw19/docker-compose.yml
@@ -0,0 +1,36 @@
+version: "3"
+services:
+ nginx:
+ container_name: nginx-otusphp
+ build: ./.docker/nginx
+ ports:
+ - "80:80"
+ volumes:
+ - ./www:/var/www/html
+ depends_on:
+ - php-fpm
+ networks:
+ - otusphp
+
+ php-fpm:
+ container_name: php-fpm-otusphp
+ build: ./.docker/php-fpm/
+ volumes:
+ - ./www:/var/www/html
+ depends_on:
+ - rabbitmq
+ networks:
+ - otusphp
+
+ rabbitmq:
+ container_name: rabbitmq-otusphp
+ image: rabbitmq:3.10.7-management
+ ports:
+ - 15672:15672
+ - 5672:5672
+ networks:
+ - otusphp
+
+networks:
+ otusphp:
+ driver: bridge
diff --git a/hw19/www/.env.example b/hw19/www/.env.example
new file mode 100644
index 000000000..c6b0c3ac9
--- /dev/null
+++ b/hw19/www/.env.example
@@ -0,0 +1,14 @@
+BROKER_CONNECT='Shabanov\Otusphp\Connection\RabbitMqConnect'
+BROKER_HOST='rabbitmq'
+BROKER_PORT=5672
+BROKER_USER='guest'
+BROKER_PASSWORD='guest'
+EXCHANGE='shabanov'
+QUEUE='otus'
+
+EMAIL_SMTP='smtp.yandex.ru'
+EMAIL_PORT=465
+EMAIL_USER='saveliy'
+EMAIL_PASSWORD='123456'
+EMAIL_FROM='saveliy@mail.ru'
+EMAIL_TO='infotest@mail.ru'
diff --git a/hw19/www/bin/console b/hw19/www/bin/console
new file mode 100755
index 000000000..0b0cad0cb
--- /dev/null
+++ b/hw19/www/bin/console
@@ -0,0 +1,20 @@
+#!/usr/bin/env php
+load(__DIR__ . '/../.env');
+
+$application = new Application();
+$application->add(new ConsumerCommand(new $_ENV['BROKER_CONNECT']()));
+try {
+ $application->run();
+} catch (Exception $e) {
+ throw new \Exception($e->getMessage());
+}
diff --git a/hw19/www/composer.json b/hw19/www/composer.json
new file mode 100644
index 000000000..0643f55f4
--- /dev/null
+++ b/hw19/www/composer.json
@@ -0,0 +1,21 @@
+{
+ "name": "shabanov/otusphp",
+ "autoload": {
+ "psr-4": {
+ "Shabanov\\Otusphp\\": "src/"
+ }
+ },
+ "authors": [
+ {
+ "name": "Vyacheslav Shabanov",
+ "email": "saveliy@mail.ru"
+ }
+ ],
+ "require": {
+ "php-amqplib/php-amqplib": "^3.6",
+ "symfony/console": "^7.0",
+ "symfony/mailer": "^7.0",
+ "symfony/dotenv": "^7.0",
+ "phpmailer/phpmailer": "^6.9"
+ }
+}
diff --git a/hw19/www/public/index.php b/hw19/www/public/index.php
new file mode 100644
index 000000000..f434cc343
--- /dev/null
+++ b/hw19/www/public/index.php
@@ -0,0 +1,13 @@
+getMessage());
+}
diff --git a/hw19/www/src/App.php b/hw19/www/src/App.php
new file mode 100644
index 000000000..398d2cef7
--- /dev/null
+++ b/hw19/www/src/App.php
@@ -0,0 +1,20 @@
+load(__DIR__ . '/../.env');
+ }
+
+ public function __invoke(): void
+ {
+ (new Route($_SERVER['REQUEST_URI']))->run();
+ }
+}
diff --git a/hw19/www/src/Command/ConsumerCommand.php b/hw19/www/src/Command/ConsumerCommand.php
new file mode 100644
index 000000000..9a21fe6b1
--- /dev/null
+++ b/hw19/www/src/Command/ConsumerCommand.php
@@ -0,0 +1,38 @@
+channel = $this->connect->getClient();
+ $this->queue = $_ENV['QUEUE'];
+ }
+
+ protected function configure(): void
+ {
+ $this->setName('rabbitmq:consumer')
+ ->setDescription('RabbitMQ consumer обработчик формы');
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output): int
+ {
+ (new RabbitMqConsumer($this->connect, $output))->run();
+
+ return Command::SUCCESS;
+ }
+}
diff --git a/hw19/www/src/Connection/ConnectionInterface.php b/hw19/www/src/Connection/ConnectionInterface.php
new file mode 100644
index 000000000..a851cd355
--- /dev/null
+++ b/hw19/www/src/Connection/ConnectionInterface.php
@@ -0,0 +1,10 @@
+connect = new AMQPStreamConnection(
+ $_ENV['BROKER_HOST'],
+ $_ENV['BROKER_PORT'],
+ $_ENV['BROKER_USER'],
+ $_ENV['BROKER_PASSWORD']
+ );
+ }
+ public function getClient(): AMQPChannel|AbstractChannel
+ {
+ return $this->connect->channel();
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function close(): void
+ {
+ $this->connect->close();
+ }
+}
diff --git a/hw19/www/src/Consumer/RabbitMqConsumer.php b/hw19/www/src/Consumer/RabbitMqConsumer.php
new file mode 100644
index 000000000..51130f664
--- /dev/null
+++ b/hw19/www/src/Consumer/RabbitMqConsumer.php
@@ -0,0 +1,61 @@
+channel = $this->connect->getClient();
+ $this->queue = $_ENV['QUEUE'];
+ }
+
+ public function run(): void
+ {
+ $this->channel->basic_consume(
+ $this->queue,
+ '',
+ false,
+ true,
+ false,
+ false,
+ [$this, 'consumeHandler']
+ );
+
+ while ($this->channel->is_consuming()) {
+ $this->channel->wait();
+ }
+
+ $this->close();
+ }
+
+ public function consumeHandler(AMQPMessage $message): void
+ {
+ /**
+ * Выведим в консоль данные
+ */
+ $this->output->writeln('
404 Not Found
+ + + +Спасибо за вашу заявку. Скоро на email вам поступит отчет
+ 'main', + '/formHandler' => 'formHandler', + ]; + public function __construct(private string $url) + {} + + public function run(): void + { + $action = self::MAP[$this->url] ?? null; + if ($action !== null) { + $controller = new PageController(); + if (method_exists($controller, $action)) { + $controller->$action(); + return; + } + } + + http_response_code(404); + echo (new Error404Render())->show(); + } +}