From ca8bbc31efe99ed273ffec883dc717633004e074 Mon Sep 17 00:00:00 2001 From: yessaliyev <40271311+yessaliyev@users.noreply.github.com> Date: Mon, 12 Jul 2021 09:06:34 +0600 Subject: [PATCH 1/2] =?UTF-8?q?=D0=B2=D0=B0=D0=BB=D0=B8=D0=B4=D0=B0=D1=82?= =?UTF-8?q?=D0=BE=D1=80=20=D1=81=D0=BA=D0=BE=D0=B1=D0=BE=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 2 + .gitignore | 3 ++ app/composer.json | 18 +++++++++ app/composer.lock | 20 ++++++++++ app/public/index.php | 13 +++++++ app/src/App.php | 24 ++++++++++++ app/src/Bracket/BracketValidator.php | 51 +++++++++++++++++++++++++ app/src/Exceptions/RequestException.php | 13 +++++++ app/src/Request.php | 30 +++++++++++++++ app/src/Response.php | 25 ++++++++++++ docker-compose.yml | 29 ++++++++++++++ docker/nginx/Dockerfile | 11 ++++++ docker/nginx/mysite.conf | 21 ++++++++++ docker/nginx/nginx.conf | 40 +++++++++++++++++++ docker/php-fpm/Dockerfile | 50 ++++++++++++++++++++++++ docker/php-fpm/zz-docker.conf | 8 ++++ 16 files changed, 358 insertions(+) create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 app/composer.json create mode 100644 app/composer.lock create mode 100644 app/public/index.php create mode 100644 app/src/App.php create mode 100644 app/src/Bracket/BracketValidator.php create mode 100644 app/src/Exceptions/RequestException.php create mode 100644 app/src/Request.php create mode 100644 app/src/Response.php create mode 100644 docker-compose.yml create mode 100644 docker/nginx/Dockerfile create mode 100644 docker/nginx/mysite.conf create mode 100644 docker/nginx/nginx.conf create mode 100644 docker/php-fpm/Dockerfile create mode 100644 docker/php-fpm/zz-docker.conf diff --git a/.env.example b/.env.example new file mode 100644 index 000000000..91a80adb9 --- /dev/null +++ b/.env.example @@ -0,0 +1,2 @@ +UID=3000 +NGINX_PHP_USER=nginxphpuser \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..b21c49049 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.env +data +vendor \ No newline at end of file diff --git a/app/composer.json b/app/composer.json new file mode 100644 index 000000000..40c593dad --- /dev/null +++ b/app/composer.json @@ -0,0 +1,18 @@ +{ + "name": "rsm/app", + "type": "project", + "authors": [ + { + "name": "yessaliyev", + "email": "40271311+yessaliyev@users.noreply.github.com" + } + ], + "require": { + "php": ">=7.4" + }, + "autoload": { + "psr-4": { + "App\\": "src" + } + } +} diff --git a/app/composer.lock b/app/composer.lock new file mode 100644 index 000000000..5694657be --- /dev/null +++ b/app/composer.lock @@ -0,0 +1,20 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "8e59a3b61ad6046e157ef7d1c264acf4", + "packages": [], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">=7.4" + }, + "platform-dev": [], + "plugin-api-version": "2.0.0" +} diff --git a/app/public/index.php b/app/public/index.php new file mode 100644 index 000000000..c7f68613d --- /dev/null +++ b/app/public/index.php @@ -0,0 +1,13 @@ +run(); +} catch (\Throwable $e) { + Response::send($e->getCode(), $e->getMessage()); +} diff --git a/app/src/App.php b/app/src/App.php new file mode 100644 index 000000000..b91ee10e0 --- /dev/null +++ b/app/src/App.php @@ -0,0 +1,24 @@ +getData(); + + if (empty($data['string'])) { + throw new RequestException('Не передан string', 400); + } + + $validator = new BracketValidator($data['string']); + $validator->check(); + } +} \ No newline at end of file diff --git a/app/src/Bracket/BracketValidator.php b/app/src/Bracket/BracketValidator.php new file mode 100644 index 000000000..cc2daeb69 --- /dev/null +++ b/app/src/Bracket/BracketValidator.php @@ -0,0 +1,51 @@ +brackets = $brackets; + } + + public function check() + { + if (!$this->validate()) { + throw new RequestException('invalid format', 400); + } + + Response::send(200, 'correct'); + } + + private function validate() : bool + { + + if (empty(trim($this->brackets))) { + return false; + } + + if ( ($this->brackets[0] === ')') || (substr($this->brackets, -1, 1) === '(') ) { + return false; + } + + foreach (str_split($this->brackets) as $value) { + + if ($value === '(') { + $arr[] = $value; + continue; + } + + if ($value === ')' && (empty($arr) || array_pop($arr) !== '(')) { + return false; + } + } + + return empty($arr); + } +} diff --git a/app/src/Exceptions/RequestException.php b/app/src/Exceptions/RequestException.php new file mode 100644 index 000000000..297973af1 --- /dev/null +++ b/app/src/Exceptions/RequestException.php @@ -0,0 +1,13 @@ +data = json_decode($json, true); + } + + public function getData(): array + { + return $this->data; + } +} \ No newline at end of file diff --git a/app/src/Response.php b/app/src/Response.php new file mode 100644 index 000000000..7f17060b5 --- /dev/null +++ b/app/src/Response.php @@ -0,0 +1,25 @@ + '200 OK', + 400 => '400 Bad Request', + 422 => 'Unprocessable Entity', + 500 => '500 Internal Server Error' + ); + + header('Status: '.$status[$code]); + + $data['status'] = $code < 300 ? "success" : "error"; + $data['message'] = $message; + echo json_encode($data); + } +} \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..ab2e7be11 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,29 @@ +version: '3.8' + +services: + nginx: + container_name: nginx + build: + context: ./docker/nginx + args: + UID: $UID + NGINX_PHP_USER: $NGINX_PHP_USER + volumes: + - ./app:/var/www/html + - ./docker/sock:/sock + ports: + - "8787:80" + + php-fpm: + container_name: php-fpm + build: + context: ./docker/php-fpm + args: + UID: $UID + NGINX_PHP_USER: $NGINX_PHP_USER + volumes: + - ./app:/var/www/html + - ./docker/sock:/sock + + + diff --git a/docker/nginx/Dockerfile b/docker/nginx/Dockerfile new file mode 100644 index 000000000..fe1f2670b --- /dev/null +++ b/docker/nginx/Dockerfile @@ -0,0 +1,11 @@ +FROM nginx +WORKDIR /var/www/html + +ARG UID +ARG NGINX_PHP_USER + +COPY nginx.conf /etc/nginx/nginx.conf +COPY mysite.conf /etc/nginx/conf.d/default.conf +RUN addgroup --gid $UID --system $NGINX_PHP_USER \ + && adduser --uid $UID --system --disabled-login --disabled-password --gid $UID $NGINX_PHP_USER \ + && sed -i -r "s/%REPLACE_USERNAME%/$NGINX_PHP_USER/g" /etc/nginx/nginx.conf \ No newline at end of file diff --git a/docker/nginx/mysite.conf b/docker/nginx/mysite.conf new file mode 100644 index 000000000..2678122e7 --- /dev/null +++ b/docker/nginx/mysite.conf @@ -0,0 +1,21 @@ +server { + listen 80; + listen [::]:80; + + index index.php; + root /var/www/html/public; + + location / { + try_files $uri $uri/ /index.php?$query_string; + } + + location ~ \.php$ { + fastcgi_pass unix:/sock/docker.sock; + fastcgi_split_path_info ^(.+?\.php)(|/.*)$; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + } + + error_log /var/log/nginx/error.log; + access_log /var/log/nginx/access.log; +} \ No newline at end of file diff --git a/docker/nginx/nginx.conf b/docker/nginx/nginx.conf new file mode 100644 index 000000000..29b8d8a6c --- /dev/null +++ b/docker/nginx/nginx.conf @@ -0,0 +1,40 @@ +user %REPLACE_USERNAME%; +worker_processes auto; + +pid /var/run/nginx.pid; +error_log /var/log/nginx/error.log crit; + +events { + use epoll; + worker_connections 4096; + multi_accept on; +} +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + access_log off; + + keepalive_timeout 30; + keepalive_requests 100; + + client_max_body_size 1m; + client_body_timeout 10; + reset_timedout_connection on; + send_timeout 2; + sendfile on; + tcp_nodelay on; + tcp_nopush on; + + gzip on; + gzip_disable "msie6"; + gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript; + + open_file_cache max=200000 inactive=20s; + open_file_cache_valid 30s; + open_file_cache_min_uses 2; + open_file_cache_errors on; + + include /etc/nginx/conf.d/*.conf; + +} \ No newline at end of file diff --git a/docker/php-fpm/Dockerfile b/docker/php-fpm/Dockerfile new file mode 100644 index 000000000..1bab9d5f4 --- /dev/null +++ b/docker/php-fpm/Dockerfile @@ -0,0 +1,50 @@ +FROM php:7.4-fpm + +ARG UID +ARG NGINX_PHP_USER +ENV DOCKER_PATH=/usr/local/etc/php-fpm.d/zz-docker.conf + +COPY zz-docker.conf $DOCKER_PATH + + +RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" \ + && apt-get update \ + && apt-get install -y \ + git \ + curl \ + wget \ + grep \ + zip \ + unzip \ + libmemcached-dev \ + zlib1g-dev \ + libzip-dev \ + libcurl4-openssl-dev \ + libbrotli-dev \ + libevent-dev \ + libicu-dev \ + libidn11-dev \ + libidn2-0-dev \ + libssl-dev \ + libpq-dev \ + libonig-dev \ + librabbitmq-dev \ + nano \ + && docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql \ + && pecl install memcached \ + && docker-php-ext-enable memcached \ + && docker-php-ext-install pdo pdo_pgsql pgsql \ + && pecl install xdebug-2.9.8 && docker-php-ext-enable xdebug \ + && pecl install -o redis && docker-php-ext-enable redis \ + && docker-php-ext-install zip sockets bcmath mbstring \ + && pecl install amqp && docker-php-ext-enable amqp \ + && addgroup --gid $UID --system $NGINX_PHP_USER \ + && adduser --uid $UID --system --disabled-login --disabled-password --gid $UID $NGINX_PHP_USER \ + && sed -i -r "s/%REPLACE_USERNAME%/$NGINX_PHP_USER/g" $DOCKER_PATH \ + && rm -rf /tmp/pear + +RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer + +WORKDIR /var/www/html + +CMD ["php-fpm"] \ No newline at end of file diff --git a/docker/php-fpm/zz-docker.conf b/docker/php-fpm/zz-docker.conf new file mode 100644 index 000000000..322ee8743 --- /dev/null +++ b/docker/php-fpm/zz-docker.conf @@ -0,0 +1,8 @@ +[global] +daemonize = no + +[www] +listen = /sock/docker.sock +listen.owner = %REPLACE_USERNAME% +listen.group = %REPLACE_USERNAME% +listen.mode = 0660 \ No newline at end of file From 7858f0a600750026f77827b00e184f17a4885c86 Mon Sep 17 00:00:00 2001 From: yessaliyev <40271311+yessaliyev@users.noreply.github.com> Date: Tue, 13 Jul 2021 09:52:04 +0600 Subject: [PATCH 2/2] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=B7=D0=B0=D0=BC=D0=B5=D1=87=D0=B0=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/Bracket/BracketValidator.php | 29 ++++++++++------------------ 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/app/src/Bracket/BracketValidator.php b/app/src/Bracket/BracketValidator.php index cc2daeb69..60fcbac12 100644 --- a/app/src/Bracket/BracketValidator.php +++ b/app/src/Bracket/BracketValidator.php @@ -7,11 +7,11 @@ class BracketValidator { - private string $brackets; + private array $brackets; public function __construct(string $brackets) { - $this->brackets = $brackets; + $this->brackets = str_split($brackets); } public function check() @@ -25,27 +25,18 @@ public function check() private function validate() : bool { - - if (empty(trim($this->brackets))) { - return false; - } - - if ( ($this->brackets[0] === ')') || (substr($this->brackets, -1, 1) === '(') ) { + if (empty($this->brackets)) { return false; } - foreach (str_split($this->brackets) as $value) { - - if ($value === '(') { - $arr[] = $value; - continue; - } - - if ($value === ')' && (empty($arr) || array_pop($arr) !== '(')) { - return false; + $counter = 0; + foreach ($this->brackets as $bracket) { + if ($bracket === '(') { + $counter++; + } else { + $counter--; } } - - return empty($arr); + return $counter === 0 && end($this->brackets) !== '('; } }