em = $em; $this->loadCustomerTags(); parent::__construct(); } protected function configure() { $this->setName('customer:createfromcarclub') ->setDescription('Create customers from car club file.') ->setHelp('Creates customers from car club file.') ->addArgument('promo_tag', InputArgument::REQUIRED, 'Promo customer tag ID to use.') ->addArgument('input_file', InputArgument::REQUIRED, 'Path to the output CSV file with the car club info.') ->addArgument('output_file', InputArgument::REQUIRED, 'Output filename'); } protected function getValidContactNumbers($contact_number) { // check contact number if mobile or not // check for spaces, slash, and forward slash $contact_num_array = []; if (preg_match('/[\\\s\/]/', $contact_number)) { $contact_num_array = preg_split('/[\\\s\/]/', $contact_number); } else { // only one mobile number $contact_num_array[] = $contact_number; } // collet clean numbers $clean_nums = []; foreach ($contact_num_array as $contact_num) { $c_num = trim($contact_num); // clean the numbers $cleaned_number = $this->normalizeContactNumber($c_num); // not a blank, save it if ($cleaned_number != '') { $clean_nums[] = $cleaned_number; } } return $clean_nums; } protected function execute(InputInterface $input, OutputInterface $output) { $csv_file = $input->getArgument('input_file'); $output_file = $input->getArgument('output_file'); $promo_tag_id = $input->getArgument('promo_tag'); // fetch promo tag $promo_tag = $this->em->getRepository(CustomerTag::class)->find($promo_tag_id); if ($promo_tag == null) { throw new Exception('Could not find promo tag - ' . $promo_tag_id); } // attempt to open file try { $fh = fopen($csv_file, "r"); } catch (Exception $e) { throw new Exception('The file "' . $csv_file . '" could be opened.'); } $row_num = 1; $output_info = []; while (($fields = fgetcsv($fh)) !== false) { // ignore first row if ($row_num == 1) { $row_num++; continue; } // process row $output_info[] = $this->processRow($fields, $promo_tag); $row_num++; } // write to output file $this->outputCustomerInfo($output_file, $output_info); fclose($fh); return 0; } protected function setOutputInfo($fields, $status, $reason, $cust_id) { $car_club = trim($fields[self::F_CAR_CLUB]); $fname = trim($fields[self::F_FIRST_NAME]); $lname = trim($fields[self::F_LAST_NAME]); $dpa = trim($fields[self::F_DPA]); $contact_number = trim($fields[SELF::F_CONTACT_NUM]); return [ $dpa, $fname, $lname, $car_club, $contact_number, $status, $reason, $cust_id ]; } protected function createNewCustomer($fields, $contact_numbers, $cust_tag, $promo_tag) { $fname = trim($fields[self::F_FIRST_NAME]); $lname = trim($fields[self::F_LAST_NAME]); $dpa = trim($fields[self::F_DPA]); if (count($contact_numbers) > 0) $clean_number = $contact_numbers[0]; else $clean_number = ''; // check dpa $is_dpa = false; if (strtoupper($dpa) == 'YES') $is_dpa = true; // create new customer $new_cust = new Customer(); $new_cust->setFirstName($fname) ->setLastName($lname) ->setPhoneMobile($clean_number) ->setDpaConsent($is_dpa) ->setCreateSource('car_club_file') ->addCustomerTag($cust_tag) ->addCustomerTag($promo_tag); $this->em->persist($new_cust); $this->em->flush(); return $new_cust; } protected function processRow($fields, $promo_tag) { $contact_number = trim($fields[SELF::F_CONTACT_NUM]); $car_club = trim($fields[self::F_CAR_CLUB]); // clean up contact number $valid_contact_numbers = $this->getValidContactNumbers($contact_number); // check customer tag $cust_tag = $this->findCustomerTag($car_club); $cust_id = ''; // give me first customer that matches any of the numbers $customer = $this->findCustomerByNumbers($valid_contact_numbers); // if no customer found, create one if ($customer == null) { error_log('Creating customer...'); error_log('cust tag id ' . $cust_tag->getID()); // create new customer $new_cust = $this->createNewCustomer($fields, $valid_contact_numbers, $cust_tag, $promo_tag); // get customer id of new customer here $cust_id = $new_cust->getID(); // add info to output array return $this->setOutputInfo($fields, 'CREATED', '', $cust_id); } error_log('Updating customer...'); // add customer tag to existing customer $cust_id = $customer->getID(); // need to check if customer tag already exists for customer $tag_exists = $customer->getCustomerTag($cust_tag->getID()); if ($tag_exists == null) { $customer->addCustomerTag($cust_tag) ->addCustomerTag($promo_tag); $this->em->flush(); // add info to output array return $this->setOutputInfo($fields, 'UPDATED', '', $cust_id); } return $this->setOutputInfo($fields, 'NOT CREATED/UPDATED', 'Customer and tag already exist', $cust_id); } protected function findCustomerByNumbers($numbers) { error_log(print_r($numbers, true)); $customer = $this->em->getRepository(Customer::class)->findOneBy(['phone_mobile' => $numbers]); return $customer; } protected function outputCustomerInfo($output_file, $entries) { try { $fh = fopen($output_file, "w"); } catch (Exception $e) { throw new Exception('The file "' . $report_file . '" could be opened.'); } // write the headers fputcsv($fh, [ 'I have read and understood and agreed to the confidentiality of this form request', 'First Name', 'Last Name', 'Car Club/Organization', 'Contact Number', 'Status', 'Reason', 'Customer ID', ]); foreach($entries as $row) { fputcsv($fh, $row); } fclose($fh); } protected function loadCustomerTags() { $this->cust_tag_hash = []; $cust_tags = $this->em->getRepository(CustomerTag::class)->findAll(); foreach ($cust_tags as $cust_tag) { $tag_id = $cust_tag->getID(); $this->cust_tag_hash[$tag_id] = $cust_tag; } } protected function normalizeClubName($name) { // uppercase the name $clean_name = trim(strtoupper($name)); // remove apostrophes $clean_name = str_replace("'", '', $clean_name); // replace all special characters except ampersand (&) with whitespace $clean_name = trim(preg_replace('/[^A-Za-z0-9&]/', ' ', $clean_name)); // replace spaces with underscore (_) $clean_name = preg_replace('/\s+/', '_', $clean_name); // prepend 'TAG_' $tag_name = 'TAG_' . $clean_name; return $tag_name; } protected function findCustomerTag($car_club) { // find the customer tag for club $tag_name = $this->normalizeClubName($car_club); error_log($tag_name); if (isset($this->cust_tag_hash[$tag_name])) return $this->cust_tag_hash[$tag_name]; error_log('customer tag not in hash...'); // create the customer tag $new_cust_tag = new CustomerTag(); $tag_details = json_decode('{"type":"car club"}', true); $new_cust_tag->setID($tag_name) ->setName(strtoupper($car_club)) ->setTagDetails($tag_details); $this->em->persist($new_cust_tag); // need to flush before adding to hash $this->em->flush(); $this->cust_tag_hash[$tag_name] = $new_cust_tag; return $new_cust_tag; } protected function normalizeContactNumber($c_num) { // remove any non digit character from string $clean_number = preg_replace('~\D~', '', $c_num); error_log('cleaned ' . $clean_number); // does it fit our 09XXXXXXXXX pattern? if (preg_match('/^09[0-9]{9}$/', $clean_number)) { // remove first '0' $clean_number = substr($clean_number, 1); error_log("CONVERTED TO $clean_number"); return $clean_number; } // does it fit our 63XXXXXXXXXX pattern? else if (preg_match('/^63[0-9]{10}$/', $clean_number)) { // remove the 63 $clean_number = substr($clean_number, 2); error_log("CONVERTED TO $clean_number"); return $clean_number; } // does it fit our 9XXXXXXXXX pattern? else if (preg_match('/^9[0-9]{9}$/', $clean_number)) { error_log("already cleaned $clean_number"); return $clean_number; } return ""; } }