Skip to content

Commit

Permalink
Add random catalog generator
Browse files Browse the repository at this point in the history
  • Loading branch information
PierreGauthier committed Jan 22, 2024
1 parent 33a109b commit fa0e42a
Show file tree
Hide file tree
Showing 12 changed files with 306 additions and 21 deletions.
1 change: 1 addition & 0 deletions .github/workflows/deploy-demo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ jobs:
docker system prune -af &&
([[ $(docker volume ls -q | awk '!/_/' | tr '\n' ' ' | wc -l) -eq 0 ]] || docker volume rm $(docker volume ls -q | awk '!/_/' | tr '\n' ' ')) &&
docker compose down &&
rm composer.lock -f &&
git fetch --all && git reset --hard && git checkout ${{ env.BRANCH }} &&
docker compose run --rm php chown www-data:www-data -R public/media &&
docker compose run --rm php bin/console doctrine:migrations:migrate &&
Expand Down
5 changes: 2 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,8 @@ ENV APP_ENV=prod

# prevent the reinstallation of vendors at every changes in the source code
COPY composer.* symfony.lock ./
COPY patches patches/
RUN set -eux; \
composer install --prefer-dist --no-autoloader --no-interaction --no-scripts --no-progress --no-dev; \
COMPOSER_MEMORY_LIMIT=2G composer install --prefer-dist --no-autoloader --no-interaction --no-scripts --no-progress --no-dev; \
composer clear-cache

# copy only specifically what we need
Expand Down Expand Up @@ -143,7 +142,7 @@ ENV APP_ENV=dev
COPY .env.test .env.test_cached ./

RUN set -eux; \
composer install --prefer-dist --no-autoloader --no-interaction --no-scripts --no-progress; \
COMPOSER_MEMORY_LIMIT=2G composer install --prefer-dist --no-autoloader --no-interaction --no-scripts --no-progress; \
composer clear-cache

FROM sylius_php_prod AS sylius_cron
Expand Down
9 changes: 3 additions & 6 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,15 @@
"require": {
"php": "^8.0",
"cweagans/composer-patches": "^1.7",
"gally/sylius-plugin": "dev-master",
"gally/sylius-plugin": "dev-feat-sync-optim",
"sylius/paypal-plugin": "^1.5",
"sylius/sylius": "^1.12.11",
"symfony/dotenv": "^5.4 || ^6.0",
"symfony/flex": "^2.1",
"symfony/runtime": "^5.4 || ^6.0"
},
"require-dev": {
"akawakaweb/sylius-fixtures-plugin": "^0.1.0",
"behat/behat": "^3.7",
"behat/mink-selenium2-driver": "^1.4",
"dmore/behat-chrome-extension": "^1.3",
Expand All @@ -46,6 +47,7 @@
"friends-of-behat/suite-settings-extension": "^1.0",
"friends-of-behat/symfony-extension": "^2.1",
"friends-of-behat/variadic-extension": "^1.3",
"friendsofphp/php-cs-fixer": "~3.4.0",
"lchrusciel/api-test-case": "^5.0",
"phpspec/phpspec": "^7.0",
"phpstan/extension-installer": "^1.0",
Expand Down Expand Up @@ -90,11 +92,6 @@
"https://api.github.com/repos/Sylius/SyliusRecipes/contents/index.json?ref=flex/main",
"flex://defaults"
]
},
"patches": {
"gally/sylius-plugin": {
"Remove final class": "patches/fix_gally_configuration.patch"
}
}
},
"autoload": {
Expand Down
3 changes: 3 additions & 0 deletions config/bundles.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,7 @@
League\FlysystemBundle\FlysystemBundle::class => ['all' => true],
Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true],
Gally\SyliusPlugin\GallySyliusPlugin::class => ['all' => true],
Zenstruck\Foundry\ZenstruckFoundryBundle::class => ['dev' => true, 'test' => true],
Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true],
Akawakaweb\SyliusFixturesPlugin\Symfony\SyliusFixturesPlugin::class => ['dev' => true, 'test' => true, 'test_cached' => true],
];
2 changes: 2 additions & 0 deletions config/packages/doctrine.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ parameters:
doctrine:
dbal:
url: '%env(resolve:DATABASE_URL)%'
logging: false
profiling: false

orm:
auto_generate_proxy_classes: '%kernel.debug%'
Expand Down
7 changes: 7 additions & 0 deletions config/packages/zenstruck_foundry.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
when@dev: &dev
# See full configuration: https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#full-default-bundle-configuration
zenstruck_foundry:
# Whether to auto-refresh proxies by default (https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#auto-refresh)
auto_refresh_proxies: true

when@test: *dev
10 changes: 10 additions & 0 deletions config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,13 @@ services:
App\Controller\:
resource: '../src/Controller'
tags: ['controller.service_arguments']

# config/services.yaml

when@dev: &fixtures_dev
services:
sylius.fixtures_plugin.story.default_locales: '@App\Foundry\Story\DefaultLocalesStory'
sylius.fixtures_plugin.story.random_dresses: '@App\Foundry\Story\RandomCatalogStory'
sylius.fixtures_plugin.story.random_caps: '@App\Foundry\Story\EmptyStory'
sylius.fixtures_plugin.story.random_jeans: '@App\Foundry\Story\EmptyStory'
sylius.fixtures_plugin.story.random_t_shirts: '@App\Foundry\Story\EmptyStory'
12 changes: 0 additions & 12 deletions patches/fix_gally_configuration.patch

This file was deleted.

34 changes: 34 additions & 0 deletions src/Foundry/Story/DefaultLocalesStory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace App\Foundry\Story;

use Akawakaweb\SyliusFixturesPlugin\Foundry\Factory\LocaleFactory;
use Akawakaweb\SyliusFixturesPlugin\Foundry\Story\DefaultLocalesStoryInterface;
use Zenstruck\Foundry\Factory;
use Zenstruck\Foundry\Story;

final class DefaultLocalesStory extends Story implements DefaultLocalesStoryInterface
{
public function __construct(
) {
}

public function build(): void
{
Factory::delayFlush(function () {
foreach ($this->getLocaleCodes() as $currencyCode) {
LocaleFactory::new()->withCode($currencyCode)->create();
}
});
}

/**
* @return string[]
*/
private function getLocaleCodes(): array
{
return ['en_US', 'fr_FR'];
}
}
21 changes: 21 additions & 0 deletions src/Foundry/Story/EmptyStory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace App\Foundry\Story;

use Akawakaweb\SyliusFixturesPlugin\Foundry\Story\RandomCapsStoryInterface;
use Akawakaweb\SyliusFixturesPlugin\Foundry\Story\RandomJeansStoryInterface;
use Akawakaweb\SyliusFixturesPlugin\Foundry\Story\RandomTShirtsStoryInterface;
use Zenstruck\Foundry\Story;

final class EmptyStory extends Story implements RandomCapsStoryInterface, RandomJeansStoryInterface, RandomTShirtsStoryInterface
{
public function __construct()
{
}

public function build(): void
{
}
}
187 changes: 187 additions & 0 deletions src/Foundry/Story/RandomCatalogStory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
<?php

declare(strict_types=1);

namespace App\Foundry\Story;

use Akawakaweb\SyliusFixturesPlugin\Foundry\Factory\ProductAttributeFactory;
use Akawakaweb\SyliusFixturesPlugin\Foundry\Factory\ProductFactory;
use Akawakaweb\SyliusFixturesPlugin\Foundry\Factory\ProductOptionFactory;
use Akawakaweb\SyliusFixturesPlugin\Foundry\Factory\TaxonFactory;
use Akawakaweb\SyliusFixturesPlugin\Foundry\Story\RandomDressesStoryInterface;
use Doctrine\ORM\EntityManagerInterface;
use Faker\Generator;
use Sylius\Component\Attribute\AttributeType\IntegerAttributeType;
use Sylius\Component\Attribute\AttributeType\TextAttributeType;
use Zenstruck\Foundry\Story;
use Faker\Factory;

final class RandomCatalogStory extends Story implements RandomDressesStoryInterface
{
private const CATEGORY_BY_LEVEL_COUNT = 10;
private const CATEGORY_LEVEL_COUNT = 3;

private const SCALAR_ATTRIBUTE_COUNT = 500;
private const SELECT_ATTRIBUTE_COUNT = 500;
private const MAX_ATTRIBUTE_OPTION_COUNT = 200;

private const PRODUCT_COUNT = 100000;

private Generator $faker;
private array $taxa = [];
private array $scalarAttributes = [];
private array $selectAttributes = [];

public function __construct(
private EntityManagerInterface $entityManager,
) {
$this->faker = Factory::create();
}

public function build(): void
{
print("\nCreate taxa");
$this->createTaxa();
print("\nCreate attributes");
$this->createAttributes();
print("\nCreate products");
$this->createProducts();
print("\n");
}

private function createTaxa(string $parentCode = null, int $level = 1): array
{
$categories = [];
for ($index = 0; $index < self::CATEGORY_BY_LEVEL_COUNT; $index++) {
$slug = $this->faker->slug(4, false);
$code = $parentCode . '/' . str_replace(' ', '_', $slug) . $index;
if ($level === 1) {
print(".");
TaxonFactory::new()
->withCode('MENU_CATEGORY')
->withName('Category')
->withTranslations([
'en_US' => ['name' => 'Category'],
'fr_FR' => ['name' => 'Catégorie'],
])
->withChildren([
[
'code' => $code,
'name' => ucfirst($slug) . "$level$index",
'translations' => [
'en_US' => ['name' => ucfirst($slug) . "US $level$index"],
'fr_FR' => ['name' => ucfirst($slug) . "FR $level$index"],
],
'children' => $this->createTaxa($code, $level+1),
]
])
->create();
} else {
$category = [
'code' => $code,
'name' => ucfirst($slug) . "$level$index",
'translations' => [
'en_US' => ['name' => ucfirst($slug) . "US $level$index"],
'fr_FR' => ['name' => ucfirst($slug) . "FR $level$index"],
]
];
if (self::CATEGORY_LEVEL_COUNT > $level) {
$category['children'] = $this->createTaxa($code, $level+1);
}
$categories[] = $category;

if (self::CATEGORY_LEVEL_COUNT === $level) {
$this->taxa[$code] = $code;
}
}
}

return $categories;
}

private function createAttributes(): void
{
$scalarTypes = [TextAttributeType::TYPE, IntegerAttributeType::TYPE];

for ($index = 0; $index < self::SCALAR_ATTRIBUTE_COUNT; $index++) {
$code = $this->faker->slug(3, false) . $index;
$type = $scalarTypes[array_rand($scalarTypes)];
ProductAttributeFactory::new()
->withCode(str_replace(' ', '_', $code))
->withName(ucfirst($code))
->withType($type)
->create();
$this->scalarAttributes[$type][$code] = $code;

if (($index % 200) === 0) {
print(".");
$this->entityManager->flush();
$this->entityManager->clear();
}
}

print("\n");
for ($index = 0; $index < self::SELECT_ATTRIBUTE_COUNT; $index++) {
$code = $this->faker->slug(1) . $index;
$options = [];
for (
$optionIndex = 0;
$optionIndex < rand((int) ceil(self::MAX_ATTRIBUTE_OPTION_COUNT/10), self::MAX_ATTRIBUTE_OPTION_COUNT);
$optionIndex++
) {
$optionCode = $this->faker->slug(1) . $optionIndex;
$options[$code . '-' . $optionCode] = ucfirst($optionCode);
}

ProductOptionFactory::new()
->withCode($code)
->withName(ucfirst($code))
->withValues($options)
->create();
$this->selectAttributes[$code] = $code;

if (($index % 200) === 0) {
print(".");
$this->entityManager->flush();
$this->entityManager->clear();
}
}
}

private function createProducts(): void
{
for ($index = 0; $index < self::PRODUCT_COUNT; $index++) {
$taxon = array_rand($this->taxa);
$sku = $this->faker->slug(1) . '-' . $index;

$attributes = [];
foreach (array_rand($this->scalarAttributes[IntegerAttributeType::TYPE], 20) as $code) {
$attributes[$code] = rand(1, 100);
}
foreach (array_rand($this->scalarAttributes[TextAttributeType::TYPE], 20) as $code) {
$attributes[$code] = $this->faker->slug(2);
}

$product = ProductFactory::new()
->withName($this->faker->slug(5) . " $index")
->withCode($sku)
->withTaxCategory('clothing')
->withChannels(['FASHION_WEB'])
->withMainTaxon($taxon)
->withTaxa([$taxon])
->withProductAttributes($attributes);

if ($index % 2) {
$product->withProductOptions(array_rand($this->selectAttributes, 2));
}

if (($index % 1000) === 0) {
print(".");
$this->entityManager->flush();
$this->entityManager->clear();
}

$product->create();
}
}
}
Loading

0 comments on commit fa0e42a

Please sign in to comment.