├── migrations ├── .gitignore ├── Version20200912213306.php └── Version20210110144329.php ├── src ├── Entity │ ├── .gitignore │ ├── Blog.php │ └── Category.php ├── Controller │ ├── .gitignore │ ├── Admin │ │ ├── DefaultController.php │ │ ├── CategoryController.php │ │ └── BlogController.php │ ├── CategoryController.php │ └── DefaultController.php ├── Repository │ ├── .gitignore │ ├── BlogRepository.php │ └── CategoryRepository.php ├── DataFixtures │ ├── BlogFixture.php │ └── CategoryFixtures.php ├── Form │ ├── CategoryType.php │ └── BlogType.php └── Kernel.php ├── translations └── .gitignore ├── docker ├── php │ ├── php.ini │ ├── Dockerfile │ └── www.conf └── nginx │ └── default.conf ├── config ├── packages │ ├── test │ │ ├── twig.yaml │ │ ├── validator.yaml │ │ ├── framework.yaml │ │ ├── web_profiler.yaml │ │ └── monolog.yaml │ ├── mailer.yaml │ ├── prod │ │ ├── routing.yaml │ │ ├── deprecations.yaml │ │ ├── monolog.yaml │ │ └── doctrine.yaml │ ├── sensio_framework_extra.yaml │ ├── twig.yaml │ ├── dev │ │ ├── web_profiler.yaml │ │ ├── debug.yaml │ │ └── monolog.yaml │ ├── translation.yaml │ ├── doctrine_migrations.yaml │ ├── routing.yaml │ ├── validator.yaml │ ├── notifier.yaml │ ├── framework.yaml │ ├── doctrine.yaml │ ├── cache.yaml │ └── security.yaml ├── routes.yaml ├── routes │ ├── dev │ │ ├── framework.yaml │ │ └── web_profiler.yaml │ └── annotations.yaml ├── bundles.php └── services.yaml ├── public ├── assets │ ├── css │ │ └── style.css │ └── bootstrap-4.5.2-dist │ │ ├── css │ │ ├── bootstrap-reboot.min.css │ │ ├── bootstrap-reboot.css │ │ ├── bootstrap-reboot.min.css.map │ │ └── bootstrap-grid.min.css │ │ └── js │ │ └── bootstrap.min.js └── index.php ├── .env.test ├── templates ├── admin │ ├── default │ │ └── index.html.twig │ ├── blog │ │ ├── create.html.twig │ │ └── index.html.twig │ ├── category │ │ ├── create.html.twig │ │ └── index.html.twig │ └── menu.html.twig ├── default │ ├── index.html.twig │ └── blog_detail.html.twig ├── macro │ └── blog.html.twig ├── category │ └── index.html.twig └── base.html.twig ├── tests └── bootstrap.php ├── .gitignore ├── bin ├── phpunit └── console ├── docker-compose.yml ├── docker-compose-mac.yml ├── phpunit.xml.dist ├── Makefile ├── .env ├── composer.json └── symfony.lock /migrations/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/Entity/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /translations/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/Controller/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/Repository/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docker/php/php.ini: -------------------------------------------------------------------------------- 1 | date.timezone="Europe/Istanbul" 2 | -------------------------------------------------------------------------------- /config/packages/test/twig.yaml: -------------------------------------------------------------------------------- 1 | twig: 2 | strict_variables: true 3 | -------------------------------------------------------------------------------- /public/assets/css/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 56px; 3 | } 4 | -------------------------------------------------------------------------------- /config/packages/mailer.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | mailer: 3 | dsn: '%env(MAILER_DSN)%' 4 | -------------------------------------------------------------------------------- /config/packages/prod/routing.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | router: 3 | strict_requirements: null 4 | -------------------------------------------------------------------------------- /config/routes.yaml: -------------------------------------------------------------------------------- 1 | #index: 2 | # path: / 3 | # controller: App\Controller\DefaultController::index 4 | -------------------------------------------------------------------------------- /config/packages/sensio_framework_extra.yaml: -------------------------------------------------------------------------------- 1 | sensio_framework_extra: 2 | router: 3 | annotations: false 4 | -------------------------------------------------------------------------------- /config/packages/test/validator.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | validation: 3 | not_compromised_password: false 4 | -------------------------------------------------------------------------------- /config/packages/test/framework.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | test: true 3 | session: 4 | storage_id: session.storage.mock_file 5 | -------------------------------------------------------------------------------- /config/routes/dev/framework.yaml: -------------------------------------------------------------------------------- 1 | _errors: 2 | resource: '@FrameworkBundle/Resources/config/routing/errors.xml' 3 | prefix: /_error 4 | -------------------------------------------------------------------------------- /docker/php/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM delirehberi/php7-symfony:7.4 2 | 3 | 4 | WORKDIR "/app" 5 | RUN usermod -u 1000 www-data 6 | 7 | CMD ["php-fpm"] 8 | 9 | -------------------------------------------------------------------------------- /config/packages/twig.yaml: -------------------------------------------------------------------------------- 1 | twig: 2 | default_path: '%kernel.project_dir%/templates' 3 | form_themes: ['bootstrap_4_horizontal_layout.html.twig'] 4 | -------------------------------------------------------------------------------- /config/packages/test/web_profiler.yaml: -------------------------------------------------------------------------------- 1 | web_profiler: 2 | toolbar: false 3 | intercept_redirects: false 4 | 5 | framework: 6 | profiler: { collect: false } 7 | -------------------------------------------------------------------------------- /config/packages/dev/web_profiler.yaml: -------------------------------------------------------------------------------- 1 | web_profiler: 2 | toolbar: true 3 | intercept_redirects: false 4 | 5 | framework: 6 | profiler: { only_exceptions: false } 7 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /config/routes/annotations.yaml: -------------------------------------------------------------------------------- 1 | controllers: 2 | resource: ../../src/Controller/ 3 | type: annotation 4 | 5 | kernel: 6 | resource: ../../src/Kernel.php 7 | type: annotation 8 | -------------------------------------------------------------------------------- /config/packages/translation.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | default_locale: en 3 | translator: 4 | default_path: '%kernel.project_dir%/translations' 5 | fallbacks: 6 | - en 7 | -------------------------------------------------------------------------------- /templates/admin/default/index.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'base.html.twig' %} 2 | 3 | {% block title %}Yönetim Sayfası{% endblock %} 4 | 5 | {% block body %} 6 | {% include 'admin/menu.html.twig'%} 7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /docker/php/www.conf: -------------------------------------------------------------------------------- 1 | [www] 2 | 3 | user = www-data 4 | group = www-data 5 | 6 | listen = nginx:9000 7 | 8 | pm = dynamic 9 | pm.max_children = 5 10 | pm.start_servers = 2 11 | pm.min_spare_servers = 1 12 | pm.max_spare_servers = 3 13 | -------------------------------------------------------------------------------- /templates/admin/blog/create.html.twig: -------------------------------------------------------------------------------- 1 | 2 | {% extends 'base.html.twig' %} 3 | 4 | {% block title %}Yeni İçerik Ekle{% endblock %} 5 | 6 | {% block body %} 7 | {%include 'admin/menu.html.twig'%} 8 |
9 | {{form(form)}} 10 | {% endblock %} 11 | -------------------------------------------------------------------------------- /config/packages/dev/debug.yaml: -------------------------------------------------------------------------------- 1 | debug: 2 | # Forwards VarDumper Data clones to a centralized server allowing to inspect dumps on CLI or in your browser. 3 | # See the "server:dump" command to start a new server. 4 | dump_destination: "tcp://%env(VAR_DUMPER_SERVER)%" 5 | -------------------------------------------------------------------------------- /templates/admin/category/create.html.twig: -------------------------------------------------------------------------------- 1 | 2 | {% extends 'base.html.twig' %} 3 | 4 | {% block title %}Yeni Kategori Ekle{% endblock %} 5 | 6 | {% block body %} 7 | {%include 'admin/menu.html.twig'%} 8 |
9 | {{form(form)}} 10 | {% endblock %} 11 | -------------------------------------------------------------------------------- /config/routes/dev/web_profiler.yaml: -------------------------------------------------------------------------------- 1 | web_profiler_wdt: 2 | resource: '@WebProfilerBundle/Resources/config/routing/wdt.xml' 3 | prefix: /_wdt 4 | 5 | web_profiler_profiler: 6 | resource: '@WebProfilerBundle/Resources/config/routing/profiler.xml' 7 | prefix: /_profiler 8 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /config/packages/prod/deprecations.yaml: -------------------------------------------------------------------------------- 1 | # As of Symfony 5.1, deprecations are logged in the dedicated "deprecation" channel when it exists 2 | #monolog: 3 | # channels: [deprecation] 4 | # handlers: 5 | # deprecation: 6 | # type: stream 7 | # channels: [deprecation] 8 | # path: "%kernel.logs_dir%/%kernel.environment%.deprecations.log" 9 | -------------------------------------------------------------------------------- /tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | bootEnv(dirname(__DIR__).'/.env'); 11 | } 12 | -------------------------------------------------------------------------------- /.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 | /src/.preload.php 9 | /var/ 10 | /vendor/ 11 | ###< symfony/framework-bundle ### 12 | 13 | ###> symfony/phpunit-bridge ### 14 | .phpunit 15 | .phpunit.result.cache 16 | /phpunit.xml 17 | ###< symfony/phpunit-bridge ### 18 | 19 | .idea 20 | -------------------------------------------------------------------------------- /config/packages/test/monolog.yaml: -------------------------------------------------------------------------------- 1 | monolog: 2 | handlers: 3 | main: 4 | type: fingers_crossed 5 | action_level: error 6 | handler: nested 7 | excluded_http_codes: [404, 405] 8 | channels: ["!event"] 9 | nested: 10 | type: stream 11 | path: "%kernel.logs_dir%/%kernel.environment%.log" 12 | level: debug 13 | -------------------------------------------------------------------------------- /templates/default/index.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'base.html.twig' %} 2 | {% import "macro/blog.html.twig" as blog_macro %} 3 | 4 | {% block title %}Emre.xyz{% endblock %} 5 | 6 | {% block body %} 7 |
8 |

Son Yazılar 9 | en son yazılar 10 |

11 | {% for item in items %} 12 | {{blog_macro.item(item)}} 13 | {% endfor %} 14 | 15 |
16 | {% endblock %} 17 | -------------------------------------------------------------------------------- /templates/default/blog_detail.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'base.html.twig' %} 2 | 3 | {% block title %}Emre.xyz{% endblock %} 4 | 5 | {% block body %} 6 |
7 | 8 |

{{item.title}}

9 | 10 |
11 | 12 | 13 |

Tarih: {{item.createdAt|date}}

14 | 15 |
16 | 17 | 18 | {{item.content|raw}} 19 |
20 |
21 | {% endblock %} 22 | -------------------------------------------------------------------------------- /bin/phpunit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | render('admin/default/index.html.twig', []); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Controller/CategoryController.php: -------------------------------------------------------------------------------- 1 | render('category/index.html.twig', [ 16 | 'controller_name' => 'CategoryController', 17 | ]); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /templates/macro/blog.html.twig: -------------------------------------------------------------------------------- 1 | {% macro item(post)%} 2 |
3 |
4 |

{{post.title}}

5 |

{{post.content[:200]}}

6 | Devamını oku→ 7 |
8 | 15 |
16 | {%endmacro%} 17 | -------------------------------------------------------------------------------- /config/packages/notifier.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | notifier: 3 | #chatter_transports: 4 | # slack: '%env(SLACK_DSN)%' 5 | # telegram: '%env(TELEGRAM_DSN)%' 6 | #texter_transports: 7 | # twilio: '%env(TWILIO_DSN)%' 8 | # nexmo: '%env(NEXMO_DSN)%' 9 | channel_policy: 10 | # use chat/slack, chat/telegram, sms/twilio or sms/nexmo 11 | urgent: ['email'] 12 | high: ['email'] 13 | medium: ['email'] 14 | low: ['email'] 15 | admin_recipients: 16 | - { email: admin@example.com } 17 | -------------------------------------------------------------------------------- /config/packages/prod/monolog.yaml: -------------------------------------------------------------------------------- 1 | monolog: 2 | handlers: 3 | main: 4 | type: fingers_crossed 5 | action_level: error 6 | handler: nested 7 | excluded_http_codes: [404, 405] 8 | buffer_size: 50 # How many messages should be saved? Prevent memory leaks 9 | nested: 10 | type: stream 11 | path: "%kernel.logs_dir%/%kernel.environment%.log" 12 | level: debug 13 | console: 14 | type: console 15 | process_psr_3_messages: false 16 | channels: ["!event", "!doctrine"] 17 | -------------------------------------------------------------------------------- /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 | #http_method_override: true 6 | 7 | # Enables session support. Note that the session will ONLY be started if you read or write from it. 8 | # Remove or comment this section to explicitly disable session support. 9 | session: 10 | handler_id: null 11 | cookie_secure: auto 12 | cookie_samesite: lax 13 | 14 | #esi: true 15 | #fragments: true 16 | php_errors: 17 | log: true 18 | -------------------------------------------------------------------------------- /templates/admin/menu.html.twig: -------------------------------------------------------------------------------- 1 | 9 | {% for label, messages in app.flashes %} 10 | {% for message in messages %} 11 |
12 | {{message}} 13 |
14 | {% endfor %} 15 | {% endfor %} 16 | 17 | -------------------------------------------------------------------------------- /src/DataFixtures/BlogFixture.php: -------------------------------------------------------------------------------- 1 | setTitle("Hello world!") 15 | ->setSlug("hello-world") 16 | ->setContent("Demo content!") 17 | ->setCreatedAt(new \DateTime()); 18 | $manager->persist($blog_item); 19 | 20 | $manager->flush(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /config/packages/prod/doctrine.yaml: -------------------------------------------------------------------------------- 1 | doctrine: 2 | orm: 3 | auto_generate_proxy_classes: false 4 | metadata_cache_driver: 5 | type: pool 6 | pool: doctrine.system_cache_pool 7 | query_cache_driver: 8 | type: pool 9 | pool: doctrine.system_cache_pool 10 | result_cache_driver: 11 | type: pool 12 | pool: doctrine.result_cache_pool 13 | 14 | framework: 15 | cache: 16 | pools: 17 | doctrine.result_cache_pool: 18 | adapter: cache.app 19 | doctrine.system_cache_pool: 20 | adapter: cache.system 21 | -------------------------------------------------------------------------------- /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: '5.7' 8 | orm: 9 | auto_generate_proxy_classes: true 10 | naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware 11 | auto_mapping: true 12 | mappings: 13 | App: 14 | is_bundle: false 15 | type: annotation 16 | dir: '%kernel.project_dir%/src/Entity' 17 | prefix: 'App\Entity' 18 | alias: App 19 | -------------------------------------------------------------------------------- /config/packages/dev/monolog.yaml: -------------------------------------------------------------------------------- 1 | monolog: 2 | handlers: 3 | main: 4 | type: stream 5 | path: "%kernel.logs_dir%/%kernel.environment%.log" 6 | level: debug 7 | channels: ["!event"] 8 | # uncomment to get logging in your browser 9 | # you may have to allow bigger header sizes in your Web server configuration 10 | #firephp: 11 | # type: firephp 12 | # level: info 13 | #chromephp: 14 | # type: chromephp 15 | # level: info 16 | console: 17 | type: console 18 | process_psr_3_messages: false 19 | channels: ["!event", "!doctrine", "!console"] 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 | -------------------------------------------------------------------------------- /src/Form/CategoryType.php: -------------------------------------------------------------------------------- 1 | add('name') 17 | ->add('parent') 18 | ->add('submit',SubmitType::class) 19 | ; 20 | } 21 | 22 | public function configureOptions(OptionsResolver $resolver) 23 | { 24 | $resolver->setDefaults([ 25 | 'data_class' => Category::class, 26 | ]); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /templates/category/index.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'base.html.twig' %} 2 | 3 | {% block title %}Hello CategoryController!{% endblock %} 4 | 5 | {% block body %} 6 | 10 | 11 |
12 |

Hello {{ controller_name }}! ✅

13 | 14 | This friendly message is coming from: 15 | 19 |
20 | {% endblock %} 21 | -------------------------------------------------------------------------------- /docker/nginx/default.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen *:80; 3 | server_name app.dev; 4 | root /app/public; 5 | access_log /var/log/nginx/app.dev.access.log; 6 | error_log /var/log/nginx/app.dev.error.log; 7 | client_max_body_size 1024M; 8 | rewrite ^/index.php?(.*)$ /$1 permanent; 9 | try_files $uri @rewriteapp; 10 | location @rewriteapp { 11 | rewrite ^(.*)$ /index.php/$1 last; 12 | } 13 | location ~ ^/(index)\.php(/|$) { 14 | fastcgi_pass php:9000; 15 | fastcgi_buffer_size 256k; 16 | fastcgi_buffers 256 16k; 17 | fastcgi_busy_buffers_size 256k; 18 | fastcgi_temp_file_write_size 256k; 19 | fastcgi_split_path_info ^(.+\.php)(/.*)$; 20 | include fastcgi_params; 21 | fastcgi_param SCRIPT_FILENAME /app/public$fastcgi_script_name; 22 | fastcgi_param HTTPS off; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | php: 4 | build: 5 | context: ./docker/php 6 | ports: 7 | - 9000:9000 8 | volumes: 9 | - ./:/app 10 | - ./docker/php/php.ini:/usr/local/etc/php/conf.d/override.ini 11 | - ./docker/php/www.conf:/usr/local/etc/php-fpm.d/www.conf 12 | nginx: 13 | image: nginx:1.16.1 14 | ports: 15 | - 80:80 16 | volumes: 17 | - ./:/app 18 | - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf 19 | depends_on: 20 | - php 21 | postgres: 22 | image: postgres:12 23 | ports: 24 | - 5432:5432 25 | volumes: 26 | - ./:/app 27 | environment: 28 | POSTGRES_DB: youtube_blog 29 | POSTGRES_USER: youtube_user 30 | POSTGRES_PASSWORD: youtube_password 31 | -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | bootEnv(dirname(__DIR__).'/.env'); 11 | 12 | if ($_SERVER['APP_DEBUG']) { 13 | umask(0000); 14 | 15 | Debug::enable(); 16 | } 17 | 18 | if ($trustedProxies = $_SERVER['TRUSTED_PROXIES'] ?? false) { 19 | Request::setTrustedProxies(explode(',', $trustedProxies), Request::HEADER_X_FORWARDED_ALL ^ Request::HEADER_X_FORWARDED_HOST); 20 | } 21 | 22 | if ($trustedHosts = $_SERVER['TRUSTED_HOSTS'] ?? false) { 23 | Request::setTrustedHosts([$trustedHosts]); 24 | } 25 | 26 | $kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']); 27 | $request = Request::createFromGlobals(); 28 | $response = $kernel->handle($request); 29 | $response->send(); 30 | $kernel->terminate($request, $response); 31 | -------------------------------------------------------------------------------- /src/DataFixtures/CategoryFixtures.php: -------------------------------------------------------------------------------- 1 | setName('Türkçe İçerikler') 16 | ->setSlug('turkce-icerikler'); 17 | $manager->persist($mainCategory); 18 | 19 | $category = new Category(); 20 | $category->setName('Gündem') 21 | ->setSlug('gundem') 22 | ->setParent($mainCategory); 23 | $manager->persist($category); 24 | 25 | $category2 = new Category(); 26 | $category2->setName("Demo") 27 | ->setSlug("demo"); 28 | $manager->persist($category2); 29 | $manager->flush(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /config/packages/security.yaml: -------------------------------------------------------------------------------- 1 | security: 2 | # https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers 3 | providers: 4 | users_in_memory: { memory: null } 5 | firewalls: 6 | dev: 7 | pattern: ^/(_(profiler|wdt)|css|images|js)/ 8 | security: false 9 | main: 10 | anonymous: true 11 | lazy: true 12 | provider: users_in_memory 13 | 14 | # activate different ways to authenticate 15 | # https://symfony.com/doc/current/security.html#firewalls-authentication 16 | 17 | # https://symfony.com/doc/current/security/impersonating_user.html 18 | # switch_user: true 19 | 20 | # Easy way to control access for large sections of your site 21 | # Note: Only the *first* access control that matches will be used 22 | access_control: 23 | # - { path: ^/admin, roles: ROLE_ADMIN } 24 | # - { path: ^/profile, roles: ROLE_USER } 25 | -------------------------------------------------------------------------------- /config/bundles.php: -------------------------------------------------------------------------------- 1 | ['all' => true], 5 | Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], 6 | Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true], 7 | Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true], 8 | Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], 9 | Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], 10 | Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], 11 | Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true], 12 | Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true], 13 | Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true, 'test' => true], 14 | Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], 15 | Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true], 16 | ]; 17 | -------------------------------------------------------------------------------- /templates/admin/category/index.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'base.html.twig' %} 2 | 3 | {% block title %}Tüm Kategoriler{% endblock %} 4 | 5 | {% block body %} 6 | {%include 'admin/menu.html.twig'%} 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | {% for item in items %} 18 | 19 | 20 | 21 | 22 | 26 | 27 | {% endfor %} 28 | 29 |
IDİsimYolİşlemler
{{item.id}}{{item.name}}{%if item.parent%}{{item.parent.path}}{%endif%} 23 | Düzenle 24 | Sil 25 |
30 | {% endblock %} 31 | -------------------------------------------------------------------------------- /templates/admin/blog/index.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'base.html.twig' %} 2 | 3 | {% block title %}Tüm İçerikler{% endblock %} 4 | 5 | {% block body %} 6 | {%include 'admin/menu.html.twig'%} 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | {% for item in items %} 19 | 20 | 21 | 22 | 23 | 24 | 28 | 29 | {% endfor %} 30 | 31 |
IDBaşlıkKategoriTarihİşlemler
{{item.id}}{{item.title}}{%if item.category%}{{item.category.path}}{%endif%}{{item.createdAt|date}} 25 | Düzenle 26 | Sil 27 |
32 | {% endblock %} 33 | -------------------------------------------------------------------------------- /docker-compose-mac.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | php: 4 | build: 5 | context: ./docker/php 6 | ports: 7 | - 9000:9000 8 | volumes: 9 | - nfsmount:/app:delegated 10 | - ./docker/php/php.ini:/usr/local/etc/php/conf.d/override.ini 11 | - ./docker/php/www.conf:/usr/local/etc/php-fpm.d/www.conf 12 | nginx: 13 | image: nginx:1.16.1 14 | ports: 15 | - 80:80 16 | volumes: 17 | - nfsmount:/app:delegated 18 | - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf 19 | depends_on: 20 | - php 21 | postgres: 22 | image: postgres:12 23 | ports: 24 | - 5432:5432 25 | volumes: 26 | - ./:/app 27 | environment: 28 | POSTGRES_DB: youtube_blog 29 | POSTGRES_USER: youtube_user 30 | POSTGRES_PASSWORD: youtube_password 31 | volumes: 32 | nfsmount: 33 | driver: local 34 | driver_opts: 35 | type: nfs 36 | o: addr=host.docker.internal,rw,nolock,hard,nointr,nfsvers=3 37 | device: ":${PWD}" 38 | 39 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | tests 21 | 22 | 23 | 24 | 25 | 26 | src 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /migrations/Version20200912213306.php: -------------------------------------------------------------------------------- 1 | addSql('CREATE SEQUENCE blog_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); 24 | $this->addSql('CREATE TABLE blog (id INT NOT NULL, title VARCHAR(255) NOT NULL, slug VARCHAR(255) NOT NULL, content TEXT DEFAULT NULL, created_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, PRIMARY KEY(id))'); 25 | } 26 | 27 | public function down(Schema $schema) : void 28 | { 29 | // this down() migration is auto-generated, please modify it to your needs 30 | $this->addSql('CREATE SCHEMA public'); 31 | $this->addSql('DROP SEQUENCE blog_id_seq CASCADE'); 32 | $this->addSql('DROP TABLE blog'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Controller/DefaultController.php: -------------------------------------------------------------------------------- 1 | getDoctrine()->getManager(); 18 | $repository = $em->getRepository(Blog::class); 19 | 20 | $items = $repository->findAll(); 21 | return $this->render('default/index.html.twig', [ 22 | 'items'=>$items 23 | ]); 24 | } 25 | 26 | /** 27 | * @Route("/{slug}",name="blog_detail") 28 | */ 29 | public function detail($slug){ 30 | $em = $this->getDoctrine()->getManager(); 31 | $repository = $em->getRepository(Blog::class); 32 | $item = $repository->findOneBy(['slug'=>$slug]); 33 | if(!$item) { 34 | throw new NotFoundHttpException(); 35 | } 36 | 37 | return $this->render('default/blog_detail.html.twig',[ 38 | 'item'=>$item, 39 | ]); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | getParameterOption(['--env', '-e'], null, true)) { 24 | putenv('APP_ENV='.$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = $env); 25 | } 26 | 27 | if ($input->hasParameterOption('--no-debug', true)) { 28 | putenv('APP_DEBUG='.$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = '0'); 29 | } 30 | 31 | (new Dotenv())->bootEnv(dirname(__DIR__).'/.env'); 32 | 33 | if ($_SERVER['APP_DEBUG']) { 34 | umask(0000); 35 | 36 | if (class_exists(Debug::class)) { 37 | Debug::enable(); 38 | } 39 | } 40 | 41 | $kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']); 42 | $application = new Application($kernel); 43 | $application->run($input); 44 | -------------------------------------------------------------------------------- /config/services.yaml: -------------------------------------------------------------------------------- 1 | # This file is the entry point to configure your own services. 2 | # Files in the packages/ subdirectory configure your dependencies. 3 | 4 | # Put parameters here that don't need to change on each machine where the app is deployed 5 | # https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration 6 | parameters: 7 | 8 | services: 9 | # default configuration for services in *this* file 10 | _defaults: 11 | autowire: true # Automatically injects dependencies in your services. 12 | autoconfigure: true # Automatically registers your services as commands, event subscribers, etc. 13 | 14 | # makes classes in src/ available to be used as services 15 | # this creates a service per class whose id is the fully-qualified class name 16 | App\: 17 | resource: '../src/' 18 | exclude: 19 | - '../src/DependencyInjection/' 20 | - '../src/Entity/' 21 | - '../src/Kernel.php' 22 | - '../src/Tests/' 23 | 24 | # controllers are imported separately to make sure services can be injected 25 | # as action arguments even if you don't extend any base controller class 26 | App\Controller\: 27 | resource: '../src/Controller/' 28 | tags: ['controller.service_arguments'] 29 | 30 | # add more service definitions when explicit configuration is needed 31 | # please note that last definitions always *replace* previous ones 32 | -------------------------------------------------------------------------------- /src/Form/BlogType.php: -------------------------------------------------------------------------------- 1 | add('title',TextType::class,[ 21 | 'label'=>'Başlık' 22 | ]) 23 | ->add('content',TextareaType::class,[ 24 | 'required'=>false, 25 | 'attr'=>[ 26 | 'data-emre'=>'here' 27 | ] 28 | ]) 29 | ->add('category',EntityType::class,[ 30 | 'label'=>'Kategori', 31 | 'required'=>false, 32 | 'class'=>Category::class 33 | ]) 34 | ->add('submit',SubmitType::class,[]) 35 | ; 36 | } 37 | 38 | public function configureOptions(OptionsResolver $resolver) 39 | { 40 | $resolver->setDefaults([ 41 | 'data_class' => Blog::class, 42 | 'attr'=>['novalidate'=>'novalidate'] 43 | ]); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Repository/BlogRepository.php: -------------------------------------------------------------------------------- 1 | createQueryBuilder('b') 29 | ->andWhere('b.exampleField = :val') 30 | ->setParameter('val', $value) 31 | ->orderBy('b.id', 'ASC') 32 | ->setMaxResults(10) 33 | ->getQuery() 34 | ->getResult() 35 | ; 36 | } 37 | */ 38 | 39 | /* 40 | public function findOneBySomeField($value): ?Blog 41 | { 42 | return $this->createQueryBuilder('b') 43 | ->andWhere('b.exampleField = :val') 44 | ->setParameter('val', $value) 45 | ->getQuery() 46 | ->getOneOrNullResult() 47 | ; 48 | } 49 | */ 50 | } 51 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PROJECT_NAME := 'Youtube Blog' 2 | UNAME_S := $(shell uname -s) 3 | ifeq ($(UNAME_S),Linux) 4 | DOCKER_COMPOSE_FILE := $(shell pwd)/docker-compose.yml 5 | endif 6 | ifeq ($(UNAME_S),Darwin) 7 | DOCKER_COMPOSE_FILE := $(shell pwd)/docker-compose-mac.yml 8 | endif 9 | 10 | ACTIVE_BRANCH := $(shell (git branch |grep '*'|tr -d '*'|tr -d ' ')) 11 | DATABASE_SERVICE := 'postgres' 12 | DATABASE_NAME := 'youtube_blog' 13 | WEB_SERVICE := 'nginx' 14 | PHP_SERVICE := 'php' 15 | 16 | start: 17 | docker-compose -f $(DOCKER_COMPOSE_FILE) up -d 18 | stop: 19 | docker-compose -f $(DOCKER_COMPOSE_FILE) stop 20 | 21 | rebuild: 22 | docker-compose -f $(DOCKER_COMPOSE_FILE) build $(PHP_SERVICE) 23 | 24 | install: 25 | docker-compose -f $(DOCKER_COMPOSE_FILE) run --rm $(PHP_SERVICE) composer install -d /app 26 | 27 | shell: 28 | docker-compose -f $(DOCKER_COMPOSE_FILE) exec $(PHP_SERVICE) bash 29 | 30 | db: 31 | docker-compose -f $(DOCKER_COMPOSE_FILE) exec $(DATABASE_SERVICE) bash 32 | db-remove: 33 | docker-compose -f $(DOCKER_COMPOSE_FILE) run --rm $(PHP_SERVICE) /app/bin/console doctrine:database:drop --force 34 | 35 | db-create: 36 | docker-compose -f $(DOCKER_COMPOSE_FILE) run --rm $(PHP_SERVICE) /app/bin/console doctrine:database:create 37 | 38 | db-reset: db-remove db-create migrate load-fixtures 39 | 40 | migrate: 41 | docker-compose -f $(DOCKER_COMPOSE_FILE) run --rm $(PHP_SERVICE) /app/bin/console doctrine:migration:migrate -n 42 | 43 | load-fixtures: 44 | docker-compose -f $(DOCKER_COMPOSE_FILE) run --rm $(PHP_SERVICE) /app/bin/console doctrine:fixtures:load -n 45 | -------------------------------------------------------------------------------- /src/Kernel.php: -------------------------------------------------------------------------------- 1 | import('../config/{packages}/*.yaml'); 17 | $container->import('../config/{packages}/'.$this->environment.'/*.yaml'); 18 | 19 | if (is_file(\dirname(__DIR__).'/config/services.yaml')) { 20 | $container->import('../config/{services}.yaml'); 21 | $container->import('../config/{services}_'.$this->environment.'.yaml'); 22 | } elseif (is_file($path = \dirname(__DIR__).'/config/services.php')) { 23 | (require $path)($container->withPath($path), $this); 24 | } 25 | } 26 | 27 | protected function configureRoutes(RoutingConfigurator $routes): void 28 | { 29 | $routes->import('../config/{routes}/'.$this->environment.'/*.yaml'); 30 | $routes->import('../config/{routes}/*.yaml'); 31 | 32 | if (is_file(\dirname(__DIR__).'/config/routes.yaml')) { 33 | $routes->import('../config/{routes}.yaml'); 34 | } elseif (is_file($path = \dirname(__DIR__).'/config/routes.php')) { 35 | (require $path)($routes->withPath($path), $this); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Repository/CategoryRepository.php: -------------------------------------------------------------------------------- 1 | createQueryBuilder('c') 29 | ->andWhere('c.exampleField = :val') 30 | ->setParameter('val', $value) 31 | ->orderBy('c.id', 'ASC') 32 | ->setMaxResults(10) 33 | ->getQuery() 34 | ->getResult() 35 | ; 36 | } 37 | */ 38 | 39 | /* 40 | public function findOneBySomeField($value): ?Category 41 | { 42 | return $this->createQueryBuilder('c') 43 | ->andWhere('c.exampleField = :val') 44 | ->setParameter('val', $value) 45 | ->getQuery() 46 | ->getOneOrNullResult() 47 | ; 48 | } 49 | */ 50 | } 51 | -------------------------------------------------------------------------------- /.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 | # 13 | # Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2). 14 | # https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration 15 | 16 | ###> symfony/framework-bundle ### 17 | APP_ENV=dev 18 | APP_SECRET=bd64e8c392c42177f0382ffe69a1bc63 19 | #TRUSTED_PROXIES=127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 20 | #TRUSTED_HOSTS='^(localhost|example\.com)$' 21 | ###< symfony/framework-bundle ### 22 | 23 | ###> symfony/mailer ### 24 | # MAILER_DSN=smtp://localhost 25 | ###< symfony/mailer ### 26 | 27 | ###> doctrine/doctrine-bundle ### 28 | # Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url 29 | # For an SQLite database, use: "sqlite:///%kernel.project_dir%/var/data.db" 30 | # For a PostgreSQL database, use: "postgresql://db_user:db_password@127.0.0.1:5432/db_name?serverVersion=11&charset=utf8" 31 | # IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml 32 | DATABASE_URL=postgresql://youtube_user:youtube_password@postgres:5432/youtube_blog?serverVersion=12&charset=utf8 33 | ###< doctrine/doctrine-bundle ### 34 | -------------------------------------------------------------------------------- /migrations/Version20210110144329.php: -------------------------------------------------------------------------------- 1 | addSql('CREATE SEQUENCE category_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); 24 | $this->addSql('CREATE TABLE category (id INT NOT NULL, parent_id INT DEFAULT NULL, name VARCHAR(255) NOT NULL, slug VARCHAR(255) NOT NULL, PRIMARY KEY(id))'); 25 | $this->addSql('CREATE INDEX IDX_64C19C1727ACA70 ON category (parent_id)'); 26 | $this->addSql('ALTER TABLE category ADD CONSTRAINT FK_64C19C1727ACA70 FOREIGN KEY (parent_id) REFERENCES category (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); 27 | $this->addSql('ALTER TABLE blog ADD category_id INT DEFAULT NULL'); 28 | $this->addSql('ALTER TABLE blog ADD CONSTRAINT FK_C015514312469DE2 FOREIGN KEY (category_id) REFERENCES category (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); 29 | $this->addSql('CREATE INDEX IDX_C015514312469DE2 ON blog (category_id)'); 30 | } 31 | 32 | public function down(Schema $schema) : void 33 | { 34 | // this down() migration is auto-generated, please modify it to your needs 35 | $this->addSql('CREATE SCHEMA public'); 36 | $this->addSql('ALTER TABLE blog DROP CONSTRAINT FK_C015514312469DE2'); 37 | $this->addSql('ALTER TABLE category DROP CONSTRAINT FK_64C19C1727ACA70'); 38 | $this->addSql('DROP SEQUENCE category_id_seq CASCADE'); 39 | $this->addSql('DROP TABLE category'); 40 | $this->addSql('DROP INDEX IDX_C015514312469DE2'); 41 | $this->addSql('ALTER TABLE blog DROP category_id'); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /templates/base.html.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {% block title %}Welcome!{% endblock %} 6 | 7 | 8 | {% block stylesheets %}{% endblock %} 9 | 10 | 11 | 12 | 29 |
30 |
31 | {% block body %}{% endblock %} 32 |
33 |
34 | 35 |
36 |
37 |

Copyright © Emre YILMAZ 2020

38 |
39 | 40 |
41 | 42 | {% block javascripts %}{% endblock %} 43 | 44 | 45 | -------------------------------------------------------------------------------- /src/Entity/Blog.php: -------------------------------------------------------------------------------- 1 | id; 48 | } 49 | 50 | public function getTitle(): ?string 51 | { 52 | return $this->title; 53 | } 54 | 55 | public function setTitle(string $title): self 56 | { 57 | $this->title = $title; 58 | 59 | return $this; 60 | } 61 | 62 | public function getSlug(): ?string 63 | { 64 | return $this->slug; 65 | } 66 | 67 | public function setSlug(string $slug): self 68 | { 69 | $this->slug = $slug; 70 | 71 | return $this; 72 | } 73 | 74 | public function getContent(): ?string 75 | { 76 | return $this->content; 77 | } 78 | 79 | public function setContent(?string $content): self 80 | { 81 | $this->content = $content; 82 | 83 | return $this; 84 | } 85 | 86 | public function getCreatedAt(): ?\DateTimeInterface 87 | { 88 | return $this->created_at; 89 | } 90 | 91 | public function setCreatedAt(\DateTimeInterface $created_at): self 92 | { 93 | $this->created_at = $created_at; 94 | 95 | return $this; 96 | } 97 | 98 | public function getCategory(): ?Category 99 | { 100 | return $this->category; 101 | } 102 | 103 | public function setCategory(?Category $category): self 104 | { 105 | $this->category = $category; 106 | 107 | return $this; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/Controller/Admin/CategoryController.php: -------------------------------------------------------------------------------- 1 | getDoctrine()->getManager(); 20 | $repository = $em->getRepository(Category::class); 21 | $items = $repository->findAll(); 22 | 23 | return $this->render('admin/category/index.html.twig', [ 24 | 'items'=>$items, 25 | ]); 26 | } 27 | /** 28 | * @Route("/admin/category/create/{id}",name="admin_category_create",defaults={"id":null}) 29 | */ 30 | public function create(Request $request, $id=null){ 31 | $em = $this->getDoctrine()->getManager(); 32 | $category_item = new Category(); 33 | if(!is_null($id) && ((int)$id)>0 ) { 34 | $category_item = $em->find(Category::class,$id)??$category_item; 35 | } 36 | 37 | $form = $this->createForm(CategoryType::class,$category_item); 38 | $form->handleRequest($request); 39 | 40 | if($form->isSubmitted() && $form->isValid()) { 41 | $slugify = new Slugify(); 42 | $slug = $slugify->slugify($category_item->getName()); 43 | $category_item->setSlug($slug); 44 | $em->persist($category_item); 45 | $em->flush(); 46 | $this->addFlash('success',"Kategori başarıyla kaydedildi!"); 47 | return $this->redirectToRoute('admin_category'); 48 | } 49 | 50 | return $this->render('admin/category/create.html.twig',[ 51 | 'form'=>$form->createView() 52 | ]); 53 | } 54 | /** 55 | * @Route("/admin/category/remove/{id}",name="admin_category_remove") 56 | */ 57 | public function remove($id){ 58 | try{ 59 | $em = $this->getDoctrine()->getManager(); 60 | $category_item = $em->find(Category::class,$id); 61 | if(!$category_item) { throw new NotFoundHttpException("Bu numaraya sahip kategory bulunamadı!") ;} 62 | $em->remove($category_item); 63 | $em->flush(); 64 | 65 | $this->addFlash("success","Kategori başarıyla silindi!"); 66 | 67 | }catch(\Exception $e){ 68 | $this->addFlash("danger", "Kategori silinemedi!"); 69 | } 70 | return $this->redirectToRoute('admin_category'); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/Controller/Admin/BlogController.php: -------------------------------------------------------------------------------- 1 | getDoctrine()->getManager(); 21 | $repository = $em->getRepository(Blog::class); 22 | $items = $repository->findAll(); 23 | 24 | return $this->render('admin/blog/index.html.twig', [ 25 | 'items'=>$items, 26 | ]); 27 | } 28 | /** 29 | * @Route("/admin/blog/create/{id}",name="admin_blog_create",defaults={"id":null}) 30 | */ 31 | public function create(Request $request, $id=null){ 32 | $em = $this->getDoctrine()->getManager(); 33 | $blog_item=new Blog(); 34 | 35 | if(!is_null($id) && ((int)$id)>0 ) { 36 | $blog_item = $em->find(Blog::class,$id)??$blog_item; 37 | } 38 | 39 | $form = $this->createForm(BlogType::class,$blog_item); 40 | $form->handleRequest($request); 41 | 42 | 43 | if($form->isSubmitted() && $form->isValid()) { 44 | $slugify = new Slugify(); 45 | $slug = $slugify->slugify($blog_item->getTitle()); 46 | $blog_item->setSlug($slug); 47 | 48 | if(!$blog_item->getId()) { 49 | $blog_item->setCreatedAt(new \DateTime()); 50 | } 51 | 52 | $em->persist($blog_item); 53 | $em->flush(); 54 | $this->addFlash('success',"İçerik başarıyla kaydedildi!"); 55 | return $this->redirectToRoute('admin_blog'); 56 | } 57 | 58 | return $this->render('admin/blog/create.html.twig',[ 59 | 'form'=>$form->createView() 60 | ]); 61 | } 62 | /** 63 | * @Route("/admin/blog/remove/{id}",name="admin_blog_remove") 64 | */ 65 | public function remove($id){ 66 | try{ 67 | $em = $this->getDoctrine()->getManager(); 68 | $blog_item = $em->find(Blog::class,$id); 69 | if(!$blog_item) { throw new NotFoundHttpException("Bu numaraya sahip içerik bulunamadı!") ;} 70 | $em->remove($blog_item); 71 | $em->flush(); 72 | 73 | $this->addFlash("success","İçerik başarıyla silindi!"); 74 | 75 | }catch(\Exception $e){ 76 | $this->addFlash("danger", "İçerik silinemedi!"); 77 | } 78 | return $this->redirectToRoute('admin_blog'); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "project", 3 | "license": "proprietary", 4 | "require": { 5 | "php": ">=7.2.5", 6 | "ext-ctype": "*", 7 | "ext-iconv": "*", 8 | "cocur/slugify": "^4.0", 9 | "composer/package-versions-deprecated": "^1.11", 10 | "doctrine/annotations": "^1.0", 11 | "doctrine/doctrine-bundle": "^2.1", 12 | "doctrine/doctrine-migrations-bundle": "^3.0", 13 | "doctrine/orm": "^2.7", 14 | "phpdocumentor/reflection-docblock": "^5.2", 15 | "sensio/framework-extra-bundle": "^5.1", 16 | "symfony/asset": "5.1.*", 17 | "symfony/console": "5.1.*", 18 | "symfony/dotenv": "5.1.*", 19 | "symfony/expression-language": "5.1.*", 20 | "symfony/flex": "^1.3.1", 21 | "symfony/form": "5.1.*", 22 | "symfony/framework-bundle": "5.1.*", 23 | "symfony/http-client": "5.1.*", 24 | "symfony/intl": "5.1.*", 25 | "symfony/mailer": "5.1.*", 26 | "symfony/mime": "5.1.*", 27 | "symfony/monolog-bundle": "^3.1", 28 | "symfony/notifier": "5.1.*", 29 | "symfony/process": "5.1.*", 30 | "symfony/property-access": "5.1.*", 31 | "symfony/property-info": "5.1.*", 32 | "symfony/security-bundle": "5.1.*", 33 | "symfony/serializer": "5.1.*", 34 | "symfony/string": "5.1.*", 35 | "symfony/translation": "5.1.*", 36 | "symfony/twig-bundle": "5.1.*", 37 | "symfony/validator": "5.1.*", 38 | "symfony/web-link": "5.1.*", 39 | "symfony/yaml": "5.1.*", 40 | "twig/extra-bundle": "^2.12|^3.0", 41 | "twig/twig": "^2.12|^3.0" 42 | }, 43 | "require-dev": { 44 | "doctrine/doctrine-fixtures-bundle": "^3.3", 45 | "symfony/browser-kit": "^5.1", 46 | "symfony/css-selector": "^5.1", 47 | "symfony/debug-bundle": "^5.1", 48 | "symfony/maker-bundle": "^1.0", 49 | "symfony/phpunit-bridge": "^5.1", 50 | "symfony/var-dumper": "^5.1" 51 | }, 52 | "config": { 53 | "optimize-autoloader": true, 54 | "preferred-install": { 55 | "*": "dist" 56 | }, 57 | "sort-packages": true 58 | }, 59 | "autoload": { 60 | "psr-4": { 61 | "App\\": "src/" 62 | } 63 | }, 64 | "autoload-dev": { 65 | "psr-4": { 66 | "App\\Tests\\": "tests/" 67 | } 68 | }, 69 | "replace": { 70 | "paragonie/random_compat": "2.*", 71 | "symfony/polyfill-ctype": "*", 72 | "symfony/polyfill-iconv": "*", 73 | "symfony/polyfill-php72": "*", 74 | "symfony/polyfill-php71": "*", 75 | "symfony/polyfill-php70": "*", 76 | "symfony/polyfill-php56": "*" 77 | }, 78 | "scripts": { 79 | "auto-scripts": { 80 | "cache:clear": "symfony-cmd", 81 | "assets:install %PUBLIC_DIR%": "symfony-cmd" 82 | }, 83 | "post-install-cmd": [ 84 | "@auto-scripts" 85 | ], 86 | "post-update-cmd": [ 87 | "@auto-scripts" 88 | ] 89 | }, 90 | "conflict": { 91 | "symfony/symfony": "*" 92 | }, 93 | "extra": { 94 | "symfony": { 95 | "allow-contrib": false, 96 | "require": "5.1.*" 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/Entity/Category.php: -------------------------------------------------------------------------------- 1 | childrens = new ArrayCollection(); 45 | } 46 | 47 | public function getId(): ?int 48 | { 49 | return $this->id; 50 | } 51 | 52 | public function getName(): ?string 53 | { 54 | return $this->name; 55 | } 56 | 57 | public function setName(string $name): self 58 | { 59 | $this->name = $name; 60 | 61 | return $this; 62 | } 63 | 64 | public function getSlug(): ?string 65 | { 66 | return $this->slug; 67 | } 68 | 69 | public function setSlug(string $slug): self 70 | { 71 | $this->slug = $slug; 72 | 73 | return $this; 74 | } 75 | 76 | public function getParent(): ?self 77 | { 78 | return $this->parent; 79 | } 80 | 81 | public function setParent(?self $parent): self 82 | { 83 | $this->parent = $parent; 84 | 85 | return $this; 86 | } 87 | 88 | /** 89 | * @return Collection|self[] 90 | */ 91 | public function getChildrens(): Collection 92 | { 93 | return $this->childrens; 94 | } 95 | 96 | public function addChildren(self $children): self 97 | { 98 | if (!$this->childrens->contains($children)) { 99 | $this->childrens[] = $children; 100 | $children->setParent($this); 101 | } 102 | 103 | return $this; 104 | } 105 | 106 | public function removeChildren(self $children): self 107 | { 108 | if ($this->childrens->contains($children)) { 109 | $this->childrens->removeElement($children); 110 | // set the owning side to null (unless already changed) 111 | if ($children->getParent() === $this) { 112 | $children->setParent(null); 113 | } 114 | } 115 | 116 | return $this; 117 | } 118 | public function getPath($root = null, $path = "") 119 | { 120 | if ($root == null) { 121 | $root = $this; 122 | } 123 | 124 | $path = $root->getName() . $path; 125 | if (!$root->getParent()) { 126 | return $path; 127 | } 128 | $path = " > " . $path; 129 | return $this->getPath($root->getParent(), $path); 130 | } 131 | 132 | public function __toString() 133 | { 134 | return $this->getPath(); 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /public/assets/bootstrap-4.5.2-dist/css/bootstrap-reboot.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Reboot v4.5.2 (https://getbootstrap.com/) 3 | * Copyright 2011-2020 The Bootstrap Authors 4 | * Copyright 2011-2020 Twitter, Inc. 5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) 7 | */*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([class]){color:inherit;text-decoration:none}a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important} 8 | /*# sourceMappingURL=bootstrap-reboot.min.css.map */ -------------------------------------------------------------------------------- /public/assets/bootstrap-4.5.2-dist/css/bootstrap-reboot.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Reboot v4.5.2 (https://getbootstrap.com/) 3 | * Copyright 2011-2020 The Bootstrap Authors 4 | * Copyright 2011-2020 Twitter, Inc. 5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) 7 | */ 8 | *, 9 | *::before, 10 | *::after { 11 | box-sizing: border-box; 12 | } 13 | 14 | html { 15 | font-family: sans-serif; 16 | line-height: 1.15; 17 | -webkit-text-size-adjust: 100%; 18 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 19 | } 20 | 21 | article, aside, figcaption, figure, footer, header, hgroup, main, nav, section { 22 | display: block; 23 | } 24 | 25 | body { 26 | margin: 0; 27 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; 28 | font-size: 1rem; 29 | font-weight: 400; 30 | line-height: 1.5; 31 | color: #212529; 32 | text-align: left; 33 | background-color: #fff; 34 | } 35 | 36 | [tabindex="-1"]:focus:not(:focus-visible) { 37 | outline: 0 !important; 38 | } 39 | 40 | hr { 41 | box-sizing: content-box; 42 | height: 0; 43 | overflow: visible; 44 | } 45 | 46 | h1, h2, h3, h4, h5, h6 { 47 | margin-top: 0; 48 | margin-bottom: 0.5rem; 49 | } 50 | 51 | p { 52 | margin-top: 0; 53 | margin-bottom: 1rem; 54 | } 55 | 56 | abbr[title], 57 | abbr[data-original-title] { 58 | text-decoration: underline; 59 | -webkit-text-decoration: underline dotted; 60 | text-decoration: underline dotted; 61 | cursor: help; 62 | border-bottom: 0; 63 | -webkit-text-decoration-skip-ink: none; 64 | text-decoration-skip-ink: none; 65 | } 66 | 67 | address { 68 | margin-bottom: 1rem; 69 | font-style: normal; 70 | line-height: inherit; 71 | } 72 | 73 | ol, 74 | ul, 75 | dl { 76 | margin-top: 0; 77 | margin-bottom: 1rem; 78 | } 79 | 80 | ol ol, 81 | ul ul, 82 | ol ul, 83 | ul ol { 84 | margin-bottom: 0; 85 | } 86 | 87 | dt { 88 | font-weight: 700; 89 | } 90 | 91 | dd { 92 | margin-bottom: .5rem; 93 | margin-left: 0; 94 | } 95 | 96 | blockquote { 97 | margin: 0 0 1rem; 98 | } 99 | 100 | b, 101 | strong { 102 | font-weight: bolder; 103 | } 104 | 105 | small { 106 | font-size: 80%; 107 | } 108 | 109 | sub, 110 | sup { 111 | position: relative; 112 | font-size: 75%; 113 | line-height: 0; 114 | vertical-align: baseline; 115 | } 116 | 117 | sub { 118 | bottom: -.25em; 119 | } 120 | 121 | sup { 122 | top: -.5em; 123 | } 124 | 125 | a { 126 | color: #007bff; 127 | text-decoration: none; 128 | background-color: transparent; 129 | } 130 | 131 | a:hover { 132 | color: #0056b3; 133 | text-decoration: underline; 134 | } 135 | 136 | a:not([href]):not([class]) { 137 | color: inherit; 138 | text-decoration: none; 139 | } 140 | 141 | a:not([href]):not([class]):hover { 142 | color: inherit; 143 | text-decoration: none; 144 | } 145 | 146 | pre, 147 | code, 148 | kbd, 149 | samp { 150 | font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; 151 | font-size: 1em; 152 | } 153 | 154 | pre { 155 | margin-top: 0; 156 | margin-bottom: 1rem; 157 | overflow: auto; 158 | -ms-overflow-style: scrollbar; 159 | } 160 | 161 | figure { 162 | margin: 0 0 1rem; 163 | } 164 | 165 | img { 166 | vertical-align: middle; 167 | border-style: none; 168 | } 169 | 170 | svg { 171 | overflow: hidden; 172 | vertical-align: middle; 173 | } 174 | 175 | table { 176 | border-collapse: collapse; 177 | } 178 | 179 | caption { 180 | padding-top: 0.75rem; 181 | padding-bottom: 0.75rem; 182 | color: #6c757d; 183 | text-align: left; 184 | caption-side: bottom; 185 | } 186 | 187 | th { 188 | text-align: inherit; 189 | } 190 | 191 | label { 192 | display: inline-block; 193 | margin-bottom: 0.5rem; 194 | } 195 | 196 | button { 197 | border-radius: 0; 198 | } 199 | 200 | button:focus { 201 | outline: 1px dotted; 202 | outline: 5px auto -webkit-focus-ring-color; 203 | } 204 | 205 | input, 206 | button, 207 | select, 208 | optgroup, 209 | textarea { 210 | margin: 0; 211 | font-family: inherit; 212 | font-size: inherit; 213 | line-height: inherit; 214 | } 215 | 216 | button, 217 | input { 218 | overflow: visible; 219 | } 220 | 221 | button, 222 | select { 223 | text-transform: none; 224 | } 225 | 226 | [role="button"] { 227 | cursor: pointer; 228 | } 229 | 230 | select { 231 | word-wrap: normal; 232 | } 233 | 234 | button, 235 | [type="button"], 236 | [type="reset"], 237 | [type="submit"] { 238 | -webkit-appearance: button; 239 | } 240 | 241 | button:not(:disabled), 242 | [type="button"]:not(:disabled), 243 | [type="reset"]:not(:disabled), 244 | [type="submit"]:not(:disabled) { 245 | cursor: pointer; 246 | } 247 | 248 | button::-moz-focus-inner, 249 | [type="button"]::-moz-focus-inner, 250 | [type="reset"]::-moz-focus-inner, 251 | [type="submit"]::-moz-focus-inner { 252 | padding: 0; 253 | border-style: none; 254 | } 255 | 256 | input[type="radio"], 257 | input[type="checkbox"] { 258 | box-sizing: border-box; 259 | padding: 0; 260 | } 261 | 262 | textarea { 263 | overflow: auto; 264 | resize: vertical; 265 | } 266 | 267 | fieldset { 268 | min-width: 0; 269 | padding: 0; 270 | margin: 0; 271 | border: 0; 272 | } 273 | 274 | legend { 275 | display: block; 276 | width: 100%; 277 | max-width: 100%; 278 | padding: 0; 279 | margin-bottom: .5rem; 280 | font-size: 1.5rem; 281 | line-height: inherit; 282 | color: inherit; 283 | white-space: normal; 284 | } 285 | 286 | progress { 287 | vertical-align: baseline; 288 | } 289 | 290 | [type="number"]::-webkit-inner-spin-button, 291 | [type="number"]::-webkit-outer-spin-button { 292 | height: auto; 293 | } 294 | 295 | [type="search"] { 296 | outline-offset: -2px; 297 | -webkit-appearance: none; 298 | } 299 | 300 | [type="search"]::-webkit-search-decoration { 301 | -webkit-appearance: none; 302 | } 303 | 304 | ::-webkit-file-upload-button { 305 | font: inherit; 306 | -webkit-appearance: button; 307 | } 308 | 309 | output { 310 | display: inline-block; 311 | } 312 | 313 | summary { 314 | display: list-item; 315 | cursor: pointer; 316 | } 317 | 318 | template { 319 | display: none; 320 | } 321 | 322 | [hidden] { 323 | display: none !important; 324 | } 325 | /*# sourceMappingURL=bootstrap-reboot.css.map */ -------------------------------------------------------------------------------- /symfony.lock: -------------------------------------------------------------------------------- 1 | { 2 | "cocur/slugify": { 3 | "version": "v4.0.0" 4 | }, 5 | "composer/package-versions-deprecated": { 6 | "version": "1.11.99" 7 | }, 8 | "doctrine/annotations": { 9 | "version": "1.0", 10 | "recipe": { 11 | "repo": "github.com/symfony/recipes", 12 | "branch": "master", 13 | "version": "1.0", 14 | "ref": "a2759dd6123694c8d901d0ec80006e044c2e6457" 15 | }, 16 | "files": [ 17 | "config/routes/annotations.yaml" 18 | ] 19 | }, 20 | "doctrine/cache": { 21 | "version": "1.10.2" 22 | }, 23 | "doctrine/collections": { 24 | "version": "1.6.7" 25 | }, 26 | "doctrine/common": { 27 | "version": "3.0.2" 28 | }, 29 | "doctrine/data-fixtures": { 30 | "version": "1.4.4" 31 | }, 32 | "doctrine/dbal": { 33 | "version": "2.10.3" 34 | }, 35 | "doctrine/doctrine-bundle": { 36 | "version": "2.0", 37 | "recipe": { 38 | "repo": "github.com/symfony/recipes", 39 | "branch": "master", 40 | "version": "2.0", 41 | "ref": "a9f2463b9f73efe74482f831f03a204a41328555" 42 | }, 43 | "files": [ 44 | "config/packages/doctrine.yaml", 45 | "config/packages/prod/doctrine.yaml", 46 | "src/Entity/.gitignore", 47 | "src/Repository/.gitignore" 48 | ] 49 | }, 50 | "doctrine/doctrine-fixtures-bundle": { 51 | "version": "3.0", 52 | "recipe": { 53 | "repo": "github.com/symfony/recipes", 54 | "branch": "master", 55 | "version": "3.0", 56 | "ref": "e5b542d4ef47d8a003c91beb35650c76907f7e53" 57 | }, 58 | "files": [ 59 | "src/DataFixtures/AppFixtures.php" 60 | ] 61 | }, 62 | "doctrine/doctrine-migrations-bundle": { 63 | "version": "2.2", 64 | "recipe": { 65 | "repo": "github.com/symfony/recipes", 66 | "branch": "master", 67 | "version": "2.2", 68 | "ref": "baaa439e3e3179e69e3da84b671f0a3e4a2f56ad" 69 | }, 70 | "files": [ 71 | "config/packages/doctrine_migrations.yaml", 72 | "migrations/.gitignore" 73 | ] 74 | }, 75 | "doctrine/event-manager": { 76 | "version": "1.1.1" 77 | }, 78 | "doctrine/inflector": { 79 | "version": "1.4.3" 80 | }, 81 | "doctrine/instantiator": { 82 | "version": "1.3.1" 83 | }, 84 | "doctrine/lexer": { 85 | "version": "1.2.1" 86 | }, 87 | "doctrine/migrations": { 88 | "version": "3.0.1" 89 | }, 90 | "doctrine/orm": { 91 | "version": "v2.7.3" 92 | }, 93 | "doctrine/persistence": { 94 | "version": "2.0.0" 95 | }, 96 | "doctrine/reflection": { 97 | "version": "1.2.1" 98 | }, 99 | "doctrine/sql-formatter": { 100 | "version": "1.1.1" 101 | }, 102 | "egulias/email-validator": { 103 | "version": "2.1.20" 104 | }, 105 | "laminas/laminas-code": { 106 | "version": "3.4.1" 107 | }, 108 | "laminas/laminas-eventmanager": { 109 | "version": "3.3.0" 110 | }, 111 | "laminas/laminas-zendframework-bridge": { 112 | "version": "1.1.0" 113 | }, 114 | "monolog/monolog": { 115 | "version": "2.1.1" 116 | }, 117 | "nikic/php-parser": { 118 | "version": "v4.9.1" 119 | }, 120 | "ocramius/proxy-manager": { 121 | "version": "2.8.0" 122 | }, 123 | "php": { 124 | "version": "7.4" 125 | }, 126 | "phpdocumentor/reflection-common": { 127 | "version": "2.2.0" 128 | }, 129 | "phpdocumentor/reflection-docblock": { 130 | "version": "5.2.1" 131 | }, 132 | "phpdocumentor/type-resolver": { 133 | "version": "1.3.0" 134 | }, 135 | "psr/cache": { 136 | "version": "1.0.1" 137 | }, 138 | "psr/container": { 139 | "version": "1.0.0" 140 | }, 141 | "psr/event-dispatcher": { 142 | "version": "1.0.0" 143 | }, 144 | "psr/link": { 145 | "version": "1.0.0" 146 | }, 147 | "psr/log": { 148 | "version": "1.1.3" 149 | }, 150 | "sensio/framework-extra-bundle": { 151 | "version": "5.2", 152 | "recipe": { 153 | "repo": "github.com/symfony/recipes", 154 | "branch": "master", 155 | "version": "5.2", 156 | "ref": "fb7e19da7f013d0d422fa9bce16f5c510e27609b" 157 | }, 158 | "files": [ 159 | "config/packages/sensio_framework_extra.yaml" 160 | ] 161 | }, 162 | "symfony/asset": { 163 | "version": "v5.1.5" 164 | }, 165 | "symfony/browser-kit": { 166 | "version": "v5.1.5" 167 | }, 168 | "symfony/cache": { 169 | "version": "v5.1.5" 170 | }, 171 | "symfony/cache-contracts": { 172 | "version": "v2.2.0" 173 | }, 174 | "symfony/config": { 175 | "version": "v5.1.5" 176 | }, 177 | "symfony/console": { 178 | "version": "5.1", 179 | "recipe": { 180 | "repo": "github.com/symfony/recipes", 181 | "branch": "master", 182 | "version": "5.1", 183 | "ref": "c6d02bdfba9da13c22157520e32a602dbee8a75c" 184 | }, 185 | "files": [ 186 | "bin/console" 187 | ] 188 | }, 189 | "symfony/css-selector": { 190 | "version": "v5.1.5" 191 | }, 192 | "symfony/debug-bundle": { 193 | "version": "4.1", 194 | "recipe": { 195 | "repo": "github.com/symfony/recipes", 196 | "branch": "master", 197 | "version": "4.1", 198 | "ref": "f8863cbad2f2e58c4b65fa1eac892ab189971bea" 199 | }, 200 | "files": [ 201 | "config/packages/dev/debug.yaml" 202 | ] 203 | }, 204 | "symfony/debug-pack": { 205 | "version": "v1.0.8" 206 | }, 207 | "symfony/dependency-injection": { 208 | "version": "v5.1.5" 209 | }, 210 | "symfony/deprecation-contracts": { 211 | "version": "v2.2.0" 212 | }, 213 | "symfony/doctrine-bridge": { 214 | "version": "v5.1.5" 215 | }, 216 | "symfony/dom-crawler": { 217 | "version": "v5.1.5" 218 | }, 219 | "symfony/dotenv": { 220 | "version": "v5.1.5" 221 | }, 222 | "symfony/error-handler": { 223 | "version": "v5.1.5" 224 | }, 225 | "symfony/event-dispatcher": { 226 | "version": "v5.1.5" 227 | }, 228 | "symfony/event-dispatcher-contracts": { 229 | "version": "v2.2.0" 230 | }, 231 | "symfony/expression-language": { 232 | "version": "v5.1.5" 233 | }, 234 | "symfony/filesystem": { 235 | "version": "v5.1.5" 236 | }, 237 | "symfony/finder": { 238 | "version": "v5.1.5" 239 | }, 240 | "symfony/flex": { 241 | "version": "1.0", 242 | "recipe": { 243 | "repo": "github.com/symfony/recipes", 244 | "branch": "master", 245 | "version": "1.0", 246 | "ref": "c0eeb50665f0f77226616b6038a9b06c03752d8e" 247 | }, 248 | "files": [ 249 | ".env" 250 | ] 251 | }, 252 | "symfony/form": { 253 | "version": "v5.1.5" 254 | }, 255 | "symfony/framework-bundle": { 256 | "version": "5.1", 257 | "recipe": { 258 | "repo": "github.com/symfony/recipes", 259 | "branch": "master", 260 | "version": "5.1", 261 | "ref": "e1b2770f2404d8307450a49cabfc3b2ff3184792" 262 | }, 263 | "files": [ 264 | "config/packages/cache.yaml", 265 | "config/packages/framework.yaml", 266 | "config/packages/test/framework.yaml", 267 | "config/routes/dev/framework.yaml", 268 | "config/services.yaml", 269 | "public/index.php", 270 | "src/Controller/.gitignore", 271 | "src/Kernel.php" 272 | ] 273 | }, 274 | "symfony/http-client": { 275 | "version": "v5.1.5" 276 | }, 277 | "symfony/http-client-contracts": { 278 | "version": "v2.2.0" 279 | }, 280 | "symfony/http-foundation": { 281 | "version": "v5.1.5" 282 | }, 283 | "symfony/http-kernel": { 284 | "version": "v5.1.5" 285 | }, 286 | "symfony/intl": { 287 | "version": "v5.1.5" 288 | }, 289 | "symfony/mailer": { 290 | "version": "4.3", 291 | "recipe": { 292 | "repo": "github.com/symfony/recipes", 293 | "branch": "master", 294 | "version": "4.3", 295 | "ref": "15658c2a0176cda2e7dba66276a2030b52bd81b2" 296 | }, 297 | "files": [ 298 | "config/packages/mailer.yaml" 299 | ] 300 | }, 301 | "symfony/maker-bundle": { 302 | "version": "1.0", 303 | "recipe": { 304 | "repo": "github.com/symfony/recipes", 305 | "branch": "master", 306 | "version": "1.0", 307 | "ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f" 308 | } 309 | }, 310 | "symfony/mime": { 311 | "version": "v5.1.5" 312 | }, 313 | "symfony/monolog-bridge": { 314 | "version": "v5.1.5" 315 | }, 316 | "symfony/monolog-bundle": { 317 | "version": "3.3", 318 | "recipe": { 319 | "repo": "github.com/symfony/recipes", 320 | "branch": "master", 321 | "version": "3.3", 322 | "ref": "d7249f7d560f6736115eee1851d02a65826f0a56" 323 | }, 324 | "files": [ 325 | "config/packages/dev/monolog.yaml", 326 | "config/packages/prod/deprecations.yaml", 327 | "config/packages/prod/monolog.yaml", 328 | "config/packages/test/monolog.yaml" 329 | ] 330 | }, 331 | "symfony/notifier": { 332 | "version": "5.0", 333 | "recipe": { 334 | "repo": "github.com/symfony/recipes", 335 | "branch": "master", 336 | "version": "5.0", 337 | "ref": "c31585e252b32fe0e1f30b1f256af553f4a06eb9" 338 | }, 339 | "files": [ 340 | "config/packages/notifier.yaml" 341 | ] 342 | }, 343 | "symfony/options-resolver": { 344 | "version": "v5.1.5" 345 | }, 346 | "symfony/orm-pack": { 347 | "version": "v2.0.0" 348 | }, 349 | "symfony/phpunit-bridge": { 350 | "version": "4.3", 351 | "recipe": { 352 | "repo": "github.com/symfony/recipes", 353 | "branch": "master", 354 | "version": "4.3", 355 | "ref": "6d0e35f749d5f4bfe1f011762875275cd3f9874f" 356 | }, 357 | "files": [ 358 | ".env.test", 359 | "bin/phpunit", 360 | "phpunit.xml.dist", 361 | "tests/bootstrap.php" 362 | ] 363 | }, 364 | "symfony/polyfill-intl-grapheme": { 365 | "version": "v1.18.1" 366 | }, 367 | "symfony/polyfill-intl-icu": { 368 | "version": "v1.18.1" 369 | }, 370 | "symfony/polyfill-intl-idn": { 371 | "version": "v1.18.1" 372 | }, 373 | "symfony/polyfill-intl-normalizer": { 374 | "version": "v1.18.1" 375 | }, 376 | "symfony/polyfill-mbstring": { 377 | "version": "v1.18.1" 378 | }, 379 | "symfony/polyfill-php73": { 380 | "version": "v1.18.1" 381 | }, 382 | "symfony/polyfill-php80": { 383 | "version": "v1.18.1" 384 | }, 385 | "symfony/process": { 386 | "version": "v5.1.5" 387 | }, 388 | "symfony/profiler-pack": { 389 | "version": "v1.0.5" 390 | }, 391 | "symfony/property-access": { 392 | "version": "v5.1.5" 393 | }, 394 | "symfony/property-info": { 395 | "version": "v5.1.5" 396 | }, 397 | "symfony/routing": { 398 | "version": "5.1", 399 | "recipe": { 400 | "repo": "github.com/symfony/recipes", 401 | "branch": "master", 402 | "version": "5.1", 403 | "ref": "b4f3e7c95e38b606eef467e8a42a8408fc460c43" 404 | }, 405 | "files": [ 406 | "config/packages/prod/routing.yaml", 407 | "config/packages/routing.yaml", 408 | "config/routes.yaml" 409 | ] 410 | }, 411 | "symfony/security-bundle": { 412 | "version": "5.1", 413 | "recipe": { 414 | "repo": "github.com/symfony/recipes", 415 | "branch": "master", 416 | "version": "5.1", 417 | "ref": "0a4bae19389d3b9cba1ca0102e3b2bccea724603" 418 | }, 419 | "files": [ 420 | "config/packages/security.yaml" 421 | ] 422 | }, 423 | "symfony/security-core": { 424 | "version": "v5.1.5" 425 | }, 426 | "symfony/security-csrf": { 427 | "version": "v5.1.5" 428 | }, 429 | "symfony/security-guard": { 430 | "version": "v5.1.5" 431 | }, 432 | "symfony/security-http": { 433 | "version": "v5.1.5" 434 | }, 435 | "symfony/serializer": { 436 | "version": "v5.1.5" 437 | }, 438 | "symfony/serializer-pack": { 439 | "version": "v1.0.3" 440 | }, 441 | "symfony/service-contracts": { 442 | "version": "v2.2.0" 443 | }, 444 | "symfony/stopwatch": { 445 | "version": "v5.1.5" 446 | }, 447 | "symfony/string": { 448 | "version": "v5.1.5" 449 | }, 450 | "symfony/test-pack": { 451 | "version": "v1.0.6" 452 | }, 453 | "symfony/translation": { 454 | "version": "3.3", 455 | "recipe": { 456 | "repo": "github.com/symfony/recipes", 457 | "branch": "master", 458 | "version": "3.3", 459 | "ref": "2ad9d2545bce8ca1a863e50e92141f0b9d87ffcd" 460 | }, 461 | "files": [ 462 | "config/packages/translation.yaml", 463 | "translations/.gitignore" 464 | ] 465 | }, 466 | "symfony/translation-contracts": { 467 | "version": "v2.2.0" 468 | }, 469 | "symfony/twig-bridge": { 470 | "version": "v5.1.5" 471 | }, 472 | "symfony/twig-bundle": { 473 | "version": "5.0", 474 | "recipe": { 475 | "repo": "github.com/symfony/recipes", 476 | "branch": "master", 477 | "version": "5.0", 478 | "ref": "fab9149bbaa4d5eca054ed93f9e1b66cc500895d" 479 | }, 480 | "files": [ 481 | "config/packages/test/twig.yaml", 482 | "config/packages/twig.yaml", 483 | "templates/base.html.twig" 484 | ] 485 | }, 486 | "symfony/twig-pack": { 487 | "version": "v1.0.0" 488 | }, 489 | "symfony/validator": { 490 | "version": "4.3", 491 | "recipe": { 492 | "repo": "github.com/symfony/recipes", 493 | "branch": "master", 494 | "version": "4.3", 495 | "ref": "d902da3e4952f18d3bf05aab29512eb61cabd869" 496 | }, 497 | "files": [ 498 | "config/packages/test/validator.yaml", 499 | "config/packages/validator.yaml" 500 | ] 501 | }, 502 | "symfony/var-dumper": { 503 | "version": "v5.1.5" 504 | }, 505 | "symfony/var-exporter": { 506 | "version": "v5.1.5" 507 | }, 508 | "symfony/web-link": { 509 | "version": "v5.1.5" 510 | }, 511 | "symfony/web-profiler-bundle": { 512 | "version": "3.3", 513 | "recipe": { 514 | "repo": "github.com/symfony/recipes", 515 | "branch": "master", 516 | "version": "3.3", 517 | "ref": "6bdfa1a95f6b2e677ab985cd1af2eae35d62e0f6" 518 | }, 519 | "files": [ 520 | "config/packages/dev/web_profiler.yaml", 521 | "config/packages/test/web_profiler.yaml", 522 | "config/routes/dev/web_profiler.yaml" 523 | ] 524 | }, 525 | "symfony/yaml": { 526 | "version": "v5.1.5" 527 | }, 528 | "twig/extra-bundle": { 529 | "version": "v3.0.5" 530 | }, 531 | "twig/twig": { 532 | "version": "v3.0.5" 533 | }, 534 | "webimpress/safe-writer": { 535 | "version": "2.1.0" 536 | }, 537 | "webmozart/assert": { 538 | "version": "1.9.1" 539 | } 540 | } 541 | -------------------------------------------------------------------------------- /public/assets/bootstrap-4.5.2-dist/css/bootstrap-reboot.min.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["../../scss/bootstrap-reboot.scss","../../scss/_reboot.scss","dist/css/bootstrap-reboot.css","../../scss/vendor/_rfs.scss","bootstrap-reboot.css","../../scss/mixins/_hover.scss"],"names":[],"mappings":"AAAA;;;;;;ACkBA,ECTA,QADA,SDaE,WAAA,WAGF,KACE,YAAA,WACA,YAAA,KACA,yBAAA,KACA,4BAAA,YAMF,QAAA,MAAA,WAAA,OAAA,OAAA,OAAA,OAAA,KAAA,IAAA,QACE,QAAA,MAUF,KACE,OAAA,EACA,YAAA,aAAA,CAAA,kBAAA,CAAA,UAAA,CAAA,MAAA,CAAA,gBAAA,CAAA,KAAA,CAAA,WAAA,CAAA,UAAA,CAAA,mBAAA,CAAA,gBAAA,CAAA,iBAAA,CAAA,mBEgFI,UAAA,KF9EJ,YAAA,IACA,YAAA,IACA,MAAA,QACA,WAAA,KACA,iBAAA,KGlBF,0CH+BE,QAAA,YASF,GACE,WAAA,YACA,OAAA,EACA,SAAA,QAaF,GAAA,GAAA,GAAA,GAAA,GAAA,GACE,WAAA,EACA,cAAA,MAOF,EACE,WAAA,EACA,cAAA,KC9CF,0BDyDA,YAEE,gBAAA,UACA,wBAAA,UAAA,OAAA,gBAAA,UAAA,OACA,OAAA,KACA,cAAA,EACA,iCAAA,KAAA,yBAAA,KAGF,QACE,cAAA,KACA,WAAA,OACA,YAAA,QCnDF,GDsDA,GCvDA,GD0DE,WAAA,EACA,cAAA,KAGF,MCtDA,MACA,MAFA,MD2DE,cAAA,EAGF,GACE,YAAA,IAGF,GACE,cAAA,MACA,YAAA,EAGF,WACE,OAAA,EAAA,EAAA,KAGF,ECvDA,ODyDE,YAAA,OAGF,MExFI,UAAA,IFiGJ,IC5DA,ID8DE,SAAA,SEnGE,UAAA,IFqGF,YAAA,EACA,eAAA,SAGF,IAAM,OAAA,OACN,IAAM,IAAA,MAON,EACE,MAAA,QACA,gBAAA,KACA,iBAAA,YIhLA,QJmLE,MAAA,QACA,gBAAA,UASJ,2BACE,MAAA,QACA,gBAAA,KI/LA,iCJkME,MAAA,QACA,gBAAA,KC7DJ,KACA,IDqEA,ICpEA,KDwEE,YAAA,cAAA,CAAA,KAAA,CAAA,MAAA,CAAA,QAAA,CAAA,iBAAA,CAAA,aAAA,CAAA,UEpJE,UAAA,IFwJJ,IAEE,WAAA,EAEA,cAAA,KAEA,SAAA,KAGA,mBAAA,UAQF,OAEE,OAAA,EAAA,EAAA,KAQF,IACE,eAAA,OACA,aAAA,KAGF,IAGE,SAAA,OACA,eAAA,OAQF,MACE,gBAAA,SAGF,QACE,YAAA,OACA,eAAA,OACA,MAAA,QACA,WAAA,KACA,aAAA,OAGF,GAGE,WAAA,QAQF,MAEE,QAAA,aACA,cAAA,MAMF,OAEE,cAAA,EAOF,aACE,QAAA,IAAA,OACA,QAAA,IAAA,KAAA,yBC1GF,OD6GA,MC3GA,SADA,OAEA,SD+GE,OAAA,EACA,YAAA,QExPE,UAAA,QF0PF,YAAA,QAGF,OC7GA,MD+GE,SAAA,QAGF,OC7GA,OD+GE,eAAA,KG7GF,cHoHE,OAAA,QAMF,OACE,UAAA,OChHF,cACA,aACA,cDqHA,OAIE,mBAAA,OCpHF,6BACA,4BACA,6BDuHE,sBAKI,OAAA,QCvHN,gCACA,+BACA,gCD2HA,yBAIE,QAAA,EACA,aAAA,KC1HF,qBD6HA,kBAEE,WAAA,WACA,QAAA,EAIF,SACE,SAAA,KAEA,OAAA,SAGF,SAME,UAAA,EAEA,QAAA,EACA,OAAA,EACA,OAAA,EAKF,OACE,QAAA,MACA,MAAA,KACA,UAAA,KACA,QAAA,EACA,cAAA,ME/RI,UAAA,OFiSJ,YAAA,QACA,MAAA,QACA,YAAA,OAGF,SACE,eAAA,SGvIF,yCFGA,yCD0IE,OAAA,KGxIF,cHgJE,eAAA,KACA,mBAAA,KG5IF,yCHoJE,mBAAA,KAQF,6BACE,KAAA,QACA,mBAAA,OAOF,OACE,QAAA,aAGF,QACE,QAAA,UACA,OAAA,QAGF,SACE,QAAA,KGzJF,SH+JE,QAAA","sourcesContent":["/*!\n * Bootstrap Reboot v4.5.2 (https://getbootstrap.com/)\n * Copyright 2011-2020 The Bootstrap Authors\n * Copyright 2011-2020 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n\n@import \"functions\";\n@import \"variables\";\n@import \"mixins\";\n@import \"reboot\";\n","// stylelint-disable at-rule-no-vendor-prefix, declaration-no-important, selector-no-qualifying-type, property-no-vendor-prefix\n\n// Reboot\n//\n// Normalization of HTML elements, manually forked from Normalize.css to remove\n// styles targeting irrelevant browsers while applying new styles.\n//\n// Normalize is licensed MIT. https://github.com/necolas/normalize.css\n\n\n// Document\n//\n// 1. Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.\n// 2. Change the default font family in all browsers.\n// 3. Correct the line height in all browsers.\n// 4. Prevent adjustments of font size after orientation changes in IE on Windows Phone and in iOS.\n// 5. Change the default tap highlight to be completely transparent in iOS.\n\n*,\n*::before,\n*::after {\n box-sizing: border-box; // 1\n}\n\nhtml {\n font-family: sans-serif; // 2\n line-height: 1.15; // 3\n -webkit-text-size-adjust: 100%; // 4\n -webkit-tap-highlight-color: rgba($black, 0); // 5\n}\n\n// Shim for \"new\" HTML5 structural elements to display correctly (IE10, older browsers)\n// TODO: remove in v5\n// stylelint-disable-next-line selector-list-comma-newline-after\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n\n// Body\n//\n// 1. Remove the margin in all browsers.\n// 2. As a best practice, apply a default `background-color`.\n// 3. Set an explicit initial text-align value so that we can later use\n// the `inherit` value on things like `` elements.\n\nbody {\n margin: 0; // 1\n font-family: $font-family-base;\n @include font-size($font-size-base);\n font-weight: $font-weight-base;\n line-height: $line-height-base;\n color: $body-color;\n text-align: left; // 3\n background-color: $body-bg; // 2\n}\n\n// Future-proof rule: in browsers that support :focus-visible, suppress the focus outline\n// on elements that programmatically receive focus but wouldn't normally show a visible\n// focus outline. In general, this would mean that the outline is only applied if the\n// interaction that led to the element receiving programmatic focus was a keyboard interaction,\n// or the browser has somehow determined that the user is primarily a keyboard user and/or\n// wants focus outlines to always be presented.\n//\n// See https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-visible\n// and https://developer.paciellogroup.com/blog/2018/03/focus-visible-and-backwards-compatibility/\n[tabindex=\"-1\"]:focus:not(:focus-visible) {\n outline: 0 !important;\n}\n\n\n// Content grouping\n//\n// 1. Add the correct box sizing in Firefox.\n// 2. Show the overflow in Edge and IE.\n\nhr {\n box-sizing: content-box; // 1\n height: 0; // 1\n overflow: visible; // 2\n}\n\n\n//\n// Typography\n//\n\n// Remove top margins from headings\n//\n// By default, `

`-`

` all receive top and bottom margins. We nuke the top\n// margin for easier control within type scales as it avoids margin collapsing.\n// stylelint-disable-next-line selector-list-comma-newline-after\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: $headings-margin-bottom;\n}\n\n// Reset margins on paragraphs\n//\n// Similarly, the top margin on `

`s get reset. However, we also reset the\n// bottom margin to use `rem` units instead of `em`.\np {\n margin-top: 0;\n margin-bottom: $paragraph-margin-bottom;\n}\n\n// Abbreviations\n//\n// 1. Duplicate behavior to the data-* attribute for our tooltip plugin\n// 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n// 3. Add explicit cursor to indicate changed behavior.\n// 4. Remove the bottom border in Firefox 39-.\n// 5. Prevent the text-decoration to be skipped.\n\nabbr[title],\nabbr[data-original-title] { // 1\n text-decoration: underline; // 2\n text-decoration: underline dotted; // 2\n cursor: help; // 3\n border-bottom: 0; // 4\n text-decoration-skip-ink: none; // 5\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: $dt-font-weight;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0; // Undo browser default\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\nb,\nstrong {\n font-weight: $font-weight-bolder; // Add the correct font weight in Chrome, Edge, and Safari\n}\n\nsmall {\n @include font-size(80%); // Add the correct font size in all browsers\n}\n\n//\n// Prevent `sub` and `sup` elements from affecting the line height in\n// all browsers.\n//\n\nsub,\nsup {\n position: relative;\n @include font-size(75%);\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub { bottom: -.25em; }\nsup { top: -.5em; }\n\n\n//\n// Links\n//\n\na {\n color: $link-color;\n text-decoration: $link-decoration;\n background-color: transparent; // Remove the gray background on active links in IE 10.\n\n @include hover() {\n color: $link-hover-color;\n text-decoration: $link-hover-decoration;\n }\n}\n\n// And undo these styles for placeholder links/named anchors (without href).\n// It would be more straightforward to just use a[href] in previous block, but that\n// causes specificity issues in many other styles that are too complex to fix.\n// See https://github.com/twbs/bootstrap/issues/19402\n\na:not([href]):not([class]) {\n color: inherit;\n text-decoration: none;\n\n @include hover() {\n color: inherit;\n text-decoration: none;\n }\n}\n\n\n//\n// Code\n//\n\npre,\ncode,\nkbd,\nsamp {\n font-family: $font-family-monospace;\n @include font-size(1em); // Correct the odd `em` font sizing in all browsers.\n}\n\npre {\n // Remove browser default top margin\n margin-top: 0;\n // Reset browser default of `1em` to use `rem`s\n margin-bottom: 1rem;\n // Don't allow content to break outside\n overflow: auto;\n // Disable auto-hiding scrollbar in IE & legacy Edge to avoid overlap,\n // making it impossible to interact with the content\n -ms-overflow-style: scrollbar;\n}\n\n\n//\n// Figures\n//\n\nfigure {\n // Apply a consistent margin strategy (matches our type styles).\n margin: 0 0 1rem;\n}\n\n\n//\n// Images and content\n//\n\nimg {\n vertical-align: middle;\n border-style: none; // Remove the border on images inside links in IE 10-.\n}\n\nsvg {\n // Workaround for the SVG overflow bug in IE10/11 is still required.\n // See https://github.com/twbs/bootstrap/issues/26878\n overflow: hidden;\n vertical-align: middle;\n}\n\n\n//\n// Tables\n//\n\ntable {\n border-collapse: collapse; // Prevent double borders\n}\n\ncaption {\n padding-top: $table-cell-padding;\n padding-bottom: $table-cell-padding;\n color: $table-caption-color;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n // Matches default `` alignment by inheriting from the ``, or the\n // closest parent with a set `text-align`.\n text-align: inherit;\n}\n\n\n//\n// Forms\n//\n\nlabel {\n // Allow labels to use `margin` for spacing.\n display: inline-block;\n margin-bottom: $label-margin-bottom;\n}\n\n// Remove the default `border-radius` that macOS Chrome adds.\n//\n// Details at https://github.com/twbs/bootstrap/issues/24093\nbutton {\n // stylelint-disable-next-line property-blacklist\n border-radius: 0;\n}\n\n// Work around a Firefox/IE bug where the transparent `button` background\n// results in a loss of the default `button` focus styles.\n//\n// Credit: https://github.com/suitcss/base/\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0; // Remove the margin in Firefox and Safari\n font-family: inherit;\n @include font-size(inherit);\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible; // Show the overflow in Edge\n}\n\nbutton,\nselect {\n text-transform: none; // Remove the inheritance of text transform in Firefox\n}\n\n// Set the cursor for non-`