├── .env
├── .env.test
├── .gitignore
├── LICENSE
├── README.md
├── bin
├── console
└── phpunit
├── composer.json
├── composer.lock
├── config
├── bootstrap.php
├── bundles.php
├── packages
│ ├── buzz.yaml
│ ├── cache.yaml
│ ├── dev
│ │ ├── debug.yaml
│ │ ├── monolog.yaml
│ │ ├── swiftmailer.yaml
│ │ └── web_profiler.yaml
│ ├── doctrine.yaml
│ ├── doctrine_migrations.yaml
│ ├── fos_user.yaml
│ ├── framework.yaml
│ ├── httplug.yaml
│ ├── knp_paginator.yaml
│ ├── liip_imagine.yaml
│ ├── nyholm_psr7.yaml
│ ├── oneup_uploader.yaml
│ ├── presta_sitemap.yaml
│ ├── prod
│ │ ├── deprecations.yaml
│ │ ├── doctrine.yaml
│ │ ├── monolog.yaml
│ │ └── routing.yaml
│ ├── routing.yaml
│ ├── security.yaml
│ ├── security_checker.yaml
│ ├── sensio_framework_extra.yaml
│ ├── swiftmailer.yaml
│ ├── test
│ │ ├── framework.yaml
│ │ ├── monolog.yaml
│ │ ├── swiftmailer.yaml
│ │ ├── twig.yaml
│ │ ├── validator.yaml
│ │ └── web_profiler.yaml
│ ├── translation.yaml
│ ├── twig.yaml
│ └── validator.yaml
├── preload.php
├── routes.yaml
├── routes
│ ├── annotations.yaml
│ ├── dev
│ │ ├── framework.yaml
│ │ ├── twig.yml
│ │ └── web_profiler.yaml
│ ├── liip_imagine.yaml
│ └── oneup_uploader.yaml
├── services.yaml
├── services_dev.yaml
└── services_test.yaml
├── docker-compose.yml
├── docker
└── development
│ ├── nginx.docker
│ ├── nginx
│ └── default.conf
│ ├── php-cli.docker
│ └── php-fpm.docker
├── migrations
├── .gitignore
├── Version20160405221329.php
├── Version20170315074425.php
├── Version20170508094506.php
├── Version20170508111346.php
├── Version20170508140613.php
└── Version20170510171203.php
├── phpunit.xml.dist
├── public
├── .htaccess
├── assets
│ ├── css
│ │ ├── bootstrap.min.css
│ │ ├── dashboard-style.css
│ │ ├── dropzone.min.css
│ │ ├── font-awesome.min.css
│ │ ├── signin.css
│ │ ├── style.css
│ │ └── summernote.css
│ ├── fancybox
│ │ ├── blank.gif
│ │ ├── fancybox_loading.gif
│ │ ├── fancybox_loading@2x.gif
│ │ ├── fancybox_overlay.png
│ │ ├── fancybox_sprite.png
│ │ ├── fancybox_sprite@2x.png
│ │ ├── jquery.fancybox.css
│ │ ├── jquery.fancybox.js
│ │ ├── jquery.fancybox.pack.js
│ │ └── jquery.mousewheel-3.0.6.pack.js
│ ├── fonts
│ │ ├── FontAwesome.otf
│ │ ├── fontawesome-webfont.eot
│ │ ├── fontawesome-webfont.svg
│ │ ├── fontawesome-webfont.ttf
│ │ ├── fontawesome-webfont.woff
│ │ ├── fontawesome-webfont.woff2
│ │ ├── glyphicons-halflings-regular.eot
│ │ ├── glyphicons-halflings-regular.svg
│ │ ├── glyphicons-halflings-regular.ttf
│ │ ├── glyphicons-halflings-regular.woff
│ │ └── glyphicons-halflings-regular.woff2
│ ├── images
│ │ └── ajax-loader.gif
│ └── js
│ │ ├── bootbox.min.js
│ │ ├── bootstrap-confirmation.min.js
│ │ ├── bootstrap.min.js
│ │ ├── cart.js
│ │ ├── dropzone.min.js
│ │ ├── ie10-viewport-bug-workaround.js
│ │ ├── js.cookie.js
│ │ ├── npm.js
│ │ ├── scripts.js
│ │ ├── speakingurl.min.js
│ │ └── summernote.min.js
├── favicon.ico
├── index.php
├── robots.txt
└── uploads
│ └── images
│ ├── no_image_available.png
│ ├── slide1.jpg
│ └── slide2.jpg
├── src
├── Controller
│ ├── .gitignore
│ ├── AjaxController.php
│ ├── CartController.php
│ ├── CatalogController.php
│ ├── LayoutsUtilityController.php
│ ├── ProfileController.php
│ └── admin
│ │ ├── AdminController.php
│ │ ├── CategoryController.php
│ │ ├── FeaturedController.php
│ │ ├── ManufacturerController.php
│ │ ├── MeasureController.php
│ │ ├── NewsController.php
│ │ ├── OrdersController.php
│ │ ├── ProductController.php
│ │ ├── SettingsController.php
│ │ ├── SlideController.php
│ │ ├── StaticPageController.php
│ │ └── UserController.php
├── DataFixtures
│ ├── AppFixtures.php
│ ├── FixturesProviderTrait.php
│ └── ORM
│ │ ├── CategoryFixtures.php
│ │ ├── LoadSettingsData.php
│ │ ├── LoadUserData.php
│ │ ├── ManufacturerFixtures.php
│ │ ├── MeasuresFixtures.php
│ │ ├── NewsFixtures.php
│ │ ├── ProductFixtures.php
│ │ ├── SlideFixtures.php
│ │ └── StaticPagesFixtures.php
├── Entity
│ ├── .gitignore
│ ├── Category.php
│ ├── Favourites.php
│ ├── Featured.php
│ ├── Image.php
│ ├── ImageHolderInterface.php
│ ├── Manufacturer.php
│ ├── Measure.php
│ ├── News.php
│ ├── OrderProduct.php
│ ├── Orders.php
│ ├── Product.php
│ ├── Settings.php
│ ├── Slide.php
│ ├── StaticPage.php
│ └── User.php
├── EventListener
│ ├── ImageUploadListener.php
│ ├── LocaleListener.php
│ ├── SitemapSubscriber.php
│ └── UploadListener.php
├── Form
│ └── Type
│ │ ├── CategoryType.php
│ │ ├── ManufacturerType.php
│ │ ├── MeasureType.php
│ │ ├── NewsType.php
│ │ ├── OrdersType.php
│ │ ├── ProductType.php
│ │ ├── RegistrationTypeExtension.php
│ │ ├── SlideType.php
│ │ └── StaticPageType.php
├── Kernel.php
├── Repository
│ ├── .gitignore
│ ├── CategoryRepository.php
│ ├── FavouritesRepository.php
│ ├── FeaturedRepository.php
│ ├── ImageRepository.php
│ ├── ManufacturerRepository.php
│ ├── MeasureRepository.php
│ ├── NewsRepository.php
│ ├── OrderProductRepository.php
│ ├── OrdersRepository.php
│ ├── ProductRepository.php
│ ├── SettingsRepository.php
│ ├── SlideRepository.php
│ ├── StaticPageRepository.php
│ └── UserRepository.php
├── Service
│ ├── Cart.php
│ ├── Catalog.php
│ ├── Category.php
│ ├── EmailNotifier.php
│ ├── FavouriteProducts.php
│ ├── FileUploader.php
│ ├── Manufacturer.php
│ ├── News.php
│ ├── PagesUtilities.php
│ ├── SettingsService.php
│ ├── Slides.php
│ └── Structs
│ │ ├── CartContents.php
│ │ ├── CartProductPosition.php
│ │ └── ProductLikeResult.php
├── Twig
│ └── RawDescriptionExtension.php
└── Utils
│ └── Slugger.php
├── symfony.lock
├── templates
├── _partials
│ ├── categories_menu.html.twig
│ ├── category_preview.html.twig
│ ├── last_seen_products.html.twig
│ ├── manufacturers_menu.html.twig
│ ├── navbar_auth_block.html.twig
│ ├── product_preview.html.twig
│ ├── slides_block.html.twig
│ └── static_pages_menu.html.twig
├── admin
│ ├── _partials
│ │ ├── admin_menu.html.twig
│ │ ├── index_product_item.html.twig
│ │ ├── init_summernote.js.twig
│ │ ├── product_images.html.twig
│ │ └── slug_generation.js.twig
│ ├── admin
│ │ └── index.html.twig
│ ├── category
│ │ ├── edit.html.twig
│ │ ├── index.html.twig
│ │ ├── new.html.twig
│ │ └── show.html.twig
│ ├── featured
│ │ └── index.html.twig
│ ├── layout.html.twig
│ ├── manufacturer
│ │ ├── edit.html.twig
│ │ ├── index.html.twig
│ │ ├── new.html.twig
│ │ └── show.html.twig
│ ├── measure
│ │ ├── edit.html.twig
│ │ ├── index.html.twig
│ │ ├── new.html.twig
│ │ └── show.html.twig
│ ├── news
│ │ ├── edit.html.twig
│ │ ├── index.html.twig
│ │ ├── new.html.twig
│ │ └── show.html.twig
│ ├── orders
│ │ ├── index.html.twig
│ │ └── show.html.twig
│ ├── product
│ │ ├── deleted.html.twig
│ │ ├── edit.html.twig
│ │ ├── index.html.twig
│ │ ├── new.html.twig
│ │ └── show.html.twig
│ ├── settings
│ │ └── index.html.twig
│ ├── slide
│ │ ├── edit.html.twig
│ │ ├── index.html.twig
│ │ ├── new.html.twig
│ │ └── show.html.twig
│ ├── static_page
│ │ ├── edit.html.twig
│ │ ├── index.html.twig
│ │ ├── new.html.twig
│ │ └── show.html.twig
│ └── user
│ │ ├── index.html.twig
│ │ ├── show_user_info.html.twig
│ │ └── show_user_orders.html.twig
├── base.html.twig
├── bundles
│ ├── FOSUserBundle
│ │ ├── ChangePassword
│ │ │ └── change_password.html.twig
│ │ ├── Registration
│ │ │ ├── confirmed.html.twig
│ │ │ └── register.html.twig
│ │ ├── Resetting
│ │ │ ├── check_email.html.twig
│ │ │ ├── email.txt.twig
│ │ │ ├── password_already_requested.html.twig
│ │ │ ├── request.html.twig
│ │ │ ├── reset.html.twig
│ │ │ └── reset_content.html.twig
│ │ └── Security
│ │ │ └── login.html.twig
│ └── TwigBundle
│ │ └── Exception
│ │ ├── error.html.twig
│ │ └── error404.html.twig
├── cart
│ ├── cart_is_empty.html.twig
│ ├── navbar_cart.html.twig
│ ├── order_form.html.twig
│ ├── show_cart.html.twig
│ └── thank_you.html.twig
├── catalog
│ ├── category.html.twig
│ ├── index.html.twig
│ ├── manufacturer.html.twig
│ ├── news.html.twig
│ ├── search_product.html.twig
│ ├── show_product.html.twig
│ └── show_static_page.html.twig
├── layout.html.twig
├── mail
│ └── order_notification_email.txt.twig
└── profile
│ └── favourites.html.twig
├── tests
├── Controller
│ ├── AdminControllerTest.php
│ ├── CategoryControllerTest.php
│ ├── ManufacturerControllerTest.php
│ ├── MeasureControllerTest.php
│ ├── NewsControllerTest.php
│ ├── ProductControllerTest.php
│ └── StaticPagesControllerTest.php
├── Utils
│ └── SluggerTest.php
└── bootstrap.php
├── translations
├── .gitignore
├── ShopBundle.en.yml
├── ShopBundle.ru.yml
├── messages.en.yml
└── messages.ru.yml
└── var
└── SymfonyRequirements.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=generate_your_own
20 | #TRUSTED_PROXIES=127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
21 | #TRUSTED_HOSTS='^(localhost|example\.com)$'
22 | ###< symfony/framework-bundle ###
23 |
24 | ###> doctrine/doctrine-bundle ###
25 | # Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
26 | # IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
27 | #
28 | # DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"
29 | # DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/db_name?serverVersion=8"
30 | DATABASE_URL="postgresql://app:!ChangeMe!@127.0.0.1:5432/db_name?serverVersion=14&charset=utf8"
31 | ###< doctrine/doctrine-bundle ###
32 |
33 | ###> symfony/swiftmailer-bundle ###
34 | # For Gmail as a transport, use: "gmail://username:password@localhost"
35 | # For a generic SMTP server, use: "smtp://localhost:25?encryption=&auth_mode="
36 | # Delivery is disabled by default via "null://localhost"
37 | MAILER_URL=null://localhost
38 | ###< symfony/swiftmailer-bundle ###
39 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ###> liip/imagine-bundle ###
2 | /public/media/cache/
3 | ###< liip/imagine-bundle ###
4 |
5 | ###> symfony/phpunit-bridge ###
6 | .phpunit
7 | .phpunit.result.cache
8 | /phpunit.xml
9 | ###< symfony/phpunit-bridge ###
10 |
11 | ###> symfony/framework-bundle ###
12 | /.env.local
13 | /.env.local.php
14 | /.env.*.local
15 | /config/secrets/prod/prod.decrypt.private.php
16 | /public/bundles/
17 | /var/
18 | /vendor/
19 | ###< symfony/framework-bundle ###
20 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Alexander Morozov
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Symfocommerce
2 | =====
3 |
4 | [](https://gitter.im/morozovalexander/symfocommerce?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
5 | [](https://opensource.org/licenses/MIT)
6 |
7 | Symfony3 Standart Edition based ecommerce project.
8 |
9 | Demo version: [http://symfocommerce.webgrowth.xyz](http://symfocommerce.webgrowth.xyz)
10 |
11 | - Products with related categories and manufacturers.
12 | - Advanced and convenient admin panel
13 | - Products sorting by name or price
14 | - Disabling products by set zero quantity
15 | - Ability to add products to favourites
16 | - Seo friendly navigation, meta tags and description on each page, routes using slug,
17 | not id's, slug generator in admin section
18 | - Different product measures, e.g. grammes, pieces, oz., ml.
19 | - Category and manufacturer images
20 | - Several product images, fancybox, image uploading by dropzone in admin
21 | - Interactive javascript cart, online cart edition
22 | - News section, last news displayed on main page
23 | - Static pages and links to static pages in top menu
24 | - Slides on top page, slides management in admin section
25 | - Summernote editor for all descriptions
26 | - Sitemap autogeneration
27 |
28 | Print /admin to access admin section.
29 |
30 | To start use project run next console commands:
31 |
32 | - $ composer update
33 | - $ php bin/console doctrine:database:create
34 | - $ php bin/console doctrine:migrations:migrate
35 |
36 | You can load some test data and admin account (admin/admin) if you want
37 |
38 | - $ php bin/console doctrine:fixtures:load
39 |
40 | Do not forget to set permissions for var/cache/, var/logs/, var/sessions/, web/media/ to run symfony ;)
41 |
--------------------------------------------------------------------------------
/bin/console:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | getParameterOption(['--env', '-e'], null, true)) {
23 | putenv('APP_ENV='.$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = $env);
24 | }
25 |
26 | if ($input->hasParameterOption('--no-debug', true)) {
27 | putenv('APP_DEBUG='.$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = '0');
28 | }
29 |
30 | require dirname(__DIR__).'/config/bootstrap.php';
31 |
32 | if ($_SERVER['APP_DEBUG']) {
33 | umask(0000);
34 |
35 | if (class_exists(Debug::class)) {
36 | Debug::enable();
37 | }
38 | }
39 |
40 | $kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']);
41 | $application = new Application($kernel);
42 | $application->run($input);
43 |
--------------------------------------------------------------------------------
/bin/phpunit:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | =7.2.5",
26 | "doctrine/orm": "^2.5",
27 | "doctrine/doctrine-bundle": "^1.6",
28 | "symfony/swiftmailer-bundle": "^3.5.0",
29 | "symfony/monolog-bundle": "^3.6.0",
30 | "php-http/guzzle6-adapter": "^2.0",
31 | "sensio/framework-extra-bundle": "^3.0.2",
32 | "incenteev/composer-parameter-handler": "^2.0",
33 | "friendsofsymfony/user-bundle": "~2.0@dev",
34 | "doctrine/doctrine-fixtures-bundle": "^2.3",
35 | "doctrine/doctrine-migrations-bundle": "^3.0",
36 | "oneup/uploader-bundle": "^3.0",
37 | "cocur/slugify": "^1.4",
38 | "liip/imagine-bundle": "^2.7",
39 | "knplabs/knp-paginator-bundle": "^5.3.0",
40 | "presta/sitemap-bundle": "^2.3.1",
41 | "symfony/flex": "^1.1",
42 | "symfony/polyfill-mbstring": "^1.20",
43 | "symfony/dotenv": "^4.4",
44 | "php-http/httplug-bundle": "^1.19"
45 | },
46 | "require-dev": {
47 | "roave/security-advisories": "dev-latest",
48 | "symfony/debug-bundle": "*",
49 | "symfony/web-profiler-bundle": "*",
50 | "symfony/phpunit-bridge": "^3.0"
51 | },
52 | "scripts": {
53 | "auto-scripts": {
54 | "cache:clear": "symfony-cmd",
55 | "assets:install --symlink --relative %PUBLIC_DIR%": "symfony-cmd",
56 | "assets:install %PUBLIC_DIR%": "symfony-cmd"
57 | },
58 | "post-install-cmd": [
59 | "@auto-scripts"
60 | ],
61 | "post-update-cmd": [
62 | "@auto-scripts"
63 | ]
64 | },
65 | "config": {
66 | "platform": {
67 | "php": "7.2.5"
68 | },
69 | "allow-plugins": {
70 | "symfony/flex": true
71 | }
72 | },
73 | "extra": {
74 | "symfony": {
75 | "allow-contrib": true,
76 | "require": "4.4.*"
77 | }
78 | },
79 | "conflict": {
80 | "symfony/symfony": "*"
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/config/bootstrap.php:
--------------------------------------------------------------------------------
1 | =1.2)
13 | if (is_array($env = @include dirname(__DIR__).'/.env.local.php') && (!isset($env['APP_ENV']) || ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? $env['APP_ENV']) === $env['APP_ENV'])) {
14 | (new Dotenv(false))->populate($env);
15 | } else {
16 | // load all the .env files
17 | (new Dotenv(false))->loadEnv(dirname(__DIR__).'/.env');
18 | }
19 |
20 | $_SERVER += $_ENV;
21 | $_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null) ?: 'dev';
22 | $_SERVER['APP_DEBUG'] = $_SERVER['APP_DEBUG'] ?? $_ENV['APP_DEBUG'] ?? 'prod' !== $_SERVER['APP_ENV'];
23 | $_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = (int) $_SERVER['APP_DEBUG'] || filter_var($_SERVER['APP_DEBUG'], FILTER_VALIDATE_BOOLEAN) ? '1' : '0';
24 |
--------------------------------------------------------------------------------
/config/bundles.php:
--------------------------------------------------------------------------------
1 | ['all' => true],
5 | Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
6 | Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
7 | FOS\UserBundle\FOSUserBundle::class => ['all' => true],
8 | Knp\Bundle\PaginatorBundle\KnpPaginatorBundle::class => ['all' => true],
9 | Liip\ImagineBundle\LiipImagineBundle::class => ['all' => true],
10 | Oneup\UploaderBundle\OneupUploaderBundle::class => ['all' => true],
11 | Presta\SitemapBundle\PrestaSitemapBundle::class => ['all' => true],
12 | Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true],
13 | Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
14 | Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle::class => ['all' => true],
15 | Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true],
16 | Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
17 | Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
18 | Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
19 | Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true],
20 | Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
21 | Http\HttplugBundle\HttplugBundle::class => ['all' => true],
22 | ];
23 |
--------------------------------------------------------------------------------
/config/packages/buzz.yaml:
--------------------------------------------------------------------------------
1 | # Read more about client options at: https://github.com/kriswallsmith/Buzz/blob/master/doc/client.md
2 | services:
3 | _defaults:
4 | public: false
5 |
6 | # Tell the auto wire system to use "FileGetContents" client as default client.
7 | # Set this to any of the other clients below (e.g. Curl or MultiCurl) to use a different default client.
8 | Buzz\Client\BuzzClientInterface: '@buzz.file_get_contents_client'
9 |
10 | # Clients
11 | buzz.file_get_contents_client:
12 | class: Buzz\Client\FileGetContents
13 | arguments:
14 | - timeout: 10
15 |
16 | buzz.curl_client:
17 | class: Buzz\Client\Curl
18 | arguments:
19 | - timeout: 10
20 |
21 | buzz.multi_curl_client:
22 | class: Buzz\Client\MultiCurl
23 | arguments:
24 | - timeout: 10
25 |
26 | # Browser
27 | Buzz\Browser:
28 | arguments: ['@Buzz\Client\BuzzClientInterface']
29 | calls:
30 | - ['addMiddleware', ['@buzz.middleware.content_length']]
31 | - ['addMiddleware', ['@buzz.middleware.logger']]
32 |
33 | # Middlewares
34 | buzz.middleware.content_length:
35 | class: Buzz\Middleware\ContentLengthMiddleware
36 |
37 | buzz.middleware.logger:
38 | class: Buzz\Middleware\LoggerMiddleware
39 | arguments: ['@?logger']
40 | tags:
41 | - { name: monolog.logger, channel: buzz }
42 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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/dev/swiftmailer.yaml:
--------------------------------------------------------------------------------
1 | # See https://symfony.com/doc/current/email/dev_environment.html
2 | #swiftmailer:
3 | # send all emails to a specific address
4 | # delivery_addresses: ['me@example.com']
5 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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: '13'
8 |
9 | # only needed for MySQL
10 | charset: utf8mb4
11 | default_table_options:
12 | collate: utf8mb4_unicode_ci
13 |
14 | # backtrace queries in profiler (increases memory usage per request)
15 | #profiling_collect_backtrace: '%kernel.debug%'
16 | orm:
17 | auto_generate_proxy_classes: true
18 | naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
19 | auto_mapping: true
20 | mappings:
21 | App:
22 | is_bundle: false
23 | type: annotation
24 | dir: '%kernel.project_dir%/src/Entity'
25 | prefix: 'App\Entity'
26 | alias: App
27 |
--------------------------------------------------------------------------------
/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/fos_user.yaml:
--------------------------------------------------------------------------------
1 | fos_user:
2 | db_driver: orm
3 | firewall_name: main
4 | user_class: App\Entity\User
5 | from_email:
6 | address: you@example.com
7 | sender_name: You
8 | service:
9 | mailer: fos_user.mailer.twig_swift
10 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/config/packages/httplug.yaml:
--------------------------------------------------------------------------------
1 | httplug:
2 | plugins:
3 | retry:
4 | retry: 1
5 |
6 | discovery:
7 | client: 'auto'
8 |
9 | clients:
10 | app:
11 | http_methods_client: true
12 | plugins:
13 | - 'httplug.plugin.content_length'
14 | - 'httplug.plugin.redirect'
15 |
--------------------------------------------------------------------------------
/config/packages/knp_paginator.yaml:
--------------------------------------------------------------------------------
1 | knp_paginator:
2 | page_range: 5 # default page range used in pagination control
3 | default_options:
4 | page_name: page # page query parameter name
5 | sort_field_name: sort # sort field query parameter name
6 | sort_direction_name: direction # sort direction query parameter name
7 | distinct: true # ensure distinct results, useful when ORM queries are using GROUP BY statements
8 | template:
9 | pagination: '@KnpPaginator/Pagination/twitter_bootstrap_v3_pagination.html.twig' # sliding pagination controls template
10 | sortable: '@KnpPaginator/Pagination/sortable_link.html.twig' # sort link template
11 |
--------------------------------------------------------------------------------
/config/packages/liip_imagine.yaml:
--------------------------------------------------------------------------------
1 | # Documentation on how to configure the bundle can be found at: https://symfony.com/doc/current/bundles/LiipImagineBundle/basic-usage.html
2 | liip_imagine:
3 | # valid drivers options include "gd" or "gmagick" or "imagick"
4 | driver: "gd"
5 | resolvers:
6 | default:
7 | web_path:
8 | web_root: "%kernel.project_dir%/public"
9 | cache_prefix: "media/cache"
10 |
11 | filter_sets:
12 | cache: ~
13 | some_thumb:
14 | quality: 75
15 | filters:
16 | thumbnail: { size: [100, 100], mode: outbound }
17 | category_mainpage_thumb:
18 | quality: 100
19 | filters:
20 | thumbnail: { size: [300, 300], mode: outbound }
21 | product_preview_thumb:
22 | quality: 100
23 | filters:
24 | thumbnail: { size: [150, 150], mode: outbound }
25 | product_main_thumb:
26 | quality: 100
27 | filters:
28 | thumbnail: { size: [600, 600], mode: outbound }
29 | slide:
30 | quality: 100
31 | filters:
32 | thumbnail: { size: [1500, 500], mode: outbound }
33 |
--------------------------------------------------------------------------------
/config/packages/nyholm_psr7.yaml:
--------------------------------------------------------------------------------
1 | services:
2 | # Register nyholm/psr7 services for autowiring with PSR-17 (HTTP factories)
3 | Psr\Http\Message\RequestFactoryInterface: '@nyholm.psr7.psr17_factory'
4 | Psr\Http\Message\ResponseFactoryInterface: '@nyholm.psr7.psr17_factory'
5 | Psr\Http\Message\ServerRequestFactoryInterface: '@nyholm.psr7.psr17_factory'
6 | Psr\Http\Message\StreamFactoryInterface: '@nyholm.psr7.psr17_factory'
7 | Psr\Http\Message\UploadedFileFactoryInterface: '@nyholm.psr7.psr17_factory'
8 | Psr\Http\Message\UriFactoryInterface: '@nyholm.psr7.psr17_factory'
9 |
10 | # Register nyholm/psr7 services for autowiring with HTTPlug factories
11 | Http\Message\MessageFactory: '@nyholm.psr7.httplug_factory'
12 | Http\Message\RequestFactory: '@nyholm.psr7.httplug_factory'
13 | Http\Message\ResponseFactory: '@nyholm.psr7.httplug_factory'
14 | Http\Message\StreamFactory: '@nyholm.psr7.httplug_factory'
15 | Http\Message\UriFactory: '@nyholm.psr7.httplug_factory'
16 |
17 | nyholm.psr7.psr17_factory:
18 | class: Nyholm\Psr7\Factory\Psr17Factory
19 |
20 | nyholm.psr7.httplug_factory:
21 | class: Nyholm\Psr7\Factory\HttplugFactory
22 |
--------------------------------------------------------------------------------
/config/packages/oneup_uploader.yaml:
--------------------------------------------------------------------------------
1 | # Read the documentation: https://github.com/1up-lab/OneupUploaderBundle/blob/master/Resources/doc/index.md
2 | oneup_uploader:
3 | mappings:
4 | # This is a mapping example, remove it and create your own mappings.
5 | gallery:
6 | frontend: dropzone # or any uploader you use in the frontend
7 | storage:
8 | directory: "%kernel.project_dir%/public/uploads/images"
9 |
--------------------------------------------------------------------------------
/config/packages/presta_sitemap.yaml:
--------------------------------------------------------------------------------
1 | presta_sitemap:
2 | timetolive: 3600
3 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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/prod/routing.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | router:
3 | strict_requirements: null
4 |
--------------------------------------------------------------------------------
/config/packages/routing.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | router:
3 | utf8: true
4 |
--------------------------------------------------------------------------------
/config/packages/security.yaml:
--------------------------------------------------------------------------------
1 | security:
2 | encoders:
3 | FOS\UserBundle\Model\UserInterface: sha512
4 |
5 | role_hierarchy:
6 | ROLE_ADMIN: ROLE_USER
7 | ROLE_SUPER_ADMIN: ROLE_ADMIN
8 |
9 | providers:
10 | fos_userbundle:
11 | id: fos_user.user_provider.username_email
12 | firewalls:
13 | main:
14 | pattern: ^/
15 | form_login:
16 | provider: fos_userbundle
17 | csrf_token_generator: security.csrf.token_manager
18 | logout: true
19 | anonymous: true
20 | login:
21 | pattern: ^/login$
22 | security: false
23 |
24 | remember_me:
25 | secret: '%env(APP_SECRET)%'
26 | lifetime: 31536000
27 | path: /
28 | domain: ~
29 |
30 | access_control:
31 | - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
32 | - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
33 | - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
34 | - { path: ^/admin/, role: ROLE_ADMIN }
35 |
--------------------------------------------------------------------------------
/config/packages/security_checker.yaml:
--------------------------------------------------------------------------------
1 | services:
2 | _defaults:
3 | autowire: true
4 | autoconfigure: true
5 |
6 | SensioLabs\Security\SecurityChecker: null
7 |
8 | SensioLabs\Security\Command\SecurityCheckerCommand: null
9 |
--------------------------------------------------------------------------------
/config/packages/sensio_framework_extra.yaml:
--------------------------------------------------------------------------------
1 | sensio_framework_extra:
2 | router:
3 | annotations: false
4 |
--------------------------------------------------------------------------------
/config/packages/swiftmailer.yaml:
--------------------------------------------------------------------------------
1 | swiftmailer:
2 | url: '%env(MAILER_URL)%'
3 | spool: { type: 'memory' }
4 |
--------------------------------------------------------------------------------
/config/packages/test/framework.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | test: true
3 | session:
4 | storage_id: session.storage.mock_file
5 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/config/packages/test/swiftmailer.yaml:
--------------------------------------------------------------------------------
1 | swiftmailer:
2 | disable_delivery: true
3 |
--------------------------------------------------------------------------------
/config/packages/test/twig.yaml:
--------------------------------------------------------------------------------
1 | twig:
2 | strict_variables: true
3 |
--------------------------------------------------------------------------------
/config/packages/test/validator.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | validation:
3 | not_compromised_password: false
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/translation.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | default_locale: en
3 | translator:
4 | default_path: '%kernel.project_dir%/translations'
5 | fallbacks:
6 | - '%locale%'
7 |
--------------------------------------------------------------------------------
/config/packages/twig.yaml:
--------------------------------------------------------------------------------
1 | twig:
2 | default_path: '%kernel.project_dir%/templates'
3 | debug: '%kernel.debug%'
4 | strict_variables: '%kernel.debug%'
5 | exception_controller: null
6 |
--------------------------------------------------------------------------------
/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/preload.php:
--------------------------------------------------------------------------------
1 | abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
22 |
23 | $this->addSql('ALTER TABLE app_user DROP locked, DROP expired, DROP expires_at, DROP credentials_expired, DROP credentials_expire_at, CHANGE username username VARCHAR(180) NOT NULL, CHANGE username_canonical username_canonical VARCHAR(180) NOT NULL, CHANGE email email VARCHAR(180) NOT NULL, CHANGE email_canonical email_canonical VARCHAR(180) NOT NULL, CHANGE salt salt VARCHAR(255) DEFAULT NULL, CHANGE confirmation_token confirmation_token VARCHAR(180) DEFAULT NULL');
24 | $this->addSql('CREATE UNIQUE INDEX UNIQ_88BDF3E9C05FB297 ON app_user (confirmation_token)');
25 | }
26 |
27 | /**
28 | * @param Schema $schema
29 | * @throws DBALException
30 | */
31 | public function down(Schema $schema): void
32 | {
33 | // this down() migration is auto-generated, please modify it to your needs
34 | $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
35 |
36 | $this->addSql('DROP INDEX UNIQ_88BDF3E9C05FB297 ON app_user');
37 | $this->addSql('ALTER TABLE app_user ADD locked TINYINT(1) NOT NULL, ADD expired TINYINT(1) NOT NULL, ADD expires_at DATETIME DEFAULT NULL, ADD credentials_expired TINYINT(1) NOT NULL, ADD credentials_expire_at DATETIME DEFAULT NULL, CHANGE username username VARCHAR(255) NOT NULL COLLATE utf8_unicode_ci, CHANGE username_canonical username_canonical VARCHAR(255) NOT NULL COLLATE utf8_unicode_ci, CHANGE email email VARCHAR(255) NOT NULL COLLATE utf8_unicode_ci, CHANGE email_canonical email_canonical VARCHAR(255) NOT NULL COLLATE utf8_unicode_ci, CHANGE salt salt VARCHAR(255) NOT NULL COLLATE utf8_unicode_ci, CHANGE confirmation_token confirmation_token VARCHAR(255) DEFAULT NULL COLLATE utf8_unicode_ci');
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/migrations/Version20170508094506.php:
--------------------------------------------------------------------------------
1 | abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
22 |
23 | $this->addSql('ALTER TABLE category ADD image VARCHAR(255) DEFAULT NULL, DROP path');
24 | }
25 |
26 | /**
27 | * @param Schema $schema
28 | * @throws DBALException
29 | */
30 | public function down(Schema $schema): void
31 | {
32 | // this down() migration is auto-generated, please modify it to your needs
33 | $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
34 |
35 | $this->addSql('ALTER TABLE category ADD path TINYTEXT DEFAULT NULL COLLATE utf8_unicode_ci, DROP image');
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/migrations/Version20170508111346.php:
--------------------------------------------------------------------------------
1 | abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
22 |
23 | $this->addSql('ALTER TABLE manufacturer ADD image VARCHAR(255) DEFAULT NULL, DROP path');
24 | }
25 |
26 | /**
27 | * @param Schema $schema
28 | * @throws DBALException
29 | */
30 | public function down(Schema $schema): void
31 | {
32 | // this down() migration is auto-generated, please modify it to your needs
33 | $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
34 |
35 | $this->addSql('ALTER TABLE manufacturer ADD path TINYTEXT DEFAULT NULL COLLATE utf8_unicode_ci, DROP image');
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/migrations/Version20170508140613.php:
--------------------------------------------------------------------------------
1 | abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
22 |
23 | $this->addSql('ALTER TABLE slide ADD image VARCHAR(255) DEFAULT NULL, DROP path');
24 | }
25 |
26 | /**
27 | * @param Schema $schema
28 | * @throws DBALException
29 | */
30 | public function down(Schema $schema): void
31 | {
32 | // this down() migration is auto-generated, please modify it to your needs
33 | $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
34 |
35 | $this->addSql('ALTER TABLE slide ADD path TINYTEXT DEFAULT NULL COLLATE utf8_unicode_ci, DROP image');
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/migrations/Version20170510171203.php:
--------------------------------------------------------------------------------
1 | abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
22 |
23 | $this->addSql('ALTER TABLE image ADD image VARCHAR(255) DEFAULT NULL, DROP path');
24 | }
25 |
26 | /**
27 | * @param Schema $schema
28 | * @throws DBALException
29 | */
30 | public function down(Schema $schema): void
31 | {
32 | // this down() migration is auto-generated, please modify it to your needs
33 | $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
34 |
35 | $this->addSql('ALTER TABLE image ADD path TINYTEXT DEFAULT NULL COLLATE utf8_unicode_ci, DROP image');
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | tests
20 |
21 |
22 |
23 |
24 |
25 | src
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/public/assets/css/dashboard-style.css:
--------------------------------------------------------------------------------
1 | /*
2 | * Base structure
3 | */
4 |
5 | /* Move down content because we have a fixed navbar that is 50px tall */
6 | body {
7 | padding-top: 50px;
8 | }
9 |
10 |
11 | /*
12 | * Global add-ons
13 | */
14 |
15 | .sub-header {
16 | padding-bottom: 10px;
17 | border-bottom: 1px solid #eee;
18 | }
19 |
20 | /*
21 | * Top navigation
22 | * Hide default border to remove 1px line.
23 | */
24 | .navbar-fixed-top {
25 | border: 0;
26 | }
27 |
28 | /*
29 | * Sidebar
30 | */
31 |
32 | .dashboard-sidebar {
33 | bottom: 0;
34 | left: 0;
35 | padding: 20px;
36 | background-color: #f5f5f5;
37 | border-right: 1px solid #eee;
38 | }
39 |
40 | /* Sidebar navigation */
41 | .nav-sidebar {
42 | margin-right: -21px; /* 20px padding + 1px border */
43 | margin-bottom: 20px;
44 | margin-left: -20px;
45 | }
46 | .nav-sidebar > li > a {
47 | padding-right: 20px;
48 | padding-left: 20px;
49 | }
50 | .nav-sidebar > .active > a,
51 | .nav-sidebar > .active > a:hover,
52 | .nav-sidebar > .active > a:focus {
53 | color: #fff;
54 | background-color: #428bca;
55 | }
56 |
57 |
58 | /*
59 | * Main content
60 | */
61 |
62 | .main {
63 | padding: 20px;
64 | }
65 | @media (min-width: 768px) {
66 | .main {
67 | padding-right: 40px;
68 | padding-left: 40px;
69 | }
70 | }
71 | .main .page-header {
72 | margin-top: 0;
73 | }
74 |
75 |
76 | /*
77 | * Placeholder dashboard ideas
78 | */
79 |
80 | .placeholders {
81 | margin-bottom: 30px;
82 | text-align: center;
83 | }
84 | .placeholders h4 {
85 | margin-bottom: 0;
86 | }
87 | .placeholder {
88 | margin-bottom: 20px;
89 | }
90 | .placeholder img {
91 | display: inline-block;
92 | border-radius: 50%;
93 | }
--------------------------------------------------------------------------------
/public/assets/css/signin.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding-top: 40px;
3 | padding-bottom: 40px;
4 | background-color: #eee;
5 | }
6 |
7 | .form-signin {
8 | max-width: 330px;
9 | padding: 15px;
10 | margin: 0 auto;
11 | }
12 | .form-signin .form-signin-heading,
13 | .form-signin .checkbox {
14 | margin-bottom: 10px;
15 | }
16 | .form-signin .checkbox {
17 | font-weight: normal;
18 | }
19 | .form-signin .form-control {
20 | position: relative;
21 | height: auto;
22 | -webkit-box-sizing: border-box;
23 | -moz-box-sizing: border-box;
24 | box-sizing: border-box;
25 | padding: 10px;
26 | font-size: 16px;
27 | }
28 | .form-signin .form-control:focus {
29 | z-index: 2;
30 | }
31 | .form-signin input[type="email"] {
32 | margin-bottom: -1px;
33 | border-bottom-right-radius: 0;
34 | border-bottom-left-radius: 0;
35 | }
36 | .form-signin input[type="password"] {
37 | margin-bottom: 10px;
38 | border-top-left-radius: 0;
39 | border-top-right-radius: 0;
40 | }
41 |
--------------------------------------------------------------------------------
/public/assets/fancybox/blank.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/morozovalexander/symfocommerce/06532086d6febd9d33c0b9abb0998dbca3dd31a8/public/assets/fancybox/blank.gif
--------------------------------------------------------------------------------
/public/assets/fancybox/fancybox_loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/morozovalexander/symfocommerce/06532086d6febd9d33c0b9abb0998dbca3dd31a8/public/assets/fancybox/fancybox_loading.gif
--------------------------------------------------------------------------------
/public/assets/fancybox/fancybox_loading@2x.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/morozovalexander/symfocommerce/06532086d6febd9d33c0b9abb0998dbca3dd31a8/public/assets/fancybox/fancybox_loading@2x.gif
--------------------------------------------------------------------------------
/public/assets/fancybox/fancybox_overlay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/morozovalexander/symfocommerce/06532086d6febd9d33c0b9abb0998dbca3dd31a8/public/assets/fancybox/fancybox_overlay.png
--------------------------------------------------------------------------------
/public/assets/fancybox/fancybox_sprite.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/morozovalexander/symfocommerce/06532086d6febd9d33c0b9abb0998dbca3dd31a8/public/assets/fancybox/fancybox_sprite.png
--------------------------------------------------------------------------------
/public/assets/fancybox/fancybox_sprite@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/morozovalexander/symfocommerce/06532086d6febd9d33c0b9abb0998dbca3dd31a8/public/assets/fancybox/fancybox_sprite@2x.png
--------------------------------------------------------------------------------
/public/assets/fancybox/jquery.mousewheel-3.0.6.pack.js:
--------------------------------------------------------------------------------
1 | /*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net)
2 | * Licensed under the MIT License (LICENSE.txt).
3 | *
4 | * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
5 | * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
6 | * Thanks to: Seamus Leahy for adding deltaX and deltaY
7 | *
8 | * Version: 3.0.6
9 | *
10 | * Requires: 1.2.2+
11 | */
12 | (function(d){function e(a){var b=a||window.event,c=[].slice.call(arguments,1),f=0,e=0,g=0,a=d.event.fix(b);a.type="mousewheel";b.wheelDelta&&(f=b.wheelDelta/120);b.detail&&(f=-b.detail/3);g=f;b.axis!==void 0&&b.axis===b.HORIZONTAL_AXIS&&(g=0,e=-1*f);b.wheelDeltaY!==void 0&&(g=b.wheelDeltaY/120);b.wheelDeltaX!==void 0&&(e=-1*b.wheelDeltaX/120);c.unshift(a,f,e,g);return(d.event.dispatch||d.event.handle).apply(this,c)}var c=["DOMMouseScroll","mousewheel"];if(d.event.fixHooks)for(var h=c.length;h;)d.event.fixHooks[c[--h]]=
13 | d.event.mouseHooks;d.event.special.mousewheel={setup:function(){if(this.addEventListener)for(var a=c.length;a;)this.addEventListener(c[--a],e,false);else this.onmousewheel=e},teardown:function(){if(this.removeEventListener)for(var a=c.length;a;)this.removeEventListener(c[--a],e,false);else this.onmousewheel=null}};d.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})})(jQuery);
--------------------------------------------------------------------------------
/public/assets/fonts/FontAwesome.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/morozovalexander/symfocommerce/06532086d6febd9d33c0b9abb0998dbca3dd31a8/public/assets/fonts/FontAwesome.otf
--------------------------------------------------------------------------------
/public/assets/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/morozovalexander/symfocommerce/06532086d6febd9d33c0b9abb0998dbca3dd31a8/public/assets/fonts/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/public/assets/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/morozovalexander/symfocommerce/06532086d6febd9d33c0b9abb0998dbca3dd31a8/public/assets/fonts/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/morozovalexander/symfocommerce/06532086d6febd9d33c0b9abb0998dbca3dd31a8/public/assets/fonts/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/public/assets/fonts/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/morozovalexander/symfocommerce/06532086d6febd9d33c0b9abb0998dbca3dd31a8/public/assets/fonts/fontawesome-webfont.woff2
--------------------------------------------------------------------------------
/public/assets/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/morozovalexander/symfocommerce/06532086d6febd9d33c0b9abb0998dbca3dd31a8/public/assets/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/public/assets/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/morozovalexander/symfocommerce/06532086d6febd9d33c0b9abb0998dbca3dd31a8/public/assets/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/morozovalexander/symfocommerce/06532086d6febd9d33c0b9abb0998dbca3dd31a8/public/assets/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/public/assets/fonts/glyphicons-halflings-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/morozovalexander/symfocommerce/06532086d6febd9d33c0b9abb0998dbca3dd31a8/public/assets/fonts/glyphicons-halflings-regular.woff2
--------------------------------------------------------------------------------
/public/assets/images/ajax-loader.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/morozovalexander/symfocommerce/06532086d6febd9d33c0b9abb0998dbca3dd31a8/public/assets/images/ajax-loader.gif
--------------------------------------------------------------------------------
/public/assets/js/ie10-viewport-bug-workaround.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * IE10 viewport hack for Surface/desktop Windows 8 bug
3 | * Copyright 2014 Twitter, Inc.
4 | * Licensed under the Creative Commons Attribution 3.0 Unported License. For
5 | * details, see http://creativecommons.org/licenses/by/3.0/.
6 | */
7 |
8 | // See the Getting Started docs for more information:
9 | // http://getbootstrap.com/getting-started/#support-ie10-width
10 |
11 | (function () {
12 | 'use strict';
13 | if (navigator.userAgent.match(/IEMobile\/10\.0/)) {
14 | var msViewportStyle = document.createElement('style')
15 | msViewportStyle.appendChild(
16 | document.createTextNode(
17 | '@-ms-viewport{width:auto!important}'
18 | )
19 | )
20 | document.querySelector('head').appendChild(msViewportStyle)
21 | }
22 | })();
--------------------------------------------------------------------------------
/public/assets/js/npm.js:
--------------------------------------------------------------------------------
1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment.
2 | require('../../js/transition.js')
3 | require('../../js/alert.js')
4 | require('../../js/button.js')
5 | require('../../js/carousel.js')
6 | require('../../js/collapse.js')
7 | require('../../js/dropdown.js')
8 | require('../../js/modal.js')
9 | require('../../js/tooltip.js')
10 | require('../../js/popover.js')
11 | require('../../js/scrollspy.js')
12 | require('../../js/tab.js')
13 | require('../../js/affix.js')
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/morozovalexander/symfocommerce/06532086d6febd9d33c0b9abb0998dbca3dd31a8/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.php:
--------------------------------------------------------------------------------
1 | handle($request);
26 | $response->send();
27 | $kernel->terminate($request, $response);
28 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # www.robotstxt.org/
2 | # www.google.com/support/webmasters/bin/answer.py?hl=en&answer=156449
3 |
4 | User-agent: *
5 | Disallow:
--------------------------------------------------------------------------------
/public/uploads/images/no_image_available.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/morozovalexander/symfocommerce/06532086d6febd9d33c0b9abb0998dbca3dd31a8/public/uploads/images/no_image_available.png
--------------------------------------------------------------------------------
/public/uploads/images/slide1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/morozovalexander/symfocommerce/06532086d6febd9d33c0b9abb0998dbca3dd31a8/public/uploads/images/slide1.jpg
--------------------------------------------------------------------------------
/public/uploads/images/slide2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/morozovalexander/symfocommerce/06532086d6febd9d33c0b9abb0998dbca3dd31a8/public/uploads/images/slide2.jpg
--------------------------------------------------------------------------------
/src/Controller/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/morozovalexander/symfocommerce/06532086d6febd9d33c0b9abb0998dbca3dd31a8/src/Controller/.gitignore
--------------------------------------------------------------------------------
/src/Controller/LayoutsUtilityController.php:
--------------------------------------------------------------------------------
1 | render('_partials/categories_menu.html.twig', [
21 | 'categories' => $category->getCategoriesForMenu()
22 | ]);
23 | }
24 |
25 | /**
26 | * Render manufacturers menu
27 | * @param Manufacturer $manufacturer
28 | * @return Response
29 | */
30 | public function manufacturersMenu(Manufacturer $manufacturer): Response
31 | {
32 | return $this->render('_partials/manufacturers_menu.html.twig', [
33 | 'manufacturers' => $manufacturer->getManufacturersForMenu()
34 | ]);
35 | }
36 |
37 | /**
38 | * Render top menu with static pages headers.
39 | * @param StaticPageRepository $staticPageRepository
40 | * @return Response
41 | */
42 | public function staticPagesMenu(StaticPageRepository $staticPageRepository): Response
43 | {
44 | $headers = $staticPageRepository->getHeaders();
45 | return $this->render('_partials/static_pages_menu.html.twig', [
46 | 'headers' => $headers
47 | ]);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/Controller/ProfileController.php:
--------------------------------------------------------------------------------
1 | getFavouriteProducts(
29 | $this->getParameter('products_pagination_count'),
30 | $request->query->getInt('page', 1)
31 | );
32 |
33 | return $this->render('profile/favourites.html.twig', [
34 | 'products' => $products,
35 | 'sortedby' => $pagesUtilities->getSortingParamName($request)
36 | ]);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/Controller/admin/AdminController.php:
--------------------------------------------------------------------------------
1 | render('admin/admin/index.html.twig');
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/Controller/admin/SettingsController.php:
--------------------------------------------------------------------------------
1 | render('admin/settings/index.html.twig', [
30 | 'settings' => $settingsRepository->findAll()[0]
31 | ]);
32 | }
33 |
34 | /**
35 | * @param Request $request
36 | * @param SettingsRepository $settingsRepository
37 | * @return JsonResponse
38 | * @Route("/settings_edit", methods={"POST"}, name="admin_settings_edit")
39 | */
40 | public function settingsEdit(Request $request, SettingsRepository $settingsRepository): JsonResponse
41 | {
42 | $em = $this->getDoctrine()->getManager();
43 | $entities = $settingsRepository->findAll();
44 | /**
45 | * @var Settings $settings
46 | */
47 | $settings = $entities[0];
48 |
49 |
50 | $editingSetting = $request->get('editing_setting');
51 | $newValue = $request->request->getBoolean('new_value');
52 |
53 | switch ($editingSetting) {
54 | case 'show_empty_categories';
55 | $settings->setShowEmptyCategories($newValue);
56 | break;
57 | case 'show_empty_manufacturers';
58 | $settings->setShowEmptyManufacturers($newValue);
59 | break;
60 | }
61 |
62 | $em->flush();
63 |
64 | return new JsonResponse(['success' => true]);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/DataFixtures/AppFixtures.php:
--------------------------------------------------------------------------------
1 | persist($product);
14 |
15 | $manager->flush();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/DataFixtures/ORM/CategoryFixtures.php:
--------------------------------------------------------------------------------
1 | getRandomCategoryTitles() as $title) {
21 | $category = new Category();
22 | $category->setName($title);
23 | $category->setSlug(Slugger::slugify($category->getName()));
24 | $category->setDescription($this->getLongTextContent());
25 | $category->setMetaKeys($this->getRandomMetaKeysString());
26 | $category->setMetaDescription($this->getRandomMetaDescriptionString());
27 | $manager->persist($category);
28 | }
29 |
30 | $manager->flush();
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/DataFixtures/ORM/LoadSettingsData.php:
--------------------------------------------------------------------------------
1 | setShowEmptyCategories(1);
16 | $settings->setShowEmptyManufacturers(1);
17 |
18 | $manager->persist($settings);
19 | $manager->flush();
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/DataFixtures/ORM/LoadUserData.php:
--------------------------------------------------------------------------------
1 | container = $container;
24 | }
25 |
26 | /**
27 | * {@inheritDoc}
28 | */
29 | public function load(ObjectManager $manager): void
30 | {
31 | $passwordEncoder = $this->container->get('security.password_encoder');
32 |
33 | //create admin
34 | $userAdmin = new User();
35 | $userAdmin->setFirstname('admin');
36 | $userAdmin->setLastname('admin');
37 | $userAdmin->setUsername('admin');
38 | $userAdmin->setPhone('1234567890');
39 | $userAdmin->setAddress('admin address');
40 | $userAdmin->setEnabled(true);
41 | $userAdmin->setRoles(['ROLE_ADMIN']);
42 | $userAdmin->setEmail('admin@example.com');
43 |
44 | $encodedPassword = $passwordEncoder->encodePassword($userAdmin, 'admin');
45 | $userAdmin->setPassword($encodedPassword);
46 |
47 | $manager->persist($userAdmin);
48 |
49 | //create test users
50 | for ($i = 1; $i < 50; $i++) {
51 | $user = new User();
52 | $user->setFirstname('Firstname' . $i);
53 | $user->setLastname('Lastname' . $i);
54 | $user->setPhone('1234567890 ' . $i);
55 | $user->setAddress('address ' . $i);
56 | $user->setUsername('user' . $i);
57 | $user->setEnabled(true);
58 | $user->setEmail('user' . $i . '@email.com');
59 |
60 | $encodedPassword = $passwordEncoder->encodePassword($user, 'user' . $i);
61 | $user->setPassword($encodedPassword);
62 | $manager->persist($user);
63 | }
64 |
65 | $manager->flush();
66 | }
67 | }
--------------------------------------------------------------------------------
/src/DataFixtures/ORM/ManufacturerFixtures.php:
--------------------------------------------------------------------------------
1 | getRandomManufacturerTitles() as $title) {
21 | $manufacturer = new Manufacturer();
22 | $manufacturer->setName($title);
23 | $manufacturer->setSlug(Slugger::slugify($manufacturer->getName()));
24 | $manufacturer->setDescription($this->getLongTextContent());
25 | $manufacturer->setMetaKeys($this->getRandomMetaKeysString());
26 | $manufacturer->setMetaDescription($this->getRandomMetaDescriptionString());
27 | $manager->persist($manufacturer);
28 | }
29 |
30 | $manager->flush();
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/DataFixtures/ORM/MeasuresFixtures.php:
--------------------------------------------------------------------------------
1 | getMeasureTitles() as $title) {
20 | $measure = new Measure();
21 | $measure->setName($title);
22 | $manager->persist($measure);
23 | }
24 |
25 | $manager->flush();
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/DataFixtures/ORM/NewsFixtures.php:
--------------------------------------------------------------------------------
1 | getRandomNewsTitles() as $title) {
21 | $news = new News();
22 | $news->setTitle($title);
23 | $news->setSlug(Slugger::slugify($news->getTitle()));
24 | $news->setText($this->getLongTextContent());
25 | $news->setMetaKeys($this->getRandomMetaKeysString());
26 | $news->setMetaDescription($this->getRandomMetaDescriptionString());
27 | $manager->persist($news);
28 | }
29 |
30 | $manager->flush();
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/DataFixtures/ORM/ProductFixtures.php:
--------------------------------------------------------------------------------
1 | getRepository(Category::class);
25 | $manufacturerRepository = $manager->getRepository(Manufacturer::class);
26 | $measureRepository = $manager->getRepository(Measure::class);
27 | //get all possible categories, manufacturers, measures
28 | $categories = $categoryRepository->findAll();
29 | $manufacturers = $manufacturerRepository->findAll();
30 | $measures = $measureRepository->findAll();
31 | for ($i = 1; $i <= 1000; $i++) {
32 | $product = new Product();
33 | $product->setName($this->getRandomProductName());
34 | $product->setSlug(Slugger::slugify($i . $product->getName()));
35 | $product->setDescription($this->getLongTextContent());
36 | //set random category or manufacturer
37 | $product->setCategory($categories[array_rand($categories)]);
38 | $product->setManufacturer($manufacturers[array_rand($manufacturers)]);
39 | $product->setMeasure($measures[array_rand($measures)]);
40 | $product->setMeasureQuantity(random_int(1, 10) * 100);
41 | $product->setQuantity(random_int(1, 10));
42 | $product->setPrice(random_int(1, 1000));
43 | $product->setMetaKeys($this->getRandomMetaKeysString());
44 | $product->setMetaDescription($this->getRandomMetaDescriptionString());
45 | $manager->persist($product);
46 | }
47 | $manager->flush();
48 | }
49 |
50 | /**
51 | * {@inheritdoc}
52 | */
53 | public function getDependencies(): array
54 | {
55 | return [
56 | CategoryFixtures::class,
57 | ManufacturerFixtures::class,
58 | MeasuresFixtures::class
59 | ];
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/DataFixtures/ORM/SlideFixtures.php:
--------------------------------------------------------------------------------
1 | setName('slide' . $i);
22 | $slide->setImage($slide->getName() . '.jpg');
23 | $slide->setSlideOrder($i);
24 | $slide->setEnabled(true);
25 | $manager->persist($slide);
26 | }
27 |
28 | $manager->flush();
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/DataFixtures/ORM/StaticPagesFixtures.php:
--------------------------------------------------------------------------------
1 | getAllStaticPageTitles() as $i => $title) {
21 | $staticPage = new StaticPage();
22 | $staticPage->setTitle($title);
23 | $staticPage->setOrderNum($i);
24 | $staticPage->setEnabled(true);
25 | $staticPage->setMetaKeys($this->getRandomMetaKeysString());
26 | $staticPage->setMetaDescription($this->getRandomMetaDescriptionString());
27 | $staticPage->setSlug(Slugger::slugify($staticPage->getTitle()));
28 | $staticPage->setContent($this->getLongTextContent());
29 | $manager->persist($staticPage);
30 | }
31 |
32 | $manager->flush();
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/Entity/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/morozovalexander/symfocommerce/06532086d6febd9d33c0b9abb0998dbca3dd31a8/src/Entity/.gitignore
--------------------------------------------------------------------------------
/src/Entity/Favourites.php:
--------------------------------------------------------------------------------
1 | id;
53 | }
54 |
55 | /**
56 | * @return \DateTime
57 | */
58 | public function getDate(): \DateTime
59 | {
60 | return $this->date;
61 | }
62 |
63 | /**
64 | * @param \DateTime $date
65 | * @return Favourites
66 | */
67 | public function setDate(\DateTime $date): Favourites
68 | {
69 | $this->date = $date;
70 | return $this;
71 | }
72 |
73 | /**
74 | * @return Product
75 | */
76 | public function getProduct(): Product
77 | {
78 | return $this->product;
79 | }
80 |
81 | /**
82 | * @param Product $product
83 | * @return Favourites
84 | */
85 | public function setProduct(Product $product): Favourites
86 | {
87 | $this->product = $product;
88 | return $this;
89 | }
90 |
91 | /**
92 | * @return User
93 | */
94 | public function getUser(): User
95 | {
96 | return $this->user;
97 | }
98 |
99 | /**
100 | * @param User $user
101 | * @return Favourites
102 | */
103 | public function setUser(User $user): Favourites
104 | {
105 | $this->user = $user;
106 | return $this;
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/Entity/Featured.php:
--------------------------------------------------------------------------------
1 | id;
45 | }
46 |
47 | /**
48 | * @param int $productOrder
49 | * @return Featured
50 | */
51 | public function setProductOrder(int $productOrder): Featured
52 | {
53 | $this->productOrder = $productOrder;
54 | return $this;
55 | }
56 |
57 | /**
58 | * @return int
59 | */
60 | public function getProductOrder(): int
61 | {
62 | return $this->productOrder;
63 | }
64 |
65 | /**
66 | * @param Product $product
67 | * @return Featured
68 | */
69 | public function setProduct(Product $product): Featured
70 | {
71 | $this->product = $product;
72 | return $this;
73 | }
74 |
75 | /**
76 | * @return Product
77 | */
78 | public function getProduct(): Product
79 | {
80 | return $this->product;
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/Entity/Image.php:
--------------------------------------------------------------------------------
1 | id;
48 | }
49 |
50 | /**
51 | * @param Product $product
52 | * @return Image
53 | */
54 | public function setProduct(Product $product): Image
55 | {
56 | $this->product = $product;
57 | return $this;
58 | }
59 |
60 | /**
61 | * @return Product
62 | */
63 | public function getProduct(): Product
64 | {
65 | return $this->product;
66 | }
67 |
68 | /**
69 | * @param string $image
70 | * @return Image
71 | */
72 | public function setImage(string $image): Image
73 | {
74 | $this->image = $image;
75 | return $this;
76 | }
77 |
78 | /**
79 | * @return string
80 | */
81 | public function getImage(): string
82 | {
83 | return $this->image;
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/Entity/ImageHolderInterface.php:
--------------------------------------------------------------------------------
1 | products = new ArrayCollection();
43 | }
44 |
45 | /**
46 | * @return string
47 | */
48 | public function __toString(): string
49 | {
50 | return $this->getName() ?? '';
51 | }
52 |
53 | /**
54 | * @return integer
55 | */
56 | public function getId(): int
57 | {
58 | return $this->id;
59 | }
60 |
61 | /**
62 | * @param string $name
63 | * @return Measure
64 | */
65 | public function setName(string $name): Measure
66 | {
67 | $this->name = $name;
68 | return $this;
69 | }
70 |
71 | /**
72 | * @return string|null
73 | */
74 | public function getName(): ?string
75 | {
76 | return $this->name;
77 | }
78 |
79 | /**
80 | * @param Product $products
81 | * @return Measure
82 | */
83 | public function addProduct(Product $products): Measure
84 | {
85 | $this->products[] = $products;
86 | return $this;
87 | }
88 |
89 | /**
90 | * @param Product $products
91 | * @return Measure
92 | */
93 | public function removeProduct(Product $products): Measure
94 | {
95 | $this->products->removeElement($products);
96 | return $this;
97 | }
98 |
99 | /**
100 | * @return Collection
101 | */
102 | public function getProducts(): ?Collection
103 | {
104 | return $this->products;
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/src/Entity/Settings.php:
--------------------------------------------------------------------------------
1 | id;
45 | }
46 |
47 | /**
48 | * @param boolean $showEmptyCategories
49 | * @return Settings
50 | */
51 | public function setShowEmptyCategories(bool $showEmptyCategories): Settings
52 | {
53 | $this->showEmptyCategories = $showEmptyCategories;
54 |
55 | return $this;
56 | }
57 |
58 | /**
59 | * @return boolean
60 | */
61 | public function getShowEmptyCategories(): bool
62 | {
63 | return $this->showEmptyCategories;
64 | }
65 |
66 | /**
67 | * @param boolean $showEmptyManufacturers
68 | * @return Settings
69 | */
70 | public function setShowEmptyManufacturers(bool $showEmptyManufacturers): Settings
71 | {
72 | $this->showEmptyManufacturers = $showEmptyManufacturers;
73 |
74 | return $this;
75 | }
76 |
77 | /**
78 | * @return boolean
79 | */
80 | public function getShowEmptyManufacturers(): bool
81 | {
82 | return $this->showEmptyManufacturers;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/EventListener/LocaleListener.php:
--------------------------------------------------------------------------------
1 | defaultLocale = $defaultLocale;
20 | }
21 |
22 | /**
23 | * @param GetResponseEvent $event
24 | */
25 | public function onKernelRequest(GetResponseEvent $event): void
26 | {
27 | $request = $event->getRequest();
28 | if (!$request->hasPreviousSession()) {
29 | return;
30 | }
31 |
32 | // try to see if the locale has been set as a _locale routing parameter
33 | if ($locale = $request->attributes->get('_locale')) {
34 | $request->getSession()->set('_locale', $locale);
35 | } else {
36 | // if no explicit locale has been set on this request, use one from the session
37 | $request->setLocale($request->getSession()->get('_locale', $this->defaultLocale));
38 | }
39 | }
40 |
41 | /**
42 | * @return array
43 | */
44 | public static function getSubscribedEvents(): array
45 | {
46 | // must be registered before the default Locale listener
47 | return [
48 | KernelEvents::REQUEST => [
49 | ['onKernelRequest', 17]
50 | ]
51 | ];
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/EventListener/UploadListener.php:
--------------------------------------------------------------------------------
1 | manager = $manager;
23 | }
24 |
25 | /**
26 | * @param PostUploadEvent $event
27 | * @return ResponseInterface
28 | */
29 | public function onUpload(PostUploadEvent $event): ResponseInterface
30 | {
31 | /** @var File $file */
32 | $file = $event->getFile();
33 |
34 | $image = new Image();
35 | /**@var Image $image */
36 | $image->setImage($file->getFilename());
37 |
38 | $this->manager->persist($image);
39 | $this->manager->flush();
40 |
41 | $response = $event->getResponse();
42 | $response['image_id'] = $image->getId();
43 |
44 | return $response;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/Form/Type/CategoryType.php:
--------------------------------------------------------------------------------
1 | add('name', TextType::class)
23 | ->add('slug', TextType::class)
24 | ->add('description', TextareaType::class)
25 | ->add('image', FileType::class, ['required' => false])
26 | ->add('metaKeys', TextType::class)
27 | ->add('metaDescription', TextType::class)
28 | ;
29 | }
30 |
31 | /**
32 | * @param OptionsResolver $resolver
33 | */
34 | public function configureOptions(OptionsResolver $resolver): void
35 | {
36 | $resolver->setDefaults([
37 | 'data_class' => Category::class
38 | ]);
39 | }
40 |
41 | /**
42 | * @return string
43 | */
44 | public function getBlockPrefix(): string
45 | {
46 | return 'eshop_shopbundle_category';
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/Form/Type/ManufacturerType.php:
--------------------------------------------------------------------------------
1 | add('name', TextType::class)
23 | ->add('slug', TextType::class)
24 | ->add('description', TextareaType::class)
25 | ->add('image', FileType::class, ['required' => false])
26 | ->add('metaKeys', TextType::class)
27 | ->add('metaDescription', TextType::class);
28 | }
29 |
30 | /**
31 | * @param OptionsResolver $resolver
32 | */
33 | public function configureOptions(OptionsResolver $resolver): void
34 | {
35 | $resolver->setDefaults([
36 | 'data_class' => Manufacturer::class
37 | ]);
38 | }
39 |
40 | /**
41 | * @return string
42 | */
43 | public function getBlockPrefix(): string
44 | {
45 | return 'eshop_shopbundle_manufacturer';
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/Form/Type/MeasureType.php:
--------------------------------------------------------------------------------
1 | add('name', TextType::class);
21 | }
22 |
23 | /**
24 | * @param OptionsResolver $resolver
25 | */
26 | public function configureOptions(OptionsResolver $resolver): void
27 | {
28 | $resolver->setDefaults(['data_class' => Measure::class]);
29 | }
30 |
31 | /**
32 | * @return string
33 | */
34 | public function getBlockPrefix(): string
35 | {
36 | return 'eshop_shopbundle_measure';
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/Form/Type/NewsType.php:
--------------------------------------------------------------------------------
1 | add('title', TextType::class)
22 | ->add('slug', TextType::class)
23 | ->add('text', TextareaType::class)
24 | ->add('metaKeys', TextType::class)
25 | ->add('metaDescription', TextType::class);
26 | }
27 |
28 | /**
29 | * @param OptionsResolver $resolver
30 | */
31 | public function configureOptions(OptionsResolver $resolver): void
32 | {
33 | $resolver->setDefaults(['data_class' => News::class]);
34 | }
35 |
36 | /**
37 | * @return string
38 | */
39 | public function getBlockPrefix(): string
40 | {
41 | return 'eshop_shopbundle_news';
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/Form/Type/OrdersType.php:
--------------------------------------------------------------------------------
1 | add('name', TextType::class)
23 | ->add('email', EmailType::class)
24 | ->add('phone', TextType::class)
25 | ->add('address', TextType::class)
26 | ->add('comment', TextareaType::class, ['required' => false]);
27 | }
28 |
29 | /**
30 | * @param OptionsResolver $resolver
31 | */
32 | public function configureOptions(OptionsResolver $resolver): void
33 | {
34 | $resolver->setDefaults(['data_class' => Orders::class]);
35 | }
36 |
37 | /**
38 | * @return string
39 | */
40 | public function getBlockPrefix(): string
41 | {
42 | return 'eshop_shopbundle_orders';
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/Form/Type/ProductType.php:
--------------------------------------------------------------------------------
1 | add('name', TextType::class)
28 | ->add('slug', TextType::class)
29 | ->add('description', TextareaType::class)
30 | ->add('price', NumberType::class)
31 | ->add('category', EntityType::class, [
32 | 'required' => true,
33 | 'multiple' => false,
34 | 'class' => Category::class,
35 | 'choice_label' => 'name'
36 | ])
37 | ->add('manufacturer', EntityType::class, [
38 | 'required' => true,
39 | 'multiple' => false,
40 | 'class' => Manufacturer::class,
41 | 'choice_label' => 'name'
42 | ])
43 | ->add('quantity', IntegerType::class)
44 | ->add('metaKeys', TextType::class)
45 | ->add('metaDescription', TextType::class)
46 | ->add('measure', EntityType::class, [
47 | 'required' => true,
48 | 'multiple' => false,
49 | 'expanded' => false,
50 | 'class' => Measure::class,
51 | 'choice_label' => 'name'
52 | ])
53 | ->add('measureQuantity', IntegerType::class);
54 | }
55 |
56 | /**
57 | * @param OptionsResolver $resolver
58 | */
59 | public function configureOptions(OptionsResolver $resolver): void
60 | {
61 | $resolver->setDefaults(['data_class' => Product::class]);
62 | }
63 |
64 | /**
65 | * @return string
66 | */
67 | public function getBlockPrefix(): string
68 | {
69 | return 'eshop_shopbundle_product';
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/Form/Type/RegistrationTypeExtension.php:
--------------------------------------------------------------------------------
1 | add('firstname', TextType::class,
25 | ['label' => 'registration.firstname', 'translation_domain' => 'ShopBundle'])
26 | ->add('lastname', TextType::class,
27 | ['label' => 'registration.lastname', 'translation_domain' => 'ShopBundle'])
28 | ->add('phone', TextType::class,
29 | ['label' => 'registration.phone', 'translation_domain' => 'ShopBundle'])
30 | ->add('address', TextareaType::class,
31 | ['label' => 'registration.address', 'translation_domain' => 'ShopBundle']);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/Form/Type/SlideType.php:
--------------------------------------------------------------------------------
1 | add('name', TextType::class)
24 | ->add('enabled', CheckboxType::class)
25 | ->add('image', FileType::class, ['required' => false])
26 | ->add('slideOrder', IntegerType::class);
27 | }
28 |
29 | /**
30 | * @param OptionsResolver $resolver
31 | */
32 | public function configureOptions(OptionsResolver $resolver): void
33 | {
34 | $resolver->setDefaults([
35 | 'data_class' => Slide::class
36 | ]);
37 | }
38 |
39 | /**
40 | * @return string
41 | */
42 | public function getBlockPrefix(): string
43 | {
44 | return 'eshop_shopbundle_slide';
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/Form/Type/StaticPageType.php:
--------------------------------------------------------------------------------
1 | add('title', TextType::class)
24 | ->add('slug', TextType::class)
25 | ->add('enabled', CheckboxType::class)
26 | ->add('orderNum', IntegerType::class)
27 | ->add('metaKeys', TextType::class)
28 | ->add('metaDescription', TextType::class)
29 | ->add('content', TextareaType::class);
30 | }
31 |
32 | /**
33 | * @param OptionsResolver $resolver
34 | */
35 | public function configureOptions(OptionsResolver $resolver): void
36 | {
37 | $resolver->setDefaults(['data_class' => StaticPage::class]);
38 | }
39 |
40 | /**
41 | * @return string
42 | */
43 | public function getBlockPrefix(): string
44 | {
45 | return 'eshop_shopbundle_staticpage';
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/Kernel.php:
--------------------------------------------------------------------------------
1 | getProjectDir().'/config/bundles.php';
21 | foreach ($contents as $class => $envs) {
22 | if ($envs[$this->environment] ?? $envs['all'] ?? false) {
23 | yield new $class();
24 | }
25 | }
26 | }
27 |
28 | public function getProjectDir(): string
29 | {
30 | return \dirname(__DIR__);
31 | }
32 |
33 | protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader): void
34 | {
35 | $container->addResource(new FileResource($this->getProjectDir().'/config/bundles.php'));
36 | $container->setParameter('container.dumper.inline_class_loader', \PHP_VERSION_ID < 70400 || $this->debug);
37 | $container->setParameter('container.dumper.inline_factories', true);
38 | $confDir = $this->getProjectDir().'/config';
39 |
40 | $loader->load($confDir.'/{packages}/*'.self::CONFIG_EXTS, 'glob');
41 | $loader->load($confDir.'/{packages}/'.$this->environment.'/*'.self::CONFIG_EXTS, 'glob');
42 | $loader->load($confDir.'/{services}'.self::CONFIG_EXTS, 'glob');
43 | $loader->load($confDir.'/{services}_'.$this->environment.self::CONFIG_EXTS, 'glob');
44 | }
45 |
46 | protected function configureRoutes(RouteCollectionBuilder $routes): void
47 | {
48 | $confDir = $this->getProjectDir().'/config';
49 |
50 | $routes->import($confDir.'/{routes}/'.$this->environment.'/*'.self::CONFIG_EXTS, '/', 'glob');
51 | $routes->import($confDir.'/{routes}/*'.self::CONFIG_EXTS, '/', 'glob');
52 | $routes->import($confDir.'/{routes}'.self::CONFIG_EXTS, '/', 'glob');
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/Repository/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/morozovalexander/symfocommerce/06532086d6febd9d33c0b9abb0998dbca3dd31a8/src/Repository/.gitignore
--------------------------------------------------------------------------------
/src/Repository/FavouritesRepository.php:
--------------------------------------------------------------------------------
1 | getEntityManager()
41 | ->createQueryBuilder()
42 | ->select('count(f.id)')
43 | ->from(Favourites::class, 'f')
44 | ->innerJoin('f.user', 'u')
45 | ->innerJoin('f.product', 'p')
46 | ->where('u = :user')
47 | ->andWhere('p.id = :product_id')
48 | ->setParameters([
49 | 'product_id' => $productId,
50 | 'user' => $user
51 | ]);
52 |
53 | if ($qb->getQuery()->getSingleScalarResult()) {
54 | return true;
55 | }
56 |
57 | return false;
58 | }
59 |
60 | /**
61 | * @param User $user
62 | * @param int[] $productIds
63 | * @return string[]
64 | */
65 | public function selectLikedProductIds(User $user, array $productIds): array
66 | {
67 | if (!count($productIds)) {
68 | return [];
69 | }
70 |
71 | $qb = $this->getEntityManager()->createQueryBuilder();
72 | $qb->select('p.id')
73 | ->from(Favourites::class, 'f')
74 | ->innerJoin('f.user', 'u')
75 | ->innerJoin('f.product', 'p')
76 | ->andWhere('u = :user')
77 | ->andWhere($qb->expr()->In('p.id', ':product_ids'))
78 | ->setParameter('user', $user)
79 | ->setParameter('product_ids', $productIds);
80 | $result = $qb->getQuery()->getScalarResult();
81 |
82 | return array_map(function ($result) {
83 | return $result['id'] ?? null;
84 | },
85 | $result
86 | );
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/src/Repository/FeaturedRepository.php:
--------------------------------------------------------------------------------
1 | getEntityManager()
34 | ->createQueryBuilder()
35 | ->select('f.productOrder')
36 | ->from(Featured::class, 'f')
37 | ->addOrderBy('f.productOrder', 'DESC')
38 | ->setMaxResults(1)
39 | ->getQuery()
40 | ->getOneOrNullResult();
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/Repository/ImageRepository.php:
--------------------------------------------------------------------------------
1 | getEntityManager()
38 | ->createQueryBuilder()
39 | ->select('n')
40 | ->from(News::class, 'n')
41 | ->where('n.slug = :slug')
42 | ->setParameter('slug', $slug)
43 | ->getQuery()
44 | ->getSingleResult();
45 | }
46 |
47 | /**
48 | * query for admin paginator
49 | *
50 | * @return QueryBuilder
51 | */
52 | public function getAllNewsAdminQB(): QueryBuilder
53 | {
54 | $qb = $this->getEntityManager()
55 | ->createQueryBuilder()
56 | ->select('n')
57 | ->from(News::class, 'n');
58 |
59 | return $qb;
60 | }
61 |
62 | /**
63 | * @return News|null
64 | * @throws NonUniqueResultException
65 | */
66 | public function getLastNews(): ?News
67 | {
68 | return $this->getEntityManager()
69 | ->createQueryBuilder()
70 | ->select('n')
71 | ->from(News::class, 'n')
72 | ->orderBy('n.date', 'DESC')
73 | ->setMaxResults(1)
74 | ->getQuery()
75 | ->getOneOrNullResult();
76 | }
77 |
78 | /**
79 | * Create query for paginator
80 | *
81 | * @return QueryBuilder
82 | */
83 | public function getNewsQB(): QueryBuilder
84 | {
85 | return $this->getEntityManager()
86 | ->createQueryBuilder()
87 | ->select('a')
88 | ->from(News::class, 'a')
89 | ->orderBy('a.date', 'DESC');
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/Repository/OrderProductRepository.php:
--------------------------------------------------------------------------------
1 | getEntityManager()
36 | ->createQueryBuilder()
37 | ->select(['o', 'u'])
38 | ->from(Orders::class, 'o')
39 | ->leftJoin('o.user', 'u')
40 | ->addOrderBy('o.date', 'DESC');
41 |
42 | return $qb;
43 | }
44 |
45 | /**
46 | * return query to get users orders
47 | *
48 | * @param User $user
49 | * @return QueryBuilder
50 | */
51 | public function getUserOrdersAdminQB(User $user): QueryBuilder
52 | {
53 | $qb = $this->getEntityManager()
54 | ->createQueryBuilder()
55 | ->select('o')
56 | ->from(Orders::class, 'o')
57 | ->innerJoin('o.user', 'ou')
58 | ->where('ou = :user')
59 | ->addOrderBy('o.date', 'DESC')
60 | ->setParameter('user', $user);
61 |
62 | return $qb;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/Repository/SettingsRepository.php:
--------------------------------------------------------------------------------
1 | getEntityManager()
33 | ->createQueryBuilder()
34 | ->select('a.title, a.slug')
35 | ->from(StaticPage::class, 'a')
36 | ->where('a.enabled = 1')
37 | ->addOrderBy('a.orderNum', 'ASC')
38 | ->getQuery()
39 | ->getResult();
40 | }
41 |
42 | /**
43 | * @param $slug
44 | * @return StaticPage|null
45 | * @throws NonUniqueResultException
46 | */
47 | public function findBySlug(string $slug): ?StaticPage
48 | {
49 | return $this->getEntityManager()
50 | ->createQueryBuilder()
51 | ->select('a')
52 | ->from(StaticPage::class, 'a')
53 | ->where('a.slug = :slug')
54 | ->setParameter('slug', $slug)
55 | ->getQuery()
56 | ->getOneOrNullResult();
57 | }
58 |
59 | /**
60 | * @return array
61 | */
62 | public function getArrayForSitemap(): array
63 | {
64 | return $this->createQueryBuilder('sp')
65 | ->select('sp.slug')
66 | ->getQuery()
67 | ->getArrayResult();
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/Repository/UserRepository.php:
--------------------------------------------------------------------------------
1 | getEntityManager()
32 | ->createQueryBuilder()
33 | ->select(['u', 'uo'])
34 | ->from(User::class, 'u')
35 | ->leftJoin('u.orders', 'uo')
36 | ->where('u.roles NOT LIKE :roles')
37 | ->setParameter('roles', '%"ROLE_ADMIN"%');
38 |
39 | return $qb;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/Service/Cart.php:
--------------------------------------------------------------------------------
1 | productRepository = $productRepository;
20 | }
21 |
22 | /**
23 | * @param int[] $quantityByProductId
24 | * @return CartContents
25 | */
26 | public function getCartContents(array $quantityByProductId): CartContents
27 | {
28 | $positions = [];
29 | $totalSum = 0.0;
30 | $productsById = $this->findProductsByIds(array_keys($quantityByProductId));
31 |
32 | foreach ($quantityByProductId as $productId => $productQuantity) {
33 | if (!isset($productsById[$productId])) {
34 | continue;
35 | }
36 | $product = $productsById[$productId];
37 | $quantity = abs($productQuantity);
38 | $price = $product->getPrice();
39 | $sum = $price * $quantity;
40 |
41 | $positions[] = new CartProductPosition($product, $quantity, $price, $sum);
42 | $totalSum += $sum;
43 | }
44 | return new CartContents($positions, $totalSum);
45 | }
46 |
47 | /**
48 | * @param int[] $productIds
49 | * @return Product[] indexed by product id
50 | */
51 | public function findProductsByIds(array $productIds = []): array
52 | {
53 | $products = $this->productRepository->findBy(['id' => $productIds]);
54 | $productsById = [];
55 | array_map(function ($product) use (&$productsById) {
56 | $productsById[$product->getId()] = $product;
57 | },
58 | $products);
59 | return $productsById;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/Service/Category.php:
--------------------------------------------------------------------------------
1 | categoryRepository = $categoryRepository;
24 | $this->settingsService = $settingsService;
25 | }
26 |
27 | /**
28 | * @return CategoryEntity[]
29 | */
30 | public function getCategoriesForMenu(): array
31 | {
32 | return $this->categoryRepository->getAllCategories(
33 | $this->settingsService->getShowEmptyCategories()
34 | );
35 | }
36 | }
--------------------------------------------------------------------------------
/src/Service/EmailNotifier.php:
--------------------------------------------------------------------------------
1 | mailer = $mailer;
35 | $this->router = $router;
36 | $this->templating = $templating;
37 | }
38 |
39 | /**
40 | * @param array $parametersArray
41 | * @throws LoaderError
42 | * @throws RuntimeError
43 | * @throws SyntaxError
44 | */
45 | public function handleNotification(array $parametersArray): void
46 | {
47 | $event = $parametersArray['event'];
48 | if ($event === 'new_order') {
49 | $this->sendNewOrderNotification($parametersArray);
50 | }
51 | }
52 |
53 | /**
54 | * @param $parametersArray array
55 | * @throws LoaderError
56 | * @throws RuntimeError
57 | * @throws SyntaxError
58 | */
59 | private function sendNewOrderNotification(array $parametersArray): void
60 | {
61 | $orderId = $parametersArray['order_id'];
62 | $to = $parametersArray['admin_email'];
63 | $subject = 'new order notification';
64 |
65 | //url generation
66 | $url = $this->router->generate(
67 | 'admin_order_show',
68 | ['id' => $orderId],
69 | true
70 | );
71 |
72 | $message = (new \Swift_Message($subject))
73 | ->setFrom(self::FROM_EMAIL)
74 | ->setTo($to)
75 | ->setBody(
76 | $this->templating->render(
77 | 'mail/order_notification_email.txt.twig', [
78 | 'subject' => $subject,
79 | 'url' => $url
80 | ]
81 | ));
82 |
83 | $this->mailer->send($message);
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/Service/FileUploader.php:
--------------------------------------------------------------------------------
1 | targetDir = $targetDir;
19 | }
20 |
21 | /**
22 | * Upload new file to server
23 | *
24 | * @param UploadedFile $file
25 | * @return string
26 | */
27 | public function upload(UploadedFile $file): string
28 | {
29 | $fileName = md5(uniqid('random', true)) . '.' . $file->guessExtension();
30 | $file->move($this->targetDir, $fileName);
31 |
32 | return $fileName;
33 | }
34 |
35 | /**
36 | * Remove file from server
37 | *
38 | * @param string $fileName
39 | * @return bool
40 | */
41 | public function removeUpload(string $fileName): bool
42 | {
43 | $fullPath = $this->targetDir . DIRECTORY_SEPARATOR . $fileName;
44 |
45 | if (is_file($fullPath)) {
46 | return unlink($fullPath);
47 | }
48 | return false;
49 | }
50 |
51 | /**
52 | * @return string
53 | */
54 | public function getTargetDir(): string
55 | {
56 | return $this->targetDir;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/Service/Manufacturer.php:
--------------------------------------------------------------------------------
1 | manufacturerRepository = $manufacturerRepository;
24 | $this->settingsService = $settingsService;
25 | }
26 |
27 | /**
28 | * @return ManufacturerEntity[]
29 | */
30 | public function getManufacturersForMenu(): array
31 | {
32 | return $this->manufacturerRepository->getAllManufacturers(
33 | $this->settingsService->getShowEmptyManufacturers()
34 | );
35 | }
36 | }
--------------------------------------------------------------------------------
/src/Service/News.php:
--------------------------------------------------------------------------------
1 | newsRepository = $newsRepository;
27 | $this->paginator = $paginator;
28 | }
29 |
30 | /**
31 | * @return NewsEntity
32 | * @throws NonUniqueResultException
33 | */
34 | public function getLastNews(): NewsEntity
35 | {
36 | return $this->newsRepository->getLastNews();
37 | }
38 |
39 | /**
40 | * @param int $limit
41 | * @param int $page
42 | * @return Iterable|News[]
43 | */
44 | public function getNews(int $limit, int $page = 1): SlidingPaginationInterface
45 | {
46 | $query = $this->newsRepository->getNewsQB();
47 | return $this->paginator
48 | ->paginate($query, $page, $limit);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/Service/SettingsService.php:
--------------------------------------------------------------------------------
1 | settings = $settingsRepository->findAll()[0];
19 | }
20 |
21 | /**
22 | * @return bool
23 | */
24 | public function getShowEmptyManufacturers(): bool
25 | {
26 | return $this->settings->getShowEmptyManufacturers();
27 | }
28 |
29 | /**
30 | * @return bool
31 | */
32 | public function getShowEmptyCategories(): bool
33 | {
34 | return $this->settings->getShowEmptyCategories();
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/Service/Slides.php:
--------------------------------------------------------------------------------
1 | slideRepository = $slideRepository;
18 | }
19 |
20 | /**
21 | * @param bool $enabled
22 | * @param bool $asc
23 | * @return array
24 | */
25 | public function getSlides(bool $enabled = true, bool $asc = true): array
26 | {
27 | $order = $asc ? 'ASC' : 'DESC';
28 | return $this->slideRepository->findBy(
29 | ['enabled' => $enabled],
30 | ['slideOrder' => $order]
31 | );
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/Service/Structs/CartContents.php:
--------------------------------------------------------------------------------
1 | positions = $positions;
19 | $this->totalSum = $totalSum;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/Service/Structs/CartProductPosition.php:
--------------------------------------------------------------------------------
1 | product = $product;
27 | $this->quantity = $quantity;
28 | $this->price = $price;
29 | $this->sum = $sum;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/Service/Structs/ProductLikeResult.php:
--------------------------------------------------------------------------------
1 | message = $message;
22 | $this->success = $success;
23 | $this->isLiked = $isLiked;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/Twig/RawDescriptionExtension.php:
--------------------------------------------------------------------------------
1 | ['html']])
17 | ];
18 | }
19 |
20 | /**
21 | * @param string $descr
22 | * @return string
23 | */
24 | public function rawdescrFilter(string $descr): string
25 | {
26 | return $descr;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/Utils/Slugger.php:
--------------------------------------------------------------------------------
1 | {{ 'categories.menu.header'|trans }}
3 |
4 | {% for category in categories %}
5 |
8 | {% endfor %}
9 |
10 |
--------------------------------------------------------------------------------
/templates/_partials/category_preview.html.twig:
--------------------------------------------------------------------------------
1 | {% trans_default_domain 'ShopBundle' %}
2 |
23 |
--------------------------------------------------------------------------------
/templates/_partials/last_seen_products.html.twig:
--------------------------------------------------------------------------------
1 | {% trans_default_domain 'ShopBundle' %}
2 | {{ 'layout.lastseen.header'|trans }}
3 |
4 | {% for product in products %}
5 | {{ include('_partials/product_preview.html.twig') }}
6 | {% endfor %}
7 |
8 |
--------------------------------------------------------------------------------
/templates/_partials/manufacturers_menu.html.twig:
--------------------------------------------------------------------------------
1 | {% trans_default_domain 'ShopBundle' %}
2 | {{ 'manufacturers.menu.header'|trans }}
3 |
4 | {% for manufacturer in manufacturers %}
5 |
8 | {% endfor %}
9 |
10 |
--------------------------------------------------------------------------------
/templates/_partials/navbar_auth_block.html.twig:
--------------------------------------------------------------------------------
1 | {% trans_default_domain 'ShopBundle' %}
2 |
3 | {% if is_granted('IS_AUTHENTICATED_REMEMBERED') %}
4 | {% if is_granted('ROLE_ADMIN') %}
5 |
6 |
8 | {{ 'layout.navbar.admin'|trans }}
9 |
10 |
14 |
15 | {% else %}
16 |
17 |
19 | {{ 'layout.navbar.loggedas'|trans }} {{ app.user.username }}
20 |
21 |
24 |
25 | {% endif %}
26 | {% else %}
27 |
28 |
30 | {{ 'layout.navbar.login'|trans }}
31 |
32 |
36 |
37 | {% endif %}
38 |
--------------------------------------------------------------------------------
/templates/_partials/product_preview.html.twig:
--------------------------------------------------------------------------------
1 | {% trans_default_domain 'ShopBundle' %}
2 |
30 |
--------------------------------------------------------------------------------
/templates/_partials/slides_block.html.twig:
--------------------------------------------------------------------------------
1 | {% trans_default_domain 'ShopBundle' %}
2 |
42 |
43 |
--------------------------------------------------------------------------------
/templates/_partials/static_pages_menu.html.twig:
--------------------------------------------------------------------------------
1 | {% for header in headers %}
2 |
3 |
4 | {{ header.title }}
5 |
6 |
7 | {% endfor %}
8 |
--------------------------------------------------------------------------------
/templates/admin/_partials/admin_menu.html.twig:
--------------------------------------------------------------------------------
1 | {% set route = app.request.get('_route') %}
2 |
3 |
11 |
12 |
26 |
27 |
43 |
--------------------------------------------------------------------------------
/templates/admin/_partials/index_product_item.html.twig:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ product.name }}
4 | |
5 |
6 |
7 | {{ product.category }}
8 |
9 | |
10 |
11 |
12 | {{ product.manufacturer }}
13 |
14 | |
15 | {{ product.price }} |
16 |
17 | {{ include('admin/_partials/product_images.html.twig') }}
18 | |
19 | {{ product.quantity }} |
20 |
21 | {{ 'show'|trans }}
22 | {{ 'edit'|trans }}
23 | {% if product.featured|length %}
24 | {{ FEATURED }}
25 | {% else %}
26 | {{ NOT_FEATURED }}
27 | {% endif %}
28 | |
29 |
30 |
--------------------------------------------------------------------------------
/templates/admin/_partials/init_summernote.js.twig:
--------------------------------------------------------------------------------
1 | $('.summernote').summernote({
2 | height: {{ height }},
3 | toolbar: [
4 | ['style', ['style']],
5 | ['font', ['bold', 'italic', 'underline', 'clear']],
6 | ['fontname', ['fontname']],
7 | ['fontsize', ['fontsize']],
8 | ['color', ['color']],
9 | ['para', ['ul', 'ol', 'paragraph']],
10 | ['height', ['height']],
11 | ['table', ['table']],
12 | ['insert', ['link', 'hr']], //hide picture button
13 | ['view', ['fullscreen', 'codeview']],
14 | ['help', ['help']]
15 | ]
16 | });
17 |
--------------------------------------------------------------------------------
/templates/admin/_partials/product_images.html.twig:
--------------------------------------------------------------------------------
1 | {% if product.images|length %}
2 | {% for image in product.images|slice(0, 3) %}
3 |
4 |
5 |
6 | {% endfor %} ...
7 | {% else %}
8 | {{ 'no photos'|trans }}
9 | {% endif %}
10 |
--------------------------------------------------------------------------------
/templates/admin/_partials/slug_generation.js.twig:
--------------------------------------------------------------------------------
1 | $('.generate-slug').on('click', function (e) {
2 | e.preventDefault();
3 | //get field value
4 | var sluggableInput = $('.sluggable-input').val();
5 | var slugOutput = $('.sluggable-output');
6 |
7 | //generate slug
8 | var slug = getSlug(sluggableInput, {
9 | custom: {
10 | '%': ' percent '
11 | },
12 | uric: true
13 | });
14 | //record to slug input
15 | slugOutput.val(slug);
16 | });
17 |
--------------------------------------------------------------------------------
/templates/admin/admin/index.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'admin/layout.html.twig' %}
2 |
3 | {% block page_content -%}
4 | {{ 'Hello, choose a category!'|trans }}
5 | {% endblock page_content %}
6 |
--------------------------------------------------------------------------------
/templates/admin/measure/edit.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'admin/layout.html.twig' %}
2 | {% form_theme edit_form 'bootstrap_3_horizontal_layout.html.twig' %}
3 |
4 | {% block page_content -%}
5 | {{ 'Measure edit'|trans }}
6 |
7 | {% for flashMessage in app.session.flashbag.get('notice') %}
8 |
9 | {{ flashMessage }}
10 |
11 | {% endfor %}
12 |
13 | {{ form_start(edit_form) }}
14 | {{ form_widget(edit_form) }}
15 |
21 | {{ form_end(edit_form) }}
22 |
23 |
38 | {% endblock page_content %}
39 |
--------------------------------------------------------------------------------
/templates/admin/measure/index.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'admin/layout.html.twig' %}
2 |
3 | {% block title %}
4 | {{ 'Measure list'|trans }} - {{ 'Administration panel'|trans }}
5 | {% endblock title %}
6 |
7 | {% block page_content -%}
8 | {{ 'Measure list'|trans }}
9 |
10 |
11 |
12 | {{ 'Create a new measure'|trans }}
13 |
14 |
15 |
38 | {% endblock page_content %}
39 |
--------------------------------------------------------------------------------
/templates/admin/measure/new.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'admin/layout.html.twig' %}
2 | {% form_theme form 'bootstrap_3_horizontal_layout.html.twig' %}
3 |
4 | {% block page_content -%}
5 | {{ 'Measure creation'|trans }}
6 |
7 | {{ form_start(form) }}
8 | {{ form_widget(form) }}
9 |
15 | {{ form_end(form) }}
16 |
17 |
18 | {{ 'Back to the list'|trans }}
19 |
20 | {% endblock page_content %}
21 |
--------------------------------------------------------------------------------
/templates/admin/measure/show.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'admin/layout.html.twig' %}
2 |
3 | {% block page_content -%}
4 | {{ 'Measure'|trans }}
5 |
6 |
7 |
8 |
9 | {{ 'Name'|trans }} |
10 | {{ entity.name }} |
11 |
12 |
13 |
14 |
15 |
33 | {% endblock page_content %}
34 |
--------------------------------------------------------------------------------
/templates/admin/news/index.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'admin/layout.html.twig' %}
2 |
3 | {% block title %}
4 | {{ 'News list'|trans }} - {{ 'Administration panel'|trans }}
5 | {% endblock title %}
6 |
7 | {% block page_content -%}
8 | {{ 'News list'|trans }}
9 |
10 |
11 |
12 | {{ 'Create a new news'|trans }}
13 |
14 |
15 |
16 |
17 |
18 | {{ knp_pagination_sortable(entities, 'Title'|trans, 'n.title') }} |
19 | {{ knp_pagination_sortable(entities, 'Text'|trans, 'n.text') }} |
20 | {{ 'Actions'|trans }} |
21 |
22 |
23 |
24 | {% for entity in entities %}
25 |
26 |
27 |
28 | {{ entity.title }}
29 |
30 | |
31 |
32 | {{ entity.text|slice(0, 130) }}...
33 | |
34 |
35 | {{ 'show'|trans }}
36 | {{ 'edit'|trans }}
37 | |
38 |
39 | {% endfor %}
40 |
41 |
42 |
43 |
44 | {{ knp_pagination_render(entities) }}
45 |
46 |
47 | {% endblock page_content %}
48 |
--------------------------------------------------------------------------------
/templates/admin/news/show.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'admin/layout.html.twig' %}
2 |
3 | {% block page_content -%}
4 | {{ 'News'|trans }}
5 |
6 |
7 |
8 | {{ 'Title'|trans }} |
9 | {{ entity.title }} |
10 |
11 |
12 | {{ 'Slug'|trans }} |
13 | {{ entity.slug }} |
14 |
15 |
16 | {{ 'Text'|trans }} |
17 |
18 | {{ entity.text|rawdescr|nl2br }}
19 | |
20 |
21 |
22 | {{ 'Meta keys'|trans }} |
23 | {{ entity.metaKeys }} |
24 |
25 |
26 | {{ 'Meta description'|trans }} |
27 | {{ entity.metaDescription }} |
28 |
29 |
30 |
31 |
32 |
50 | {% endblock page_content %}
51 |
--------------------------------------------------------------------------------
/templates/admin/orders/index.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'admin/layout.html.twig' %}
2 |
3 | {% block title %}
4 | {{ 'Orders list'|trans }} - {{ 'Administration panel'|trans }}
5 | {% endblock title %}
6 |
7 | {% block page_content -%}
8 | {{ 'Orders list'|trans }}
9 | {% if orders|length %}
10 |
11 |
12 |
13 | {{ 'Order No'|trans }} # |
14 | {{ knp_pagination_sortable(orders, 'Client name'|trans, 'o.name') }} |
15 | {{ knp_pagination_sortable(orders, 'User'|trans, 'u.username') }} |
16 | {{ knp_pagination_sortable(orders, 'Order totalsum'|trans, 'o.sum') }} |
17 | {{ knp_pagination_sortable(orders, 'Order date'|trans, 'o.date') }} |
18 | {{ 'Actions'|trans }} |
19 |
20 |
21 |
22 | {% for order in orders %}
23 |
24 |
25 | {{ order.id }}
26 | |
27 |
28 | {{ order.name }}
29 | |
30 |
31 | {% if order.user %}
32 | {{ order.user.username }}
33 | {% else %}
34 | {{ 'not registered'|trans }}
35 | {% endif %}
36 | |
37 |
38 | {{ order.sum }} {{ 'currency'|trans }}
39 | |
40 |
41 | {{ order.date|date('Y-m-d H:i') }}
42 | |
43 |
44 | {{ 'Show'|trans }}
45 | |
46 |
47 | {% endfor %}
48 |
49 |
50 | {% else %}
51 | {{ 'No orders yet'|trans }}
52 | {% endif %}
53 |
54 |
55 | {{ knp_pagination_render(orders) }}
56 |
57 |
58 | {% endblock page_content %}
59 |
--------------------------------------------------------------------------------
/templates/admin/product/deleted.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'admin/layout.html.twig' %}
2 |
3 | {% block page_content -%}
4 | {{ 'Product'|trans }}
5 |
6 | {{ 'Product deleted'|trans }}
7 |
8 |
15 | {% endblock page_content %}
16 |
--------------------------------------------------------------------------------
/templates/admin/slide/edit.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'admin/layout.html.twig' %}
2 | {% form_theme edit_form 'bootstrap_3_horizontal_layout.html.twig' %}
3 |
4 | {% block page_content -%}
5 | {{ 'Slide edit'|trans }}
6 |
7 | {% for flashMessage in app.session.flashbag.get('notice') %}
8 |
9 | {{ flashMessage }}
10 |
11 | {% endfor %}
12 |
13 | {{ form_start(edit_form) }}
14 | {{ form_widget(edit_form) }}
15 |
21 | {{ form_end(edit_form) }}
22 |
23 |
38 | {% endblock page_content %}
39 |
--------------------------------------------------------------------------------
/templates/admin/slide/new.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'admin/layout.html.twig' %}
2 | {% form_theme form 'bootstrap_3_horizontal_layout.html.twig' %}
3 |
4 | {% block page_content -%}
5 | {{ 'Slide creation'|trans }}
6 |
7 | {{ form_start(form) }}
8 | {{ form_widget(form) }}
9 |
15 | {{ form_end(form) }}
16 |
17 |
18 | {{ 'Back to the list'|trans }}
19 |
20 | {% endblock page_content %}
21 |
--------------------------------------------------------------------------------
/templates/admin/slide/show.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'admin/layout.html.twig' %}
2 |
3 | {% block stylesheets %}
4 | {{ parent() }}
5 |
7 | {% endblock stylesheets %}
8 |
9 | {% block page_content -%}
10 | {{ 'Slide'|trans }}
11 |
12 |
13 |
14 |
15 | {{ 'Name'|trans }} |
16 | {{ entity.name }} |
17 |
18 |
19 | {{ 'Enabled'|trans }} |
20 |
21 | {% if entity.enabled %}
22 | {{ 'yes'|trans }}
23 | {% else %}
24 | {{ 'no'|trans }}
25 | {% endif %}
26 | |
27 |
28 |
29 | {{ 'Image'|trans }} |
30 |
31 | {% if entity.image %}
32 |
33 |
34 |
35 | {% else %}
36 | {{ 'no photos'|trans }}
37 | {% endif %}
38 | |
39 |
40 |
41 | {{ 'Slide order'|trans }} |
42 | {{ entity.slideOrder }} |
43 |
44 |
45 |
46 |
47 |
65 | {% endblock page_content %}
66 |
67 | {% block javascripts %}
68 | {{ parent() }}
69 |
71 |
72 |
77 | {% endblock javascripts %}
78 |
--------------------------------------------------------------------------------
/templates/admin/static_page/index.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'admin/layout.html.twig' %}
2 |
3 | {% block title %}
4 | {{ 'Static pages'|trans }} - {{ 'Administration panel'|trans }}
5 | {% endblock title %}
6 |
7 | {% block page_content -%}
8 | {{ 'Static pages'|trans }}
9 |
10 |
11 |
12 | {{ 'Create a new page'|trans }}
13 |
14 |
15 |
16 |
17 |
18 | {{ 'Title'|trans }} |
19 | {{ 'Page order'|trans }} |
20 | {{ 'Enabled'|trans }} |
21 | {{ 'Actions'|trans }} |
22 |
23 |
24 |
25 | {% for entity in entities %}
26 |
27 |
28 |
29 | {{ entity.title }}
30 |
31 | |
32 |
33 | {{ entity.orderNum }}
34 | |
35 |
36 | {% if entity.enabled %}
37 | {{ 'yes'|trans }}
38 | {% else %}
39 | {{ 'no'|trans }}
40 | {% endif %}
41 | |
42 |
43 | {{ 'show'|trans }}
44 | {{ 'edit'|trans }}
45 | |
46 |
47 | {% endfor %}
48 |
49 |
50 | {% endblock page_content %}
51 |
--------------------------------------------------------------------------------
/templates/admin/static_page/show.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'admin/layout.html.twig' %}
2 |
3 | {% block page_content -%}
4 | {{ 'Static page'|trans }}
5 |
6 |
7 |
8 |
9 | {{ 'Title'|trans }} |
10 | {{ entity.title }} |
11 |
12 |
13 | {{ 'Enabled'|trans }} |
14 |
15 | {% if entity.enabled %}
16 | {{ 'yes'|trans }}
17 | {% else %}
18 | {{ 'no'|trans }}
19 | {% endif %}
20 | |
21 |
22 |
23 | {{ 'Page order'|trans }} |
24 | {{ entity.orderNum }} |
25 |
26 |
27 | {{ 'Meta keys'|trans }} |
28 | {{ entity.metaKeys }} |
29 |
30 |
31 | {{ 'Meta description'|trans }} |
32 | {{ entity.metaDescription }} |
33 |
34 |
35 | {{ 'Content'|trans }} |
36 |
37 | {{ entity.content|rawdescr|nl2br }}
38 | |
39 |
40 |
41 |
42 |
43 |
61 | {% endblock page_content %}
62 |
--------------------------------------------------------------------------------
/templates/admin/user/index.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'admin/layout.html.twig' %}
2 |
3 | {% block title %}
4 | {{ 'User list'|trans }} - {{ 'Administration panel'|trans }}
5 | {% endblock title %}
6 |
7 | {% block page_content -%}
8 | {{ 'User list'|trans }}
9 |
10 |
11 |
12 |
13 | {{ knp_pagination_sortable(entities, 'Username'|trans, 'u.username') }} |
14 | {{ knp_pagination_sortable(entities, 'Email'|trans, 'u.email') }} |
15 | {{ knp_pagination_sortable(entities, 'Registration date'|trans, 'u.joinDate') }} |
16 | {{ 'Orders'|trans }} |
17 | {{ 'Actions'|trans }} |
18 |
19 |
20 |
21 | {% for entity in entities %}
22 |
23 |
24 | {{ entity.username }}
25 | |
26 |
27 | {{ entity.email }}
28 | |
29 |
30 | {{ entity.joinDate|date('Y-m-d H:i') }}
31 | |
32 |
33 | {% if entity.orders|length %}
34 |
35 | {{ 'Orders'|trans }} ({{ entity.orders|length }})
36 |
37 | {% else %}
38 | -
39 | {% endif %}
40 | |
41 |
42 | {{ 'Show'|trans }}
43 | |
44 |
45 | {% endfor %}
46 |
47 |
48 |
49 |
50 | {{ knp_pagination_render(entities) }}
51 |
52 |
53 | {% endblock page_content %}
54 |
--------------------------------------------------------------------------------
/templates/admin/user/show_user_info.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'admin/layout.html.twig' %}
2 |
3 | {% block page_content -%}
4 | {{ 'User'|trans }}
5 |
6 |
7 |
8 |
9 | {{ 'Firstname'|trans }} |
10 | {{ user.firstname }} |
11 |
12 |
13 | {{ 'Lastname'|trans }} |
14 | {{ user.lastname }} |
15 |
16 |
17 | {{ 'Username'|trans }} |
18 | {{ user.username }} |
19 |
20 |
21 | {{ 'Email'|trans }} |
22 | {{ user.email }} |
23 |
24 |
25 | {{ 'Phone number'|trans }} |
26 | {{ user.phone }} |
27 |
28 |
29 | {{ 'Address'|trans }} |
30 | {{ user.address }} |
31 |
32 |
33 | {{ 'Join date'|trans }} |
34 | {{ user.joinDate|date('Y-m-d h:i') }} |
35 |
36 |
37 | {{ 'Orders'|trans }} |
38 |
39 | {% if user.orders|length %}
40 |
41 | {{ 'Orders'|trans }} ({{ user.orders|length }})
42 |
43 | {% else %}
44 | -
45 | {% endif %}
46 | |
47 |
48 |
49 |
50 |
51 |
58 | {% endblock page_content %}
59 |
60 |
--------------------------------------------------------------------------------
/templates/admin/user/show_user_orders.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'admin/layout.html.twig' %}
2 |
3 | {% block title %}
4 | {{ user.firstname ~' '~user.lastname }} - {{ 'Orders list'|trans }}
5 | {% endblock title %}
6 |
7 | {% block page_content -%}
8 | {{ user.firstname ~' '~user.lastname }} - {{ 'Orders list'|trans }}
9 | {% if orders|length %}
10 |
11 |
12 |
13 | {{ 'Order No'|trans }} # |
14 | {{ knp_pagination_sortable(orders, 'Client name'|trans, 'o.name') }} |
15 | {{ knp_pagination_sortable(orders, 'Order date'|trans, 'o.date') }} |
16 | {{ 'Actions'|trans }} |
17 |
18 |
19 |
20 | {% for order in orders %}
21 |
22 |
23 | {{ order.id }}
24 | |
25 |
26 | {{ order.name }}
27 | |
28 |
29 | {{ order.date|date('Y-m-d H:i') }}
30 | |
31 |
32 | {{ 'Show'|trans }}
33 | |
34 |
35 | {% endfor %}
36 |
37 |
38 | {% else %}
39 | {{ 'No orders yet'|trans }}
40 | {% endif %}
41 |
42 |
43 | {{ knp_pagination_render(orders) }}
44 |
45 |
46 | {% endblock page_content %}
47 |
--------------------------------------------------------------------------------
/templates/base.html.twig:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | {% block title %}Welcome!{% endblock %}
12 |
13 | {% block stylesheets %}{% endblock %}
14 | {% block header_javascripts %}{% endblock %}
15 |
16 |
17 |
18 |
22 |
23 |
24 | {% block body %}{% endblock %}
25 | {% block javascripts %}
26 |
27 |
28 |
29 |
30 | {% endblock %}
31 |
32 |
33 |
--------------------------------------------------------------------------------
/templates/bundles/FOSUserBundle/ChangePassword/change_password.html.twig:
--------------------------------------------------------------------------------
1 | {% extends "layout.html.twig" %}
2 | {% trans_default_domain 'FOSUserBundle' %}
3 | {% form_theme form 'bootstrap_3_horizontal_layout.html.twig' %}
4 |
5 | {% block title %}
6 | {{ 'change_password.submit'|trans }}
7 | {% endblock title %}
8 |
9 | {% block page_content %}
10 | {{ form_start(form, { 'action': path('fos_user_change_password'), 'attr': { 'class': 'fos_user_change_password' } }) }}
11 |
12 |
17 |
18 | {{ form_widget(form) }}
19 |
20 |
25 |
26 | {{ form_end(form) }}
27 | {% endblock page_content %}
28 |
--------------------------------------------------------------------------------
/templates/bundles/FOSUserBundle/Registration/confirmed.html.twig:
--------------------------------------------------------------------------------
1 | {% extends "layout.html.twig" %}
2 | {% trans_default_domain 'ShopBundle' %}
3 |
4 | {% block page_content %}
5 | {{ 'registration.successful'|trans }}
6 | {% if targetUrl %}
7 |
8 | {{ 'registration.back'|trans }}
9 |
10 | {% endif %}
11 | {% endblock page_content %}
12 |
--------------------------------------------------------------------------------
/templates/bundles/FOSUserBundle/Registration/register.html.twig:
--------------------------------------------------------------------------------
1 | {% extends "layout.html.twig" %}
2 | {% trans_default_domain 'FOSUserBundle' %}
3 | {% form_theme form 'bootstrap_3_horizontal_layout.html.twig' %}
4 |
5 | {% block title %}
6 | {{ 'layout.register'|trans }}
7 | {% endblock title %}
8 |
9 | {% block page_content %}
10 | {{ form_start(form, {'method': 'post', 'action': path('fos_user_registration_register'), 'attr': {'class': 'fos_user_registration_register'}}) }}
11 |
12 |
17 | {{ form_row(form.firstname) }}
18 | {{ form_row(form.lastname) }}
19 | {{ form_row(form.username) }}
20 | {{ form_row(form.email) }}
21 | {{ form_row(form.phone) }}
22 | {{ form_row(form.plainPassword.first) }}
23 | {{ form_row(form.plainPassword.second) }}
24 | {{ form_row(form.address) }}
25 | {{ form_widget(form) }}
26 |
27 |
32 |
33 | {{ form_end(form) }}
34 | {% endblock page_content %}
35 |
--------------------------------------------------------------------------------
/templates/bundles/FOSUserBundle/Resetting/check_email.html.twig:
--------------------------------------------------------------------------------
1 | {% extends "layout.html.twig" %}
2 | {% trans_default_domain 'FOSUserBundle' %}
3 |
4 | {% block page_content %}
5 |
6 | {{ 'resetting.check_email'|trans({'%email%': email}) }}
7 |
8 | {% endblock page_content %}
9 |
--------------------------------------------------------------------------------
/templates/bundles/FOSUserBundle/Resetting/email.txt.twig:
--------------------------------------------------------------------------------
1 | {% trans_default_domain 'FOSUserBundle' %}
2 | {% block subject %}
3 | {% autoescape false %}
4 | {{ 'resetting.email.subject'|trans({'%username%': user.username}) }}
5 | {% endautoescape %}
6 | {% endblock %}
7 | {% block body_text %}
8 | {% autoescape false %}
9 | {{ 'resetting.email.message'|trans({'%username%': user.username, '%confirmationUrl%': confirmationUrl}) }}
10 | {% endautoescape %}
11 | {% endblock %}
12 | {% block body_html %}{% endblock %}
13 |
--------------------------------------------------------------------------------
/templates/bundles/FOSUserBundle/Resetting/password_already_requested.html.twig:
--------------------------------------------------------------------------------
1 | {% extends "layout.html.twig" %}
2 | {% trans_default_domain 'FOSUserBundle' %}
3 |
4 | {% block page_content %}
5 | {{ 'resetting.password_already_requested'|trans }}
6 | {% endblock page_content %}
7 |
--------------------------------------------------------------------------------
/templates/bundles/FOSUserBundle/Resetting/request.html.twig:
--------------------------------------------------------------------------------
1 | {% extends "layout.html.twig" %}
2 | {% trans_default_domain 'FOSUserBundle' %}
3 |
4 | {% block title %}
5 | {{ 'resetting.request.submit'|trans }}
6 | {% endblock title %}
7 |
8 | {% block page_content %}
9 |
26 | {% endblock page_content %}
27 |
--------------------------------------------------------------------------------
/templates/bundles/FOSUserBundle/Resetting/reset.html.twig:
--------------------------------------------------------------------------------
1 | {% extends "FOSUserBundle::layout.html.twig" %}
2 |
3 | {% block fos_user_content %}
4 | {% include "FOSUserBundle:Resetting:reset_content.html.twig" %}
5 | {% endblock fos_user_content %}
6 |
--------------------------------------------------------------------------------
/templates/bundles/FOSUserBundle/Resetting/reset_content.html.twig:
--------------------------------------------------------------------------------
1 | {% trans_default_domain 'FOSUserBundle' %}
2 |
3 | {{ form_start(form, { 'action': path('fos_user_resetting_reset', {'token': token}), 'attr': { 'class': 'fos_user_resetting_reset' } }) }}
4 | {{ form_widget(form) }}
5 |
6 |
7 |
8 | {{ form_end(form) }}
9 |
--------------------------------------------------------------------------------
/templates/bundles/FOSUserBundle/Security/login.html.twig:
--------------------------------------------------------------------------------
1 | {% extends "base.html.twig" %}
2 |
3 | {% trans_default_domain 'FOSUserBundle' %}
4 |
5 | {% block stylesheets %}
6 | {{ parent() }}
7 |
8 | {% endblock %}
9 |
10 | {% block body %}
11 | {% if error %}
12 | {{ error.messageKey|trans(error.messageData, 'security') }}
13 | {% endif %}
14 |
15 |
36 |
37 | {% endblock body %}
38 |
--------------------------------------------------------------------------------
/templates/bundles/TwigBundle/Exception/error.html.twig:
--------------------------------------------------------------------------------
1 | {% extends "layout.html.twig" %}
2 | {% trans_default_domain 'ShopBundle' %}
3 |
4 | {% block page_content %}
5 | {{ 'errors.err.header'|trans }}
6 |
7 |
8 | {{ 'errors.err.description'|trans }}
9 |
10 |
11 |
12 | {{ 'errors.err.tohomepage'|trans }}
13 |
14 |
15 | {% endblock page_content %}
16 |
--------------------------------------------------------------------------------
/templates/bundles/TwigBundle/Exception/error404.html.twig:
--------------------------------------------------------------------------------
1 | {% extends "layout.html.twig" %}
2 | {% trans_default_domain 'ShopBundle' %}
3 |
4 | {% block page_content %}
5 | {{ 'errors.pnf.header'|trans }}
6 |
7 |
8 | {{ 'errors.pnf.description'|trans }}
9 |
10 |
11 |
12 | {{ 'errors.pnf.tohomepage'|trans }}
13 |
14 |
15 | {% endblock page_content %}
16 |
--------------------------------------------------------------------------------
/templates/cart/cart_is_empty.html.twig:
--------------------------------------------------------------------------------
1 | {% extends "layout.html.twig" %}
2 | {% trans_default_domain 'ShopBundle' %}
3 |
4 | {% block title %}
5 | {{ 'cart.isempty'|trans }}
6 | {% endblock title %}
7 |
8 | {% block page_content -%}
9 |
15 | {% endblock page_content %}
16 |
--------------------------------------------------------------------------------
/templates/cart/navbar_cart.html.twig:
--------------------------------------------------------------------------------
1 | {% trans_default_domain 'ShopBundle' %}
2 | {{ productsCount }} {{ 'cart.navbar.goods'|trans }}
3 | {{ totalSum }} {{ 'currency'|trans }}
4 |
--------------------------------------------------------------------------------
/templates/cart/order_form.html.twig:
--------------------------------------------------------------------------------
1 | {% extends "layout.html.twig" %}
2 | {% trans_default_domain 'ShopBundle' %}
3 |
4 | {% form_theme form 'bootstrap_3_horizontal_layout.html.twig' %}
5 |
6 | {% block title %}{{ 'orderform.orderform'|trans }}{% endblock title %}
7 |
8 | {% block page_content -%}
9 | {{ 'orderform.orderform'|trans }}
10 |
11 |
12 |
13 | {{ form_start(form) }}
14 | {{ form_errors(form) }}
15 |
21 |
27 |
33 |
39 |
45 | {{ form_rest(form) }}
46 |
51 |
56 | {{ form_start(form) }}
57 |
58 |
59 | {% endblock page_content %}
60 |
61 | {% block javascripts %}
62 | {{ parent() }}
63 |
70 | {% endblock javascripts %}
71 |
--------------------------------------------------------------------------------
/templates/cart/thank_you.html.twig:
--------------------------------------------------------------------------------
1 | {% extends "layout.html.twig" %}
2 | {% trans_default_domain 'ShopBundle' %}
3 |
4 | {% block title %}
5 | {{ 'thankyou.thankyou'|trans }}
6 | {% endblock title %}
7 |
8 | {% block page_content -%}
9 |
19 | {% endblock page_content %}
20 |
--------------------------------------------------------------------------------
/templates/catalog/category.html.twig:
--------------------------------------------------------------------------------
1 | {% extends "layout.html.twig" %}
2 | {% trans_default_domain 'ShopBundle' %}
3 |
4 | {% block title %}
5 | {{ category.name }}
6 | {% endblock title %}
7 |
8 | {% block metadescription %}{{ category.metaDescription }}{% endblock %}
9 | {% block metakeys %}{{ category.metaKeys }}{% endblock %}
10 |
11 | {% block page_content -%}
12 |
13 |
18 |
{{ category.name }}
19 |
20 | {{ 'category.sort.by'|trans }}
21 |
26 |
30 |
31 |
32 |
33 | {% if products|length %}
34 | {% for product in products %}
35 | {{ include('_partials/product_preview.html.twig') }}
36 | {% endfor %}
37 | {% else %}
38 |
{{ 'manufacturer.noproducts'|trans }}
39 | {% endif %}
40 |
41 |
42 |
43 | {{ knp_pagination_render(products) }}
44 |
45 |
46 |
47 |
{{ category.name }}
48 |
49 |
50 | {{ category.description|rawdescr|nl2br }}
51 |
52 |
53 |
54 | {% endblock page_content %}
55 |
56 | {% block javascripts %}
57 | {{ parent() }}
58 |
64 | {% endblock javascripts %}
65 |
--------------------------------------------------------------------------------
/templates/catalog/index.html.twig:
--------------------------------------------------------------------------------
1 | {% extends "layout.html.twig" %}
2 | {% trans_default_domain 'ShopBundle' %}
3 |
4 | {% block title %}
5 | {{ 'layout.navbar.sitename'|trans }} - {{ 'categories.menu.header'|trans }}
6 | {% endblock title %}
7 |
8 | {% block page_content -%}
9 | {% if slides|length %}
10 | {{ include('_partials/slides_block.html.twig') }}
11 | {% endif %}
12 |
13 |
14 |
15 | {% if news | length %}
16 |
17 | {{ news.title }}
18 |
19 |
20 | {{ news.text|rawdescr|nl2br }}
21 |
22 |
{{ news.date|date() }}
23 | {% else %}
24 | {{ 'news.nonews'|trans }}
25 | {% endif %}
26 |
27 |
28 |
29 |
30 |
31 |
{{ 'layout.index.latestproducts'|trans }}
32 | {% for product in latest_products %}
33 | {{ include('_partials/product_preview.html.twig') }}
34 | {% endfor %}
35 |
36 |
37 |
38 |
39 |
{{ 'layout.index.featuredproducts'|trans }}
40 | {% for product in featured_products %}
41 | {{ include('_partials/product_preview.html.twig') }}
42 | {% endfor %}
43 |
44 |
45 | {% endblock page_content %}
46 |
47 | {% block javascripts %}
48 | {{ parent() }}
49 |
61 | {% endblock javascripts %}
62 |
--------------------------------------------------------------------------------
/templates/catalog/manufacturer.html.twig:
--------------------------------------------------------------------------------
1 | {% extends "layout.html.twig" %}
2 | {% trans_default_domain 'ShopBundle' %}
3 |
4 | {% block title %}
5 | {{ manufacturer.name }}
6 | {% endblock title %}
7 |
8 | {% block metadescription %}{{ manufacturer.metaDescription }}{% endblock %}
9 | {% block metakeys %}{{ manufacturer.metaKeys }}{% endblock %}
10 |
11 | {% block page_content -%}
12 |
13 |
18 |
{{ manufacturer.name }}
19 |
20 | {{ 'manufacturer.sort.by'|trans }}
21 |
26 |
30 |
31 |
32 |
33 | {% if products|length %}
34 | {% for product in products %}
35 | {{ include('_partials/product_preview.html.twig') }}
36 | {% endfor %}
37 | {% else %}
38 |
{{ 'manufacturer.noproducts'|trans }}
39 | {% endif %}
40 |
41 |
42 |
43 | {{ knp_pagination_render(products) }}
44 |
45 |
46 |
47 |
{{ manufacturer.name }}
48 |
49 |
50 | {{ manufacturer.description|rawdescr|nl2br }}
51 |
52 |
53 |
54 | {% endblock page_content %}
55 |
56 | {% block javascripts %}
57 | {{ parent() }}
58 |
64 | {% endblock javascripts %}
65 |
--------------------------------------------------------------------------------
/templates/catalog/news.html.twig:
--------------------------------------------------------------------------------
1 | {% extends "layout.html.twig" %}
2 | {% trans_default_domain 'ShopBundle' %}
3 |
4 | {% block title %}
5 | {{ 'layout.navbar.sitename'|trans }} - {{ 'layout.navbar.news'|trans }}
6 | {% endblock title %}
7 |
8 | {% block page_content -%}
9 | {% if news|length %}
10 | {% for entity in news %}
11 |
12 |
13 |
14 |
15 | {{ entity.title }}
16 |
17 |
18 | {{ entity.text|rawdescr|nl2br }}
19 |
20 |
{{ entity.date|date() }}
21 |
22 |
23 |
24 | {% endfor %}
25 | {% else %}
26 | {{ 'news.nonews'|trans }}
27 | {% endif %}
28 |
29 |
30 | {{ knp_pagination_render(news) }}
31 |
32 |
33 | {% endblock page_content %}
34 |
--------------------------------------------------------------------------------
/templates/catalog/search_product.html.twig:
--------------------------------------------------------------------------------
1 | {% extends "layout.html.twig" %}
2 | {% trans_default_domain 'ShopBundle' %}
3 |
4 | {% block title %}
5 | {{ 'search.searchfor'|trans }} "{{ search_phrase }}"
6 | {% endblock title %}
7 |
8 | {% block page_content -%}
9 |
10 |
15 |
{{ 'search.searchfor'|trans }} "{{ search_phrase }}"
16 |
17 | {{ 'category.sort.by'|trans }}
18 |
23 |
27 |
28 |
29 |
30 | {% if products|length %}
31 | {% for product in products %}
32 | {{ include('_partials/product_preview.html.twig') }}
33 | {% endfor %}
34 | {% else %}
35 |
{{ 'manufacturer.noproducts'|trans }}
36 | {% endif %}
37 |
38 |
39 |
40 | {{ knp_pagination_render(products) }}
41 |
42 |
43 | {% endblock page_content %}
44 |
--------------------------------------------------------------------------------
/templates/catalog/show_static_page.html.twig:
--------------------------------------------------------------------------------
1 | {% extends "layout.html.twig" %}
2 | {% trans_default_domain 'ShopBundle' %}
3 |
4 | {% block title %}
5 | {{ page.title }}
6 | {% endblock title %}
7 |
8 | {% block page_content -%}
9 |
10 |
11 |
12 |
13 | {{ page.title }}
14 |
15 |
16 | {{ page.content|rawdescr|nl2br }}
17 |
18 |
19 |
20 |
21 | {% endblock page_content %}
22 |
--------------------------------------------------------------------------------
/templates/mail/order_notification_email.txt.twig:
--------------------------------------------------------------------------------
1 | {% trans_default_domain 'ShopBundle' %}
2 | {% autoescape false %}{{ 'notification.neworder'|trans }} {{ url }}{% endautoescape %}
3 |
--------------------------------------------------------------------------------
/templates/profile/favourites.html.twig:
--------------------------------------------------------------------------------
1 | {% extends "layout.html.twig" %}
2 | {% trans_default_domain 'ShopBundle' %}
3 |
4 | {% block title %}
5 | {{ 'layout.navbar.favourites'|trans }} - {{ 'layout.navbar.news'|trans }}
6 | {% endblock title %}
7 |
8 | {% block page_content -%}
9 |
10 |
15 |
{{ 'favourites.yourfavouriteproducts'|trans }}
16 |
17 | {{ 'favourites.sort.by'|trans }}
18 |
23 |
28 |
29 |
30 |
31 | {% if products|length %}
32 | {% for product in products %}
33 | {{ include('_partials/product_preview.html.twig') }}
34 | {% endfor %}
35 | {% else %}
36 |
{{ 'favourites.noproducts'|trans }}
37 | {% endif %}
38 |
39 |
40 |
41 | {{ knp_pagination_render(products) }}
42 |
43 |
44 | {% endblock page_content %}
45 |
--------------------------------------------------------------------------------
/tests/Controller/AdminControllerTest.php:
--------------------------------------------------------------------------------
1 | loadFixtures([
18 | LoadUserData::class,
19 | CategoryFixtures::class
20 | ]);
21 |
22 | $client = static::createClient([], [
23 | 'PHP_AUTH_USER' => 'user1',
24 | 'PHP_AUTH_PW' => 'user1',
25 | ]);
26 |
27 | $client->followRedirects();
28 | $client->request($httpMethod, $url);
29 | $this->assertSame(Response::HTTP_FORBIDDEN, $client->getResponse()->getStatusCode());
30 | }
31 |
32 | public function testAccessibleForAdmin()
33 | {
34 | $this->loadFixtures([
35 | LoadUserData::class,
36 | CategoryFixtures::class
37 | ]);
38 |
39 | $client = static::createClient([], [
40 | 'PHP_AUTH_USER' => 'admin',
41 | 'PHP_AUTH_PW' => 'admin',
42 | ]);
43 |
44 | $client->followRedirects();
45 | $crawler = $client->request('GET', '/admin/');
46 | $this->assertSame(Response::HTTP_OK, $client->getResponse()->getStatusCode());
47 |
48 | $this->assertGreaterThanOrEqual(
49 | 1,
50 | $crawler->filter('h3#admin-index')->count(),
51 | 'Backend is available.'
52 | );
53 | }
54 |
55 | public function getUrlsForRegularUsers()
56 | {
57 | yield ['GET', '/admin/'];
58 | yield ['GET', '/admin/category'];
59 | yield ['DELETE', '/admin/category/1'];
60 | yield ['GET', '/admin/category/1/edit'];
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/tests/Utils/SluggerTest.php:
--------------------------------------------------------------------------------
1 | assertSame($slug, Slugger::slugify($string));
16 | }
17 |
18 | public function getSlugs()
19 | {
20 | yield ['Lorem Ipsum', 'lorem-ipsum'];
21 | yield [' Lorem Ipsum ', 'lorem-ipsum'];
22 | yield [' lOrEm iPsUm ', 'lorem-ipsum'];
23 | yield ['!Lorem Ipsum!', '!lorem-ipsum!'];
24 | yield ['lorem-ipsum', 'lorem-ipsum'];
25 | yield ['lorem 日本語 ipsum', 'lorem-日本語-ipsum'];
26 | yield ['lorem русский язык ipsum', 'lorem-русский-язык-ipsum'];
27 | yield ['lorem العَرَبِيَّة ipsum', 'lorem-العَرَبِيَّة-ipsum'];
28 | }
29 |
30 | public function testThatMyComputerWorks()
31 | {
32 | $this->assertTrue(true);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/tests/bootstrap.php:
--------------------------------------------------------------------------------
1 | bootEnv(dirname(__DIR__).'/.env');
11 | }
12 |
--------------------------------------------------------------------------------
/translations/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/morozovalexander/symfocommerce/06532086d6febd9d33c0b9abb0998dbca3dd31a8/translations/.gitignore
--------------------------------------------------------------------------------