/**
  * Synchronize the object with the UF Match entry. Can be called stand-alone from
  * the drupalUsers script
  *
  * @param Object  $user    the drupal user object
  * @param string  $userKey the id of the user from the uf object
  * @param string  $uniqId    the OpenID of the user
  * @param string  $uf      the name of the user framework
  * @param integer $status  returns the status if user created or already exits (used for CMS sync)
  *
  * @return the ufmatch object that was found or created
  * @access public
  * @static
  */
 static function &synchronizeUFMatch(&$user, $userKey, $uniqId, $uf, $status = NULL, $ctype = NULL, $isLogin = FALSE)
 {
     $config = CRM_Core_Config::singleton();
     if (!CRM_Utils_Rule::email($uniqId)) {
         $retVal = $status ? NULL : FALSE;
         return $retVal;
     }
     $newContact = FALSE;
     // make sure that a contact id exists for this user id
     $ufmatch = new CRM_Core_DAO_UFMatch();
     $ufmatch->domain_id = CRM_Core_Config::domainID();
     $ufmatch->uf_id = $userKey;
     if (!$ufmatch->find(TRUE)) {
         $transaction = new CRM_Core_Transaction();
         $dao = NULL;
         if (!empty($_POST) && !$isLogin) {
             $params = $_POST;
             $params['email'] = $uniqId;
             $dedupeParams = CRM_Dedupe_Finder::formatParams($params, 'Individual');
             $dedupeParams['check_permission'] = FALSE;
             $ids = CRM_Dedupe_Finder::dupesByParams($dedupeParams, 'Individual');
             if (!empty($ids) && CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::MULTISITE_PREFERENCES_NAME, 'uniq_email_per_site')) {
                 // restrict dupeIds to ones that belong to current domain/site.
                 $siteContacts = CRM_Core_BAO_Domain::getContactList();
                 foreach ($ids as $index => $dupeId) {
                     if (!in_array($dupeId, $siteContacts)) {
                         unset($ids[$index]);
                     }
                 }
                 // re-index the array
                 $ids = array_values($ids);
             }
             if (!empty($ids)) {
                 $dao = new CRM_Core_DAO();
                 $dao->contact_id = $ids[0];
             }
         } else {
             $dao = CRM_Contact_BAO_Contact::matchContactOnEmail($uniqId, $ctype);
         }
         $found = FALSE;
         if ($dao) {
             // ensure there does not exists a contact_id / uf_id pair
             // in the DB. This might be due to multiple emails per contact
             // CRM-9091
             $sql = "\nSELECT id\nFROM   civicrm_uf_match\nWHERE  contact_id = %1\nAND    domain_id = %2\n";
             $params = array(1 => array($dao->contact_id, 'Integer'), 2 => array(CRM_Core_Config::domainID(), 'Integer'));
             $conflict = CRM_Core_DAO::singleValueQuery($sql, $params);
             if (!$conflict) {
                 $found = TRUE;
                 $ufmatch->contact_id = $dao->contact_id;
                 $ufmatch->uf_name = $uniqId;
             }
         }
         if (!$found) {
             if ($config->userSystem->is_drupal) {
                 $mail = 'mail';
             } elseif ($uf == 'WordPress') {
                 $mail = 'user_email';
             } else {
                 $mail = 'email';
             }
             if (is_object($user)) {
                 $params = array('email-Primary' => $user->{$mail});
             }
             if ($ctype == 'Organization') {
                 $params['organization_name'] = $uniqId;
             } elseif ($ctype == 'Household') {
                 $params['household_name'] = $uniqId;
             }
             if (!$ctype) {
                 $ctype = "Individual";
             }
             $params['contact_type'] = $ctype;
             // extract first / middle / last name
             // for joomla
             if ($uf == 'Joomla' && $user->name) {
                 CRM_Utils_String::extractName($user->name, $params);
             }
             if ($uf == 'WordPress') {
                 if ($user->first_name) {
                     $params['first_name'] = $user->first_name;
                 }
                 if ($user->last_name) {
                     $params['last_name'] = $user->last_name;
                 }
             }
             $contactId = CRM_Contact_BAO_Contact::createProfileContact($params, CRM_Core_DAO::$_nullArray);
             $ufmatch->contact_id = $contactId;
             $ufmatch->uf_name = $uniqId;
         }
         // check that there are not two CMS IDs matching the same CiviCRM contact - this happens when a civicrm
         // user has two e-mails and there is a cms match for each of them
         // the gets rid of the nasty fata error but still reports the error
         $sql = "\nSELECT uf_id\nFROM   civicrm_uf_match\nWHERE  ( contact_id = %1\nOR     uf_name      = %2\nOR     uf_id        = %3 )\nAND    domain_id    = %4\n";
         $params = array(1 => array($ufmatch->contact_id, 'Integer'), 2 => array($ufmatch->uf_name, 'String'), 3 => array($ufmatch->uf_id, 'Integer'), 4 => array($ufmatch->domain_id, 'Integer'));
         $conflict = CRM_Core_DAO::singleValueQuery($sql, $params);
         if (!$conflict) {
             $ufmatch->save();
             $ufmatch->free();
             $newContact = TRUE;
             $transaction->commit();
         } else {
             $msg = ts("Contact ID %1 is a match for %2 user %3 but has already been matched to %4", array(1 => $ufmatch->contact_id, 2 => $uf, 3 => $ufmatch->uf_id, 4 => $conflict));
             unset($conflict);
         }
     }
     if ($status) {
         return $newContact;
     } else {
         return $ufmatch;
     }
 }
 /**
  * Create WordPress user from contacts
  *
  * @access private
  *
  * @param array $rows The contacts data array
  * @return void
  */
 private function createUsers($rows)
 {
     // set debug flag when testing
     $debug = false;
     // init debug arrays
     $users = array();
     $messages = array();
     // extend PHP's execution time
     ini_set('max_execution_time', 300);
     // get default role only once
     $default_role = get_option('default_role');
     // get Civi config object
     $config = CRM_Core_Config::singleton();
     // code for redirect grabbed from CRM_Contact_Form_Task_Delete::postProcess()
     $urlParams = 'force=1';
     $urlString = "civicrm/contact/search/advanced";
     // let WordPress plugins know what we're about to do
     do_action('civicrm_wp_profile_sync_user_add_pre');
     // disable Civi's own register hook
     remove_action('user_register', array(civi_wp(), 'update_user'));
     remove_action('profile_update', array($this, 'update_user'));
     // process data
     foreach ($rows as $row) {
         // skip if no email
         if (empty($row['email'])) {
             continue;
         }
         // skip if email is not valid
         if (!is_email($row['email'])) {
             continue;
         }
         // skip if email already exists
         if (email_exists($row['email'])) {
             $messages[] = $row['email'] . ' already exists';
             continue;
         }
         // filter names
         $first_name = $this->filterName($row['first_name']);
         $middle_name = $this->filterName($row['middle_name']);
         $last_name = $this->filterName($row['last_name']);
         // lots of first names are simply initials - if so, use both first and middle names
         if (strlen($first_name) == 1) {
             $first_name .= $middle_name;
         }
         // lets only take a maximum of 8 letters of the last name
         $last_name = substr($last_name, 0, 8);
         // concatenate first and last names
         $uname = $first_name . $last_name;
         // construct a likely username
         $uname = sanitize_user($uname);
         // skip if username not valid
         if (!validate_username($uname)) {
             $messages[] = 'username ' . $uname . ' is not valid';
             continue;
         }
         // does this username already exist?
         if (username_exists($uname)) {
             $messages[] = 'username ' . $uname . ' already exists';
             $messages[] = $row;
             // let's try adding in the middle name
             $uname = $first_name . $middle_name . $last_name;
             // construct a likely username
             $uname = sanitize_user($uname);
             // skip if username not valid
             if (!validate_username($uname)) {
                 $messages[] = 'username ' . $uname . ' is not valid';
                 continue;
             }
             // skip if this username already exists
             if (username_exists($uname)) {
                 $messages[] = 'extra username ' . $uname . ' already exists';
                 continue;
             } else {
                 $messages[] = 'extra username ' . $uname . ' does not exist - we could add it';
             }
         }
         /**
          * We cannot create WP user using CRM_Core_BAO_CMSUser::create() because it
          * will attempt to log the user in and notify them of their new account. We
          * have to find another means to do this.
          *
          * In the meantime, what follows is cloned from the CiviCRM process for
          * creating WordPress users and modified accordingly.
          */
         // create an arbitrary password
         $password = substr(md5(uniqid(microtime())), 0, 8);
         // populate user data
         $user_data = array('ID' => '', 'user_login' => $uname, 'user_email' => $row['email'], 'user_pass' => $password, 'nickname' => $uname, 'role' => $default_role, 'first_name' => $row['first_name'], 'last_name' => $row['last_name']);
         // skip if debugging
         if (!$debug) {
             // add the user
             $user_id = wp_insert_user($user_data);
             // if contact doesn't already exist create UF Match
             if ($user_id !== FALSE && isset($row['id'])) {
                 $transaction = new CRM_Core_Transaction();
                 // create the UF Match record
                 $ufmatch = new CRM_Core_DAO_UFMatch();
                 $ufmatch->domain_id = CRM_Core_Config::domainID();
                 $ufmatch->uf_id = $user_id;
                 $ufmatch->contact_id = $row['id'];
                 $ufmatch->uf_name = $row['mail'];
                 if (!$ufmatch->find(TRUE)) {
                     $ufmatch->save();
                     $ufmatch->free();
                     $transaction->commit();
                 }
             }
         } else {
             // add to debug array
             $users[] = $user_data;
         }
     }
     // if debugging die now
     if ($debug) {
         trigger_error(print_r(array('method' => 'createUsers', 'messages' => $messages, 'count' => count($messages), 'users' => $users), true), E_USER_ERROR);
         die;
     }
     // re-enable Civi's register hook
     add_action('user_register', array(civi_wp(), 'update_user'));
     // let WordPress plugins know what we've done
     do_action('civicrm_wp_profile_sync_user_add_post');
     // set a message
     CRM_Core_Session::setStatus('', ts('Users Added to WordPress'), 'success');
     // redirect?
     CRM_Utils_System::redirect(CRM_Utils_System::url($urlString, $urlParams));
 }
 /**
  * Synchronize the object with the UF Match entry. Can be called stand-alone from
  * the drupalUsers script
  *
  * @param Object  $user    the drupal user object
  * @param string  $userKey the id of the user from the uf object
  * @param string  $uniqId    the OpenID of the user
  * @param string  $uf      the name of the user framework
  * @param integer $status  returns the status if user created or already exits (used for CMS sync)
  *
  * @return the ufmatch object that was found or created
  * @access public
  * @static
  */
 static function &synchronizeUFMatch(&$user, $userKey, $uniqId, $uf, $status = null, $ctype = null, $isLogin = false)
 {
     // validate that uniqId is a valid url. it will either be
     // an OpenID (which should always be a valid url) or a
     // http://uf_username/ construction (so that it can
     // be used as an OpenID in the future)
     require_once 'CRM/Utils/Rule.php';
     if ($uf == 'Standalone') {
         if (!CRM_Utils_Rule::url($uniqId)) {
             return $status ? null : false;
         }
     } else {
         if (!CRM_Utils_Rule::email($uniqId)) {
             return $status ? null : false;
         }
     }
     $newContact = false;
     // make sure that a contact id exists for this user id
     $ufmatch = new CRM_Core_DAO_UFMatch();
     if (CRM_Core_DAO::checkFieldExists('civicrm_uf_match', 'domain_id')) {
         // FIXME: if() condition check was required especially for upgrade cases (2.2.x -> 3.0.x),
         // where folks if happen to logout, would encounter a column not found fatal error
         $ufmatch->domain_id = CRM_Core_Config::domainID();
     }
     $ufmatch->uf_id = $userKey;
     if (!$ufmatch->find(true)) {
         require_once 'CRM/Core/Transaction.php';
         $transaction = new CRM_Core_Transaction();
         if (!empty($_POST) && !$isLogin) {
             $params = $_POST;
             $params['email'] = $uniqId;
             require_once 'CRM/Dedupe/Finder.php';
             $dedupeParams = CRM_Dedupe_Finder::formatParams($params, 'Individual');
             $dedupeParams['check_permission'] = false;
             $ids = CRM_Dedupe_Finder::dupesByParams($dedupeParams, 'Individual');
             if (!empty($ids) && defined('CIVICRM_UNIQ_EMAIL_PER_SITE') && CIVICRM_UNIQ_EMAIL_PER_SITE) {
                 // restrict dupeIds to ones that belong to current domain/site.
                 require_once 'CRM/Core/BAO/Domain.php';
                 $siteContacts = CRM_Core_BAO_Domain::getContactList();
                 foreach ($ids as $index => $dupeId) {
                     if (!in_array($dupeId, $siteContacts)) {
                         unset($ids[$index]);
                     }
                 }
                 $ids = array_values($ids);
                 //re-index the array
             }
             if (!empty($ids)) {
                 $dao = new CRM_Core_DAO();
                 $dao->contact_id = $ids[0];
             }
         } else {
             require_once 'CRM/Contact/BAO/Contact.php';
             if ($uf == 'Standalone') {
                 $dao =& CRM_Contact_BAO_Contact::matchContactOnOpenId($uniqId, $ctype);
             } else {
                 $dao =& CRM_Contact_BAO_Contact::matchContactOnEmail($uniqId, $ctype);
             }
         }
         if ($dao) {
             //print "Found contact with uniqId $uniqId<br/>";
             $ufmatch->contact_id = $dao->contact_id;
             $ufmatch->uf_name = $uniqId;
         } else {
             if ($uf == 'Drupal') {
                 $mail = 'mail';
             } else {
                 $mail = 'email';
             }
             if (is_Object($user)) {
                 $params = array('email-Primary' => $user->{$mail});
             }
             if ($ctype == 'Organization') {
                 $params['organization_name'] = $uniqId;
             } else {
                 if ($ctype == 'Household') {
                     $params['household_name'] = $uniqId;
                 }
             }
             if (!$ctype) {
                 $ctype = "Individual";
             }
             $params['contact_type'] = $ctype;
             // extract first / middle / last name
             // for joomla
             if ($uf == 'Joomla' && $user->name) {
                 require_once 'CRM/Utils/String.php';
                 CRM_Utils_String::extractName($user->name, $params);
             }
             if ($uf == 'Standalone') {
                 $params['openid-Primary'] = $uniqId;
                 //need to delete below code once profile is
                 //exposed on signup page
                 if (!empty($user->first_name) || !empty($user->last_name)) {
                     $params['first_name'] = $user->first_name;
                     $params['last_name'] = $user->last_name;
                 } elseif (!empty($user->name)) {
                     require_once 'CRM/Utils/String.php';
                     CRM_Utils_String::extractName($user->name, $params);
                 }
             }
             $contactId = CRM_Contact_BAO_Contact::createProfileContact($params, CRM_Core_DAO::$_nullArray);
             $ufmatch->contact_id = $contactId;
             $ufmatch->uf_name = $uniqId;
         }
         // check that there are not two CMS IDs matching the same CiviCRM contact - this happens when a civicrm
         // user has two e-mails and there is a cms match for each of them
         // the gets rid of the nasty fata error but still reports the error
         $sql = "\nSELECT uf_id\nFROM   civicrm_uf_match\nWHERE  ( contact_id = %1\nOR     uf_name      = %2\nOR     uf_id        = %3 )\nAND    domain_id    = %4\n";
         $params = array(1 => array($ufmatch->contact_id, 'Integer'), 2 => array($ufmatch->uf_name, 'String'), 3 => array($ufmatch->uf_id, 'Integer'), 4 => array($ufmatch->domain_id, 'Integer'));
         require_once 'CRM/Core/DAO.php';
         $conflict = CRM_Core_DAO::singleValueQuery($sql, $params);
         if (!$conflict) {
             $ufmatch->save();
             $ufmatch->free();
             $newContact = true;
             $transaction->commit();
         } else {
             $msg = ts("Contact ID %1 is a match for %2 user %3 but has already been matched to %4", array(1 => $ufmatch->contact_id, 2 => $uf, 3 => $ufmatch->uf_id, 4 => $conflict));
             unset($conflict);
         }
     }
     if ($status) {
         return $newContact;
     } else {
         return $ufmatch;
     }
 }