├── .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 | [![Join the chat at https://gitter.im/morozovalexander/symfocommerce](https://badges.gitter.im/morozovalexander/symfocommerce.svg)](https://gitter.im/morozovalexander/symfocommerce?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 5 | [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](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 | 6 | {{ category.name }} 7 | 8 | {% endfor %} 9 |
10 | -------------------------------------------------------------------------------- /templates/_partials/category_preview.html.twig: -------------------------------------------------------------------------------- 1 | {% trans_default_domain 'ShopBundle' %} 2 |
3 |
4 | 5 | {% if category.path %} 6 | {{ category.name }} 9 | {% else %} 10 | {{ category.name }} 13 | {% endif %} 14 | 15 | 16 |
17 |

18 | {{ category.name }} 19 |

20 |
21 |
22 |
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 | 6 | {{ manufacturer.name }} 7 | 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 | 15 | {% else %} 16 | 25 | {% endif %} 26 | {% else %} 27 | 37 | {% endif %} 38 | -------------------------------------------------------------------------------- /templates/_partials/product_preview.html.twig: -------------------------------------------------------------------------------- 1 | {% trans_default_domain 'ShopBundle' %} 2 |
3 |
4 | 5 | {% if product.images|length %} 6 | {{ product.name }} 9 | {% else %} 10 | {{ product.name }} 13 | {% endif %} 14 | 15 | 16 | 28 |
29 |
30 | -------------------------------------------------------------------------------- /templates/_partials/slides_block.html.twig: -------------------------------------------------------------------------------- 1 | {% trans_default_domain 'ShopBundle' %} 2 |
3 |
4 | 40 |
41 |
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 | 11 | {% endfor %} 12 | 13 | {{ form_start(edit_form) }} 14 | {{ form_widget(edit_form) }} 15 |
    16 | 17 |
    18 | 19 |
    20 |
    21 | {{ form_end(edit_form) }} 22 | 23 |
    24 | 37 |
    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 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | {% for entity in entities %} 24 | 25 | 30 | 34 | 35 | {% endfor %} 36 | 37 |
    {{ 'Name'|trans }}{{ 'Actions'|trans }}
    26 | 27 | {{ entity.name }} 28 | 29 | 31 | {{ 'show'|trans }}
    32 | {{ 'edit'|trans }} 33 |
    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 |
    10 | 11 |
    12 | 13 |
    14 |
    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 | 10 | 11 | 12 | 13 |
    {{ 'Name'|trans }}{{ entity.name }}
    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 | 19 | 20 | 21 | 22 | 23 | 24 | {% for entity in entities %} 25 | 26 | 31 | 34 | 38 | 39 | {% endfor %} 40 | 41 |
    {{ knp_pagination_sortable(entities, 'Title'|trans, 'n.title') }}{{ knp_pagination_sortable(entities, 'Text'|trans, 'n.text') }}{{ 'Actions'|trans }}
    27 | 28 | {{ entity.title }} 29 | 30 | 32 | {{ entity.text|slice(0, 130) }}... 33 | 35 | {{ 'show'|trans }}
    36 | {{ 'edit'|trans }} 37 |
    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 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
    {{ 'Title'|trans }}{{ entity.title }}
    {{ 'Slug'|trans }}{{ entity.slug }}
    {{ 'Text'|trans }} 18 | {{ entity.text|rawdescr|nl2br }} 19 |
    {{ 'Meta keys'|trans }}{{ entity.metaKeys }}
    {{ 'Meta description'|trans }}{{ entity.metaDescription }}
    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 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | {% for order in orders %} 23 | 24 | 27 | 30 | 37 | 40 | 43 | 46 | 47 | {% endfor %} 48 | 49 |
    {{ 'Order No'|trans }} #{{ knp_pagination_sortable(orders, 'Client name'|trans, 'o.name') }}{{ knp_pagination_sortable(orders, 'User'|trans, 'u.username') }}{{ knp_pagination_sortable(orders, 'Order totalsum'|trans, 'o.sum') }}{{ knp_pagination_sortable(orders, 'Order date'|trans, 'o.date') }}{{ 'Actions'|trans }}
    25 | {{ order.id }} 26 | 28 | {{ order.name }} 29 | 31 | {% if order.user %} 32 | {{ order.user.username }} 33 | {% else %} 34 | {{ 'not registered'|trans }} 35 | {% endif %} 36 | 38 | {{ order.sum }} {{ 'currency'|trans }} 39 | 41 | {{ order.date|date('Y-m-d H:i') }} 42 | 44 | {{ 'Show'|trans }} 45 |
    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 | 11 | {% endfor %} 12 | 13 | {{ form_start(edit_form) }} 14 | {{ form_widget(edit_form) }} 15 |
    16 | 17 |
    18 | 19 |
    20 |
    21 | {{ form_end(edit_form) }} 22 | 23 |
    24 | 37 |
    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 |
    10 | 11 |
    12 | 13 |
    14 |
    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 | 16 | 17 | 18 | 19 | 20 | 27 | 28 | 29 | 30 | 39 | 40 | 41 | 42 | 43 | 44 | 45 |
    {{ 'Name'|trans }}{{ entity.name }}
    {{ 'Enabled'|trans }} 21 | {% if entity.enabled %} 22 | {{ 'yes'|trans }} 23 | {% else %} 24 | {{ 'no'|trans }} 25 | {% endif %} 26 |
    {{ 'Image'|trans }} 31 | {% if entity.image %} 32 | 33 | 34 | 35 | {% else %} 36 | {{ 'no photos'|trans }} 37 | {% endif %} 38 |
    {{ 'Slide order'|trans }}{{ entity.slideOrder }}
    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 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | {% for entity in entities %} 26 | 27 | 32 | 35 | 42 | 46 | 47 | {% endfor %} 48 | 49 |
    {{ 'Title'|trans }}{{ 'Page order'|trans }}{{ 'Enabled'|trans }}{{ 'Actions'|trans }}
    28 | 29 | {{ entity.title }} 30 | 31 | 33 | {{ entity.orderNum }} 34 | 36 | {% if entity.enabled %} 37 | {{ 'yes'|trans }} 38 | {% else %} 39 | {{ 'no'|trans }} 40 | {% endif %} 41 | 43 | {{ 'show'|trans }}
    44 | {{ 'edit'|trans }} 45 |
    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 | 10 | 11 | 12 | 13 | 14 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 39 | 40 | 41 |
    {{ 'Title'|trans }}{{ entity.title }}
    {{ 'Enabled'|trans }} 15 | {% if entity.enabled %} 16 | {{ 'yes'|trans }} 17 | {% else %} 18 | {{ 'no'|trans }} 19 | {% endif %} 20 |
    {{ 'Page order'|trans }}{{ entity.orderNum }}
    {{ 'Meta keys'|trans }}{{ entity.metaKeys }}
    {{ 'Meta description'|trans }}{{ entity.metaDescription }}
    {{ 'Content'|trans }} 37 | {{ entity.content|rawdescr|nl2br }} 38 |
    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 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | {% for entity in entities %} 22 | 23 | 26 | 29 | 32 | 41 | 44 | 45 | {% endfor %} 46 | 47 |
    {{ knp_pagination_sortable(entities, 'Username'|trans, 'u.username') }}{{ knp_pagination_sortable(entities, 'Email'|trans, 'u.email') }}{{ knp_pagination_sortable(entities, 'Registration date'|trans, 'u.joinDate') }}{{ 'Orders'|trans }}{{ 'Actions'|trans }}
    24 | {{ entity.username }} 25 | 27 | {{ entity.email }} 28 | 30 | {{ entity.joinDate|date('Y-m-d H:i') }} 31 | 33 | {% if entity.orders|length %} 34 | 35 | {{ 'Orders'|trans }} ({{ entity.orders|length }}) 36 | 37 | {% else %} 38 | - 39 | {% endif %} 40 | 42 | {{ 'Show'|trans }} 43 |
    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 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 47 | 48 | 49 |
    {{ 'Firstname'|trans }}{{ user.firstname }}
    {{ 'Lastname'|trans }}{{ user.lastname }}
    {{ 'Username'|trans }}{{ user.username }}
    {{ 'Email'|trans }}{{ user.email }}
    {{ 'Phone number'|trans }}{{ user.phone }}
    {{ 'Address'|trans }}{{ user.address }}
    {{ 'Join date'|trans }}{{ user.joinDate|date('Y-m-d h:i') }}
    {{ 'Orders'|trans }} 39 | {% if user.orders|length %} 40 | 41 | {{ 'Orders'|trans }} ({{ user.orders|length }}) 42 | 43 | {% else %} 44 | - 45 | {% endif %} 46 |
    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 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | {% for order in orders %} 21 | 22 | 25 | 28 | 31 | 34 | 35 | {% endfor %} 36 | 37 |
    {{ 'Order No'|trans }} #{{ knp_pagination_sortable(orders, 'Client name'|trans, 'o.name') }}{{ knp_pagination_sortable(orders, 'Order date'|trans, 'o.date') }}{{ 'Actions'|trans }}
    23 | {{ order.id }} 24 | 26 | {{ order.name }} 27 | 29 | {{ order.date|date('Y-m-d H:i') }} 30 | 32 | {{ 'Show'|trans }} 33 |
    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 |
    13 |
    14 |

    {{ 'change_password.submit'|trans }}

    15 |
    16 |
    17 | 18 | {{ form_widget(form) }} 19 | 20 |
    21 |
    22 | 23 |
    24 |
    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 |
    13 |
    14 |

    {{ 'layout.register'|trans }}

    15 |
    16 |
    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 |
    28 |
    29 | 30 |
    31 |
    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 |
    11 | 12 | {% if invalid_username is defined %} 13 |

    14 | {{ 'resetting.request.invalid_username'|trans({'%username%': invalid_username}) }} 15 |

    16 | {% endif %} 17 | 18 |
    19 | 20 | 21 |
    22 | 23 | 24 | 25 |
    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 |
    16 |

    {% trans from "messages" %}Please sign in{% endtrans %}

    17 | 18 | 19 |
    20 | 21 | 23 |
    24 |
    25 | 26 | 27 |
    28 | 29 | 31 | 32 | 34 | 35 |
    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 |
    10 |
    11 |

    {{ 'cart.isemptyyet'|trans }}

    12 |

    {{ 'cart.continue'|trans }}

    13 |
    14 |
    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 |
    16 | {{ form_label(form.name, 'orderform.name'|trans) }} 17 |
    18 | {{ form_widget(form.name) }} 19 |
    20 |
    21 |
    22 | {{ form_label(form.email, 'orderform.email'|trans) }} 23 |
    24 | {{ form_widget(form.email) }} 25 |
    26 |
    27 |
    28 | {{ form_label(form.phone, 'orderform.phone'|trans) }} 29 |
    30 | {{ form_widget(form.phone) }} 31 |
    32 |
    33 |
    34 | {{ form_label(form.address, 'orderform.address'|trans) }} 35 |
    36 | {{ form_widget(form.address) }} 37 |
    38 |
    39 |
    40 | {{ form_label(form.comment, 'orderform.yourcomment'|trans) }} 41 |
    42 | {{ form_widget(form.comment) }} 43 |
    44 |
    45 | {{ form_rest(form) }} 46 |
    47 |
    48 | 49 |
    50 |
    51 |
    52 |
    53 | {{ 'orderform.totalsumis'|trans }} {{ 'currency'|trans }} 54 |
    55 |
    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 |
    10 |
    11 |

    {{ 'thankyou.handleorder'|trans }}

    12 |

    13 | 14 | {{ 'thankyou.continue'|trans }} 15 | 16 |

    17 |
    18 |
    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 |
    14 | 15 | {{ 'category.view.list'|trans }} {{ 'category.view.grid'|trans }} 17 |
    18 | {{ category.name }} 19 | 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 |
    14 | 15 | {{ 'manufacturer.view.list'|trans }} {{ 'category.view.grid'|trans }} 17 |
    18 | {{ manufacturer.name }} 19 | 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 |
    11 | 12 | {{ 'category.view.list'|trans }} {{ 'category.view.grid'|trans }} 14 |
    15 | {{ 'search.searchfor'|trans }} "{{ search_phrase }}" 16 | 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 |
    11 | 12 | {{ 'favourites.view.list'|trans }} {{ 'favourites.view.grid'|trans }} 14 |
    15 | {{ 'favourites.yourfavouriteproducts'|trans }} 16 | 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 --------------------------------------------------------------------------------