}
// get first name & last name
$firstName = html_entity_decode($wpUser->first_name); // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
$lastName = html_entity_decode($wpUser->last_name); // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
if (empty($wpUser->first_name) && empty($wpUser->last_name)) { // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
$firstName = html_entity_decode($wpUser->display_name); // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
}
$signupConfirmationEnabled = SettingsController::getInstance()->get('signup_confirmation.enabled');
$status = $signupConfirmationEnabled ? SubscriberEntity::STATUS_UNCONFIRMED : SubscriberEntity::STATUS_SUBSCRIBED;
// we want to mark a new subscriber as unsubscribe when the checkbox from registration is unchecked
if (isset($_POST['mailpoet']['subscribe_on_register_active']) && (bool)$_POST['mailpoet']['subscribe_on_register_active'] === true) {
$status = SubscriberEntity::STATUS_UNSUBSCRIBED;
}
// subscriber data
$data = [
'wp_user_id' => $wpUser->ID,
'email' => $wpUser->user_email, // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
'first_name' => $firstName,
'last_name' => $lastName,
'status' => $status,
'source' => Source::WORDPRESS_USER,
];
if (!is_null($subscriber)) {
$data['id'] = $subscriber->getId();
unset($data['status']); // don't override status for existing users
unset($data['source']); // don't override status for existing users
}
$addingNewUserToDisabledWPSegment = $wpSegment->getDeletedAt() !== null && $currentFilter === 'user_register';
$otherActiveSegments = [];
if ($subscriber) {
$otherActiveSegments = array_filter($subscriber->getSegments()->toArray() ?? [], function (SegmentEntity $segment) {
return $segment->getType() !== SegmentEntity::TYPE_WP_USERS && $segment->getDeletedAt() === null;
});
}
$isWooCustomer = $this->wooHelper->isWooCommerceActive() && in_array('customer', $wpUser->roles, true);
// When WP Segment is disabled force trashed state and unconfirmed status for new WPUsers without active segment
// or who are not WooCommerce customers at the same time since customers are added to the WooCommerce list
if ($addingNewUserToDisabledWPSegment && !$otherActiveSegments && !$isWooCustomer) {
$data['deleted_at'] = Carbon::createFromTimestamp($this->wp->currentTime('timestamp'));
$data['status'] = SubscriberEntity::STATUS_UNCONFIRMED;
}
try {
$subscriber = $this->createOrUpdateSubscriber($data, $subscriber);
} catch (\Exception $e) {
return; // fails silently as this was the behavior of this methods before the Doctrine refactor.
}
// add subscriber to the WP Users segment
$this->subscriberSegmentRepository->subscribeToSegments(
$subscriber,
[$wpSegment]
);
if (!$signupConfirmationEnabled && $subscriber->getStatus() === SubscriberEntity::STATUS_SUBSCRIBED && $currentFilter === 'user_register') {
$subscriberSegment = $this->subscriberSegmentRepository->findOneBy([
'subscriber' => $subscriber->getId(),
'segment' => $wpSegment->getId(),
]);
if (!is_null($subscriberSegment)) {
$this->wp->doAction('mailpoet_segment_subscribed', $subscriberSegment);
}
}
$subscribeOnRegisterEnabled = SettingsController::getInstance()->get('subscribe.on_register.enabled');
$sendConfirmationEmail =
$signupConfirmationEnabled
&& $subscribeOnRegisterEnabled
&& $currentFilter !== 'profile_update'
&& !$addingNewUserToDisabledWPSegment;
if ($sendConfirmationEmail && ($subscriber->getStatus() === SubscriberEntity::STATUS_UNCONFIRMED)) {
/** @var ConfirmationEmailMailer $confirmationEmailMailer */
$confirmationEmailMailer = ContainerWrapper::getInstance()->get(ConfirmationEmailMailer::class);
try {
$confirmationEmailMailer->sendConfirmationEmailOnce($subscriber);
} catch (\Exception $e) {
// ignore errors
}
}
// welcome email
$scheduleWelcomeNewsletter = false;
if (in_array($currentFilter, ['profile_update', 'user_register', 'add_user_role', 'set_user_role'])) {
$scheduleWelcomeNewsletter = true;
}
if ($scheduleWelcomeNewsletter === true) {
$this->welcomeScheduler->scheduleWPUserWelcomeNotification(
$subscriber->getId(),
(array)$wpUser,
(array)$oldWpUserData
);
}
}
private function createOrUpdateSubscriber(array $data, ?SubscriberEntity $subscriber = null): SubscriberEntity {
if (is_null($subscriber)) {
$subscriber = new SubscriberEntity();
}
$subscriber->setWpUserId($data['wp_user_id']);
$subscriber->setEmail($data['email']);
$subscriber->setFirstName($data['first_name']);
$subscriber->setLastName($data['last_name']);
if (isset($data['status'])) {
$subscriber->setStatus($data['status']);
}
if (isset($data['source'])) {
$subscriber->setSource($data['source']);
}
if (isset($data['deleted_at'])) {
$subscriber->setDeletedAt($data['deleted_at']);
}
$this->subscribersRepository->persist($subscriber);
$this->subscribersRepository->flush();
return $subscriber;
}
public function synchronizeUsers(): bool {
// Save timestamp about changes and update before insert
$this->subscriberChangesNotifier->subscribersBatchCreate();
$this->subscriberChangesNotifier->subscribersBatchUpdate();
$updatedUsersEmails = $this->updateSubscribersEmails();
$insertedUsersEmails = $this->insertSubscribers();
$this->removeUpdatedSubscribersWithInvalidEmail(array_merge($updatedUsersEmails, $insertedUsersEmails));
// There is high chance that an update will be made
$this->subscriberChangesNotifier->subscribersBatchUpdate();
unset($updatedUsersEmails);
unset($insertedUsersEmails);
$this->updateFirstNames();
$this->updateLastNames();
$this->updateFirstNameIfMissing();
$this->insertUsersToSegment();
$this->removeOrphanedSubscribers();
$this->subscribersRepository->invalidateTotalSubscribersCache();
$this->subscribersRepository->refreshAll();
return true;
}
private function removeUpdatedSubscribersWithInvalidEmail(array $updatedEmails): void {
$invalidWpUserIds = array_map(function($item) {
return $item['id'];
},
array_filter($updatedEmails, function($updatedEmail) {
return !$this->validator->validateEmail($updatedEmail['email']);
}));
if (!$invalidWpUserIds) {
return;
}
$this->subscribersRepository->removeByWpUserIds($invalidWpUserIds);
}
private function updateSubscribersEmails(): array {
global $wpdb;
$stmt = $this->databaseConnection->executeQuery('SELECT NOW();');
$startTime = $stmt->fetchOne();
if (!is_string($startTime)) {
throw new \RuntimeException("Failed to fetch the current time.");
}
$updateSql =
"UPDATE IGNORE {$this->subscribersTable} s
INNER JOIN {$wpdb->users} as wu ON s.wp_user_id = wu.id
SET s.email = wu.user_email";
$this->databaseConnection->executeStatement($updateSql);
$selectSql =
"SELECT wp_user_id as id, email FROM {$this->subscribersTable}
WHERE updated_at >= '{$startTime}'";
$updatedEmails = $this->databaseConnection->fetchAllAssociative($selectSql);
return $updatedEmails;
}
private function insertSubscribers(): array {
global $wpdb;
$wpSegment = $this->segmentsRepository->getWPUsersSegment();
if ($wpSegment->getDeletedAt() !== null) {
$subscriberStatus = SubscriberEntity::STATUS_UNCONFIRMED;
$deletedAt = 'CURRENT_TIMESTAMP()';
} else {
$signupConfirmationEnabled = SettingsController::getInstance()->get('signup_confirmation.enabled');
$subscriberStatus = $signupConfirmationEnabled ? SubscriberEntity::STATUS_UNCONFIRMED : SubscriberEntity::STATUS_SUBSCRIBED;
$deletedAt = 'null';
}
// Fetch users that are not in the subscribers table
$selectSql =
"SELECT u.id, u.user_email as email
FROM {$wpdb->users} u
LEFT JOIN {$this->subscribersTable} AS s ON s.wp_user_id = u.id
WHERE s.wp_user_id IS NULL AND u.user_email != ''";
$insertedUserIds = $this->databaseConnection->fetchAllAssociative($selectSql);
// Insert new users into the subscribers table
$insertSql =
"INSERT IGNORE INTO {$this->subscribersTable} (wp_user_id, email, status, created_at, `source`, deleted_at)
SELECT wu.id, wu.user_email, :subscriberStatus, CURRENT_TIMESTAMP(), :source, {$deletedAt}
FROM {$wpdb->users} wu
LEFT JOIN {$this->subscribersTable} s ON wu.id = s.wp_user_id
WHERE s.wp_user_id IS NULL AND wu.user_email != ''
ON DUPLICATE KEY UPDATE wp_user_id = wu.id";
$stmt = $this->databaseConnection->prepare($insertSql);
$stmt->bindValue('subscriberStatus', $subscriberStatus);
$stmt->bindValue('source', Source::WORDPRESS_USER);
$stmt->executeStatement();
return $insertedUserIds;
}
private function updateFirstNames(): void {
global $wpdb;
$sql =
"UPDATE {$this->subscribersTable} s
JOIN {$wpdb->usermeta} as wpum ON s.wp_user_id = wpum.user_id AND wpum.meta_key = 'first_name'
SET s.first_name = SUBSTRING(wpum.meta_value, 1, 255)
WHERE s.first_name = ''
AND s.wp_user_id IS NOT NULL
AND wpum.meta_value IS NOT NULL";
$this->databaseConnection->executeStatement($sql);
}
private function updateLastNames(): void {
global $wpdb;
$sql =
"UPDATE {$this->subscribersTable} s
JOIN {$wpdb->usermeta} as wpum ON s.wp_user_id = wpum.user_id AND wpum.meta_key = 'last_name'
SET s.last_name = SUBSTRING(wpum.meta_value, 1, 255)
WHERE s.last_name = ''
AND s.wp_user_id IS NOT NULL
AND wpum.meta_value IS NOT NULL";
$this->databaseConnection->executeStatement($sql);
}
private function updateFirstNameIfMissing(): void {
global $wpdb;
$sql =
"UPDATE {$this->subscribersTable} s
JOIN {$wpdb->users} wu ON s.wp_user_id = wu.id
SET s.first_name = wu.display_name
WHERE s.first_name = ''
AND s.wp_user_id IS NOT NULL";
$this->databaseConnection->executeStatement($sql);
}
private function insertUsersToSegment(): void {
$wpSegment = $this->segmentsRepository->getWPUsersSegment();
$subscribersSegmentTable = $this->entityManager->getClassMetadata(SubscriberSegmentEntity::class)->getTableName();
$sql =
"INSERT IGNORE INTO {$subscribersSegmentTable} (subscriber_id, segment_id, created_at)
SELECT s.id, '{$wpSegment->getId()}', CURRENT_TIMESTAMP() FROM {$this->subscribersTable} s
WHERE s.wp_user_id > 0";
$this->databaseConnection->executeStatement($sql);
}
private function removeOrphanedSubscribers(): void {
$this->subscribersRepository->removeOrphanedSubscribersFromWpSegment();
}
}
Fatal error: Uncaught Error: Class "MailPoet\Segments\WP" not found in /htdocs/wp-content/plugins/mailpoet/generated/FreeCachedContainer.php:4808
Stack trace:
#0 /htdocs/wp-content/plugins/mailpoet/generated/FreeCachedContainer.php(2673): MailPoetGenerated\FreeCachedContainer->getWPService()
#1 /htdocs/wp-content/plugins/mailpoet/generated/FreeCachedContainer.php(2578): MailPoetGenerated\FreeCachedContainer->getPopulatorService()
#2 /htdocs/wp-content/plugins/mailpoet/generated/FreeCachedContainer.php(2640): MailPoetGenerated\FreeCachedContainer->getActivatorService()
#3 /htdocs/wp-content/plugins/mailpoet/vendor-prefixed/symfony/dependency-injection/Container.php(122): MailPoetGenerated\FreeCachedContainer->getInitializerService()
#4 /htdocs/wp-content/plugins/mailpoet/vendor-prefixed/symfony/dependency-injection/Container.php(110): MailPoetVendor\Symfony\Component\DependencyInjection\Container->make('MailPoet\\Config...', 1)
#5 /htdocs/wp-content/plugins/mailpoet/lib/DI/ContainerWrapper.php(39): MailPoetVendor\Symfony\Component\DependencyInjection\Container->get('MailPoet\\Config...')
#6 /htdocs/wp-content/plugins/mailpoet/mailpoet_initializer.php(89): MailPoet\DI\ContainerWrapper->get('MailPoet\\Config...')
#7 /htdocs/wp-content/plugins/mailpoet/mailpoet.php(194): require_once('/htdocs/wp-cont...')
#8 /htdocs/wp-settings.php(526): include_once('/htdocs/wp-cont...')
#9 /htdocs/wp-config.php(85): require_once('/htdocs/wp-sett...')
#10 /htdocs/wp-load.php(50): require_once('/htdocs/wp-conf...')
#11 /htdocs/wp-blog-header.php(13): require_once('/htdocs/wp-load...')
#12 /htdocs/index.php(17): require('/htdocs/wp-blog...')
#13 {main}
thrown in /htdocs/wp-content/plugins/mailpoet/generated/FreeCachedContainer.php on line 4808