Compare commits
78 Commits
f49c7287fd
...
139c313a84
Author | SHA1 | Date | |
---|---|---|---|
|
139c313a84 | ||
|
64f1621e04 | ||
|
f9ee00b29b | ||
|
562599b00f | ||
|
f394bf42eb | ||
|
59118cd6a4 | ||
|
961711b34b | ||
|
d7ec6aee4d | ||
|
af801110aa | ||
|
d86c1fa0f8 | ||
|
53c72f729e | ||
|
188494a996 | ||
|
2f14e147b5 | ||
|
0bdc9cafc0 | ||
|
8ea48bcaf3 | ||
|
c4150dc362 | ||
|
4ed6c45441 | ||
|
eaf58bd477 | ||
|
69d51636f2 | ||
|
a865c5ec8d | ||
|
106aa2149e | ||
|
fb6cc37dd8 | ||
|
17dd5ed296 | ||
|
535f899aaf | ||
|
edba09be4c | ||
|
b71ca34dd3 | ||
|
65a9819b1b | ||
|
53d49d3894 | ||
|
ab56fe9917 | ||
|
75c0c98c8d | ||
|
c2b959a9da | ||
|
4647bb2cc1 | ||
|
2a96c5a863 | ||
|
3bc176936c | ||
|
e0574615a7 | ||
|
452a5c4993 | ||
|
85a2a2a4a7 | ||
|
ed8c62f4bd | ||
|
63c5f7572b | ||
|
531228dfca | ||
|
b8734d4dc6 | ||
|
7db9517840 | ||
|
ab9e1b5b99 | ||
|
c72bf86a96 | ||
|
a893929cf9 | ||
|
ec23a41e37 | ||
|
7279f2096e | ||
|
cde6507197 | ||
|
10756226f1 | ||
|
5c8a0238f1 | ||
|
87e4121444 | ||
|
ea283a86e7 | ||
|
ae05646888 | ||
|
3e695bfef7 | ||
|
1a0515742e | ||
|
50a79470e7 | ||
|
7ffd3c02cd | ||
|
e6c5047408 | ||
|
87255eaf13 | ||
|
ee0cde0400 | ||
|
45004444e6 | ||
|
a9a0f2f413 | ||
|
9f3f6bf22b | ||
|
a3de2b244f | ||
|
950e310096 | ||
|
847e3a078f | ||
|
67f7ba2a88 | ||
|
6bd71f0ec5 | ||
|
c1a58f4bd6 | ||
|
934561ca0e | ||
|
c602737ba1 | ||
|
ee3dc50914 | ||
|
4d98a8607b | ||
|
92c12d1c9a | ||
|
dd5fbc1ed8 | ||
|
a7bd34677b | ||
|
66e45c8112 | ||
|
9ecadfd4d1 |
1
.docker-compose/api/.env
Normal file
1
.docker-compose/api/.env
Normal file
@ -0,0 +1 @@
|
|||||||
|
PHP_IDE_CONFIG=serverName=cojedzie
|
31
.docker-compose/nginx/cojedzie-rr.conf
Normal file
31
.docker-compose/nginx/cojedzie-rr.conf
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
server {
|
||||||
|
root /var/www/front/public/;
|
||||||
|
|
||||||
|
server_name cojedzie.localhost;
|
||||||
|
|
||||||
|
location /_profiler/ {
|
||||||
|
try_files $uri $uri/ @api;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /bundles/ {
|
||||||
|
try_files $uri $uri/ @api;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /api/ {
|
||||||
|
try_files $uri $uri/ @api;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ @frontend;
|
||||||
|
}
|
||||||
|
|
||||||
|
location @frontend {
|
||||||
|
proxy_pass http://frontend:3000;
|
||||||
|
proxy_intercept_errors on;
|
||||||
|
}
|
||||||
|
|
||||||
|
location @api {
|
||||||
|
proxy_pass http://api:8080;
|
||||||
|
proxy_intercept_errors on;
|
||||||
|
}
|
||||||
|
}
|
44
.docker-compose/nginx/cojedzie.conf
Normal file
44
.docker-compose/nginx/cojedzie.conf
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
server {
|
||||||
|
root /var/www/front/public/;
|
||||||
|
server_name cojedzie.localhost;
|
||||||
|
|
||||||
|
location /api/ {
|
||||||
|
root /var/www/api/public/;
|
||||||
|
try_files $uri $uri/ index.php$is_args$args;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /_profiler/ {
|
||||||
|
root /var/www/api/public/;
|
||||||
|
try_files $uri $uri/ index.php$is_args$args;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /bundles/ {
|
||||||
|
root /var/www/api/public/;
|
||||||
|
try_files $uri $uri/;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ @frontend;
|
||||||
|
}
|
||||||
|
|
||||||
|
location @frontend {
|
||||||
|
proxy_pass http://frontend:3000;
|
||||||
|
proxy_intercept_errors on;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~ (.+).php(/|$) {
|
||||||
|
root /var/www/api/public/;
|
||||||
|
|
||||||
|
fastcgi_pass api:9000;
|
||||||
|
fastcgi_split_path_info ^(.+\.php)(/.*)$;
|
||||||
|
|
||||||
|
include fastcgi_params;
|
||||||
|
fastcgi_param SCRIPT_FILENAME /var/www/public/$fastcgi_script_name;
|
||||||
|
fastcgi_param DOCUMENT_ROOT /var/www/public/;
|
||||||
|
|
||||||
|
fastcgi_param APP_ENV "dev";
|
||||||
|
fastcgi_param DATABASE_URL "sqlite:///%kernel.project_dir%/var/app.db";
|
||||||
|
|
||||||
|
internal;
|
||||||
|
}
|
||||||
|
}
|
17
.env.dist
17
.env.dist
@ -1,17 +0,0 @@
|
|||||||
# This file is a "template" of which env vars need to be defined for your application
|
|
||||||
# Copy this file to .env file for development, create environment variables when deploying to production
|
|
||||||
# https://symfony.com/doc/current/best_practices/configuration.html#infrastructure-related-configuration
|
|
||||||
|
|
||||||
GOOGLE_ANALYTICS=
|
|
||||||
|
|
||||||
###> symfony/framework-bundle ###
|
|
||||||
APP_ENV=dev
|
|
||||||
APP_SECRET=1bdf86cdc78fba654e4f2c309c6bbdbd
|
|
||||||
###< symfony/framework-bundle ###
|
|
||||||
|
|
||||||
###> doctrine/doctrine-bundle ###
|
|
||||||
# Format described at http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
|
|
||||||
# For an SQLite database, use: "sqlite:///%kernel.project_dir%/var/data.db"
|
|
||||||
# Configure your db driver and server_version in config/packages/doctrine.yaml
|
|
||||||
DATABASE_URL=sqlite:///%kernel.project_dir%/var/app.db
|
|
||||||
###< doctrine/doctrine-bundle ###
|
|
18
.gitignore
vendored
18
.gitignore
vendored
@ -1,19 +1 @@
|
|||||||
|
|
||||||
###> symfony/framework-bundle ###
|
|
||||||
/.env
|
|
||||||
/public/bundles/
|
|
||||||
/var/
|
|
||||||
/vendor/
|
|
||||||
###< symfony/framework-bundle ###
|
|
||||||
|
|
||||||
###> symfony/web-server-bundle ###
|
|
||||||
/.web-server-pid
|
|
||||||
###< symfony/web-server-bundle ###
|
|
||||||
|
|
||||||
/node_modules/
|
|
||||||
/.idea/
|
/.idea/
|
||||||
/public/*
|
|
||||||
!/public/index.php
|
|
||||||
!/public/manifest.jso
|
|
||||||
|
|
||||||
/yarn-error.log
|
|
||||||
|
71
CLA.md
Normal file
71
CLA.md
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
# Co Jedzie Individual Contributor License Agreement
|
||||||
|
|
||||||
|
Adapted from http://www.apache.org/licenses/icla.txt © The Apache Software Foundation
|
||||||
|
|
||||||
|
Thank you for your interest in Co Jedzie (the **"Project"**) by Kacper Donat (the **"Author"**). In order to clarify the
|
||||||
|
intellectual property license granted with Contributions from any person or entity, the Author must have a Contributor
|
||||||
|
License Agreement ("CLA") on file that has been signed by each Contributor, indicating agreement to the license terms
|
||||||
|
below. This license is for your protection as a Contributor as well as the protection of the Author and its users; it
|
||||||
|
does not change your rights to use your own Contributions for any other purpose.
|
||||||
|
|
||||||
|
You accept and agree to the following terms and conditions for Your present and future Contributions submitted to the
|
||||||
|
Author. In return, the Author shall not use Your Contributions in a way that is contrary to the public benefit or
|
||||||
|
inconsistent with its bylaws in effect at the time of the Contribution. Except for the license granted herein to the
|
||||||
|
Author and recipients of software distributed by the Author, You reserve all right, title, and interest in and to Your
|
||||||
|
Contributions.
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
- **"You"** (or **"Your"**) shall mean the copyright owner or legal entity authorized by the copyright owner that is
|
||||||
|
making this Agreement with the Author. For legal entities, the entity making a Contribution and all other entities
|
||||||
|
that control, are controlled by, or are under common control with that entity are considered to be a single
|
||||||
|
Contributor. For the purposes of this definition, **"control"** means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or
|
||||||
|
more of the outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
- **"Contribution"** shall mean any original work of authorship, including any modifications or additions to an existing
|
||||||
|
work, that is intentionally submitted by You to the Author for inclusion in, or documentation of, any of the products
|
||||||
|
owned or managed by the Author (the **"Work"**). For the purposes of this definition, **"submitted"** means any form
|
||||||
|
of electronic, verbal, or written communication sent to the Author or its representatives, including but not limited
|
||||||
|
to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed
|
||||||
|
by, or on behalf of, the Author for the purpose of discussing and improving the Work, but excluding communication that
|
||||||
|
is conspicuously marked or otherwise designated in writing by You as **"Not a Contribution."**
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to the Author and
|
||||||
|
to recipients of software distributed by the Author a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
||||||
|
irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform,
|
||||||
|
sublicense, re-license, and distribute Your Contributions and such derivative works.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to the Author and to
|
||||||
|
recipients of software distributed by the Author a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
||||||
|
irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import,
|
||||||
|
and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are
|
||||||
|
necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which
|
||||||
|
such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (
|
||||||
|
including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have
|
||||||
|
contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity
|
||||||
|
under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. You represent that you are legally entitled to grant the above license. If your employer(s) has rights to
|
||||||
|
intellectual property that you create that includes your Contributions, you represent that you have received
|
||||||
|
permission to make Contributions on behalf of that employer, that your employer has waived such rights for your
|
||||||
|
Contributions to the Author, or that your employer has executed a separate Corporate CLA with the Author.
|
||||||
|
|
||||||
|
5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of
|
||||||
|
others). You represent that Your Contribution submissions include complete details of any third-party license or
|
||||||
|
other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware
|
||||||
|
and which are associated with any part of Your Contributions.
|
||||||
|
|
||||||
|
6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support.
|
||||||
|
You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in
|
||||||
|
writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
|
||||||
|
express or implied, including, without limitation, any warranties or conditions of TITLE, NON- INFRINGEMENT,
|
||||||
|
MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
7. Should You wish to submit work that is not Your original creation, You may submit it to the Author separately from
|
||||||
|
any Contribution, identifying the complete details of its source and of any license or other restriction (including,
|
||||||
|
but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and
|
||||||
|
conspicuously marking the work as "Submitted on behalf of a third-party: [named here]".
|
||||||
|
|
||||||
|
8. You agree to notify the Author of any facts or circumstances of which you become aware that would make these
|
||||||
|
representations inaccurate in any respect.
|
||||||
|
|
38
CONTRIBUTING.md
Normal file
38
CONTRIBUTING.md
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# How to contribute?
|
||||||
|
|
||||||
|
Thanks for your interest in the project!
|
||||||
|
|
||||||
|
## I'd like to propose some feature / change...
|
||||||
|
|
||||||
|
Cool! Go ahead, [create an issue] and describe your proposal so anyone can see it. You can also vote on features that
|
||||||
|
you want the most.
|
||||||
|
|
||||||
|
## I've found a bug!
|
||||||
|
|
||||||
|
Well, less cool! Before creating an issue, please check if the bug remains after hard refreshing (usually `ctrl+F5`) the
|
||||||
|
application. If the answer is yes, or this is not the first encounter of it please [create an issue] and describe the
|
||||||
|
problem. If you can, please attach screenshots (especially if this is visual bug), and console logs (especially for
|
||||||
|
connection problems) - this will help to reproduce the problem.
|
||||||
|
|
||||||
|
## I've got some spare resources on my server...
|
||||||
|
Soon you will be able to help the project by hosting your own API node that will be available for clients to use.
|
||||||
|
More details to come soon.
|
||||||
|
|
||||||
|
## I want to contribute some code...
|
||||||
|
|
||||||
|
That's great! If you want to make changes to API (which is responsible for collecting and supplying applicaiton with
|
||||||
|
data) please check the [API contribution guidelines], if you are interested in UI side of the app please read the
|
||||||
|
[frontend contribution guidelines].
|
||||||
|
|
||||||
|
### Contributor License Agreement
|
||||||
|
|
||||||
|
Unfortunately due to this project nature and license I need you to sign [Contributor License Agreement] - the nice thing
|
||||||
|
is that it can be done with simple push of a button! **You still will have full copyright to your contribution** but
|
||||||
|
basically you consent that you are entitled to code you are submitting and also to allow me to license this project on
|
||||||
|
other terms if needed to, for example, local governments. If you don't want to sign - I understand - but I won't be able
|
||||||
|
to accept your contribution :(
|
||||||
|
|
||||||
|
[Contributor License Agreement]: ./CLA.md
|
||||||
|
[create an issue]: https://github.com/cojedzie/cojedzie/issues/new
|
||||||
|
[API contribution guidelines]: ./api/CONTRIBUTING.md
|
||||||
|
[frontend contribution guidelines]: ./front/CONTRIBUTING.md
|
41
LICENSE.md
Normal file
41
LICENSE.md
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
“Commons Clause” License Condition v1.0
|
||||||
|
|
||||||
|
The Software is provided to you by the Licensor under the License, as defined
|
||||||
|
below, subject to the following condition.
|
||||||
|
|
||||||
|
Without limiting other conditions in the License, the grant of rights under the
|
||||||
|
License will not include, and the License does not grant to you, the right to
|
||||||
|
Sell the Software.
|
||||||
|
|
||||||
|
For purposes of the foregoing, “Sell” means practicing any or all of the rights
|
||||||
|
granted to you under the License to provide to third parties, for a fee or other
|
||||||
|
consideration (including without limitation fees for hosting or consulting/
|
||||||
|
support services related to the Software), a product or service whose value
|
||||||
|
derives, entirely or substantially, from the functionality of the Software. Any
|
||||||
|
license notice or attribution required by the License must also include this
|
||||||
|
Commons Clause License Condition notice.
|
||||||
|
|
||||||
|
Software: Co Jedzie
|
||||||
|
|
||||||
|
License: MIT
|
||||||
|
|
||||||
|
Licensor: Kacper Donat
|
||||||
|
|
||||||
|
Copyright 2020 Kacper Donat
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
32
README.md
Normal file
32
README.md
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# [Co Jedzie](https://cojedzie.pl)
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
Co Jedzie is an app that allows you to quickly and easily check realtime departure times on public transport stops. It
|
||||||
|
aims to be the central hub for all public transport information you will need.
|
||||||
|
|
||||||
|
You can use the app at [cojedzie.pl](https://cojedzie.pl).
|
||||||
|
|
||||||
|
## Roadmap
|
||||||
|
Co Jedzie is in active development, roadmap of the project can be found on [trello]. This roadmap is regularly updated
|
||||||
|
and represents current state of the project. Feel free to take a look.
|
||||||
|
|
||||||
|
### Contributing to roadmap
|
||||||
|
If you have found a bug or want to propose some changes feel free to create an [issue] explaining your proposal or
|
||||||
|
problem. Issue management and discussion would be done on the github, but planning will be carried away to the [trello]
|
||||||
|
trello with linked issue.
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
Wan't to contribute? Nice! Please see [CONTRIBUTING.md]
|
||||||
|
|
||||||
|
## License
|
||||||
|
This project is [fair-code](https://faircode.io/) licensed under [MIT with Commons Clause](./LICENSE.md). Basically, Co
|
||||||
|
Jedzie is free and code is available to everyone, but it's not allowed to make money directly with it without
|
||||||
|
authors permission.
|
||||||
|
|
||||||
|
Note that data collected from available data sources is licensed by their respective owners, thus it may be
|
||||||
|
available under different terms than the project itself and may require additional permissions to use.
|
||||||
|
|
||||||
|
[trello]: https://trello.com/b/QXqDvmoG/co-jedzie
|
||||||
|
[issue]: https://github.com/cojedzie/cojedzie/issues/new
|
||||||
|
[CONTRIBUTING.md]: ./CONTRIBUTING.md
|
2
api/.dockerignore
Normal file
2
api/.dockerignore
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/vendor/
|
||||||
|
/var/
|
22
api/.env
Normal file
22
api/.env
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# This file is a "template" of which env vars need to be defined for your application
|
||||||
|
# Copy this file to .env file for development, create environment variables when deploying to production
|
||||||
|
# https://symfony.com/doc/current/best_practices/configuration.html#infrastructure-related-configuration
|
||||||
|
|
||||||
|
###> symfony/framework-bundle ###
|
||||||
|
APP_ENV=dev
|
||||||
|
APP_SECRET=494a9d1f8cc383f16075f4d5e54ae1a2
|
||||||
|
#TRUSTED_PROXIES=127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
|
||||||
|
#TRUSTED_HOSTS='^(localhost|example\.com)$'
|
||||||
|
###< symfony/framework-bundle ###
|
||||||
|
|
||||||
|
###> doctrine/doctrine-bundle ###
|
||||||
|
# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
|
||||||
|
# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
|
||||||
|
#
|
||||||
|
DATABASE_URL="sqlite:///%kernel.project_dir%/var/app.db"
|
||||||
|
# DATABASE_URL="mysql://db_user:db_password@127.0.0.1:3306/db_name?serverVersion=5.7"
|
||||||
|
###< doctrine/doctrine-bundle ###
|
||||||
|
|
||||||
|
###> symfony/messenger ###
|
||||||
|
APP_EVENT_QUEUE_DSN="doctrine://default"
|
||||||
|
###< symfony/messenger ###
|
16
api/.gitignore
vendored
Normal file
16
api/.gitignore
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
###> symfony/framework-bundle ###
|
||||||
|
/.env.local
|
||||||
|
/.env.local.php
|
||||||
|
/.env.*.local
|
||||||
|
/config/secrets/prod/prod.decrypt.private.php
|
||||||
|
/public/bundles/
|
||||||
|
/var/
|
||||||
|
/vendor/
|
||||||
|
###< symfony/framework-bundle ###
|
||||||
|
/node_modules/
|
||||||
|
/public/*
|
||||||
|
!/public/index.php
|
||||||
|
|
||||||
|
###> baldinof/roadrunner-bundle ###
|
||||||
|
/bin/rr
|
||||||
|
###< baldinof/roadrunner-bundle ###
|
11
api/.rr.dev.yaml
Normal file
11
api/.rr.dev.yaml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
include:
|
||||||
|
- .rr.yaml
|
||||||
|
|
||||||
|
reload:
|
||||||
|
enabled: true
|
||||||
|
interval: 1s
|
||||||
|
patterns: [".php"]
|
||||||
|
services:
|
||||||
|
http:
|
||||||
|
dirs: ["."]
|
||||||
|
recursive: true
|
13
api/.rr.yaml
Normal file
13
api/.rr.yaml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
http:
|
||||||
|
address: "0.0.0.0:8080"
|
||||||
|
|
||||||
|
uploads:
|
||||||
|
forbid: [".php", ".exe", ".bat"]
|
||||||
|
|
||||||
|
workers:
|
||||||
|
command: "php bin/console baldinof:roadrunner:worker"
|
||||||
|
relay: "unix://var/roadrunner.sock"
|
||||||
|
|
||||||
|
static:
|
||||||
|
dir: "public"
|
||||||
|
forbid: [".php", ".htaccess"]
|
3
api/CONTRIBUTING.md
Normal file
3
api/CONTRIBUTING.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Contributing guidelines
|
||||||
|
|
||||||
|
TBD
|
28
api/Dockerfile
Normal file
28
api/Dockerfile
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
FROM php:7.4-fpm-alpine
|
||||||
|
|
||||||
|
COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/
|
||||||
|
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
|
||||||
|
|
||||||
|
RUN install-php-extensions bcmath intl opcache zip sockets xdebug-^3.0;
|
||||||
|
RUN apk add git;
|
||||||
|
|
||||||
|
# XDebug
|
||||||
|
RUN echo "xdebug.mode=debug" >> $PHP_INI_DIR/conf.d/docker-php-ext-xdebug.ini && \
|
||||||
|
echo "xdebug.discover_client_host=On" >> $PHP_INI_DIR/conf.d/docker-php-ext-xdebug.ini;
|
||||||
|
|
||||||
|
# Blackfire
|
||||||
|
RUN version=$(php -r "echo PHP_MAJOR_VERSION.PHP_MINOR_VERSION;") \
|
||||||
|
&& curl -A "Docker" -o /tmp/blackfire-probe.tar.gz -D - -L -s https://blackfire.io/api/v1/releases/probe/php/linux/amd64/$version \
|
||||||
|
&& mkdir -p /tmp/blackfire \
|
||||||
|
&& tar zxpf /tmp/blackfire-probe.tar.gz -C /tmp/blackfire \
|
||||||
|
&& mv /tmp/blackfire/blackfire-*.so $(php -r "echo ini_get ('extension_dir');")/blackfire.so \
|
||||||
|
&& printf "extension=blackfire.so\nblackfire.agent_socket=tcp://blackfire:8707\n" > $PHP_INI_DIR/conf.d/blackfire.ini \
|
||||||
|
&& rm -rf /tmp/blackfire /tmp/blackfire-probe.tar.gz
|
||||||
|
|
||||||
|
# Timezone
|
||||||
|
RUN ln -snf /usr/share/zoneinfo/Europe/Warsaw /etc/localtime && \
|
||||||
|
echo "date.timezone = Europe/Warsaw" >> /usr/local/etc/php/conf.d/datetime.ini;
|
||||||
|
|
||||||
|
WORKDIR /var/www
|
||||||
|
|
||||||
|
EXPOSE 9001
|
3
api/bin/docker-entrypoint.sh
Normal file
3
api/bin/docker-entrypoint.sh
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
exec "$@"
|
5
api/bin/docker-init.sh
Executable file
5
api/bin/docker-init.sh
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
./bin/console doctrine:migrations:migrate --no-interaction
|
||||||
|
|
||||||
|
exec "$@"
|
@ -1,34 +1,37 @@
|
|||||||
{
|
{
|
||||||
"name": "kadet/czydojade",
|
"name": "kadet/cojedzie",
|
||||||
|
"description": "Co Jedzie",
|
||||||
"type": "project",
|
"type": "project",
|
||||||
"license": "MIT",
|
"license": "MIT with Commons Clause",
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^7.1.3",
|
"php": "^7.4",
|
||||||
"ext-ctype": "*",
|
"ext-ctype": "*",
|
||||||
"ext-iconv": "*",
|
"ext-iconv": "*",
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
|
"baldinof/roadrunner-bundle": "^1.3",
|
||||||
"cerbero/json-objects": "^1.1",
|
"cerbero/json-objects": "^1.1",
|
||||||
"doctrine/doctrine-cache-bundle": "^1.4",
|
"illuminate/collections": "^8.35",
|
||||||
"jms/serializer-bundle": "^3.5",
|
"jms/serializer-bundle": "^3.5",
|
||||||
|
"kadet/functional": "dev-master",
|
||||||
"nelmio/api-doc-bundle": "^3.5",
|
"nelmio/api-doc-bundle": "^3.5",
|
||||||
"nesbot/carbon": "^1.33",
|
"nesbot/carbon": "^2.46.0",
|
||||||
"ocramius/proxy-manager": "^2.0",
|
"ocramius/proxy-manager": "^2.0",
|
||||||
"sensio/framework-extra-bundle": "^5.2",
|
"sensio/framework-extra-bundle": "^5.2",
|
||||||
"symfony/asset": "^4.4",
|
"spiral/roadrunner": "^1.8",
|
||||||
"symfony/console": "^4.4",
|
"symfony/asset": "^5.2",
|
||||||
|
"symfony/console": "^5.2",
|
||||||
|
"symfony/doctrine-messenger": "5.2.*",
|
||||||
"symfony/flex": "^1.1",
|
"symfony/flex": "^1.1",
|
||||||
"symfony/framework-bundle": "^4.4",
|
"symfony/framework-bundle": "^5.2",
|
||||||
|
"symfony/messenger": "5.2.*",
|
||||||
"symfony/monolog-bundle": "^3.3",
|
"symfony/monolog-bundle": "^3.3",
|
||||||
"symfony/orm-pack": "^1.0",
|
"symfony/orm-pack": "^1.0",
|
||||||
"symfony/profiler-pack": "^1.0",
|
"symfony/profiler-pack": "^1.0",
|
||||||
"symfony/twig-bundle": "^4.4",
|
"symfony/twig-bundle": "^5.2",
|
||||||
"symfony/yaml": "^4.4",
|
"symfony/yaml": "^5.2",
|
||||||
"tightenco/collect": "^5.6"
|
"symfony/dotenv": "5.2.*",
|
||||||
},
|
"symfony/amqp-messenger": "5.2.*",
|
||||||
"require-dev": {
|
"symfony/redis-messenger": "5.2.*"
|
||||||
"symfony/dotenv": "^4.4",
|
|
||||||
"symfony/web-server-bundle": "^4.4",
|
|
||||||
"kadet/functional": "dev-master"
|
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"preferred-install": {
|
"preferred-install": {
|
||||||
@ -37,14 +40,17 @@
|
|||||||
"sort-packages": true,
|
"sort-packages": true,
|
||||||
"secure-http": false,
|
"secure-http": false,
|
||||||
"platform": {
|
"platform": {
|
||||||
"php": "7.3.12"
|
"php": "7.4.15"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"App\\": "src/"
|
"App\\": "src/"
|
||||||
},
|
},
|
||||||
"files": ["./src/Functions/index.php"]
|
"files": [
|
||||||
|
"vendor/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php",
|
||||||
|
"./src/Functions/index.php"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"autoload-dev": {
|
"autoload-dev": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
@ -75,7 +81,8 @@
|
|||||||
},
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
"symfony": {
|
"symfony": {
|
||||||
"allow-contrib": true
|
"allow-contrib": true,
|
||||||
|
"require": "5.2.*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"repositories": [
|
"repositories": [
|
||||||
@ -83,5 +90,8 @@
|
|||||||
"type": "vcs",
|
"type": "vcs",
|
||||||
"url": "https://git.kadet.net/kadet/functional-php.git"
|
"url": "https://git.kadet.net/kadet/functional-php.git"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"require-dev": {
|
||||||
|
"symfony/maker-bundle": "^1.30"
|
||||||
|
}
|
||||||
}
|
}
|
6497
composer.lock → api/composer.lock
generated
6497
composer.lock → api/composer.lock
generated
File diff suppressed because it is too large
Load Diff
23
api/config/bootstrap.php
Normal file
23
api/config/bootstrap.php
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Symfony\Component\Dotenv\Dotenv;
|
||||||
|
|
||||||
|
require dirname(__DIR__).'/vendor/autoload.php';
|
||||||
|
|
||||||
|
if (!class_exists(Dotenv::class)) {
|
||||||
|
throw new LogicException('Please run "composer require symfony/dotenv" to load the ".env" files configuring the application.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load cached env vars if the .env.local.php file exists
|
||||||
|
// Run "composer dump-env prod" to create it (requires symfony/flex >=1.2)
|
||||||
|
if (is_array($env = @include dirname(__DIR__).'/.env.local.php') && (!isset($env['APP_ENV']) || ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? $env['APP_ENV']) === $env['APP_ENV'])) {
|
||||||
|
(new Dotenv(false))->populate($env);
|
||||||
|
} else {
|
||||||
|
// load all the .env files
|
||||||
|
(new Dotenv(false))->loadEnv(dirname(__DIR__).'/.env');
|
||||||
|
}
|
||||||
|
|
||||||
|
$_SERVER += $_ENV;
|
||||||
|
$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null) ?: 'dev';
|
||||||
|
$_SERVER['APP_DEBUG'] = $_SERVER['APP_DEBUG'] ?? $_ENV['APP_DEBUG'] ?? 'prod' !== $_SERVER['APP_ENV'];
|
||||||
|
$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = (int) $_SERVER['APP_DEBUG'] || filter_var($_SERVER['APP_DEBUG'], FILTER_VALIDATE_BOOLEAN) ? '1' : '0';
|
@ -2,14 +2,14 @@
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
|
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
|
||||||
Symfony\Bundle\WebServerBundle\WebServerBundle::class => ['dev' => true],
|
|
||||||
Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true],
|
Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true],
|
||||||
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
|
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
|
||||||
Doctrine\Bundle\DoctrineCacheBundle\DoctrineCacheBundle::class => ['all' => true],
|
|
||||||
Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
|
Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
|
||||||
Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
|
Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
|
||||||
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
|
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
|
||||||
Nelmio\ApiDocBundle\NelmioApiDocBundle::class => ['all' => true],
|
Nelmio\ApiDocBundle\NelmioApiDocBundle::class => ['all' => true],
|
||||||
JMS\SerializerBundle\JMSSerializerBundle::class => ['all' => true],
|
JMS\SerializerBundle\JMSSerializerBundle::class => ['all' => true],
|
||||||
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
|
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
|
||||||
|
Baldinof\RoadRunnerBundle\BaldinofRoadRunnerBundle::class => ['all' => true],
|
||||||
|
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
|
||||||
];
|
];
|
18
api/config/packages/baldinof_road_runner.yaml
Normal file
18
api/config/packages/baldinof_road_runner.yaml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
baldinof_road_runner:
|
||||||
|
# The kernel is preserved between requests. Change this to `true`
|
||||||
|
# if you want to reboot it, and use a fresh container on each request.
|
||||||
|
should_reboot_kernel: false
|
||||||
|
|
||||||
|
# Integrations are automatically detected, depending on installed bundle & current configuration
|
||||||
|
# See https://github.com/baldinof/roadrunner-bundle#integrations
|
||||||
|
default_integrations: true
|
||||||
|
|
||||||
|
# Allow to send prometheus metrics to the master RoadRunner process,
|
||||||
|
# via a `Spiral\RoadRunner\MetricsInterface` service.
|
||||||
|
# See https://github.com/baldinof/roadrunner-bundle#metrics
|
||||||
|
metrics_enabled: false
|
||||||
|
|
||||||
|
# You can use middlewares to manipulate PSR requests & responses.
|
||||||
|
# See https://github.com/baldinof/roadrunner-bundle#middlewares
|
||||||
|
# middlewares:
|
||||||
|
# - App\Middleware\YourMiddleware
|
19
api/config/packages/cache.yaml
Normal file
19
api/config/packages/cache.yaml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
framework:
|
||||||
|
cache:
|
||||||
|
# Unique name of your app: used to compute stable namespaces for cache keys.
|
||||||
|
#prefix_seed: your_vendor_name/app_name
|
||||||
|
|
||||||
|
# The "app" cache stores to the filesystem by default.
|
||||||
|
# The data in this cache should persist between deploys.
|
||||||
|
# Other options include:
|
||||||
|
|
||||||
|
# Redis
|
||||||
|
#app: cache.adapter.redis
|
||||||
|
#default_redis_provider: redis://localhost
|
||||||
|
|
||||||
|
# APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues)
|
||||||
|
#app: cache.adapter.apcu
|
||||||
|
|
||||||
|
# Namespaced pools use the above "app" backend by default
|
||||||
|
#pools:
|
||||||
|
#my.dedicated.cache: null
|
@ -1,5 +1,5 @@
|
|||||||
web_profiler:
|
web_profiler:
|
||||||
toolbar: true
|
toolbar: false
|
||||||
intercept_redirects: false
|
intercept_redirects: false
|
||||||
|
|
||||||
framework:
|
framework:
|
@ -5,14 +5,13 @@ doctrine:
|
|||||||
dbal:
|
dbal:
|
||||||
driver: 'pdo_sqlite'
|
driver: 'pdo_sqlite'
|
||||||
url: '%env(resolve:DATABASE_URL)%'
|
url: '%env(resolve:DATABASE_URL)%'
|
||||||
logging: true
|
logging: '%kernel.debug%'
|
||||||
profiling: true
|
profiling: '%kernel.debug%'
|
||||||
types:
|
types:
|
||||||
datetime: App\Doctrine\CarbonDateTimeType
|
datetime: App\Doctrine\CarbonDateTimeType
|
||||||
|
|
||||||
orm:
|
orm:
|
||||||
auto_generate_proxy_classes: '%kernel.debug%'
|
auto_generate_proxy_classes: true
|
||||||
naming_strategy: doctrine.orm.naming_strategy.underscore
|
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
|
||||||
auto_mapping: true
|
auto_mapping: true
|
||||||
mappings:
|
mappings:
|
||||||
App:
|
App:
|
||||||
@ -20,4 +19,4 @@ doctrine:
|
|||||||
type: annotation
|
type: annotation
|
||||||
dir: '%kernel.project_dir%/src/Entity'
|
dir: '%kernel.project_dir%/src/Entity'
|
||||||
prefix: 'App\Entity'
|
prefix: 'App\Entity'
|
||||||
alias: Entity
|
alias: App
|
3
api/config/packages/doctrine_migrations.yaml
Normal file
3
api/config/packages/doctrine_migrations.yaml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
doctrine_migrations:
|
||||||
|
migrations_paths:
|
||||||
|
'DoctrineMigrations': '%kernel.project_dir%/migrations'
|
6
api/config/packages/framework.yaml
Normal file
6
api/config/packages/framework.yaml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
framework:
|
||||||
|
secret: '%env(APP_SECRET)%'
|
||||||
|
csrf_protection: false
|
||||||
|
|
||||||
|
php_errors:
|
||||||
|
log: true
|
@ -1,4 +1,8 @@
|
|||||||
jms_serializer:
|
jms_serializer:
|
||||||
|
default_context:
|
||||||
|
serialization:
|
||||||
|
serialize_null: true
|
||||||
|
|
||||||
visitors:
|
visitors:
|
||||||
xml_serialization:
|
xml_serialization:
|
||||||
format_output: '%kernel.debug%'
|
format_output: '%kernel.debug%'
|
11
api/config/packages/messenger.yaml
Normal file
11
api/config/packages/messenger.yaml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
parameters:
|
||||||
|
env(APP_EVENT_QUEUE): "doctrine://default"
|
||||||
|
|
||||||
|
framework:
|
||||||
|
messenger:
|
||||||
|
transports:
|
||||||
|
main: '%env(resolve:APP_EVENT_QUEUE)%'
|
||||||
|
sync: 'sync://'
|
||||||
|
|
||||||
|
routing:
|
||||||
|
'App\Message\UpdateDataMessage': main
|
@ -1,7 +1,7 @@
|
|||||||
nelmio_api_doc:
|
nelmio_api_doc:
|
||||||
documentation:
|
documentation:
|
||||||
info:
|
info:
|
||||||
title: Czy Dojadę?
|
title: Co Jedzie?
|
||||||
version: 0.1.0
|
version: 0.1.0
|
||||||
parameters:
|
parameters:
|
||||||
provider:
|
provider:
|
||||||
@ -13,7 +13,7 @@ nelmio_api_doc:
|
|||||||
|
|
||||||
areas:
|
areas:
|
||||||
path_patterns:
|
path_patterns:
|
||||||
- ^/[^\/]+/api(?!/doc$) # Accepts routes under /api except /api/doc
|
- /api(?!/doc$) # Accepts routes under /api except /api/doc
|
||||||
|
|
||||||
|
|
||||||
|
|
20
api/config/packages/prod/doctrine.yaml
Normal file
20
api/config/packages/prod/doctrine.yaml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
doctrine:
|
||||||
|
orm:
|
||||||
|
auto_generate_proxy_classes: false
|
||||||
|
metadata_cache_driver:
|
||||||
|
type: pool
|
||||||
|
pool: doctrine.system_cache_pool
|
||||||
|
query_cache_driver:
|
||||||
|
type: pool
|
||||||
|
pool: doctrine.system_cache_pool
|
||||||
|
result_cache_driver:
|
||||||
|
type: pool
|
||||||
|
pool: doctrine.result_cache_pool
|
||||||
|
|
||||||
|
framework:
|
||||||
|
cache:
|
||||||
|
pools:
|
||||||
|
doctrine.result_cache_pool:
|
||||||
|
adapter: cache.app
|
||||||
|
doctrine.system_cache_pool:
|
||||||
|
adapter: cache.system
|
@ -1,3 +1,4 @@
|
|||||||
framework:
|
framework:
|
||||||
router:
|
router:
|
||||||
strict_requirements: ~
|
strict_requirements: ~
|
||||||
|
|
2
api/config/packages/test/twig.yaml
Normal file
2
api/config/packages/test/twig.yaml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
twig:
|
||||||
|
strict_variables: true
|
5
api/config/packages/twig.yaml
Normal file
5
api/config/packages/twig.yaml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
twig:
|
||||||
|
default_path: '%kernel.project_dir%/templates'
|
||||||
|
debug: '%kernel.debug%'
|
||||||
|
strict_variables: '%kernel.debug%'
|
||||||
|
exception_controller: null
|
9
api/config/preload.php
Normal file
9
api/config/preload.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
if (file_exists(dirname(__DIR__).'/var/cache/prod/srcApp_KernelProdContainer.preload.php')) {
|
||||||
|
require dirname(__DIR__).'/var/cache/prod/srcApp_KernelProdContainer.preload.php';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_exists(dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php')) {
|
||||||
|
require dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php';
|
||||||
|
}
|
16
api/config/routes.yaml
Normal file
16
api/config/routes.yaml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
api_v1:
|
||||||
|
resource: ../src/Controller/Api/v1
|
||||||
|
type: annotation
|
||||||
|
prefix: /api/v1/{provider}
|
||||||
|
|
||||||
|
api_v1_providers:
|
||||||
|
path: /api/v1/providers
|
||||||
|
methods: ["GET"]
|
||||||
|
defaults:
|
||||||
|
_controller: '\App\Controller\Api\v1\ProviderController::index'
|
||||||
|
|
||||||
|
api_v1_providers_one:
|
||||||
|
path: /api/v1/providers/{id}
|
||||||
|
methods: ["GET"]
|
||||||
|
defaults:
|
||||||
|
_controller: '\App\Controller\Api\v1\ProviderController::one'
|
3
api/config/routes/dev/framework.yaml
Normal file
3
api/config/routes/dev/framework.yaml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
_errors:
|
||||||
|
resource: '@FrameworkBundle/Resources/config/routing/errors.xml'
|
||||||
|
prefix: /_error
|
@ -19,11 +19,14 @@ services:
|
|||||||
App\Provider\Provider:
|
App\Provider\Provider:
|
||||||
tags: [ app.provider ]
|
tags: [ app.provider ]
|
||||||
|
|
||||||
|
App\Service\Converter:
|
||||||
|
tags: [ app.converter ]
|
||||||
|
|
||||||
# makes classes in src/ available to be used as services
|
# makes classes in src/ available to be used as services
|
||||||
# this creates a service per class whose id is the fully-qualified class name
|
# this creates a service per class whose id is the fully-qualified class name
|
||||||
App\:
|
App\:
|
||||||
resource: '../src/*'
|
resource: '../src/*'
|
||||||
exclude: '../src/{DependencyInjection,Entity,Model,Migrations,Tests,Functions,Kernel.php}'
|
exclude: '../src/{DependencyInjection,Exception,Modifier,Entity,Model,Migrations,Tests,Functions,Handler,Kernel.php}'
|
||||||
|
|
||||||
# controllers are imported separately to make sure services can be injected
|
# controllers are imported separately to make sure services can be injected
|
||||||
# as action arguments even if you don't extend any base controller class
|
# as action arguments even if you don't extend any base controller class
|
||||||
@ -35,12 +38,9 @@ services:
|
|||||||
resource: '../src/Provider'
|
resource: '../src/Provider'
|
||||||
public: true
|
public: true
|
||||||
|
|
||||||
# add more service definitions when explicit configuration is needed
|
App\Handler\:
|
||||||
# please note that last definitions always *replace* previous ones
|
resource: '../src/Handler'
|
||||||
|
tags: [ app.handler ]
|
||||||
#assets
|
|
||||||
assets.modified_time_version_strategy:
|
|
||||||
class: App\Asset\ModifiedTimeVersionStrategy
|
|
||||||
|
|
||||||
#eerialziser
|
#eerialziser
|
||||||
jms_serializer.serialized_name_annotation_strategy:
|
jms_serializer.serialized_name_annotation_strategy:
|
||||||
@ -53,7 +53,7 @@ services:
|
|||||||
|
|
||||||
#proxy configuration
|
#proxy configuration
|
||||||
proxy.locator:
|
proxy.locator:
|
||||||
class: 'ProxyManager\FileLocator\FileLocator'
|
class: 'App\Service\Proxy\FileLocator'
|
||||||
arguments: ['%kernel.cache_dir%/proxy']
|
arguments: ['%kernel.cache_dir%/proxy']
|
||||||
|
|
||||||
proxy.strategy:
|
proxy.strategy:
|
||||||
@ -75,12 +75,6 @@ services:
|
|||||||
|
|
||||||
App\Service\Converter: '@App\Service\AggregateConverter'
|
App\Service\Converter: '@App\Service\AggregateConverter'
|
||||||
|
|
||||||
App\Service\EntityConverter:
|
|
||||||
tags: ['app.converter']
|
|
||||||
|
|
||||||
App\Service\ScheduledStopConverter:
|
|
||||||
tags: ['app.converter']
|
|
||||||
|
|
||||||
# serializer configuration
|
# serializer configuration
|
||||||
App\Service\SerializerContextFactory:
|
App\Service\SerializerContextFactory:
|
||||||
arguments:
|
arguments:
|
||||||
@ -90,3 +84,7 @@ services:
|
|||||||
# other servces
|
# other servces
|
||||||
App\Service\ProviderResolver:
|
App\Service\ProviderResolver:
|
||||||
arguments: [!tagged app.provider, '%kernel.debug%']
|
arguments: [!tagged app.provider, '%kernel.debug%']
|
||||||
|
|
||||||
|
App\Service\HandlerProvider:
|
||||||
|
arguments: [!tagged_locator app.handler]
|
||||||
|
shared: false
|
43
api/migrations/Version20200314112552.php
Normal file
43
api/migrations/Version20200314112552.php
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20200314112552 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription() : string
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema) : void
|
||||||
|
{
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'sqlite', 'Migration can only be executed safely on \'sqlite\'.');
|
||||||
|
|
||||||
|
$this->addSql('CREATE TEMPORARY TABLE __temp__trip_stop AS SELECT stop_id, trip_id, sequence, arrival, departure FROM trip_stop');
|
||||||
|
$this->addSql('DROP TABLE trip_stop');
|
||||||
|
$this->addSql('CREATE TABLE trip_stop (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, sequence INTEGER NOT NULL, arrival DATETIME NOT NULL, departure DATETIME NOT NULL, stop_id VARCHAR(255) DEFAULT NULL, trip_id VARCHAR(255) DEFAULT NULL)');
|
||||||
|
$this->addSql('INSERT INTO trip_stop (stop_id, trip_id, sequence, arrival, departure) SELECT stop_id, trip_id, sequence, arrival, departure FROM __temp__trip_stop');
|
||||||
|
$this->addSql('DROP TABLE __temp__trip_stop');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema) : void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'sqlite', 'Migration can only be executed safely on \'sqlite\'.');
|
||||||
|
|
||||||
|
$this->addSql('CREATE TEMPORARY TABLE __temp__trip_stop AS SELECT sequence, arrival, departure, stop_id, trip_id FROM trip_stop');
|
||||||
|
$this->addSql('DROP TABLE trip_stop');
|
||||||
|
$this->addSql('CREATE TABLE trip_stop (sequence INTEGER NOT NULL, stop_id VARCHAR(255) NOT NULL COLLATE BINARY, trip_id VARCHAR(255) NOT NULL COLLATE BINARY, arrival DATETIME NOT NULL, departure DATETIME NOT NULL, PRIMARY KEY(stop_id, trip_id, sequence))');
|
||||||
|
$this->addSql('INSERT INTO trip_stop (sequence, arrival, departure, stop_id, trip_id) SELECT sequence, arrival, departure, stop_id, trip_id FROM __temp__trip_stop');
|
||||||
|
$this->addSql('DROP TABLE __temp__trip_stop');
|
||||||
|
}
|
||||||
|
}
|
27
api/public/index.php
Normal file
27
api/public/index.php
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Kernel;
|
||||||
|
use Symfony\Component\ErrorHandler\Debug;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
|
||||||
|
require dirname(__DIR__).'/config/bootstrap.php';
|
||||||
|
|
||||||
|
if ($_SERVER['APP_DEBUG']) {
|
||||||
|
umask(0000);
|
||||||
|
|
||||||
|
Debug::enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($trustedProxies = $_SERVER['TRUSTED_PROXIES'] ?? false) {
|
||||||
|
Request::setTrustedProxies(explode(',', $trustedProxies), Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($trustedHosts = $_SERVER['TRUSTED_HOSTS'] ?? false) {
|
||||||
|
Request::setTrustedHosts([$trustedHosts]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']);
|
||||||
|
$request = Request::createFromGlobals();
|
||||||
|
$response = $kernel->handle($request);
|
||||||
|
$response->send();
|
||||||
|
$kernel->terminate($request, $response);
|
29
api/rr.Dockerfile
Normal file
29
api/rr.Dockerfile
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
FROM cojedzie/api:latest-rr
|
||||||
|
|
||||||
|
COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/
|
||||||
|
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
|
||||||
|
|
||||||
|
RUN install-php-extensions xdebug-^3.0;
|
||||||
|
RUN apk add git;
|
||||||
|
|
||||||
|
# XDebug
|
||||||
|
RUN echo "xdebug.mode=debug" >> $PHP_INI_DIR/conf.d/docker-php-ext-xdebug.ini && \
|
||||||
|
echo "xdebug.client_host=172.17.0.1" >> $PHP_INI_DIR/conf.d/docker-php-ext-xdebug.ini && \
|
||||||
|
echo "xdebug.start_with_request=On" >> $PHP_INI_DIR/conf.d/docker-php-ext-xdebug.ini;
|
||||||
|
|
||||||
|
# Blackfire
|
||||||
|
RUN version=$(php -r "echo PHP_MAJOR_VERSION.PHP_MINOR_VERSION;") \
|
||||||
|
&& curl -A "Docker" -o /tmp/blackfire-probe.tar.gz -D - -L -s https://blackfire.io/api/v1/releases/probe/php/linux/amd64/$version \
|
||||||
|
&& mkdir -p /tmp/blackfire \
|
||||||
|
&& tar zxpf /tmp/blackfire-probe.tar.gz -C /tmp/blackfire \
|
||||||
|
&& mv /tmp/blackfire/blackfire-*.so $(php -r "echo ini_get ('extension_dir');")/blackfire.so \
|
||||||
|
&& printf "extension=blackfire.so\nblackfire.agent_socket=tcp://blackfire:8707\n" > $PHP_INI_DIR/conf.d/blackfire.ini \
|
||||||
|
&& rm -rf /tmp/blackfire /tmp/blackfire-probe.tar.gz
|
||||||
|
|
||||||
|
# Timezone
|
||||||
|
RUN ln -snf /usr/share/zoneinfo/Europe/Warsaw /etc/localtime && \
|
||||||
|
echo "date.timezone = Europe/Warsaw" >> /usr/local/etc/php/conf.d/datetime.ini;
|
||||||
|
|
||||||
|
WORKDIR /var/www
|
||||||
|
|
||||||
|
EXPOSE 9001
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<rulset name="Kadet.CzyDojade">
|
<rulset name="CoJedzie">
|
||||||
<description>Czy Dojadę ruleset</description>
|
<description>Co Jedzie ruleset</description>
|
||||||
|
|
||||||
<arg name="colors"/>
|
<arg name="colors"/>
|
||||||
<arg name="parallel" value="75"/>
|
<arg name="parallel" value="75"/>
|
48
api/src/Command/UpdateCommand.php
Normal file
48
api/src/Command/UpdateCommand.php
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Command;
|
||||||
|
|
||||||
|
use App\Message\UpdateDataMessage;
|
||||||
|
use App\Service\DataUpdater;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Messenger\MessageBusInterface;
|
||||||
|
|
||||||
|
class UpdateCommand extends Command
|
||||||
|
{
|
||||||
|
/** @var DataUpdater */
|
||||||
|
private $updater;
|
||||||
|
/** @var MessageBusInterface */
|
||||||
|
private $bus;
|
||||||
|
|
||||||
|
public function __construct(DataUpdater $updater, MessageBusInterface $bus)
|
||||||
|
{
|
||||||
|
parent::__construct('app:update');
|
||||||
|
|
||||||
|
$this->updater = $updater;
|
||||||
|
$this->bus = $bus;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->addOption(
|
||||||
|
'async', 'a',
|
||||||
|
InputOption::VALUE_NONE,
|
||||||
|
'Run in worker process via message queue.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
|
{
|
||||||
|
if ($input->getOption('async')) {
|
||||||
|
$this->bus->dispatch(new UpdateDataMessage());
|
||||||
|
$output->writeln("Update request sent to message queue.");
|
||||||
|
} else {
|
||||||
|
$this->updater->update($output);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,10 @@ namespace App\Controller\Api\v1;
|
|||||||
|
|
||||||
use App\Controller\Controller;
|
use App\Controller\Controller;
|
||||||
use App\Model\Departure;
|
use App\Model\Departure;
|
||||||
|
use App\Modifier\FieldFilter;
|
||||||
|
use App\Modifier\IdFilter;
|
||||||
|
use App\Modifier\Limit;
|
||||||
|
use App\Modifier\With;
|
||||||
use App\Provider\DepartureRepository;
|
use App\Provider\DepartureRepository;
|
||||||
use App\Provider\StopRepository;
|
use App\Provider\StopRepository;
|
||||||
use App\Service\SerializerContextFactory;
|
use App\Service\SerializerContextFactory;
|
||||||
@ -32,11 +36,11 @@ class DeparturesController extends Controller
|
|||||||
* @SWG\Schema(type="array", @SWG\Items(ref=@Model(type=Departure::class)))
|
* @SWG\Schema(type="array", @SWG\Items(ref=@Model(type=Departure::class)))
|
||||||
* )
|
* )
|
||||||
*/
|
*/
|
||||||
public function stop(DepartureRepository $departures, StopRepository $stops, $stop)
|
public function stop(DepartureRepository $departures, StopRepository $stops, $stop, Request $request)
|
||||||
{
|
{
|
||||||
$stop = $stops->getById($stop);
|
$stop = $stops->first(new IdFilter($stop));
|
||||||
|
|
||||||
return $this->json($departures->getForStop($stop));
|
return $this->json($departures->current(collect($stop), ...$this->getModifiersFromRequest($request)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -64,16 +68,21 @@ class DeparturesController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function stops(DepartureRepository $departures, StopRepository $stops, Request $request)
|
public function stops(DepartureRepository $departures, StopRepository $stops, Request $request)
|
||||||
{
|
{
|
||||||
$stops = $stops
|
$stops = $stops->all(new IdFilter($request->query->get('stop', [])));
|
||||||
->getManyById($request->query->get('stop'))
|
$result = $departures->current($stops, ...$this->getModifiersFromRequest($request));
|
||||||
->flatMap(ref([ $departures, 'getForStop' ]))
|
|
||||||
->sortBy(property('departure'));
|
|
||||||
|
|
||||||
return $this->json(
|
return $this->json(
|
||||||
$stops->values()->slice(0, (int)$request->query->get('limit', 8)),
|
$result->values()->slice(0, (int)$request->query->get('limit', 8)),
|
||||||
200,
|
200,
|
||||||
[],
|
[],
|
||||||
$this->serializerContextFactory->create(Departure::class, ['Default'])
|
$this->serializerContextFactory->create(Departure::class, ['Default'])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getModifiersFromRequest(Request $request)
|
||||||
|
{
|
||||||
|
if ($request->query->has('limit')) {
|
||||||
|
yield Limit::count($request->query->getInt('limit'));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
34
api/src/Controller/Api/v1/ProviderController.php
Normal file
34
api/src/Controller/Api/v1/ProviderController.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controller\Api\v1;
|
||||||
|
|
||||||
|
use App\Controller\Controller;
|
||||||
|
use App\Exception\NonExistentServiceException;
|
||||||
|
use App\Service\Converter;
|
||||||
|
use App\Service\ProviderResolver;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
|
use function Kadet\Functional\ref;
|
||||||
|
|
||||||
|
class ProviderController extends Controller
|
||||||
|
{
|
||||||
|
public function index(ProviderResolver $resolver, Converter $converter)
|
||||||
|
{
|
||||||
|
$providers = $resolver
|
||||||
|
->all()
|
||||||
|
->map(ref([$converter, 'convert']))
|
||||||
|
->values()
|
||||||
|
->toArray()
|
||||||
|
;
|
||||||
|
return $this->json($providers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function one(ProviderResolver $resolver, Converter $converter, $id)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$provider = $resolver->resolve($id);
|
||||||
|
return $this->json($converter->convert($provider));
|
||||||
|
} catch (NonExistentServiceException $exception) {
|
||||||
|
throw new NotFoundHttpException($exception->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,20 +1,22 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
|
||||||
namespace App\Controller\Api\v1;
|
namespace App\Controller\Api\v1;
|
||||||
|
|
||||||
use App\Controller\Controller;
|
use App\Controller\Controller;
|
||||||
use App\Model\Stop;
|
use App\Model\Stop;
|
||||||
use App\Model\Track;
|
|
||||||
use App\Model\StopGroup;
|
use App\Model\StopGroup;
|
||||||
|
use App\Model\TrackStop;
|
||||||
|
use App\Modifier\FieldFilter;
|
||||||
|
use App\Modifier\IdFilter;
|
||||||
|
use App\Modifier\RelatedFilter;
|
||||||
|
use App\Modifier\With;
|
||||||
use App\Provider\StopRepository;
|
use App\Provider\StopRepository;
|
||||||
use App\Provider\TrackRepository;
|
use App\Provider\TrackRepository;
|
||||||
use App\Service\Proxy\ReferenceFactory;
|
use Illuminate\Support\Collection;
|
||||||
use Nelmio\ApiDocBundle\Annotation\Model;
|
use Nelmio\ApiDocBundle\Annotation\Model;
|
||||||
use Swagger\Annotations as SWG;
|
use Swagger\Annotations as SWG;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\Routing\Annotation\Route;
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
use Tightenco\Collect\Support\Collection;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class StopsController
|
* Class StopsController
|
||||||
@ -38,7 +40,8 @@ class StopsController extends Controller
|
|||||||
* name="id",
|
* name="id",
|
||||||
* in="query",
|
* in="query",
|
||||||
* type="array",
|
* type="array",
|
||||||
* description="Stop identificators to retrieve at once. Can be used to bulk load data. If not specified will return all data.",
|
* description="Stop identificators to retrieve at once. Can be used to bulk load data. If not specified will
|
||||||
|
* return all data.",
|
||||||
* @SWG\Items(type="string")
|
* @SWG\Items(type="string")
|
||||||
* )
|
* )
|
||||||
*
|
*
|
||||||
@ -46,16 +49,9 @@ class StopsController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function index(Request $request, StopRepository $stops)
|
public function index(Request $request, StopRepository $stops)
|
||||||
{
|
{
|
||||||
switch (true) {
|
$modifiers = $this->getModifiersFromRequest($request);
|
||||||
case $request->query->has('id'):
|
|
||||||
$result = $stops->getManyById($request->query->get('id'));
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
return $this->json($stops->all(...$modifiers)->toArray());
|
||||||
$result = $stops->getAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->json($result->all());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -76,16 +72,9 @@ class StopsController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function groups(Request $request, StopRepository $stops)
|
public function groups(Request $request, StopRepository $stops)
|
||||||
{
|
{
|
||||||
switch (true) {
|
$modifiers = $this->getModifiersFromRequest($request);
|
||||||
case $request->query->has('name'):
|
|
||||||
$result = $stops->findByName($request->query->get('name'));
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
return $this->json(static::group($stops->all(...$modifiers))->toArray());
|
||||||
$result = $stops->getAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->json(static::group($result)->all());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -106,7 +95,7 @@ class StopsController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function one(Request $request, StopRepository $stops, $id)
|
public function one(Request $request, StopRepository $stops, $id)
|
||||||
{
|
{
|
||||||
return $this->json($stops->getById($id));
|
return $this->json($stops->first(new IdFilter($id), new With("destinations")));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -115,21 +104,12 @@ class StopsController extends Controller
|
|||||||
* @SWG\Response(
|
* @SWG\Response(
|
||||||
* response=200,
|
* response=200,
|
||||||
* description="Returns specific stop referenced via identificator.",
|
* description="Returns specific stop referenced via identificator.",
|
||||||
* @SWG\Schema(type="object", properties={
|
* @SWG\Schema(ref=@Model(type=TrackStop::class))
|
||||||
* @SWG\Property(property="track", type="object", ref=@Model(type=Track::class)),
|
|
||||||
* @SWG\Property(property="order", type="integer", minimum="0")
|
|
||||||
* })
|
|
||||||
* )
|
* )
|
||||||
*
|
|
||||||
* @SWG\Tag(name="Tracks")
|
|
||||||
*/
|
*/
|
||||||
public function tracks(ReferenceFactory $reference, TrackRepository $tracks, $id)
|
public function tracks(TrackRepository $tracks, $id)
|
||||||
{
|
{
|
||||||
$stop = $reference->get(Stop::class, $id);
|
return $this->json($tracks->stops(new RelatedFilter(Stop::reference($id))));
|
||||||
|
|
||||||
return $this->json($tracks->getByStop($stop)->map(function ($tuple) {
|
|
||||||
return array_combine(['track', 'order'], $tuple);
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function group(Collection $stops)
|
public static function group(Collection $stops)
|
||||||
@ -145,4 +125,19 @@ class StopsController extends Controller
|
|||||||
return $group;
|
return $group;
|
||||||
})->values();
|
})->values();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getModifiersFromRequest(Request $request)
|
||||||
|
{
|
||||||
|
if ($request->query->has('name')) {
|
||||||
|
yield FieldFilter::contains('name', $request->query->get('name'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->query->has('id')) {
|
||||||
|
yield new IdFilter($request->query->get('id'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->query->has('include-destinations')) {
|
||||||
|
yield new With("destinations");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
98
api/src/Controller/Api/v1/TracksController.php
Normal file
98
api/src/Controller/Api/v1/TracksController.php
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controller\Api\v1;
|
||||||
|
|
||||||
|
use App\Controller\Controller;
|
||||||
|
use App\Model\Line;
|
||||||
|
use App\Model\Stop;
|
||||||
|
use App\Model\Track;
|
||||||
|
use App\Modifier\IdFilter;
|
||||||
|
use App\Modifier\RelatedFilter;
|
||||||
|
use App\Provider\TrackRepository;
|
||||||
|
use Swagger\Annotations as SWG;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
use function App\Functions\encapsulate;
|
||||||
|
use function Kadet\Functional\ref;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Route("/tracks")
|
||||||
|
* @SWG\Tag(name="Tracks")
|
||||||
|
*/
|
||||||
|
class TracksController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @SWG\Response(
|
||||||
|
* response=200,
|
||||||
|
* description="Returns all tracks for specific provider, e.g. ZTM Gdańsk.",
|
||||||
|
* )
|
||||||
|
* @Route("/", methods={"GET"})
|
||||||
|
*/
|
||||||
|
public function index(Request $request, TrackRepository $repository)
|
||||||
|
{
|
||||||
|
$modifiers = $this->getModifiersFromRequest($request);
|
||||||
|
|
||||||
|
return $this->json($repository->all(...$modifiers));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Route("/stops", methods={"GET"})
|
||||||
|
* @Route("/{track}/stops", methods={"GET"})
|
||||||
|
*
|
||||||
|
* @SWG\Tag(name="Tracks")
|
||||||
|
*
|
||||||
|
* @SWG\Response(response=200, description="Stops related to specified query.")
|
||||||
|
*/
|
||||||
|
public function stops(Request $request, TrackRepository $repository)
|
||||||
|
{
|
||||||
|
$modifiers = $this->getStopsModifiersFromRequest($request);
|
||||||
|
|
||||||
|
return $this->json($repository->stops(...$modifiers));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getModifiersFromRequest(Request $request)
|
||||||
|
{
|
||||||
|
if ($request->query->has('stop')) {
|
||||||
|
$stop = encapsulate($request->query->get('stop'));
|
||||||
|
$stop = collect($stop)->map([Stop::class, 'reference']);
|
||||||
|
|
||||||
|
yield new RelatedFilter($stop, Stop::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->query->has('line')) {
|
||||||
|
$line = encapsulate($request->query->get('line'));
|
||||||
|
$line = collect($line)->map([Line::class, 'reference']);
|
||||||
|
|
||||||
|
yield new RelatedFilter($line, Line::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->query->has('id')) {
|
||||||
|
$id = encapsulate($request->query->get('id'));
|
||||||
|
|
||||||
|
yield new IdFilter($id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getStopsModifiersFromRequest(Request $request)
|
||||||
|
{
|
||||||
|
if ($request->query->has('stop')) {
|
||||||
|
$stop = encapsulate($request->query->get('stop'));
|
||||||
|
$stop = collect($stop)->map(ref([Stop::class, 'reference']));
|
||||||
|
|
||||||
|
yield new RelatedFilter($stop);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->query->has('track') || $request->attributes->has('track')) {
|
||||||
|
$track = $request->get('track');
|
||||||
|
$track = Track::reference($track);
|
||||||
|
|
||||||
|
yield new RelatedFilter($track);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->query->has('id')) {
|
||||||
|
$id = encapsulate($request->query->get('id'));
|
||||||
|
|
||||||
|
yield new IdFilter($id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,8 @@ namespace App\Controller\Api\v1;
|
|||||||
|
|
||||||
use App\Controller\Controller;
|
use App\Controller\Controller;
|
||||||
use App\Model\Trip;
|
use App\Model\Trip;
|
||||||
|
use App\Modifier\IdFilter;
|
||||||
|
use App\Modifier\With;
|
||||||
use App\Provider\TripRepository;
|
use App\Provider\TripRepository;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\Routing\Annotation\Route;
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
@ -14,11 +16,11 @@ use Symfony\Component\Routing\Annotation\Route;
|
|||||||
class TripController extends Controller
|
class TripController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @Route("/{id}")
|
* @Route("/{id}", methods={"GET"})
|
||||||
*/
|
*/
|
||||||
public function one($id, TripRepository $repository)
|
public function one($id, TripRepository $repository)
|
||||||
{
|
{
|
||||||
$trip = $repository->getById($id);
|
$trip = $repository->first(new IdFilter($id), new With('schedule'));
|
||||||
|
|
||||||
return $this->json($trip, Response::HTTP_OK, [], $this->serializerContextFactory->create(Trip::class));
|
return $this->json($trip, Response::HTTP_OK, [], $this->serializerContextFactory->create(Trip::class));
|
||||||
}
|
}
|
@ -45,16 +45,18 @@ class TrackEntity implements Entity, Fillable
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops in track
|
* Stops in track
|
||||||
* @var StopInTrack[]|Collection
|
*
|
||||||
* @ORM\OneToMany(targetEntity=StopInTrack::class, fetch="LAZY", mappedBy="track", cascade={"persist"})
|
* @var TrackStopEntity[]|Collection
|
||||||
|
* @ORM\OneToMany(targetEntity=TrackStopEntity::class, fetch="LAZY", mappedBy="track", cascade={"persist"})
|
||||||
* @ORM\OrderBy({"order": "ASC"})
|
* @ORM\OrderBy({"order": "ASC"})
|
||||||
*/
|
*/
|
||||||
private $stopsInTrack;
|
private $stopsInTrack;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Final stop in this track.
|
* Final stop in this track.
|
||||||
* @var StopInTrack
|
*
|
||||||
* @ORM\OneToOne(targetEntity=StopInTrack::class, fetch="LAZY")
|
* @var TrackStopEntity
|
||||||
|
* @ORM\OneToOne(targetEntity=TrackStopEntity::class, fetch="LAZY")
|
||||||
*/
|
*/
|
||||||
private $final;
|
private $final;
|
||||||
|
|
||||||
@ -114,7 +116,7 @@ class TrackEntity implements Entity, Fillable
|
|||||||
$this->final = $this->stopsInTrack->last();
|
$this->final = $this->stopsInTrack->last();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFinal(): StopInTrack
|
public function getFinal(): TrackStopEntity
|
||||||
{
|
{
|
||||||
return $this->final;
|
return $this->final;
|
||||||
}
|
}
|
@ -14,7 +14,7 @@ use Doctrine\ORM\Mapping as ORM;
|
|||||||
* @ORM\UniqueConstraint(name="stop_in_track_idx", columns={"stop_id", "track_id", "sequence"})
|
* @ORM\UniqueConstraint(name="stop_in_track_idx", columns={"stop_id", "track_id", "sequence"})
|
||||||
* })
|
* })
|
||||||
*/
|
*/
|
||||||
class StopInTrack implements Fillable, Referable
|
class TrackStopEntity implements Fillable, Referable
|
||||||
{
|
{
|
||||||
use FillTrait, ReferableEntityTrait;
|
use FillTrait, ReferableEntityTrait;
|
||||||
|
|
@ -4,6 +4,7 @@ namespace App\Entity;
|
|||||||
|
|
||||||
use App\Model\Fillable;
|
use App\Model\Fillable;
|
||||||
use App\Model\FillTrait;
|
use App\Model\FillTrait;
|
||||||
|
use App\Model\Referable;
|
||||||
use App\Model\Trip;
|
use App\Model\Trip;
|
||||||
use App\Service\IdUtils;
|
use App\Service\IdUtils;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
@ -14,21 +15,28 @@ use JMS\Serializer\Tests\Fixtures\Discriminator\Car;
|
|||||||
* @ORM\Entity
|
* @ORM\Entity
|
||||||
* @ORM\Table("trip_stop")
|
* @ORM\Table("trip_stop")
|
||||||
*/
|
*/
|
||||||
class TripStopEntity implements Fillable
|
class TripStopEntity implements Fillable, Referable
|
||||||
{
|
{
|
||||||
use FillTrait;
|
use FillTrait, ReferableEntityTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifier for stop coming from provider
|
||||||
|
*
|
||||||
|
* @ORM\Column(type="integer")
|
||||||
|
* @ORM\Id
|
||||||
|
* @ORM\GeneratedValue
|
||||||
|
*/
|
||||||
|
private $id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var StopEntity
|
* @var StopEntity
|
||||||
* @ORM\ManyToOne(targetEntity=StopEntity::class, fetch="EAGER")
|
* @ORM\ManyToOne(targetEntity=StopEntity::class, fetch="EAGER")
|
||||||
* @ORM\Id
|
|
||||||
*/
|
*/
|
||||||
private $stop;
|
private $stop;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var TripEntity
|
* @var TripEntity
|
||||||
* @ORM\ManyToOne(targetEntity=TripEntity::class, fetch="EAGER", inversedBy="stops")
|
* @ORM\ManyToOne(targetEntity=TripEntity::class, fetch="EAGER", inversedBy="stops")
|
||||||
* @ORM\Id
|
|
||||||
*/
|
*/
|
||||||
private $trip;
|
private $trip;
|
||||||
|
|
||||||
@ -37,7 +45,6 @@ class TripStopEntity implements Fillable
|
|||||||
* @var int
|
* @var int
|
||||||
*
|
*
|
||||||
* @ORM\Column(name="sequence", type="integer")
|
* @ORM\Column(name="sequence", type="integer")
|
||||||
* @ORM\Id
|
|
||||||
*/
|
*/
|
||||||
private $order;
|
private $order;
|
||||||
|
|
34
api/src/Event/HandleDatabaseModifierEvent.php
Normal file
34
api/src/Event/HandleDatabaseModifierEvent.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Event;
|
||||||
|
|
||||||
|
use App\Event\HandleModifierEvent;
|
||||||
|
use App\Modifier\Modifier;
|
||||||
|
use App\Provider\Repository;
|
||||||
|
use Doctrine\ORM\QueryBuilder;
|
||||||
|
|
||||||
|
class HandleDatabaseModifierEvent extends HandleModifierEvent
|
||||||
|
{
|
||||||
|
private $builder;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
Modifier $modifier,
|
||||||
|
Repository $repository,
|
||||||
|
QueryBuilder $builder,
|
||||||
|
array $meta = []
|
||||||
|
) {
|
||||||
|
parent::__construct($modifier, $repository, $meta);
|
||||||
|
|
||||||
|
$this->builder = $builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBuilder(): QueryBuilder
|
||||||
|
{
|
||||||
|
return $this->builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function replaceBuilder(QueryBuilder $builder): void
|
||||||
|
{
|
||||||
|
$this->builder = $builder;
|
||||||
|
}
|
||||||
|
}
|
35
api/src/Event/HandleModifierEvent.php
Normal file
35
api/src/Event/HandleModifierEvent.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Event;
|
||||||
|
|
||||||
|
use App\Modifier\Modifier;
|
||||||
|
use App\Provider\Repository;
|
||||||
|
|
||||||
|
class HandleModifierEvent
|
||||||
|
{
|
||||||
|
private $repository;
|
||||||
|
private $modifier;
|
||||||
|
private $meta = [];
|
||||||
|
|
||||||
|
public function __construct(Modifier $modifier, Repository $repository, array $meta = [])
|
||||||
|
{
|
||||||
|
$this->repository = $repository;
|
||||||
|
$this->modifier = $modifier;
|
||||||
|
$this->meta = $meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getModifier(): Modifier
|
||||||
|
{
|
||||||
|
return $this->modifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRepository()
|
||||||
|
{
|
||||||
|
return $this->repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMeta(): array
|
||||||
|
{
|
||||||
|
return $this->meta;
|
||||||
|
}
|
||||||
|
}
|
27
api/src/Event/PostProcessEvent.php
Normal file
27
api/src/Event/PostProcessEvent.php
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Event;
|
||||||
|
|
||||||
|
use App\Modifier\Modifier;
|
||||||
|
use App\Provider\Repository;
|
||||||
|
|
||||||
|
class PostProcessEvent extends HandleModifierEvent
|
||||||
|
{
|
||||||
|
private $data;
|
||||||
|
|
||||||
|
public function __construct($data, Modifier $modifier, Repository $repository, array $meta = [])
|
||||||
|
{
|
||||||
|
parent::__construct($modifier, $repository, $meta);
|
||||||
|
$this->data = $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getData()
|
||||||
|
{
|
||||||
|
return $this->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setData($data): void
|
||||||
|
{
|
||||||
|
$this->data = $data;
|
||||||
|
}
|
||||||
|
}
|
13
api/src/Exception/InvalidArgumentException.php
Normal file
13
api/src/Exception/InvalidArgumentException.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Exception;
|
||||||
|
|
||||||
|
class InvalidArgumentException extends \InvalidArgumentException
|
||||||
|
{
|
||||||
|
public static function invalidType($parameter, $value, array $expected = [])
|
||||||
|
{
|
||||||
|
return new static(
|
||||||
|
sprintf('Expected %s to be of type: %s. %s given.', $parameter, implode(', ', $expected), gettype($value))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
9
api/src/Exception/NonExistentServiceException.php
Normal file
9
api/src/Exception/NonExistentServiceException.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace App\Exception;
|
||||||
|
|
||||||
|
|
||||||
|
class NonExistentServiceException extends \LogicException
|
||||||
|
{
|
||||||
|
}
|
7
api/src/Exception/NotSupportedException.php
Normal file
7
api/src/Exception/NotSupportedException.php
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Exception;
|
||||||
|
|
||||||
|
class NotSupportedException extends \LogicException
|
||||||
|
{
|
||||||
|
}
|
13
api/src/Exception/UnsupportedModifierException.php
Normal file
13
api/src/Exception/UnsupportedModifierException.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Exception;
|
||||||
|
|
||||||
|
use App\Modifier\Modifier;
|
||||||
|
|
||||||
|
class UnsupportedModifierException extends \LogicException
|
||||||
|
{
|
||||||
|
public static function createFromModifier(Modifier $modifier)
|
||||||
|
{
|
||||||
|
return new static(sprintf("Modifier %s is not supported.", get_class($modifier)));
|
||||||
|
}
|
||||||
|
}
|
@ -13,3 +13,9 @@ function encapsulate($value)
|
|||||||
return [ $value ];
|
return [ $value ];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setup($value, $callback)
|
||||||
|
{
|
||||||
|
$callback($value);
|
||||||
|
return $value;
|
||||||
|
}
|
3
api/src/Functions/index.php
Normal file
3
api/src/Functions/index.php
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__ . '/helpers.php';
|
63
api/src/Handler/Database/FieldFilterDatabaseHandler.php
Normal file
63
api/src/Handler/Database/FieldFilterDatabaseHandler.php
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Handler\Database;
|
||||||
|
|
||||||
|
use App\Event\HandleDatabaseModifierEvent;
|
||||||
|
use App\Event\HandleModifierEvent;
|
||||||
|
use App\Handler\ModifierHandler;
|
||||||
|
use App\Model\ScheduledStop;
|
||||||
|
use App\Model\Stop;
|
||||||
|
use App\Modifier\FieldFilter;
|
||||||
|
use function App\Functions\encapsulate;
|
||||||
|
|
||||||
|
class FieldFilterDatabaseHandler implements ModifierHandler
|
||||||
|
{
|
||||||
|
protected $mapping = [
|
||||||
|
Stop::class => [
|
||||||
|
'name' => 'name',
|
||||||
|
],
|
||||||
|
ScheduledStop::class => [
|
||||||
|
'departure' => 'departure',
|
||||||
|
'arrival' => 'arrival',
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
public function process(HandleModifierEvent $event)
|
||||||
|
{
|
||||||
|
if (!$event instanceof HandleDatabaseModifierEvent) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var FieldFilter $modifier */
|
||||||
|
$modifier = $event->getModifier();
|
||||||
|
$builder = $event->getBuilder();
|
||||||
|
$alias = $event->getMeta()['alias'];
|
||||||
|
|
||||||
|
$field = $this->mapFieldName($event->getMeta()['type'], $modifier->getField());
|
||||||
|
$operator = $modifier->getOperator();
|
||||||
|
$value = $modifier->getValue();
|
||||||
|
|
||||||
|
$parameter = sprintf(":%s_%s", $alias, $field);
|
||||||
|
|
||||||
|
if ($operator === 'in' || $operator === 'not in') {
|
||||||
|
$parameter = "($parameter)";
|
||||||
|
$value = encapsulate($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
$builder
|
||||||
|
->andWhere(sprintf("%s.%s %s %s", $alias, $field, $operator, $parameter))
|
||||||
|
->setParameter($parameter, $value)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function mapFieldName(string $class, string $field)
|
||||||
|
{
|
||||||
|
if (!isset($this->mapping[$class][$field])) {
|
||||||
|
throw new \InvalidArgumentException(
|
||||||
|
sprintf("Unable to map field %s of %s into entity field.", $field, $class)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->mapping[$class][$field];
|
||||||
|
}
|
||||||
|
}
|
103
api/src/Handler/Database/GenericWithDatabaseHandler.php
Normal file
103
api/src/Handler/Database/GenericWithDatabaseHandler.php
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Handler\Database;
|
||||||
|
|
||||||
|
use App\Event\HandleDatabaseModifierEvent;
|
||||||
|
use App\Event\HandleModifierEvent;
|
||||||
|
use App\Handler\ModifierHandler;
|
||||||
|
use App\Model\ScheduledStop;
|
||||||
|
use App\Model\Track;
|
||||||
|
use App\Model\TrackStop;
|
||||||
|
use App\Model\Trip;
|
||||||
|
use App\Modifier\RelatedFilter;
|
||||||
|
use App\Service\EntityReferenceFactory;
|
||||||
|
use App\Service\IdUtils;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use function Kadet\Functional\Transforms\property;
|
||||||
|
|
||||||
|
class GenericWithDatabaseHandler implements ModifierHandler
|
||||||
|
{
|
||||||
|
protected $mapping = [
|
||||||
|
Track::class => [
|
||||||
|
'line' => 'line',
|
||||||
|
'stops' => 'stopsInTrack',
|
||||||
|
],
|
||||||
|
Trip::class => [
|
||||||
|
'schedule' => 'stops.stop',
|
||||||
|
],
|
||||||
|
TrackStop::class => [
|
||||||
|
'track' => 'track',
|
||||||
|
],
|
||||||
|
ScheduledStop::class => [
|
||||||
|
'trip' => 'trip',
|
||||||
|
'track' => 'trip.track',
|
||||||
|
'destination' => 'trip.track.final',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
private $em;
|
||||||
|
private $id;
|
||||||
|
private $references;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
EntityManagerInterface $em,
|
||||||
|
IdUtils $idUtils,
|
||||||
|
EntityReferenceFactory $references
|
||||||
|
) {
|
||||||
|
$this->em = $em;
|
||||||
|
$this->id = $idUtils;
|
||||||
|
$this->references = $references;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function process(HandleModifierEvent $event)
|
||||||
|
{
|
||||||
|
if (!$event instanceof HandleDatabaseModifierEvent) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var RelatedFilter $modifier */
|
||||||
|
$modifier = $event->getModifier();
|
||||||
|
$builder = $event->getBuilder();
|
||||||
|
$alias = $event->getMeta()['alias'];
|
||||||
|
$type = $event->getMeta()['type'];
|
||||||
|
|
||||||
|
if (!array_key_exists($modifier->getRelationship(), $this->mapping[$type])) {
|
||||||
|
throw new \InvalidArgumentException(
|
||||||
|
sprintf("Relationship %s is not supported for .", $type)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$relationship = $this->mapping[$type][$modifier->getRelationship()];
|
||||||
|
|
||||||
|
foreach ($this->getRelationships($relationship, $alias) as [$relationshipPath, $relationshipAlias]) {
|
||||||
|
$selected = collect($builder->getDQLPart('select'))->flatMap(property('parts'));
|
||||||
|
|
||||||
|
if ($selected->contains($relationshipAlias)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$builder
|
||||||
|
->join($relationshipPath, $relationshipAlias)
|
||||||
|
->addSelect($relationshipAlias);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public static function getSubscribedServices()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
TrackByStopDatabaseHandler::class,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getRelationships($relationship, $alias)
|
||||||
|
{
|
||||||
|
$relationships = explode('.', $relationship);
|
||||||
|
|
||||||
|
foreach ($relationships as $current) {
|
||||||
|
yield [sprintf("%s.%s", $alias, $current), $alias = sprintf('%s_%s', $alias, $current)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
44
api/src/Handler/Database/IdFilterDatabaseHandler.php
Normal file
44
api/src/Handler/Database/IdFilterDatabaseHandler.php
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Handler\Database;
|
||||||
|
|
||||||
|
use App\Handler\ModifierHandler;
|
||||||
|
use App\Modifier\IdFilter;
|
||||||
|
use App\Event\HandleDatabaseModifierEvent;
|
||||||
|
use App\Event\HandleModifierEvent;
|
||||||
|
use App\Service\IdUtils;
|
||||||
|
use function Kadet\Functional\apply;
|
||||||
|
|
||||||
|
class IdFilterDatabaseHandler implements ModifierHandler
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var IdUtils
|
||||||
|
*/
|
||||||
|
private $id;
|
||||||
|
|
||||||
|
public function __construct(IdUtils $id)
|
||||||
|
{
|
||||||
|
$this->id = $id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function process(HandleModifierEvent $event)
|
||||||
|
{
|
||||||
|
if (!$event instanceof HandleDatabaseModifierEvent) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var IdFilter $modifier */
|
||||||
|
$modifier = $event->getModifier();
|
||||||
|
$builder = $event->getBuilder();
|
||||||
|
$alias = $event->getMeta()['alias'];
|
||||||
|
$provider = $event->getMeta()['provider'];
|
||||||
|
|
||||||
|
$id = $modifier->getId();
|
||||||
|
$mapper = apply([$this->id, 'generate'], $provider);
|
||||||
|
|
||||||
|
$builder
|
||||||
|
->andWhere($modifier->isMultiple() ? "{$alias} in (:id)" : "{$alias} = :id")
|
||||||
|
->setParameter(':id', $modifier->isMultiple() ? array_map($mapper, $id) : $mapper($id));
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
27
api/src/Handler/Database/LimitDatabaseHandler.php
Normal file
27
api/src/Handler/Database/LimitDatabaseHandler.php
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Handler\Database;
|
||||||
|
|
||||||
|
use App\Event\HandleDatabaseModifierEvent;
|
||||||
|
use App\Event\HandleModifierEvent;
|
||||||
|
use App\Handler\ModifierHandler;
|
||||||
|
use App\Modifier\Limit;
|
||||||
|
|
||||||
|
class LimitDatabaseHandler implements ModifierHandler
|
||||||
|
{
|
||||||
|
public function process(HandleModifierEvent $event)
|
||||||
|
{
|
||||||
|
if (!$event instanceof HandleDatabaseModifierEvent) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var Limit $modifier */
|
||||||
|
$modifier = $event->getModifier();
|
||||||
|
$builder = $event->getBuilder();
|
||||||
|
|
||||||
|
$builder
|
||||||
|
->setFirstResult($modifier->getOffset())
|
||||||
|
->setMaxResults($modifier->getCount())
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user