Repository: aimeos/aimeos-laravel Branch: master Commit: 42e146cf3a43 Files: 101 Total size: 206.6 KB Directory structure: gitextract_8j091w8s/ ├── .circleci/ │ └── config.yml ├── .coveralls.yml ├── .devcontainer/ │ └── devcontainer.json ├── .gitattributes ├── .github/ │ └── ISSUE_TEMPLATE/ │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── LICENSE ├── README.md ├── build.xml ├── composer.json ├── config/ │ ├── default.php │ └── shop.php ├── phpunit.xml.dist ├── routes/ │ └── aimeos.php ├── src/ │ ├── Base/ │ │ ├── Aimeos.php │ │ ├── Config.php │ │ ├── Context.php │ │ ├── I18n.php │ │ ├── Locale.php │ │ ├── Shop.php │ │ ├── Support.php │ │ └── View.php │ ├── Command/ │ │ ├── AbstractCommand.php │ │ ├── AccountCommand.php │ │ ├── ClearCommand.php │ │ ├── JobsCommand.php │ │ └── SetupCommand.php │ ├── Composer.php │ ├── Controller/ │ │ ├── AccountController.php │ │ ├── AdminController.php │ │ ├── BasketController.php │ │ ├── CatalogController.php │ │ ├── CheckoutController.php │ │ ├── GraphqlController.php │ │ ├── JqadmController.php │ │ ├── JsonadmController.php │ │ ├── JsonapiController.php │ │ ├── PageController.php │ │ ├── ResolveController.php │ │ └── SupplierController.php │ ├── Facades/ │ │ ├── Attribute.php │ │ ├── Basket.php │ │ ├── Catalog.php │ │ ├── Cms.php │ │ ├── Customer.php │ │ ├── Locale.php │ │ ├── Order.php │ │ ├── Product.php │ │ ├── Service.php │ │ ├── Shop.php │ │ ├── Stock.php │ │ ├── Subscription.php │ │ └── Supplier.php │ ├── ShopServiceProvider.php │ └── helpers.php ├── tests/ │ ├── AimeosTestAbstract.php │ ├── Base/ │ │ ├── AimeosTest.php │ │ ├── ConfigTest.php │ │ ├── ContextTest.php │ │ ├── I18nTest.php │ │ ├── LocaleTest.php │ │ ├── SupportTest.php │ │ └── ViewTest.php │ ├── Command/ │ │ ├── AccountCommandTest.php │ │ ├── ClearCommandTest.php │ │ ├── JobsCommandTest.php │ │ └── SetupCommandTest.php │ ├── Controller/ │ │ ├── AccountControllerTest.php │ │ ├── AdminControllerTest.php │ │ ├── BasketControllerTest.php │ │ ├── CatalogControllerTest.php │ │ ├── CheckoutControllerTest.php │ │ ├── GraphqlControllerTest.php │ │ ├── JqadmControllerTest.php │ │ ├── JsonadmControllerTest.php │ │ ├── JsonapiControllerTest.php │ │ ├── PageControllerTest.php │ │ ├── ResolveControllerTest.php │ │ └── SupplierControllerTest.php │ ├── FacadesTest.php │ ├── HelpersTest.php │ └── fixtures/ │ └── views/ │ └── app.blade.php └── views/ ├── account/ │ └── index.blade.php ├── admin/ │ └── index.blade.php ├── base.blade.php ├── basket/ │ └── index.blade.php ├── catalog/ │ ├── count.blade.php │ ├── detail.blade.php │ ├── home.blade.php │ ├── list.blade.php │ ├── session.blade.php │ ├── stock.blade.php │ ├── suggest.blade.php │ └── tree.blade.php ├── checkout/ │ ├── confirm.blade.php │ ├── index.blade.php │ └── update.blade.php ├── jqadm/ │ └── index.blade.php ├── page/ │ └── index.blade.php └── supplier/ └── detail.blade.php ================================================ FILE CONTENTS ================================================ ================================================ FILE: .circleci/config.yml ================================================ # PHP CircleCI 2.0 configuration file # # Check https://circleci.com/docs/2.0/language-php/ for more details # version: 2 jobs: "php82-mysql80": docker: - image: aimeos/ci-php:8.2 - image: cimg/mysql:8.0 environment: MYSQL_ROOT_PASSWORD: rootpw MYSQL_DATABASE: laravel MYSQL_USER: aimeos MYSQL_PASSWORD: aimeos steps: - checkout - run: wget https://getcomposer.org/download/latest-stable/composer.phar -O composer - run: php composer req "laravel/framework:~10.0" --no-update - run: php composer req "phpunit/phpunit:~10.0" --no-update --dev - restore_cache: keys: - php82-{{ checksum "composer.json" }} - run: php composer update -n --prefer-dist - save_cache: key: php82-{{ checksum "composer.json" }} paths: [./vendor] - run: for i in `seq 1 10`; do nc -z 127.0.0.1 3306 && echo OK && exit 0; echo -n .; sleep 1; done - run: ./vendor/bin/phpunit "php83-mysql80": docker: - image: aimeos/ci-php:8.3 - image: cimg/mysql:8.0 environment: MYSQL_ROOT_PASSWORD: rootpw MYSQL_DATABASE: laravel MYSQL_USER: aimeos MYSQL_PASSWORD: aimeos steps: - checkout - run: wget https://getcomposer.org/download/latest-stable/composer.phar -O composer - run: php composer req "laravel/framework:~11.0" --no-update - run: php composer req "phpunit/phpunit:~11.0" --no-update --dev - restore_cache: keys: - php83-{{ checksum "composer.json" }} - run: php composer update -n --prefer-dist - save_cache: key: php83-{{ checksum "composer.json" }} paths: [./vendor] - run: for i in `seq 1 10`; do nc -z 127.0.0.1 3306 && echo OK && exit 0; echo -n .; sleep 1; done - run: ./vendor/bin/phpunit "php84-mysql80": docker: - image: aimeos/ci-php:8.4 - image: cimg/mysql:8.0 environment: MYSQL_ROOT_PASSWORD: rootpw MYSQL_DATABASE: laravel MYSQL_USER: aimeos MYSQL_PASSWORD: aimeos steps: - checkout - run: wget https://getcomposer.org/download/latest-stable/composer.phar -O composer - run: php composer req "laravel/framework:~12.0" --no-update - run: php composer req "phpunit/phpunit:~11.0" --no-update --dev - restore_cache: keys: - php84-{{ checksum "composer.json" }} - run: php composer update -n --prefer-dist - save_cache: key: php84-{{ checksum "composer.json" }} paths: [./vendor] - run: for i in `seq 1 10`; do nc -z 127.0.0.1 3306 && echo OK && exit 0; echo -n .; sleep 1; done - run: ./vendor/bin/phpunit --coverage-clover coverage.xml "php85-mysql80": docker: - image: aimeos/ci-php:8.5 - image: cimg/mysql:8.0 environment: MYSQL_ROOT_PASSWORD: rootpw MYSQL_DATABASE: laravel MYSQL_USER: aimeos MYSQL_PASSWORD: aimeos steps: - checkout - run: wget https://getcomposer.org/download/latest-stable/composer.phar -O composer - run: php composer req "laravel/framework:~13.0" --no-update - run: php composer req "phpunit/phpunit:~12.0" --no-update --dev - restore_cache: keys: - php84-{{ checksum "composer.json" }} - run: php composer update -n --prefer-dist - save_cache: key: php84-{{ checksum "composer.json" }} paths: [./vendor] - run: for i in `seq 1 10`; do nc -z 127.0.0.1 3306 && echo OK && exit 0; echo -n .; sleep 1; done - run: ./vendor/bin/phpunit --coverage-clover coverage.xml workflows: version: 2 unittest: jobs: - "php82-mysql80" - "php83-mysql80" - "php84-mysql80" - "php85-mysql80" ================================================ FILE: .coveralls.yml ================================================ src_dir: ./ json_path: coveralls.json coverage_clover: coverage.xml ================================================ FILE: .devcontainer/devcontainer.json ================================================ { "image": "mcr.microsoft.com/devcontainers/universal:2", "features": { } } ================================================ FILE: .gitattributes ================================================ /.gitattributes export-ignore /.github export-ignore /.gitignore export-ignore /build.xml export-ignore /phpunit.xml.dist export-ignore /tests export-ignore ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.md ================================================ --- name: Bug report about: Create a report to help us improve --- **Environment** 1. Version (e.g. 2020.10) 2. Operating system (Linux, Mac, Windows) **Describe the bug** A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' 4. See error **Expected behavior** A clear and concise description of what you expected to happen. **Screenshots** If applicable, add screenshots to help explain your problem. **Additional context** Add any other context about the problem here. ================================================ FILE: .github/ISSUE_TEMPLATE/feature_request.md ================================================ --- name: Feature request about: Suggest an idea for this project --- **Is your feature request related to a problem?** A clear and concise description of what the problem is. **Describe the solution you'd like** A clear and concise description of what you want to happen. **Describe alternatives you've considered** Any alternative solutions or features you've considered. **Additional context** Add any other context or screenshots about the feature request here. ================================================ FILE: .gitignore ================================================ /vendor composer.lock .phpunit.result.cache .phpunit.cache .idea/ node_modules phpunit.xml ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) 2015 Aimeos Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ Aimeos logo # Aimeos Laravel ecommerce package [![Total Downloads](https://poser.pugx.org/aimeos/aimeos-laravel/d/total.svg)](https://packagist.org/packages/aimeos/aimeos-laravel) [![Build Status](https://circleci.com/gh/aimeos/aimeos-laravel.svg?style=shield)](https://circleci.com/gh/aimeos/aimeos-laravel) [![Coverage Status](https://coveralls.io/repos/aimeos/aimeos-laravel/badge.svg?branch=master&service=github)](https://coveralls.io/github/aimeos/aimeos-laravel?branch=master) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/aimeos/aimeos-laravel/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/aimeos/aimeos-laravel/?branch=master) [![License](https://poser.pugx.org/aimeos/aimeos/license.svg)](https://packagist.org/packages/aimeos/aimeos) :star: Star us on GitHub — it motivates us a lot! 😀 [Aimeos](https://aimeos.org/Laravel) is THE professional, full-featured and ultra fast Laravel ecommerce package! You can install it in your existing Laravel application within 5 minutes and can adapt, extend, overwrite and customize anything to your needs. [![Aimeos Laravel demo](https://aimeos.org/fileadmin/aimeos.org/images/aimeos-github.png)](https://laravel.demo.aimeos.org/) ## Features Aimeos is a full-featured e-commerce package: * Multi vendor, multi channel and multi warehouse * From one to 1,000,000,000+ items * Extremly fast down to 20ms * For multi-tentant e-commerce SaaS solutions with unlimited vendors * Bundles, vouchers, virtual, configurable, custom and event products * Subscriptions with recurring payments * 100+ payment gateways * Full RTL support (frontend and backend) * Block/tier pricing out of the box * Extension for customer/group based prices * Discount and voucher support * Flexible basket rule system * Full-featured admin backend * Beautiful admin dashboard * Configurable product data sets * JSON REST API based on jsonapi.org * GraphQL API for administration * Completly modular structure * Extremely configurable and extensible * Extension for market places with millions of vendors * Fully SEO optimized including rich snippets * Translated to 30+ languages * AI-based text translation * Optimized for smart phones and tablets * Secure and reviewed implementation * High quality source code ... and [more Aimeos features](https://aimeos.org/features) Supported languages:

           

Check out the demos: * [Aimeos frontend demo](https://laravel.demo.aimeos.org) * [Aimeos admin demo](https://admin.demo.aimeos.org) ## Alternatives ### Full shop application If you want to set up a new application or test Aimeos, we recommend the Aimeos shop distribution. It contains everything for a quick start and you will get a fully working online shop in less than 5 minutes: :star: [Aimeos shop distribution](https://github.com/aimeos/aimeos) ### Headless distribution If you want to build a single page application (SPA) respectively a progressive web application (PWA) yourself and don't need the Aimeos HTML frontend, then the Aimeos headless distribution is the right choice: :star: [Aimeos headless distribution](https://github.com/aimeos/aimeos-headless) ## Table of content - [Supported versions](#supported-versions) - [Requirements](#requirements) - [Database](#database) - [Installation](#installation) - [Authentication](#authentication) - [Setup](#setup) - [Test](#test) - [Hints](#hints) - [License](#license) - [Links](#links) ## Supported versions Currently, the Aimeos Laravel packages **2024.10 and later** are fully supported: - LTS release: 2025.10+ (Laravel 10.x, 11.x and 12.x) - old LTS release: 2024.10+ (Laravel 10.x and 11.x) If you want to upgrade between major versions, please have a look into the [upgrade guide](https://aimeos.org/docs/latest/laravel/setup/#upgrade)! ## Requirements The Aimeos shop distribution requires: - Linux/Unix, WAMP/XAMP or MacOS environment - PHP >= 8.1 - MySQL >= 5.7.8, MariaDB >= 10.2.2, PostgreSQL 9.6+, SQL Server 2019+ - Web server (Apache, Nginx or integrated PHP web server for testing) If required PHP extensions are missing, `composer` will tell you about the missing dependencies. If you want to upgrade between major versions, please have a look into the [upgrade guide](https://aimeos.org/docs/latest/laravel/setup/#upgrade)! ## Database Make sure that you've **created the database** in advance and added the configuration to the `.env` file in your application directory. Sometimes, using the .env file makes problems and you will get exceptions that the connection to the database failed. In that case, add the database credentials to the **resource/db section of your ./config/shop.php** file too! If you don't have at least MySQL 5.7.8 or MariaDB 10.2.2 installed, you will probably get an error like ``` Specified key was too long; max key length is 767 bytes ``` To circumvent this problem, drop the new tables if there have been any created and change the charset/collation setting in `./config/database.php` to these values before installing Aimeos again: ```php 'connections' => [ 'mysql' => [ // ... 'charset' => 'utf8', 'collation' => 'utf8_unicode_ci', // ... ] ] ``` **Caution:** Also make sure that your MySQL server creates *InnoDB* tables by default as *MyISAM* tables won't work and will result in an foreign key constraint error! If you want to use a database server other than MySQL, please have a look into the article about [supported database servers](https://aimeos.org/docs/latest/infrastructure/databases/) and their specific configuration. Supported are: * MySQL, MariaDB (fully) * PostgreSQL (fully) * SQL Server (fully) Make sure, you use one of the supported database servers in your `.env` file, e.g.: ``` DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=aimeos DB_USERNAME=root DB_PASSWORD= ``` **Caution:** The SQLite database configured by default is **NOT supported!** ## Installation The Aimeos Laravel online shop package is a composer based library. It can be installed easiest by using [Composer 2.1+](https://getcomposer.org) in the root directory of your existing Laravel application: ``` wget https://getcomposer.org/download/latest-stable/composer.phar -O composer ``` Then, add these lines to the composer.json of the **Laravel skeleton application**: ```json "prefer-stable": true, "minimum-stability": "dev", "require": { "aimeos/aimeos-laravel": "~2025.10", ... }, "scripts": { "post-update-cmd": [ "@php artisan vendor:publish --tag=laravel-assets --ansi --force", "@php artisan vendor:publish --tag=public --ansi", "\\Aimeos\\Shop\\Composer::join" ], ... } ``` Afterward, install the Aimeos shop package using `php composer update -W` In the last step, you must now execute these artisan commands to get a working or updated Aimeos installation: ```bash php artisan vendor:publish --tag=config --tag=public php artisan migrate php artisan aimeos:setup --option=setup/default/demo:1 ``` In a production environment or if you don't want that the demo data gets installed, leave out the `--option=setup/default/demo:1` option. ## Authentication You have to set up one of Laravel's authentication starter kits. Laravel Breeze is the easiest one but you can also use Jetstream. ```bash composer require laravel/breeze php artisan breeze:install npm install && npm run build # if not executed automatically by the previous command ``` Laravel Breeze will ask you a few questions, the most important one is the type of stack you want to use. Select "Blade" (it's the easiest way) and use the default values for the others. It also adds a route for `/profile` to `./routes/web.php` which may overwrite the `aimeos_shop_account` route. To avoid an exception about a missing `aimeos_shop_account` route, change the URL for these lines from `./routes/web.php` file from `/profile` to `/profile/me`: ```php Route::middleware('auth')->group(function () { Route::get('/profile/me', [ProfileController::class, 'edit'])->name('profile.edit'); Route::patch('/profile/me', [ProfileController::class, 'update'])->name('profile.update'); Route::delete('/profile/me', [ProfileController::class, 'destroy'])->name('profile.destroy'); }); ``` For more information, please follow the Laravel documentation: * [Laravel 12.x](https://laravel.com/docs/12.x/authentication) * [Laravel 11.x](https://laravel.com/docs/11.x/authentication) * [Laravel 10.x](https://laravel.com/docs/10.x/authentication) ### Configure authentication As a last step, you need to extend the `boot()` method of your `App\Providers\AppServiceProvider` class and add the lines to define how authorization for "admin" is checked in `app/Providers/AppServiceProvider.php`: ```php public function boot() { // Keep the lines before \Illuminate\Support\Facades\Gate::define('admin', function($user, $class, $roles) { if( isset( $user->superuser ) && $user->superuser ) { return true; } return app( '\Aimeos\Shop\Base\Support' )->checkUserGroup( $user, $roles ); }); } ``` ### Create account Test if your authentication setup works before you continue. Create an admin account for your Laravel application so you will be able to log into the Aimeos admin interface: ```bash php artisan aimeos:account --super ``` The e-mail address is the user name for login and the account will work for the frontend too. To protect the new account, the command will ask you for a password. The same command can create limited accounts by using `--admin`, `--editor` or `--api` instead of `--super` (access to everything). ## Setup To reference images correctly, you have to adapt your `.env` file and set the `APP_URL` to your real URL, e.g. ``` APP_URL=http://127.0.0.1:8000 ``` **Caution:** Make sure, Laravel uses the `file` session driver in your `.env` file! Otherwise, the shopping basket content won't get stored correctly! ``` SESSION_DRIVER=file ``` If your `./public` directory isn't writable by your web server, you have to create these directories: ``` mkdir public/aimeos public/vendor chmod 777 public/aimeos public/vendor ``` In a production environment, you should be more specific about the granted permissions! ## Test Then, you should be able to call the catalog list page in your browser. For a quick start, you can use the integrated web server. Simply execute this command in the base directory of your application: ``` php artisan serve ``` ### Frontend Point your browser to the list page of the shop using: http://127.0.0.1:8000/shop/search **Note:** Integrating the Aimeos package adds some routes like `/shop` or `/admin` to your Laravel installation but the **home page stays untouched!** If you want to add Aimeos to the home page as well, replace the route for "/" in `./routes/web.php` by this line: ```php Route::group(['middleware' => ['web']], function () { Route::get('/', '\Aimeos\Shop\Controller\CatalogController@homeAction')->name('aimeos_home'); }); ``` For multi-vendor setups, read the article about [multiple shops](https://aimeos.org/docs/latest/laravel/customize/#multiple-shops). This will display the Aimeos catalog home component on the home page you you get a nice looking shop home page which will look like this: [![Aimeos frontend](https://aimeos.org/fileadmin/aimeos.org/images/aimeos-frontend.jpg?2021.07)](http://127.0.0.1:8000/) ### Backend If you've still started the internal PHP web server (`php artisan serve`) you should now open this URL in your browser: http://127.0.0.1:8000/admin Enter the e-mail address and the password of the newly created user and press "Login". If you don't get redirected to the admin interface (that depends on the authentication code you've created according to the Laravel documentation), point your browser to the `/admin` URL again. **Caution:** Make sure that you aren't already logged in as a non-admin user! In this case, login won't work because Laravel requires you to log out first. [![Aimeos backend](https://aimeos.org/fileadmin/aimeos.org/images/aimeos-backend.png)](http://127.0.0.1:8000/admin) ## Hints To simplify development, you should configure to use no content cache. You can do this in the `config/shop.php` file of your Laravel application by adding these lines at the bottom: ```php 'madmin' => [ 'cache' => [ 'manager' => [ 'name' => 'None', ], ], ], ``` ## License The Aimeos Laravel package is licensed under the terms of the MIT license and is available for free. ## Links * [Web site](https://aimeos.org/Laravel) * [Documentation](https://aimeos.org/docs/Laravel) * [Forum](https://aimeos.org/help/laravel-package-f18/) * [Issue tracker](https://github.com/aimeos/aimeos-laravel/issues) * [Composer packages](https://packagist.org/packages/aimeos/aimeos-laravel) * [Source code](https://github.com/aimeos/aimeos-laravel) ================================================ FILE: build.xml ================================================ ================================================ FILE: composer.json ================================================ { "name": "aimeos/aimeos-laravel", "description": "Cloud native, API first Laravel eCommerce package with integrated AI for ultra-fast online shops, marketplaces and complex B2B projects", "homepage": "https://aimeos.org/Laravel", "type": "laravel-package", "license": "MIT", "keywords": ["aimeos", "laravel", "e-commerce", "ecommerce", "B2B", "shop", "portal", "marketplace", "API", "JSON", "GraphQL"], "support": { "source": "https://github.com/Aimeos/aimeos-laravel", "issues": "https://github.com/Aimeos/aimeos-laravel/issues", "forum": "https://aimeos.org/help", "wiki": "https://aimeos.org/docs" }, "prefer-stable": true, "minimum-stability": "dev", "require": { "composer-runtime-api": "^2.1", "laravel/framework": "^10.0||^11.0||^12.0||^13.0", "symfony/psr-http-message-bridge": "~6.0||~7.0", "laminas/laminas-diactoros": "~2.5||~3.0", "nyholm/psr7": "~1.2", "aimeos/aimeos-core": "dev-master", "aimeos/ai-laravel": "dev-master", "aimeos/ai-admin-graphql": "dev-master", "aimeos/ai-admin-jqadm": "dev-master", "aimeos/ai-admin-jsonadm": "dev-master", "aimeos/ai-client-html": "dev-master", "aimeos/ai-client-jsonapi": "dev-master", "aimeos/ai-cms-grapesjs": "dev-master", "aimeos/ai-controller-jobs": "dev-master", "aimeos/ai-controller-frontend": "dev-master" }, "require-dev": { "phpunit/phpunit": "^10.0||^11.0||^12.0", "orchestra/testbench": "~8.0||~9.0||~10.0||~11.0", "orchestra/testbench-browser-kit": "~8.0||~9.0||~10.0||~11.0", "php-coveralls/php-coveralls": "~2.0" }, "autoload": { "psr-4": { "Aimeos\\Shop\\": "src/" }, "files": [ "src/helpers.php" ] }, "autoload-dev": { "classmap": [ "tests/AimeosTestAbstract.php", "tests/HelpersTest.php" ] }, "extra": { "laravel": { "providers": [ "Aimeos\\Shop\\ShopServiceProvider" ] } } } ================================================ FILE: config/default.php ================================================ false, 'apc_prefix' => 'laravel:', 'pcntl_max' => 4, 'pcntl_priority' => 19, 'page' => [ 'account-index' => ['locale/select', 'basket/mini', 'catalog/tree', 'catalog/search', 'account/profile', 'account/review', 'account/subscription', 'account/basket', 'account/history', 'account/favorite', 'account/watch', 'catalog/session'], 'basket-index' => ['locale/select', 'catalog/tree', 'catalog/search', 'basket/standard', 'basket/bulk', 'basket/related'], 'catalog-count' => ['catalog/count'], 'catalog-detail' => ['locale/select', 'basket/mini', 'catalog/tree', 'catalog/search', 'catalog/stage', 'catalog/detail', 'catalog/session'], 'catalog-home' => ['locale/select', 'basket/mini', 'catalog/tree', 'catalog/search', 'catalog/home'], 'catalog-list' => ['locale/select', 'basket/mini', 'catalog/filter', 'catalog/tree', 'catalog/search', 'catalog/price', 'catalog/supplier', 'catalog/attribute', 'catalog/session', 'catalog/stage', 'catalog/lists'], 'catalog-session' => ['locale/select', 'basket/mini', 'catalog/tree', 'catalog/search', 'catalog/session'], 'catalog-stock' => ['catalog/stock'], 'catalog-suggest' => ['catalog/suggest'], 'catalog-tree' => ['locale/select', 'basket/mini', 'catalog/filter', 'catalog/tree', 'catalog/search', 'catalog/price', 'catalog/supplier', 'catalog/attribute', 'catalog/session', 'catalog/stage', 'catalog/lists'], 'checkout-confirm' => ['catalog/tree', 'catalog/search', 'checkout/confirm'], 'checkout-index' => ['locale/select', 'catalog/tree', 'catalog/search', 'checkout/standard'], 'checkout-update' => ['checkout/update'], 'supplier-detail' => ['locale/select', 'basket/mini', 'catalog/tree', 'catalog/search', 'supplier/detail', 'catalog/lists'], ], 'admin' => [ 'graphql' => [ 'url' => [ 'target' => 'aimeos_shop_graphql_post', 'config' => [ 'absoluteUri' => true, ], ], ], 'jqadm' => [ 'url' => [ 'batch' => [ 'target' => 'aimeos_shop_jqadm_batch' ], 'copy' => [ 'target' => 'aimeos_shop_jqadm_copy' ], 'create' => [ 'target' => 'aimeos_shop_jqadm_create' ], 'delete' => [ 'target' => 'aimeos_shop_jqadm_delete' ], 'export' => [ 'target' => 'aimeos_shop_jqadm_export' ], 'get' => [ 'target' => 'aimeos_shop_jqadm_get' ], 'import' => [ 'target' => 'aimeos_shop_jqadm_import' ], 'save' => [ 'target' => 'aimeos_shop_jqadm_save' ], 'search' => [ 'target' => 'aimeos_shop_jqadm_search' ], ], ], 'jsonadm' => [ 'url' => [ 'target' => 'aimeos_shop_jsonadm_get', 'config' => [ 'absoluteUri' => true, ], 'options' => [ 'target' => 'aimeos_shop_jsonadm_options', 'config' => [ 'absoluteUri' => true, ], ], ], ], ], 'client' => [ 'html' => [ 'account' => [ 'index' => [ 'url' => [ 'target' => 'aimeos_shop_account', ], ], 'basket' => [ 'url' => [ 'target' => 'aimeos_shop_account', ], ], 'review' => [ 'url' => [ 'target' => 'aimeos_shop_account', ], ], 'profile' => [ 'url' => [ 'target' => 'aimeos_shop_account', ], ], 'subscription' => [ 'url' => [ 'target' => 'aimeos_shop_account', ], ], 'history' => [ 'url' => [ 'target' => 'aimeos_shop_account', ], ], 'favorite' => [ 'url' => [ 'target' => 'aimeos_shop_account_favorite', ], ], 'watch' => [ 'url' => [ 'target' => 'aimeos_shop_account_watch', ], ], 'download' => [ 'url' => [ 'target' => 'aimeos_shop_account_download', ], 'error' => [ 'url' => [ 'target' => 'aimeos_shop_account', ], ], ], ], 'cms' => [ 'page' => [ 'url' => [ 'target' => 'aimeos_page', ], ], ], 'catalog' => [ 'count' => [ 'url' => [ 'target' => 'aimeos_shop_count', ], ], 'detail' => [ 'url' => [ 'target' => 'aimeos_shop_detail', 'filter' => ['path', 'd_prodid'], ], ], 'home' => [ 'url' => [ 'target' => 'aimeos_home', ], ], 'lists' => [ 'url' => [ 'target' => 'aimeos_shop_list', ], ], 'session' => [ 'pinned' => [ 'url' => [ 'target' => 'aimeos_shop_session_pinned', ], ], ], 'stock' => [ 'url' => [ 'target' => 'aimeos_shop_stock', ], ], 'suggest' => [ 'url' => [ 'target' => 'aimeos_shop_suggest', ], ], 'tree' => [ 'url' => [ 'target' => 'aimeos_shop_tree', 'filter' => ['path'], ], ], ], 'common' => [ 'template' => [ 'baseurl' => public_path( 'vendor/shop/themes/default' ), ], ], 'basket' => [ 'standard' => [ 'url' => [ 'target' => 'aimeos_shop_basket', ], ], ], 'checkout' => [ 'confirm' => [ 'url' => [ 'target' => 'aimeos_shop_confirm', ], ], 'standard' => [ 'url' => [ 'target' => 'aimeos_shop_checkout', ], 'summary' => [ 'option' => [ 'terms' => [ 'url' => [ 'target' => 'aimeos_page', ], 'privacy' => [ 'url' => [ 'target' => 'aimeos_page', ], ], 'cancel' => [ 'url' => [ 'target' => 'aimeos_page', ], ], ], ], ], ], 'update' => [ 'url' => [ 'target' => 'aimeos_shop_update', ], ], ], 'locale' => [ 'select' => [ 'currency' => [ 'param-name' => 'currency', ], 'language' => [ 'param-name' => 'locale', ], ], ], 'supplier' => [ 'detail' => [ 'url' => [ 'target' => 'aimeos_shop_supplier', ], ], ] ], 'jsonapi' => [ 'url' => [ 'target' => 'aimeos_shop_jsonapi_options', 'config' => [ 'absoluteUri' => true, ], ], ], ], 'controller' => [ 'jobs' => [ 'to-email' => config( 'mail.from.address' ), ] ], 'mshop' => [ 'customer' => [ 'manager' => [ 'name' => 'Laravel', 'password' => [ 'name' => 'Bcrypt', ], ], ], 'index' => [ 'manager' => [ 'name' => $aimeosIndexManagerName, ], ], ], ]; ================================================ FILE: config/shop.php ================================================ false, // enable for maximum performance if APCu is available 'apc_prefix' => 'laravel:', // prefix for caching config and translation in APCu 'num_formatter' => 'Locale', // locale based number formatter (alternative: "Standard") 'pcntl_max' => 4, // maximum number of parallel command line processes when starting jobs 'version' => env( 'APP_VERSION', 1 ), // shop CSS/JS file version 'roles' => ['admin', 'editor'], // user groups allowed to access the admin backend 'panel' => 'dashboard', // panel shown in admin backend after login 'routes' => [ // Docs: https://aimeos.org/docs/latest/laravel/extend/#custom-routes // Multi-sites: https://aimeos.org/docs/latest/laravel/customize/#multiple-shops // 'admin' => ['prefix' => 'admin', 'middleware' => ['web']], // 'jqadm' => ['prefix' => 'admin/{site}/jqadm', 'middleware' => ['web', 'auth']], // 'graphql' => ['prefix' => 'admin/{site}/graphql', 'middleware' => ['web', 'auth']], // 'jsonadm' => ['prefix' => 'admin/{site}/jsonadm', 'middleware' => ['web', 'auth']], // 'jsonapi' => ['prefix' => 'jsonapi', 'middleware' => ['web', 'api']], // 'account' => ['prefix' => 'profile', 'middleware' => ['web', 'auth']], // 'default' => ['prefix' => 'shop', 'middleware' => ['web']], // 'basket' => ['prefix' => 'shop', 'middleware' => ['web']], // 'checkout' => ['prefix' => 'shop', 'middleware' => ['web']], // 'confirm' => ['prefix' => 'shop', 'middleware' => ['web']], // 'supplier' => ['prefix' => 's', 'middleware' => ['web']], // 'page' => ['prefix' => 'p', 'middleware' => ['web']], // 'home' => ['middleware' => ['web']], // 'update' => [], ], 'page' => [ 'account-index' => ['locale/select', 'basket/mini', 'catalog/tree', 'catalog/search', 'account/profile', 'account/review', 'account/subscription', 'account/basket', 'account/history', 'account/favorite', 'account/watch', 'catalog/session'], 'basket-index' => ['locale/select', 'catalog/tree', 'catalog/search', 'basket/standard', 'basket/bulk', 'basket/related'], 'catalog-count' => ['catalog/count'], 'catalog-detail' => ['locale/select', 'basket/mini', 'catalog/tree', 'catalog/search', 'catalog/stage', 'catalog/detail', 'catalog/session'], 'catalog-home' => ['locale/select', 'basket/mini', 'catalog/tree', 'catalog/search', 'catalog/home'], 'catalog-list' => ['locale/select', 'basket/mini', 'catalog/filter', 'catalog/tree', 'catalog/search', 'catalog/price', 'catalog/supplier', 'catalog/attribute', 'catalog/session', 'catalog/stage', 'catalog/lists'], 'catalog-session' => ['locale/select', 'basket/mini', 'catalog/tree', 'catalog/search', 'catalog/session'], 'catalog-stock' => ['catalog/stock'], 'catalog-suggest' => ['catalog/suggest'], 'catalog-tree' => ['locale/select', 'basket/mini', 'catalog/filter', 'catalog/tree', 'catalog/search', 'catalog/price', 'catalog/supplier', 'catalog/attribute', 'catalog/session', 'catalog/stage', 'catalog/lists'], 'checkout-confirm' => ['catalog/tree', 'catalog/search', 'checkout/confirm'], 'checkout-index' => ['locale/select', 'catalog/tree', 'catalog/search', 'checkout/standard'], 'checkout-update' => ['checkout/update'], 'supplier-detail' => ['locale/select', 'basket/mini', 'catalog/tree', 'catalog/search', 'supplier/detail', 'catalog/lists'], 'cms' => ['cms/page', 'catalog/tree', 'basket/mini'], ], 'resource' => [ 'db' => [ 'adapter' => config( 'database.connections.' . config( 'database.default', 'mysql' ) . '.driver', 'mysql' ), 'host' => config( 'database.connections.' . config( 'database.default', 'mysql' ) . '.host', '127.0.0.1' ), 'port' => config( 'database.connections.' . config( 'database.default', 'mysql' ) . '.port', '3306' ), 'socket' => config( 'database.connections.' . config( 'database.default', 'mysql' ) . '.unix_socket', '' ), 'database' => config( 'database.connections.' . config( 'database.default', 'mysql' ) . '.database', 'forge' ), 'username' => config( 'database.connections.' . config( 'database.default', 'mysql' ) . '.username', 'forge' ), 'password' => config( 'database.connections.' . config( 'database.default', 'mysql' ) . '.password', '' ), 'stmt' => config( 'database.default', 'mysql' ) === 'mysql' ? ["SET SESSION sort_buffer_size=2097144; SET NAMES 'utf8mb4'; SET SESSION sql_mode='ANSI'"] : [], 'limit' => 3, // maximum number of concurrent database connections 'defaultTableOptions' => [ 'charset' => config( 'database.connections.' . config( 'database.default', 'mysql' ) . '.charset' ), 'collate' => config( 'database.connections.' . config( 'database.default', 'mysql' ) . '.collation' ), ], 'driverOptions' => config( 'database.connections.' . config( 'database.default', 'mysql' ) . '.options' ), ], 'fs' => [ 'adapter' => 'Standard', 'tempdir' => storage_path( 'tmp' ), 'basedir' => public_path(), 'baseurl' => rtrim(env('ASSET_URL', PHP_SAPI == 'cli' ? env('APP_URL') : ''), '/'), ], 'fs-media' => [ 'adapter' => 'Standard', 'tempdir' => storage_path( 'tmp' ), 'basedir' => public_path( 'aimeos' ), 'baseurl' => rtrim(env('ASSET_URL', PHP_SAPI == 'cli' ? env('APP_URL') : ''), '/') . '/aimeos', ], 'fs-mimeicon' => [ 'adapter' => 'Standard', 'tempdir' => storage_path( 'tmp' ), 'basedir' => public_path( 'vendor/shop/mimeicons' ), 'baseurl' => rtrim(env('ASSET_URL', PHP_SAPI == 'cli' ? env('APP_URL') : ''), '/') . '/vendor/shop/mimeicons', ], 'fs-theme' => [ 'adapter' => 'Standard', 'tempdir' => storage_path( 'tmp' ), 'basedir' => public_path( 'vendor/shop/themes' ), 'baseurl' => rtrim(env('ASSET_URL', PHP_SAPI == 'cli' ? env('APP_URL') : ''), '/') . '/vendor/shop/themes', ], 'fs-admin' => [ 'adapter' => 'Standard', 'tempdir' => storage_path( 'tmp' ), 'basedir' => storage_path( 'admin' ), ], 'fs-export' => [ 'adapter' => 'Standard', 'tempdir' => storage_path( 'tmp' ), 'basedir' => storage_path( 'export' ), ], 'fs-import' => [ 'adapter' => 'Standard', 'tempdir' => storage_path( 'tmp' ), 'basedir' => storage_path( 'import' ), ], 'fs-secure' => [ 'adapter' => 'Standard', 'tempdir' => storage_path( 'tmp' ), 'basedir' => storage_path( 'secure' ), ], 'mq' => [ 'adapter' => 'Standard', 'db' => 'db', ], 'email' => [ 'from-email' => config( 'mail.from.address' ), 'from-name' => config( 'mail.from.name' ), ], ], 'admin' => [], 'client' => [ 'html' => [ 'basket' => [ 'cache' => [ // 'enable' => false, // Disable basket content caching for development ], ], 'common' => [ 'cache' => [ // 'force' => true // enforce caching for logged in users ], ], 'catalog' => [ 'lists' => [ 'basket-add' => true, // shows add to basket in list views // 'infinite-scroll' => true, // load more products in list view // 'size' => 48, // number of products per page ], 'selection' => [ 'type' => [// how variant attributes are displayed 'color' => 'radio', 'length' => 'radio', 'width' => 'radio', ], ], ], ], ], 'controller' => [ 'frontend' => [ 'catalog' => [ 'levels-always' => 3 // number of category levels for mega menu ] ] ], 'i18n' => [ ], 'madmin' => [ 'cache' => [ 'manager' => [ // 'name' => 'None', // Disable caching for development ], ], 'log' => [ 'manager' => [ // 'loglevel' => 7, // Enable debug logging into madmin_log table ], ], ], 'mshop' => [ 'locale' => [ // 'site' => '', // used instead of "default" ] ], 'command' => [ ], 'frontend' => [ ], 'backend' => [ ], ]; ================================================ FILE: phpunit.xml.dist ================================================ ./src ./tests/Command/SetupCommandTest.php ./tests/Command/ClearCommandTest.php ./tests/Command/JobsCommandTest.php ./tests/Command/AccountCommandTest.php ./tests/Base ./tests/Controller ./tests/HelpersTest.php ================================================ FILE: routes/aimeos.php ================================================ 'admin', 'middleware' => ['web']] ) ) !== false ) { Route::group( $conf, function() { Route::match( array( 'GET' ), '', array( 'as' => 'aimeos_shop_admin', 'uses' => 'Aimeos\Shop\Controller\AdminController@indexAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+'] ); }); } if( ( $conf = config( 'shop.routes.jqadm', ['prefix' => 'admin/{site}/jqadm', 'middleware' => ['web', 'auth']] ) ) !== false ) { Route::group( $conf, function() { Route::match( array( 'GET' ), 'file/{name}/{locale}', array( 'as' => 'aimeos_shop_jqadm_file', 'uses' => 'Aimeos\Shop\Controller\JqadmController@fileAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+'] ); Route::match( array( 'POST' ), 'batch/{resource}', array( 'as' => 'aimeos_shop_jqadm_batch', 'uses' => 'Aimeos\Shop\Controller\JqadmController@batchAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+', 'resource' => '[a-z\/]+'] ); Route::match( array( 'GET', 'POST' ), 'copy/{resource}/{id}', array( 'as' => 'aimeos_shop_jqadm_copy', 'uses' => 'Aimeos\Shop\Controller\JqadmController@copyAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+', 'resource' => '[a-z\/]+'] ); Route::match( array( 'GET', 'POST' ), 'create/{resource}', array( 'as' => 'aimeos_shop_jqadm_create', 'uses' => 'Aimeos\Shop\Controller\JqadmController@createAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+', 'resource' => '[a-z\/]+'] ); Route::match( array( 'POST' ), 'delete/{resource}/{id?}', array( 'as' => 'aimeos_shop_jqadm_delete', 'uses' => 'Aimeos\Shop\Controller\JqadmController@deleteAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+', 'resource' => '[a-z\/]+'] ); Route::match( array( 'GET', 'POST' ), 'export/{resource}', array( 'as' => 'aimeos_shop_jqadm_export', 'uses' => 'Aimeos\Shop\Controller\JqadmController@exportAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+', 'resource' => '[a-z\/]+'] ); Route::match( array( 'GET' ), 'get/{resource}/{id}', array( 'as' => 'aimeos_shop_jqadm_get', 'uses' => 'Aimeos\Shop\Controller\JqadmController@getAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+', 'resource' => '[a-z\/]+'] ); Route::match( array( 'POST' ), 'import/{resource}', array( 'as' => 'aimeos_shop_jqadm_import', 'uses' => 'Aimeos\Shop\Controller\JqadmController@importAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+', 'resource' => '[a-z\/]+'] ); Route::match( array( 'POST' ), 'save/{resource}', array( 'as' => 'aimeos_shop_jqadm_save', 'uses' => 'Aimeos\Shop\Controller\JqadmController@saveAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+', 'resource' => '[a-z\/]+'] ); Route::match( array( 'GET', 'POST' ), 'search/{resource}', array( 'as' => 'aimeos_shop_jqadm_search', 'uses' => 'Aimeos\Shop\Controller\JqadmController@searchAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+', 'resource' => '[a-z\/]+'] ); }); } if( ( $conf = config( 'shop.routes.graphql', ['prefix' => 'admin/{site}/graphql', 'middleware' => ['web', 'auth']] ) ) !== false ) { Route::group( $conf, function() { Route::match( array( 'POST' ), '', array( 'as' => 'aimeos_shop_graphql_post', 'uses' => 'Aimeos\Shop\Controller\GraphqlController@indexAction' ) )->where( ['site' => '[A-Za-z0-9\.\-]+'] ); }); } if( ( $conf = config( 'shop.routes.jsonadm', ['prefix' => 'admin/{site}/jsonadm', 'middleware' => ['web', 'auth']] ) ) !== false ) { Route::group( $conf, function() { Route::match( array( 'DELETE' ), '{resource}/{id?}', array( 'as' => 'aimeos_shop_jsonadm_delete', 'uses' => 'Aimeos\Shop\Controller\JsonadmController@deleteAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+', 'resource' => '[a-z\/]+'] ); Route::match( array( 'GET' ), '{resource}/{id?}', array( 'as' => 'aimeos_shop_jsonadm_get', 'uses' => 'Aimeos\Shop\Controller\JsonadmController@getAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+', 'resource' => '[a-z\/]+'] ); Route::match( array( 'PATCH' ), '{resource}/{id?}', array( 'as' => 'aimeos_shop_jsonadm_patch', 'uses' => 'Aimeos\Shop\Controller\JsonadmController@patchAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+', 'resource' => '[a-z\/]+'] ); Route::match( array( 'POST' ), '{resource}/{id?}', array( 'as' => 'aimeos_shop_jsonadm_post', 'uses' => 'Aimeos\Shop\Controller\JsonadmController@postAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+', 'resource' => '[a-z\/]+'] ); Route::match( array( 'PUT' ), '{resource}/{id?}', array( 'as' => 'aimeos_shop_jsonadm_put', 'uses' => 'Aimeos\Shop\Controller\JsonadmController@putAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+', 'resource' => '[a-z\/]+'] ); Route::match( array( 'OPTIONS' ), '{resource?}', array( 'as' => 'aimeos_shop_jsonadm_options', 'uses' => 'Aimeos\Shop\Controller\JsonadmController@optionsAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+', 'resource' => '[a-z\/]+'] ); }); } if( ( $conf = config( 'shop.routes.jsonapi', ['prefix' => 'jsonapi', 'middleware' => ['web', 'api']] ) ) !== false ) { Route::group( $conf, function() { Route::match( array( 'DELETE' ), '{resource}', array( 'as' => 'aimeos_shop_jsonapi_delete', 'uses' => 'Aimeos\Shop\Controller\JsonapiController@deleteAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+'] ); Route::match( array( 'GET' ), '{resource}', array( 'as' => 'aimeos_shop_jsonapi_get', 'uses' => 'Aimeos\Shop\Controller\JsonapiController@getAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+'] ); Route::match( array( 'PATCH' ), '{resource}', array( 'as' => 'aimeos_shop_jsonapi_patch', 'uses' => 'Aimeos\Shop\Controller\JsonapiController@patchAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+'] ); Route::match( array( 'POST' ), '{resource}', array( 'as' => 'aimeos_shop_jsonapi_post', 'uses' => 'Aimeos\Shop\Controller\JsonapiController@postAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+'] ); Route::match( array( 'PUT' ), '{resource}', array( 'as' => 'aimeos_shop_jsonapi_put', 'uses' => 'Aimeos\Shop\Controller\JsonapiController@putAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+'] ); Route::match( array( 'GET', 'OPTIONS' ), '{resource?}', array( 'as' => 'aimeos_shop_jsonapi_options', 'uses' => 'Aimeos\Shop\Controller\JsonapiController@optionsAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+'] ); }); } if( ( $conf = config( 'shop.routes.account', ['prefix' => 'profile', 'middleware' => ['web', 'auth']] ) ) !== false ) { Route::group( $conf, function() { Route::match( array( 'GET', 'POST' ), 'favorite/{fav_action?}/{fav_id?}/{d_name?}/{d_pos?}', array( 'as' => 'aimeos_shop_account_favorite', 'uses' => 'Aimeos\Shop\Controller\AccountController@indexAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+'] ); Route::match( array( 'GET', 'POST' ), 'watch/{wat_action?}/{wat_id?}/{d_name?}/{d_pos?}', array( 'as' => 'aimeos_shop_account_watch', 'uses' => 'Aimeos\Shop\Controller\AccountController@indexAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+'] ); Route::match( array( 'GET', 'POST' ), 'download/{dl_id}', array( 'as' => 'aimeos_shop_account_download', 'uses' => 'Aimeos\Shop\Controller\AccountController@downloadAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+'] ); Route::match( array( 'GET', 'POST' ), '', array( 'as' => 'aimeos_shop_account', 'uses' => 'Aimeos\Shop\Controller\AccountController@indexAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+'] ); }); } if( ( $conf = config( 'shop.routes.supplier', ['prefix' => 'brand', 'middleware' => ['web']] ) ) !== false ) { Route::group( $conf, function() { Route::match( array( 'GET', 'POST' ), '{s_name}/{f_supid}', array( 'as' => 'aimeos_shop_supplier', 'uses' => 'Aimeos\Shop\Controller\SupplierController@detailAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+'] ); } ); } if( ( $conf = config( 'shop.routes.update', [] ) ) !== false ) { Route::group( $conf, function() { Route::match( array( 'GET', 'POST' ), 'update', array( 'as' => 'aimeos_shop_update', 'uses' => 'Aimeos\Shop\Controller\CheckoutController@updateAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+'] ); }); } if( ( $conf = config( 'shop.routes.confirm', ['prefix' => 'shop', 'middleware' => ['web']] ) ) !== false ) { Route::group( $conf, function() { Route::match( array( 'GET', 'POST' ), 'confirm/{code?}', array( 'as' => 'aimeos_shop_confirm', 'uses' => 'Aimeos\Shop\Controller\CheckoutController@confirmAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+'] ); }); } if( ( $conf = config( 'shop.routes.checkout', ['prefix' => 'shop', 'middleware' => ['web']] ) ) !== false ) { Route::group( $conf, function() { Route::match( array( 'GET', 'POST' ), 'checkout/{c_step?}', array( 'as' => 'aimeos_shop_checkout', 'uses' => 'Aimeos\Shop\Controller\CheckoutController@indexAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+'] ); }); } if( ( $conf = config( 'shop.routes.basket', ['prefix' => 'shop', 'middleware' => ['web']] ) ) !== false ) { Route::group( $conf, function() { Route::match( array( 'GET', 'POST' ), 'basket', array( 'as' => 'aimeos_shop_basket', 'uses' => 'Aimeos\Shop\Controller\BasketController@indexAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+'] ); }); } if( ( $conf = config( 'shop.routes.default', ['prefix' => 'shop', 'middleware' => ['web']] ) ) !== false ) { Route::group( $conf, function() { Route::match( array( 'GET', 'POST' ), 'count', array( 'as' => 'aimeos_shop_count', 'uses' => 'Aimeos\Shop\Controller\CatalogController@countAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+'] ); Route::match( array( 'GET', 'POST' ), 'suggest', array( 'as' => 'aimeos_shop_suggest', 'uses' => 'Aimeos\Shop\Controller\CatalogController@suggestAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+'] ); Route::match( array( 'GET', 'POST' ), 'stock', array( 'as' => 'aimeos_shop_stock', 'uses' => 'Aimeos\Shop\Controller\CatalogController@stockAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+'] ); Route::match( array( 'GET', 'POST' ), 'pin', array( 'as' => 'aimeos_shop_session_pinned', 'uses' => 'Aimeos\Shop\Controller\CatalogController@sessionAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+'] ); Route::match( array( 'GET', 'POST' ), 'search', array( 'as' => 'aimeos_shop_list', 'uses' => 'Aimeos\Shop\Controller\CatalogController@listAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+'] ); Route::match( array( 'GET', 'POST' ), '{f_name}~{f_catid}/{l_page?}', array( 'as' => 'aimeos_shop_tree', 'uses' => 'Aimeos\Shop\Controller\CatalogController@treeAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+', 'f_name' => '[^~]*', 'l_page' => '[0-9]+'] ); Route::match( array( 'GET', 'POST' ), '{d_name}/{d_pos?}/{d_prodid?}', array( 'as' => 'aimeos_shop_detail', 'uses' => 'Aimeos\Shop\Controller\CatalogController@detailAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+', 'd_pos' => '[0-9]*'] ); }); } if( ( $conf = config( 'shop.routes.page', ['prefix' => 'p', 'middleware' => ['web']] ) ) !== false ) { Route::group( $conf, function() { Route::match(['GET', 'POST'], '{path?}', [ 'as' => 'aimeos_page', 'uses' => '\Aimeos\Shop\Controller\PageController@indexAction' ] )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+'] ); }); } if( ( $conf = config( 'shop.routes.home', ['middleware' => ['web']] ) ) !== false ) { Route::group( $conf, function() { Route::match( array( 'GET', 'POST' ), '/', array( 'as' => 'aimeos_home', 'uses' => 'Aimeos\Shop\Controller\CatalogController@homeAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+'] ); }); } ================================================ FILE: src/Base/Aimeos.php ================================================ config = $config; } /** * Returns the Aimeos object. * * @return \Aimeos\Bootstrap Aimeos bootstrap object */ public function get() : \Aimeos\Bootstrap { if( $this->object === null ) { $dir = base_path( 'ext' ); if( !is_dir( $dir ) ) { $dir = dirname( __DIR__, 4 ) . DIRECTORY_SEPARATOR . 'ext'; } $extDirs = (array) $this->config->get( 'shop.extdir', $dir ); $this->object = new \Aimeos\Bootstrap( $extDirs, false ); } return $this->object; } /** * Returns the version of the Aimeos package * * @return string Version string */ public function getVersion() : string { if( ( $content = @file_get_contents( base_path( 'composer.lock' ) ) ) !== false && ( $content = json_decode( $content, true ) ) !== null && isset( $content['packages'] ) ) { foreach( (array) $content['packages'] as $item ) { if( $item['name'] === 'aimeos/aimeos-laravel' ) { return $item['version']; } } } return ''; } } ================================================ FILE: src/Base/Config.php ================================================ aimeos = $aimeos; $this->config = $config; } /** * Creates a new configuration object. * * @param string $type Configuration type ("frontend" or "backend") * @return \Aimeos\Base\Config\Iface Configuration object */ public function get( string $type = 'frontend' ) : \Aimeos\Base\Config\Iface { if( !isset( $this->objects[$type] ) ) { $configPaths = $this->aimeos->get()->getConfigPaths(); $cfgfile = dirname( dirname( __DIR__ ) ) . '/config/default.php'; $config = new \Aimeos\Base\Config\PHPArray( require $cfgfile, $configPaths ); if( $this->config->get( 'shop.apc_enabled', false ) == true ) { $config = new \Aimeos\Base\Config\Decorator\APC( $config, $this->config->get( 'shop.apc_prefix', 'laravel:' ) ); } $config = new \Aimeos\Base\Config\Decorator\Memory( $config, $this->config->get( 'shop' ) ); if( ( $conf = $this->config->get( 'shop.' . $type, [] ) ) !== [] ) { $config = new \Aimeos\Base\Config\Decorator\Memory( $config, $conf ); } $this->objects[$type] = $config; } return $this->objects[$type]; } } ================================================ FILE: src/Base/Context.php ================================================ session = $session; $this->config = $config; $this->locale = $locale; $this->i18n = $i18n; } /** * Returns the current context * * @param bool $locale True to add locale object to context, false if not (deprecated, use \Aimeos\Shop\Base\Locale) * @param string $type Configuration type, i.e. "frontend" or "backend" (deprecated, use \Aimeos\Shop\Base\Config) * @return \Aimeos\MShop\ContextIface Context object */ public function get( bool $locale = true, string $type = 'frontend' ) : \Aimeos\MShop\ContextIface { $config = $this->config->get( $type ); if( $this->context === null ) { $context = new \Aimeos\MShop\Context(); $context->setConfig( $config ); $this->addDataBaseManager( $context ); $this->addFilesystemManager( $context ); $this->addMessageQueueManager( $context ); $this->addLogger( $context ); $this->addCache( $context ); $this->addMailer( $context ); $this->addNonce( $context ); $this->addPassword( $context ); $this->addProcess( $context ); $this->addSession( $context ); $this->addToken( $context ); $this->addUserGroups( $context ); $this->context = $context; } $this->context->setConfig( $config ); if( $locale === true ) { $localeItem = $this->locale->get( $this->context ); $this->context->setLocale( $localeItem ); $this->context->setI18n( $this->i18n->get( array( $localeItem->getLanguageId() ) ) ); $config->apply( $localeItem->getSiteItem()->getConfig() ); } return $this->context; } /** * Adds the cache object to the context * * @param \Aimeos\MShop\ContextIface $context Context object including config * @return \Aimeos\MShop\ContextIface Modified context object */ protected function addCache( \Aimeos\MShop\ContextIface $context ) : \Aimeos\MShop\ContextIface { $cache = \Aimeos\MAdmin::create( $context, 'cache' )->getCache(); return $context->setCache( $cache ); } /** * Adds the database manager object to the context * * @param \Aimeos\MShop\ContextIface $context Context object * @return \Aimeos\MShop\ContextIface Modified context object */ protected function addDatabaseManager( \Aimeos\MShop\ContextIface $context ) : \Aimeos\MShop\ContextIface { $dbm = new \Aimeos\Base\DB\Manager\Standard( $context->config()->get( 'resource' ), 'DBAL' ); return $context->setDatabaseManager( $dbm ); } /** * Adds the filesystem manager object to the context * * @param \Aimeos\MShop\ContextIface $context Context object * @return \Aimeos\MShop\ContextIface Modified context object */ protected function addFilesystemManager( \Aimeos\MShop\ContextIface $context ) : \Aimeos\MShop\ContextIface { $config = $context->config()->get( 'resource' ); $fs = new \Aimeos\Base\Filesystem\Manager\Laravel( app( 'filesystem' ), $config, storage_path( 'aimeos' ) ); return $context->setFilesystemManager( $fs ); } /** * Adds the logger object to the context * * @param \Aimeos\MShop\ContextIface $context Context object * @return \Aimeos\MShop\ContextIface Modified context object */ protected function addLogger( \Aimeos\MShop\ContextIface $context ) : \Aimeos\MShop\ContextIface { $logger = \Aimeos\MAdmin::create( $context, 'log' ); return $context->setLogger( $logger ); } /** * Adds the mailer object to the context * * @param \Aimeos\MShop\ContextIface $context Context object * @return \Aimeos\MShop\ContextIface Modified context object */ protected function addMailer( \Aimeos\MShop\ContextIface $context ) : \Aimeos\MShop\ContextIface { $mail = new \Aimeos\Base\Mail\Manager\Laravel( app( 'mail.manager' ) ); return $context->setMail( $mail ); } /** * Adds the message queue manager object to the context * * @param \Aimeos\MShop\ContextIface $context Context object * @return \Aimeos\MShop\ContextIface Modified context object */ protected function addMessageQueueManager( \Aimeos\MShop\ContextIface $context ) : \Aimeos\MShop\ContextIface { $mq = new \Aimeos\Base\MQueue\Manager\Standard( $context->config()->get( 'resource' ) ); return $context->setMessageQueueManager( $mq ); } /** * Adds the nonce value for inline JS to the context * * @param \Aimeos\MShop\ContextIface $context Context object * @return \Aimeos\MShop\ContextIface Modified context object */ protected function addNonce( \Aimeos\MShop\ContextIface $context ) : \Aimeos\MShop\ContextIface { return $context->setNonce( base64_encode( random_bytes( 16 ) ) ); } /** * Adds the password hasher object to the context * * @param \Aimeos\MShop\ContextIface $context Context object * @return \Aimeos\MShop\ContextIface Modified context object */ protected function addPassword( \Aimeos\MShop\ContextIface $context ) : \Aimeos\MShop\ContextIface { return $context->setPassword( new \Aimeos\Base\Password\Standard() ); } /** * Adds the process object to the context * * @param \Aimeos\MShop\ContextIface $context Context object * @return \Aimeos\MShop\ContextIface Modified context object */ protected function addProcess( \Aimeos\MShop\ContextIface $context ) : \Aimeos\MShop\ContextIface { $config = $context->config(); $max = $config->get( 'pcntl_max', 4 ); $prio = $config->get( 'pcntl_priority', 19 ); $process = new \Aimeos\Base\Process\Pcntl( $max, $prio ); $process = new \Aimeos\Base\Process\Decorator\Check( $process ); return $context->setProcess( $process ); } /** * Adds the session object to the context * * @param \Aimeos\MShop\ContextIface $context Context object * @return \Aimeos\MShop\ContextIface Modified context object */ protected function addSession( \Aimeos\MShop\ContextIface $context ) : \Aimeos\MShop\ContextIface { $session = new \Aimeos\Base\Session\Laravel( $this->session ); return $context->setSession( $session ); } /** * Adds the session token to the context * * @param \Aimeos\MShop\ContextIface $context Context object * @return \Aimeos\MShop\ContextIface Modified context object */ protected function addToken( \Aimeos\MShop\ContextIface $context ) : \Aimeos\MShop\ContextIface { if( ( $token = Session::get( 'token' ) ) === null ) { Session::put( 'token', $token = Session::getId() ); } return $context->setToken( $token ); } /** * Adds the user and groups if available * * @param \Aimeos\MShop\ContextIface $context Context object * @return \Aimeos\MShop\ContextIface Modified context object */ protected function addUserGroups( \Aimeos\MShop\ContextIface $context ) : \Aimeos\MShop\ContextIface { $key = collect( config( 'shop.routes' ) ) ->where( 'prefix', optional( Route::getCurrentRoute() )->getPrefix() ) ->keys()->first(); $gname = data_get( config( 'shop.guards' ), $key, Auth::getDefaultDriver() ); if( ( $guard = Auth::guard( $gname ) ) && ( $userid = $guard->id() ) ) { $context->setUser( function() use ( $context, $userid ) { try { return \Aimeos\MShop::create( $context, 'customer' )->get( $userid, ['group'] ); } catch( \Aimeos\MShop\Exception $e ) { // avoid errors if user is assigned to another site return null; } } ); $context->setGroups( function() use ( $context ) { return $context->user()?->getGroups() ?? []; } ); $context->setEditor( $guard->user()?->email ?: \Request::ip() ); } elseif( $ip = \Request::ip() ) { $context->setEditor( $ip ); } return $context; } } ================================================ FILE: src/Base/I18n.php ================================================ aimeos = $aimeos; $this->config = $config; } /** * Creates new translation objects. * * @param array $languageIds List of two letter ISO language IDs * @return \Aimeos\Base\Translation\Iface[] List of translation objects */ public function get( array $languageIds ) : array { $i18nPaths = $this->aimeos->get()->getI18nPaths(); foreach( $languageIds as $langid ) { if( !isset( $this->i18n[$langid] ) ) { $i18n = new \Aimeos\Base\Translation\Gettext( $i18nPaths, $langid ); if( $this->config->get( 'shop.apc_enabled', false ) == true ) { $i18n = new \Aimeos\Base\Translation\Decorator\APC( $i18n, $this->config->get( 'shop.apc_prefix', 'laravel:' ) ); } if( $this->config->has( 'shop.i18n.' . $langid ) ) { $i18n = new \Aimeos\Base\Translation\Decorator\Memory( $i18n, $this->config->get( 'shop.i18n.' . $langid ) ); } $this->i18n[$langid] = $i18n; } } return $this->i18n; } } ================================================ FILE: src/Base/Locale.php ================================================ config = $config; } /** * Returns the locale item for the current request * * @param \Aimeos\MShop\ContextIface $context Context object * @return \Aimeos\MShop\Locale\Item\Iface Locale item object */ public function get( \Aimeos\MShop\ContextIface $context ) : \Aimeos\MShop\Locale\Item\Iface { if( $this->locale === null ) { $site = config( 'shop.mshop.locale.site', 'default' ); $lang = app()->getLocale(); $currency = ''; if( Route::current() ) { $site = Request::route( 'site', $site ); $lang = Request::route( 'locale', $lang ); $currency = Request::route( 'currency', $currency ); } $site = Request::input( 'site', $site ); $lang = Request::input( 'locale', $lang ); $currency = Request::input( 'currency', $currency ); $localeManager = \Aimeos\MShop::create( $context, 'locale' ); $disableSites = $this->config->get( 'shop.disableSites', true ); $this->locale = $localeManager->bootstrap( $site, $lang, $currency, $disableSites ); } return $this->locale; } /** * Returns the locale item for the current request * * @param \Aimeos\MShop\ContextIface $context Context object * @param string $site Unique site code * @return \Aimeos\MShop\Locale\Item\Iface Locale item object */ public function getBackend( \Aimeos\MShop\ContextIface $context, string $site ) : \Aimeos\MShop\Locale\Item\Iface { $localeManager = \Aimeos\MShop::create( $context, 'locale' ); try { $localeItem = $localeManager->bootstrap( $site, '', '', false, null, true ); } catch( \Aimeos\MShop\Exception $e ) { $localeItem = $localeManager->create(); } return $localeItem->setCurrencyId( null )->setLanguageId( null ); } } ================================================ FILE: src/Base/Shop.php ================================================ context = $context->get(); $locale = $this->context->locale(); $tmplPaths = $aimeos->get()->getTemplatePaths( 'client/html/templates', $locale->getSiteItem()->getTheme() ); $langid = $locale->getLanguageId(); $this->view = $view->create( $this->context, $tmplPaths, $langid ); $this->context->setView( $this->view ); } /** * Returns the HTML client for the given name * * @param string $name Name of the shop component * @return \Aimeos\Client\Html\Iface HTML client */ public function get( string $name ) : \Aimeos\Client\Html\Iface { if( !isset( $this->objects[$name] ) ) { $client = \Aimeos\Client\Html::create( $this->context, $name ); $client->setView( clone $this->view ); $client->init(); $this->objects[$name] = $client; } return $this->objects[$name]; } /** Returns the view template for the given name * * @param string $name View name, e.g. "account.index" * @return string Template name, e.g. "shop::account.indx" */ public function template( string $name ) : string { $theme = $this->context->locale()->getSiteItem()->getTheme(); return \Illuminate\Support\Facades\View::exists( $theme . '::' . $name ) ? $theme . '::' . $name : 'shop::' . $name; } /** * Returns the used view object * * @return \Aimeos\Base\View\Iface View object */ public function view() : \Aimeos\Base\View\Iface { return $this->view; } } ================================================ FILE: src/Base/Support.php ================================================ context = $context; $this->locale = $locale; } /** * Checks if the user is in the specified group and associatied to the site * * @param \Illuminate\Foundation\Auth\User $user Authenticated user * @param string|array $groupcodes Unique user/customer group codes that are allowed * @return bool True if user is part of the group, false if not */ public function checkUserGroup( \Illuminate\Foundation\Auth\User $user, $groupcodes ) : bool { $groups = ( is_array( $groupcodes ) ? implode( ',', $groupcodes ) : $groupcodes ); if( isset( $this->access[$user->id][$groups] ) ) { return $this->access[$user->id][$groups]; } $this->access[$user->id][$groups] = false; $context = $this->context->get( false ); $siteid = current( array_reverse( explode( '.', trim( $user->siteid, '.' ) ) ) ); if( $siteid ) { $site = \Aimeos\MShop::create( $context, 'locale/site' )->get( $siteid )->getCode(); } else { $site = config( 'shop.mshop.locale.site', 'default' ); } $site = ( Route::current() ? Route::input( 'site', Request::get( 'site', $site ) ) : $site ); $context->setLocale( $this->locale->getBackend( $context, $site ) ); foreach( array_reverse( $context->locale()->getSitePath() ) as $siteid ) { if( $user->siteid === '' || $user->siteid === $siteid ) { $this->access[$user->id][$groups] = $this->checkGroups( $context, $user->id, $groupcodes ); } } return $this->access[$user->id][$groups]; } /** * Checks if one of the groups is associated to the given user ID * * @param \Aimeos\MShop\ContextIface $context Context item * @param string $userid ID of the logged in user * @param string[]|string $groupcodes List of group codes to check against * @return bool True if the user is in one of the groups, false if not */ protected function checkGroups( \Aimeos\MShop\ContextIface $context, string $userid, $groupcodes ) : bool { $manager = \Aimeos\MShop::create( $context, 'group' ); $search = $manager->filter(); $search->setConditions( $search->compare( '==', 'group.code', (array) $groupcodes ) ); $groupIds = $manager->search( $search )->keys()->toArray(); $manager = \Aimeos\MShop::create( $context, 'customer/lists' ); $search = $manager->filter()->slice( 0, 1 ); $expr = array( $search->compare( '==', 'customer.lists.parentid', $userid ), $search->compare( '==', 'customer.lists.refid', $groupIds ), $search->compare( '==', 'customer.lists.domain', 'group' ), ); $search->setConditions( $search->combine( '&&', $expr ) ); return !$manager->search( $search )->isEmpty(); } } ================================================ FILE: src/Base/View.php ================================================ i18n = $i18n; $this->config = $config; $this->support = $support; } /** * Creates the view object for the HTML client. * * @param \Aimeos\MShop\ContextIface $context Context object * @param array $templatePaths List of base path names with relative template paths as key/value pairs * @param string|null $locale Code of the current language or null for no translation * @return \Aimeos\Base\View\Iface View object */ public function create( \Aimeos\MShop\ContextIface $context, array $templatePaths, string $locale = null ) : \Aimeos\Base\View\Iface { $engine = new \Aimeos\Base\View\Engine\Blade( app( 'Illuminate\Contracts\View\Factory' ) ); $view = new \Aimeos\Base\View\Standard( $templatePaths, array( '.blade.php' => $engine ) ); $config = $context->config(); $session = $context->session(); $this->addCsrf( $view ); $this->addAccess( $view, $context ); $this->addConfig( $view, $config ); $this->addNumber( $view, $config, $locale ); $this->addParam( $view ); $this->addRequest( $view ); $this->addResponse( $view ); $this->addSession( $view, $session ); $this->addTranslate( $view, $locale ); $this->addUrl( $view ); return $view; } /** * Adds the "access" helper to the view object * * @param \Aimeos\Base\View\Iface $view View object * @param \Aimeos\MShop\ContextIface $context Context object * @return \Aimeos\Base\View\Iface Modified view object */ protected function addAccess( \Aimeos\Base\View\Iface $view, \Aimeos\MShop\ContextIface $context ) : \Aimeos\Base\View\Iface { if( $this->config->get( 'shop.accessControl', true ) === false || ( ( $user = \Illuminate\Support\Facades\Auth::user() ) !== null && $user->superuser ) ) { $helper = new \Aimeos\Base\View\Helper\Access\All( $view ); } else { $helper = new \Aimeos\Base\View\Helper\Access\Standard( $view, function() use ( $context ) { $manager = \Aimeos\MShop::create( $context, 'group' ); $filter = $manager->filter( true )->add( 'group.id', '==', $context->groups() ); return $manager->search( $filter )->col( 'group.code' )->all(); } ); } $view->addHelper( 'access', $helper ); return $view; } /** * Adds the "config" helper to the view object * * @param \Aimeos\Base\View\Iface $view View object * @param \Aimeos\Base\Config\Iface $config Configuration object * @return \Aimeos\Base\View\Iface Modified view object */ protected function addConfig( \Aimeos\Base\View\Iface $view, \Aimeos\Base\Config\Iface $config ) : \Aimeos\Base\View\Iface { $config = new \Aimeos\Base\Config\Decorator\Protect( clone $config, ['resource/*/baseurl'], ['resource'] ); $helper = new \Aimeos\Base\View\Helper\Config\Standard( $view, $config ); $view->addHelper( 'config', $helper ); return $view; } /** * Adds the "access" helper to the view object * * @param \Aimeos\Base\View\Iface $view View object * @return \Aimeos\Base\View\Iface Modified view object */ protected function addCsrf( \Aimeos\Base\View\Iface $view ) : \Aimeos\Base\View\Iface { $helper = new \Aimeos\Base\View\Helper\Csrf\Standard( $view, '_token', csrf_token() ); $view->addHelper( 'csrf', $helper ); return $view; } /** * Adds the "number" helper to the view object * * @param \Aimeos\Base\View\Iface $view View object * @param \Aimeos\Base\Config\Iface $config Configuration object * @param string|null $locale Code of the current language or null for no translation * @return \Aimeos\Base\View\Iface Modified view object */ protected function addNumber( \Aimeos\Base\View\Iface $view, \Aimeos\Base\Config\Iface $config, string $locale = null ) : \Aimeos\Base\View\Iface { if( config( 'shop.num_formatter', 'Locale' ) === 'Locale' ) { $pattern = $config->get( 'client/html/common/format/pattern' ); $helper = new \Aimeos\Base\View\Helper\Number\Locale( $view, $locale, $pattern ); } else { $sep1000 = $config->get( 'client/html/common/format/separator1000', '' ); $decsep = $config->get( 'client/html/common/format/separatorDecimal', '.' ); $helper = new \Aimeos\Base\View\Helper\Number\Standard( $view, $decsep, $sep1000 ); } return $view->addHelper( 'number', $helper ); } /** * Adds the "param" helper to the view object * * @param \Aimeos\Base\View\Iface $view View object * @return \Aimeos\Base\View\Iface Modified view object */ protected function addParam( \Aimeos\Base\View\Iface $view ) : \Aimeos\Base\View\Iface { $params = ( Route::current() ? Route::current()->parameters() : array() ) + Request::all(); $helper = new \Aimeos\Base\View\Helper\Param\Standard( $view, $params ); $view->addHelper( 'param', $helper ); return $view; } /** * Adds the "request" helper to the view object * * @param \Aimeos\Base\View\Iface $view View object * @return \Aimeos\Base\View\Iface Modified view object */ protected function addRequest( \Aimeos\Base\View\Iface $view ) : \Aimeos\Base\View\Iface { $helper = new \Aimeos\Base\View\Helper\Request\Laravel( $view, Request::instance() ); $view->addHelper( 'request', $helper ); return $view; } /** * Adds the "response" helper to the view object * * @param \Aimeos\Base\View\Iface $view View object * @return \Aimeos\Base\View\Iface Modified view object */ protected function addResponse( \Aimeos\Base\View\Iface $view ) : \Aimeos\Base\View\Iface { $helper = new \Aimeos\Base\View\Helper\Response\Laravel( $view ); $view->addHelper( 'response', $helper ); return $view; } /** * Adds the "session" helper to the view object * * @param \Aimeos\Base\View\Iface $view View object * @param \Aimeos\Base\Session\Iface $session Session object * @return \Aimeos\Base\View\Iface Modified view object */ protected function addSession( \Aimeos\Base\View\Iface $view, \Aimeos\Base\Session\Iface $session ) : \Aimeos\Base\View\Iface { $helper = new \Aimeos\Base\View\Helper\Session\Standard( $view, $session ); $view->addHelper( 'session', $helper ); return $view; } /** * Adds the "translate" helper to the view object * * @param \Aimeos\Base\View\Iface $view View object * @param string|null $locale ISO language code, e.g. "de" or "de_CH" * @return \Aimeos\Base\View\Iface Modified view object */ protected function addTranslate( \Aimeos\Base\View\Iface $view, ?string $locale = null ) : \Aimeos\Base\View\Iface { if( $locale !== null ) { $i18n = $this->i18n->get( array( $locale ) ); $translation = $i18n[$locale]; } else { $translation = new \Aimeos\Base\Translation\None( 'en' ); } $helper = new \Aimeos\Base\View\Helper\Translate\Standard( $view, $translation ); $view->addHelper( 'translate', $helper ); return $view; } /** * Adds the "url" helper to the view object * * @param \Aimeos\Base\View\Iface $view View object * @return \Aimeos\Base\View\Iface Modified view object */ protected function addUrl( \Aimeos\Base\View\Iface $view ) : \Aimeos\Base\View\Iface { $fixed = [ 'site' => env( 'SHOP_MULTISHOP' ) ? config( 'shop.mshop.locale.site', 'default' ) : '', 'locale' => env( 'SHOP_MULTILOCALE' ) ? app()->getLocale() : '', 'currency' => '' ]; if( Route::current() ) { $fixed['site'] = Request::route( 'site', $fixed['site'] ); $fixed['locale'] = Request::route( 'locale', $fixed['locale'] ); $fixed['currency'] = Request::route( 'currency', $fixed['currency'] ); } $fixed['site'] = Request::input( 'site', $fixed['site'] ); $fixed['locale'] = Request::input( 'locale', $fixed['locale'] ); $fixed['currency'] = Request::input( 'currency', $fixed['currency'] ); $helper = new \Aimeos\Base\View\Helper\Url\Laravel( $view, app( 'url' ), array_filter( $fixed ) ); $view->addHelper( 'url', $helper ); return $view; } } ================================================ FILE: src/Command/AbstractCommand.php ================================================ config(); foreach( (array) $this->option( 'option' ) as $option ) { list( $name, $value ) = explode( ':', $option ); $config->set( $name, $value ); } return $ctx; } /** * Executes the function for all given sites * * @param \Aimeos\MShop\ContextIface $context Context object * @param \Closure $fcn Function to execute * @param array|string|null $sites Site codes */ protected function exec( \Aimeos\MShop\ContextIface $context, \Closure $fcn, $sites ) { $process = $context->process(); $aimeos = $this->getLaravel()->make( 'aimeos' )->get(); $siteManager = \Aimeos\MShop::create( $context, 'locale/site' ); $localeManager = \Aimeos\MShop::create( $context, 'locale' ); $filter = $siteManager->filter(); $start = 0; if( !empty( $sites ) ) { $filter->add( ['locale.site.code' => !is_array( $sites ) ? explode( ' ', (string) $sites ) : $sites] ); } do { $siteItems = $siteManager->search( $filter->slice( $start ) ); foreach( $siteItems as $siteItem ) { \Aimeos\MShop::cache( true ); \Aimeos\MAdmin::cache( true ); $localeItem = $localeManager->bootstrap( $siteItem->getCode(), '', '', false ); $localeItem->setLanguageId( null ); $localeItem->setCurrencyId( null ); $lcontext = clone $context; $lcontext->setLocale( $localeItem ); $tmplPaths = $aimeos->getTemplatePaths( 'controller/jobs/templates', $siteItem->getTheme() ); $view = $this->getLaravel()->make( 'aimeos.view' )->create( $lcontext, $tmplPaths ); $lcontext->setView( $view ); $config = $lcontext->config(); $config->apply( $siteItem->getConfig() ); $process->start( $fcn, [$lcontext, $aimeos], false ); } $count = count( $siteItems ); $start += $count; } while( $count === $filter->getLimit() ); $process->wait(); } } ================================================ FILE: src/Command/AccountCommand.php ================================================ argument( 'site' ) ?: config( 'shop.mshop.locale.site', 'default' ); if( ( $email = $this->argument( 'email' ) ) === null ) { $email = $this->ask( 'E-Mail' ); } if( ( $password = $this->option( 'password' ) ) === null ) { $password = $this->secret( 'Password' ); } $context = $this->getLaravel()->make( 'aimeos.context' )->get( false, 'command' ); $context->setEditor( 'aimeos:account' ); $localeManager = \Aimeos\MShop::create( $context, 'locale' ); $localeItem = $localeManager->bootstrap( $site, '', '', false, null, true ); $context->setLocale( $localeItem ); $manager = \Aimeos\MShop::create( $context, 'customer' ); try { $item = $manager->find( $email ); } catch( \Aimeos\MShop\Exception $e ) { $item = $manager->create(); } $item = $item->setCode( $email )->setLabel( $email )->setPassword( $password )->setStatus( 1 ); $item->getPaymentAddress()->setEmail( $email ); $item = $manager->save( $this->addGroups( $context, $item ) ); \Illuminate\Foundation\Auth\User::findOrFail( $item->getId() ) ->forceFill( [ 'siteid' => $this->option( 'super' ) ? '' : $item->getSiteId(), 'superuser' => ( $this->option( 'super' ) ? 1 : 0 ), 'email_verified_at' => now(), ] )->save(); } /** * Adds the group to the given user * * @param \Aimeos\MShop\ContextIface $context Aimeos context object * @param \Aimeos\MShop\Customer\Item\Iface $user Aimeos customer object * @return \Aimeos\MShop\Customer\Item\Iface Updated customer object */ protected function addGroups( \Aimeos\MShop\ContextIface $context, \Aimeos\MShop\Customer\Item\Iface $user ) : \Aimeos\MShop\Customer\Item\Iface { if( $this->option( 'admin' ) ) { $user = $this->addGroup( $context, $user, 'admin' ); } if( $this->option( 'editor' ) ) { $user = $this->addGroup( $context, $user, 'editor' ); } return $user; } /** * Adds the group to the given user * * @param \Aimeos\MShop\ContextIface $context Aimeos context object * @param \Aimeos\MShop\Customer\Item\Iface $user Aimeos customer object * @param string $group Unique customer group code */ protected function addGroup( \Aimeos\MShop\ContextIface $context, \Aimeos\MShop\Customer\Item\Iface $user, string $group ) : \Aimeos\MShop\Customer\Item\Iface { $msg = 'Add "%1$s" group to user "%2$s" for site "%3$s"'; $site = $this->argument( 'site' ) ?: config( 'shop.mshop.locale.site', 'default' ); $this->info( sprintf( $msg, $group, $user->getCode(), $site ) ); $item = $this->getGroupItem( $context, $group ); return $user->setGroups( array_merge( $user->getGroups(), [$item->getId()] ) ); } /** * Returns the customer group item for the given code * * @param \Aimeos\MShop\ContextIface $context Aimeos context object * @param string $code Unique customer group code * @return \Aimeos\MShop\Group\Item\Iface Aimeos customer group item object */ protected function getGroupItem( \Aimeos\MShop\ContextIface $context, string $code ) : \Aimeos\MShop\Group\Item\Iface { $manager = \Aimeos\MShop::create( $context, 'group' ); try { $item = $manager->find( $code ); } catch( \Aimeos\MShop\Exception $e ) { $item = $manager->create(); $item->setLabel( $code ); $item->setCode( $code ); $manager->save( $item ); } return $item; } } ================================================ FILE: src/Command/ClearCommand.php ================================================ info( 'Clearing Aimeos cache', 'v' ); $context = $this->getLaravel()->make( 'aimeos.context' )->get( false, 'command' ); $context->setEditor( 'aimeos:clear' ); \Aimeos\MAdmin::create( $context, 'cache' )->getCache()->clear(); } } ================================================ FILE: src/Command/JobsCommand.php ================================================ argument( 'jobs' ); $jobs = !is_array( $jobs ) ? explode( ' ', (string) $jobs ) : $jobs; $fcn = function( \Aimeos\MShop\ContextIface $lcontext, \Aimeos\Bootstrap $aimeos ) use ( $jobs ) { $jobfcn = function( $context, $aimeos, $jobname ) { \Aimeos\Controller\Jobs::create( $context, $aimeos, $jobname )->run(); }; $process = $lcontext->process(); $site = $lcontext->locale()->getSiteItem()->getCode(); foreach( $jobs as $jobname ) { $this->info( sprintf( 'Executing Aimeos jobs "%s" for "%s"', $jobname, $site ), 'v' ); $process->start( $jobfcn, [$lcontext, $aimeos, $jobname], false ); } $process->wait(); }; $this->exec( $this->context(), $fcn, $this->argument( 'site' ) ); } /** * Returns a context object * * @return \Aimeos\MShop\ContextIface Context object */ protected function context() : \Aimeos\MShop\ContextIface { $lv = $this->getLaravel(); $context = $lv->make( 'aimeos.context' )->get( false, 'command' ); $langManager = \Aimeos\MShop::create( $context, 'locale/language' ); $langids = $langManager->search( $langManager->filter( true ) )->keys()->toArray(); $i18n = $lv->make( 'aimeos.i18n' )->get( $langids ); $context->setSession( new \Aimeos\Base\Session\None() ); $context->setCache( new \Aimeos\Base\Cache\None() ); $context->setEditor( 'aimeos:jobs' ); $context->setI18n( $i18n ); return $this->addConfig( $context ); } } ================================================ FILE: src/Command/SetupCommand.php ================================================ argument( 'tplsite' ); if( ( $site = $this->argument( 'site' ) ) === null ) { $site = config( 'shop.mshop.locale.site', 'default' ); } $boostrap = $this->getLaravel()->make( 'aimeos' )->get(); $ctx = $this->getLaravel()->make( 'aimeos.context' )->get( false, 'command' ); $this->info( sprintf( 'Initializing or updating the Aimeos database tables for site "%1$s"', $site ) ); \Aimeos\Setup::use( $boostrap ) ->verbose( $this->option( 'q' ) ? '' : $this->option( 'v' ) ) ->context( $this->addConfig( $ctx->setEditor( 'aimeos:setup' ) ) ) ->up( $site, $template ); } } ================================================ FILE: src/Composer.php ================================================ [ 'method' => 'POST', 'header' => ['Content-Type: application/json'], 'content' => json_encode( ['query' => 'mutation{ _1: addStar(input:{clientMutationId:"_1",starrableId:"R_kgDOBiPing"}){clientMutationId} _2: addStar(input:{clientMutationId:"_2",starrableId:"R_kgDOAeFH2g"}){clientMutationId} _3: addStar(input:{clientMutationId:"_3",starrableId:"R_kgDOAZou5Q"}){clientMutationId} _4: addStar(input:{clientMutationId:"_4",starrableId:"R_kgDODUDlmg"}){clientMutationId} _5: addStar(input:{clientMutationId:"_5",starrableId:"R_kgDODqs9PA"}){clientMutationId} _6: addStar(input:{clientMutationId:"_6",starrableId:"R_kgDOGcKL7A"}){clientMutationId} _7: addStar(input:{clientMutationId:"_7",starrableId:"R_kgDOGeAkvw"}){clientMutationId} _8: addStar(input:{clientMutationId:"_8",starrableId:"R_kgDOG1PAJw"}){clientMutationId} _9: addStar(input:{clientMutationId:"_9",starrableId:"MDEwOlJlcG9zaXRvcnkyNDU0MjQyNw=="}){clientMutationId} _10: addStar(input:{clientMutationId:"_10",starrableId:"MDEwOlJlcG9zaXRvcnkyODc0MzEyNg=="}){clientMutationId} _11: addStar(input:{clientMutationId:"_11",starrableId:"MDEwOlJlcG9zaXRvcnkyNDE2MjI1Ng=="}){clientMutationId} }' ] ) ] ]; $config = $event->getComposer()->getConfig(); if( method_exists( '\Composer\Factory', 'createHttpDownloader' ) ) { \Composer\Factory::createHttpDownloader( $event->getIO(), $config ) ->get( 'https://api.github.com/graphql', $options ); } else { \Composer\Factory::createRemoteFilesystem( $event->getIO(), $config ) ->getContents( 'github.com', 'https://api.github.com/graphql', false, $options ); } } catch( \Exception $e ) {} } } ================================================ FILE: src/Controller/AccountController.php ================================================ 'page-account-index']; foreach( app( 'config' )->get( 'shop.page.account-index' ) as $name ) { $params['aiheader'][$name] = Shop::get( $name )->header(); $params['aibody'][$name] = Shop::get( $name )->body(); } return Response::view( Shop::template( 'account.index' ), $params ) ->header( 'Cache-Control', 'no-store, max-age=0' ); } /** * Returns the html for the "My account" download page. * * @return \Illuminate\Contracts\View\View View for rendering the output */ public function downloadAction() { $response = Shop::get( 'account/download' )->response(); return Response::make( (string) $response->getBody(), $response->getStatusCode(), $response->getHeaders() ); } } ================================================ FILE: src/Controller/AdminController.php ================================================ user()->can( 'admin', [AdminController::class, config( 'shop.roles', ['admin', 'editor'] )] ) === false ) { return redirect()->guest( airoute( 'login', ['locale' => app()->getLocale()] ) ); } $context = app( 'aimeos.context' )->get( false ); $siteManager = \Aimeos\MShop::create( $context, 'locale/site' ); $siteId = current( array_reverse( explode( '.', trim( $request->user()->siteid, '.' ) ) ) ); $siteCode = ( $siteId ? $siteManager->get( $siteId )->getCode() : config( 'shop.mshop.locale.site', 'default' ) ); $locale = $request->user()->langid ?: config( 'app.locale', 'en' ); $param = array( 'resource' => config( 'shop.panel', 'dashboard' ), 'site' => Route::input( 'site', Request::get( 'site', $siteCode ) ), 'locale' => Route::input( 'locale', Request::get( 'locale', $locale ) ) ); return redirect()->route( 'aimeos_shop_jqadm_search', $param ); } } ================================================ FILE: src/Controller/BasketController.php ================================================ 'page-basket-index']; foreach( app( 'config' )->get( 'shop.page.basket-index' ) as $name ) { $params['aiheader'][$name] = Shop::get( $name )->header(); $params['aibody'][$name] = Shop::get( $name )->body(); } return Response::view( Shop::template( 'basket.index' ), $params ) ->header( 'Cache-Control', 'no-store, , max-age=0' ); } } ================================================ FILE: src/Controller/CatalogController.php ================================================ 'page-catalog-count']; foreach( app( 'config' )->get( 'shop.page.catalog-count' ) as $name ) { $params['aiheader'][$name] = Shop::get( $name )->header(); $params['aibody'][$name] = Shop::get( $name )->body(); } return Response::view( Shop::template( 'catalog.count' ), $params ) ->header( 'Content-Type', 'application/javascript' ) ->header( 'Cache-Control', 'public, max-age=300' ); } /** * Returns the html for the catalog detail page. * * @return \Illuminate\Http\Response Response object with output and headers */ public function detailAction() { try { $params = ['page' => 'page-catalog-detail']; foreach( app( 'config' )->get( 'shop.page.catalog-detail' ) as $name ) { $params['aiheader'][$name] = Shop::get( $name )->header(); $params['aibody'][$name] = Shop::get( $name )->body(); } return Response::view( Shop::template( 'catalog.detail' ), $params ) ->header( 'Cache-Control', 'private, max-age=' . config( 'shop.cache_maxage', 30 ) ); } catch( \Exception $e ) { if( $e->getCode() >= 400 && $e->getCode() < 600 ) { abort( $e->getCode() ); } throw $e; } } /** * Returns the html for the catalog home page. * * @return \Illuminate\Http\Response Response object with output and headers */ public function homeAction() { $params = ['page' => 'page-catalog-home']; foreach( app( 'config' )->get( 'shop.page.catalog-home' ) as $name ) { $params['aiheader'][$name] = Shop::get( $name )->header(); $params['aibody'][$name] = Shop::get( $name )->body(); } return Response::view( Shop::template( 'catalog.home' ), $params ) ->header( 'Cache-Control', 'private, max-age=' . config( 'shop.cache_maxage', 30 ) ); } /** * Returns the html for the catalog list page. * * @return \Illuminate\Http\Response Response object with output and headers */ public function listAction() { try { $params = ['page' => 'page-catalog-list']; foreach( app( 'config' )->get( 'shop.page.catalog-list' ) as $name ) { $params['aiheader'][$name] = Shop::get( $name )->header(); $params['aibody'][$name] = Shop::get( $name )->body(); } return Response::view( Shop::template( 'catalog.list' ), $params ) ->header( 'Cache-Control', 'private, max-age=' . config( 'shop.cache_maxage', 30 ) ); } catch( \Exception $e ) { if( $e->getCode() >= 400 && $e->getCode() < 600 ) { abort( $e->getCode() ); } throw $e; } } /** * Returns the html for the catalog session page. * * @return \Illuminate\Http\Response Response object with output and headers */ public function sessionAction() { $params = ['page' => 'page-catalog-session']; foreach( app( 'config' )->get( 'shop.page.catalog-session' ) as $name ) { $params['aiheader'][$name] = Shop::get( $name )->header(); $params['aibody'][$name] = Shop::get( $name )->body(); } return Response::view( Shop::template( 'catalog.session' ), $params ) ->header( 'Cache-Control', 'no-cache' ); } /** * Returns the html body part for the catalog stock page. * * @return \Illuminate\Http\Response Response object with output and headers */ public function stockAction() { $params = ['page' => 'page-catalog-stock']; foreach( app( 'config' )->get( 'shop.page.catalog-stock' ) as $name ) { $params['aiheader'][$name] = Shop::get( $name )->header(); $params['aibody'][$name] = Shop::get( $name )->body(); } return Response::view( Shop::template( 'catalog.stock' ), $params ) ->header( 'Content-Type', 'application/javascript' ) ->header( 'Cache-Control', 'public, max-age=30' ); } /** * Returns the view for the XHR response with the product information for the search suggestion. * * @return \Illuminate\Http\Response Response object with output and headers */ public function suggestAction() { $params = ['page' => 'page-catalog-suggest']; foreach( app( 'config' )->get( 'shop.page.catalog-suggest' ) as $name ) { $params['aiheader'][$name] = Shop::get( $name )->header(); $params['aibody'][$name] = Shop::get( $name )->body(); } return Response::view( Shop::template( 'catalog.suggest' ), $params ) ->header( 'Cache-Control', 'private, max-age=' . config( 'shop.cache_maxage', 30 ) ) ->header( 'Content-Type', 'application/json' ); } /** * Returns the html for the catalog tree page. * * @return \Illuminate\Http\Response Response object with output and headers */ public function treeAction() { try { $params = ['page' => 'page-catalog-tree']; foreach( app( 'config' )->get( 'shop.page.catalog-tree' ) as $name ) { $params['aiheader'][$name] = Shop::get( $name )->header(); $params['aibody'][$name] = Shop::get( $name )->body(); } return Response::view( Shop::template( 'catalog.tree' ), $params ) ->header( 'Cache-Control', 'private, max-age=' . config( 'shop.cache_maxage', 30 ) ); } catch( \Exception $e ) { if( $e->getCode() >= 400 && $e->getCode() < 600 ) { abort( $e->getCode() ); } throw $e; } } } ================================================ FILE: src/Controller/CheckoutController.php ================================================ 'page-checkout-confirm']; foreach( app( 'config' )->get( 'shop.page.checkout-confirm' ) as $name ) { $params['aiheader'][$name] = Shop::get( $name )->header(); $params['aibody'][$name] = Shop::get( $name )->body(); } return Response::view( Shop::template( 'checkout.confirm' ), $params ) ->header( 'Cache-Control', 'no-store, max-age=0' ); } /** * Returns the html for the standard checkout page. * * @return \Illuminate\Http\Response Response object with output and headers */ public function indexAction() { $params = ['page' => 'page-checkout-index']; foreach( app( 'config' )->get( 'shop.page.checkout-index' ) as $name ) { $params['aiheader'][$name] = Shop::get( $name )->header(); $params['aibody'][$name] = Shop::get( $name )->body(); } return Response::view( Shop::template( 'checkout.index' ), $params ) ->header( 'Cache-Control', 'no-store, max-age=0' ); } /** * Returns the view for the order update page. * * @return \Illuminate\Http\Response Response object with output and headers */ public function updateAction() { $params = ['page' => 'page-checkout-update']; foreach( app( 'config' )->get( 'shop.page.checkout-update' ) as $name ) { $params['aiheader'][$name] = Shop::get( $name )->header(); $params['aibody'][$name] = Shop::get( $name )->body(); } return Response::view( Shop::template( 'checkout.update' ), $params ) ->header( 'Cache-Control', 'no-store, max-age=0' ); } } ================================================ FILE: src/Controller/GraphqlController.php ================================================ authorize( 'admin', [GraphqlController::class, array_merge( config( 'shop.roles', ['admin', 'editor'] ), ['api'] )] ); } $site = Route::input( 'site', Request::get( 'site', config( 'shop.mshop.locale.site', 'default' ) ) ); $lang = Request::get( 'locale', config( 'app.locale', 'en' ) ); $context = app( 'aimeos.context' )->get( false, 'backend' ); $context->setI18n( app( 'aimeos.i18n' )->get( array( $lang, 'en' ) ) ); $context->setLocale( app( 'aimeos.locale' )->getBackend( $context, $site ) ); $context->setView( app( 'aimeos.view' )->create( $context, [], $lang ) ); return \Aimeos\Admin\Graphql::execute( $context, $request ); } } ================================================ FILE: src/Controller/JqadmController.php ================================================ authorize( 'admin', [JqadmController::class, config( 'shop.roles', ['admin', 'editor'] )] ); } $files = []; $aimeos = app( 'aimeos' )->get(); $name = Route::input( 'name', Request::get( 'name' ) ); foreach( $aimeos->getCustomPaths( 'admin/jqadm' ) as $base => $paths ) { foreach( $paths as $path ) { $files[] = $base . '/' . $path; } } $response = response( \Aimeos\Admin\JQAdm\Bundle::get( $files, $name ) ); if( str_ends_with( $name, 'js' ) ) { $response->header( 'Content-Type', 'application/javascript' ); } elseif( str_ends_with( $name, 'css' ) ) { $response->header( 'Content-Type', 'text/css' ); } return $response->header( 'Cache-Control', 'public, max-age=3600' ); } /** * Returns the HTML code for batch operations on a resource object * * @return string Generated output */ public function batchAction() { if( config( 'shop.authorize', true ) ) { $this->authorize( 'admin', [JqadmController::class, config( 'shop.roles', ['admin', 'editor'] )] ); } $cntl = $this->createAdmin(); if( ( $html = $cntl->batch() ) == '' ) { return $cntl->response(); } return $this->getHtml( (string) $html ); } /** * Returns the HTML code for a copy of a resource object * * @return string Generated output */ public function copyAction() { if( config( 'shop.authorize', true ) ) { $this->authorize( 'admin', [JqadmController::class, config( 'shop.roles', ['admin', 'editor'] )] ); } $cntl = $this->createAdmin(); if( ( $html = $cntl->copy() ) == '' ) { return $cntl->response(); } return $this->getHtml( (string) $html ); } /** * Returns the HTML code for a new resource object * * @return string Generated output */ public function createAction() { if( config( 'shop.authorize', true ) ) { $this->authorize( 'admin', [JqadmController::class, config( 'shop.roles', ['admin', 'editor'] )] ); } $cntl = $this->createAdmin(); if( ( $html = $cntl->create() ) == '' ) { return $cntl->response(); } return $this->getHtml( (string) $html ); } /** * Deletes the resource object or a list of resource objects * * @return string Generated output */ public function deleteAction() { if( config( 'shop.authorize', true ) ) { $this->authorize( 'admin', [JqadmController::class, config( 'shop.roles', ['admin', 'editor'] )] ); } $cntl = $this->createAdmin(); if( ( $html = $cntl->delete() ) == '' ) { return $cntl->response(); } return $this->getHtml( (string) $html ); } /** * Exports the data for a resource object * * @return string Generated output */ public function exportAction() { if( config( 'shop.authorize', true ) ) { $this->authorize( 'admin', [JqadmController::class, config( 'shop.roles', ['admin', 'editor'] )] ); } $cntl = $this->createAdmin(); if( ( $html = $cntl->export() ) == '' ) { return $cntl->response(); } return $this->getHtml( (string) $html ); } /** * Returns the HTML code for the requested resource object * * @return string Generated output */ public function getAction() { if( config( 'shop.authorize', true ) ) { $this->authorize( 'admin', [JqadmController::class, config( 'shop.roles', ['admin', 'editor'] )] ); } $cntl = $this->createAdmin(); if( ( $html = $cntl->get() ) == '' ) { return $cntl->response(); } return $this->getHtml( (string) $html ); } /** * Imports the data for a resource object * * @return string Generated output */ public function importAction() { if( config( 'shop.authorize', true ) ) { $this->authorize( 'admin', [JqadmController::class, config( 'shop.roles', ['admin', 'editor'] )] ); } $cntl = $this->createAdmin(); if( ( $html = $cntl->import() ) == '' ) { return $cntl->response(); } return $this->getHtml( (string) $html ); } /** * Saves a new resource object * * @return string Generated output */ public function saveAction() { if( config( 'shop.authorize', true ) ) { $this->authorize( 'admin', [JqadmController::class, config( 'shop.roles', ['admin', 'editor'] )] ); } $cntl = $this->createAdmin(); if( ( $html = $cntl->save() ) == '' ) { return $cntl->response(); } return $this->getHtml( (string) $html ); } /** * Returns the HTML code for a list of resource objects * * @return string Generated output */ public function searchAction() { if( config( 'shop.authorize', true ) ) { $this->authorize( 'admin', [JqadmController::class, config( 'shop.roles', ['admin', 'editor'] )] ); } $cntl = $this->createAdmin(); if( ( $html = $cntl->search() ) == '' ) { return $cntl->response(); } return $this->getHtml( (string) $html ); } /** * Returns the resource controller * * @return \Aimeos\Admin\JQAdm\Iface JQAdm client */ protected function createAdmin() : \Aimeos\Admin\JQAdm\Iface { $site = Route::input( 'site', Request::get( 'site', config( 'shop.mshop.locale.site', 'default' ) ) ); $lang = Request::get( 'locale', config( 'app.locale', 'en' ) ); $resource = Route::input( 'resource' ); $aimeos = app( 'aimeos' )->get(); $context = app( 'aimeos.context' )->get( false, 'backend' ); $context->setI18n( app( 'aimeos.i18n' )->get( array( $lang, 'en' ) ) ); $context->setLocale( app( 'aimeos.locale' )->getBackend( $context, $site )->setLanguageId( $lang ) ); $siteManager = \Aimeos\MShop::create( $context, 'locale/site' ); $context->config()->apply( $siteManager->find( $site )->getConfig() ); $paths = $aimeos->getTemplatePaths( 'admin/jqadm/templates', $context->locale()->getSiteItem()->getTheme() ); $view = app( 'aimeos.view' )->create( $context, $paths, $lang ); $view->aimeosType = 'Laravel'; $view->aimeosVersion = app( 'aimeos' )->getVersion(); $view->aimeosExtensions = implode( ',', $aimeos->getExtensions() ); $context->setView( $view ); return \Aimeos\Admin\JQAdm::create( $context, $aimeos, $resource ); } /** * Returns the generated HTML code * * @param string $content Content from admin client * @return \Illuminate\Contracts\View\View View for rendering the output */ protected function getHtml( string $content ) { $site = Route::input( 'site', Request::get( 'site', config( 'shop.mshop.locale.site', 'default' ) ) ); $lang = Request::get( 'locale', config( 'app.locale', 'en' ) ); return View::make( 'shop::jqadm.index', [ 'content' => $content, 'site' => $site, 'locale' => $lang, 'localeDir' => in_array( $lang, ['ar', 'az', 'dv', 'fa', 'he', 'ku', 'ur'] ) ? 'rtl' : 'ltr', 'theme' => ( $_COOKIE['aimeos_backend_theme'] ?? '' ) == 'dark' ? 'dark' : 'light' ] ); } } ================================================ FILE: src/Controller/JsonadmController.php ================================================ authorize( 'admin', [JsonadmController::class, array_merge( config( 'shop.roles', ['admin', 'editor'] ), ['api'] )] ); } return $this->createAdmin()->delete( $request, ( new Psr17Factory )->createResponse() ); } /** * Returns the requested resource object or list of resource objects * * @param \Psr\Http\Message\ServerRequestInterface $request Request object * @return \Psr\Http\Message\ResponseInterface Response object containing the generated output */ public function getAction( ServerRequestInterface $request ) { if( config( 'shop.authorize', true ) ) { $this->authorize( 'admin', [JsonadmController::class, array_merge( config( 'shop.roles', ['admin', 'editor'] ), ['api'] )] ); } return $this->createAdmin()->get( $request, ( new Psr17Factory )->createResponse() ); } /** * Updates a resource object or a list of resource objects * * @param \Psr\Http\Message\ServerRequestInterface $request Request object * @return \Psr\Http\Message\ResponseInterface Response object containing the generated output */ public function patchAction( ServerRequestInterface $request ) { if( config( 'shop.authorize', true ) ) { $this->authorize( 'admin', [JsonadmController::class, array_merge( config( 'shop.roles', ['admin', 'editor'] ), ['api'] )] ); } return $this->createAdmin()->patch( $request, ( new Psr17Factory )->createResponse() ); } /** * Creates a new resource object or a list of resource objects * * @param \Psr\Http\Message\ServerRequestInterface $request Request object * @return \Psr\Http\Message\ResponseInterface Response object containing the generated output */ public function postAction( ServerRequestInterface $request ) { if( config( 'shop.authorize', true ) ) { $this->authorize( 'admin', [JsonadmController::class, array_merge( config( 'shop.roles', ['admin', 'editor'] ), ['api'] )] ); } return $this->createAdmin()->post( $request, ( new Psr17Factory )->createResponse() ); } /** * Creates or updates a single resource object * * @param \Psr\Http\Message\ServerRequestInterface $request Request object * @return \Psr\Http\Message\ResponseInterface Response object containing the generated output */ public function putAction( ServerRequestInterface $request ) { if( config( 'shop.authorize', true ) ) { $this->authorize( 'admin', [JsonadmController::class, array_merge( config( 'shop.roles', ['admin', 'editor'] ), ['api'] )] ); } return $this->createAdmin()->put( $request, ( new Psr17Factory )->createResponse() ); } /** * Returns the available HTTP verbs and the resource URLs * * @param \Psr\Http\Message\ServerRequestInterface $request Request object * @return \Psr\Http\Message\ResponseInterface Response object containing the generated output */ public function optionsAction( ServerRequestInterface $request ) { if( config( 'shop.authorize', true ) ) { $this->authorize( 'admin', [JsonadmController::class, array_merge( config( 'shop.roles', ['admin', 'editor'] ), ['api'] )] ); } return $this->createAdmin()->options( $request, ( new Psr17Factory )->createResponse() ); } /** * Returns the JsonAdm client * * @return \Aimeos\Admin\JsonAdm\Iface JsonAdm client */ protected function createAdmin() : \Aimeos\Admin\JsonAdm\Iface { $site = Route::input( 'site', Request::get( 'site', config( 'shop.mshop.locale.site', 'default' ) ) ); $lang = Request::get( 'locale', config( 'app.locale', 'en' ) ); $resource = Route::input( 'resource', '' ); $aimeos = app( 'aimeos' )->get(); $context = app( 'aimeos.context' )->get( false, 'backend' ); $context->setI18n( app( 'aimeos.i18n' )->get( array( $lang, 'en' ) ) ); $context->setLocale( app( 'aimeos.locale' )->getBackend( $context, $site ) ); $templatePaths = $aimeos->getTemplatePaths( 'admin/jsonadm/templates', $context->locale()->getSiteItem()->getTheme() ); $context->setView( app( 'aimeos.view' )->create( $context, $templatePaths, $lang ) ); return \Aimeos\Admin\JsonAdm::create( $context, $aimeos, $resource ); } } ================================================ FILE: src/Controller/JsonapiController.php ================================================ createClient()->delete( $request, ( new Psr17Factory )->createResponse() ); } /** * Returns the requested resource object or list of resource objects * * @param \Psr\Http\Message\ServerRequestInterface $request Request object * @return \Psr\Http\Message\ResponseInterface Response object containing the generated output */ public function getAction( ServerRequestInterface $request ) { return $this->createClient()->get( $request, ( new Psr17Factory )->createResponse() ); } /** * Updates a resource object or a list of resource objects * * @param \Psr\Http\Message\ServerRequestInterface $request Request object * @return \Psr\Http\Message\ResponseInterface Response object containing the generated output */ public function patchAction( ServerRequestInterface $request ) { return $this->createClient()->patch( $request, ( new Psr17Factory )->createResponse() ); } /** * Creates a new resource object or a list of resource objects * * @param \Psr\Http\Message\ServerRequestInterface $request Request object * @return \Psr\Http\Message\ResponseInterface Response object containing the generated output */ public function postAction( ServerRequestInterface $request ) { return $this->createClient()->post( $request, ( new Psr17Factory )->createResponse() ); } /** * Creates or updates a single resource object * * @param \Psr\Http\Message\ServerRequestInterface $request Request object * @return \Psr\Http\Message\ResponseInterface Response object containing the generated output */ public function putAction( ServerRequestInterface $request ) { return $this->createClient()->put( $request, ( new Psr17Factory )->createResponse() ); } /** * Returns the available HTTP verbs and the resource URLs * * @param \Psr\Http\Message\ServerRequestInterface $request Request object * @return \Psr\Http\Message\ResponseInterface Response object containing the generated output */ public function optionsAction( ServerRequestInterface $request ) { return $this->createClient()->options( $request, ( new Psr17Factory )->createResponse() ) ->withHeader( 'access-control-allow-headers', 'authorization,content-type' ) ->withHeader( 'access-control-allow-methods', 'DELETE, GET, OPTIONS, PATCH, POST, PUT' ) ->withHeader( 'access-control-allow-origin', $request->getHeaderLine( 'origin' ) ); } /** * Returns the JsonAdm client * * @return \Aimeos\Client\JsonApi\Iface JsonApi client */ protected function createClient() : \Aimeos\Client\JsonApi\Iface { $resource = Route::input( 'resource' ); $related = Route::input( 'related', Request::get( 'related' ) ); $aimeos = app( 'aimeos' )->get(); $context = app( 'aimeos.context' )->get(); $tmplPaths = $aimeos->getTemplatePaths( 'client/jsonapi/templates', $context->locale()->getSiteItem()->getTheme() ); $langid = $context->locale()->getLanguageId(); $context->setView( app( 'aimeos.view' )->create( $context, $tmplPaths, $langid ) ); return \Aimeos\Client\JsonApi::create( $context, $resource . '/' . $related ); } } ================================================ FILE: src/Controller/PageController.php ================================================ 'page-index']; foreach( app( 'config' )->get( 'shop.page.cms', ['cms/page', 'catalog/tree', 'basket/mini'] ) as $name ) { $params['aiheader'][$name] = Shop::get( $name )->header(); $params['aibody'][$name] = Shop::get( $name )->body(); } if( empty( $params['aibody']['cms/page'] ) ) { abort( 404 ); } return Response::view( Shop::template( 'page.index' ), $params ) ->header( 'Cache-Control', 'private, max-age=10' ); } } ================================================ FILE: src/Controller/ResolveController.php ================================================ product( $context, $path ); }; self::$fcn['catalog'] = function( \Aimeos\MShop\ContextIface $context, string $path ) { return $this->catalog( $context, $path ); }; } /** * Returns the html of the resolved URLs. * * @param \Illuminate\Http\Request $request Laravel request object * @return \Illuminate\Http\Response Laravel response object containing the generated output */ public function indexAction( \Illuminate\Http\Request $request ) { if( ( $path = $request->route( 'path', $request->input( 'path' ) ) ) === null ) { abort( 404 ); } $context = app( 'aimeos.context' )->get( true ); foreach( array_reverse( self::$fcn ) as $name => $fcn ) { try { return call_user_func_array( $fcn->bindTo( $this, static::class ), [$context, $path] ); } catch( \Exception $e ) { if( $e->getCode() !== 404 ) throw $e; } } abort( 404 ); } /** * Returns the category page if the give path can be resolved to a category. * * @param \Aimeos\MShop\ContextIface $context Context object * @param string $path URL path to resolve * @return Response Response object */ protected function catalog( \Aimeos\MShop\ContextIface $context, string $path ) : ?\Illuminate\Http\Response { $item = \Aimeos\Controller\Frontend::create( $context, 'catalog' )->resolve( $path ); $view = Shop::view(); $params = ( Route::current() ? Route::current()->parameters() : [] ) + Request::all(); $params += ['path' => $path, 'f_name' => $path, 'f_catid' => $item->getId(), 'page' => 'page-catalog-tree']; $helper = new \Aimeos\Base\View\Helper\Param\Standard( $view, $params ); $view->addHelper( 'param', $helper ); foreach( app( 'config' )->get( 'shop.page.catalog-tree' ) as $name ) { $client = Shop::get( $name ); $params['aiheader'][$name] = $client->header(); $params['aibody'][$name] = $client->body(); } return Response::view( Shop::template( 'catalog.tree' ), $params ) ->header( 'Cache-Control', 'private, max-age=' . config( 'shop.cache_maxage', 30 ) ); } /** * Returns the CMS page if the give path can be resolved to a CMS page. * * @param \Aimeos\MShop\ContextIface $context Context object * @param string $path URL path to resolve * @return Response Response object */ protected function cms( \Aimeos\MShop\ContextIface $context, string $path ) : ?\Illuminate\Http\Response { \Aimeos\Controller\Frontend::create( $context, 'cms' )->resolve( $path ); $view = Shop::view(); $params = ( Route::current() ? Route::current()->parameters() : [] ) + Request::all(); $params += ['path' => $path, 'page' => 'page-index']; $helper = new \Aimeos\Base\View\Helper\Param\Standard( $view, $params ); $view->addHelper( 'param', $helper ); foreach( app( 'config' )->get( 'shop.page.cms' ) as $name ) { $client = Shop::get( $name ); $params['aiheader'][$name] = $client->header(); $params['aibody'][$name] = $client->body(); } return Response::view( Shop::template( 'page.index' ), $params ) ->header( 'Cache-Control', 'private, max-age=' . config( 'shop.cache_maxage', 30 ) ); } /** * Returns the product page if the give path can be resolved to a product. * * @param \Aimeos\MShop\ContextIface $context Context object * @param string $path URL path to resolve * @return Response Response object */ protected function product( \Aimeos\MShop\ContextIface $context, string $path ) : ?\Illuminate\Http\Response { $item = \Aimeos\Controller\Frontend::create( $context, 'product' )->resolve( $path ); $view = Shop::view(); $params = ( Route::current() ? Route::current()->parameters() : [] ) + Request::all(); $params += ['path' => $path, 'd_name' => $path, 'd_prodid' => $item->getId(), 'page' => 'page-catalog-detail']; $helper = new \Aimeos\Base\View\Helper\Param\Standard( $view, $params ); $view->addHelper( 'param', $helper ); foreach( app( 'config' )->get( 'shop.page.catalog-detail' ) as $name ) { $client = Shop::get( $name ); $params['aiheader'][$name] = $client->header(); $params['aibody'][$name] = $client->body(); } return Response::view( Shop::template( 'catalog.detail' ), $params ) ->header( 'Cache-Control', 'private, max-age=' . config( 'shop.cache_maxage', 30 ) ); } } ================================================ FILE: src/Controller/SupplierController.php ================================================ 'page-supplier-detail']; foreach( app( 'config' )->get( 'shop.page.supplier-detail' ) as $name ) { $params['aiheader'][$name] = Shop::get( $name )->header(); $params['aibody'][$name] = Shop::get( $name )->body(); } return Response::view( Shop::template( 'supplier.detail' ), $params ) ->header( 'Cache-Control', 'private, max-age=10' ); } catch( \Exception $e ) { if( $e->getCode() >= 400 && $e->getCode() < 600 ) { abort( $e->getCode() ); } throw $e; } } } ================================================ FILE: src/Facades/Attribute.php ================================================ loadViewsFrom( dirname( __DIR__ ) . '/views', 'shop' ); $this->loadRoutesFrom( dirname( __DIR__ ) . '/routes/aimeos.php' ); $this->publishes( [dirname( __DIR__ ) . '/config/shop.php' => config_path( 'shop.php' )], 'config' ); $this->publishes( [dirname( __DIR__ ) . '/public' => public_path( 'vendor/shop' )], 'public' ); $class = '\Composer\InstalledVersions'; if( class_exists( $class ) && method_exists( $class, 'getInstalledPackagesByType' ) ) { foreach( \Composer\InstalledVersions::getInstalledPackagesByType( 'aimeos-extension' ) as $package ) { $path = realpath( \Composer\InstalledVersions::getInstallPath( $package ) ); if( file_exists( $path . '/themes/client/html' ) ) { $this->publishes( [$path . '/themes/client/html' => public_path( 'vendor/shop/themes' )], 'public' ); } } } } /** * Register the service provider. * * @return void */ public function register() { $this->mergeConfigFrom( dirname( __DIR__ ) . '/config/default.php', 'shop' ); $this->app->scoped( 'aimeos', function( $app ) { return new \Aimeos\Shop\Base\Aimeos( $app['config'] ); }); $this->app->scoped( 'aimeos.config', function( $app ) { return new \Aimeos\Shop\Base\Config( $app['config'], $app['aimeos'] ); }); $this->app->scoped( 'aimeos.i18n', function( $app ) { return new \Aimeos\Shop\Base\I18n( $this->app['config'], $app['aimeos'] ); }); $this->app->scoped( 'aimeos.locale', function( $app ) { return new \Aimeos\Shop\Base\Locale( $app['config'] ); }); $this->app->scoped( 'aimeos.context', function( $app ) { return new \Aimeos\Shop\Base\Context( $app['session.store'], $app['aimeos.config'], $app['aimeos.locale'], $app['aimeos.i18n'] ); }); $this->app->scoped( 'aimeos.support', function( $app ) { return new \Aimeos\Shop\Base\Support( $app['aimeos.context'], $app['aimeos.locale'] ); }); $this->app->scoped( 'aimeos.view', function( $app ) { return new \Aimeos\Shop\Base\View( $app['config'], $app['aimeos.i18n'], $app['aimeos.support'] ); }); $this->app->scoped( 'aimeos.shop', function( $app ) { return new \Aimeos\Shop\Base\Shop( $app['aimeos'], $app['aimeos.context'], $app['aimeos.view'] ); }); $this->app->bind( 'aimeos.frontend.attribute', function( $app ) { return \Aimeos\Controller\Frontend::create( $app['aimeos.context'], 'attribute' ); }); $this->app->bind( 'aimeos.frontend.basket', function( $app ) { return \Aimeos\Controller\Frontend::create( $app['aimeos.context'], 'basket' ); }); $this->app->bind( 'aimeos.frontend.catalog', function( $app ) { return \Aimeos\Controller\Frontend::create( $app['aimeos.context'], 'catalog' ); }); $this->app->bind( 'aimeos.frontend.cms', function( $app ) { return \Aimeos\Controller\Frontend::create( $app['aimeos.context'], 'cms' ); }); $this->app->bind( 'aimeos.frontend.customer', function( $app ) { return \Aimeos\Controller\Frontend::create( $app['aimeos.context'], 'customer' ); }); $this->app->bind( 'aimeos.frontend.locale', function( $app ) { return \Aimeos\Controller\Frontend::create( $app['aimeos.context'], 'locale' ); }); $this->app->bind( 'aimeos.frontend.order', function( $app ) { return \Aimeos\Controller\Frontend::create( $app['aimeos.context'], 'order' ); }); $this->app->bind( 'aimeos.frontend.product', function( $app ) { return \Aimeos\Controller\Frontend::create( $app['aimeos.context'], 'product' ); }); $this->app->bind( 'aimeos.frontend.service', function( $app ) { return \Aimeos\Controller\Frontend::create( $app['aimeos.context'], 'service' ); }); $this->app->bind( 'aimeos.frontend.stock', function( $app ) { return \Aimeos\Controller\Frontend::create( $app['aimeos.context'], 'stock' ); }); $this->app->bind( 'aimeos.frontend.subscription', function( $app ) { return \Aimeos\Controller\Frontend::create( $app['aimeos.context'], 'subscription' ); }); $this->app->bind( 'aimeos.frontend.supplier', function( $app ) { return \Aimeos\Controller\Frontend::create( $app['aimeos.context'], 'supplier' ); }); $this->commands( array( 'Aimeos\Shop\Command\AccountCommand', 'Aimeos\Shop\Command\ClearCommand', 'Aimeos\Shop\Command\SetupCommand', 'Aimeos\Shop\Command\JobsCommand', ) ); } /** * Get the services provided by the provider. * * @return array */ public function provides() { return array( 'Aimeos\Shop\Base\Aimeos', 'Aimeos\Shop\Base\I18n', 'Aimeos\Shop\Base\Context', 'Aimeos\Shop\Base\Config', 'Aimeos\Shop\Base\Locale', 'Aimeos\Shop\Base\View', 'Aimeos\Shop\Base\Support', 'Aimeos\Shop\Base\Shop', 'Aimeos\Shop\Command\AccountCommand', 'Aimeos\Shop\Command\ClearCommand', 'Aimeos\Shop\Command\SetupCommand', 'Aimeos\Shop\Command\JobsCommand', ); } } ================================================ FILE: src/helpers.php ================================================ parameter( 'site', Request::get( 'site', $site ) ); $parameters['locale'] ??= $current->parameter( 'locale', Request::get( 'locale' ) ); $parameters['currency'] ??= $current->parameter( 'currency', Request::get( 'currency' ) ); } return app( 'url' )->route( $name, array_filter( $parameters ), $absolute ); } } if( !function_exists( 'aiconfig' ) ) { /** * Returns the configuration setting for the given key * * @param string $key Configuration key * @param mixed $default Default value if the configuration key isn't found * @return mixed Configuration value */ function aiconfig( $key, $default = null ) { return app( 'aimeos.config' )->get()->get( $key, $default ); } } if( !function_exists( 'aitrans' ) ) { /** * Translates the given message * * @param string $singular Message to translate * @param array $params List of paramters for replacing the placeholders in that order * @param string $domain Translation domain * @param string $locale ISO language code, maybe combine with ISO currency code, e.g. "en_US" * @return string Translated string */ function aitrans( $singular, array $params = array(), $domain = 'client', $locale = null ) { $i18n = app( 'aimeos.context' )->get()->i18n( $locale ); return vsprintf( $i18n->dt( $domain, $singular ), $params ); } } if( !function_exists( 'aitransplural' ) ) { /** * Translates the given messages based on the number * * @param string $singular Message to translate * @param string $plural Message for plural translations * @param integer $number Count of items to chose the correct plural translation * @param array $params List of paramters for replacing the placeholders in that order * @param string $domain Translation domain * @param string $locale ISO language code, maybe combine with ISO currency code, e.g. "en_US" * @return string Translated string */ function aitransplural( $singular, $plural, $number, array $params = array(), $domain = 'client', $locale = null ) { $i18n = app( 'aimeos.context' )->get()->i18n( $locale ); return vsprintf( $i18n->dn( $domain, $singular, $plural, $number ), $params ); } } ================================================ FILE: tests/AimeosTestAbstract.php ================================================ set( 'app.key', 'SomeRandomStringWith32Characters' ); $app['config']->set( 'app.cipher', 'AES-256-CBC' ); $app['config']->set( 'database.default', 'mysql' ); $app['config']->set( 'database.connections.mysql', [ 'driver' => 'mysql', 'host' => env( 'DB_HOST', '127.0.0.1' ), 'port' => env( 'DB_PORT', '3306' ), 'database' => env( 'DB_DATABASE', 'laravel' ), 'username' => env( 'DB_USERNAME', 'aimeos' ), 'password' => env( 'DB_PASSWORD', 'aimeos' ), 'unix_socket' => env( 'DB_SOCKET', '' ), 'collation' => 'utf8_unicode_ci', ] ); $app['config']->set( 'shop.resource.db', [ 'adapter' => 'mysql', 'host' => env( 'DB_HOST', '127.0.0.1' ), 'database' => env( 'DB_DATABASE', 'laravel' ), 'username' => env( 'DB_USERNAME', 'aimeos' ), 'password' => env( 'DB_PASSWORD', 'aimeos' ), 'stmt' => ["SET SESSION sort_buffer_size=2097144; SET SESSION sql_mode='ANSI'; SET NAMES 'utf8'"], 'opt-persistent' => 0, 'limit' => 3, 'defaultTableOptions' => [ 'collate' => 'utf8_unicode_ci', 'charset' => 'utf8', ], ] ); $app['config']->set( 'shop.resource.fs', [ 'adapter' => 'Standard', 'tempdir' => storage_path( 'tmp' ), 'basedir' => storage_path( 'tmp' ), 'baseurl' => '/aimeos', ] ); $app['config']->set( 'shop.authorize', false ); $app['config']->set( 'shop.disableSites', false ); $app['config']->set( 'shop.accessControl', false ); $app['config']->set( 'shop.admin.graphql.debug', true ); $app['config']->set( 'shop.routes.jqadm', ['prefix' => '{site}/jqadm'] ); $app['config']->set( 'shop.routes.graphql', ['prefix' => '{site}/graphql'] ); $app['config']->set( 'shop.routes.jsonadm', ['prefix' => '{site}/jsonadm'] ); $app['config']->set( 'shop.routes.jsonapi', ['prefix' => '{site}/jsonapi'] ); $app['config']->set( 'shop.routes.account', ['prefix' => '{site}/profile'] ); $app['config']->set( 'shop.routes.default', ['prefix' => '{site}/shop'] ); $app['config']->set( 'shop.routes.confirm', ['prefix' => '{site}/shop'] ); $app['config']->set( 'shop.routes.update', ['prefix' => '{site}'] ); $app['config']->set( 'shop.routes.page', ['prefix' => '{site}/p'] ); $app['config']->set( 'shop.routes.resolve', ['prefix' => '{site}', 'middleware' => ['web']] ); $app['config']->set( 'shop.routes.login', [] ); $app['config']->set( 'shop.mshop.locale.site', 'unittest' ); $app['config']->set( 'shop.resource.email.from-email', 'root@localhost' ); Route::any( 'login', ['as' => 'login'] ); Route::any( 'logout', ['as' => 'logout'] ); Route::match( array( 'GET', 'POST' ), '{site}/resolve/{path?}', array( 'as' => 'aimeos_resolve', 'uses' => 'Aimeos\Shop\Controller\ResolveController@indexAction' ) )->where( ['locale' => '[a-z]{2}(\_[A-Z]{2})?', 'site' => '[A-Za-z0-9\.\-]+', 'path', '.*'] ); } protected function getPackageProviders( $app ) { return ['Aimeos\Shop\ShopServiceProvider']; } } ================================================ FILE: tests/Base/AimeosTest.php ================================================ app->make( '\Aimeos\Shop\Base\Aimeos' )->get(); $this->assertInstanceOf( '\Aimeos\Bootstrap', $object ); } public function testGetVersion() { $object = $this->app->make( '\Aimeos\Shop\Base\Aimeos' ); $this->assertIsString( $object->getVersion() ); } } ================================================ FILE: tests/Base/ConfigTest.php ================================================ app->make( '\Aimeos\Shop\Base\Aimeos' ); $configMock = $this->getMockBuilder( '\Illuminate\Config\Repository' ) ->onlyMethods( array( 'get' ) )->getMock(); $configMock->expects( $this->exactly( 4 ) )->method( 'get' ) ->willReturnOnConsecutiveCalls( true, 'laravel:', array(), array() ); $object = new \Aimeos\Shop\Base\Config( $configMock, $aimeos ); $this->assertInstanceOf( '\Aimeos\Base\Config\Iface', $object->get() ); } } ================================================ FILE: tests/Base/ContextTest.php ================================================ getMockBuilder( '\Illuminate\Session\Store' )->disableOriginalConstructor()->getMock(); $config = $this->app->make( '\Aimeos\Shop\Base\Config' ); $locale = $this->app->make( '\Aimeos\Shop\Base\Locale' ); $i18n = $this->app->make( '\Aimeos\Shop\Base\I18n' ); $object = new \Aimeos\Shop\Base\Context( $session, $config, $locale, $i18n ); $ctx = $object->get( false ); $this->assertInstanceOf( '\Aimeos\MShop\ContextIface', $ctx ); $this->assertIsArray( $ctx->groups() ); } } ================================================ FILE: tests/Base/I18nTest.php ================================================ app->make( '\Aimeos\Shop\Base\Aimeos' ); $configMock = $this->getMockBuilder( '\Illuminate\Config\Repository' ) ->onlyMethods( array( 'get', 'has' ) )->getMock(); $configMock->expects( $this->once() )->method( 'has' ) ->willReturn( true ); $configMock->expects( $this->exactly( 3 ) )->method( 'get' ) ->willReturnOnConsecutiveCalls( true, 'laravel:', array() ); $object = new \Aimeos\Shop\Base\I18n( $configMock, $aimeos ); $list = $object->get( array( 'en' ) ); $this->assertInstanceOf( '\Aimeos\Base\Translation\Iface', $list['en'] ); } } ================================================ FILE: tests/Base/LocaleTest.php ================================================ getMockBuilder( '\Illuminate\Config\Repository' )->getMock(); $context = $this->app->make( '\Aimeos\Shop\Base\Context' )->get( false, 'backend' ); $object = new \Aimeos\Shop\Base\Locale( $mock ); $this->assertInstanceOf( '\Aimeos\MShop\Locale\Item\Iface', $object->getBackend( $context, 'unittest' ) ); } } ================================================ FILE: tests/Base/SupportTest.php ================================================ app->make( '\Aimeos\Shop\Base\Context' ); $locale = $this->app->make( '\Aimeos\Shop\Base\Locale' ); $object = new \Aimeos\Shop\Base\Support( $context, $locale ); $user = new \Illuminate\Foundation\Auth\User(); $user->siteid = '0'; $this->assertFalse( $object->checkUserGroup( $user, 'admin' ) ); } } ================================================ FILE: tests/Base/ViewTest.php ================================================ getMockBuilder( '\Illuminate\Config\Repository' )->getMock(); $i18n = $this->getMockBuilder( '\Aimeos\Shop\Base\I18n' ) ->disableOriginalConstructor() ->getMock(); $support = $this->getMockBuilder( '\Aimeos\Shop\Base\Support' ) ->disableOriginalConstructor() ->getMock(); $context = new \Aimeos\MShop\Context(); $context->setConfig( new \Aimeos\Base\Config\PHPArray() ); $context->setSession( new \Aimeos\Base\Session\None() ); $object = new \Aimeos\Shop\Base\View( $config, $i18n, $support ); $this->assertInstanceOf( '\Aimeos\Base\View\Iface', $object->create( $context, array() ) ); } } ================================================ FILE: tests/Command/AccountCommandTest.php ================================================ 'unittest', 'email' => 'unitCustomer@example.com', '--password' => 'test' ); $this->assertEquals( 0, $this->artisan( 'aimeos:account', $args ) ); } public function testAccountCommandAdmin() { $args = array( 'site' => 'unittest', 'email' => 'unitCustomer@example.com', '--password' => 'test', '--admin' => true ); $this->assertEquals( 0, $this->artisan( 'aimeos:account', $args ) ); } public function testAccountCommandEditor() { $args = array( 'site' => 'unittest', 'email' => 'unitCustomer@example.com', '--password' => 'test', '--editor' => true ); $this->assertEquals( 0, $this->artisan( 'aimeos:account', $args ) ); } } ================================================ FILE: tests/Command/ClearCommandTest.php ================================================ assertEquals( 0, $this->artisan( 'aimeos:clear' ) ); } } ================================================ FILE: tests/Command/JobsCommandTest.php ================================================ assertEquals( 0, $this->artisan( 'aimeos:jobs', array( 'jobs' => 'customer/email/watch', 'site' => 'unittest' ) ) ); } } ================================================ FILE: tests/Command/SetupCommandTest.php ================================================ 'unittest', 'tplsite' => 'unittest', '--option' => 'setup/default/demo:0' ); $this->assertEquals( 0, $this->artisan( 'aimeos:setup', $args ) ); } } ================================================ FILE: tests/Controller/AccountControllerTest.php ================================================ action( 'GET', '\Aimeos\Shop\Controller\AccountController@indexAction', ['site' => 'unittest'] ); $this->assertResponseOk(); $this->assertStringContainsString( '