diff --git a/Controller/Raas/GigyaEditPost.php b/Controller/Raas/GigyaEditPost.php index dbf64ec..217a667 100644 --- a/Controller/Raas/GigyaEditPost.php +++ b/Controller/Raas/GigyaEditPost.php @@ -21,6 +21,7 @@ use Magento\Framework\Exception\AuthenticationException; use Magento\Framework\Exception\InputException; use Gigya\GigyaIM\Model\Config as GigyaConfig; +use Gigya\GigyaIM\Logger\Logger as GigyaLogger; class GigyaEditPost extends \Magento\Customer\Controller\Account\EditPost { @@ -48,6 +49,9 @@ class GigyaEditPost extends \Magento\Customer\Controller\Account\EditPost /** @var GigyaConfig */ protected $config; + /** @var GigyaLogger */ + protected $logger; + /** * @param Context $context * @param Session $customerSession @@ -58,6 +62,7 @@ class GigyaEditPost extends \Magento\Customer\Controller\Account\EditPost * @param CustomerExtractor $customerExtractor * @param GigyaConfig $config * @param GigyaMageHelper $gigyaMageHelper + * @param GigyaLogger $logger */ public function __construct( Context $context, @@ -68,7 +73,8 @@ public function __construct( Validator $formKeyValidator, CustomerExtractor $customerExtractor, GigyaConfig $config, - GigyaMageHelper $gigyaMageHelper + GigyaMageHelper $gigyaMageHelper, + GigyaLogger $logger ) { parent::__construct( @@ -83,10 +89,11 @@ public function __construct( $this->gigyaMageHelper = $gigyaMageHelper; $this->gigyaSyncHelper = $gigyaSyncHelper; $this->config = $config; + $this->logger = $logger; } /** - * Change customer password action + * Edit profile and change customer password action * * @return \Magento\Framework\Controller\Result\Redirect * @@ -123,7 +130,6 @@ public function execute() } try { - $gigyaAccount = $this->gigyaMageHelper->getGigyaAccountDataFromLoginData($this->getRequest()->getParam('gigya_user')); if ($gigyaAccount == false || $gigyaAccount->getUID() != $this->session->getGigyaAccountData()->getUID()) { @@ -139,7 +145,6 @@ public function execute() $this->gigyaMageHelper->transferAttributes($customer, $eligibleCustomer); $this->customerRepository->save($eligibleCustomer); - } catch (AuthenticationException $e) { $this->messageManager->addErrorMessage($e->getMessage()); } catch (InputException $e) { diff --git a/Controller/Raas/GigyaPost.php b/Controller/Raas/GigyaPost.php index 1d7bb94..c82e872 100644 --- a/Controller/Raas/GigyaPost.php +++ b/Controller/Raas/GigyaPost.php @@ -338,8 +338,6 @@ protected function doLogin(GigyaUser $valid_gigya_user) * Retrieve success message * * @return string - * - * @throws \Magento\Framework\Exception\NoSuchEntityException */ protected function getSuccessMessage() { diff --git a/Helper/CmsStarterKit/GigyaApiHelper.php b/Helper/CmsStarterKit/GigyaApiHelper.php index b605d83..0d4efb9 100644 --- a/Helper/CmsStarterKit/GigyaApiHelper.php +++ b/Helper/CmsStarterKit/GigyaApiHelper.php @@ -117,6 +117,7 @@ public function fetchGigyaAccount($uid, $include = null, $extraProfileFields = n $include = 'identities-active,identities-all,identities-global,loginIDs,emails,profile,data,password,isLockedOut,' . 'lastLoginLocation,regSource,irank,rba,subscriptions,userInfo,preferences'; } + if (null === $extraProfileFields) { $extraProfileFields = 'languages,address,phones,education,educationLevel,honors,publications,patents,certifications,' @@ -139,6 +140,51 @@ public function fetchGigyaAccount($uid, $include = null, $extraProfileFields = n return $gigyaUser; } + /** + * Queries Gigya with the accounts.search call + * + * @param string|array $query The literal query to send to accounts.search, or a set of params to send instead (useful for cursors) + * @param bool $useCursor + * + * @return GigyaUser[] + * + * @throws GSApiException + * @throws sdk\GSException + */ + public function searchGigyaUsers($query, $useCursor = false) { + $gigyaUsers = array(); + + if (is_array($query)) /* Query is actually a set of params. Useful for setting cursor ID instead of query */ + { + $params = $query; + } + else + { + $params = array( + 'openCursor' => $useCursor, + 'query' => $query, + ); + } + + $gigyaData = $this->sendApiCall('accounts.search', $params)->getData()->serialize(); + + foreach ($gigyaData['results'] as $userData) { + $profileArray = $userData['profile']; + $gigyaUser = GigyaUserFactory::createGigyaUserFromArray($userData); + $gigyaProfile = GigyaUserFactory::createGigyaProfileFromArray($profileArray); + $gigyaUser->setProfile($gigyaProfile); + + $gigyaUsers[] = $gigyaUser; + } + + if (!empty($gigyaData['nextCursorId'])) { + $cursorId = $gigyaData['nextCursorId']; + return array_merge($gigyaUsers, $this->searchGigyaUsers(['cursorId' => $cursorId])); + } + + return $gigyaUsers; + } + /** * Send all the Gigya data for the user specified by the UID * diff --git a/Helper/CmsStarterKit/fieldMapping/CmsUpdater.php b/Helper/CmsStarterKit/fieldMapping/CmsUpdater.php index 3bd3028..cdf578d 100644 --- a/Helper/CmsStarterKit/fieldMapping/CmsUpdater.php +++ b/Helper/CmsStarterKit/fieldMapping/CmsUpdater.php @@ -31,15 +31,16 @@ public function __construct($gigyaAccount, $mappingFilePath) { } /** - * @param mixed $cmsAccount - * @param $cmsAccountSaver + * @param mixed $cmsAccount + * @param $cmsAccountSaver + * @param boolean $skipCache Determines whether to skip the caching and cache retrieval for field mapping * * @throws \Gigya\GigyaIM\Helper\CmsStarterKit\fieldMapping\CmsUpdaterException */ - public function updateCmsAccount(&$cmsAccount, $cmsAccountSaver = null) { + public function updateCmsAccount(&$cmsAccount, $cmsAccountSaver = null, $skipCache = false) { if (!isset($this->gigyaMapping)) { - $this->retrieveFieldMappings(); + $this->retrieveFieldMappings($skipCache); } if (method_exists($this, 'callCmsHook')) @@ -62,9 +63,11 @@ abstract protected function callCmsHook(); abstract protected function saveCmsAccount(&$cmsAccount, $cmsAccountSaver); /** - * @throws \Gigya\GigyaIM\Helper\CmsStarterKit\fieldMapping\CmsUpdaterException + * @param boolean $skipCache + * + * @throws CmsUpdaterException */ - public function retrieveFieldMappings() { + public function retrieveFieldMappings($skipCache = false) { if (file_exists($this->path)) { $mappingJson = file_get_contents($this->path); @@ -73,10 +76,11 @@ public function retrieveFieldMappings() { { throw new CmsUpdaterException("Field Mapping file could not be found at " . $this->path); } - if (false === $mappingJson) + + if ($mappingJson === false) { $err = error_get_last(); - $message = "Could not retrieve field mapping configuration file. message was:" . $err['message']; + $message = "CMSUpdater: Could not retrieve field mapping configuration file. The message was: " . $err['message']; throw new CmsUpdaterException("$message"); } $conf = new Conf($mappingJson); diff --git a/Helper/CmsStarterKit/fieldMapping/Conf.php b/Helper/CmsStarterKit/fieldMapping/Conf.php index e519499..236d765 100644 --- a/Helper/CmsStarterKit/fieldMapping/Conf.php +++ b/Helper/CmsStarterKit/fieldMapping/Conf.php @@ -14,34 +14,25 @@ public function __construct($json) { $this->mappingConf = json_decode($json, true); } - /** - * @return array - */ - public function getCmsKeyed() { - if (empty($this->cmsKeyed)) - { - $this->buildKeyedArrays($this->mappingConf); - } - - return $this->cmsKeyed; - } - protected function buildKeyedArrays($array) { $cmsKeyedArray = []; $gigyaKeyedArray = []; + $allowedDirections = ['cms2g', 'g2cms', 'both']; + foreach ($array as $confItem) { $cmsKey = $confItem['cmsName']; $gigyaKey = $confItem['gigyaName']; - $direction = isset($confItem['direction']) ? $confItem['direction'] : "g2cms"; + $direction = (isset($confItem['direction']) and in_array($confItem['direction'], $allowedDirections)) ? $confItem['direction'] : 'g2cms'; $conf = new ConfItem($confItem); + switch ($direction) { - case "cms2g": + case 'cms2g': $cmsKeyedArray[$cmsKey][] = $conf; break; - case "both": + case 'both': $gigyaKeyedArray[$gigyaKey][] = $conf; $cmsKeyedArray[$cmsKey][] = $conf; break; @@ -55,6 +46,18 @@ protected function buildKeyedArrays($array) { $this->cmsKeyed = $cmsKeyedArray; } + /** + * @return array + */ + public function getCmsKeyed() { + if (empty($this->cmsKeyed)) + { + $this->buildKeyedArrays($this->mappingConf); + } + + return $this->cmsKeyed; + } + /** * @return array */ diff --git a/Helper/CmsStarterKit/fieldMapping/ConfItem.php b/Helper/CmsStarterKit/fieldMapping/ConfItem.php index 292cdf0..c61d6c3 100644 --- a/Helper/CmsStarterKit/fieldMapping/ConfItem.php +++ b/Helper/CmsStarterKit/fieldMapping/ConfItem.php @@ -39,6 +39,8 @@ class ConfItem /** * ConfItem constructor. + * + * @param array $array */ public function __construct($array) { foreach ($array as $key => $value) diff --git a/Helper/CmsStarterKit/fieldMapping/GigyaUpdater.php b/Helper/CmsStarterKit/fieldMapping/GigyaUpdater.php index c94c172..e06bcb7 100644 --- a/Helper/CmsStarterKit/fieldMapping/GigyaUpdater.php +++ b/Helper/CmsStarterKit/fieldMapping/GigyaUpdater.php @@ -162,12 +162,14 @@ protected function retrieveFieldMappings() { if (false === $mappingJson) { $err = error_get_last(); - $message = "Could not retrieve field mapping configuration file. message was:" . $err['message']; + $message = "GigyaUpdater: Could not retrieve field mapping configuration file. The message was: " . $err['message']; throw new \Exception($message); } + $conf = new Conf($mappingJson); $this->setMappingCache($conf); } + $this->cmsMappings = $conf->getCmsKeyed(); } diff --git a/Helper/GigyaCronHelper.php b/Helper/GigyaCronHelper.php new file mode 100644 index 0000000..4e13749 --- /dev/null +++ b/Helper/GigyaCronHelper.php @@ -0,0 +1,202 @@ +customerRepository = $customerRepository; + $this->searchCriteria = $criteria; + $this->filterGroup = $filterGroup; + $this->filterBuilder = $filterBuilder; + $this->storeManager = $storeManager; + $this->logger = $logger; + } + + /** + * @param $attributeCode + * @param $value + * + * @return \Magento\Customer\Api\Data\CustomerInterface[] + * + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function getCustomersByAttributeValue($attributeCode, $value) + { + $this->filterGroup->setFilters( + [ + $this->filterBuilder + ->setField($attributeCode) + ->setConditionType('eq') + ->setValue($value) + ->create() + ] + ); + + $this->searchCriteria->setFilterGroups([$this->filterGroup]); + $customersList = $this->customerRepository->getList($this->searchCriteria); + $customers = $customersList->getItems(); + + return $customers; + } + + /** + * @param $attributeCode + * @param $value + * + * @return \Magento\Customer\Api\Data\CustomerInterface + * + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function getFirstCustomerByAttributeValue($attributeCode, $value) { + $customers = $this->getCustomersByAttributeValue($attributeCode, $value); + if (count($customers) > 0) { + return $customers[0]; + } + + return null; + } + + /** + * Parses a configuration setting and return an array of email addresses. An empty array is returned if the field is blank. + * The function does not perform any validation on the correctness of the email addresses, but will return false if more than one valid delimiter is present in the emails string. + * Input example: + * string: "a@a.com, b@b.com" + * + * @param string $configSetting + * @param array $validDelimiters + * + * @return array|false + */ + public function getEmailsFromConfig($configSetting, $validDelimiters = [',', ';']) + { + /* Get config */ + $emails = str_replace(' ', '', $this->scopeConfig->getValue($configSetting)); + + /* If config was empty or non-existent */ + if (empty($emails)) { + return array(); + } + + /* If there is more than one email, delimited by one of the valid delimiters given */ + $email_array = array(); + $foundDelimiterCount = 0; + foreach ($validDelimiters as $delimiter) { + if (strpos($emails, $delimiter) !== false) { + $foundDelimiterCount++; + if ($foundDelimiterCount > 1) { + return false; + } + + $email_array = explode($delimiter, $emails); + } + } + + /* If no delimiters found, return an array containing the entire input (assumed: it is a single email address). Otherwise return found array */ + if (empty($email_array)) { + return array($emails); + } + return $email_array; + } + + /** + * @param string $job_type + * @param string $job_status + * @param string|array $email_to + * @param int|null $processed_items + * @param int $failed_users + * @param string $custom_email_body + * + * @return boolean + */ + public function sendEmail($job_type, $job_status, $email_to, $processed_items = null, $failed_users = 0, $custom_email_body = '') + { + if (empty($email_to)) { + return false; + } + + /* Generic email sender init */ + $email_sender = new \Zend_Mail(); + + /* Set email body */ + $email_body = $custom_email_body; + if (empty($custom_email_body)) { + $email_body = ''; + if ($job_status == 'succeeded' or $job_status == 'completed with errors') { + $email_body = 'Job ' . $job_status . ' on ' . gmdate("F n, Y H:i:s") . ' (UTC).'; + if ($processed_items !== null) { + $email_body .= ' ' . $processed_items . ' ' . (($processed_items > 1) ? 'items' : 'item') . ' successfully processed, ' . $failed_users . ' failed.'; + } + } elseif ($job_status == 'failed') { + $email_body = 'Job failed. No items were processed. Please consult the Gigya log ([Magento 2 dir]/var/gigya.log) for more info.'; + } + } + + try { + $email_subject = 'Gigya job of type ' . $job_type . ' ' . $job_status . ' on website ' . $this->storeManager->getStore()->getBaseUrl(); + $email_from = $email_to[0]; + + $email_sender->setSubject($email_subject); + $email_sender->setBodyText($email_body); + $email_sender->setFrom($email_from, $job_type . ' cron'); + $email_sender->addTo($email_to); + $email_sender->send(); + + $this->logger->info($job_type . ' cron: mail sent to: ' . implode(', ', $email_to) . ' with status ' . $job_status); + } catch (\Zend_Mail_Exception $e) { + $this->logger->warning($job_type . ' cron: unable to send email: ' . $e->getMessage()); + return false; + } + + return true; + } +} \ No newline at end of file diff --git a/Helper/GigyaMageHelper.php b/Helper/GigyaMageHelper.php index dcbbb5c..eb2da3d 100644 --- a/Helper/GigyaMageHelper.php +++ b/Helper/GigyaMageHelper.php @@ -9,7 +9,7 @@ use Gigya\GigyaIM\Helper\CmsStarterKit\sdk\SigUtils; use Gigya\GigyaIM\Helper\CmsStarterKit\user\GigyaUser; use Gigya\GigyaIM\Helper\CmsStarterKit\GigyaApiHelper; -use Gigya\GigyaIM\Logger\Logger; +use Gigya\GigyaIM\Logger\Logger as GigyaLogger; use Gigya\GigyaIM\Model\Settings; use Gigya\GigyaIM\Model\Config; use Gigya\GigyaIM\Model\SettingsFactory; @@ -44,7 +44,7 @@ class GigyaMageHelper extends AbstractHelper protected $configModel; protected $cookieManager; - public $_logger; + public $logger; /** @var Session */ protected $session; @@ -63,7 +63,7 @@ public function __construct( SettingsFactory $settingsFactory, // virtual class Settings $settings, Context $context, - Logger $logger, + GigyaLogger $logger, ModuleListInterface $moduleList, Config $configModel, Session $session, @@ -76,7 +76,7 @@ public function __construct( $this->configSettings = $context->getScopeConfig()->getValue('gigya_section/general', 'website'); $this->debug = $context->getScopeConfig()->getValue('gigya_advanced/debug_mode/debug_mode', 'website'); $this->dbSettings = $settings->load(1); - $this->_logger = $logger; + $this->logger = $logger; $this->configModel = $configModel; $this->scopeConfig = $context->getScopeConfig(); $this->_fileSystem = $fileSystem; @@ -463,7 +463,7 @@ private function getRandomString($len, $chars) public function gigyaLog($message, $type = 'info') { if ($this->debug) { if (in_array($type, ['info', 'warning', 'error'])) { - call_user_func_array([$this->_logger, $type], [$message]); + call_user_func_array([$this->logger, $type], [$message]); } } } @@ -500,14 +500,14 @@ public function getGigyaAccountDataFromLoginData($loginData) if (!empty($gigya_validation_o->errorCode)) { switch($gigya_validation_o->errorCode) { case GigyaAccountServiceInterface::ERR_CODE_LOGIN_ID_ALREADY_EXISTS: - $this->_logger->error("Error while retrieving Gigya account data", [ + $this->logger->error("Error while retrieving Gigya account data", [ 'gigya_data' => $loginData, 'customer_entity_id' => ($this->session->isLoggedIn()) ? $this->session->getCustomerId() : 'not logged in' ]); throw new GSException("Email already exists."); default: - $this->_logger->error("Error while retrieving Gigya account data", [ + $this->logger->error("Error while retrieving Gigya account data", [ 'gigya_data' => $loginData, 'customer_entity_id' => ($this->session->isLoggedIn()) ? $this->session->getCustomerId() : 'not logged in' ]); @@ -613,36 +613,45 @@ protected function getDynamicSessionSignatureUserSigned($glt_cookie, $timeoutInS return $ret; } - protected function signBaseString($key, $unsignedExpString) { + protected function signBaseString($key, $unsignedExpString) + { $unsignedExpString = utf8_encode($unsignedExpString); $rawHmac = hash_hmac("sha1", utf8_encode($unsignedExpString), base64_decode($key), true); $signature = base64_encode($rawHmac); return $signature; } - public function transferAttributes( - CustomerInterface $from, CustomerInterface $to) - { - $ext = $from->getExtensionAttributes(); - if(!is_null($ext)) - { - $to->setExtensionAttributes($ext); - } - foreach(get_class_methods(CustomerInterface::class) as $method) - { - $match = []; - if(preg_match('/^get(.*)/', $method, $match) - && $method != 'getId' && $method != 'getExtensionAttributes' - && $method != 'getCustomAttribute' && $method != 'getData') - { - $getter = $method; - $setter = 'set'.$match[1]; - if(method_exists($to, $setter)) - { - $to->$setter($from->$getter()); - } - } - } - return $this; - } + /** + * @param CustomerInterface $from + * @param CustomerInterface $to + * + * @return $this + */ + public function transferAttributes(CustomerInterface $from, CustomerInterface $to) + { + $ext = $from->getExtensionAttributes(); + + if (!is_null($ext)) { + $to->setExtensionAttributes($ext); + } + + foreach (get_class_methods(CustomerInterface::class) as $method) { + $match = []; + + if (preg_match('/^get(.*)/', $method, $match) + && $method != 'getId' + && $method != 'getExtensionAttributes' + && $method != 'getCustomAttribute' + && $method != 'getData' + ) { + $getter = $method; + $setter = 'set' . $match[1]; + if (method_exists($to, $setter)) { + $to->$setter($from->$getter()); + } + } + } + + return $this; + } } diff --git a/Helper/GigyaSyncHelper.php b/Helper/GigyaSyncHelper.php index f746f8e..229838f 100644 --- a/Helper/GigyaSyncHelper.php +++ b/Helper/GigyaSyncHelper.php @@ -66,18 +66,20 @@ class GigyaSyncHelper extends AbstractHelper */ protected $shareConfig; - /** - * GigyaSyncHelper constructor. - * - * @param HelperContext $helperContext - * @param MessageManager $messageManager - * @param CustomerRepositoryInterface $customerRepository - * @param SearchCriteriaBuilder $searchCriteriaBuilder - * @param FilterBuilder $filterBuilder - * @param FilterGroupBuilder $filterGroupBuilder - * @param StoreManagerInterface $storeManager - * @param Session $customerSession - */ + /** + * GigyaSyncHelper constructor. + * + * @param HelperContext $helperContext + * @param MessageManager $messageManager + * @param CustomerRepositoryInterface $customerRepository + * @param SearchCriteriaBuilder $searchCriteriaBuilder + * @param FilterBuilder $filterBuilder + * @param FilterGroupBuilder $filterGroupBuilder + * @param StoreManagerInterface $storeManager + * @param Session $customerSession + * @param AppState $state + * @param Share $shareConfig + */ public function __construct( HelperContext $helperContext, MessageManager $messageManager, @@ -116,7 +118,6 @@ public function __construct( * @throws GSException If no Magento customer account could be used nor created with this Gigya UID and provided LoginIDs emails : user can not be logged in. * Reason can be for instance : all emails attached with this Gigya account are already set on Magento accounts on this website but for other Gigya UIDs. * @throws \Magento\Framework\Exception\LocalizedException - * @throws \Magento\Framework\Exception\NoSuchEntityException */ public function getMagentoCustomerAndLoggingEmail($gigyaAccount) { @@ -128,8 +129,10 @@ public function getMagentoCustomerAndLoggingEmail($gigyaAccount) $gigyaUid = $gigyaAccount->getUID(); $gigyaLoginIdsEmails = $gigyaAccount->getLoginIDs()['emails']; $gigyaProfileEmail = $gigyaAccount->getProfile()->getEmail(); + // Will be fed with the emails that are already used by a Magento customer account, but to a different or null Gigya UID $notUsableEmails = []; + // Search criteria and filter to use for checking the existence of a Magento customer account with a given email $filterGroups = []; $searchCustomerByEmailCriteriaFilter = $this->filterBuilder->setField('email')->setConditionType('eq')->create(); @@ -184,6 +187,7 @@ public function getMagentoCustomerAndLoggingEmail($gigyaAccount) // 2. no customer account exists on Magento with this Gigya UID and one of the Gigya loginIDs emails : check if we can create it with one of the Gigya loginIDs emails // 2.1 Gigya profile email is the preferred one $updateMagentoCustomerWithGigyaProfileEmail = false; + // Gigya profile email is in the Gigya loginIDs emails ? if (in_array($gigyaProfileEmail, $gigyaLoginIdsEmails)) { // and Gigya profile email is not already attached to an existing Magento account ? @@ -296,6 +300,7 @@ public function setMagentoLoggingContext($gigyaAccount) // We initialize it to null. If it's still null at the end of the algorithm that means that the user can not logged in // because all Gigya loginIDs emails are already set to existing Magento customer accounts with a different or null Gigya UID $this->session->setGigyaAccountLoggingEmail(null); + // This will be set with the incoming $gigyaAccount parameter if the customer can be logged in on Magento. $this->session->setGigyaAccountData(null); diff --git a/Helper/GigyaUserDeletionHelper.php b/Helper/GigyaUserDeletionHelper.php deleted file mode 100644 index 90ec94e..0000000 --- a/Helper/GigyaUserDeletionHelper.php +++ /dev/null @@ -1,77 +0,0 @@ -customerRepository = $customerRepository; - $this->searchCriteria = $criteria; - $this->filterGroup = $filterGroup; - $this->filterBuilder = $filterBuilder; - } - - /** - * @param $attributeCode - * @param $value - * - * @return \Magento\Customer\Api\Data\CustomerInterface[] - * - * @throws \Magento\Framework\Exception\LocalizedException - */ - public function getCustomersByAttributeValue($attributeCode, $value) - { - $this->filterGroup->setFilters( - [ - $this->filterBuilder - ->setField($attributeCode) - ->setConditionType('eq') - ->setValue($value) - ->create() - ] - ); - - $this->searchCriteria->setFilterGroups([$this->filterGroup]); - $customersList = $this->customerRepository->getList($this->searchCriteria); - $customers = $customersList->getItems(); - - return $customers; - } -} \ No newline at end of file diff --git a/Model/Config/Source/OfflineSyncFrequency.php b/Model/Config/Source/OfflineSyncFrequency.php new file mode 100644 index 0000000..506c54f --- /dev/null +++ b/Model/Config/Source/OfflineSyncFrequency.php @@ -0,0 +1,23 @@ + '*/5 * * * *', 'label' => __('Every 5 minutes')], + ['value' => '*/30 * * * *', 'label' => __('Every 30 minutes')], + ['value' => '0 * * * *', 'label' => __('Every hour')], + ['value' => '0 0 * * *', 'label' => __('Every day')], + ['value' => '0 0 * * 0', 'label' => __('Every week')], + ['value' => '0 0 1 * *', 'label' => __('Every month')], + ]; + } +} \ No newline at end of file diff --git a/Model/Cron/GigyaOfflineSync.php b/Model/Cron/GigyaOfflineSync.php new file mode 100644 index 0000000..e81cb2a --- /dev/null +++ b/Model/Cron/GigyaOfflineSync.php @@ -0,0 +1,217 @@ +logger = $logger; + $this->scopeConfig = $context->getScopeConfig(); + $this->gigyaMageHelper = $gigyaMageHelper; + $this->gigyaSyncHelper = $gigyaSyncHelper; + $this->configWriter = $configWriter; + $this->customerFieldsUpdater = $customerFieldsUpdater; + $this->gigyaFromMagento = $gigyaFromMagento; + $this->gigyaCronHelper = $gigyaUserDeletionHelper; + $this->customerRepository = $customerRepository; + $this->gigyaToMagento = $gigyaToMagento; + } + + /** + * @param string $gigyaQuery + * @param \Exception &$gigyaException + * @param int $triesLeft + * + * @return array|false + */ + public function searchGigyaUsers($gigyaQuery, &$gigyaException, $triesLeft = 1) + { + if ($triesLeft > 0) { + $this->gigyaApiHelper = $this->gigyaMageHelper->getGigyaApiHelper(); + + try { + /** @var GSResponse $gigya_data */ + $gigyaUsers = $this->gigyaApiHelper->searchGigyaUsers($gigyaQuery, true); + + return $gigyaUsers; + } catch (\Exception $e) { + sleep(self::RETRY_WAIT); + $gigyaException = ['message' => $e->getMessage(), 'code' => $e->getCode()]; + return $this->searchGigyaUsers($gigyaQuery, $gigyaException, $triesLeft - 1); + } + } + + return false; + } + + private function handleError($errorMessage, $emailsOnFailure, $processedUsers, $usersNotFound) { + $this->gigyaCronHelper->sendEmail(self::CRON_NAME, 'failed', $emailsOnFailure, $processedUsers, $usersNotFound); + $this->logger->error('Error on cron ' . self::CRON_NAME . ': ' .$errorMessage . '.'); + } + + public function execute() + { + $enableSync = $this->scopeConfig->getValue('gigya_section_fieldmapping/offline_sync/offline_sync_is_enabled', 'website'); + $isDebugMode = boolval($this->gigyaMageHelper->getDebug()); + + $emailsOnSuccess = $this->gigyaCronHelper->getEmailsFromConfig('gigya_section_fieldmapping/offline_sync/sync_email_success'); + $emailsOnFailure = $this->gigyaCronHelper->getEmailsFromConfig('gigya_section_fieldmapping/offline_sync/sync_email_failure'); + + $this->logger->info(self::CRON_NAME . ' started. Time: ' . date("Y-m-d H:i:s")); + + if ($enableSync) { + if (!($lastCustomerUpdate = $this->scopeConfig->getValue('gigya_section_fieldmapping/offline_sync/last_customer_update'))) { + $lastCustomerUpdate = 0; + } + + $gigyaQuery = 'SELECT * FROM accounts'; + if ($lastCustomerUpdate) { + $gigyaQuery .= ' WHERE lastUpdatedTimestamp > ' . $lastCustomerUpdate; + } + $gigyaQuery .= ' ORDER BY lastUpdatedTimestamp ASC LIMIT ' . self::MAX_USERS; + + try { + $processedUsers = 0; + $usersNotFound = 0; + + /* Get user data from Gigya */ + $gigyaUsers = $this->searchGigyaUsers($gigyaQuery, $gigyaException, 3); + if ($gigyaUsers === false) { + $this->handleError($gigyaException['message'], $emailsOnFailure, $processedUsers, $usersNotFound); + throw new \Exception($gigyaException['message'], $gigyaException['code']); + } + + foreach ($gigyaUsers as $gigyaUser) { + /* Abort if user does not have UID */ + $gigyaUID = $gigyaUser->getUID(); + if (empty($gigyaUID)) { + $message = 'User with the following data does not have a UID. Unable to process. ' . json_encode($gigyaUser); + $this->handleError($message, $emailsOnFailure, $processedUsers, $usersNotFound); + throw new \Exception($message); + } + + /* Abort if user does not have a valid lastUpdatedTimestamp */ + if (empty($gigyaUser->getLastUpdatedTimestamp())) { + $message = 'User ' . $gigyaUID . ' does not have a valid last updated timestamp'; + $this->handleError($message, $emailsOnFailure, $processedUsers, $usersNotFound); + throw new \Exception($message); + } + + /* Run sync (field mapping) */ + $magentoCustomer = $this->gigyaCronHelper->getFirstCustomerByAttributeValue('gigya_uid', $gigyaUser->getUID()); /* Retrieve Magento 2 customer by Gigya UID */ + if (!empty($magentoCustomer)) { + try { + $this->gigyaToMagento->run($magentoCustomer, $gigyaUser, true); /* Enriches Magento customer with Gigya data */ + $this->customerRepository->save($magentoCustomer); + + /* Save the successful save timestamp */ + $lastCustomerUpdate = $gigyaUser->getLastUpdatedTimestamp(); + if ($lastCustomerUpdate) { + $lastCustomerUpdate -= self::UPDATE_DELAY; /* Create a window of UPDATE_DELAY in which users will be re-synced on the next run (if applicable). This is to compensate for possible replication delays in accounts.search */ + $this->configWriter->save('gigya_section_fieldmapping/offline_sync/last_customer_update', $lastCustomerUpdate); + } + + $processedUsers++; + } catch (\Exception $e) { + $message = 'Error syncing user. Gigya UID: ' . $gigyaUID; + $this->handleError($message, $emailsOnFailure, $processedUsers, $usersNotFound); + throw new FieldMappingException($message); + } + } else { + $usersNotFound++; + if ($isDebugMode) { + $this->logger->warning(self::CRON_NAME . ': User not found. Gigya UID: ' . $gigyaUID); + } + } + } + + /* Successful run completion actions */ + $this->configWriter->save('gigya_section_fieldmapping/offline_sync/last_run', round(microtime(true) * 1000)); + $this->logger->info(self::CRON_NAME . ' completed. Users processed: ' . $processedUsers . (($usersNotFound) ? '. Users not found: ' . $usersNotFound : '')); + $status = ($usersNotFound > 0) ? 'completed with errors' : 'succeeded'; + $this->gigyaCronHelper->sendEmail(self::CRON_NAME, $status, $emailsOnSuccess, $processedUsers, $usersNotFound); + } catch (\Exception $e) { + $this->handleError($e->getMessage(), $emailsOnFailure, $processedUsers, $usersNotFound); + $this->logger->error('Error on cron ' . self::CRON_NAME . ': ' . $e->getMessage() . '.'); + } + } + } +} \ No newline at end of file diff --git a/Model/Cron/RetryGigyaUpdate.php b/Model/Cron/RetryGigyaUpdate.php index 96cba09..701b9bc 100644 --- a/Model/Cron/RetryGigyaUpdate.php +++ b/Model/Cron/RetryGigyaUpdate.php @@ -4,9 +4,10 @@ use Gigya\GigyaIM\Helper\RetryGigyaSyncHelper; use Gigya\GigyaIM\Logger\Logger as GigyaLogger; +use Gigya\GigyaIM\Model\Config as GigyaConfig; use Magento\Customer\Api\CustomerRepositoryInterface; use Magento\Customer\Api\Data\CustomerInterface; -use Gigya\GigyaIM\Model\Config as GigyaConfig; +use \Magento\Framework\Event\ManagerInterface as EventManager; /** * RetryGigyaUpdate @@ -26,6 +27,9 @@ class RetryGigyaUpdate /** @var GigyaConfig */ protected $config; + /** @var EventManager */ + protected $eventManager; + /** * RetryGigyaUpdate constructor. * @@ -33,18 +37,21 @@ class RetryGigyaUpdate * @param RetryGigyaSyncHelper $retryGigyaSyncHelper * @param CustomerRepositoryInterface $customerRepository * @param GigyaConfig $config + * @param EventManager $eventManager */ public function __construct( GigyaLogger $logger, RetryGigyaSyncHelper $retryGigyaSyncHelper, CustomerRepositoryInterface $customerRepository, - GigyaConfig $config + GigyaConfig $config, + EventManager $eventManager ) { $this->logger = $logger; $this->config = $config; $this->retryGigyaSyncHelper = $retryGigyaSyncHelper; $this->customerRepository = $customerRepository; + $this->eventManager = $eventManager; } /** @@ -70,7 +77,9 @@ public function execute(\Magento\Cron\Model\Schedule $schedule) /** @var CustomerInterface $customer */ $customer = $this->customerRepository->getById($customerEntityId); try { + $this->eventManager->dispatch('gigya_fieldmapping_retry_before_save', array('customer' => $customer)); $this->customerRepository->save($customer); + $this->eventManager->dispatch('gigya_fieldmapping_retry_after_save', array('customer' => $customer)); } catch (\Exception $e) { $message = $e->getMessage(); $message = $message != null ? (strlen($message) > 255 ? substr($message, 0, 255).' ...': $message) : null; diff --git a/Model/Cron/UserDeletion.php b/Model/Cron/UserDeletion.php index f123701..a9c01b0 100644 --- a/Model/Cron/UserDeletion.php +++ b/Model/Cron/UserDeletion.php @@ -4,7 +4,7 @@ use Aws\S3\Exception\S3Exception; use Aws\S3\S3Client; -use Gigya\GigyaIM\Helper\GigyaUserDeletionHelper; +use Gigya\GigyaIM\Helper\GigyaCronHelper; use Gigya\GigyaIM\Logger\Logger as GigyaLogger; use Gigya\GigyaIM\Model\ResourceModel\ConnectionFactory; use Magento\Cron\Model\Schedule; @@ -58,7 +58,7 @@ class UserDeletion /** @var Manager */ private $eventManager; - /** @var GigyaUserDeletionHelper */ + /** @var GigyaCronHelper */ private $helper; /** @var array */ @@ -70,18 +70,18 @@ class UserDeletion /** * UserDeletion constructor. * - * @param GigyaLogger $logger - * @param Context $context - * @param CustomerRepository $customerRepository - * @param CustomerFactory $customerFactory - * @param WriterInterface $configWriter - * @param GigyaUserDeletionHelper $gigyaUserDeletionHelper - * @param Registry $registry - * @param ResourceConnection $resourceConnection - * @param ConnectionFactory $connectionFactory - * @param Attribute $attribute + * @param GigyaLogger $logger + * @param Context $context + * @param CustomerRepository $customerRepository + * @param CustomerFactory $customerFactory + * @param WriterInterface $configWriter + * @param GigyaCronHelper $gigyaUserDeletionHelper + * @param Registry $registry + * @param ResourceConnection $resourceConnection + * @param ConnectionFactory $connectionFactory + * @param Attribute $attribute * @param StoreManagerInterface $storeManager - * @param Manager $eventManager + * @param Manager $eventManager */ public function __construct( GigyaLogger $logger, @@ -89,7 +89,7 @@ public function __construct( CustomerRepository $customerRepository, CustomerFactory $customerFactory, WriterInterface $configWriter, - GigyaUserDeletionHelper $gigyaUserDeletionHelper, + GigyaCronHelper $gigyaUserDeletionHelper, Registry $registry, ResourceConnection $resourceConnection, ConnectionFactory $connectionFactory, @@ -305,8 +305,6 @@ protected function deleteUsers($uid_type, $uid_array, &$failed_users) } /** - * @param Schedule $schedule - * * @throws \Magento\Framework\Exception\LocalizedException */ public function execute() diff --git a/Model/FieldMapping/AbstractFieldMapping.php b/Model/FieldMapping/AbstractFieldMapping.php index 461d25f..27f36c5 100644 --- a/Model/FieldMapping/AbstractFieldMapping.php +++ b/Model/FieldMapping/AbstractFieldMapping.php @@ -21,6 +21,7 @@ class AbstractFieldMapping * @var ModuleDirReader */ protected $moduleDirReader; + /** * MagentoToGigyaFieldMapping constructor. * @@ -39,18 +40,17 @@ public function __construct( $this->logger = $logger; } - protected function getFieldMappingFilePath() - { - $config_file_path = $this->scopeConfig->getValue("gigya_section_fieldmapping/general_fieldmapping/mapping_file_path"); - if($config_file_path) - { - return $config_file_path; - } - else - { - $this->logger->alert(__('No Field Mapping file provided. Reverting to the default one.')); - } - return $this->moduleDirReader->getModuleDir(Dir::MODULE_ETC_DIR, 'Gigya_GigyaIM') . - DIRECTORY_SEPARATOR . 'json' . DIRECTORY_SEPARATOR . 'default_field_mapping.json'; - } + protected function getFieldMappingFilePath() + { + $config_file_path = $this->scopeConfig->getValue("gigya_section_fieldmapping/general_fieldmapping/mapping_file_path"); + + if ($config_file_path) { + return $config_file_path; + } else { + $this->logger->alert(__('No Field Mapping file provided. Reverting to the default one.')); + + return $this->moduleDirReader->getModuleDir(Dir::MODULE_ETC_DIR, 'Gigya_GigyaIM') . + DIRECTORY_SEPARATOR . 'json' . DIRECTORY_SEPARATOR . 'default_field_mapping.json'; + } + } } \ No newline at end of file diff --git a/Model/FieldMapping/GigyaToMagento.php b/Model/FieldMapping/GigyaToMagento.php index ce37085..c09df8a 100644 --- a/Model/FieldMapping/GigyaToMagento.php +++ b/Model/FieldMapping/GigyaToMagento.php @@ -3,6 +3,7 @@ namespace Gigya\GigyaIM\Model\FieldMapping; use Gigya\GigyaIM\Exception\GigyaFieldMappingException; +use Magento\Customer\Api\Data\CustomerInterface; use \Magento\Framework\App\Config\ScopeConfigInterface; use Gigya\GigyaIM\Model\MagentoCustomerFieldsUpdater; use Gigya\GigyaIM\Logger\Logger as GigyaLogger; @@ -49,11 +50,13 @@ public function __construct( * * The mapping rules are retrieved from the json field mapping file pointed to by backend configuration key 'gigya_section_fieldmapping/general_fieldmapping/mapping_file_path' * - * @param Customer $customer - * @param $gigyaUser + * @param Customer|CustomerInterface $customer + * @param array $gigyaUser + * @param boolean $skipCache + * * @throws GigyaFieldMappingException */ - public function run($customer, $gigyaUser) + public function run($customer, $gigyaUser, $skipCache = false) { $config_file_path = $this->getFieldMappingFilePath(); if ($config_file_path != null) { @@ -61,7 +64,7 @@ public function run($customer, $gigyaUser) $this->customerFieldsUpdater->setGigyaUser($gigyaUser); $this->customerFieldsUpdater->setMagentoUser($customer); try { - $this->customerFieldsUpdater->updateCmsAccount($customer); + $this->customerFieldsUpdater->updateCmsAccount($customer, null, $skipCache); } catch (\Exception $e) { $message = "error " . $e->getCode() . ". message: " . $e->getMessage() . ". File: " .$e->getFile(); $this->logger->error( @@ -74,7 +77,7 @@ public function run($customer, $gigyaUser) throw new GigyaFieldMappingException($message); } } else { - $message = "mapping fields file path is not defined. Define file path at: Stores:Config:Gigya:Field Mapping"; + $message = "Mapping fields file path is not defined. Define file path at: Stores > Config > Gigya > Field Mapping"; $this->logger->warn( $message, [ diff --git a/Model/MagentoCustomerFieldsUpdater.php b/Model/MagentoCustomerFieldsUpdater.php index bfdc55e..6b010e0 100644 --- a/Model/MagentoCustomerFieldsUpdater.php +++ b/Model/MagentoCustomerFieldsUpdater.php @@ -80,15 +80,17 @@ public function callCmsHook() { * @param \Magento\Customer\Model\Data\Customer $account */ public function setAccountValues(&$account) { - foreach ($this->getGigyaMapping() as $gigyaName => $confs) { + $gigyaMapping = $this->getGigyaMapping(); + foreach ($gigyaMapping as $gigyaName => $confs) { /** @var \Gigya\GigyaIM\Helper\CmsStarterKit\fieldMapping\ConfItem $conf */ $value = parent::getValueFromGigyaAccount($gigyaName); // e.g: loginProvider = facebook /* If no value found, log and skip field */ if (is_null($value)) { - $this->logger->info( __FUNCTION__ . ": Value for {$gigyaName} not found in gigya user object. Check your field mapping configuration"); + $this->logger->info( __FUNCTION__ . ": Value for {$gigyaName} not found in Gigya user object for Magento user {$account->getId()}. Check your field mapping configuration"); continue; } + foreach ($confs as $conf) { $mageKey = $conf->getCmsName(); // e.g: mageKey = prefix $value = $this->castValue($value, $conf); @@ -144,21 +146,31 @@ public function saveCmsAccount(&$cmsAccount, $cmsAccountSaver = null) } /** + * @param boolean $skipCache + * * @throws \Exception */ - public function retrieveFieldMappings() + public function retrieveFieldMappings($skipCache = false) { - $conf = $this->getMappingFromCache(); - if (false === $conf) { + $conf = false; + if (!$skipCache) { + $conf = $this->getMappingFromCache(); + } + + if ($conf === false) { $mappingJson = file_get_contents($this->getPath()); - if (false === $mappingJson) { + if ($mappingJson === false) { $err = error_get_last(); - $message = "Could not retrieve field mapping configuration file. message was:" . $err['message']; + $message = "MagentoCustomerFieldsUpdater: Could not retrieve field mapping configuration file. The message was: " . $err['message']; throw new \Exception("$message"); } $conf = new fieldMapping\Conf($mappingJson); - $this->setMappingCache($conf); + + if (!$skipCache) { + $this->setMappingCache($conf); + } } + $this->setGigyaMapping($conf->getGigyaKeyed()); } diff --git a/Model/RetryMagentoCustomerFieldsUpdater.php b/Model/RetryMagentoCustomerFieldsUpdater.php index 734afc4..d288b54 100644 --- a/Model/RetryMagentoCustomerFieldsUpdater.php +++ b/Model/RetryMagentoCustomerFieldsUpdater.php @@ -67,8 +67,12 @@ protected function setMappingCache($mappingConf) * * The $gigyaMapping param is ignored : we call parent::setGigyaMapping with our own retrieved from $this->retryConfMapping->getGigyaKeyed() */ - public function setGigyaMapping($gigyaMapping) - { - parent::setGigyaMapping($this->retryConfMapping->getGigyaKeyed()); - } + public function setGigyaMapping($gigyaMapping) + { + if (!empty($this->retryConfMapping)) { + $gigyaMapping = $this->retryConfMapping->getGigyaKeyed(); + } + + parent::setGigyaMapping($gigyaMapping); + } } \ No newline at end of file diff --git a/Observer/AbstractMagentoCustomerEnricher.php b/Observer/AbstractMagentoCustomerEnricher.php index e97bd45..b10ea03 100644 --- a/Observer/AbstractMagentoCustomerEnricher.php +++ b/Observer/AbstractMagentoCustomerEnricher.php @@ -93,9 +93,7 @@ protected function shallEnrichMagentoCustomerWithGigyaAccount($magentoCustomer) && !$magentoCustomer->isObjectNew() && !$this->retrieveRegisteredCustomer($magentoCustomer) && !(empty($magentoCustomer->getGigyaUid())) - && !$this->gigyaSyncHelper->isCustomerIdExcludedFromSync( - $magentoCustomer->getId(), GigyaSyncHelper::DIR_G2CMS - ); + && !$this->gigyaSyncHelper->isCustomerIdExcludedFromSync($magentoCustomer->getId(), GigyaSyncHelper::DIR_G2CMS); return $result; } @@ -139,7 +137,6 @@ protected function processEventMapGigyaToMagentoException($e, $magentoCustomer, * * @throws GSException * @throws \Magento\Framework\Exception\LocalizedException - * @throws \Magento\Framework\Exception\NoSuchEntityException */ protected function getGigyaDataForEnrichment($magentoCustomer) { @@ -223,7 +220,7 @@ public function saveMagentoCustomer($magentoCustomer) { */ public function execute(Observer $observer) { - /** @var \Magento\Customer\Model\Backend\Customer $magentoCustomer */ + /** @var \Magento\Customer\Model\Backend\Customer $magentoCustomer */ $magentoCustomer = $observer->getData('customer'); if (empty($magentoCustomer->getGigyaAccountEnriched())) { $magentoCustomer->setGigyaAccountEnriched(false); @@ -231,23 +228,19 @@ public function execute(Observer $observer) $gigyaData = null; if ($this->shallEnrichMagentoCustomerWithGigyaAccount($magentoCustomer)) { - try { $gigyaData = $this->getGigyaDataForEnrichment($magentoCustomer); - $magentoCustomer = $this->enrichMagentoCustomerWithGigyaData($magentoCustomer, - $gigyaData['gigya_user'], $gigyaData['gigya_logging_email']); + $magentoCustomer = $this->enrichMagentoCustomerWithGigyaData($magentoCustomer, $gigyaData['gigya_user'], $gigyaData['gigya_logging_email']); $magentoCustomer->setGigyaAccountEnriched(true); $customerEntityId = $magentoCustomer->getId(); $excludeSyncCms2G = true; - if (!$this->gigyaSyncHelper->isCustomerIdExcludedFromSync($customerEntityId, - GigyaSyncHelper::DIR_CMS2G) - ) { + if (!$this->gigyaSyncHelper->isCustomerIdExcludedFromSync($customerEntityId, GigyaSyncHelper::DIR_CMS2G)) { // We prevent synchronizing the M2 customer data to the Gigya account : that should be done only on explicit customer save, // here the very first action is to load the M2 customer - $this->gigyaSyncHelper->excludeCustomerIdFromSync($magentoCustomer->getId(), - GigyaSyncHelper::DIR_CMS2G); + $this->gigyaSyncHelper->excludeCustomerIdFromSync($magentoCustomer->getId(), GigyaSyncHelper::DIR_CMS2G); $excludeSyncCms2G = false; } + try { $this->saveMagentoCustomer($magentoCustomer); } finally { diff --git a/Observer/BackendMagentoCustomerEnricher.php b/Observer/BackendMagentoCustomerEnricher.php index e8b82b5..feed83b 100644 --- a/Observer/BackendMagentoCustomerEnricher.php +++ b/Observer/BackendMagentoCustomerEnricher.php @@ -15,7 +15,7 @@ * * @inheritdoc * - * Backend enrichement of Magento customer with Gigya data happens on customer page detail loading. + * Backend enrichment of Magento customer with Gigya data happens on customer page detail loading. * * This subclass is here just to mute any GigyaMagentoCustomerSaveException that could be thrown during the enrichment, at the moment of the enriched customer is saved. * The exception is muted because the goal is before all to display the latest Gigya data, even if it's not persisted in Magento database. @@ -63,15 +63,15 @@ public function __construct( /** * @inheritdoc * - * If GigyaMagentoCustomerSaveException is caught it's muted. Any other exception is not muted. - */ - public function saveMagentoCustomer($magentoCustomer) { - - try { - parent::saveMagentoCustomer($magentoCustomer); - } catch(\Exception $e) { - $magentoCustomer->setGigyaAccountEnriched(false); - $this->customerRegistry->push($magentoCustomer); - } - } + * If GigyaMagentoCustomerSaveException is caught it's muted. Any other exception is not muted. + */ + public function saveMagentoCustomer($magentoCustomer) + { + try { + parent::saveMagentoCustomer($magentoCustomer); + } catch (\Exception $e) { + $magentoCustomer->setGigyaAccountEnriched(false); + $this->customerRegistry->push($magentoCustomer); + } + } } \ No newline at end of file diff --git a/composer.json b/composer.json index 5ff2f4b..3b4b3ca 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "gigya/magento2-im", "description": "Gigya Identity Management for Magento 2", "type": "magento2-module", - "version": "5.3.5", + "version": "5.4.0", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml index e5957af..1877080 100644 --- a/etc/adminhtml/system.xml +++ b/etc/adminhtml/system.xml @@ -63,6 +63,26 @@ Gigya\GigyaIM\Model\Config\ValidateFieldMappingConf + + + + + Magento\Config\Model\Config\Source\Yesno + + + + Gigya\GigyaIM\Model\Config\Source\OfflineSyncFrequency + + + + + validate-emails + + + + validate-emails + +
@@ -136,10 +156,11 @@ - required-entry validate-no-empty validate-email + required-entry validate-no-empty validate-emails + validate-emails diff --git a/etc/config.xml b/etc/config.xml index 0c50faf..f895049 100644 --- a/etc/config.xml +++ b/etc/config.xml @@ -6,13 +6,13 @@ 0 - - - 0 - 1800 - - - + + + 0 + 0 * * * * + + + Default-RegistrationLogin @@ -20,6 +20,12 @@ Default-ProfileUpdate + + + 0 + 1800 + + * 0 * * * diff --git a/etc/crontab.xml b/etc/crontab.xml index b8e0760..7d39958 100644 --- a/etc/crontab.xml +++ b/etc/crontab.xml @@ -1,12 +1,15 @@ - - - - */5 * * * * - - - gigya_delete/deletion_general/deletion_job_frequency - - + + + + */5 * * * * + + + gigya_delete/deletion_general/deletion_job_frequency + + + gigya_section_fieldmapping/offline_sync/offline_sync_frequency + + diff --git a/etc/crontab/events.xml b/etc/crontab/events.xml index cdda3b0..6ce5df9 100644 --- a/etc/crontab/events.xml +++ b/etc/crontab/events.xml @@ -5,11 +5,11 @@ */ --> - + - + diff --git a/etc/module.xml b/etc/module.xml index fe81270..7cbbfcf 100644 --- a/etc/module.xml +++ b/etc/module.xml @@ -1,6 +1,6 @@ - +