Нет описания

Subscriber.php 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708
  1. <?php
  2. namespace MailPoet\Models;
  3. if (!defined('ABSPATH')) exit;
  4. use MailPoet\DI\ContainerWrapper;
  5. use MailPoet\Settings\SettingsController;
  6. use MailPoet\Util\Helpers;
  7. use MailPoet\Util\Security;
  8. use MailPoet\WP\Functions as WPFunctions;
  9. /**
  10. * @property int $id
  11. * @property string $email
  12. * @property string $firstName
  13. * @property string $lastName
  14. * @property string $status
  15. * @property string|null $subscribedIp
  16. * @property string|null $confirmedIp
  17. * @property string|null $confirmedAt
  18. * @property string|null $lastSubscribedAt
  19. * @property string|null $deletedAt
  20. * @property string|null $source
  21. * @property string|null $linkToken
  22. * @property int $countConfirmations
  23. * @property int $wpUserId
  24. * @property array $segments
  25. * @property array $subscriptions
  26. * @property string|null $unconfirmedData
  27. * @property int $isWoocommerceUser
  28. */
  29. class Subscriber extends Model {
  30. public static $_table = MP_SUBSCRIBERS_TABLE; // phpcs:ignore PSR2.Classes.PropertyDeclaration
  31. const STATUS_SUBSCRIBED = 'subscribed';
  32. const STATUS_UNSUBSCRIBED = 'unsubscribed';
  33. const STATUS_UNCONFIRMED = 'unconfirmed';
  34. const STATUS_BOUNCED = 'bounced';
  35. const STATUS_INACTIVE = 'inactive';
  36. const OBSOLETE_LINK_TOKEN_LENGTH = 6;
  37. const LINK_TOKEN_LENGTH = 32;
  38. /** @var string|bool */
  39. public $token;
  40. public function __construct() {
  41. parent::__construct();
  42. $this->addValidations('email', [
  43. 'required' => WPFunctions::get()->__('Please enter your email address', 'mailpoet'),
  44. 'validEmail' => WPFunctions::get()->__('Your email address is invalid!', 'mailpoet'),
  45. ]);
  46. }
  47. public static function findOne($id = false) {
  48. if (is_int($id) || (string)(int)$id === $id) {
  49. return parent::findOne($id);
  50. } else if (strlen(trim($id)) > 0) {
  51. return parent::where('email', $id)->findOne();
  52. }
  53. return false;
  54. }
  55. public function segments() {
  56. return $this->has_many_through(
  57. __NAMESPACE__ . '\Segment',
  58. __NAMESPACE__ . '\SubscriberSegment',
  59. 'subscriber_id',
  60. 'segment_id'
  61. )
  62. ->where(MP_SUBSCRIBER_SEGMENT_TABLE . '.status', self::STATUS_SUBSCRIBED);
  63. }
  64. public function save() {
  65. // convert email to lowercase format
  66. $this->email = strtolower($this->email);
  67. return parent::save();
  68. }
  69. public function delete() {
  70. // WP Users cannot be deleted
  71. if (!$this->isWPUser() && !$this->isWooCommerceUser()) {
  72. // delete all relations to segments
  73. SubscriberSegment::deleteSubscriptions($this);
  74. // delete all relations to custom fields
  75. SubscriberCustomField::deleteSubscriberRelations($this);
  76. return parent::delete();
  77. }
  78. return null;
  79. }
  80. public function trash() {
  81. // WP Users cannot be trashed
  82. if ($this->isWPUser() || $this->isWooCommerceUser()) {
  83. return false;
  84. } else {
  85. return parent::trash();
  86. }
  87. }
  88. public function isWPUser() {
  89. return (bool)$this->wpUserId;
  90. }
  91. public function isWooCommerceUser() {
  92. return (bool)$this->isWoocommerceUser;
  93. }
  94. /**
  95. * @deprecated Use the version in \MailPoet\Subscribers\SubscribersRepository::getCurrentWPUser
  96. */
  97. public static function getCurrentWPUser() {
  98. trigger_error('Calling Subscriber::getCurrentWPUser() is deprecated and will be removed. Use MailPoet\Subscribers\SubscribersRepository::getCurrentWPUser(). ', E_USER_DEPRECATED);
  99. $wpUser = WPFunctions::get()->wpGetCurrentUser();
  100. if (empty($wpUser->ID)) {
  101. return false; // Don't look up a subscriber for guests
  102. }
  103. return self::where('wp_user_id', $wpUser->ID)->findOne();
  104. }
  105. public static function filterOutReservedColumns(array $subscriberData) {
  106. $reservedColumns = [
  107. 'id',
  108. 'wp_user_id',
  109. 'is_woocommerce_user',
  110. 'status',
  111. 'subscribed_ip',
  112. 'confirmed_ip',
  113. 'confirmed_at',
  114. 'created_at',
  115. 'updated_at',
  116. 'deleted_at',
  117. 'unconfirmed_data',
  118. ];
  119. $subscriberData = array_diff_key(
  120. $subscriberData,
  121. array_flip($reservedColumns)
  122. );
  123. return $subscriberData;
  124. }
  125. public static function search($orm, $search = '') {
  126. if (strlen(trim($search)) === 0) {
  127. return $orm;
  128. }
  129. return $orm->where_raw(
  130. '(`email` LIKE ? OR `first_name` LIKE ? OR `last_name` LIKE ?)',
  131. ['%' . $search . '%', '%' . $search . '%', '%' . $search . '%']
  132. );
  133. }
  134. public static function filters($data = []) {
  135. $group = (!empty($data['group'])) ? $data['group'] : 'all';
  136. $segments = Segment::orderByAsc('name')
  137. ->whereNull('deleted_at')
  138. ->whereIn('type', Segment::getSegmentTypes())
  139. ->findMany();
  140. $segmentList = [];
  141. $segmentList[] = [
  142. 'label' => WPFunctions::get()->__('All Lists', 'mailpoet'),
  143. 'value' => '',
  144. ];
  145. $subscribersWithoutSegment = self::filter('withoutSegments')
  146. ->whereNull('deleted_at')
  147. ->count();
  148. $subscribersWithoutSegmentLabel = sprintf(
  149. __('Subscribers without a list (%s)', 'mailpoet'),
  150. number_format($subscribersWithoutSegment)
  151. );
  152. $segmentList[] = [
  153. 'label' => $subscribersWithoutSegmentLabel,
  154. 'value' => 'none',
  155. ];
  156. foreach ($segments as $segment) {
  157. $subscribersCount = 0;
  158. $subscribers = $segment->subscribers()
  159. ->filter('groupBy', $group);
  160. if ($subscribers) {
  161. $subscribersCount = $subscribers->count();
  162. }
  163. $label = sprintf(
  164. '%s (%s)',
  165. $segment->name,
  166. number_format($subscribersCount)
  167. );
  168. $segmentList[] = [
  169. 'label' => $label,
  170. 'value' => $segment->id(),
  171. ];
  172. }
  173. $filters = [
  174. 'segment' => $segmentList,
  175. ];
  176. return $filters;
  177. }
  178. public static function filterBy($orm, $filters = null) {
  179. if (empty($filters)) {
  180. return $orm;
  181. }
  182. foreach ($filters as $key => $value) {
  183. if ($key === 'segment') {
  184. if ($value === 'none') {
  185. return self::filter('withoutSegments');
  186. } else {
  187. $segment = Segment::findOne($value);
  188. if ($segment instanceof Segment) {
  189. return $segment->subscribers();
  190. }
  191. }
  192. }
  193. }
  194. return $orm;
  195. }
  196. public static function groupBy($orm, $group = null) {
  197. if ($group === 'trash') {
  198. return $orm->whereNotNull('deleted_at');
  199. } else if ($group === 'all') {
  200. return $orm->whereNull('deleted_at');
  201. } else {
  202. return $orm->filter($group);
  203. }
  204. }
  205. public static function filterWithCustomFields($orm) {
  206. $orm = $orm->select(MP_SUBSCRIBERS_TABLE . '.*');
  207. $customFields = CustomField::findArray();
  208. foreach ($customFields as $customField) {
  209. $orm = $orm->select_expr(
  210. 'IFNULL(GROUP_CONCAT(CASE WHEN ' .
  211. MP_CUSTOM_FIELDS_TABLE . '.id=' . $customField['id'] . ' THEN ' .
  212. MP_SUBSCRIBER_CUSTOM_FIELD_TABLE . '.value END), NULL) as "' . $customField['name'] . '"');
  213. }
  214. $orm = $orm
  215. ->leftOuterJoin(
  216. MP_SUBSCRIBER_CUSTOM_FIELD_TABLE,
  217. [
  218. MP_SUBSCRIBERS_TABLE . '.id',
  219. '=',
  220. MP_SUBSCRIBER_CUSTOM_FIELD_TABLE . '.subscriber_id',
  221. ]
  222. )
  223. ->leftOuterJoin(
  224. MP_CUSTOM_FIELDS_TABLE,
  225. [
  226. MP_CUSTOM_FIELDS_TABLE . '.id',
  227. '=',
  228. MP_SUBSCRIBER_CUSTOM_FIELD_TABLE . '.custom_field_id',
  229. ]
  230. )
  231. ->groupBy(MP_SUBSCRIBERS_TABLE . '.id');
  232. return $orm;
  233. }
  234. /**
  235. * @deprecated
  236. */
  237. public static function filterWithCustomFieldsForExport($orm) {
  238. $orm = $orm->select(MP_SUBSCRIBERS_TABLE . '.*');
  239. $customFields = CustomField::findArray();
  240. foreach ($customFields as $customField) {
  241. $orm = $orm->selectExpr(
  242. 'MAX(CASE WHEN ' .
  243. MP_CUSTOM_FIELDS_TABLE . '.id=' . $customField['id'] . ' THEN ' .
  244. MP_SUBSCRIBER_CUSTOM_FIELD_TABLE . '.value END) as "' . $customField['id'] . '"'
  245. );
  246. }
  247. $orm = $orm
  248. ->leftOuterJoin(
  249. MP_SUBSCRIBER_CUSTOM_FIELD_TABLE,
  250. [
  251. MP_SUBSCRIBERS_TABLE . '.id', '=',
  252. MP_SUBSCRIBER_CUSTOM_FIELD_TABLE . '.subscriber_id',
  253. ]
  254. )
  255. ->leftOuterJoin(
  256. MP_CUSTOM_FIELDS_TABLE,
  257. [
  258. MP_CUSTOM_FIELDS_TABLE . '.id','=',
  259. MP_SUBSCRIBER_CUSTOM_FIELD_TABLE . '.custom_field_id',
  260. ]
  261. );
  262. return $orm;
  263. }
  264. public static function getSubscribedInSegments($segmentIds) {
  265. $subscribers = SubscriberSegment::tableAlias('relation')
  266. ->whereIn('relation.segment_id', $segmentIds)
  267. ->where('relation.status', 'subscribed')
  268. ->join(
  269. MP_SUBSCRIBERS_TABLE,
  270. 'subscribers.id = relation.subscriber_id',
  271. 'subscribers'
  272. )
  273. ->select('subscribers.id')
  274. ->whereNull('subscribers.deleted_at')
  275. ->where('subscribers.status', 'subscribed')
  276. ->distinct();
  277. return $subscribers;
  278. }
  279. /**
  280. * @param string $customerEmail
  281. * @return bool|Subscriber
  282. */
  283. public static function getWooCommerceSegmentSubscriber($customerEmail) {
  284. $wcSegment = Segment::getWooCommerceSegment();
  285. return Subscriber::tableAlias('subscribers')
  286. ->select('subscribers.*')
  287. ->where('subscribers.email', $customerEmail)
  288. ->join(
  289. MP_SUBSCRIBER_SEGMENT_TABLE,
  290. 'relation.subscriber_id = subscribers.id',
  291. 'relation'
  292. )
  293. ->where('relation.segment_id', $wcSegment->id)
  294. ->where('relation.status', Subscriber::STATUS_SUBSCRIBED)
  295. ->whereIn('subscribers.status', [Subscriber::STATUS_SUBSCRIBED, Subscriber::STATUS_UNCONFIRMED])
  296. ->where('subscribers.is_woocommerce_user', 1)
  297. ->findOne();
  298. }
  299. public function customFields() {
  300. return $this->hasManyThrough(
  301. __NAMESPACE__ . '\CustomField',
  302. __NAMESPACE__ . '\SubscriberCustomField',
  303. 'subscriber_id',
  304. 'custom_field_id'
  305. )->select_expr(MP_SUBSCRIBER_CUSTOM_FIELD_TABLE . '.value');
  306. }
  307. public static function createOrUpdate($data = []) {
  308. $subscriber = false;
  309. if (is_array($data) && !empty($data)) {
  310. $data = WPFunctions::get()->stripslashesDeep($data);
  311. }
  312. if (isset($data['id']) && (int)$data['id'] > 0) {
  313. $subscriber = self::findOne((int)$data['id']);
  314. unset($data['id']);
  315. }
  316. if ($subscriber === false && !empty($data['email'])) {
  317. $subscriber = self::where('email', $data['email'])->findOne();
  318. if ($subscriber !== false) {
  319. unset($data['email']);
  320. }
  321. }
  322. // segments
  323. $segmentIds = false;
  324. if (array_key_exists('segments', $data)) {
  325. $segmentIds = (array)$data['segments'];
  326. unset($data['segments']);
  327. }
  328. // if new subscriber, make sure that required fields are set
  329. if (!$subscriber) {
  330. $data = self::setRequiredFieldsDefaultValues($data);
  331. }
  332. // get custom fields
  333. list($data, $customFields) = self::extractCustomFieldsFromFromObject($data);
  334. // wipe any unconfirmed data at this point
  335. $data['unconfirmed_data'] = null;
  336. $oldStatus = false;
  337. $newStatus = false;
  338. if ($subscriber === false) {
  339. $subscriber = self::create();
  340. $subscriber->hydrate($data);
  341. } else {
  342. $oldStatus = $subscriber->status;
  343. $subscriber->set($data);
  344. $newStatus = $subscriber->status;
  345. }
  346. // Update last_subscribed_at when status changes to subscribed
  347. if ($oldStatus !== self::STATUS_SUBSCRIBED && $subscriber->status === self::STATUS_SUBSCRIBED) {
  348. $subscriber->set('last_subscribed_at', WPFunctions::get()->currentTime('mysql'));
  349. }
  350. if ($subscriber->save()) {
  351. if (!empty($customFields)) {
  352. $subscriber->saveCustomFields($customFields);
  353. }
  354. // check for status change
  355. if (
  356. ($oldStatus === self::STATUS_SUBSCRIBED)
  357. &&
  358. ($newStatus === self::STATUS_UNSUBSCRIBED)
  359. ) {
  360. // make sure we unsubscribe the user from all segments
  361. SubscriberSegment::unsubscribeFromSegments($subscriber);
  362. } else {
  363. if ($segmentIds !== false) {
  364. SubscriberSegment::resetSubscriptions($subscriber, $segmentIds);
  365. }
  366. }
  367. }
  368. return $subscriber;
  369. }
  370. public function withCustomFields() {
  371. $customFields = CustomField::select('id')->findArray();
  372. if (empty($customFields)) return $this;
  373. $customFieldIds = array_column($customFields, 'id');
  374. $relations = SubscriberCustomField::select('custom_field_id')
  375. ->select('value')
  376. ->whereIn('custom_field_id', $customFieldIds)
  377. ->where('subscriber_id', $this->id())
  378. ->findMany();
  379. foreach ($relations as $relation) {
  380. $this->{'cf_' . $relation->customFieldId} = $relation->value;
  381. }
  382. return $this;
  383. }
  384. public function withSegments() {
  385. $this->segments = $this->segments()->findArray();
  386. return $this;
  387. }
  388. public function withSubscriptions() {
  389. $this->subscriptions = SubscriberSegment::where('subscriber_id', $this->id())
  390. ->findArray();
  391. return $this;
  392. }
  393. public function getCustomField($customFieldId, $default = null) {
  394. $customField = SubscriberCustomField::select('value')
  395. ->where('custom_field_id', $customFieldId)
  396. ->where('subscriber_id', $this->id())
  397. ->findOne();
  398. if ($customField instanceof SubscriberCustomField) {
  399. return $customField->value;
  400. } else {
  401. return $default;
  402. }
  403. }
  404. public function saveCustomFields($customFieldsData = []) {
  405. // get custom field ids
  406. $customFieldIds = array_keys($customFieldsData);
  407. // get custom fields
  408. $customFields = CustomField::whereIdIn($customFieldIds)->findMany();
  409. foreach ($customFields as $customField) {
  410. $value = (isset($customFieldsData[$customField->id])
  411. ? $customFieldsData[$customField->id]
  412. : null
  413. );
  414. // format value
  415. $value = $customField->formatValue($value);
  416. $this->setCustomField($customField->id, $value);
  417. }
  418. }
  419. public function setCustomField($customFieldId, $value) {
  420. return SubscriberCustomField::createOrUpdate([
  421. 'subscriber_id' => $this->id(),
  422. 'custom_field_id' => $customFieldId,
  423. 'value' => $value,
  424. ]);
  425. }
  426. public function setUnconfirmedData(array $subscriberData) {
  427. $subscriberData = self::filterOutReservedColumns($subscriberData);
  428. $encoded = json_encode($subscriberData);
  429. if (is_string($encoded)) {
  430. $this->unconfirmedData = $encoded;
  431. }
  432. }
  433. public function getUnconfirmedData() {
  434. if (!empty($this->unconfirmedData)) {
  435. $subscriberData = json_decode($this->unconfirmedData, true);
  436. $subscriberData = self::filterOutReservedColumns((array)$subscriberData);
  437. return $subscriberData;
  438. }
  439. return null;
  440. }
  441. /**
  442. * @deprecated Use MailPoet\Util\License\Features\Subscribers::getSubscribersCount or \MailPoet\Subscribers\SubscribersRepository::getTotalSubscribers
  443. */
  444. public static function getTotalSubscribers() {
  445. return self::whereIn('status', [
  446. self::STATUS_SUBSCRIBED,
  447. self::STATUS_UNCONFIRMED,
  448. self::STATUS_INACTIVE,
  449. ])
  450. ->whereNull('deleted_at')
  451. ->count();
  452. }
  453. public static function getInactiveSubscribersCount() {
  454. return self::where('status', self::STATUS_INACTIVE)
  455. ->whereNull('deleted_at')
  456. ->count();
  457. }
  458. public static function subscribed($orm) {
  459. return $orm
  460. ->whereNull('deleted_at')
  461. ->where('status', self::STATUS_SUBSCRIBED);
  462. }
  463. public static function unsubscribed($orm) {
  464. return $orm
  465. ->whereNull('deleted_at')
  466. ->where('status', self::STATUS_UNSUBSCRIBED);
  467. }
  468. public static function unconfirmed($orm) {
  469. return $orm
  470. ->whereNull('deleted_at')
  471. ->where('status', self::STATUS_UNCONFIRMED);
  472. }
  473. public static function bounced($orm) {
  474. return $orm
  475. ->whereNull('deleted_at')
  476. ->where('status', self::STATUS_BOUNCED);
  477. }
  478. public static function inactive($orm) {
  479. return $orm
  480. ->whereNull('deleted_at')
  481. ->where('status', self::STATUS_INACTIVE);
  482. }
  483. public static function withoutSegments($orm) {
  484. return $orm->select(MP_SUBSCRIBERS_TABLE . '.*')
  485. ->whereRaw(
  486. MP_SUBSCRIBERS_TABLE . '.id NOT IN (
  487. SELECT `subscriber_id`
  488. FROM ' . MP_SUBSCRIBER_SEGMENT_TABLE . '
  489. WHERE `status` = "' . self::STATUS_SUBSCRIBED . '" AND `segment_id` IN (
  490. SELECT `id` FROM ' . MP_SEGMENTS_TABLE . ' WHERE `deleted_at` IS NULL
  491. )
  492. )'
  493. );
  494. }
  495. public static function createMultiple($columns, $values) {
  496. return self::rawExecute(
  497. 'INSERT INTO `' . self::$_table . '` ' .
  498. '(' . implode(', ', $columns) . ') ' .
  499. 'VALUES ' . rtrim(
  500. str_repeat(
  501. '(' . rtrim(str_repeat('?,', count($columns)), ',') . ')' . ', ',
  502. count($values)
  503. ),
  504. ', '
  505. ),
  506. Helpers::flattenArray($values)
  507. );
  508. }
  509. public static function updateMultiple($columns, $subscribers, $updatedAt = false) {
  510. $ignoreColumnsOnUpdate = [
  511. 'wp_user_id',
  512. 'is_woocommerce_user',
  513. 'email',
  514. 'created_at',
  515. 'last_subscribed_at',
  516. ];
  517. // check if there is anything to update after excluding ignored columns
  518. if (!array_diff($columns, $ignoreColumnsOnUpdate)) return;
  519. $subscribers = array_map('array_values', $subscribers);
  520. $emailPosition = array_search('email', $columns);
  521. $sql =
  522. function($type) use (
  523. $columns,
  524. $subscribers,
  525. $emailPosition,
  526. $ignoreColumnsOnUpdate
  527. ) {
  528. return array_filter(
  529. array_map(function($columnPosition, $columnName) use (
  530. $type,
  531. $subscribers,
  532. $emailPosition,
  533. $ignoreColumnsOnUpdate
  534. ) {
  535. if (in_array($columnName, $ignoreColumnsOnUpdate)) return;
  536. $query = array_map(
  537. function($subscriber) use ($type, $columnPosition, $emailPosition) {
  538. return ($type === 'values') ?
  539. [
  540. $subscriber[$emailPosition],
  541. $subscriber[$columnPosition],
  542. ] :
  543. 'WHEN email = ? THEN ?';
  544. }, $subscribers);
  545. return ($type === 'values') ?
  546. Helpers::flattenArray($query) :
  547. $columnName . '= (CASE ' . implode(' ', $query) . ' END)';
  548. }, array_keys($columns), $columns)
  549. );
  550. };
  551. return self::rawExecute(
  552. 'UPDATE `' . self::$_table . '` ' .
  553. 'SET ' . implode(', ', $sql('statement')) . ' ' .
  554. (($updatedAt) ? ', updated_at = "' . $updatedAt . '" ' : '') .
  555. ', unconfirmed_data = NULL ' .
  556. 'WHERE email IN ' .
  557. '(' . rtrim(str_repeat('?,', count($subscribers)), ',') . ')',
  558. array_merge(
  559. Helpers::flattenArray($sql('values')),
  560. array_column($subscribers, $emailPosition)
  561. )
  562. );
  563. }
  564. public static function findSubscribersInSegments(array $subscribersIds, array $segmentsIds) {
  565. return self::getSubscribedInSegments($segmentsIds)
  566. ->whereIn('subscribers.id', $subscribersIds)
  567. ->select('subscribers.*');
  568. }
  569. public static function extractSubscribersIds(array $subscribers) {
  570. return array_filter(
  571. array_map(function($subscriber) {
  572. return (!empty($subscriber->id)) ? $subscriber->id : false;
  573. }, $subscribers)
  574. );
  575. }
  576. public static function setRequiredFieldsDefaultValues($data) {
  577. $settings = SettingsController::getInstance();
  578. $requiredFieldDefaultValues = [
  579. 'first_name' => '',
  580. 'last_name' => '',
  581. 'unsubscribe_token' => Security::generateUnsubscribeToken(self::class),
  582. 'link_token' => Security::generateRandomString(self::LINK_TOKEN_LENGTH),
  583. 'status' => (!$settings->get('signup_confirmation.enabled')) ? self::STATUS_SUBSCRIBED : self::STATUS_UNCONFIRMED,
  584. ];
  585. foreach ($requiredFieldDefaultValues as $field => $value) {
  586. if (!isset($data[$field])) {
  587. $data[$field] = $value;
  588. }
  589. }
  590. return $data;
  591. }
  592. public static function extractCustomFieldsFromFromObject($data) {
  593. $customFields = [];
  594. foreach ($data as $key => $value) {
  595. if (strpos($key, 'cf_') === 0) {
  596. $customFields[(int)substr($key, 3)] = $value;
  597. unset($data[$key]);
  598. }
  599. }
  600. return [$data, $customFields];
  601. }
  602. public function getAllSegmentNamesWithStatus() {
  603. return Segment::tableAlias('segment')
  604. ->select('name')
  605. ->select('subscriber_segment.segment_id', 'segment_id')
  606. ->select('subscriber_segment.status', 'status')
  607. ->select('subscriber_segment.updated_at', 'updated_at')
  608. ->join(
  609. SubscriberSegment::$_table,
  610. ['subscriber_segment.segment_id', '=', 'segment.id'],
  611. 'subscriber_segment'
  612. )
  613. ->where('subscriber_segment.subscriber_id', $this->id)
  614. ->orderByAsc('name')
  615. ->findArray();
  616. }
  617. /**
  618. * This method is here only for BC fix of 3rd party plugin integration.
  619. * @see https://kb.mailpoet.com/article/195-add-subscribers-through-your-own-form-or-plugin
  620. * @deprecated
  621. */
  622. public static function subscribe($subscriberData = [], $segmentIds = []) {
  623. trigger_error('Calling Subscriber::subscribe() is deprecated and will be removed. Use MailPoet\API\MP\v1\API instead. ', E_USER_DEPRECATED);
  624. $service = ContainerWrapper::getInstance()->get(\MailPoet\Subscribers\SubscriberActions::class);
  625. return $service->subscribe($subscriberData, $segmentIds);
  626. }
  627. }