├── Console └── Command │ └── FakeMyData.php ├── Faker └── Provider │ └── Got │ └── Person.php ├── Model └── FakeMyData.php ├── README.md ├── composer.json ├── etc ├── adminhtml │ └── system.xml ├── config.xml ├── di.xml └── module.xml └── registration.php /Console/Command/FakeMyData.php: -------------------------------------------------------------------------------- 1 | fakeMyDataModel = $fakeMyDataModel; 20 | parent::__construct('fakemydata'); 21 | } 22 | 23 | /** 24 | * {@inheritdoc} 25 | */ 26 | protected function execute( 27 | InputInterface $input, 28 | OutputInterface $output 29 | ) { 30 | $this->fakeMyDataModel->fakeAll(); 31 | } 32 | 33 | /** 34 | * {@inheritdoc} 35 | */ 36 | protected function configure() 37 | { 38 | $this->setName("experius_fakemydata:fakeall"); 39 | $this->setDescription("Replace Customer Data with Fake Names"); 40 | parent::configure(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Faker/Provider/Got/Person.php: -------------------------------------------------------------------------------- 1 | faker = $faker; 68 | $this->resourceConnection = $resourceConnection; 69 | $this->connection = $this->resourceConnection->getConnection(); 70 | $this->encryptor = $encryptor; 71 | $this->scopeConfig = $scopeConfig; 72 | $this->state = $state; 73 | $this->storeRepository = $storeRepository; 74 | } 75 | 76 | public function initStores(){ 77 | $stores = $this->storeRepository->getList(); 78 | foreach($stores as $store){ 79 | $this->stores[$store->getId()] = $this->scopeConfig->getValue('general/locale/code',\Magento\Store\Model\ScopeInterface::SCOPE_STORE,$store->getId()); 80 | } 81 | } 82 | 83 | public function getLocaleByStoreId($storeId){ 84 | if(isset($this->stores[$storeId])){ 85 | return $this->stores[$storeId]; 86 | } 87 | return 'en_US'; 88 | } 89 | 90 | public function getExcludedEmailDomains(){ 91 | if(!$this->excludedEmailDomains){ 92 | $this->excludedEmailDomains = $this->scopeConfig->getValue('fakemydata/general/excluded_email_domains'); 93 | } 94 | return $this->excludedEmailDomains; 95 | } 96 | 97 | public function getFakeEmailDomain(){ 98 | if(!$this->fakeEmailDomain){ 99 | $this->fakeEmailDomain = $this->scopeConfig->getValue('fakemydata/general/fake_email_domain'); 100 | } 101 | return $this->fakeEmailDomain; 102 | } 103 | 104 | public function getFakeEmailPrefix(){ 105 | if(!$this->fakeEmailPrefix){ 106 | $this->fakeEmailPrefix = $this->scopeConfig->getValue('fakemydata/general/fake_email_prefix'); 107 | } 108 | return $this->fakeEmailPrefix; 109 | } 110 | 111 | public function getPassword(){ 112 | if(!$this->password){ 113 | $this->password = $this->scopeConfig->getValue('fakemydata/general/password'); 114 | } 115 | return $this->password; 116 | } 117 | 118 | public function getCustomProvider(){ 119 | if(!$this->customProvider){ 120 | $this->customProvider = $this->scopeConfig->getValue('fakemydata/general/customprovider'); 121 | } 122 | return $this->customProvider; 123 | } 124 | 125 | public function getSelect($tableName,$excludeEmailField='email',$join){ 126 | $select = $this->connection->select(); 127 | $select->from($tableName,'*'); 128 | 129 | if($join) { 130 | $select->joinLeft(['customers' => 'customer_entity'], 'customers.entity_id' . ' = ' . $tableName . '.parent_id', ['email']); 131 | } 132 | 133 | foreach(explode(',',$this->getExcludedEmailDomains()) as $excludedEmailDomain){ 134 | $select->where($excludeEmailField . " NOT LIKE '%" . $excludedEmailDomain ."'"); 135 | } 136 | 137 | return $select; 138 | } 139 | 140 | public function fakeAll(){ 141 | 142 | if(\Magento\Framework\App\State::MODE_DEVELOPER != $this->state->getMode()){ 143 | echo "Wow you're not in develop mode. Don't run this on production environments"; 144 | exit; 145 | } 146 | 147 | $this->initStores(); 148 | 149 | foreach($this->fakedDataTypes as $type) { 150 | $this->fakeData($type); 151 | } 152 | } 153 | 154 | public function stringToUniqueInt($value){ 155 | return base_convert(md5($value), 10, 10); 156 | } 157 | 158 | public function getSeed($value){ 159 | if(!is_numeric($value)){ 160 | return $this->stringToUniqueInt($value); 161 | } 162 | return $value; 163 | } 164 | 165 | /* TODO make unique address work */ 166 | 167 | public function getFakeCustomerData($results,$identifier='entity_id',$uniqueAddress=false){ 168 | foreach($results as $result) { 169 | 170 | $seed = $this->getSeed($result[$identifier]); 171 | 172 | $locale = 'en_US'; 173 | if(isset($result['store_id'])){ 174 | $locale = $this->getLocaleByStoreId($result['store_id']); 175 | } 176 | 177 | $faker = $this->faker->create($locale); 178 | $faker->seed($seed); 179 | 180 | if($this->getCustomProvider()) { 181 | $customProvider = $this->getCustomProvider(); 182 | $class = "\\Experius\\FakeMyData\\Faker\\Provider\\" . $customProvider . "\\Person"; 183 | $faker->addProvider(new $class($faker)); 184 | } 185 | 186 | $firstname = $faker->firstName; 187 | $lastname = $faker->lastName; 188 | $dateOfBirthYear = $faker->dateTimeThisCentury->format('Y'); 189 | 190 | $fakeData = [ 191 | 'firstname'=>$firstname, 192 | 'lastname'=>$lastname, 193 | 'name' => $firstname . ' ' . $lastname, 194 | 'email'=> $this->getFakeEmail([$firstname,$lastname,$dateOfBirthYear]), 195 | 'street' => $this->getFakeStreet([$faker->streetName, $faker->buildingNumber]), 196 | 'postcode' => $faker->postcode, 197 | 'telephone' => $faker->phoneNumber, 198 | 'city'=> $faker->city, 199 | 'company' => $faker->company, 200 | 'password_hash' => $this->getPasswordHash() 201 | ]; 202 | 203 | $fakeData['address'] = $fakeData['street'] . "\n" . $fakeData['postcode'] . "\n". $fakeData['city']; 204 | 205 | $this->fakedData[$seed] = $fakeData; 206 | 207 | } 208 | } 209 | 210 | public function fakeData($type){ 211 | 212 | switch($type){ 213 | case 'customer': 214 | 215 | $select = $this->getSelect('customer_entity','email',false); 216 | $results = $this->connection->fetchAll($select); 217 | $this->getFakeCustomerData($results,'entity_id'); 218 | $this->updateData('entity_id',['firstname'=>'firstname','lastname'=>'lastname','email'=>'email','password_hash'=>'password_hash'],'customer_entity',$results,'entity_id'); 219 | 220 | break; 221 | case 'customer_address': 222 | 223 | $select = $this->getSelect('customer_address_entity','email','customer_id'); 224 | $results = $this->connection->fetchAll($select); 225 | 226 | /* TODO fake each address different */ 227 | 228 | $this->getFakeCustomerData($results,'parent_id'); 229 | $this->updateData('parent_id',['firstname'=>'firstname','lastname'=>'lastname','postcode'=>'postcode','telephone'=>'telephone','city'=>'city','street'=>'street'],'customer_address_entity',$results,'entity_id'); 230 | 231 | break; 232 | 233 | case 'order': 234 | 235 | $select = $this->getSelect('sales_order','customer_email',false); 236 | $select->where('customer_id IS NOT NULL'); 237 | $results = $this->connection->fetchAll($select); 238 | $this->getFakeCustomerData($results,'customer_id'); 239 | $this->updateData('customer_id',['customer_firstname'=>'firstname','customer_lastname'=>'lastname','customer_email'=>'email'],'sales_order',$results,'entity_id'); 240 | 241 | $select = $this->getSelect('sales_order','customer_email',false); 242 | $select->where('customer_id IS NULL'); 243 | $results = $this->connection->fetchAll($select); 244 | $this->getFakeCustomerData($results,'entity_id'); 245 | $this->updateData('entity_id',['customer_firstname'=>'firstname','customer_lastname'=>'lastname','customer_email'=>'email'],'sales_order',$results,'entity_id'); 246 | 247 | break; 248 | case 'order_grid': 249 | 250 | $select = $this->getSelect('sales_order_grid','customer_email',false); 251 | $select->where('customer_id IS NOT NULL'); 252 | $results = $this->connection->fetchAll($select); 253 | $this->getFakeCustomerData($results,'customer_id'); 254 | $this->updateData('customer_id',['shipping_name'=>'name','billing_name'=>'name','customer_name'=>'name','customer_email'=>'email'],'sales_order_grid',$results,'entity_id'); 255 | 256 | $select = $this->getSelect('sales_order_grid','customer_email',false); 257 | $select->where('customer_id IS NULL'); 258 | $results = $this->connection->fetchAll($select); 259 | $this->getFakeCustomerData($results,'entity_id'); 260 | $this->updateData('entity_id',['shipping_name'=>'name','billing_name'=>'name','customer_name'=>'name','customer_email'=>'email'],'sales_order_grid',$results,'entity_id'); 261 | 262 | break; 263 | 264 | case 'sales_invoice_grid': 265 | case 'sales_shipment_grid': 266 | case 'sales_creditmemo_grid': 267 | $select = $this->getSelect($type,$type.'.customer_email',false); 268 | $select->joinLeft(['sales_order_grid' => 'sales_order_grid'], 'sales_order_grid.entity_id' . ' = '.$type.'.order_id', ['customer_id'=>'customer_id']); 269 | $select->where('sales_order_grid.customer_id IS NOT NULL'); 270 | $results = $this->connection->fetchAll($select); 271 | $this->getFakeCustomerData($results,'customer_id'); 272 | $this->updateData('customer_id',['billing_name'=>'name','customer_name'=>'name','customer_email'=>'email','billing_address'=>'address','shipping_address'=>'address'],$type,$results,'entity_id'); 273 | 274 | $select = $this->getSelect($type,$type.'.customer_email',false); 275 | $select->joinLeft(['sales_order_grid' => 'sales_order_grid'], 'sales_order_grid.entity_id' . ' = '.$type.'.order_id', ['customer_id'=>'customer_id']); 276 | $select->where('sales_order_grid.customer_id IS NULL'); 277 | $results = $this->connection->fetchAll($select); 278 | $this->getFakeCustomerData($results,'order_id'); 279 | $this->updateData('order_id',['billing_name'=>'name','customer_name'=>'name','customer_email'=>'email','billing_address'=>'address','shipping_address'=>'address'],$type,$results,'entity_id'); 280 | break; 281 | case 'quote': 282 | 283 | $select = $this->getSelect('quote','customer_email',false); 284 | $select->where('customer_id IS NOT NULL'); 285 | $results = $this->connection->fetchAll($select); 286 | $this->getFakeCustomerData($results,'customer_id'); 287 | $this->updateData('customer_id',['customer_firstname'=>'firstname','customer_lastname'=>'lastname','customer_email'=>'email'],'quote',$results,'entity_id'); 288 | 289 | /* Todo Join with order Table */ 290 | $select = $this->getSelect('quote','customer_email',false); 291 | $select->where('customer_id IS NULL'); 292 | $select->where('customer_firstname IS NOT NULL OR customer_lastname IS NOT NULL OR customer_email IS NOT NULL'); 293 | $results = $this->connection->fetchAll($select); 294 | $this->getFakeCustomerData($results,'entity_id'); 295 | $this->updateData('entity_id',['customer_firstname'=>'firstname','customer_lastname'=>'lastname','customer_email'=>'email'],'quote',$results,'entity_id'); 296 | 297 | break; 298 | case 'quote_address': 299 | break; 300 | case 'review': 301 | break; 302 | case 'newsletter': 303 | 304 | $select = $this->getSelect('newsletter_subscriber','subscriber_email',false); 305 | $select->where('customer_id IS NOT NULL'); 306 | $results = $this->connection->fetchAll($select); 307 | $this->getFakeCustomerData($results,'customer_id'); 308 | $this->updateData('customer_id',['subscriber_email'=>'email'],'newsletter_subscriber',$results,'subscriber_id'); 309 | 310 | $select = $this->getSelect('newsletter_subscriber','subscriber_email',false); 311 | $select->where('subscriber_id IS NOT NULL'); 312 | $results = $this->connection->fetchAll($select); 313 | $this->getFakeCustomerData($results,'customer_id'); 314 | $this->updateData('subscriber_id',['subscriber_email'=>'email'],'newsletter_subscriber',$results,'subscriber_id'); 315 | 316 | break; 317 | } 318 | 319 | } 320 | 321 | public function updateData($identifier,$fields,$tableName,$results,$updateIdentifier){ 322 | $tableName = $this->resourceConnection->getTableName($tableName); 323 | $this->updateFlat($identifier,$results,$fields,$tableName,$updateIdentifier); 324 | } 325 | 326 | public function getFakeEmail($values){ 327 | return $this->getFakeEmailPrefix() . str_replace([" ","'",],'.',implode('.',$values)) . '@' . $this->getFakeEmailDomain(); 328 | } 329 | 330 | public function getPasswordHash(){ 331 | if(!$this->passwordHash) { 332 | $this->passwordHash = $this->encryptor->getHash($this->getPassword(), true); 333 | } 334 | return $this->passwordHash; 335 | } 336 | 337 | public function getAddressLines(){ 338 | if(!$this->addressLines){ 339 | $this->addressLines = $this->scopeConfig->getValue('customer/address/street_lines'); 340 | } 341 | return $this->addressLines; 342 | } 343 | 344 | public function getFakeStreet($values){ 345 | $addressLines = $this->addressLines; 346 | 347 | if($addressLines==1){ 348 | return implode(" ",$values); 349 | } 350 | 351 | if($addressLines==2){ 352 | return $values[0] . "\n" . $values[1] . (isset($values[3])) ? " " . $values[3] : ''; 353 | } 354 | 355 | return implode("\n",$values); 356 | } 357 | 358 | /* TODO Optional update only if field has value */ 359 | public function updateFlat($identifier,$results,$fields,$tableName,$updateIdentifier){ 360 | 361 | foreach($results as $result){ 362 | 363 | $seed = $this->getSeed($result[$identifier]); 364 | 365 | $updateData = []; 366 | 367 | $fakeData = $this->fakedData[$seed]; 368 | 369 | foreach($fields as $field=>$fakeDataArrayKey){ 370 | $updateData[$field] = $fakeData[$fakeDataArrayKey]; 371 | } 372 | 373 | $this->connection->update($tableName,$updateData,[$updateIdentifier." = ? " => $result[$updateIdentifier]]); 374 | 375 | } 376 | } 377 | } 378 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **Data Faker For Magento 2** 2 | 3 | Based on fzaninotto/Faker https://github.com/fzaninotto/Faker 4 | 5 | Replaces existing customer data for fake data. Used for develop and staging environments. 6 | 7 | Effects Following Tables 8 | 9 | - customer_entity 10 | - customer_address_entity 11 | - sales_order 12 | - sales_order_grid 13 | - sales_invoice_grid 14 | - sales_creditmemo_grid 15 | - sales_shipment_grid 16 | - qoute 17 | - newsletter 18 | 19 | php bin/magento experius_fakemydata:fakeall 20 | 21 | 22 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "experius/module-fakemydata", 3 | "description": "Magento 2 Customer Data Faker. Replaces existing customer data for fake data. Used for develop and staging environments.", 4 | "license": "proprietary", 5 | "authors": [ 6 | { 7 | "name": "Mage2Gen", 8 | "email": "info@mage2gen.com" 9 | }, 10 | { 11 | "name": "Derrick Heesbeen", 12 | "email": "derrick@experius.nl" 13 | } 14 | ], 15 | "minimum-stability": "dev", 16 | "require": { 17 | "fzaninotto/faker": "1.6.*" 18 | }, 19 | "autoload": { 20 | "psr-4": { 21 | "Experius\\FakeMyData\\": "" 22 | }, 23 | "files": [ 24 | "registration.php" 25 | ] 26 | } 27 | } -------------------------------------------------------------------------------- /etc/adminhtml/system.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | advanced 7 | Experius_FakeMyData::config_experius_fakemydata 8 | 9 | 10 | 11 | 12 | (comma separated) Data with e-mail addresses with these domains will not be changed 13 | 14 | 15 | 16 | (comma separated) Is used for the fake email addresses (In case its the same as Excluded domain. Data will only be changed once) 17 | 18 | 19 | 20 | for example john+ 21 | 22 | 23 | 24 | Will be used for all changed customer accounts 25 | 26 | 27 |
28 |
29 |
-------------------------------------------------------------------------------- /etc/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | experius.nl 7 | experius.nl 8 | 9 | F@k3MyD@t@ 10 | 0 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /etc/di.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Experius\FakeMyData\Console\Command\FakeMyData 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /etc/module.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /registration.php: -------------------------------------------------------------------------------- 1 |