* * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ namespace Chill\PersonBundle\DataFixtures\ORM; use Chill\MainBundle\Entity\Center; use Chill\MainBundle\Entity\Country; use Chill\MainBundle\Entity\PostalCode; use Chill\MainBundle\Entity\Scope; use Chill\MainBundle\Entity\User; use Chill\MainBundle\Repository\CenterRepository; use Chill\MainBundle\Repository\CountryRepository; use Chill\MainBundle\Repository\ScopeRepository; use Chill\MainBundle\Repository\UserRepository; use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\MaritalStatus; use Chill\PersonBundle\Entity\SocialWork\SocialIssue; use Chill\PersonBundle\Repository\MaritalStatusRepository; use Chill\ThirdPartyBundle\Entity\ThirdParty; use Doctrine\Common\DataFixtures\AbstractFixture; use Doctrine\Common\DataFixtures\OrderedFixtureInterface; use Doctrine\Persistence\ObjectManager; use Chill\PersonBundle\Entity\Person; use Faker\Factory; use Faker\Generator; use Nelmio\Alice\Faker\GeneratorFactory; use Nelmio\Alice\Loader\NativeLoader; use Nelmio\Alice\ObjectSet; use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Chill\MainBundle\DataFixtures\ORM\LoadPostalCodes; use Chill\MainBundle\Entity\Address; use Chill\MainBundle\Doctrine\Model\Point; use Symfony\Component\Workflow\Registry; use Symfony\Component\Workflow\Workflow; use Chill\PersonBundle\Repository\SocialWork\SocialIssueRepository; /** * Load people into database * */ class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, ContainerAwareInterface { use \Symfony\Component\DependencyInjection\ContainerAwareTrait; protected Generator $faker; protected Registry $workflowRegistry; protected SocialIssueRepository $socialIssueRepository; protected CountryRepository $countryRepository; protected NativeLoader $loader; /** * @var array|SocialIssue[] */ protected array $cacheSocialIssues = []; /** * @var array|Country[] */ protected array $cacheCountries = []; /** * @var array|Center[] */ protected array $cacheCenters = []; protected CenterRepository $centerRepository; /** * @var array|MaritalStatus[] */ protected array $cacheMaritalStatuses = []; protected MaritalStatusRepository $maritalStatusRepository; /** * @var array|Scope[] */ protected array $cacheScopes = []; protected ScopeRepository $scopeRepository; /** @var array|User[] */ protected array $cacheUsers = []; protected UserRepository $userRepository; public function __construct( Registry $workflowRegistry, SocialIssueRepository $socialIssueRepository, CenterRepository $centerRepository, CountryRepository $countryRepository, MaritalStatusRepository $maritalStatusRepository, ScopeRepository $scopeRepository, UserRepository $userRepository ) { $this->faker = Factory::create('fr_FR'); $this->faker->addProvider($this); $this->workflowRegistry = $workflowRegistry; $this->socialIssueRepository = $socialIssueRepository; $this->centerRepository = $centerRepository; $this->countryRepository = $countryRepository; $this->maritalStatusRepository = $maritalStatusRepository; $this->loader = new NativeLoader($this->faker); $this->scopeRepository = $scopeRepository; $this->userRepository = $userRepository; } public function getOrder() { return 10000; } public function load(ObjectManager $manager) { $this->loadExpectedPeople($manager); $this->loadRandPeople($manager); $manager->flush(); } public function loadExpectedPeople(ObjectManager $manager) { echo "loading expected people...\n"; foreach ($this->peoples as $personDef) { $person = $this->createExpectedPerson($personDef); $this->addAPerson($person, $manager); } } protected function loadRandPeople(ObjectManager $manager) { echo "loading rand people...\n"; $persons = $this->createRandPerson()->getObjects(); foreach ($persons as $person) { $this->addAPerson($person, $manager); } } private function createRandPerson(): ObjectSet { return $this->loader->loadData([ Person::class => [ 'persons{1..300}' => [ 'firstName' => '', 'lastName' => '', 'gender' => '', 'nationality' => '', 'center' => '', 'maritalStatus' => '', 'birthdate' => '', 'placeOfBirth' => '', 'email' => '', 'countryOfBirth' => '', ] ] ]); } private function createExpectedPerson($default): Person { $person = $this->loader->loadData([ Person::class => [ "person" => [ 'firstName' => $default['firstName'] ?? '', 'lastName' => $default['lastName'] ?? '', 'gender' => '', 'nationality' => '', 'center' => '', 'maritalStatus' => '', 'birthdate' => '', 'placeOfBirth' => '', 'email' => '', 'countryOfBirth' => '', ], ] ])->getObjects()['person']; // force some values foreach ($default as $key => $value) { switch ($key) { case 'birthdate': $person->setBirthdate(new \DateTime($value)); break; case 'center': $person->setCenter($this->centerRepository ->findOneBy(['name' => $value])); break; case 'countryOfBirth': case 'nationality': $country = $this->countryRepository ->findOneBy(['countryCode' => $value]); $person->{'set'.\ucfirst($key)}($country); break; case 'maritalStatus': $person->setMaritalStatus($this->maritalStatusRepository ->find($value)); break; } } return $person; } /** * create a new person from array data * * @throws \Exception */ private function addAPerson(Person $person, ObjectManager $manager) { $accompanyingPeriod = new AccompanyingPeriod( (new \DateTime()) ->sub( new \DateInterval('P' . \random_int(0, 180) . 'D') ) ); $accompanyingPeriod->setCreatedBy($this->getRandomUser()) ->setCreatedAt(new \DateTimeImmutable('now')); $person->addAccompanyingPeriod($accompanyingPeriod); $accompanyingPeriod->addSocialIssue($this->getRandomSocialIssue()); if (\random_int(0, 10) > 3) { // always add social scope: $accompanyingPeriod->addScope($this->getReference('scope_social')); $accompanyingPeriod->setAddressLocation($this->createAddress()); $manager->persist($accompanyingPeriod->getAddressLocation()); $workflow = $this->workflowRegistry->get($accompanyingPeriod); $workflow->apply($accompanyingPeriod, 'confirm'); } $manager->persist($person); $manager->persist($accompanyingPeriod); echo "add person'".$person->__toString()."'\n"; } private function getRandomUser(): User { if (0 === count($this->cacheUsers)) { $this->cacheUsers = $this->userRepository->findAll(); } return $this->cacheUsers[\array_rand($this->cacheUsers)]; } private function createAddress(): Address { $objectSet = $this->loader->loadData([ Address::class => [ 'address' => [ 'street' => '', 'streetNumber' => '', 'validFrom' => '', 'postCode' => $this->getPostalCode() ], ], ]); return $objectSet->getObjects()['address']; } private function getRandomSocialIssue(): SocialIssue { if (0 === count($this->cacheSocialIssues)) { $this->cacheSocialIssues = $this->socialIssueRepository->findAll(); } return $this->cacheSocialIssues[\array_rand($this->cacheSocialIssues)]; } private function getPostalCode(): PostalCode { $ref = LoadPostalCodes::$refs[\array_rand(LoadPostalCodes::$refs)]; return $this->getReference($ref); } /** * Create a random point * * @return Point */ private function getRandomPoint() { $lonBrussels = 4.35243; $latBrussels = 50.84676; $lon = $lonBrussels + 0.01 * rand(-5, 5); $lat = $latBrussels + 0.01 * rand(-5, 5); return Point::fromLonLat($lon, $lat); } /** * Create a random address * * @return Address */ private function getRandomAddress() { return (new Address()) ->setStreetAddress1($this->faker->streetAddress) ->setStreetAddress2( rand(0,9) > 5 ? $this->faker->streetAddress : '' ) ->setPoint( rand(0,9) > 5 ? $this->getRandomPoint() : NULL ) ->setPostcode($this->getReference( LoadPostalCodes::$refs[array_rand(LoadPostalCodes::$refs)] )) ->setValidFrom($this->faker->dateTimeBetween('-5 years')) ; } /** * @internal This method is public and called by faker as a custom generator * @return Center */ public function getRandomCenter(): Center { if (0 === count($this->cacheCenters)) { $this->cacheCenters = $this->centerRepository->findAll(); } return $this->cacheCenters[\array_rand($this->cacheCenters)]; } /** * @internal This method is public and called by faker as a custom generator * @param int $nullPercentage * @return Country|null * @throws \Exception */ public function getRandomCountry(int $nullPercentage = 20): ?Country { if (0 === count($this->cacheCountries)) { $this->cacheCountries = $this->countryRepository->findAll(); } if ($nullPercentage < \random_int(0, 100)) { return NULL; } return $this->cacheCountries [\array_rand($this->cacheCountries)]; } /** * @internal This method is public and called by faker as a custom generator * @return string */ public function getRandomGender(): string { return $this->genders[array_rand($this->genders)]; } /** * @internal This method is public and called by faker as a custom generator * @param int $nullPercentage * @return MaritalStatus|null * @throws \Exception */ public function getRandomMaritalStatus(int $nullPercentage = 50): ?MaritalStatus { if (0 === count($this->cacheMaritalStatuses)) { $this->cacheMaritalStatuses = $this->maritalStatusRepository->findAll(); } if ($nullPercentage < \random_int(0, 100)) { return NULL; } return $this->cacheMaritalStatuses[array_rand($this->cacheMaritalStatuses)]; } private $genders = array(Person::MALE_GENDER, Person::FEMALE_GENDER, Person::BOTH_GENDER); private $peoples = array( array( 'lastName' => "Depardieu", 'firstName' => "Gérard", 'birthdate' => "1948-12-27", 'placeOfBirth' => "Châteauroux", 'nationality' => 'RU', 'gender' => Person::MALE_GENDER, 'center' => 'Center A', 'accompanyingPeriods' => [ [ 'from' => '2015-02-01', 'to' => '2015-10-30', 'remark' => 'oops', ],[ 'from' => '2017-06-01', 'to' => '2018-03-30', 'remark' => 'argg', ],[ 'from' => '2019-01-01', 'to' => '2019-12-31', 'remark' => 'blob', ] ] ), array( //to have a person with same firstname as Gérard Depardieu 'lastName' => "Depardieu", 'firstName' => "Jean", 'birthdate' => "1960-10-12", 'countryOfBirth' => 'FR', 'nationality' => 'FR', 'center' => 'Center A', 'maritalStatus' => 'ms_divorce' ), array( //to have a person with same birthdate of Gérard Depardieu 'lastName' => 'Van Snick', 'firstName' => 'Bart', 'birthdate' => '1948-12-27', 'center' => 'Center A', 'maritalStatus' => 'ms_legalco' ), array( //to have a woman with Depardieu as FirstName 'lastName' => 'Depardieu', 'firstName' => 'Charline', 'gender' => Person::FEMALE_GENDER, 'center' => 'Center A', 'maritalStatus' => 'ms_legalco' ), array( //to have a special character in lastName 'lastName' => 'Manço', 'firstName' => 'Étienne', 'center' => 'Center A', 'maritalStatus' => 'ms_unknown' ), array( //to have true duplicate person 'lastName' => "Depardieu", 'firstName' => "Jean", 'birthdate' => "1960-10-12", 'countryOfBirth' => 'FR', 'nationality' => 'FR', 'center' => 'Center A', 'maritalStatus' => 'ms_divorce' ), array( //to have false duplicate person 'lastName' => "Depardieu", 'firstName' => "Jeanne", 'birthdate' => "1966-11-13", 'countryOfBirth' => 'FR', 'nationality' => 'FR', 'center' => 'Center A', 'maritalStatus' => 'ms_legalco' ), [ 'lastName' => 'Diallo', 'firstName' => "Fatoumata Binta" ], [ 'lastName' => 'Diallo', 'firstName' => 'Abdoulaye', ], [ 'lastName' => 'Diallo', 'firstName' => 'Diakite', ], [ 'lastName' => 'Diallo', 'firstName' => 'Mohamed', ], [ 'lastName' => 'Diallo', 'firstName' => 'Fatou', ], [ 'lastName' => 'Diallo', 'firstName' => 'Fanta', ], [ 'lastName' => 'Bah', 'firstName' => "Fatoumata Binta" ], [ 'lastName' => 'Bah', 'firstName' => 'Abdoulaye', ], [ 'lastName' => 'Bah', 'firstName' => 'Diakite', ], [ 'lastName' => 'Bah', 'firstName' => 'Mohamed', ], [ 'lastName' => 'Bah', 'firstName' => 'Fatou', ], [ 'lastName' => 'Bah', 'firstName' => 'Fanta', ], [ 'lastName' => 'Bah', 'firstName' => 'Gaston', ], [ 'lastName' => 'Gaillot', 'firstName' => 'Adèle', ], ); /* private function addAccompanyingPeriods(Person $person, array $periods, ObjectManager $manager) { foreach ($periods as $period) { echo "adding new past Accompanying Period..\n"; /** @var AccompanyingPeriod $accompanyingPeriod $accompanyingPeriod = new AccompanyingPeriod(new \DateTime($period['from'])); $accompanyingPeriod ->setClosingDate(new \DateTime($period['to'])) ->setRemark($period['remark']) ; $person->addAccompanyingPeriod($accompanyingPeriod); } } */ }