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

[WIP] Update Generator for 2.0 #52

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Generator/AttributeGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,12 @@ public function generate(array $globalConfig, array $entitiesConfig, ProgressBar
$attribute['group'] = $this->getRandomAttributeGroupCode();

if (AttributeTypes::OPTION_SIMPLE_SELECT === $type && $minVariantAxes > 0) {
// Configure a minimum set of non localizable and non scopable select axes for variant groups.
// Configure a minimum set of non localizable and non scopable select axes for family variants.
$attribute['localizable'] = 0;
$attribute['scopable'] = 0;
$minVariantAxes--;
} elseif (AttributeTypes::TEXT === $type && $minVariantAttributes > 0) {
// Configure a minimum set of non localizable and non scopable text attributes for variant groups.
// Configure a minimum set of non localizable and non scopable text attributes for family variants.
$attribute['localizable'] = 0;
$attribute['scopable'] = 0;
$minVariantAttributes--;
Expand Down
8 changes: 4 additions & 4 deletions Generator/FamilyGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,10 @@ public function generate(array $globalConfig, array $entitiesConfig, ProgressBar
for ($i = 0; $i < $count; $i++) {
$family = [];

$family['code'] =self::FAMILY_CODE_PREFIX.$i;
$family['code'] = self::FAMILY_CODE_PREFIX . $i;

foreach ($this->getLocalizedRandomLabels() as $localeCode => $label) {
$family['label-'.$localeCode] = $label;
$family['label-' . $localeCode] = $label;
}

$family['attribute_as_label'] = $this->labelAttribute;
Expand All @@ -105,7 +105,7 @@ public function generate(array $globalConfig, array $entitiesConfig, ProgressBar
$attributeReqs = $this->faker->randomElements($nonMediaAttributeCodes, $requirementsCount);
$attributeReqs = array_merge([$this->identifierAttribute], $attributeReqs);

$family['requirements-'.$channel->getCode()] = implode(self::ATTRIBUTE_DELIMITER, $attributeReqs);
$family['requirements-' . $channel->getCode()] = implode(self::ATTRIBUTE_DELIMITER, $attributeReqs);
}

$families[$family['code']] = $family;
Expand All @@ -123,7 +123,7 @@ public function generate(array $globalConfig, array $entitiesConfig, ProgressBar
))
->write($families);

return [];
return ['families' => $this->getFamilyObjects()];
}

/**
Expand Down
310 changes: 310 additions & 0 deletions Generator/FamilyVariantGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,310 @@
<?php

namespace Pim\Bundle\DataGeneratorBundle\Generator;

use Faker\Factory;
use Faker\Generator;
use Pim\Bundle\DataGeneratorBundle\Writer\CsvWriter;
use Pim\Component\Catalog\AttributeTypes;
use Pim\Component\Catalog\Model\AttributeInterface;
use Pim\Component\Catalog\Model\FamilyInterface;
use Symfony\Component\Console\Helper\ProgressBar;

/**
* Generate native YML file for family variant useable as fixtures
*
* @author Willy Mesnage <[email protected]>
* @copyright 2017 Akeneo SAS (http://www.akeneo.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
class FamilyVariantGenerator implements GeneratorInterface
{
// code;family;label-de_DE;label-en_US;label-fr_FR;variant-axes_1;variant-axes_2;variant-attributes_1;variant-attributes_2

const TYPE = 'family_variant';

const FAMILY_VARIANT_CODE_PREFIX = 'fam_variant_';

const FAMILY_VARIANTS_FILENAME = 'family_variants.csv';

const ATTRIBUTE_DELIMITER = ',';

/** @var array */
protected $locales = [];

/** @var array */
protected $channels = [];

/** @var Generator */
protected $faker;

/** @var array */
protected $familyVariants = [];

/** @var AttributeInterface[] */
protected $availableAxes = [];

/** @var AttributeInterface[] */
protected $availableAttributes = [];

/** @var string */
protected $identifierAttributeCode;

/** @var array */
protected $availableFamilies;

/** @var CsvWriter */
protected $writer;

/**
* @param CsvWriter $writer
*/
public function __construct(CsvWriter $writer)
{
$this->writer = $writer;
}

/**
* {@inheritdoc}
*/
public function generate(array $globalConfig, array $entitiesConfig, ProgressBar $progress, array $options = [])
{
$this->locales = $options['locales'];
$this->channels = $options['channels'];

$count = (int) $entitiesConfig['count'];
$oneLevelProbability = (float) $entitiesConfig['one_level_probability'];
$twoLevelProbability = (float) $entitiesConfig['two_level_probability'];
$maxAttributesPerAxe = (int) $entitiesConfig['max_attributes_per_axe'];
$this->identifierAttributeCode = $entitiesConfig['identifier_attribute'];
$this->setFamilies($options['families'], $count);
$this->setFaker($globalConfig);

if (100 !== $oneLevelProbability + $twoLevelProbability) {
throw new \Exception('Addition of one level and two level family variants probability must be equals to 100');
}
$nbOfOneLevelNeeded = $count * 100 / $oneLevelProbability;
$nbOfTwoLevelNeeded = $count - $nbOfOneLevelNeeded;

$familyVariants = [];
// code;family;label-de_DE;label-en_US;label-fr_FR;variant-axes_1;variant-axes_2;variant-attributes_1;variant-attributes_2
foreach ($this->availableFamilies as $code => $parentFamily) {
$family = [];

$family['code'] = self::FAMILY_VARIANT_CODE_PREFIX . $code;
$family['family'] = $code;

foreach ($this->getLocalizedRandomLabels() as $localeCode => $label) {
$family['label-' . $localeCode] = $label;
}

if (count($parentFamily['availableAxes']) >= 2 && 0 < $nbOfTwoLevelNeeded) {
$level = $this->buildLevel($code, $maxAttributesPerAxe, true);
$nbOfTwoLevelNeeded--;
} elseif (0 < $nbOfOneLevelNeeded) {
$level = $this->buildLevel($code, $maxAttributesPerAxe);
$nbOfOneLevelNeeded--;
}
//Array merge
//stop process if count is reach
// Check if we have enough family variants

$familyVariants[$family['code']] = $family;
$progress->advance();
}

$this->familyVariants = $familyVariants;

$this->writer
->setFilename(sprintf(
'%s%s%s',
$globalConfig['output_dir'],
DIRECTORY_SEPARATOR,
self::FAMILY_VARIANTS_FILENAME
))
->write($familyVariants);

return [];
}

/**
* {@inheritdoc}
*/
public function supports($type)
{
return self::TYPE === $type;
}

/**
* @param string $familyParentCode
* @param int $maxAttributesPerAxe
* @param bool $twoLevels
*
* @return array
*/
protected function buildLevel($familyParentCode, $maxAttributesPerAxe, $twoLevels = false)
{
$chunkSize = count($this->availableFamilies[$familyParentCode]['availableAttributes']) / 2;
$availableAttributes = array_chunk(
$this->availableFamilies[$familyParentCode]['availableAttributes'],
$chunkSize
);

$axis1 = array_shift($this->availableFamilies[$familyParentCode]['availableAxes']);
$levels['variant-axes_1'] = [$axis1->getCode()];
$levels['variant-attributes_1'] = $this->buildAvailableAttributes(
$availableAttributes[0],
$maxAttributesPerAxe
);

if ($twoLevels) {
$axis2 = array_shift($this->availableFamilies[$familyParentCode]['availableAxes']);
$levels['variant-axes_2'] = [$axis2->getCode()];
$levels['variant-attributes_2'] = $this->buildAvailableAttributes(
$availableAttributes[1],
$maxAttributesPerAxe
);
}

return $levels;
}

/**
* @param array $availableAttributes
* @param int $maxAttributes
*
* @return string
*/
protected function buildAvailableAttributes(array $availableAttributes, $maxAttributes)
{
$variantAttributes = [];
while (!empty($availableAttributes) || 0 !== $maxAttributes) {
$attribute = array_shift($availableAttributes);
$variantAttributes[] = $attribute->getCode();
$maxAttributes--;
}

return implode(self::ATTRIBUTE_DELIMITER, $variantAttributes);
}

/**
* Get localized random labels
*
* @return array
*/
protected function getLocalizedRandomLabels()
{
$labels = [];

foreach ($this->locales as $locale) {
$labels[$locale->getCode()] = $this->faker->sentence(2);
}

return $labels;
}

/**
* @param FamilyInterface[] $families
* @param int $count
*
* @throws \Exception if there is not enough families available to create asked number of family variants.
*/
protected function setFamilies(array $families, $count)
{
foreach ($families as $family) {
$attributes = $family->getAttributes();

$availableAxes = $this->getAvailableAxis($attributes);
$availableAttributes = $this->getAvailableAttributes($attributes);

if (0 !== count($availableAxes) && 0 !== count($availableAttributes)) {
$this->availableFamilies[$family->getCode()] = [
'family' => $family,
'availableAxes' => $availableAxes,
'availableAttributes' => $availableAttributes
];
}
}

if (count($this->availableFamilies) < $count) {
throw new \Exception('There is not enough available families to create family variants.');
}
}

/**
* Returns the available attributes to define family variant axes
* (only selects non localizable and non scopable).
*
* @param AttributeInterface[] $attributes
*
* @return AttributeInterface[]
*/
protected function getAvailableAxis(array $attributes)
{
return array_filter($attributes, function ($attribute) {
return in_array($attribute->getAttributeType(), [
AttributeTypes::OPTION_SIMPLE_SELECT,
AttributeTypes::REFERENCE_DATA_SIMPLE_SELECT
]) && !$attribute->isLocalizable() && !$attribute->isScopable();
});
}

/**
* Returns the available attributes to define family variant attributes
* (only texts non localizable and non scopable).
*
* @param AttributeInterface[] $attributes
*
* @return AttributeInterface[]
*/
protected function getAvailableAttributes(array $attributes)
{
return array_filter($attributes, function ($attribute) {
return (($attribute->getAttributeType() === AttributeTypes::TEXT)
&& !$attribute->isLocalizable()
&& !$attribute->isScopable()
);
});
}

/**
* @param array $globalConfig
*/
protected function setFaker(array $globalConfig)
{
$this->faker = Factory::create();
if (isset($globalConfig['seed'])) {
$this->faker->seed($globalConfig['seed']);
}
}

/**
* Returns the number of attributes to set.
*
* @param FamilyInterface $family
* @param int $nbAttrBase
* @param int $nbAttrDeviation
*
* @return int
*/
private function getRandomAttributesCount(FamilyInterface $family, $nbAttrBase, $nbAttrDeviation)
{
if ($nbAttrBase > 0) {
if ($nbAttrDeviation > 0) {
$nbAttr = $this->faker->numberBetween(
$nbAttrBase - round($nbAttrDeviation / 2),
$nbAttrBase + round($nbAttrDeviation / 2)
);
} else {
$nbAttr = $nbAttrBase;
}
}
$familyAttrCount = count($this->getAttributesFromFamily($family));

if (!isset($nbAttr) || $nbAttr > $familyAttrCount) {
$nbAttr = $familyAttrCount;
}

return $nbAttr;
}
}
2 changes: 1 addition & 1 deletion Generator/Product/ProductRawBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public function fillInRandomAttributes(
$nbAttr,
$nbAttrDeviation
);
$attributes = $this->getRandomAttributesFromFamily($family, $randomNbAttr);
$attributes = $this->getRandomAttributesFromFamily($family, $randomNbAttr);

foreach ($attributes as $attribute) {
$valueData = $this->generateValue($attribute, $forcedAttributes);
Expand Down
8 changes: 8 additions & 0 deletions Resources/config/generators.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ parameters:
pim_data_generator.generator.attribute.class: Pim\Bundle\DataGeneratorBundle\Generator\AttributeGenerator
pim_data_generator.generator.attribute_option.class: Pim\Bundle\DataGeneratorBundle\Generator\AttributeOptionGenerator
pim_data_generator.generator.family.class: Pim\Bundle\DataGeneratorBundle\Generator\FamilyGenerator
pim_data_generator.generator.family_variant.class: Pim\Bundle\DataGeneratorBundle\Generator\FamilyVariantGenerator
pim_data_generator.generator.attribute_group.class: Pim\Bundle\DataGeneratorBundle\Generator\AttributeGroupGenerator
pim_data_generator.generator.category.class: Pim\Bundle\DataGeneratorBundle\Generator\CategoryGenerator
pim_data_generator.generator.user_group.class: Pim\Bundle\DataGeneratorBundle\Generator\UserGroupGenerator
Expand Down Expand Up @@ -79,6 +80,13 @@ services:
tags:
- { name: pim_data_generator.generator }

pim_data_generator.generator.family_variant:
class: '%pim_data_generator.generator.family_variant.class%'
arguments:
- '@pim_data_generator.writer.csv_writer'
tags:
- { name: pim_data_generator.generator }

pim_data_generator.generator.attribute_option:
class: '%pim_data_generator.generator.attribute_option.class%'
arguments:
Expand Down