Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve attribute and combinations generation #4

Merged
merged 4 commits into from Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
77 changes: 77 additions & 0 deletions .github/workflows/php.yml
@@ -0,0 +1,77 @@
name: PHP tests
on: [push, pull_request]
jobs:
# Check there is no syntax errors in the project
php-linter:
name: PHP Syntax check 7.4 => 8.2
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3.1.0

- name: PHP syntax checker 7.4
uses: prestashop/github-action-php-lint/7.4@master

- name: PHP syntax checker 8.0
uses: prestashop/github-action-php-lint/8.0@master

- name: PHP syntax checker 8.1
uses: prestashop/github-action-php-lint/8.1@master

- name: PHP syntax checker 8.2
uses: prestashop/github-action-php-lint/8.2@master

# Check the PHP code follow the coding standards
php-cs-fixer:
name: PHP-CS-Fixer
runs-on: ubuntu-latest
steps:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '7.4'

- name: Checkout
uses: actions/checkout@v3.1.0

- name: Install dependencies
run: composer install

- name: Run PHP-CS-Fixer
run: ./vendor/bin/php-cs-fixer fix --dry-run --diff --using-cache=no

# Run PHPStan against the module and a PrestaShop release
phpstan:
name: PHPStan
runs-on: ubuntu-latest
strategy:
matrix:
presta-versions: ['8.0', '8.1', 'latest']
steps:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '7.4'

- name: Checkout
uses: actions/checkout@v3.1.0

# Add vendor folder in cache to make next builds faster
- name: Cache vendor folder
uses: actions/cache@v3
with:
path: vendor
key: php-${{ hashFiles('composer.lock') }}

# Add composer local folder in cache to make next builds faster
- name: Cache composer folder
uses: actions/cache@v3
with:
path: ~/.composer/cache
key: php-composer-cache

- run: composer install

# Docker images prestashop/prestashop may be used, even if the shop remains uninstalled
- name: Execute PHPStan on PrestaShop (Tag ${{ matrix.presta-versions }})
run: ./tests/phpstan.sh ${{ matrix.presta-versions }}
1 change: 1 addition & 0 deletions .gitignore
@@ -1,2 +1,3 @@
vendor/
composer.lock
.php-cs-fixer.cache
11 changes: 11 additions & 0 deletions .php-cs-fixer.dist.php
@@ -0,0 +1,11 @@
<?php

$config = new PrestaShop\CodingStandards\CsFixer\Config();

$config
->setUsingCache(true)
->getFinder()
->in(__DIR__)
->exclude('vendor');

return $config;
42 changes: 27 additions & 15 deletions composer.json
@@ -1,23 +1,35 @@
{
"name": "prestashop/ps_fixtures_creator",
"name": "prestashop/ps_fixtures_creator",
"license": "AFL-3.0",
"authors": [
{
"name": "Fabien Papet",
"email": "FabienPapet@users.noreply.github.com"
}
],
"autoload": {
"psr-4": {
"PrestaShop\\Module\\PsFixturesCreator\\": "src/"
}
},
"require": {
"fakerphp/faker": "^1.21.0",
"symfony/console": "^4.4"
{
"name": "Fabien Papet",
"email": "FabienPapet@users.noreply.github.com"
}
],
"autoload": {
"psr-4": {
"PrestaShop\\Module\\PsFixturesCreator\\": "src/"
},
"classmap": [
"psfixturescreator.php"
],
"exclude-from-classmap": []
},
"require": {
"php": ">=7.4",
"fakerphp/faker": "^1.21.0",
"symfony/console": "^4.4",
"mbezhanov/faker-provider-collection": "^2.0"
},
"require-dev": {
"prestashop/php-dev-tools": "^4.3"
},
"config": {
"prepend-autoloader": false
"prepend-autoloader": false,
"platform": {
"php": "7.4.0"
}
},
"type": "prestashop-module"
}
47 changes: 26 additions & 21 deletions config/services.yml
@@ -1,50 +1,55 @@
services:
Faker\Generator:
factory: ['Faker\Factory', 'create']
factory: ['PrestaShop\Module\PsFixturesCreator\Faker\FakerFactory', 'create']
arguments:
- 'en_EN'

PrestaShop\Module\PsFixturesCreator\CustomerCreator:
class: PrestaShop\Module\PsFixturesCreator\CustomerCreator
PrestaShop\Module\PsFixturesCreator\Creator\CustomerCreator:
arguments:
$faker: '@Faker\Generator'

PrestaShop\Module\PsFixturesCreator\CartCreator:
class: PrestaShop\Module\PsFixturesCreator\CartCreator
PrestaShop\Module\PsFixturesCreator\Creator\CartCreator:
arguments:
$faker: '@Faker\Generator'

PrestaShop\Module\PsFixturesCreator\CartRuleCreator:
class: PrestaShop\Module\PsFixturesCreator\CartRuleCreator
PrestaShop\Module\PsFixturesCreator\Creator\CartRuleCreator:
arguments:
$faker: '@Faker\Generator'

PrestaShop\Module\PsFixturesCreator\ProductCreator:
class: PrestaShop\Module\PsFixturesCreator\ProductCreator
PrestaShop\Module\PsFixturesCreator\Creator\ProductCreator:
arguments:
$faker: '@Faker\Generator'

PrestaShop\Module\PsFixturesCreator\OrderCreator:
class: PrestaShop\Module\PsFixturesCreator\OrderCreator
PrestaShop\Module\PsFixturesCreator\Creator\OrderCreator:
arguments:
$faker: '@Faker\Generator'
$customerCreator: '@PrestaShop\Module\PsFixturesCreator\CustomerCreator'
$cartCreator: '@PrestaShop\Module\PsFixturesCreator\CartCreator'
$customerCreator: '@PrestaShop\Module\PsFixturesCreator\Creator\CustomerCreator'
$cartCreator: '@PrestaShop\Module\PsFixturesCreator\Creator\CartCreator'

PrestaShop\Module\PsFixturesCreator\ProductCombinationCreator:
class: PrestaShop\Module\PsFixturesCreator\ProductCombinationCreator
PrestaShop\Module\PsFixturesCreator\Creator\AttributeCreator:
arguments:
$entityManager: '@doctrine.orm.entity_manager'
$langRepository: '@prestashop.core.admin.lang.repository'
$shopRepository: '@prestashop.core.admin.shop.repository'
$faker: '@Faker\Generator'

PrestaShop\Module\PsFixturesCreator\Creator\ProductCombinationCreator:
arguments:
$entityManager: '@doctrine.orm.entity_manager'
$commandBus: '@prestashop.core.command_bus'
$attributeCreator: '@PrestaShop\Module\PsFixturesCreator\Creator\AttributeCreator'
$langRepository: '@prestashop.core.admin.lang.repository'
$faker: '@Faker\Generator'

PrestaShop\Module\PsFixturesCreator\Command\ShopCreatorCommand:
class: PrestaShop\Module\PsFixturesCreator\Command\ShopCreatorCommand
arguments:
$customerCreator: '@PrestaShop\Module\PsFixturesCreator\CustomerCreator'
$cartCreator: '@PrestaShop\Module\PsFixturesCreator\CartCreator'
$orderCreator: '@PrestaShop\Module\PsFixturesCreator\OrderCreator'
$cartRuleCreator: '@PrestaShop\Module\PsFixturesCreator\CartRuleCreator'
$productCreator: '@PrestaShop\Module\PsFixturesCreator\ProductCreator'
$productCombinationCreator: '@PrestaShop\Module\PsFixturesCreator\ProductCombinationCreator'
$customerCreator: '@PrestaShop\Module\PsFixturesCreator\Creator\CustomerCreator'
$cartCreator: '@PrestaShop\Module\PsFixturesCreator\Creator\CartCreator'
$orderCreator: '@PrestaShop\Module\PsFixturesCreator\Creator\OrderCreator'
$cartRuleCreator: '@PrestaShop\Module\PsFixturesCreator\Creator\CartRuleCreator'
$productCreator: '@PrestaShop\Module\PsFixturesCreator\Creator\ProductCreator'
$attributeCreator: '@PrestaShop\Module\PsFixturesCreator\Creator\AttributeCreator'
$productCombinationCreator: '@PrestaShop\Module\PsFixturesCreator\Creator\ProductCombinationCreator'
tags:
- { name: 'console.command' }
88 changes: 53 additions & 35 deletions src/Command/ShopCreatorCommand.php
Expand Up @@ -27,12 +27,13 @@
namespace PrestaShop\Module\PsFixturesCreator\Command;

use Db;
use PrestaShop\Module\PsFixturesCreator\CartCreator;
use PrestaShop\Module\PsFixturesCreator\CartRuleCreator;
use PrestaShop\Module\PsFixturesCreator\CustomerCreator;
use PrestaShop\Module\PsFixturesCreator\OrderCreator;
use PrestaShop\Module\PsFixturesCreator\ProductCombinationCreator;
use PrestaShop\Module\PsFixturesCreator\ProductCreator;
use PrestaShop\Module\PsFixturesCreator\Creator\AttributeCreator;
use PrestaShop\Module\PsFixturesCreator\Creator\CartCreator;
use PrestaShop\Module\PsFixturesCreator\Creator\CartRuleCreator;
use PrestaShop\Module\PsFixturesCreator\Creator\CustomerCreator;
use PrestaShop\Module\PsFixturesCreator\Creator\OrderCreator;
use PrestaShop\Module\PsFixturesCreator\Creator\ProductCombinationCreator;
use PrestaShop\Module\PsFixturesCreator\Creator\ProductCreator;
use Shop;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
Expand All @@ -54,6 +55,8 @@ class ShopCreatorCommand extends Command

private ProductCreator $productCreator;

private AttributeCreator $attributeCreator;

private ProductCombinationCreator $productCombinationCreator;

public function __construct(
Expand All @@ -62,6 +65,7 @@ public function __construct(
OrderCreator $orderCreator,
CartRuleCreator $cartRuleCreator,
ProductCreator $productCreator,
AttributeCreator $attributeCreator,
ProductCombinationCreator $productCombinationCreator
) {
parent::__construct(null);
Expand All @@ -71,6 +75,7 @@ public function __construct(
$this->orderCreator = $orderCreator;
$this->cartRuleCreator = $cartRuleCreator;
$this->productCreator = $productCreator;
$this->attributeCreator = $attributeCreator;
$this->productCombinationCreator = $productCombinationCreator;
}

Expand All @@ -86,14 +91,12 @@ protected function configure(): void
->addOption('carts', null, InputOption::VALUE_OPTIONAL, 'Number of carts to create', 0)
->addOption('cart-rules', null, InputOption::VALUE_OPTIONAL, 'Number of cart rules to create', 0)
->addOption('products', null, InputOption::VALUE_OPTIONAL, 'Number of products to create', 0)
->addOption('productsWithCombinations', null, InputOption::VALUE_OPTIONAL, 'Number of products with combinations to create', 0)
->addOption('shopId', null, InputOption::VALUE_OPTIONAL, 'The shop identifier', 1)
->addOption('shopGroupId', null, InputOption::VALUE_OPTIONAL, 'The shop group identifier', 1)
->addOption('languageId', null, InputOption::VALUE_OPTIONAL, 'The languageId identifier', 1)

// values for product combinations, if all three parameters are not above zero, nothing will be done
->addOption('attributeGroups', null, InputOption::VALUE_OPTIONAL, 'Number of attribute groups', 0)
->addOption('attributes', null, InputOption::VALUE_OPTIONAL, 'Number of attributes per attribute group', 0)
->addOption('targetProductIdForAttributes', null, InputOption::VALUE_OPTIONAL, 'ID of the product that will receive attributes', 0)
->addOption('attributes', null, InputOption::VALUE_OPTIONAL, 'Number of attributes per attribute group', 10)
;
}

Expand All @@ -111,36 +114,51 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$idShopGroup = (int) $input->getOption('shopGroupId');
$numberOfAttributeGroups = (int) $input->getOption('attributeGroups');
$numberOfAttributes = (int) $input->getOption('attributes');
$targetProductIdForAttributes = (int) $input->getOption('targetProductIdForAttributes');
$productsWithCombinations = (int) $input->getOption('productsWithCombinations');

$productIds = $this->getSimpleProducts($idLang);
$productIds = $this->getStandardProducts($idLang);

// Create customers (without order)
$this->customerCreator->generate($numberOfCustomerWithoutOrder);
$output->writeln(sprintf('%s customer(s) without orders created.', $numberOfCustomerWithoutOrder));

// Create carts
$this->cartCreator->generate($numberOfCarts, $productIds);
$output->writeln(sprintf('%s cart(s) created.', $numberOfCarts));

// Create orders
$this->orderCreator->generate($numberOfOrders, $idShopGroup, $idshop, $productIds);
$output->writeln(sprintf('%s order(s) created.', $numberOfOrders));
if (!empty($numberOfCustomerWithoutOrder)) {
$this->customerCreator->generate($numberOfCustomerWithoutOrder);
$output->writeln(sprintf('%s customer(s) without orders created.', $numberOfCustomerWithoutOrder));
}

// create cart rules
$this->cartRuleCreator->generate($numberOfCartRules, $idLang);
$output->writeln(sprintf('%s cart rule(s) created.', $numberOfCartRules));
if (!empty($numberOfCartRules)) {
$this->cartRuleCreator->generate($numberOfCartRules, $idLang);
$output->writeln(sprintf('%s cart rule(s) created.', $numberOfCartRules));
}

// create products
$this->productCreator->generate($numberOfProducts, $idLang);
$output->writeln(sprintf('%s product(s) created', $numberOfProducts));
if (!empty($numberOfProducts)) {
$this->productCreator->generate($numberOfProducts, $idLang);
$output->writeln(sprintf('%s product(s) created', $numberOfProducts));
}

// create product combination (attribute groups and attributes which are then attached to a product)
if ($numberOfAttributeGroups > 0 && $numberOfAttributes > 0 && $targetProductIdForAttributes > 0) {
$this->productCombinationCreator->generate($numberOfAttributeGroups, $numberOfAttributes, $targetProductIdForAttributes, $idLang, $idshop);
$output->writeln(sprintf('Created %s attribute group(s) with %s different values each for product with ID %s.', $numberOfAttributeGroups, $numberOfAttributes, $targetProductIdForAttributes));
// create product with combinations, if attributes are needed they will be created dynamically
if (!empty($productsWithCombinations)) {
$this->productCombinationCreator->generate($productsWithCombinations, $numberOfAttributeGroups, $numberOfAttributes, $idshop);
$output->writeln(sprintf('%s product(s) with combinations created', $productsWithCombinations));
} else {
$output->writeln('0 product combination(s) created.');
// If not product with combinations asked, simply create attributes
if ($numberOfAttributeGroups > 0 && $numberOfAttributes > 0) {
$this->attributeCreator->generate($numberOfAttributeGroups, $numberOfAttributes, $idshop);
$output->writeln(sprintf('Created %s attribute group(s) with %s different values each.', $numberOfAttributeGroups, $numberOfAttributes));
}
}

// Carts and orders are created last, so they can use new products randomly
// Create carts
if (!empty($numberOfCarts)) {
$this->cartCreator->generate($numberOfCarts, $productIds);
$output->writeln(sprintf('%s cart(s) created.', $numberOfCarts));
}

// Create orders
if (!empty($numberOfOrders)) {
$this->orderCreator->generate($numberOfOrders, $idShopGroup, $idshop, $productIds);
$output->writeln(sprintf('%s order(s) created.', $numberOfOrders));
}

return 0;
Expand All @@ -149,18 +167,18 @@ protected function execute(InputInterface $input, OutputInterface $output): int
/**
* @param int $id_lang Language identifier
*
* @return array
* @return bool|array
*/
private function getSimpleProducts($id_lang, bool $front = true): bool|array
private function getStandardProducts($id_lang, bool $front = true)
{
$sql = 'SELECT p.`id_product`, pl.`name`
FROM `' . _DB_PREFIX_ . 'product` p
' . Shop::addSqlAssociation('product', 'p') . '
LEFT JOIN `' . _DB_PREFIX_ . 'product_lang` pl ON (p.`id_product` = pl.`id_product` ' . Shop::addSqlRestrictionOnLang('pl') . ')
WHERE pl.`id_lang` = ' . (int) $id_lang . '
WHERE p.`product_type` = "standard" AND pl.`id_lang` = ' . (int) $id_lang . '
' . ($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '') . '
ORDER BY pl.`name`';

return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql);
return Db::getInstance((bool) _PS_USE_SQL_SLAVE_)->executeS($sql);
}
}