├── .env ├── .env.test ├── .gitignore ├── README.md ├── bin ├── console └── phpunit ├── compose.yaml ├── composer.json ├── composer.lock ├── config ├── bundles.php ├── packages │ ├── api_platform.yaml │ ├── cache.yaml │ ├── doctrine.yaml │ ├── doctrine_migrations.yaml │ ├── framework.yaml │ ├── nelmio_cors.yaml │ ├── routing.yaml │ ├── security.yaml │ ├── twig.yaml │ ├── uid.yaml │ └── validator.yaml ├── preload.php ├── routes.yaml ├── routes │ ├── api_platform.yaml │ ├── framework.yaml │ └── security.yaml └── services.yaml ├── in ├── json_province.json ├── mada_fokontany_payload.csv └── mixed_payload.json ├── migrations └── .gitignore ├── phpunit.xml.dist ├── public ├── custom │ ├── css │ │ └── style.css │ ├── custom_style.css │ ├── custorm_script.js │ ├── images │ │ ├── cta-illustration-dark.svg │ │ ├── cta-illustration-light.svg │ │ ├── feature-01-dark.svg │ │ ├── feature-01-light.svg │ │ ├── feature-02-dark.svg │ │ ├── feature-02-light.svg │ │ ├── feature-03-dark.svg │ │ ├── feature-03-light.svg │ │ ├── features-box-dark.svg │ │ ├── features-box-light.svg │ │ ├── features-illustration-dark.svg │ │ ├── features-illustration-light.svg │ │ ├── features-illustration-top-dark.svg │ │ ├── features-illustration-top-light.svg │ │ ├── github.png │ │ ├── header-illustration-dark.svg │ │ ├── header-illustration-light.svg │ │ ├── hero-media-dark.svg │ │ ├── hero-media-illustration-dark.svg │ │ ├── hero-media-illustration-light.svg │ │ ├── hero-media-light.svg │ │ ├── logo-dark.svg │ │ ├── logo-light.svg │ │ └── mada-ill.png │ ├── img.png │ ├── img_1.png │ ├── img_2.png │ └── js │ │ └── main.min.js └── index.php ├── src ├── ApiResource │ └── .gitignore ├── Command │ └── ImportPayloadCommand.php ├── Controller │ ├── .gitignore │ └── HomeController.php ├── Entity │ ├── .gitignore │ ├── CodePostale.php │ ├── Commune.php │ ├── District.php │ ├── Fokontany.php │ ├── Province.php │ └── Region.php ├── Kernel.php ├── Manager │ └── ImportDataManager.php └── Repository │ ├── .gitignore │ ├── CodePostaleRepository.php │ ├── CommuneRepository.php │ ├── DistrictRepository.php │ ├── FokontanyRepository.php │ ├── ProvinceRepository.php │ └── RegionRepository.php ├── symfony.lock ├── templates ├── base.html.twig ├── bundles │ └── ApiPlatformBundle │ │ └── SwaggerUi │ │ └── index.html.twig └── homepage │ └── index.html.twig └── tests ├── CommuneTest.php ├── DistrictTest.php ├── FokontanyTest.php ├── RegionTest.php └── bootstrap.php /.env: -------------------------------------------------------------------------------- 1 | # In all environments, the following files are loaded if they exist, 2 | # the latter taking precedence over the former: 3 | # 4 | # * .env contains default values for the environment variables needed by the app 5 | # * .env.local uncommitted file with local overrides 6 | # * .env.$APP_ENV committed environment-specific defaults 7 | # * .env.$APP_ENV.local uncommitted environment-specific overrides 8 | # 9 | # Real environment variables win over .env files. 10 | # 11 | # DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES. 12 | # https://symfony.com/doc/current/configuration/secrets.html 13 | # 14 | # Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2). 15 | # https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration 16 | 17 | ###> symfony/framework-bundle ### 18 | APP_ENV=dev 19 | APP_SECRET=cdcd615f67c15d8d611ae1ce387153d7 20 | ###< symfony/framework-bundle ### 21 | 22 | ###> doctrine/doctrine-bundle ### 23 | # Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url 24 | # IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml 25 | # 26 | # DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db" 27 | # DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8.0.32&charset=utf8mb4" 28 | # DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=10.11.2-MariaDB&charset=utf8mb4" 29 | DATABASE_URL="postgresql://app:!ChangeMe!@127.0.0.1:5432/app?serverVersion=15&charset=utf8" 30 | ###< doctrine/doctrine-bundle ### 31 | 32 | ###> nelmio/cors-bundle ### 33 | CORS_ALLOW_ORIGIN='^https?://(localhost|127\.0\.0\.1)(:[0-9]+)?$' 34 | ###< nelmio/cors-bundle ### 35 | 36 | ###> docker/env ### 37 | POSTGRES_PASSWORD= 38 | POSTGRES_USER= 39 | POSTGRES_DB= 40 | ###> docker/env ### 41 | -------------------------------------------------------------------------------- /.env.test: -------------------------------------------------------------------------------- 1 | # define your env variables for the test env here 2 | KERNEL_CLASS='App\Kernel' 3 | APP_SECRET='$ecretf0rt3st' 4 | SYMFONY_DEPRECATIONS_HELPER=999999 5 | PANTHER_APP_ENV=panther 6 | PANTHER_ERROR_SCREENSHOT_DIR=./var/error-screenshots 7 | 8 | ###> docker/env ### 9 | POSTGRES_USER=mada 10 | POSTGRES_PASSWORD=mada 11 | POSTGRES_DB=mada-map 12 | ###> docker/env ### 13 | 14 | DATABASE_URL="postgresql://mada:mada@localhost:5432/mada-map?serverVersion=15&charset=utf8" -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | ###> symfony/framework-bundle ### 3 | /.env.local 4 | /.env.local.php 5 | /.env.*.local 6 | /config/secrets/prod/prod.decrypt.private.php 7 | /public/bundles/ 8 | /var/ 9 | /vendor/ 10 | ###< symfony/framework-bundle ### 11 | 12 | ###> .idea/ide ### 13 | /.idea/ 14 | /.vscode/ 15 | ###< idea/ide ### 16 | 17 | ###> symfony/phpunit-bridge ### 18 | .phpunit.result.cache 19 | /phpunit.xml 20 | ###< symfony/phpunit-bridge ### 21 | 22 | ###> phpunit/phpunit ### 23 | /phpunit.xml 24 | .phpunit.result.cache 25 | ###< phpunit/phpunit ### 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Madagascar map API 2 | 3 | ## Contribution Guides 4 | 5 | Your feedback and collaboration are highly valued as we evolve this resource for the developer community. 💪 6 | 7 | - Add issues for what you wish to work on. 8 | - Fork this Repository 9 | - Add Unit Test 10 | - Make a PR to the main branch 11 | 12 | ## Requirements : 13 | ``` 14 | - Docker 15 | - Postgresql 16 | - PHP > 8.1 17 | ``` 18 | 19 | ## Installation 20 | You can install this project using Docker [PHP & Postgres] as outlined above, or alternatively, by installing Postgres and PHP directly in your workspace. 21 | 22 | ``` 23 | - Clone the repos 24 | - Run docker compose build 25 | - Run docker compose up 26 | - Copy .env to .env.local, then customise your DB_URL. 27 | - Run symfony serve 28 | - Do what you want 29 | ``` 30 | 31 | 32 | *For fun :heart: !* 33 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | = 80000) { 10 | require dirname(__DIR__).'/vendor/phpunit/phpunit/phpunit'; 11 | } else { 12 | define('PHPUNIT_COMPOSER_INSTALL', dirname(__DIR__).'/vendor/autoload.php'); 13 | require PHPUNIT_COMPOSER_INSTALL; 14 | PHPUnit\TextUI\Command::main(); 15 | } 16 | } else { 17 | if (!is_file(dirname(__DIR__).'/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php')) { 18 | echo "Unable to find the `simple-phpunit.php` script in `vendor/symfony/phpunit-bridge/bin/`.\n"; 19 | exit(1); 20 | } 21 | 22 | require dirname(__DIR__).'/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php'; 23 | } 24 | -------------------------------------------------------------------------------- /compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | ###> doctrine/doctrine-bundle ### 5 | database: 6 | image: postgres:${POSTGRES_VERSION:-15}-alpine 7 | environment: 8 | POSTGRES_DB: ${POSTGRES_DB:-app} 9 | # You should definitely change the password in production 10 | POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-!ChangeMe!} 11 | POSTGRES_USER: ${POSTGRES_USER:-app} 12 | volumes: 13 | - database_data:/var/lib/postgresql/data:rw 14 | ports: 15 | - "5432:5432" 16 | # You may use a bind-mounted host directory instead, so that it is harder to accidentally remove the volume and lose all your data! 17 | # - ./docker/db/data:/var/lib/postgresql/data:rw 18 | ###< doctrine/doctrine-bundle ### 19 | 20 | volumes: 21 | ###> doctrine/doctrine-bundle ### 22 | database_data: 23 | ###< doctrine/doctrine-bundle ### 24 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "project", 3 | "license": "proprietary", 4 | "minimum-stability": "stable", 5 | "prefer-stable": true, 6 | "require": { 7 | "php": ">=8.1", 8 | "ext-ctype": "*", 9 | "ext-iconv": "*", 10 | "api-platform/core": "^3.2", 11 | "doctrine/doctrine-bundle": "^2.11", 12 | "doctrine/doctrine-migrations-bundle": "^3.3", 13 | "doctrine/orm": "^2.17", 14 | "nelmio/cors-bundle": "^2.4", 15 | "phpdocumentor/reflection-docblock": "^5.3", 16 | "phpstan/phpdoc-parser": "^1.25", 17 | "symfony/asset": "6.4.*", 18 | "symfony/console": "6.4.*", 19 | "symfony/dotenv": "6.4.*", 20 | "symfony/expression-language": "6.4.*", 21 | "symfony/flex": "^2", 22 | "symfony/framework-bundle": "6.4.*", 23 | "symfony/property-access": "6.4.*", 24 | "symfony/property-info": "6.4.*", 25 | "symfony/runtime": "6.4.*", 26 | "symfony/security-bundle": "6.4.*", 27 | "symfony/serializer": "6.4.*", 28 | "symfony/twig-bundle": "6.4.*", 29 | "symfony/uid": "6.4.*", 30 | "symfony/validator": "6.4.*", 31 | "symfony/yaml": "6.4.*" 32 | }, 33 | "config": { 34 | "allow-plugins": { 35 | "php-http/discovery": true, 36 | "symfony/flex": true, 37 | "symfony/runtime": true 38 | }, 39 | "sort-packages": true 40 | }, 41 | "autoload": { 42 | "psr-4": { 43 | "App\\": "src/" 44 | } 45 | }, 46 | "autoload-dev": { 47 | "psr-4": { 48 | "App\\Tests\\": "tests/" 49 | } 50 | }, 51 | "replace": { 52 | "symfony/polyfill-ctype": "*", 53 | "symfony/polyfill-iconv": "*", 54 | "symfony/polyfill-php72": "*", 55 | "symfony/polyfill-php73": "*", 56 | "symfony/polyfill-php74": "*", 57 | "symfony/polyfill-php80": "*", 58 | "symfony/polyfill-php81": "*" 59 | }, 60 | "scripts": { 61 | "auto-scripts": { 62 | "cache:clear": "symfony-cmd", 63 | "assets:install %PUBLIC_DIR%": "symfony-cmd" 64 | }, 65 | "post-install-cmd": [ 66 | "@auto-scripts" 67 | ], 68 | "post-update-cmd": [ 69 | "@auto-scripts" 70 | ] 71 | }, 72 | "conflict": { 73 | "symfony/symfony": "*" 74 | }, 75 | "extra": { 76 | "symfony": { 77 | "allow-contrib": false, 78 | "require": "6.4.*" 79 | } 80 | }, 81 | "require-dev": { 82 | "phpunit/phpunit": "^9.5", 83 | "symfony/browser-kit": "6.4.*", 84 | "symfony/css-selector": "6.4.*", 85 | "symfony/http-client": "6.4.*", 86 | "symfony/maker-bundle": "^1.52", 87 | "symfony/phpunit-bridge": "^7.0" 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /config/bundles.php: -------------------------------------------------------------------------------- 1 | ['all' => true], 5 | Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], 6 | Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], 7 | Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], 8 | Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], 9 | Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true], 10 | ApiPlatform\Symfony\Bundle\ApiPlatformBundle::class => ['all' => true], 11 | Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], 12 | ]; 13 | -------------------------------------------------------------------------------- /config/packages/api_platform.yaml: -------------------------------------------------------------------------------- 1 | api_platform: 2 | title: Madagascar Localization 3 | version: 1.1.0 4 | formats: 5 | jsonld: ['application/ld+json'] 6 | docs_formats: 7 | jsonld: ['application/ld+json'] 8 | jsonopenapi: ['application/vnd.openapi+json'] 9 | html: ['text/html'] 10 | defaults: 11 | pagination_items_per_page: 30 12 | stateless: true 13 | cache_headers: 14 | vary: ['Content-Type', 'Authorization', 'Origin'] 15 | extra_properties: 16 | standard_put: true 17 | rfc_7807_compliant_errors: true 18 | event_listeners_backward_compatibility_layer: false 19 | keep_legacy_inflector: false 20 | -------------------------------------------------------------------------------- /config/packages/cache.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | cache: 3 | # Unique name of your app: used to compute stable namespaces for cache keys. 4 | #prefix_seed: your_vendor_name/app_name 5 | 6 | # The "app" cache stores to the filesystem by default. 7 | # The data in this cache should persist between deploys. 8 | # Other options include: 9 | 10 | # Redis 11 | #app: cache.adapter.redis 12 | #default_redis_provider: redis://localhost 13 | 14 | # APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues) 15 | #app: cache.adapter.apcu 16 | 17 | # Namespaced pools use the above "app" backend by default 18 | #pools: 19 | #my.dedicated.cache: null 20 | -------------------------------------------------------------------------------- /config/packages/doctrine.yaml: -------------------------------------------------------------------------------- 1 | doctrine: 2 | dbal: 3 | url: '%env(resolve:DATABASE_URL)%' 4 | 5 | # IMPORTANT: You MUST configure your server version, 6 | # either here or in the DATABASE_URL env var (see .env file) 7 | #server_version: '15' 8 | 9 | profiling_collect_backtrace: '%kernel.debug%' 10 | orm: 11 | auto_generate_proxy_classes: true 12 | enable_lazy_ghost_objects: true 13 | report_fields_where_declared: true 14 | validate_xml_mapping: true 15 | naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware 16 | auto_mapping: true 17 | mappings: 18 | App: 19 | type: attribute 20 | is_bundle: false 21 | dir: '%kernel.project_dir%/src/Entity' 22 | prefix: 'App\Entity' 23 | alias: App 24 | 25 | when@test: 26 | doctrine: 27 | dbal: 28 | # "TEST_TOKEN" is typically set by ParaTest 29 | dbname_suffix: '_test%env(default::TEST_TOKEN)%' 30 | 31 | when@prod: 32 | doctrine: 33 | orm: 34 | auto_generate_proxy_classes: false 35 | proxy_dir: '%kernel.build_dir%/doctrine/orm/Proxies' 36 | query_cache_driver: 37 | type: pool 38 | pool: doctrine.system_cache_pool 39 | result_cache_driver: 40 | type: pool 41 | pool: doctrine.result_cache_pool 42 | 43 | framework: 44 | cache: 45 | pools: 46 | doctrine.result_cache_pool: 47 | adapter: cache.app 48 | doctrine.system_cache_pool: 49 | adapter: cache.system 50 | -------------------------------------------------------------------------------- /config/packages/doctrine_migrations.yaml: -------------------------------------------------------------------------------- 1 | doctrine_migrations: 2 | migrations_paths: 3 | # namespace is arbitrary but should be different from App\Migrations 4 | # as migrations classes should NOT be autoloaded 5 | 'DoctrineMigrations': '%kernel.project_dir%/migrations' 6 | enable_profiler: false 7 | -------------------------------------------------------------------------------- /config/packages/framework.yaml: -------------------------------------------------------------------------------- 1 | # see https://symfony.com/doc/current/reference/configuration/framework.html 2 | framework: 3 | secret: '%env(APP_SECRET)%' 4 | #csrf_protection: true 5 | annotations: false 6 | http_method_override: false 7 | handle_all_throwables: true 8 | 9 | # Enables session support. Note that the session will ONLY be started if you read or write from it. 10 | # Remove or comment this section to explicitly disable session support. 11 | session: 12 | handler_id: null 13 | cookie_secure: auto 14 | cookie_samesite: lax 15 | 16 | #esi: true 17 | #fragments: true 18 | php_errors: 19 | log: true 20 | 21 | when@test: 22 | framework: 23 | test: true 24 | session: 25 | storage_factory_id: session.storage.factory.mock_file 26 | -------------------------------------------------------------------------------- /config/packages/nelmio_cors.yaml: -------------------------------------------------------------------------------- 1 | nelmio_cors: 2 | defaults: 3 | origin_regex: true 4 | allow_origin: ['%env(CORS_ALLOW_ORIGIN)%'] 5 | allow_methods: ['GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE'] 6 | allow_headers: ['Content-Type', 'Authorization'] 7 | expose_headers: ['Link'] 8 | max_age: 3600 9 | paths: 10 | '^/': null 11 | -------------------------------------------------------------------------------- /config/packages/routing.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | router: 3 | utf8: true 4 | 5 | # Configure how to generate URLs in non-HTTP contexts, such as CLI commands. 6 | # See https://symfony.com/doc/current/routing.html#generating-urls-in-commands 7 | #default_uri: http://localhost 8 | 9 | when@prod: 10 | framework: 11 | router: 12 | strict_requirements: null 13 | -------------------------------------------------------------------------------- /config/packages/security.yaml: -------------------------------------------------------------------------------- 1 | security: 2 | # https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords 3 | password_hashers: 4 | Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto' 5 | # https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider 6 | providers: 7 | users_in_memory: { memory: null } 8 | firewalls: 9 | dev: 10 | pattern: ^/(_(profiler|wdt)|css|images|js)/ 11 | security: false 12 | main: 13 | lazy: true 14 | provider: users_in_memory 15 | 16 | # activate different ways to authenticate 17 | # https://symfony.com/doc/current/security.html#the-firewall 18 | 19 | # https://symfony.com/doc/current/security/impersonating_user.html 20 | # switch_user: true 21 | 22 | # Easy way to control access for large sections of your site 23 | # Note: Only the *first* access control that matches will be used 24 | access_control: 25 | # - { path: ^/admin, roles: ROLE_ADMIN } 26 | # - { path: ^/profile, roles: ROLE_USER } 27 | 28 | when@test: 29 | security: 30 | password_hashers: 31 | # By default, password hashers are resource intensive and take time. This is 32 | # important to generate secure password hashes. In tests however, secure hashes 33 | # are not important, waste resources and increase test times. The following 34 | # reduces the work factor to the lowest possible values. 35 | Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 36 | algorithm: auto 37 | cost: 4 # Lowest possible value for bcrypt 38 | time_cost: 3 # Lowest possible value for argon 39 | memory_cost: 10 # Lowest possible value for argon 40 | -------------------------------------------------------------------------------- /config/packages/twig.yaml: -------------------------------------------------------------------------------- 1 | twig: 2 | default_path: '%kernel.project_dir%/templates' 3 | 4 | when@test: 5 | twig: 6 | strict_variables: true 7 | -------------------------------------------------------------------------------- /config/packages/uid.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | uid: 3 | default_uuid_version: 7 4 | time_based_uuid_version: 7 5 | -------------------------------------------------------------------------------- /config/packages/validator.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | validation: 3 | email_validation_mode: html5 4 | 5 | # Enables validator auto-mapping support. 6 | # For instance, basic validation constraints will be inferred from Doctrine's metadata. 7 | #auto_mapping: 8 | # App\Entity\: [] 9 | 10 | when@test: 11 | framework: 12 | validation: 13 | not_compromised_password: false 14 | -------------------------------------------------------------------------------- /config/preload.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | tests 23 | 24 | 25 | 26 | 27 | 28 | src 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /public/custom/custom_style.css: -------------------------------------------------------------------------------- 1 | 2 | header:before { 3 | content: ""; 4 | background-color: white; 5 | height: 70px; 6 | width: 100%; 7 | text-align: center; 8 | position: fixed; 9 | top: 0; 10 | z-index: 100; 11 | box-shadow: 0 1px 3px rgba(0, 0, 0, .12), 0 1px 2px rgba(0, 0, 0, .24); 12 | } 13 | 14 | header #logo { 15 | position: fixed; 16 | top : 35px; 17 | right: 40px; 18 | z-index: 102; 19 | transform: translateY(-50%); 20 | } 21 | 22 | header #logo img { 23 | height: 50px; 24 | background: transparent; 25 | } 26 | 27 | header #home { 28 | position: fixed; 29 | top : 35px; 30 | left: 40px; 31 | z-index: 102; 32 | transform: translateY(-50%); 33 | } 34 | 35 | header #home img { 36 | height: 50px; 37 | background: transparent; 38 | } 39 | 40 | #swagger-ui.api-platform .info .title { 41 | color: #014d86; 42 | } 43 | 44 | .swagger-ui .auth-wrapper .authorize { 45 | display: none; 46 | } 47 | 48 | #swagger-ui.api-platform .opblock.opblock-get .opblock-summary-method { 49 | background-color: #014d86; 50 | } 51 | 52 | #swagger-ui.api-platform .btn.execute { 53 | background-color: #014d86; 54 | border-color: #014d86; 55 | animation: none; 56 | transition: all ease .3s; 57 | } -------------------------------------------------------------------------------- /public/custom/custorm_script.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/julkwel/madagascar-map-api/82ce603cc410cb48acddb611cbc8faaa36024cb6/public/custom/custorm_script.js -------------------------------------------------------------------------------- /public/custom/images/feature-01-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/custom/images/feature-01-light.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/custom/images/feature-02-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/custom/images/feature-02-light.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/custom/images/feature-03-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/custom/images/feature-03-light.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/custom/images/features-box-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/custom/images/features-box-light.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/custom/images/features-illustration-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/custom/images/features-illustration-light.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/custom/images/features-illustration-top-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/custom/images/features-illustration-top-light.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/custom/images/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/julkwel/madagascar-map-api/82ce603cc410cb48acddb611cbc8faaa36024cb6/public/custom/images/github.png -------------------------------------------------------------------------------- /public/custom/images/header-illustration-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/custom/images/header-illustration-light.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/custom/images/hero-media-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/custom/images/hero-media-illustration-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/custom/images/hero-media-illustration-light.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/custom/images/hero-media-light.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/custom/images/logo-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/custom/images/logo-light.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/custom/images/mada-ill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/julkwel/madagascar-map-api/82ce603cc410cb48acddb611cbc8faaa36024cb6/public/custom/images/mada-ill.png -------------------------------------------------------------------------------- /public/custom/img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/julkwel/madagascar-map-api/82ce603cc410cb48acddb611cbc8faaa36024cb6/public/custom/img.png -------------------------------------------------------------------------------- /public/custom/img_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/julkwel/madagascar-map-api/82ce603cc410cb48acddb611cbc8faaa36024cb6/public/custom/img_1.png -------------------------------------------------------------------------------- /public/custom/img_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/julkwel/madagascar-map-api/82ce603cc410cb48acddb611cbc8faaa36024cb6/public/custom/img_2.png -------------------------------------------------------------------------------- /public/custom/js/main.min.js: -------------------------------------------------------------------------------- 1 | !function(){const e=document,t=e.documentElement,n=e.body,i=e.getElementById("lights-toggle"),s=window.sr=ScrollReveal();function a(){let e=i.parentNode.querySelector(".label-text");i.checked?(n.classList.remove("lights-off"),e&&(e.innerHTML="dark")):(n.classList.add("lights-off"),e&&(e.innerHTML="light"))}t.classList.remove("no-js"),t.classList.add("js"),window.addEventListener("load",function(){n.classList.add("is-loaded")}),n.classList.contains("has-animations")&&window.addEventListener("load",function(){s.reveal(".feature",{duration:600,distance:"20px",easing:"cubic-bezier(0.215, 0.61, 0.355, 1)",origin:"right",viewFactor:.2})}),i&&(window.addEventListener("load",a),i.addEventListener("change",a))}(); -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | addOption('province', null, InputOption::VALUE_NONE); 26 | $this->addOption('code-postale', null, InputOption::VALUE_NONE); 27 | } 28 | 29 | protected function configure(): void 30 | {} 31 | 32 | protected function execute(InputInterface $input, OutputInterface $output): int 33 | { 34 | $ioStyle = new SymfonyStyle($input, $output); 35 | 36 | if ($input->getOption('code-postale')) { 37 | $this->dataManager->importCodePostale($ioStyle); 38 | exit(Command::SUCCESS); 39 | } 40 | 41 | if ($input->getOption('province')) { 42 | $this->dataManager->importProvince($ioStyle); 43 | exit(Command::SUCCESS); 44 | } 45 | 46 | $this->dataManager->importData($ioStyle); 47 | 48 | return Command::SUCCESS; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Controller/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/julkwel/madagascar-map-api/82ce603cc410cb48acddb611cbc8faaa36024cb6/src/Controller/.gitignore -------------------------------------------------------------------------------- /src/Controller/HomeController.php: -------------------------------------------------------------------------------- 1 | render('homepage/index.html.twig'); 25 | } 26 | } -------------------------------------------------------------------------------- /src/Entity/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/julkwel/madagascar-map-api/82ce603cc410cb48acddb611cbc8faaa36024cb6/src/Entity/.gitignore -------------------------------------------------------------------------------- /src/Entity/CodePostale.php: -------------------------------------------------------------------------------- 1 | ['code:read']], 24 | )] 25 | #[ApiFilter(SearchFilter::class, properties: ['codePostal' => 'ipartial', 'ville' => 'ipartial'])] 26 | #[ApiFilter(OrderFilter::class, properties: ['codePostal'], arguments: ['orderParameterName' => 'order'])] 27 | class CodePostale 28 | { 29 | #[ORM\Id] 30 | #[ORM\Column(type: UuidType::NAME, unique: true)] 31 | #[ORM\GeneratedValue(strategy: 'CUSTOM')] 32 | #[ORM\CustomIdGenerator(class: 'doctrine.uuid_generator')] 33 | #[Groups(['code:read'])] 34 | private ?Uuid $id = null; 35 | 36 | #[ORM\Column(length: 5)] 37 | #[Groups(['code:read'])] 38 | private ?string $codePostal = null; 39 | 40 | #[ORM\Column(length: 255)] 41 | #[Groups(['code:read'])] 42 | private ?string $ville = null; 43 | 44 | #[ORM\ManyToOne] 45 | #[Groups(['code:read'])] 46 | private ?Region $region = null; 47 | 48 | #[ORM\ManyToOne(inversedBy: 'codePostales')] 49 | #[ORM\JoinColumn(nullable: false)] 50 | #[Groups(['code:read'])] 51 | private ?Province $province = null; 52 | 53 | public function getId(): ?string 54 | { 55 | return $this->id; 56 | } 57 | 58 | public function getCodePostal(): ?string 59 | { 60 | return $this->codePostal; 61 | } 62 | 63 | public function setCodePostal(string $codePostal): static 64 | { 65 | $this->codePostal = $codePostal; 66 | 67 | return $this; 68 | } 69 | 70 | public function getVille(): ?string 71 | { 72 | return $this->ville; 73 | } 74 | 75 | public function setVille(string $ville): static 76 | { 77 | $this->ville = $ville; 78 | 79 | return $this; 80 | } 81 | 82 | public function getRegion(): ?Region 83 | { 84 | return $this->region; 85 | } 86 | 87 | public function setRegion(?Region $region): static 88 | { 89 | $this->region = $region; 90 | 91 | return $this; 92 | } 93 | 94 | public function getProvince(): ?Province 95 | { 96 | return $this->province; 97 | } 98 | 99 | public function setProvince(?Province $province): static 100 | { 101 | $this->province = $province; 102 | 103 | return $this; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/Entity/Commune.php: -------------------------------------------------------------------------------- 1 | ['commune:read', 'fokontany:read']] 26 | )] 27 | #[ApiFilter(SearchFilter::class, properties: ['name' => 'ipartial'])] 28 | #[ApiFilter(OrderFilter::class, properties: ['name'], arguments: ['orderParameterName' => 'order'])] 29 | class Commune 30 | { 31 | #[ORM\Id] 32 | #[ORM\Column(type: UuidType::NAME, unique: true)] 33 | #[ORM\GeneratedValue(strategy: 'CUSTOM')] 34 | #[ORM\CustomIdGenerator(class: 'doctrine.uuid_generator')] 35 | #[Groups(['commune:read'])] 36 | private ?Uuid $id = null; 37 | 38 | #[ORM\Column(length: 255)] 39 | #[Groups(['commune:read', 'fokontany:read'])] 40 | private ?string $name = null; 41 | 42 | #[ORM\ManyToOne(inversedBy: 'communes')] 43 | #[Groups(['commune:read'])] 44 | private ?Region $region = null; 45 | 46 | #[ORM\ManyToOne(inversedBy: 'communes')] 47 | #[Groups(['commune:read'])] 48 | private ?District $district = null; 49 | 50 | #[ORM\OneToMany(mappedBy: 'commune', targetEntity: Fokontany::class)] 51 | private Collection $fokontanies; 52 | 53 | public function __construct() 54 | { 55 | $this->fokontanies = new ArrayCollection(); 56 | } 57 | 58 | public function getId(): ?string 59 | { 60 | return $this->id; 61 | } 62 | 63 | public function getName(): ?string 64 | { 65 | return $this->name; 66 | } 67 | 68 | public function setName(string $name): static 69 | { 70 | $this->name = $name; 71 | 72 | return $this; 73 | } 74 | 75 | public function getRegion(): ?Region 76 | { 77 | return $this->region; 78 | } 79 | 80 | public function setRegion(?Region $region): static 81 | { 82 | $this->region = $region; 83 | 84 | return $this; 85 | } 86 | 87 | public function getDistrict(): ?District 88 | { 89 | return $this->district; 90 | } 91 | 92 | public function setDistrict(?District $district): static 93 | { 94 | $this->district = $district; 95 | 96 | return $this; 97 | } 98 | 99 | /** 100 | * @return Collection 101 | */ 102 | public function getFokontanies(): Collection 103 | { 104 | return $this->fokontanies; 105 | } 106 | 107 | public function addFokontany(Fokontany $fokontany): static 108 | { 109 | if (!$this->fokontanies->contains($fokontany)) { 110 | $this->fokontanies->add($fokontany); 111 | $fokontany->setCommune($this); 112 | } 113 | 114 | return $this; 115 | } 116 | 117 | public function removeFokontany(Fokontany $fokontany): static 118 | { 119 | if ($this->fokontanies->removeElement($fokontany)) { 120 | // set the owning side to null (unless already changed) 121 | if ($fokontany->getCommune() === $this) { 122 | $fokontany->setCommune(null); 123 | } 124 | } 125 | 126 | return $this; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/Entity/District.php: -------------------------------------------------------------------------------- 1 | ['district:read', 'commune:read', 'fokontany:read']] 26 | )] 27 | #[ApiFilter(SearchFilter::class, properties: ['name' => 'ipartial'])] 28 | #[ApiFilter(OrderFilter::class, properties: ['name'], arguments: ['orderParameterName' => 'order'])] 29 | class District 30 | { 31 | #[ORM\Id] 32 | #[ORM\Column(type: UuidType::NAME, unique: true)] 33 | #[ORM\GeneratedValue(strategy: 'CUSTOM')] 34 | #[ORM\CustomIdGenerator(class: 'doctrine.uuid_generator')] 35 | #[Groups(['district:read'])] 36 | private ?Uuid $id = null; 37 | 38 | #[ORM\Column(length: 255)] 39 | #[Groups(['district:read', 'commune:read', 'fokontany:read'])] 40 | private ?string $name = null; 41 | 42 | #[ORM\ManyToOne(inversedBy: 'districts')] 43 | #[Groups(['district:read'])] 44 | private ?Region $region = null; 45 | 46 | #[ORM\OneToMany(mappedBy: 'district', targetEntity: Commune::class)] 47 | private Collection $communes; 48 | 49 | #[ORM\OneToMany(mappedBy: 'district', targetEntity: Fokontany::class)] 50 | private Collection $fokontanies; 51 | 52 | public function __construct() 53 | { 54 | $this->communes = new ArrayCollection(); 55 | $this->fokontanies = new ArrayCollection(); 56 | } 57 | 58 | public function getId(): ?string 59 | { 60 | return $this->id; 61 | } 62 | 63 | public function getRegion(): ?Region 64 | { 65 | return $this->region; 66 | } 67 | 68 | public function setRegion(?Region $region): static 69 | { 70 | $this->region = $region; 71 | 72 | return $this; 73 | } 74 | 75 | public function getName(): ?string 76 | { 77 | return $this->name; 78 | } 79 | 80 | public function setName(string $name): static 81 | { 82 | $this->name = $name; 83 | 84 | return $this; 85 | } 86 | 87 | /** 88 | * @return Collection 89 | */ 90 | public function getCommunes(): Collection 91 | { 92 | return $this->communes; 93 | } 94 | 95 | public function addCommune(Commune $commune): static 96 | { 97 | if (!$this->communes->contains($commune)) { 98 | $this->communes->add($commune); 99 | $commune->setDistrict($this); 100 | } 101 | 102 | return $this; 103 | } 104 | 105 | public function removeCommune(Commune $commune): static 106 | { 107 | if ($this->communes->removeElement($commune)) { 108 | // set the owning side to null (unless already changed) 109 | if ($commune->getDistrict() === $this) { 110 | $commune->setDistrict(null); 111 | } 112 | } 113 | 114 | return $this; 115 | } 116 | 117 | /** 118 | * @return Collection 119 | */ 120 | public function getFokontanies(): Collection 121 | { 122 | return $this->fokontanies; 123 | } 124 | 125 | public function addFokontany(Fokontany $fokontany): static 126 | { 127 | if (!$this->fokontanies->contains($fokontany)) { 128 | $this->fokontanies->add($fokontany); 129 | $fokontany->setDistrict($this); 130 | } 131 | 132 | return $this; 133 | } 134 | 135 | public function removeFokontany(Fokontany $fokontany): static 136 | { 137 | if ($this->fokontanies->removeElement($fokontany)) { 138 | // set the owning side to null (unless already changed) 139 | if ($fokontany->getDistrict() === $this) { 140 | $fokontany->setDistrict(null); 141 | } 142 | } 143 | 144 | return $this; 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/Entity/Fokontany.php: -------------------------------------------------------------------------------- 1 | ['fokontany:read']] 24 | )] 25 | #[ApiFilter(SearchFilter::class, properties: ['name' => 'ipartial'])] 26 | #[ApiFilter(OrderFilter::class, properties: ['name'], arguments: ['orderParameterName' => 'order'])] 27 | class Fokontany 28 | { 29 | #[ORM\Id] 30 | #[ORM\Column(type: UuidType::NAME, unique: true)] 31 | #[ORM\GeneratedValue(strategy: 'CUSTOM')] 32 | #[ORM\CustomIdGenerator(class: 'doctrine.uuid_generator')] 33 | #[Groups(['fokontany:read'])] 34 | private ?Uuid $id = null; 35 | 36 | #[ORM\Column(length: 255)] 37 | #[Groups(['fokontany:read'])] 38 | private ?string $name = null; 39 | 40 | #[ORM\ManyToOne(inversedBy: 'fokontanies')] 41 | #[Groups(['fokontany:read'])] 42 | private ?Commune $commune = null; 43 | 44 | #[ORM\ManyToOne(inversedBy: 'fokontanies')] 45 | #[Groups(['fokontany:read'])] 46 | private ?Region $region = null; 47 | 48 | #[ORM\ManyToOne(inversedBy: 'fokontanies')] 49 | #[Groups(['fokontany:read'])] 50 | private ?District $district = null; 51 | 52 | public function getId(): ?string 53 | { 54 | return $this->id; 55 | } 56 | 57 | public function getName(): ?string 58 | { 59 | return $this->name; 60 | } 61 | 62 | public function setName(string $name): static 63 | { 64 | $this->name = $name; 65 | 66 | return $this; 67 | } 68 | 69 | public function getCommune(): ?Commune 70 | { 71 | return $this->commune; 72 | } 73 | 74 | public function setCommune(?Commune $commune): static 75 | { 76 | $this->commune = $commune; 77 | 78 | return $this; 79 | } 80 | 81 | public function getRegion(): ?Region 82 | { 83 | return $this->region; 84 | } 85 | 86 | public function setRegion(?Region $region): static 87 | { 88 | $this->region = $region; 89 | 90 | return $this; 91 | } 92 | 93 | public function getDistrict(): ?District 94 | { 95 | return $this->district; 96 | } 97 | 98 | public function setDistrict(?District $district): static 99 | { 100 | $this->district = $district; 101 | 102 | return $this; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/Entity/Province.php: -------------------------------------------------------------------------------- 1 | ['province:read', 'code:read']], 26 | )] 27 | #[ApiFilter(SearchFilter::class, properties: ['name' => 'ipartial'])] 28 | #[ApiFilter(OrderFilter::class, properties: ['name'], arguments: ['orderParameterName' => 'order'])] 29 | class Province 30 | { 31 | #[ORM\Id] 32 | #[ORM\Column(type: UuidType::NAME, unique: true)] 33 | #[ORM\GeneratedValue(strategy: 'CUSTOM')] 34 | #[ORM\CustomIdGenerator(class: 'doctrine.uuid_generator')] 35 | #[Groups(['province:read'])] 36 | private ?Uuid $id = null; 37 | 38 | #[ORM\Column(length: 255)] 39 | #[Groups(['province:read', 'code:read'])] 40 | private ?string $name = null; 41 | 42 | #[ORM\OneToMany(mappedBy: 'province', targetEntity: CodePostale::class)] 43 | private Collection $codePostales; 44 | 45 | public function __construct() 46 | { 47 | $this->codePostales = new ArrayCollection(); 48 | } 49 | 50 | public function getId(): ?string 51 | { 52 | return $this->id; 53 | } 54 | 55 | public function getName(): ?string 56 | { 57 | return $this->name; 58 | } 59 | 60 | public function setName(string $name): static 61 | { 62 | $this->name = $name; 63 | 64 | return $this; 65 | } 66 | 67 | /** 68 | * @return Collection 69 | */ 70 | public function getCodePostales(): Collection 71 | { 72 | return $this->codePostales; 73 | } 74 | 75 | public function addCodePostale(CodePostale $codePostale): static 76 | { 77 | if (!$this->codePostales->contains($codePostale)) { 78 | $this->codePostales->add($codePostale); 79 | $codePostale->setProvince($this); 80 | } 81 | 82 | return $this; 83 | } 84 | 85 | public function removeCodePostale(CodePostale $codePostale): static 86 | { 87 | if ($this->codePostales->removeElement($codePostale)) { 88 | // set the owning side to null (unless already changed) 89 | if ($codePostale->getProvince() === $this) { 90 | $codePostale->setProvince(null); 91 | } 92 | } 93 | 94 | return $this; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/Entity/Region.php: -------------------------------------------------------------------------------- 1 | ['region:read', 'commune:read', 'district:read', 'fokontany:read', 'code:read']] 26 | )] 27 | #[ApiFilter(SearchFilter::class, properties: ['name' => 'ipartial'])] 28 | #[ApiFilter(OrderFilter::class, properties: ['name'], arguments: ['orderParameterName' => 'order'])] 29 | class Region 30 | { 31 | #[ORM\Id] 32 | #[ORM\Column(type: UuidType::NAME, unique: true)] 33 | #[ORM\GeneratedValue(strategy: 'CUSTOM')] 34 | #[ORM\CustomIdGenerator(class: 'doctrine.uuid_generator')] 35 | #[Groups(['region:read'])] 36 | private ?Uuid $id = null; 37 | 38 | #[ORM\Column(length: 255)] 39 | #[Groups(['region:read', 'commune:read', 'district:read', 'fokontany:read', 'code:read'])] 40 | private ?string $name = null; 41 | 42 | #[ORM\OneToMany(mappedBy: 'region', targetEntity: District::class)] 43 | private Collection $districts; 44 | 45 | #[ORM\OneToMany(mappedBy: 'region', targetEntity: Commune::class)] 46 | private Collection $communes; 47 | 48 | #[ORM\OneToMany(mappedBy: 'region', targetEntity: Fokontany::class)] 49 | private Collection $fokontanies; 50 | 51 | public function __construct() 52 | { 53 | $this->districts = new ArrayCollection(); 54 | $this->communes = new ArrayCollection(); 55 | $this->fokontanies = new ArrayCollection(); 56 | } 57 | 58 | public function getId(): ?string 59 | { 60 | return $this->id; 61 | } 62 | 63 | public function getName(): ?string 64 | { 65 | return $this->name; 66 | } 67 | 68 | public function setName(string $name): static 69 | { 70 | $this->name = $name; 71 | 72 | return $this; 73 | } 74 | 75 | /** 76 | * @return Collection 77 | */ 78 | public function getDistricts(): Collection 79 | { 80 | return $this->districts; 81 | } 82 | 83 | public function addDistrict(District $district): static 84 | { 85 | if (!$this->districts->contains($district)) { 86 | $this->districts->add($district); 87 | $district->setRegion($this); 88 | } 89 | 90 | return $this; 91 | } 92 | 93 | public function removeDistrict(District $district): static 94 | { 95 | if ($this->districts->removeElement($district)) { 96 | // set the owning side to null (unless already changed) 97 | if ($district->getRegion() === $this) { 98 | $district->setRegion(null); 99 | } 100 | } 101 | 102 | return $this; 103 | } 104 | 105 | /** 106 | * @return Collection 107 | */ 108 | public function getCommunes(): Collection 109 | { 110 | return $this->communes; 111 | } 112 | 113 | public function addCommune(Commune $commune): static 114 | { 115 | if (!$this->communes->contains($commune)) { 116 | $this->communes->add($commune); 117 | $commune->setRegion($this); 118 | } 119 | 120 | return $this; 121 | } 122 | 123 | public function removeCommune(Commune $commune): static 124 | { 125 | if ($this->communes->removeElement($commune)) { 126 | // set the owning side to null (unless already changed) 127 | if ($commune->getRegion() === $this) { 128 | $commune->setRegion(null); 129 | } 130 | } 131 | 132 | return $this; 133 | } 134 | 135 | /** 136 | * @return Collection 137 | */ 138 | public function getFokontanies(): Collection 139 | { 140 | return $this->fokontanies; 141 | } 142 | 143 | public function addFokontany(Fokontany $fokontany): static 144 | { 145 | if (!$this->fokontanies->contains($fokontany)) { 146 | $this->fokontanies->add($fokontany); 147 | $fokontany->setRegion($this); 148 | } 149 | 150 | return $this; 151 | } 152 | 153 | public function removeFokontany(Fokontany $fokontany): static 154 | { 155 | if ($this->fokontanies->removeElement($fokontany)) { 156 | // set the owning side to null (unless already changed) 157 | if ($fokontany->getRegion() === $this) { 158 | $fokontany->setRegion(null); 159 | } 160 | } 161 | 162 | return $this; 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /src/Kernel.php: -------------------------------------------------------------------------------- 1 | createProgressBar(); 34 | $payloadFile = $this->parameterBag->get('kernel.project_dir').'/in/mada_fokontany_payload.csv'; 35 | $ressource = fopen($payloadFile, 'r+'); 36 | 37 | $i = 0; 38 | while (false !== ($line = fgetcsv($ressource, 1000, "\t"))) { 39 | $progressBar->advance(); 40 | if ($i === 0) { 41 | $i++; 42 | continue; 43 | } 44 | 45 | $region = $this->entityManager->getRepository(Region::class)->findOneBy(['name' => $line[0]]); 46 | if (!$region) { 47 | $region = new Region(); 48 | $region->setName($line[0]); 49 | 50 | $this->entityManager->persist($region); 51 | $this->entityManager->flush(); 52 | } 53 | 54 | $district = $this->entityManager->getRepository(District::class)->findOneBy(['name' => $line[1], 'region' => $region]); 55 | if (!$district) { 56 | $district = new District(); 57 | $district->setName($line[1]); 58 | $district->setRegion($region); 59 | 60 | $this->entityManager->persist($district); 61 | $this->entityManager->flush(); 62 | } 63 | 64 | $commune = $this->entityManager->getRepository(Commune::class)->findOneBy(['name' => $line[2], 'district' => $district]); 65 | if (!$commune) { 66 | $commune = new Commune(); 67 | $commune->setName($line[2]); 68 | $commune->setDistrict($district); 69 | $commune->setRegion($region); 70 | 71 | $this->entityManager->persist($commune); 72 | $this->entityManager->flush(); 73 | } 74 | 75 | $fokontany = $this->entityManager->getRepository(Fokontany::class)->findOneBy(['name' => $line[3], 'commune' => $commune]); 76 | if (!$fokontany) { 77 | $fokontany = new Fokontany(); 78 | $fokontany->setCommune($commune); 79 | $fokontany->setRegion($region); 80 | $fokontany->setDistrict($district); 81 | $fokontany->setName($line[3]); 82 | 83 | $this->entityManager->persist($fokontany); 84 | $this->entityManager->flush(); 85 | } 86 | } 87 | 88 | $progressBar->finish(); 89 | } 90 | 91 | /** 92 | * @param SymfonyStyle $ioStyle 93 | * 94 | * @return void 95 | */ 96 | public function importProvince(SymfonyStyle $ioStyle): void 97 | { 98 | $payloadFile = $this->parameterBag->get('kernel.project_dir').'/in/json_province.json'; 99 | $data = json_decode(file_get_contents($payloadFile), true); 100 | 101 | $progressBar = $ioStyle->createProgressBar(count($data)); 102 | foreach ($data as $item) { 103 | $progressBar->advance(); 104 | $province = $this->entityManager->getRepository(Province::class)->findOneBy(['name' => $item['province']]) ?? new Province(); 105 | $province->setName($item['province']); 106 | 107 | $this->entityManager->persist($province); 108 | $this->entityManager->flush(); 109 | } 110 | } 111 | 112 | public function importCodePostale(SymfonyStyle $ioStyle) 113 | { 114 | $payloadFile = $this->parameterBag->get('kernel.project_dir').'/in/json_province.json'; 115 | $data = json_decode(file_get_contents($payloadFile), true); 116 | 117 | $progressBar = $ioStyle->createProgressBar(count($data)); 118 | foreach ($data as $item) { 119 | $progressBar->advance(); 120 | $province = $this->entityManager->getRepository(Province::class)->findOneBy(['name' => $item['province']]); 121 | $codePostale = $this->entityManager->getRepository(CodePostale::class)->findOneBy(['codePostal' => $item['zip'], 'province' => $province]) ?? new CodePostale(); 122 | 123 | $codePostale->setCodePostal($item['zip']); 124 | $codePostale->setProvince($province); 125 | $codePostale->setVille($item['ville']); 126 | if ('Antananarivo Nord' === $item['ville']) { 127 | $codePostale->setVille('Antananarivo Avaradrano'); 128 | } 129 | 130 | if ('Antananarivo Sud' === $item['ville']) { 131 | $codePostale->setVille('Antananarivo Atsimondrano'); 132 | } 133 | 134 | $this->entityManager->persist($codePostale); 135 | $this->entityManager->flush(); 136 | } 137 | } 138 | } -------------------------------------------------------------------------------- /src/Repository/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/julkwel/madagascar-map-api/82ce603cc410cb48acddb611cbc8faaa36024cb6/src/Repository/.gitignore -------------------------------------------------------------------------------- /src/Repository/CodePostaleRepository.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * @method CodePostale|null find($id, $lockMode = null, $lockVersion = null) 13 | * @method CodePostale|null findOneBy(array $criteria, array $orderBy = null) 14 | * @method CodePostale[] findAll() 15 | * @method CodePostale[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) 16 | */ 17 | class CodePostaleRepository extends ServiceEntityRepository 18 | { 19 | public function __construct(ManagerRegistry $registry) 20 | { 21 | parent::__construct($registry, CodePostale::class); 22 | } 23 | 24 | // /** 25 | // * @return CodePostale[] Returns an array of CodePostale objects 26 | // */ 27 | // public function findByExampleField($value): array 28 | // { 29 | // return $this->createQueryBuilder('c') 30 | // ->andWhere('c.exampleField = :val') 31 | // ->setParameter('val', $value) 32 | // ->orderBy('c.id', 'ASC') 33 | // ->setMaxResults(10) 34 | // ->getQuery() 35 | // ->getResult() 36 | // ; 37 | // } 38 | 39 | // public function findOneBySomeField($value): ?CodePostale 40 | // { 41 | // return $this->createQueryBuilder('c') 42 | // ->andWhere('c.exampleField = :val') 43 | // ->setParameter('val', $value) 44 | // ->getQuery() 45 | // ->getOneOrNullResult() 46 | // ; 47 | // } 48 | } 49 | -------------------------------------------------------------------------------- /src/Repository/CommuneRepository.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * @method Commune|null find($id, $lockMode = null, $lockVersion = null) 13 | * @method Commune|null findOneBy(array $criteria, array $orderBy = null) 14 | * @method Commune[] findAll() 15 | * @method Commune[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) 16 | */ 17 | class CommuneRepository extends ServiceEntityRepository 18 | { 19 | public function __construct(ManagerRegistry $registry) 20 | { 21 | parent::__construct($registry, Commune::class); 22 | } 23 | 24 | // /** 25 | // * @return Commune[] Returns an array of Commune objects 26 | // */ 27 | // public function findByExampleField($value): array 28 | // { 29 | // return $this->createQueryBuilder('c') 30 | // ->andWhere('c.exampleField = :val') 31 | // ->setParameter('val', $value) 32 | // ->orderBy('c.id', 'ASC') 33 | // ->setMaxResults(10) 34 | // ->getQuery() 35 | // ->getResult() 36 | // ; 37 | // } 38 | 39 | // public function findOneBySomeField($value): ?Commune 40 | // { 41 | // return $this->createQueryBuilder('c') 42 | // ->andWhere('c.exampleField = :val') 43 | // ->setParameter('val', $value) 44 | // ->getQuery() 45 | // ->getOneOrNullResult() 46 | // ; 47 | // } 48 | } 49 | -------------------------------------------------------------------------------- /src/Repository/DistrictRepository.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * @method District|null find($id, $lockMode = null, $lockVersion = null) 13 | * @method District|null findOneBy(array $criteria, array $orderBy = null) 14 | * @method District[] findAll() 15 | * @method District[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) 16 | */ 17 | class DistrictRepository extends ServiceEntityRepository 18 | { 19 | public function __construct(ManagerRegistry $registry) 20 | { 21 | parent::__construct($registry, District::class); 22 | } 23 | 24 | // /** 25 | // * @return District[] Returns an array of District objects 26 | // */ 27 | // public function findByExampleField($value): array 28 | // { 29 | // return $this->createQueryBuilder('d') 30 | // ->andWhere('d.exampleField = :val') 31 | // ->setParameter('val', $value) 32 | // ->orderBy('d.id', 'ASC') 33 | // ->setMaxResults(10) 34 | // ->getQuery() 35 | // ->getResult() 36 | // ; 37 | // } 38 | 39 | // public function findOneBySomeField($value): ?District 40 | // { 41 | // return $this->createQueryBuilder('d') 42 | // ->andWhere('d.exampleField = :val') 43 | // ->setParameter('val', $value) 44 | // ->getQuery() 45 | // ->getOneOrNullResult() 46 | // ; 47 | // } 48 | } 49 | -------------------------------------------------------------------------------- /src/Repository/FokontanyRepository.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * @method Fokontany|null find($id, $lockMode = null, $lockVersion = null) 13 | * @method Fokontany|null findOneBy(array $criteria, array $orderBy = null) 14 | * @method Fokontany[] findAll() 15 | * @method Fokontany[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) 16 | */ 17 | class FokontanyRepository extends ServiceEntityRepository 18 | { 19 | public function __construct(ManagerRegistry $registry) 20 | { 21 | parent::__construct($registry, Fokontany::class); 22 | } 23 | 24 | // /** 25 | // * @return Fokontany[] Returns an array of Fokontany objects 26 | // */ 27 | // public function findByExampleField($value): array 28 | // { 29 | // return $this->createQueryBuilder('f') 30 | // ->andWhere('f.exampleField = :val') 31 | // ->setParameter('val', $value) 32 | // ->orderBy('f.id', 'ASC') 33 | // ->setMaxResults(10) 34 | // ->getQuery() 35 | // ->getResult() 36 | // ; 37 | // } 38 | 39 | // public function findOneBySomeField($value): ?Fokontany 40 | // { 41 | // return $this->createQueryBuilder('f') 42 | // ->andWhere('f.exampleField = :val') 43 | // ->setParameter('val', $value) 44 | // ->getQuery() 45 | // ->getOneOrNullResult() 46 | // ; 47 | // } 48 | } 49 | -------------------------------------------------------------------------------- /src/Repository/ProvinceRepository.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * @method Province|null find($id, $lockMode = null, $lockVersion = null) 13 | * @method Province|null findOneBy(array $criteria, array $orderBy = null) 14 | * @method Province[] findAll() 15 | * @method Province[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) 16 | */ 17 | class ProvinceRepository extends ServiceEntityRepository 18 | { 19 | public function __construct(ManagerRegistry $registry) 20 | { 21 | parent::__construct($registry, Province::class); 22 | } 23 | 24 | // /** 25 | // * @return Province[] Returns an array of Province objects 26 | // */ 27 | // public function findByExampleField($value): array 28 | // { 29 | // return $this->createQueryBuilder('p') 30 | // ->andWhere('p.exampleField = :val') 31 | // ->setParameter('val', $value) 32 | // ->orderBy('p.id', 'ASC') 33 | // ->setMaxResults(10) 34 | // ->getQuery() 35 | // ->getResult() 36 | // ; 37 | // } 38 | 39 | // public function findOneBySomeField($value): ?Province 40 | // { 41 | // return $this->createQueryBuilder('p') 42 | // ->andWhere('p.exampleField = :val') 43 | // ->setParameter('val', $value) 44 | // ->getQuery() 45 | // ->getOneOrNullResult() 46 | // ; 47 | // } 48 | } 49 | -------------------------------------------------------------------------------- /src/Repository/RegionRepository.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * @method Region|null find($id, $lockMode = null, $lockVersion = null) 13 | * @method Region|null findOneBy(array $criteria, array $orderBy = null) 14 | * @method Region[] findAll() 15 | * @method Region[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) 16 | */ 17 | class RegionRepository extends ServiceEntityRepository 18 | { 19 | public function __construct(ManagerRegistry $registry) 20 | { 21 | parent::__construct($registry, Region::class); 22 | } 23 | 24 | // /** 25 | // * @return Region[] Returns an array of Region objects 26 | // */ 27 | // public function findByExampleField($value): array 28 | // { 29 | // return $this->createQueryBuilder('r') 30 | // ->andWhere('r.exampleField = :val') 31 | // ->setParameter('val', $value) 32 | // ->orderBy('r.id', 'ASC') 33 | // ->setMaxResults(10) 34 | // ->getQuery() 35 | // ->getResult() 36 | // ; 37 | // } 38 | 39 | // public function findOneBySomeField($value): ?Region 40 | // { 41 | // return $this->createQueryBuilder('r') 42 | // ->andWhere('r.exampleField = :val') 43 | // ->setParameter('val', $value) 44 | // ->getQuery() 45 | // ->getOneOrNullResult() 46 | // ; 47 | // } 48 | } 49 | -------------------------------------------------------------------------------- /symfony.lock: -------------------------------------------------------------------------------- 1 | { 2 | "api-platform/core": { 3 | "version": "3.2", 4 | "recipe": { 5 | "repo": "github.com/symfony/recipes", 6 | "branch": "main", 7 | "version": "3.2", 8 | "ref": "696d44adc3c0d4f5d25a2f1c4f3700dd8a5c6db9" 9 | }, 10 | "files": [ 11 | "config/packages/api_platform.yaml", 12 | "config/routes/api_platform.yaml", 13 | "src/ApiResource/.gitignore" 14 | ] 15 | }, 16 | "doctrine/doctrine-bundle": { 17 | "version": "2.11", 18 | "recipe": { 19 | "repo": "github.com/symfony/recipes", 20 | "branch": "main", 21 | "version": "2.10", 22 | "ref": "0b4a11ee7e60b36227502ed26874edd7e8b66353" 23 | }, 24 | "files": [ 25 | "config/packages/doctrine.yaml", 26 | "src/Entity/.gitignore", 27 | "src/Repository/.gitignore" 28 | ] 29 | }, 30 | "doctrine/doctrine-migrations-bundle": { 31 | "version": "3.3", 32 | "recipe": { 33 | "repo": "github.com/symfony/recipes", 34 | "branch": "main", 35 | "version": "3.1", 36 | "ref": "1d01ec03c6ecbd67c3375c5478c9a423ae5d6a33" 37 | }, 38 | "files": [ 39 | "config/packages/doctrine_migrations.yaml", 40 | "migrations/.gitignore" 41 | ] 42 | }, 43 | "nelmio/cors-bundle": { 44 | "version": "2.4", 45 | "recipe": { 46 | "repo": "github.com/symfony/recipes", 47 | "branch": "main", 48 | "version": "1.5", 49 | "ref": "6bea22e6c564fba3a1391615cada1437d0bde39c" 50 | }, 51 | "files": [ 52 | "config/packages/nelmio_cors.yaml" 53 | ] 54 | }, 55 | "phpunit/phpunit": { 56 | "version": "9.6", 57 | "recipe": { 58 | "repo": "github.com/symfony/recipes", 59 | "branch": "main", 60 | "version": "9.6", 61 | "ref": "7364a21d87e658eb363c5020c072ecfdc12e2326" 62 | }, 63 | "files": [ 64 | ".env.test", 65 | "phpunit.xml.dist", 66 | "tests/bootstrap.php" 67 | ] 68 | }, 69 | "symfony/console": { 70 | "version": "6.4", 71 | "recipe": { 72 | "repo": "github.com/symfony/recipes", 73 | "branch": "main", 74 | "version": "5.3", 75 | "ref": "da0c8be8157600ad34f10ff0c9cc91232522e047" 76 | }, 77 | "files": [ 78 | "bin/console" 79 | ] 80 | }, 81 | "symfony/flex": { 82 | "version": "2.4", 83 | "recipe": { 84 | "repo": "github.com/symfony/recipes", 85 | "branch": "main", 86 | "version": "1.0", 87 | "ref": "146251ae39e06a95be0fe3d13c807bcf3938b172" 88 | }, 89 | "files": [ 90 | ".env" 91 | ] 92 | }, 93 | "symfony/framework-bundle": { 94 | "version": "6.4", 95 | "recipe": { 96 | "repo": "github.com/symfony/recipes", 97 | "branch": "main", 98 | "version": "6.4", 99 | "ref": "a91c965766ad3ff2ae15981801643330eb42b6a5" 100 | }, 101 | "files": [ 102 | "config/packages/cache.yaml", 103 | "config/packages/framework.yaml", 104 | "config/preload.php", 105 | "config/routes/framework.yaml", 106 | "config/services.yaml", 107 | "public/index.php", 108 | "src/Controller/.gitignore", 109 | "src/Kernel.php" 110 | ] 111 | }, 112 | "symfony/maker-bundle": { 113 | "version": "1.52", 114 | "recipe": { 115 | "repo": "github.com/symfony/recipes", 116 | "branch": "main", 117 | "version": "1.0", 118 | "ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f" 119 | } 120 | }, 121 | "symfony/phpunit-bridge": { 122 | "version": "7.0", 123 | "recipe": { 124 | "repo": "github.com/symfony/recipes", 125 | "branch": "main", 126 | "version": "6.3", 127 | "ref": "1f5830c331065b6e4c9d5fa2105e322d29fcd573" 128 | }, 129 | "files": [ 130 | ".env.test", 131 | "bin/phpunit", 132 | "phpunit.xml.dist", 133 | "tests/bootstrap.php" 134 | ] 135 | }, 136 | "symfony/routing": { 137 | "version": "6.4", 138 | "recipe": { 139 | "repo": "github.com/symfony/recipes", 140 | "branch": "main", 141 | "version": "6.2", 142 | "ref": "e0a11b4ccb8c9e70b574ff5ad3dfdcd41dec5aa6" 143 | }, 144 | "files": [ 145 | "config/packages/routing.yaml", 146 | "config/routes.yaml" 147 | ] 148 | }, 149 | "symfony/security-bundle": { 150 | "version": "6.4", 151 | "recipe": { 152 | "repo": "github.com/symfony/recipes", 153 | "branch": "main", 154 | "version": "6.4", 155 | "ref": "2ae08430db28c8eb4476605894296c82a642028f" 156 | }, 157 | "files": [ 158 | "config/packages/security.yaml", 159 | "config/routes/security.yaml" 160 | ] 161 | }, 162 | "symfony/twig-bundle": { 163 | "version": "6.4", 164 | "recipe": { 165 | "repo": "github.com/symfony/recipes", 166 | "branch": "main", 167 | "version": "6.3", 168 | "ref": "b7772eb20e92f3fb4d4fe756e7505b4ba2ca1a2c" 169 | }, 170 | "files": [ 171 | "config/packages/twig.yaml", 172 | "templates/base.html.twig" 173 | ] 174 | }, 175 | "symfony/uid": { 176 | "version": "6.4", 177 | "recipe": { 178 | "repo": "github.com/symfony/recipes", 179 | "branch": "main", 180 | "version": "6.2", 181 | "ref": "d294ad4add3e15d7eb1bae0221588ca89b38e558" 182 | }, 183 | "files": [ 184 | "config/packages/uid.yaml" 185 | ] 186 | }, 187 | "symfony/validator": { 188 | "version": "6.4", 189 | "recipe": { 190 | "repo": "github.com/symfony/recipes", 191 | "branch": "main", 192 | "version": "5.3", 193 | "ref": "c32cfd98f714894c4f128bb99aa2530c1227603c" 194 | }, 195 | "files": [ 196 | "config/packages/validator.yaml" 197 | ] 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /templates/base.html.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {% block title %}Welcome!{% endblock %} 6 | 7 | {% block stylesheets %} 8 | {% endblock %} 9 | 10 | {% block javascripts %} 11 | {% endblock %} 12 | 13 | 14 | {% block body %}{% endblock %} 15 | 16 | 17 | -------------------------------------------------------------------------------- /templates/bundles/ApiPlatformBundle/SwaggerUi/index.html.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% block head_metas %} 5 | 6 | {% endblock %} 7 | 8 | {% block title %} 9 | Madagascar Localisation API 10 | {% endblock %} 11 | 12 | {% block stylesheet %} 13 | 14 | 15 | 16 | 17 | 18 | {% endblock %} 19 | 20 | {% set oauth_data = {'oauth': swagger_data.oauth|merge({'redirectUrl' : absolute_url(asset('bundles/apiplatform/swagger-ui/oauth2-redirect.html', assetPackage)) })} %} 21 | 22 | {% block head_javascript %} 23 | {# json_encode(65) is for JSON_UNESCAPED_SLASHES|JSON_HEX_TAG to avoid JS XSS #} 24 | 25 | {% endblock %} 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | {% block header %} 64 |
65 | 68 | 69 | Home page 70 | 71 |
72 | {% endblock %} 73 | 74 |
75 | 76 | {% block javascript %} 77 | 78 | 79 | 80 | 81 | {% endblock %} 82 | 83 | 84 | -------------------------------------------------------------------------------- /templates/homepage/index.html.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Mada localization 8 | 9 | 10 | 11 | 12 | 13 |
14 | 32 |
33 |
34 |
35 |
36 |
37 |

Madagascar MAP Project

38 |

The Madagascar Map initiative aims to provide comprehensive and accurate information about towns, 39 | cities, districts, and regions in Madagascar. 40 | The project involves adding code and SVG tiles for each city, with the ultimate goal of implementing a robust search query functionality.".

41 |
42 | Go to API 43 | 46 |
47 |
48 |
49 |
50 | Header illustration 51 | Header illustration 52 |
53 |
54 | Hero media illustration 55 | Hero media illustration 56 |
57 |
58 | Hero media 59 | Hero media 60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /tests/CommuneTest.php: -------------------------------------------------------------------------------- 1 | request( 20 | 'GET', 21 | '/api/communes', [ 22 | 'headers' => [ 23 | 'Content-Type' => 'application/ld+json', 24 | ], 25 | ]); 26 | 27 | $this->assertResponseStatusCodeSame(200); 28 | } 29 | } -------------------------------------------------------------------------------- /tests/DistrictTest.php: -------------------------------------------------------------------------------- 1 | request( 20 | 'GET', 21 | '/api/districts', [ 22 | 'headers' => [ 23 | 'Content-Type' => 'application/ld+json', 24 | ], 25 | ]); 26 | 27 | $this->assertResponseStatusCodeSame(200); 28 | } 29 | } -------------------------------------------------------------------------------- /tests/FokontanyTest.php: -------------------------------------------------------------------------------- 1 | request( 20 | 'GET', 21 | '/api/fokontanies', [ 22 | 'headers' => [ 23 | 'Content-Type' => 'application/ld+json', 24 | ], 25 | ]); 26 | 27 | $this->assertResponseStatusCodeSame(200); 28 | } 29 | } -------------------------------------------------------------------------------- /tests/RegionTest.php: -------------------------------------------------------------------------------- 1 | request( 20 | 'GET', 21 | '/api/regions', [ 22 | 'headers' => [ 23 | 'Content-Type' => 'application/ld+json', 24 | ], 25 | ]); 26 | 27 | $this->assertResponseStatusCodeSame(200); 28 | } 29 | } -------------------------------------------------------------------------------- /tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | bootEnv(dirname(__DIR__).'/.env'); 11 | } 12 | 13 | if ($_SERVER['APP_DEBUG']) { 14 | umask(0000); 15 | } 16 | --------------------------------------------------------------------------------