<?php
class OroConnector
{
protected $_username;
protected $_apiKey;
protected $_userSalt;
private $header;
protected $_server = 'https://orocrm.my.url/api';
public $debug;
/**
* @param $username
* @param $apiUserKey
* @param string $userSalt
*/
public function __construct ($debug = false, $apiUserKey="myApiKey", $username="miUserName", $userSalt = '')
{
$this->debug = $debug;
$this->_username = $username;
$this->_apiKey = $apiUserKey;
$this->_userSalt = $userSalt; // deprecated in OroCRM v1.0
}
/**
* @param $raw
* @param $salt
* @return string
*/
private function _encodePassword($raw, $salt)
{
$salted = $this->_mergePasswordAndSalt($raw, $salt);
$digest = hash('sha1', $salted, true);
return base64_encode($digest);
}
/**
* @param $password
* @param $salt
* @return string
* @throws InvalidArgumentException
*/
private function _mergePasswordAndSalt($password, $salt)
{
if (empty($salt)) {
return $password;
}
if (false !== strrpos($salt, '{') || false !== strrpos($salt, '}')) {
throw new \InvalidArgumentException('Cannot use { or } in salt.');
}
return $password.'{'.$salt.'}';
}
/**
* @return array
*/
public function setHeader()
{
$prefix = $this->_server;
$created = date('c');
$nonce = base64_encode(substr(md5(uniqid($prefix . '_', true)), 0, 16));
$passwordDigest = $this->_encodePassword(base64_decode($nonce) . $created . $this->_apiKey, $this->_userSalt);
$wsseProfile = sprintf(
'X-WSSE: UsernameToken Username="%s", PasswordDigest="%s", Nonce="%s", Created="%s"',
$this->_username,
$passwordDigest,
$nonce,
$created
);
$this->header = array(
'Content-Type: application/vnd.api+json',
'Authorization: WSSE profile="UsernameToken"',
$wsseProfile
);
}
public function getHeader(){
return $this->header;
}
private function goCurl($url,$method,$data = array()){
$ch = curl_init();
$this->setHeader();
$curlOpt = array(
CURLOPT_URL => $this->_server . $url,
CURLOPT_RETURNTRANSFER => ($this->debug)?false:true,
CURLOPT_HTTPHEADER => $this->header,
CURLOPT_HEADER => ($this->debug)?true:false,
CURLOPT_FAILONERROR => false,
CURLOPT_NOBODY => false,
CURLOPT_VERBOSE => ($this->debug)?true:false,
CURLINFO_HEADER_OUT => ($this->debug)?true:false,
);
switch(strtoupper($method)){
case 'POST':
$curlOpt[CURLOPT_CUSTOMREQUEST]='POST';
BREAK;
case 'OPTIONS':
$curlOpt[CURLOPT_CUSTOMREQUEST]='OPTIONS';
break;
case 'PUT':
$curlOpt[CURLOPT_CUSTOMREQUEST]='PUT';
break;
case 'PATCH':
$curlOpt[CURLOPT_CUSTOMREQUEST]='PATCH';
break;
case 'DELETE':
$curlOpt[CURLOPT_CUSTOMREQUEST]='DELETE';
break;
}
if (!empty($data)) {
$curlOpt[CURLOPT_POSTFIELDS] = json_encode($data);
}
curl_setopt_array($ch, $curlOpt);
$result = curl_exec($ch);
if ( $result === false) {
return curl_getinfo($ch);
}
curl_close($ch);
return json_decode($result,true);
}
public function saveContact($contact){
/**
* Find clients by email
*/
$url = '/contacts?include=emails,phones&filter[emails.email]='.urlencode($contact['email']);
$contacts = $this->goCurl($url,'GET');
//if not found and in the form they have the phone, filter by phone
if(count($contacts['data']) == 0 && isset($contact['phone']) && $contact['phone'] != ''){
$url = '/contacts?include=emails,phones&filter[phones.phone]='.urlencode($contact['phone']);
$contacts = $this->goCurl($url,'GET');
//if you add it does not exist and if there is update only phone i emails
if(count($contacts['data']) == 0){
return $this->storeContact($contact);
} else {
// actualitzar
return $this->updateContact($contact,$contacts);
}
//if there is no filtering mail and telephone has not set I add
} elseif(count($contacts['data']) == 0){
return $this->storeContact($contact);
} else { //if there is mail filtering upgraded phone and email
return $this->updateContact($contact,$contacts);
}
}
private function storeContact($contact){
$contacPatch = [ 'data'=> [
"type"=> "contacts",
"attributes" => [
'firstName'=>$contact['firstName'],
'lastName'=>$contact['lastName'],
],
'relationships'=>[
'owner'=>[
'data'=>[
'type'=>'users',
'id'=>2
]
],
'organization'=>[
'data'=>[
'type' => 'organizations',
'id'=>2
]
]
]
]
];
$url = '/contacts';
$savedContact = $this->goCurl($url,'POST',$contacPatch);
if(isset($savedContact['data']['id'])){
$contacEmails = [ 'data'=> [
"type"=> "contactemails",
"attributes" => [
'email'=>$contact['email'],
'primary'=>true,
],
'relationships'=>[
'owner'=>[
'data'=>[
'type' => 'contacts',
'id' =>$savedContact['data']['id']
]
]
]
]
];
$url = '/contactemails';
$this->goCurl($url,'POST',$contacEmails);
if(isset($contact['phone']) and $contact['phone'] != ''){
$contacPhones = [ 'data'=> [
"type"=> "contactphones",
"attributes" => [
'phone'=>$contact['phone'],
'primary'=>true,
],
'relationships'=>[
'owner'=>[
'data'=>[
'type' => 'contacts',
'id' =>$savedContact['data']['id']
]
]
]
]
];
$url = '/contactphones';
$this->goCurl($url,'POST',$contacPhones);
}
} else {
return false;
}
return true;
}
private function updateContact($contact,$contactOld){
$contactId=$contactOld['data'][0]['id'];
$emailsOld = [];
foreach($contactOld['data'][0]['relationships']['emails']['data'] as $email) $emailsOld[]=$email['id'];
$phonesOld = [];
foreach($contactOld['data'][0]['relationships']['phones']['data'] as $phone) $phonesOld[]=$phone['id'];
$newEmails = [];
$newPhones = [];
$updateEmails = [];
$updatePhones = [];
$newEmail = true;
$newPhone = (!isset($contact['phone']) || $contact['phone'] =='') ? false : true;
foreach($contactOld['included'] as $related){
if($related['type'] == 'contactemails' && in_array($related['id'],$emailsOld)){ //si es email i es del contacte que actualitzem
if($related['attributes']['email'] == $contact['email'] && $related['attributes']['primary'] != 1){
// si es el que ha posat i no es primary el posem com a primary
$tmp = $related;
$tmp['attributes']['primary'] = 1;
$updateEmails[] = $tmp;
$newEmail = false;
} elseif($related['attributes']['email'] == $contact['email'] && $related['attributes']['primary'] == 1){
// si es el que ha posat i es primary fixem per a no crear un correu
$newEmail = false;
} elseif($related['attributes']['email'] != $contact['email'] && $related['attributes']['primary'] == 1){
// si el correu que te guardad es diferent al nou y estava com a primary li treiem el primary.
$tmp = $related;
$tmp['attributes']['primary'] = 0;
$updateEmails[] = $tmp;
}
//si un correu es diferent i no esta com a primary no cal fer res.
}
if($related['type'] == 'contactphones' && in_array($related['id'],$phonesOld) && isset($contact['phone']) && $contact['phone'] !=''){ //si es phone i es del contacte que actualitzem
if($related['attributes']['phone'] == $contact['phone'] && $related['attributes']['primary'] != 1){
// si es el que ha posat i no es primary el posem com a primary
$tmp = $related;
$tmp['attributes']['primary'] = 1;
$updatePhones[] = $tmp;
$newPhone = false;
} elseif($related['attributes']['phone'] == $contact['phone'] && $related['attributes']['primary'] == 1){
// si es el que ha posat i es primary fixem per a no crear un telefon
$newPhone = false;
} elseif($related['attributes']['phone'] != $contact['phone'] && $related['attributes']['primary'] == 1){
// si el telefon que te guardat es diferent al nou y estava com a primary li treiem el primary.
$tmp = $related;
$tmp['attributes']['primary'] = 0;
$updatePhones[] = $tmp;
}
}
}
if(count($updateEmails) > 0){
foreach($updateEmails as $email){
$url = '/contactemails/'.$email['id'];
$this->goCurl($url,'PATCH',['data'=>$email]);
}
}
if(count($updatePhones) > 0){
foreach($updatePhones as $phone){
$url = '/contactphones/'.$phone['id'];
$this->goCurl($url,'PATCH',['data'=>$phone]);
}
}
if($newEmail){
$email = [ 'data'=> [
"type"=> "contactemails",
"attributes" => [
'email'=>$contact['email'],
'primary'=>true,
],
'relationships'=>[
'owner'=>[
'data'=>[
'type' => 'contacts',
'id' =>$contactId
]
]
]
]
];
$url = '/contactemails';
$this->goCurl($url,'POST',$email);
}
if($newPhone){
$phone = [ 'data'=> [
"type"=> "contactphones",
"attributes" => [
'phone'=>$contact['phone'],
'primary'=>true,
],
'relationships'=>[
'owner'=>[
'data'=>[
'type' => 'contacts',
'id' =>$contactId
]
]
]
]
];
$url = '/contactphones';
$this->goCurl($url,'POST',$phone);
}
return true;
}
}