Commit inicial - WordPress Análisis de Precios Unitarios

- WordPress core y plugins
- Tema Twenty Twenty-Four configurado
- Plugin allow-unfiltered-html.php simplificado
- .gitignore configurado para excluir wp-config.php y uploads

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-11-03 21:04:30 -06:00
commit a22573bf0b
24068 changed files with 4993111 additions and 0 deletions

View File

@@ -0,0 +1,706 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
return array(
'.*Java.*outbrain',
'008\/',
'192.comAgent',
'2ip\.ru',
'404checker',
'^bluefish ',
'^FDM ',
'^Goose\/',
'^Java\/',
'^Mget',
'^NG\/[0-9\.]',
'^NING\/',
'^PHP\/[0-9]',
'^RMA\/',
'^Ruby|Ruby\/[0-9]',
'^scrutiny\/',
'^VSE\/[0-9]',
'^WordPress\.com',
'^XRL\/[0-9]',
'a3logics\.in',
'A6-Indexer',
'a\.pr-cy\.ru',
'Aboundex',
'aboutthedomain',
'Accoona-AI-Agent',
'acoon',
'acrylicapps\.com\/pulp',
'adbeat',
'AddThis',
'ADmantX',
'adressendeutschland',
'Advanced Email Extractor v',
'agentslug',
'AHC',
'aihit',
'aiohttp\/',
'Airmail',
'akula\/',
'alertra',
'alexa site audit',
'alyze\.info',
'amagit',
'AndroidDownloadManager',
'Anemone',
'Ant\.com',
'Anturis Agent',
'AnyEvent-HTTP\/',
'Apache-HttpClient\/',
'AportWorm\/[0-9]',
'AppEngine-Google',
'Arachmo',
'arachnode',
'Arachnophilia',
'archive-com',
'aria2',
'asafaweb.com',
'AskQuickly',
'Astute',
'autocite',
'Autonomy',
'B-l-i-t-z-B-O-T',
'Backlink-Ceck\.de',
'Bad-Neighborhood',
'baidu\.com',
'baypup\/[0-9]',
'baypup\/colbert',
'BazQux',
'BCKLINKS',
'BDFetch',
'BegunAdvertising\/',
'bibnum\.bnf',
'BigBozz',
'biglotron',
'BingLocalSearch',
'BingPreview',
'binlar',
'biz_Directory',
'Blackboard Safeassign',
'Bloglovin',
'BlogPulseLive',
'BlogSearch',
'Blogtrottr',
'boitho\.com-dc',
'BPImageWalker',
'Braintree-Webhooks',
'Branch Metrics API',
'Branch-Passthrough',
'Browsershots',
'BUbiNG',
'Butterfly\/',
'BuzzSumo',
'CakePHP',
'CapsuleChecker',
'CaretNail',
'cb crawl',
'CC Metadata Scaper',
'Cerberian Drtrs',
'CERT\.at-Statistics-Survey',
'cg-eye',
'changedetection',
'Charlotte',
'CheckHost',
'chkme\.com',
'CirrusExplorer\/',
'CISPA Vulnerability Notification',
'CJNetworkQuality',
'clips\.ua\.ac\.be',
'Cloud mapping experiment',
'CloudFlare-AlwaysOnline',
'Cloudinary\/[0-9]',
'cmcm\.com',
'coccoc',
'CommaFeed',
'Commons-HttpClient',
'Comodo SSL Checker',
'contactbigdatafr',
'convera',
'copyright sheriff',
'cosmos\/[0-9]',
'Covario-IDS',
'CrawlForMe\/[0-9]',
'cron-job\.org',
'Crowsnest',
'curb',
'Curious George',
'curl',
'cuwhois\/[0-9]',
'CyberPatrol',
'cybo\.com',
'DareBoost',
'DataparkSearch',
'dataprovider',
'Daum(oa)?[ \/][0-9]',
'DeuSu',
'developers\.google\.com\/\+\/web\/snippet\/',
'Digg',
'Dispatch\/',
'dlvr',
'DNS-Tools Header-Analyzer',
'DNSPod-reporting',
'docoloc',
'DomainAppender',
'dotSemantic',
'downforeveryoneorjustme',
'downnotifier\.com',
'DowntimeDetector',
'Dragonfly File Reader',
'drupact',
'Drupal (\+http:\/\/drupal\.org\/)',
'dubaiindex',
'EARTHCOM',
'Easy-Thumb',
'ec2linkfinder',
'eCairn-Grabber',
'ECCP',
'ElectricMonk',
'elefent',
'EMail Exractor',
'EmailWolf',
'Embed PHP Library',
'Embedly',
'europarchive\.org',
'evc-batch\/[0-9]',
'EventMachine HttpClient',
'Evidon',
'Evrinid',
'ExactSearch',
'ExaleadCloudview',
'Excel\/',
'Exploratodo',
'EyeMonIT',
'ezooms',
'facebookexternalhit',
'facebookplatform',
'fairshare',
'Faraday v',
'Faveeo',
'Favicon downloader',
'FavOrg',
'Feed Wrangler',
'Feedbin',
'FeedBooster',
'FeedBucket',
'FeedBurner',
'FeedChecker',
'Feedly',
'Feedspot',
'feeltiptop',
'Fetch API',
'Fetch\/[0-9]',
'Fever\/[0-9]',
'findlink',
'findthatfile',
'Flamingo_SearchEngine',
'FlipboardBrowserProxy',
'FlipboardProxy',
'FlipboardRSS',
'fluffy',
'flynxapp',
'forensiq',
'FoundSeoTool\/[0-9]',
'free thumbnails',
'FreeWebMonitoring SiteChecker',
'Funnelback',
'g00g1e\.net',
'GAChecker',
'geek-tools',
'Genderanalyzer',
'Genieo',
'GentleSource',
'GetLinkInfo',
'getprismatic\.com',
'GetURLInfo\/[0-9]',
'GigablastOpenSource',
'Go [\d\.]* package http',
'Go-http-client',
'GomezAgent',
'gooblog',
'Goodzer\/[0-9]',
'Google favicon',
'Google Keyword Suggestion',
'Google Keyword Tool',
'Google Page Speed Insights',
'Google PP Default',
'Google Search Console',
'Google Web Preview',
'Google-Adwords',
'Google-Apps-Script',
'Google-Calendar-Importer',
'Google-HTTP-Java-Client',
'Google-Publisher-Plugin',
'Google-SearchByImage',
'Google-Site-Verification',
'Google-Structured-Data-Testing-Tool',
'google_partner_monitoring',
'GoogleDocs',
'GoogleHC\/',
'GoogleProducer',
'GoScraper',
'GoSpotCheck',
'GoSquared-Status-Checker',
'gosquared-thumbnailer',
'GotSiteMonitor',
'Grammarly',
'grouphigh',
'grub-client',
'GTmetrix',
'Hatena',
'hawkReader',
'HEADMasterSEO',
'HeartRails_Capture',
'heritrix',
'hledejLevne\.cz\/[0-9]',
'Holmes',
'HootSuite Image proxy',
'Hootsuite-WebFeed\/[0-9]',
'HostTracker',
'ht:\/\/check',
'htdig',
'HTMLParser\/',
'HTTP-Header-Abfrage',
'http-kit',
'HTTP-Tiny',
'HTTP_Compression_Test',
'http_request2',
'http_requester',
'HttpComponents',
'httphr',
'HTTPMon',
'httpscheck',
'httpssites_power',
'httpunit',
'HttpUrlConnection',
'httrack',
'hosterstats',
'huaweisymantec',
'HubPages.*crawlingpolicy',
'HubSpot Connect',
'HubSpot Marketing Grader',
'HyperZbozi.cz Feeder',
'ichiro',
'IdeelaborPlagiaat',
'IDG Twitter Links Resolver',
'IDwhois\/[0-9]',
'Iframely',
'igdeSpyder',
'IlTrovatore',
'ImageEngine\/',
'Imagga',
'InAGist',
'inbound\.li parser',
'InDesign%20CC',
'infegy',
'infohelfer',
'InfoWizards Reciprocal Link System PRO',
'inpwrd\.com',
'Integrity',
'integromedb',
'internet_archive',
'InternetSeer',
'internetVista monitor',
'IODC',
'IOI',
'ips-agent',
'iqdb\/',
'Irokez',
'isitup\.org',
'iskanie',
'iZSearch',
'janforman',
'Jigsaw',
'Jobboerse',
'jobo',
'Jobrapido',
'KeepRight OpenStreetMap Checker',
'KimonoLabs\/',
'knows\.is',
'kouio',
'KrOWLer',
'kulturarw3',
'KumKie',
'L\.webis',
'Larbin',
'LayeredExtractor',
'LibVLC',
'libwww',
'link checker',
'Link Valet',
'link_thumbnailer',
'linkCheck',
'linkdex',
'LinkExaminer',
'linkfluence',
'linkpeek',
'LinkTiger',
'LinkWalker',
'Lipperhey',
'livedoor ScreenShot',
'LoadImpactPageAnalyzer',
'LoadImpactRload',
'LongURL API',
'looksystems\.net',
'ltx71',
'lwp-trivial',
'lycos',
'LYT\.SR',
'mabontland',
'MagpieRSS',
'Mail.Ru',
'MailChimp\.com',
'Mandrill',
'marketinggrader',
'Mediapartners-Google',
'MegaIndex\.ru',
'Melvil Rawi\/',
'MergeFlow-PageReader',
'MetaInspector',
'Metaspinner',
'MetaURI',
'Microsearch',
'Microsoft Office ',
'Microsoft Windows Network Diagnostics',
'Mindjet',
'Miniflux',
'Mnogosearch',
'mogimogi',
'Mojolicious (Perl)',
'monitis',
'Monitority\/[0-9]',
'montastic',
'MonTools',
'Moreover',
'Morning Paper',
'mowser',
'Mrcgiguy',
'mShots',
'MVAClient',
'nagios',
'Najdi\.si\/',
'NETCRAFT',
'NetLyzer FastProbe',
'netresearch',
'NetShelter ContentScan',
'NetTrack',
'Netvibes',
'Neustar WPM',
'NeutrinoAPI',
'NewsBlur .*Finder',
'NewsGator',
'newsme',
'newspaper\/',
'NG-Search',
'nineconnections\.com',
'NLNZ_IAHarvester',
'Nmap Scripting Engine',
'node-superagent',
'node\.io',
'nominet\.org\.uk',
'Norton-Safeweb',
'Notifixious',
'notifyninja',
'nuhk',
'nutch',
'Nuzzel',
'nWormFeedFinder',
'Nymesis',
'Ocelli\/[0-9]',
'oegp',
'okhttp',
'Omea Reader',
'omgili',
'Online Domain Tools',
'OpenCalaisSemanticProxy',
'Openstat\/',
'OpenVAS',
'Optimizer',
'Orbiter',
'OrgProbe\/[0-9]',
'ow\.ly',
'ownCloud News',
'Page Analyzer',
'Page Valet',
'page2rss',
'page_verifier',
'PagePeeker',
'Pagespeed\/[0-9]',
'Panopta',
'panscient',
'parsijoo',
'PayPal IPN',
'Pcore-HTTP',
'Pearltrees',
'peerindex',
'Peew',
'PhantomJS\/',
'Photon\/',
'phpcrawl',
'phpservermon',
'Pi-Monster',
'Pingdom\.com',
'Pingoscope',
'PingSpot',
'Pinterest',
'Pizilla',
'Ploetz \+ Zeller',
'Plukkie',
'PocketParser',
'Pompos',
'Porkbun',
'Port Monitor',
'postano',
'PostPost',
'postrank',
'PowerPoint\/',
'Priceonomics Analysis Engine',
'Prlog',
'probethenet',
'Project 25499',
'Promotion_Tools_www.searchenginepromotionhelp.com',
'prospectb2b',
'Protopage',
'proximic',
'PTST ',
'PTST\/[0-9]+',
'Pulsepoint XT3 web scraper',
'Python-httplib2',
'python-requests',
'Python-urllib',
'Qirina Hurdler',
'Qseero',
'Qualidator.com SiteAnalyzer',
'Quora Link Preview',
'Qwantify',
'Radian6',
'RankSonicSiteAuditor',
'Readability',
'RealPlayer%20Downloader',
'RebelMouse',
'redback\/',
'Redirect Checker Tool',
'ReederForMac',
'ResponseCodeTest\/[0-9]',
'RestSharp',
'RetrevoPageAnalyzer',
'Riddler',
'Rival IQ',
'Robosourcer',
'Robozilla\/[0-9]',
'ROI Hunter',
'SalesIntelligent',
'SauceNAO',
'SBIder',
'Scoop',
'scooter',
'ScoutJet',
'ScoutURLMonitor',
'Scrapy',
'Scrubby',
'SearchSight',
'semanticdiscovery',
'semanticjuice',
'SEO Browser',
'Seo Servis',
'seo-nastroj.cz',
'Seobility',
'SEOCentro',
'SeoCheck',
'SeopultContentAnalyzer',
'SEOstats',
'Server Density Service Monitoring',
'servernfo\.com',
'Seznam screenshot-generator',
'Shelob',
'Shoppimon Analyzer',
'ShoppimonAgent\/[0-9]',
'ShopWiki',
'ShortLinkTranslate',
'shrinktheweb',
'SilverReader',
'SimplePie',
'SimplyFast',
'Site-Shot\/',
'Site24x7',
'SiteBar',
'SiteCondor',
'siteexplorer\.info',
'SiteGuardian',
'Siteimprove\.com',
'Sitemap(s)? Generator',
'Siteshooter B0t',
'SiteTruth',
'sitexy\.com',
'SkypeUriPreview',
'slider\.com',
'slurp',
'SMRF URL Expander',
'Snappy',
'SniffRSS',
'sniptracker',
'Snoopy',
'sogou web',
'SortSite',
'spaziodati',
'Specificfeeds',
'speedy',
'SPEng',
'Spinn3r',
'spray-can',
'Sprinklr ',
'spyonweb',
'Sqworm',
'SSL Labs',
'StackRambler',
'Statastico\/',
'StatusCake',
'Stratagems Kumo',
'Stroke.cz',
'StudioFACA',
'suchen',
'summify',
'Super Monitoring',
'Surphace Scout',
'SwiteScraper',
'Symfony2 BrowserKit',
'Sysomos',
'T0PHackTeam',
'Tarantula\/',
'teoma',
'terrainformatica\.com',
'The Expert HTML Source Viewer',
'theinternetrules',
'theoldreader\.com',
'Thumbshots',
'ThumbSniper',
'TinEye',
'Tiny Tiny RSS',
'topster',
'touche.com',
'Traackr.com',
'truwoGPS',
'tweetedtimes\.com',
'Tweetminster',
'Twikle',
'Twingly',
'Typhoeus',
'ubermetrics-technologies',
'uclassify',
'UdmSearch',
'UnwindFetchor',
'updated',
'Upflow',
'URLChecker',
'URLitor.com',
'urlresolver',
'Urlstat',
'UrlTrends Ranking Updater',
'Vagabondo',
'via ggpht\.com GoogleImageProxy',
'visionutils',
'vkShare',
'voltron',
'Vortex\/[0-9]',
'voyager\/',
'VSAgent\/[0-9]',
'VSB-TUO\/[0-9]',
'VYU2',
'w3af\.org',
'W3C-checklink',
'W3C-mobileOK',
'W3C_I18n-Checker',
'W3C_Unicorn',
'wangling',
'Wappalyzer',
'WatchMouse',
'WbSrch\/',
'web-capture\.net',
'Web-Monitoring',
'Web-sniffer',
'Webauskunft',
'WebCapture',
'webcollage',
'WebCookies',
'WebCorp',
'WebDoc',
'WebFetch',
'WebImages',
'WebIndex',
'webkit2png',
'webmastercoffee',
'webmon ',
'webscreenie',
'Webshot',
'Website Analyzer\/',
'websitepulse[+ ]checker',
'Websnapr\/',
'Websquash\.com',
'Webthumb\/[0-9]',
'WebThumbnail',
'WeCrawlForThePeace',
'WeLikeLinks',
'WEPA',
'WeSEE',
'wf84',
'wget',
'WhatsApp',
'WhatsMyIP',
'WhatWeb',
'Whibse',
'Whynder Magnet',
'Windows-RSS-Platform',
'WinHttpRequest',
'wkhtmlto',
'wmtips',
'Woko',
'WomlpeFactory',
'Word\/',
'WordPress\/',
'wotbox',
'WP Engine Install Performance API',
'WPScan',
'wscheck',
'WWW-Mechanize',
'www\.monitor\.us',
'XaxisSemanticsClassifier',
'Xenu Link Sleuth',
'XING-contenttabreceiver\/[0-9]',
'XmlSitemapGenerator',
'xpymep([0-9]?)\.exe',
'Y!J-(ASR|BSC)',
'Yaanb',
'yacy',
'Yahoo Ad monitoring',
'Yahoo Link Preview',
'YahooCacheSystem',
'YahooSeeker',
'YahooYSMcm',
'YandeG',
'yandex',
'yanga',
'yeti',
'Yo-yo',
'Yoleo Consumer',
'yoogliFetchAgent',
'YottaaMonitor',
'yourls\.org',
'Zao',
'Zemanta Aggregator',
'Zend\\\\Http\\\\Client',
'Zend_Http_Client',
'zgrab',
'ZnajdzFoto',
'ZyBorg',
'[a-z0-9\-_]*((?<!cu)bot|crawler|archiver|transcoder|spider|uptime|validator|fetcher)',
);

View File

@@ -0,0 +1,173 @@
<?php
namespace TVD\Dashboard\Access_Manager;
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class Main {
public static function init() {
static::hooks();
}
public static function hooks() {
add_action( 'current_screen', array( __CLASS__, 'conditional_hooks' ) );
}
/**
* Getting site's roles and the url to their users
*
* @return array
*/
public static function get_roles_url() {
global $wp_roles;
$all_roles = array();
foreach ( $wp_roles->roles as $role_tag => $role ) {
$role['url'] = add_query_arg( 'role', $role['name'], admin_url( 'users.php' ) );
$role['tag'] = $role_tag;
$role['can_edit_posts'] = isset( $role['capabilities']['edit_posts'] );
unset( $role['capabilities'] );
$all_roles[ $role['tag'] ] = $role;
}
return $all_roles;
}
/**
* Get all the products that should be included in the AM
*
* @return array
*/
public static function get_products() {
$all_products = array();
$all_products['td'] = array(
'name' => 'Thrive Dashboard Settings',
'tag' => 'td',
'logo' => TVE_DASH_IMAGES_URL . '/dash-logo-icon-small.png',
'prod_capability' => TVE_DASH_CAPABILITY,
);
foreach ( tve_dash_get_products( false ) as $product ) {
/* Skip old themes */
if ( 'theme' === $product->get_type() && 'thrive theme' !== strtolower( $product->get_title() ) ) {
continue;
}
$tag = $product->get_tag();
$all_products[ $tag ] = array(
'name' => $product->get_title(),
'tag' => $tag,
'logo' => $product->get_logo(),
'prod_capability' => $product->get_cap(),
);
}
return $all_products;
}
/**
* Getting plugin capabilities for each of the existing roles
*
* @param $all_roles
*
* @return array
*/
public static function get_roles_capabilities( $all_roles ) {
foreach ( static::get_products() as $product ) {
foreach ( $all_roles as $role ) {
$wp_role = get_role( $role['tag'] );
$all_roles[ $role['tag'] ]['products'][ $product['tag'] ] = array(
'name' => $product['name'],
'tag' => $product['tag'],
'logo' => $product['logo'],
'can_use' => $wp_role ? $wp_role->has_cap( $product['prod_capability'] ) : false,
'is_editable' => $product['tag'] === 'td' ? $role['tag'] !== 'administrator' && $role['can_edit_posts'] : $role['can_edit_posts'],
'prod_capability' => $product['prod_capability'],
);
}
}
return $all_roles;
}
/**
* Hook based on the current screen
*/
public static function conditional_hooks() {
if ( tve_get_current_screen_key() === 'admin_page_tve_dash_access_manager' ) {
add_action( 'admin_enqueue_scripts', array( __CLASS__, 'tve_dash_access_manager_include_scripts' ) );
add_action( 'admin_print_footer_scripts', array( __CLASS__, 'render_backbone_templates' ) );
}
}
public static function render_backbone_templates() {
$templates = tve_dash_get_backbone_templates( TVE_DASH_PATH . '/inc/access-manager/includes/templates', 'templates' );
tve_dash_output_backbone_templates( $templates, '' );
}
public static function tve_dash_access_manager_include_scripts() {
tve_dash_enqueue();
include TVE_DASH_PATH . '/inc/access-manager/includes/assets/css/am-icons.svg';
tve_dash_enqueue_style( 'tve-dash-access-manager-css', TVE_DASH_URL . '/inc/access-manager/includes/assets/css/style.css' );
tve_dash_enqueue_script( 'tve-dash-access-manager-js', TVE_DASH_URL . '/inc/access-manager/includes/assets/dist/admin.min.js', array(
'tve-dash-main-js',
'jquery',
'backbone',
), false, true );
wp_localize_script( 'tve-dash-access-manager-js', 'TVD_AM_CONST', array(
'roles_properties' => static::get_roles_functionalities( static::get_roles_capabilities( static::get_roles_url() ) ),
'baseUrl' => get_rest_url( get_current_blog_id(), 'wp/v2/pages/' ),
) );
}
/**
* Getting functionalities for each of the existing roles
*
* @param $all_roles
*
* @return array
*/
public static function get_roles_functionalities( $all_roles ) {
$functionalities = static::get_all_functionalities();
foreach ( $all_roles as $role ) {
foreach ( $functionalities as $functionality ) {
$roles_functionalities = $functionality::get_properties( $role['tag'] );
$all_roles[ $role['tag'] ]['functionalities'][ $roles_functionalities['tag'] ] = $roles_functionalities;
}
}
return $all_roles;
}
/**
* Get all functionalities from the Access Manager
*
* @return string[]
*/
public static function get_all_functionalities( $functionality_tag = null ) {
$functionalities = array(
new \TVD\Dashboard\Access_Manager\Admin_Bar_Visibility(),
new \TVD\Dashboard\Access_Manager\Login_Redirect()
);
if ( $functionality_tag ) {
$functionalities = current( array_filter( $functionalities,
static function ( $functionality ) use ( $functionality_tag ) {
return $functionality::get_tag() === $functionality_tag;
} ) );
}
return $functionalities;
}
}

View File

@@ -0,0 +1,77 @@
<?php
namespace TVD\Dashboard\Access_Manager;
use TVD\Dashboard\Access_Manager\Functionality;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Admin_Bar_Visibility extends Functionality {
public static function hooks() {
add_filter( 'show_admin_bar', array( __CLASS__, 'show_admin_bar' ) );
}
public static function get_name() {
return __( 'Admin Bar Visibility', 'thrive-dash' );
}
public static function get_tag() {
return 'admin_bar_visibility';
}
public static function get_default() {
return 'inherit';
}
public static function get_options() {
return array(
[
'name' => 'Inherit',
'tag' => 'inherit',
],
[
'name' => 'Hidden',
'tag' => 'hidden',
],
[
'name' => 'Displayed',
'tag' => 'displayed',
],
);
}
public static function get_icon() {
return 'wordpress';
}
public static function get_options_type() {
return 'dropdown';
}
public static function get_option_value( $user_role ) {
return get_option( static::get_option_name( $user_role ) );
}
public static function show_admin_bar( $show_admin_bar ) {
if ( is_user_logged_in() ) {
$user_role = reset( wp_get_current_user()->roles );
$visibility = static::get_option_value( $user_role );
switch ( $visibility ) {
case 'displayed':
$show_admin_bar = true;
break;
case 'hidden':
$show_admin_bar = false;
break;
default:
break;
}
}
return $show_admin_bar;
}
}

View File

@@ -0,0 +1,43 @@
<?php
namespace TVD\Dashboard\Access_Manager;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
abstract class Functionality {
public static function init() {
static::hooks();
}
abstract public static function hooks();
abstract public static function get_name();
abstract public static function get_tag();
abstract public static function get_default();
public static function update_option_value( $user_role, $updated_value ) {
update_option( static::get_option_name( $user_role ), $updated_value );
}
public static function get_option_name( $user_role ) {
return '_' . $user_role . '_' . static::get_tag();
}
public static function get_properties( $user_role ) {
return array(
'name' => static::get_name(),
'tag' => static::get_tag(),
'functionality_options' => static::get_options(),
'get_options_type' => static::get_options_type(),
'icon' => static::get_icon(),
'default_value' => static::get_default(),
'value' => static::get_option_value( $user_role ),
);
}
}

View File

@@ -0,0 +1,107 @@
<?php
namespace TVD\Dashboard\Access_Manager;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Login_Redirect extends Functionality {
public static function hooks() {
add_filter( 'login_redirect', array( __CLASS__, 'login_redirect' ), 10, 3 );
}
public static function get_name() {
return 'WordPress Login Redirect';
}
public static function get_tag() {
return 'login_redirect';
}
public static function get_default() {
return 'inherit';
}
public static function get_options() {
$options = array(
[
'name' => 'Inherit',
'tag' => 'inherit',
],
[
'name' => 'WordPress Dashboard',
'tag' => 'wpdashboard',
],
[
'name' => 'Homepage',
'tag' => 'homepage',
],
[
'name' => 'Custom',
'tag' => 'custom',
],
);
if ( tve_dash_is_plugin_active( 'thrive-apprentice' ) ) {
$options[] = [
'name' => 'Apprentice Homepage',
'tag' => 'apphomepage',
];
}
return $options;
}
public static function get_icon() {
return 'wordpress';
}
public static function get_options_type() {
return 'dropdown';
}
public static function get_option_value( $user_role ) {
$option = get_option( static::get_option_name( $user_role ) );
if ( $option === 'apphomepage' && ! tve_dash_is_plugin_active( 'thrive-apprentice' ) ) {
$option = 'inherit';
}
return $option;
}
public static function login_redirect( $redirect, $requested_redirect_to, $logged_in_user ) {
if ( ! is_wp_error( $logged_in_user ) && $logged_in_user && $logged_in_user->ID ) {
if ( ! empty( $logged_in_user->roles ) ) {
$user_role = $logged_in_user->roles[0];
$url = static::get_option_value( $user_role );
} else {
$url = 'inherit';
}
if ( $url ) {
switch ( $url ) {
case 'inherit':
break;
case 'wpdashboard':
$redirect = get_admin_url();
break;
case 'homepage':
$redirect = get_home_url();
break;
case 'apphomepage':
if ( tve_dash_is_plugin_active( 'thrive-apprentice' ) ) {
$redirect = get_permalink( tva_get_settings_manager()->factory( 'index_page' )->get_value() );
}
break;
default:
$redirect = get_permalink( $url['pageId'] );
break;
}
}
}
return $redirect;
}
}

View File

@@ -0,0 +1,47 @@
<svg style="position: absolute; width: 0; height: 0; overflow: hidden;" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<symbol id="icon-cap-editable" viewBox="0 0 512 512">
<path d="M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z"/>
</symbol>
<symbol id="icon-cap-non-editable" viewBox="0 0 26 25">
<g fill-rule="nonzero" fill="none">
<path d="M20.672 11.125a9.86 9.86 0 0 0-1.374-5.086 10.278 10.278 0 0 0-3.712-3.712A9.86 9.86 0 0 0 10.5.953a9.86 9.86 0 0 0-5.086 1.374A10.278 10.278 0 0 0 1.702 6.04a9.86 9.86 0 0 0-1.374 5.086 9.86 9.86 0 0 0 1.374 5.086 10.278 10.278 0 0 0 3.712 3.712 9.86 9.86 0 0 0 5.086 1.374 9.86 9.86 0 0 0 5.086-1.374 10.278 10.278 0 0 0 3.712-3.712 9.86 9.86 0 0 0 1.374-5.086zM9.31 16.498a.546.546 0 0 1-.452.205.546.546 0 0 1-.45-.205l-4.266-4.266a.546.546 0 0 1-.206-.45c0-.192.069-.343.206-.452l.902-.943a.648.648 0 0 1 .472-.205c.177 0 .335.068.471.205l2.871 2.87 6.153-6.152a.648.648 0 0 1 .471-.205c.178 0 .335.069.472.205l.902.944c.137.11.205.26.205.451a.546.546 0 0 1-.205.451l-7.546 7.547z"
fill="#8E8E8E" opacity=".75"/>
<path d="M24.594 18.188c.286 0 .53.1.73.3.2.2.301.444.301.73v4.126c0 .286-.1.53-.3.73-.201.2-.445.301-.731.301H17.03c-.286 0-.53-.1-.73-.3-.2-.201-.301-.445-.301-.731v-4.125c0-.287.1-.53.3-.73.201-.201.445-.301.731-.301h.516V16.64c0-.588.147-1.132.44-1.633a3.282 3.282 0 0 1 1.193-1.193 3.174 3.174 0 0 1 1.632-.44c.588 0 1.132.147 1.633.44.502.294.9.692 1.193 1.193.293.501.44 1.045.44 1.633v1.547h.516zm-2.235 0V16.64c0-.43-.15-.795-.45-1.096-.302-.3-.667-.451-1.097-.451-.43 0-.794.15-1.095.45-.301.302-.451.667-.451 1.097v1.547h3.093z"
fill="#787F78"/>
</g>
</symbol>
<symbol id="icon-no-cap-editable" viewBox="0 0 512 512">
<path d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm121.6 313.1c4.7 4.7 4.7 12.3 0 17L338 377.6c-4.7 4.7-12.3 4.7-17 0L256 312l-65.1 65.6c-4.7 4.7-12.3 4.7-17 0L134.4 338c-4.7-4.7-4.7-12.3 0-17l65.6-65-65.6-65.1c-4.7-4.7-4.7-12.3 0-17l39.6-39.6c4.7-4.7 12.3-4.7 17 0l65 65.7 65.1-65.6c4.7-4.7 12.3-4.7 17 0l39.6 39.6c4.7 4.7 4.7 12.3 0 17L312 256l65.6 65.1z"/>
</symbol>
<symbol id="icon-no-cap-non-editable" viewBox="0 0 26 25">
<g fill-rule="nonzero" fill="none">
<path d="M10.5.953a9.86 9.86 0 0 1 5.086 1.374 10.278 10.278 0 0 1 3.712 3.712 9.86 9.86 0 0 1 1.374 5.086 9.86 9.86 0 0 1-1.374 5.086 10.278 10.278 0 0 1-3.712 3.712 9.86 9.86 0 0 1-5.086 1.374 9.86 9.86 0 0 1-5.086-1.374 10.278 10.278 0 0 1-3.712-3.712 9.86 9.86 0 0 1-1.374-5.086 9.86 9.86 0 0 1 1.374-5.086 10.278 10.278 0 0 1 3.712-3.712A9.86 9.86 0 0 1 10.5.953zm5.004 12.838-2.707-2.666 2.707-2.666a.571.571 0 0 0 .123-.349.571.571 0 0 0-.123-.348l-1.64-1.64a.443.443 0 0 0-.329-.124.6.6 0 0 0-.369.123L10.5 8.828 7.834 6.121a.571.571 0 0 0-.349-.123.571.571 0 0 0-.348.123l-1.64 1.64a.443.443 0 0 0-.124.329.6.6 0 0 0 .123.369l2.707 2.666-2.707 2.666a.571.571 0 0 0-.123.349c0 .123.041.239.123.348l1.64 1.64a.443.443 0 0 0 .329.124.6.6 0 0 0 .369-.123l2.666-2.707 2.666 2.707c.11.082.226.123.349.123.123 0 .239-.041.348-.123l1.64-1.64a.443.443 0 0 0 .124-.329.6.6 0 0 0-.123-.369z"
fill="#8E8E8E" opacity=".75"/>
<path d="M24.594 18.188c.286 0 .53.1.73.3.2.2.301.444.301.73v4.126c0 .286-.1.53-.3.73-.201.2-.445.301-.731.301H17.03c-.286 0-.53-.1-.73-.3-.2-.201-.301-.445-.301-.731v-4.125c0-.287.1-.53.3-.73.201-.201.445-.301.731-.301h.516V16.64c0-.588.147-1.132.44-1.633a3.282 3.282 0 0 1 1.193-1.193 3.174 3.174 0 0 1 1.632-.44c.588 0 1.132.147 1.633.44.502.294.9.692 1.193 1.193.293.501.44 1.045.44 1.633v1.547h.516zm-2.235 0V16.64c0-.43-.15-.795-.45-1.096-.302-.3-.667-.451-1.097-.451-.43 0-.794.15-1.095.45-.301.302-.451.667-.451 1.097v1.547h3.093z"
fill="#787F78"/>
</g>
</symbol>
<symbol id="icon-sync-alt" viewBox="0 0 512 512">
<path d="M483.515 28.485L431.35 80.65C386.475 35.767 324.485 8 256 8 123.228 8 14.824 112.338 8.31 243.493 7.971 250.311 13.475 256 20.301 256h28.045c6.353 0 11.613-4.952 11.973-11.294C66.161 141.649 151.453 60 256 60c54.163 0 103.157 21.923 138.614 57.386l-54.128 54.129c-7.56 7.56-2.206 20.485 8.485 20.485H492c6.627 0 12-5.373 12-12V36.971c0-10.691-12.926-16.045-20.485-8.486zM491.699 256h-28.045c-6.353 0-11.613 4.952-11.973 11.294C445.839 370.351 360.547 452 256 452c-54.163 0-103.157-21.923-138.614-57.386l54.128-54.129c7.56-7.56 2.206-20.485-8.485-20.485H20c-6.627 0-12 5.373-12 12v143.029c0 10.691 12.926 16.045 20.485 8.485L80.65 431.35C125.525 476.233 187.516 504 256 504c132.773 0 241.176-104.338 247.69-235.493.339-6.818-5.165-12.507-11.991-12.507z"/>
</symbol>
<symbol id="icon-users" viewBox="0 0 640 512">
<path d="M544 224c44.2 0 80-35.8 80-80s-35.8-80-80-80-80 35.8-80 80 35.8 80 80 80zm0-112c17.6 0 32 14.4 32 32s-14.4 32-32 32-32-14.4-32-32 14.4-32 32-32zM96 224c44.2 0 80-35.8 80-80s-35.8-80-80-80-80 35.8-80 80 35.8 80 80 80zm0-112c17.6 0 32 14.4 32 32s-14.4 32-32 32-32-14.4-32-32 14.4-32 32-32zm396.4 210.9c-27.5-40.8-80.7-56-127.8-41.7-14.2 4.3-29.1 6.7-44.7 6.7s-30.5-2.4-44.7-6.7c-47.1-14.3-100.3.8-127.8 41.7-12.4 18.4-19.6 40.5-19.6 64.3V432c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48v-44.8c.2-23.8-7-45.9-19.4-64.3zM464 432H176v-44.8c0-36.4 29.2-66.2 65.4-67.2 25.5 10.6 51.9 16 78.6 16 26.7 0 53.1-5.4 78.6-16 36.2 1 65.4 30.7 65.4 67.2V432zm92-176h-24c-17.3 0-33.4 5.3-46.8 14.3 13.4 10.1 25.2 22.2 34.4 36.2 3.9-1.4 8-2.5 12.3-2.5h24c19.8 0 36 16.2 36 36 0 13.2 10.8 24 24 24s24-10.8 24-24c.1-46.3-37.6-84-83.9-84zm-236 0c61.9 0 112-50.1 112-112S381.9 32 320 32 208 82.1 208 144s50.1 112 112 112zm0-176c35.3 0 64 28.7 64 64s-28.7 64-64 64-64-28.7-64-64 28.7-64 64-64zM154.8 270.3c-13.4-9-29.5-14.3-46.8-14.3H84c-46.3 0-84 37.7-84 84 0 13.2 10.8 24 24 24s24-10.8 24-24c0-19.8 16.2-36 36-36h24c4.4 0 8.5 1.1 12.3 2.5 9.3-14 21.1-26.1 34.5-36.2z"/>
</symbol>
<symbol id="icon-wordpress" viewBox="0 0 22 22">
<path d="M2.664 7.012a8.975 8.975 0 0 0-.816 3.738c0 1.776.472 3.402 1.418 4.877.945 1.475 2.191 2.585 3.738 3.33L2.664 7.012zm14.523 3.265c0-.487-.085-.974-.257-1.46a8.57 8.57 0 0 0-.516-1.032l-.086-.172c-.286-.458-.473-.787-.559-.988a2.21 2.21 0 0 1-.257-.988c0-.43.15-.81.45-1.139.302-.33.667-.494 1.097-.494h.128a9.634 9.634 0 0 0-2.835-1.762A8.836 8.836 0 0 0 11 1.598a8.907 8.907 0 0 0-4.383 1.117 9.154 9.154 0 0 0-3.265 3.008h.601c.401 0 .931-.015 1.59-.043l.86-.043c.143-.029.25.021.322.15a.413.413 0 0 1 .021.387.304.304 0 0 1-.3.193l-1.032.086 3.309 9.926 2.02-6.016-1.419-3.91c-.344 0-.673-.028-.988-.086a.304.304 0 0 1-.3-.193.413.413 0 0 1 .02-.387c.072-.129.194-.179.366-.15l.86.043c.658.028 1.18.043 1.568.043.386 0 .895-.015 1.525-.043l.86-.043c.171-.029.293.021.365.15a.413.413 0 0 1 .021.387.304.304 0 0 1-.3.193l-1.032.086 3.266 9.84 1.03-3.352c.201-.687.345-1.174.43-1.46a5.05 5.05 0 0 0 .172-1.204zm-8.765 9.239c.86.257 1.719.386 2.578.386a9.348 9.348 0 0 0 3.05-.515l-.085-.13-2.793-7.69-2.75 7.949zM19.035 6.367c.029.287.043.602.043.946 0 1.03-.23 2.12-.687 3.265l-2.793 8.078a9.159 9.159 0 0 0 3.308-3.308 8.864 8.864 0 0 0 1.246-4.598 8.907 8.907 0 0 0-1.117-4.383zm2.621 4.383c0-1.92-.48-3.695-1.44-5.328a10.768 10.768 0 0 0-3.888-3.889A10.33 10.33 0 0 0 11 .093c-1.92 0-3.695.48-5.328 1.44a10.768 10.768 0 0 0-3.889 3.889 10.33 10.33 0 0 0-1.44 5.328c0 1.92.48 3.695 1.44 5.328a10.768 10.768 0 0 0 3.889 3.889A10.33 10.33 0 0 0 11 21.407c1.92 0 3.695-.48 5.328-1.44a10.768 10.768 0 0 0 3.889-3.889 10.33 10.33 0 0 0 1.44-5.328zm-.472 0a9.88 9.88 0 0 1-1.375 5.092 10.275 10.275 0 0 1-3.717 3.717A9.88 9.88 0 0 1 11 20.934a9.88 9.88 0 0 1-5.092-1.375 10.275 10.275 0 0 1-3.717-3.717A9.88 9.88 0 0 1 .816 10.75a9.88 9.88 0 0 1 1.375-5.092 10.275 10.275 0 0 1 3.717-3.717A9.88 9.88 0 0 1 11 .566a9.88 9.88 0 0 1 5.092 1.375c1.561.917 2.8 2.156 3.717 3.717a9.88 9.88 0 0 1 1.375 5.092z"
fill="#424242" fill-rule="nonzero"/>
</symbol>
<symbol id="icon-info" viewBox="0 0 512 512">
<path d="M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 448c-110.532 0-200-89.431-200-200 0-110.495 89.472-200 200-200 110.491 0 200 89.471 200 200 0 110.53-89.431 200-200 200zm42-104c0 23.159-18.841 42-42 42s-42-18.841-42-42 18.841-42 42-42 42 18.841 42 42zm-81.37-211.401l6.8 136c.319 6.387 5.591 11.401 11.985 11.401h41.17c6.394 0 11.666-5.014 11.985-11.401l6.8-136c.343-6.854-5.122-12.599-11.985-12.599h-54.77c-6.863 0-12.328 5.745-11.985 12.599z"/>
</symbol>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 8.9 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,19 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
require_once( TVE_DASH_PATH . '/templates/header.phtml' ); ?>
<div class="tvd-am-breadcrumbs">
<a href="<?php echo esc_url( admin_url( 'admin.php?page=tve_dash_section' ) ); ?>">
<?php echo esc_html__( 'Thrive Dashboard', 'thrive-dash' ); ?>
</a>
<span class="tvd-breadcrumb"><?php echo esc_html__( 'User Access Manager', 'thrive-dash' ); ?></span>
</div>
<div class="tvd-access-manager-setting"></div>

View File

@@ -0,0 +1,13 @@
<div class="tvd-am-reset-default-modal">
<div class="title">
<?php echo __( 'Are you sure you want to reset the access options for the ', 'thrive-dash' ); ?>
<span class="role-name"></span>
<?php echo __( ' role?', 'thrive-dash' ); ?></div>
<div class="subtitle">
<?php dashboard_icon( 'info' ); ?>
<?php echo __( 'Please note that this cannot be undone', 'thrive-dash' ); ?></div>
<div class="buttons-wrapper">
<button class="click reset-button tvd-modal-close"><?php echo __( 'NO', 'thrive-dash' ); ?></button>
<button class="click reset-button tvd-modal-submit"><?php echo __( 'YES', 'thrive-dash' ); ?></button>
</div>
</div>

View File

@@ -0,0 +1,43 @@
<div class="tvd-am-container-header">
<h3 class="tvd-am-container-title"><?php echo esc_html__( 'User Access Manager', 'thrive-dash' ); ?></h3>
<div class="tvd-am-buttons-wrapper">
<a class="tvd-am-view-users click" target="_blank">
<?php dashboard_icon( 'users' ); ?>
<span><?php echo esc_html__( 'VIEW USERS', 'thrive-dash' ); ?></span>
</a>
<button class="tvd-am-reset-defaults click">
<?php dashboard_icon( 'sync-alt' ); ?>
<span><?php echo esc_html__( 'RESET DEFAULTS', 'thrive-dash' ); ?></span>
</button>
</div>
</div>
<div class="tvd-am-container-info">
<?php echo esc_html__( 'Edit which user roles have access to Thrive Themes plugins by enabling or disabling the checkboxes below.', 'thrive-dash' ); ?></div>
</div>
<h3 class="tvd-am-container-role"></h3>
<div class="tvd-am-container-sections">
<div class="tvd-am-section-wrapper tvd-am-products-cap-wrapper">
<div class="tvd-am-section-header">
<div class="tvd-am-section-title"><?php echo esc_html__( 'Products', 'thrive-dash' ); ?></div>
<div class="tvd-am-section-functionality"><?php echo esc_html__( 'HAS ACCESS', 'thrive-dash' ); ?></div>
</div>
<div class="tvd-am-section-content tvd-am-products-cap-content"></div>
</div>
<div class="tvd-am-section-wrapper tvd-am-functionality-wrapper">
<div class="tvd-am-section-header">
<div class="tvd-am-section-title"><?php echo esc_html__( 'Functionality', 'thrive-dash' ); ?></div>
<div class="tvd-am-section-functionality"><?php echo esc_html__( 'SETTING', 'thrive-dash' ); ?></div>
</div>
<div class="tvd-am-section-content tvd-am-functionality-content"></div>
</div>
<div id="tvd-back-td" class="tvd-col tvd-m6">
<a href="
<?php echo admin_url( 'admin.php?page=tve_dash_section' ); ?>" class="tvd-waves-effect tvd-waves-light tvd-btn-small tvd-btn-gray">
<?php echo __( 'Back To Dashboard', 'thrive-dash' ); ?>
</a>
</div>
</div>

View File

@@ -0,0 +1,2 @@
<div class="tvd-sidebar tvd-am-sidebar"></div>
<div class="tvd-am-container"></div>

View File

@@ -0,0 +1,22 @@
<div class="custom-redirect-select-wrapper tvd-page-selector" style="display:none;">
<div id="custom-page-info">
<p>
<?php echo __( 'Select a page using the field below. If no page is selected this setting will not remain active.', 'thrive-dash' ); ?>
</p>
</div>
<select id="tvd-am-custom-redirect"></select>
<div class="custom-page-options">
<span class="custom-page-title"></span>
<a class="view-page" target="_blank"><span class="tvd-icon-eye"></span><?php echo __( 'View', 'thrive-dash' ) ?></a>
<span class="tvd-sep"></span>
<button class="click open-remove-options"><span class="tvd-icon-delete"></span><?php echo __( 'Remove page', 'thrive-dash' ) ?></button>
</div>
</div>
<div class="custom-redirect-remove-page-wrapper" style="display: none">
<?php echo __( 'Are you sure you want to remove this login redirect page?', 'thrive-dash' ) ?>
<div class="remove-page-options">
<button class="click keep-page"><?php echo __( 'Keep this page', 'thrive-dash' ) ?></button>
<button class="click remove-page"><?php echo __( 'Remove this page', 'thrive-dash' ) ?></button>
</div>
</div>

View File

@@ -0,0 +1,16 @@
<div class="tvd-am-item-wrapper tvd-am-functionality-wrapper tvd-am-<#= model.getTag() #>">
<div class="tvd-am-item-icon tvd-am-functionality-icon">
<?php dashboard_icon( '<#= model.getIcon() #>' ); ?>
</div>
<div class="tvd-am-item-title tvd-am-functionality-title">
<#= model.getName()#>
</div>
<div>
<select class="tvd-am-functionality-select" data-functionality="<#= model.getTag() #>">
<# optionsTags.forEach((option, index) => {#>
<option value="<#= option #>"
<#= option === selectedValue ? 'selected=selected' : ''#>><#= optionsNames[index] #></option>
<#})#>
</select>
</div>
</div>

View File

@@ -0,0 +1,14 @@
<div class="tvd-am-item-wrapper tvd-am-product-wrapper">
<div class="tvd-am-item-icon tvd-am-product-icon">
<img src="<#= model.getLogo() #>" alt="" class="tvd-responsive-img">
</div>
<div class="tvd-am-item-title tvd-am-product-title">
<#= model.getName() #>
</div>
<div class="tvd-am-product-cap-wrapper">
<button class="tvd-am-product-cap click tvd-am-<#= canUse #> tvd-am<#= isEditable #>" data-cap="<#= model.getProductCapability() #>">
<?php dashboard_icon( '<#= canUse.concat(isEditable)#>' ); ?>
<div class="tvd-am-product-cap-tooltip"></div>
</button>
</div>
</div>

View File

@@ -0,0 +1,3 @@
<button class="click tvd-am-role<#= model.isActive() ? ' active' : ''#>" data-role="<#= model.getTag() #>">
<#= model.getName() #>
</button>

View File

@@ -0,0 +1,35 @@
<svg style="position: absolute; width: 0; height: 0; overflow: hidden;" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<svg id="icon-tve-dash-notification" width="40" height="41" viewBox="0 0 40 41" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle opacity="0.7" cx="20" cy="20.7935" r="20"/>
<rect x="10" y="10.7935" width="20" height="20" rx="1"/>
<path d="M30 25.0793H23.5135C23.5135 25.0793 23.5135 27.9365 20.2703 27.9365C17.027 27.9365 17.027 25.0793 17.027 25.0793H10"/>
</svg>
<svg id="icon-tve-dash-tar" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="1" y="1" width="14" height="14" rx="1" stroke="#879198" stroke-width="1.5"/>
<path d="M15 11H10.4595C10.4595 11 10.4595 13 8.18919 13C5.91892 13 5.91892 11 5.91892 11H1" stroke="#879198" stroke-width="1.5"/>
</svg>
<svg id="icon-tvd-notification-cross" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.8211 1.3415L10.6451 0.166504L5.98305 4.82484L1.32097 0.166504L0.14502 1.3415L4.80711 5.99984L0.14502 10.6582L1.32097 11.8332L5.98305 7.17484L10.6451 11.8332L11.8211 10.6582L7.159 5.99984L11.8211 1.3415Z" fill="currentColor"/>
</svg>
<svg id="icon-notification-type-error" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 2.00006C6.47 2.00006 2 6.47006 2 12.0001C2 17.5301 6.47 22.0001 12 22.0001C17.53 22.0001 22 17.5301 22 12.0001C22 6.47006 17.53 2.00006 12 2.00006ZM14.59 8.00006L12 10.5901L9.41 8.00006L8 9.41006L10.59 12.0001L8 14.5901L9.41 16.0001L12 13.4101L14.59 16.0001L16 14.5901L13.41 12.0001L16 9.41006L14.59 8.00006ZM4 12.0001C4 16.4101 7.59 20.0001 12 20.0001C16.41 20.0001 20 16.4101 20 12.0001C20 7.59006 16.41 4.00006 12 4.00006C7.59 4.00006 4 7.59006 4 12.0001Z" fill="currentColor"/>
</svg>
<svg id="icon-notification-type-info" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 2C6.48 2 2 6.48 2 12C2 17.52 6.48 22 12 22C17.52 22 22 17.52 22 12C22 6.48 17.52 2 12 2ZM12 20C7.59 20 4 16.41 4 12C4 7.59 7.59 4 12 4C16.41 4 20 7.59 20 12C20 16.41 16.41 20 12 20ZM10 14.17L16.59 7.58L18 9L10 17L6 13L7.41 11.59L10 14.17Z" fill="currentColor"/>
</svg>
<svg id="icon-notification-type-success" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 2C6.48 2 2 6.48 2 12C2 17.52 6.48 22 12 22C17.52 22 22 17.52 22 12C22 6.48 17.52 2 12 2ZM12 20C7.59 20 4 16.41 4 12C4 7.59 7.59 4 12 4C16.41 4 20 7.59 20 12C20 16.41 16.41 20 12 20ZM10 14.17L16.59 7.58L18 9L10 17L6 13L7.41 11.59L10 14.17Z" fill="currentColor"/>
</svg>
<svg id="icon-notification-type-warning" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.99 2.00012C6.47 2.00012 2 6.48012 2 12.0001C2 17.5201 6.47 22.0001 11.99 22.0001C17.52 22.0001 22 17.5201 22 12.0001C22 6.48012 17.52 2.00012 11.99 2.00012ZM13 13.0001V7.00012H11V13.0001H13ZM13 17.0001V15.0001H11V17.0001H13ZM4 12.0001C4 16.4201 7.58 20.0001 12 20.0001C16.42 20.0001 20 16.4201 20 12.0001C20 7.58012 16.42 4.00012 12 4.00012C7.58 4.00012 4 7.58012 4 12.0001Z" fill="currentColor"></path>
</svg>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,10 @@
module.exports = Backbone.Collection.extend( {
/**
* helper function to get the last item of a collection
*
* @return Backbone.Model
*/
last: function () {
return this.at( this.size() - 1 );
}
} );

View File

@@ -0,0 +1,6 @@
var NotificationModel = require( './../models/Notification' );
module.exports = Backbone.Collection.extend({
model: NotificationModel,
});

View File

@@ -0,0 +1,46 @@
module.exports = Backbone.Model.extend({
idAttribute: 'id',
defaults: {
active: {},
dismissed: {},
},
getDate: function () {
if (this.has('start') && this.get('start')) {
let startDate = new Date(this.get('start'));
let currentDate = new Date(TD_Notification?.date_time_now);
let timeDiff = currentDate.getTime() - startDate.getTime();
// Convert the difference to months, days, hours, or minutes
let yearsDiff = Math.floor(timeDiff / (1000 * 3600 * 24 * 365));
if (yearsDiff > 0) {
return yearsDiff + (yearsDiff === 1 ? " year ago" : " years ago");
}
let monthsDiff = Math.floor(timeDiff / (1000 * 3600 * 24 * 30));
if (monthsDiff > 0) {
return monthsDiff + (monthsDiff === 1 ? " month ago" : " months ago");
}
let daysDiff = Math.floor(timeDiff / (1000 * 3600 * 24));
if (daysDiff > 0) {
return daysDiff + (daysDiff === 1 ? " day ago" : " days ago");
}
let hoursDiff = Math.floor(timeDiff / (1000 * 3600));
if (hoursDiff > 0) {
return hoursDiff + (hoursDiff === 1 ? " hour ago" : " hours ago");
}
let minsDiff = Math.floor(timeDiff / (1000 * 60));
if (minsDiff > 0) {
return minsDiff + (minsDiff === 1 ? " minute ago" : " minutes ago");
}
return "just now";
} else {
return "";
}
}
});

View File

@@ -0,0 +1,131 @@
TD_Notification = TD_Notification || {};
// Import necessary modules
const NotificationDrawer = require( './views/NotificationDrawer' );
const NotificationsList = require( './views/NotificationsList' );
const NotificationCollection = require( './collections/Notifications' );
const FooterView = require( './views/NotificationFooter' );
( function ( $ ) {
$(document).ready(function () {
// Initialize variables
let notificationType = 'Active';
let notificationData = [];
let notificationListView = null;
let footerView = null;
// Function to render the UI
const renderUI = function () {
// Filter data based on notification type
const filteredData = notificationType === 'Active' ? TD_Notification?.data?.active : TD_Notification?.data?.dismissed;
// Count dismissed and active notifications
const dismissedCount = TD_Notification?.data?.dismissed?.length;
const activeCount = TD_Notification?.data?.active?.length;
if ( activeCount <= 0 ) {
$('.notification-indicator').parent().remove();
}
// Create a new collection with filtered data
const collection = new NotificationCollection( filteredData );
// Render NotificationDrawer
const notificationDrawer = new NotificationDrawer( {
el: $( '.td-app-notification-counter' ),
collection: collection,
activeCount,
dismissedCount
} );
notificationDrawer.render();
// Render NotificationsList
notificationListView = new NotificationsList( {
el: $('.td-app-notification-holder'),
collection,
notificationType,
dismissedCount,
activeCount,
} );
notificationListView.render();
footerView = new FooterView({
el: $('.notification-footer'),
collection: collection,
notificationType: notificationType,
hideDismissAll: notificationType === 'Dismissed' || activeCount < 2,
});
footerView.render();
// Event handler for collection change
notificationListView.on( 'collectionChanged', function ( data ) {
notificationData = data.collection.toJSON();
renderUI(); // Re-render UI with updated data
} );
footerView.on( 'collectionChanged', function ( data ) {
notificationData = data.collection.toJSON();
renderUI(); // Re-render UI with updated data
} );
// Event handler for notification type change
notificationListView.on( 'notificationTypeChanged', function ( data ) {
notificationType = data?.notification_type ? data?.notification_type : 'Active';
renderUI(); // Re-render UI with updated notification type
} );
$('.tve-notification').last().css('border-bottom', 'none')
};
window.render_ui = renderUI;
// Check visibility every 100 milliseconds
const interval = setInterval(function () {
if ($('.td-app-notification-counter').is(':visible')) {
// Render the UI for the first time
renderUI();
clearInterval(interval);
}
}, 100);
// Initial check in case the element is already visible when the script runs
if ($('.td-app-notification-counter').is(':visible')) {
renderUI();
clearInterval(interval);
}
const checkEmptyOrNot = setInterval(function () {
if ($('.td-app-notification-wrapper').is(':empty')) {
renderUI();
} else {
clearInterval(checkEmptyOrNot);
}
}, 100);
// Function to close the notification drawer
const closeNotificationDrawer = function () {
$( '.td-app-notification-overlay' ).addClass( 'close' );
$( '.td-app-notification-drawer' ).removeClass( 'open' );
};
// Event listener for Esc key press
$(document).on('keydown', function (e) {
if (e.key === 'Escape') {
closeNotificationDrawer();
}
});
const getUrlParameter = function(name) {
name = name.replace(/[\[\]]/g, '\\$&'); // Escape special characters for regex
const regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)');
const results = regex.exec(window.location.href);
if (!results) return null; // If no match is found
if (!results[2]) return ''; // If the parameter exists but no value is set
return decodeURIComponent(results[2].replace(/\+/g, ' '));
}
if ( getUrlParameter('notify') == 1 ) {
$( '.td-app-notification-overlay' ).removeClass( 'close' );
$( '.td-app-notification-drawer' ).addClass( 'open' );
}
});
} )( jQuery );

View File

@@ -0,0 +1,12 @@
/**
* Created by Russel Hussain on 4/29/2024.
*/
( function ( $ ) {
module.exports = Backbone.View.extend( {
render: function () {
return this;
}
} )
} )( jQuery );

View File

@@ -0,0 +1,47 @@
/**
* Created by Russel Hussain on 05/05/2024.
*/
( function ( $ ) {
const BaseView = require( './Base' );
module.exports = BaseView.extend( {
notificationType: 'Active',
translate: TD_Notification.t,
initialize: function ( options ) {
if (options && options.notificationType) {
this.notificationType = options.notificationType;
}
},
render: function () {
this.$el.html( this.getHtml() );
return this;
},
getHtml: function () {
let theme_class = TD_Notification.notify_class ? TD_Notification.notify_class : '';
let html = '<div class="no-notifications no-notifications-'+ theme_class +'">';
let notificationType = this.notificationType;
if ( notificationType === 'Active' ) {
html += '<img alt="Dannie the Detective" src="'+ TD_Notification?.image_url +'">' +
'<div class="great-scott great-scott-'+ theme_class +'">' + this.translate.no_new_title + '</div>' +
'<div class="no-new-notifications no-new-notification-'+ theme_class +'">' + this.translate.no_new + '</div>' +
'<span class="switch-notification-type toggle-to-dismissed switch-notification-type-'+ theme_class + '">' + this.translate.see_dismissed +'</span>';
}
if (notificationType === 'Dismissed') {
html += '<img alt="Dannie the Detective" src="'+ TD_Notification?.image_url +'">' +
'<div class="great-scott great-scott-'+ theme_class +'">' + this.translate.no_new_title + '</div>' +
'<div class="no-new-notifications no-new-notification-'+ theme_class +'">' + this.translate.no_dismissed + '</div>' +
'<span class="switch-notification-type toggle-to-active switch-notification-type-'+ theme_class +'">' + this.translate.see_new + '</span>';
}
html += '</div>';
return html;
}
} );
} )( jQuery );

View File

@@ -0,0 +1,111 @@
( function ( $ ) {
const BaseView = require( './Base' );
module.exports = BaseView.extend( {
render: function () {
this.$el.append( this.getHtml() );
return this;
},
getHtml: function () {
let theme_class = TD_Notification.notify_class ? TD_Notification.notify_class : '';
let html = '<div class="tve-notification notification-'+ theme_class +'">' +
'<div class="icon icon-'+ theme_class +'">' +
'<svg class="tve-circle-close type-' + this.model.get('type') + '" xmlns="http://www.w3.org/2000/svg">><use xlink:href="#icon-notification-type-' + this.model.get('type') + '"></use></svg>' +
'</div>' +
'<div class="body">' +
'<div class="title title-'+ theme_class +'">' +
'<div>' + this.model.get('title') + '</div>';
if (this.model.getDate()) {
html += '<div class="date date-'+ theme_class +'">' + this.model.getDate() + '</div>';
}
html += '</div>' +
'<div class="notification-content notification-content-'+ theme_class +'">' + this.addMediaPlayer(this.model.get('content')) + '</div>' +
'<div class="tvd-notification-actions">';
if ( this.model.get( 'button1_action' )) {
html += '<a type="button" class="tve-dash-button notify-primary notify-primary-'+ theme_class +'" href="' + this.model.get( 'button1_action' ) + '" target="_blank" rel="noopener noreferrer">' + this.model.get( 'button1_label' ) + '</a>';
}
if ( this.model.get( 'button2_action' ) ) {
html += '<a type="button" class="tve-dash-button notify-secondary notify-secondary-'+ theme_class +'" href="' + this.model.get( 'button2_action' ) + '" target="_blank" rel="noopener noreferrer">' + this.model.get( 'button2_label' ) + '</a>';
}
if ( this.model.get('dismissed') != 1 ) {
html += '<span class="dismiss-notification dismiss-notification-'+ theme_class +'" data-id="' + this.model.get('notification_id') + '">Dismiss</span>';
}
html += '</div>' +
'</div>' +
'</div>';
return html;
},
addMediaPlayer: function (content) {
content = content.replace(/&nbsp;/g, '<br>');
// Check for direct video links (mp4, webm, ogg)
const videoRegex = /(https?:\/\/\S+\.(mp4|webm|ogg))/gi;
if (videoRegex.test(content)) {
content = content.replace(videoRegex, (match, videoUrl) => {
return `<div class="notification-content-video-container"><video class="custom-video-player" controls>
<source src="${videoUrl}" type="video/mp4">
Your browser does not support the video tag.
</video></div>`;
});
}
// Check for YouTube links
const youtubeRegex = /(https?:\/\/(www\.)?youtube\.com\/watch\?v=[\w-]+|https?:\/\/youtu\.be\/[\w-]+)/gi;
if (youtubeRegex.test(content)) {
content = content.replace(youtubeRegex, (match, youtubeUrl) => {
const urlParams = new URLSearchParams(new URL(youtubeUrl).search);
const videoId = urlParams.get('v') || youtubeUrl.split('/').pop();
const embedUrl = `https://www.youtube.com/embed/${videoId}`;
return `<div class="notification-content-video-container"><iframe class="custom-iframe" src="${embedUrl}" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>`;
});
}
const youtubeFigureRegex = /<figure[^>]*>\s*<div[^>]*>\s*(https?:\/\/(www\.)?youtube\.com\/watch\?v=[\w-]+|https?:\/\/youtu\.be\/[\w-]+)\s*<\/div>\s*<\/figure>/gi;
content = content.replace(youtubeFigureRegex, (match, youtubeUrl) => {
const urlParams = new URLSearchParams(new URL(youtubeUrl).search);
const videoId = urlParams.get('v') || youtubeUrl.split('/').pop();
const embedUrl = `https://www.youtube.com/embed/${videoId}`;
return `<div class="notification-content-video-container"><iframe class="custom-iframe" src="${embedUrl}" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>`;
});
// Check for GIF images inside <a> tags
const gifInAnchorRegex = /<a[^>]*>\s*(https?:\/\/\S+\.(gif))\s*<\/a>/gi;
if (gifInAnchorRegex.test(content)) {
content = content.replace(gifInAnchorRegex, (match, gifUrl) => {
return `<div class="notification-content-image-container"><img class="custom-image-player" src="${gifUrl}" alt="GIF"></div>`;
});
}
// Check for image links (jpg, jpeg, png, gif)
const imageRegex = /(https?:\/\/\S+\.(jpg|jpeg|png|gif))/gi;
if (content.includes('<img')) {
return content;
}
if (imageRegex.test(content)) {
content = content.replace(imageRegex, (match, imageUrl) => {
return `<div class="notification-content-image-container"><img class="custom-image-player" src="${imageUrl}" alt="Image"></div>`;
});
}
const htmlTagRegex = /<\/?[a-z][\s\S]*>/i;
if (!htmlTagRegex.test(content)) {
content = content.replace(/\n/g, '<br>');
}
return content;
}
} );
} )( jQuery );

View File

@@ -0,0 +1,48 @@
(function ( $ ) {
const BaseView = require( './Base' );
module.exports = BaseView.extend( {
dismissedCount: 0,
activeCount: 0,
events: {
'click .tvd-notifications-btn': 'open',
'click .td-app-notification-counter-holder': 'open',
'click .text-notify-t-automator': 'open',
},
initialize: function ( options ) {
$( window ).on('scroll', this.adjustDrawerPosition.bind(this));
$( document ).on('click', this.handleDocumentClick.bind(this));
if ( options ) {
this.activeCount = options.activeCount;
this.dismissedCount = options.dismissedCount;
}
},
adjustDrawerPosition: function () {
const scrollTop = $( window ).scrollTop();
const newTop = 124 + scrollTop + 'px';
this.$( '.td-app-notification-drawer' ).css( 'top', newTop );
},
render: function () {
this.$( '.td-app-notification-counter-holder' ).text( this.activeCount );
this.activeCount >= 1 ? this.$( '.td-app-notification-counter-holder' ).show() : this.$( '.td-app-notification-counter-holder' ).hide();
return this;
},
open: function () {
$( '.td-app-notification-overlay' ).removeClass( 'close' );
$( '.td-app-notification-drawer' ).addClass( 'open' );
},
handleDocumentClick: function (event) {
if ( $(event.target).closest('.td-app-notification-overlay.overlay').length) {
$( '.td-app-notification-overlay' ).addClass( 'close' );
$( '.td-app-notification-drawer' ).removeClass( 'open' );
}
}
} );
} )( jQuery );

View File

@@ -0,0 +1,73 @@
( function ( $ ) {
const BaseView = require( './Base' );
module.exports = BaseView.extend( {
hideDismissAll: false,
events: {
'click .dismiss-all': 'dismissAll',
},
initialize: function ( options ) {
if ( options && options.hideDismissAll ) {
this.hideDismissAll = options.hideDismissAll;
}
this.listenTo( this.collection, 'change:dismiss-all', this.collectionChanged );
},
render: function () {
this.$el.html( this.getHtml() );
return this;
},
getHtml: function () {
let theme_class = TD_Notification.notify_class ? TD_Notification.notify_class : '';
let html = '<div class="pagination pagination-'+ theme_class +'"></div>' +
'<div class="dismiss-all dismiss-all-'+ theme_class +'">';
if ( !this.hideDismissAll ) {
html += '<span class="dismiss-all dismiss-all-'+ theme_class +'">Dismiss All</span>';
}
html += '</div>';
return html;
},
dismissAll: function () {
this.collection.each(function (item) {
const index = TD_Notification.data.active.findIndex(notification => notification.notification_id == item.get('notification_id'));
if (index !== -1) {
TD_Notification.data.active.splice(index, 1);
}
TD_Notification.data.dismissed.unshift(item.toJSON());
});
this.collectionChanged();
this.dismissAllNotification();
},
dismissAllNotification: function () {
$.ajax( {
type: 'POST',
url: TD_Notification.baseUrl + '/dismiss-all',
headers: {
'X-WP-Nonce': TD_Notification?.dismiss_nonce // Pass the nonce in the headers
},
success: function (response) {
// Handle success response
},
error: function (xhr, status, error) {
console.error('Error marking notification as read:', error);
}
} );
},
collectionChanged: function () {
this.trigger( 'collectionChanged', { notification_type: 'Active', collection: this.collection } );
}
});
} )( jQuery );

View File

@@ -0,0 +1,75 @@
( function ( $ ) {
let BaseView = require( './Base' );
module.exports = BaseView.extend( {
data: {
notification_type: 'Active',
notification_number: 0,
active_count: 0,
dismissed_count: 0
},
events: {
'click .toggle-to-dismissed': 'toggleNotification',
'click .toggle-to-active': 'toggleNotification'
},
initialize: function ( options ) {
if ( options ) {
this.data.active_count = options.activeCount;
this.data.dismissed_count = options.dismissedCount;
this.data.notification_type = options.notificationType;
}
if ( this.data.notification_type === 'Dismissed' ) {
this.collection.each( function ( item ) {
if ( item.get( 'dismissed' ) == 0 ) {
item.set( 'dismissed', 1 );
}
});
}
this.data.notification_number = this.collection.length;
},
render: function () {
this.$el.html( this.getHtml() );
return this;
},
getHtml: function () {
let html = '';
let theme_class = TD_Notification.notify_class ? TD_Notification.notify_class : '';
if ( this.data.notification_type === 'Active' ) {
html += '<span class="tvd-notification-number notification-number-'+ theme_class +'">(' + this.data.notification_number + ') New Notifications</span>';
} else if ( this.data.notification_type === 'Dismissed' ) {
html += '<span class="tvd-notification-number notification-number-'+ theme_class +'"> (' + this.data.notification_number + ') Notifications</span>';
}
html += '<div class="toggle-notifications">';
//If current tab is active and no of dismissed notification is zero, no need to show
if ( this.data.notification_type === 'Active' && this.data.dismissed_count > 0 ) {
html += '<span class="toggle-to-dismissed toggle-notifications toggle-'+ theme_class +'">Dismissed Notifications</span>';
}
//If Current tab is Dismissed should have option to go to active notification
if ( this.data.notification_type === 'Dismissed' ) {
html += '<span class="toggle-to-active toggle-notifications toggle-'+ theme_class +'">Active Notifications</span>';
}
html += '</div>';
html += '<span class="tvd-close-notification-drawer close-notification-'+ theme_class +'">';
html += '<svg class="icon-tve-dash-notification-cross"><use xlink:href="#icon-tvd-notification-cross"></use></svg>';
html += '</span>';
return html;
},
toggleNotification: function ( event ) {
const notificationType = $( event.currentTarget ).hasClass( 'toggle-to-dismissed' ) ? 'Dismissed' : 'Active';
if (this.data.notification_type !== notificationType) {
this.data.notification_type = notificationType;
this.trigger('notificationTypeChanged', { notification_type: notificationType });
}
event.stopPropagation();
}
} );
} )( jQuery );

View File

@@ -0,0 +1,149 @@
(function ( $ ) {
let BaseView = require('./Base');
let HeaderView = require('./NotificationHeader');
let FooterView = require('./NotificationFooter');
let NotificationView = require('./NotificationController');
let NoNotificationView = require('./NoNotification');
module.exports = BaseView.extend( {
headerView: null,
hideDismissAll: false,
notificationType: 'Active',
dismissedCount: 0,
activeCount: 0,
events: {
'click .tvd-close-notification-drawer': 'close',
'click .dismiss-notification': 'dismiss',
'click .switch-notification-type': 'toggleNotification',
},
initialize: function ( options ) {
if ( options ) {
this.activeCount = options.activeCount;
this.dismissedCount = options.dismissedCount;
this.hideDismissAll = options.notificationType === 'Dismissed' || this.activeCount < 2;
this.notificationType = options.notificationType;
}
this.listenTo( this.collection, 'change:dismiss', this.collectionChanged );
},
render: function () {
this.renderHeader();
const $wrapperContainer = this.$('.td-app-notification-wrapper');
if (this.collection.length > 0) {
$wrapperContainer.html('<div class="tvd-notifications-list"></div>');
this.renderList();
} else {
$wrapperContainer.empty();
new NoNotificationView( {
el: $wrapperContainer,
notificationType: this.notificationType
} ).render();
}
if ($wrapperContainer.find('.notification-footer').length === 0) {
this.renderFooter();
}
return this;
},
renderHeader: function () {
this.headerView = new HeaderView( {
el: this.$( '.td-app-notification-header' ),
collection: this.collection,
activeCount: this.activeCount,
dismissedCount: this.dismissedCount,
notificationType: this.notificationType
} ).render();
this.listenTo( this.headerView, 'notificationTypeChanged', this.notificationTypeChanged );
},
renderList: function () {
const $listContainer = this.$( '.tvd-notifications-list' );
$listContainer.empty();
// Instantiate NotificationView outside the loop
const notificationViews = this.collection.map(function(model) {
return new NotificationView({
model: model
});
});
// Render each NotificationView instance within the loop
notificationViews.forEach(function(notificationView) {
$listContainer.append(notificationView.render().el);
});
},
renderFooter: function () {
const $notificationFooter = $( '.notification-footer' );
$notificationFooter.empty();
new FooterView({
el: $notificationFooter,
collection: this.collection,
notificationType: this.notificationType,
hideDismissAll: this.hideDismissAll,
}).render();
},
toggleNotification: function ( event ) {
const notificationType = $( event.currentTarget ).hasClass( 'toggle-to-dismissed' ) ? 'Dismissed' : 'Active';
this.trigger('notificationTypeChanged', { notification_type: notificationType });
},
dismiss: function ( event ) {
event.preventDefault();
let notification_id = $( event.currentTarget ).data( 'id' );
let item = this.collection.findWhere( { notification_id: String(notification_id) } );
if ( item ) {
this.collection.remove(item);
const index = TD_Notification.data.active.findIndex(notification => notification.notification_id== notification_id);
if (index !== -1) {
TD_Notification.data.active.splice(index, 1);
}
TD_Notification.data.dismissed.unshift(item.toJSON());
this.dismissNotification( notification_id );
this.collectionChanged();
}
},
dismissNotification: function ( remoteId ) {
$.ajax( {
type: 'POST',
url: TD_Notification.baseUrl + '/dismiss',
headers: {
'X-WP-Nonce': TD_Notification?.dismiss_nonce // Pass the nonce in the headers
},
data: {
notification_id: remoteId,
},
success: function ( response ) {
// Handle success response
},
error: function (xhr, status, error) {
console.error('Error marking notification as read:', error);
}
} );
},
close: function () {
const notificationType = 'Active';
this.trigger('notificationTypeChanged', { notification_type: notificationType });
$( '.td-app-notification-overlay' ).addClass( 'close' );
$( '.td-app-notification-drawer' ).removeClass( 'open' );
},
collectionChanged: function () {
this.trigger( 'collectionChanged', { notification_type: 'Active', collection: this.collection } );
},
notificationTypeChanged: function ( data ) {
this.trigger( 'notificationTypeChanged', data );
}
} );
} )( jQuery );

View File

@@ -0,0 +1,278 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
if ( ! class_exists( 'App_Notification' ) ) {
class App_Notification {
protected $namespace = 'tve-dash/v1';
protected $class_path;
protected $base_path;
protected $template_path;
protected $current_page;
/**
* @var App_Notification
*/
public static $_instance;
/**
* App_Notification constructor.
*/
private function __construct() {
$this->base_path = dirname( dirname( __FILE__ ) );
$this->class_path = $this->base_path . '/classes';
$current_page = isset( $_GET['page'] ) ? $_GET['page'] : '';
$this->current_page = isset( $_GET['action'] ) ? $_GET['action'] : $current_page;
$this->template_path = $this->base_path . '/templates';
$this->_load();
$this->_hooks();
}
/**
* Singleton instance
*
* @return App_Notification
*/
public static function instance() {
if ( is_null( self::$_instance ) ) {
self::$_instance = new self();
}
return self::$_instance;
}
/**
* Enqueue notification scripts
*/
public function tve_dash_enqueue_notification_scripts() {
$limit = 10;
$offset = 0;
$js_prefix = tve_dash_is_debug_on() ? '.js' : '.min.js';
$notifications = ( new TD_Notifications )->check_notification();
$product_key = TD_Ian_Helper::get_product_name_by_page( $this->current_page );
$notify_class = TD_Ian_Helper::class_by_product( $product_key );
$image_url = TVE_DASH_URL . '/css/images/No-notifications-Thrive.png';
$params = array(
'baseUrl' => tva_get_rest_route_url( $this->namespace, 'app-notification' ),
't' => include $this->path( 'i18n.php' ),
'dash_url' => admin_url( 'admin.php?page=tve_dash_section' ),
'image_url' => $image_url,
'data' => $notifications,
'limit' => $limit,
'offset' => $offset + $limit,
'current_page' => $this->current_page,
'notify_class' => $notify_class,
'date_time_now' => current_time( 'Y-m-d H:i:s ' ),
'dismiss_nonce' => wp_create_nonce( 'wp_rest' ),
);
tve_dash_enqueue_style( 'tve_dash_app_notification',
TVE_DASH_URL . '/inc/app-notification/assets/css/tve-app-notification.css' );
tve_dash_enqueue_script( 'tve_dash_app_notification',
TVE_DASH_URL . '/inc/app-notification/assets/dist/tve-app-notification' . $js_prefix, array(
'jquery',
'backbone',
), TVE_DASH_VERSION, true );
tve_dash_admin_enqueue_scripts( 'tve_dash_app_notification' );
wp_enqueue_style( 'wp-block-library' );
wp_enqueue_style( 'wp-block-library-theme' );
wp_localize_script( 'tve_dash_app_notification', 'TD_Notification', $params );
}
/**
* Check if the current page is the editor
*
* @return bool
*/
private function isEditor() {
return 'architect' === $this->current_page;
}
private function is_ttb() {
return 'thrive-theme-dashboard' === $this->current_page;
}
/**
* Enqueue notification icons
*/
public function tve_dash_enqueue_notification_icons() {
$icon_file_path = TVE_DASH_PATH . '/inc/app-notification/assets/css/notification-icons.svg';
if ( file_exists( $icon_file_path ) ) {
include_once $icon_file_path;
}
}
/**
* Register REST routes
*/
public static function register_rest_routes() {
require_once dirname( __FILE__ ) . DIRECTORY_SEPARATOR . "Notification_Controller.php";
$notificationController = new TD_Notification_Controller();
$notificationController->register_routes();
}
/**
* Load required files
*
* @param string $path
*/
private function _load( $path = '' ) {
$path = $path ? $path : $this->class_path;
$dir = new DirectoryIterator( $path );
foreach ( $dir as $file ) {
if ( $file->isDot() ) {
continue;
}
if ( file_exists( $file->getPathname() ) && $file->isFile() ) {
require_once( $file->getPathname() );
}
}
// Run the migration if db tables are not created
TD_DbMigration::migrate();
if ( ! wp_next_scheduled( 'delete_expired_notice_daily' ) ) {
wp_schedule_event( time(), 'daily', 'delete_expired_notice_daily' );
}
add_action( 'delete_expired_notice_daily', [ $this, 'delete_expired_notices' ] );
}
public function delete_expired_notices() {
global $wpdb;
$current_time = current_time( 'Y-m-d H:i:s' );
$expired_notices_query = $wpdb->prepare( "
SELECT ID
FROM {$wpdb->prefix}td_app_notifications
WHERE end < %s
", $current_time );
$expired_notices = $wpdb->get_results( $expired_notices_query );
foreach ( $expired_notices as $notice ) {
$wpdb->delete( $wpdb->prefix . 'td_app_notifications', array( 'ID' => $notice->ID ) );
}
}
/**
* Get the full path to a file
*
* @param string $file
*
* @return string
*/
private function path( $file = '' ) {
return untrailingslashit( $this->base_path ) . ( ! empty( $file ) ? DIRECTORY_SEPARATOR : '' ) . ltrim( $file,
'\\/' );
}
/**
* Hook into WordPress actions and filters
*/
public function _hooks() {
add_filter( 'tve_dash_admin_product_menu', array( $this, 'add_to_dashboard_menu' ) );
if ( $this->isEditor() ) {
add_action( 'wp_loaded', array( $this, 'tve_dash_enqueue_notification_scripts' ) );
add_action( 'tcb_editor_iframe_after', array( $this, 'include_notification_icons_svg' ) );
} else {
add_action( 'admin_enqueue_scripts', array( $this, 'tve_dash_enqueue_notification_scripts' ) );
}
add_action( 'admin_enqueue_scripts', array( $this, 'tve_dash_enqueue_notification_icons' ) );
add_action( 'rest_api_init', array( $this, 'register_rest_routes' ) );
add_action( 'tvd_notification_inbox', array( $this, 'notification_button' ) );
}
public function include_notification_icons_svg() {
$file_path = TVE_DASH_PATH . '/inc/app-notification/assets/css/notification-icons.svg';
if ( file_exists( $file_path ) ) {
include $file_path;
}
}
public static function get_unread_count() {
global $wpdb;
$current_time = current_time( 'Y-m-d H:i:s' );
$unread_count = $wpdb->get_var(
$wpdb->prepare(
"SELECT COUNT(id) FROM {$wpdb->prefix}td_app_notifications WHERE dismissed = 0 AND start <= %s",
$current_time
)
);
if ( $unread_count > 99 ) {
$unread_count = '99+';
}
return $unread_count;
}
/**
* Add notifications to the dashboard menu
*
* @param array $menus
*
* @return array
*/
public function add_to_dashboard_menu( $menus = array() ) {
$count = static::get_unread_count();
if ( $count > 0 ) {
$menus['app_notifications'] = array(
'parent_slug' => 'tve_dash_section',
'page_title' => __( 'App Notification', 'thrive-dash' ),
'menu_title' => __( 'Notifications',
'thrive-dash' ) . '<span class="notification-indicator"></span>',
'capability' => TVE_DASH_CAPABILITY,
'menu_slug' => 'tve_dash_section&notify=1',
'function' => 'tve_dash_section',
);
} else {
unset( $menus['app_notifications'] );
}
return $menus;
}
/**
* Render the notification button
*
* @param bool $return
*
* @return string|void
*/
public function notification_button( $return = false ) {
$template = $this->template_path . '/app-notification-button.php';
ob_start();
if ( file_exists( $template ) ) {
include $template;
}
$html = ob_get_clean();
if ( $return ) {
return $html;
}
echo $html; // phpcs:ignore
}
}
}

View File

@@ -0,0 +1,56 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
class TD_DbMigration {
static $tableName = 'td_app_notifications';
public static function migrate() {
global $wpdb;
$charsetCollate = $wpdb->get_charset_collate();
$table = $wpdb->prefix . static::$tableName;
if ( $wpdb->get_var("SHOW TABLES LIKE '$table'") != $table ) {
$sql = "CREATE TABLE $table (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`slug` varchar(255) NOT NULL,
`title` text NOT NULL,
`content` longtext NOT NULL,
`type` varchar(64) NOT NULL,
`level` text NOT NULL,
`notification_id` bigint(20) unsigned DEFAULT NULL,
`notification_name` varchar(255) DEFAULT NULL,
`start` datetime DEFAULT NULL,
`end` datetime DEFAULT NULL,
`button1_label` varchar(255) DEFAULT NULL,
`button1_action` varchar(255) DEFAULT NULL,
`button2_label` varchar(255) DEFAULT NULL,
`button2_action` varchar(255) DEFAULT NULL,
`dismissed` tinyint(1) NOT NULL DEFAULT 0,
`created` datetime NOT NULL,
`updated` datetime NOT NULL,
PRIMARY KEY (id),
KEY ian_dates (start, end),
KEY ian_type (type),
KEY ian_dismissed (dismissed)
) $charsetCollate;";
dbDelta($sql);
}
$index_exists = $wpdb->get_results("SHOW INDEX FROM $table WHERE Key_name = 'ian_slug'");
if ($index_exists) {
$wpdb->query("ALTER TABLE $table DROP INDEX ian_slug");
}
// Make level column nullable
$level_exists = $wpdb->get_results("SHOW COLUMNS FROM $table LIKE 'level'");
if ($level_exists) {
$wpdb->query("ALTER TABLE $table MODIFY COLUMN `level` text DEFAULT NULL");
}
}
}

View File

@@ -0,0 +1,61 @@
<?php
class TD_Ian_Helper {
public static function product_list() {
return [
'tve_dash',// Thrive Dashboard
'thrive_automator',//Thrive Automator
'thrive_apprentice', //Thrive Apprentice
'tcm', // Thrive Comments
'tvo',// Thrive Ovation
'tab_admin_dashboard', // Thrive Optimize
'thrive_leads', // Thrive Leads
'tqb', // Thrive Quiz Builder
'tve_ult', //Thrive Ultimatum
'architect', //Thrive Architect
'thrive-theme-dashboard' //Thrive Theme Builder
];
}
public static function class_by_product( $product ) {
$classList = [
'tve_dash' => 'notify-td',
'thrive_automator' => 'notify-t-automator',
'thrive_apprentice' => 'notify-ta',
'tcm' => 'notify-tcm',
'tvo' => 'notify-tvo',
'tab_admin_dashboard' => 'notify-t-optimize',
'thrive_leads' => 'notify-thrive-leads',
'tqb' => 'notify-tqb',
'tve_ult' => 'notify-tve-ult',
'architect' => 'notify-tar',
'thrive-theme-dashboard' => 'notify-ttb'
];
return isset( $classList[ $product ] ) ? $classList[ $product ] : '';
}
public static function get_product_name_by_page( $page ) {
$products = self::product_list();
$product = "";
foreach ( $products as $p ) {
if ( strpos( $page, $p ) !== false ) {
$product = $p;
break;
}
}
return $product;
}
public static function get_user_product_ids() {
$user_license_details = thrive_get_transient( 'td_ttw_licenses_details' );
$user_products = [];
foreach ( $user_license_details as $license ) {
$user_products[] = $license['product_id'];
}
return $user_products;
}
}

View File

@@ -0,0 +1,104 @@
<?php
/**
* Notification Controller Class
*
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
if ( ! class_exists( 'TD_Notification_Controller' ) ) {
/**
* Notification Controller Class.
*
* @since 1.0.0
*/
class TD_Notification_Controller {
/**
* REST namespace for the controller.
*
* @since 1.0.0
* @var string
*/
const REST_NAMESPACE = 'tve-dash/v1';
/**
* Registers REST API routes for the controller.
*
* @since 1.0.0
*/
public function register_routes() {
register_rest_route( static::REST_NAMESPACE, 'app-notification/dismiss', array(
array(
'methods' => \WP_REST_Server::CREATABLE,
'callback' => array( $this, 'dismiss_notification' ),
'args' => array(
'notification_id' => array(
'type' => 'integer || string',
'required' => true,
)
),
'permission_callback' => function () {
return current_user_can( 'manage_options' );
},
),
) );
register_rest_route( static::REST_NAMESPACE, 'app-notification/dismiss-all', array(
array(
'methods' => \WP_REST_Server::CREATABLE,
'callback' => array( $this, 'dismiss_all_notification' ),
'permission_callback' => function () {
return current_user_can( 'manage_options' );
},
),
) );
}
/**
* Dismisses a notification.
*
* @param WP_REST_Request $request The request object.
*
* @return WP_REST_Response Response object indicating success or failure.
* @since 1.0.0
*
*/
public function dismiss_notification( $request ) {
require_once dirname( __FILE__ ) . DIRECTORY_SEPARATOR . "Notifications.php";
global $wpdb;
$notification_id = intval( $request->get_param( 'notification_id' ) );
$updated = $wpdb->update( $wpdb->prefix . 'td_app_notifications', [ 'dismissed' => 1 ],
[ 'notification_id' => $notification_id ] );
if ( ! $updated ) {
return new WP_REST_Response( array( 'success' => false ), 403 );
}
( new TD_Notifications() )->update_transients();
return new WP_REST_Response( array( 'success' => true ), 200 );
}
/**
* Dismisses all notifications.
*
* @return WP_REST_Response Response object indicating success or failure.
* @since 1.0.0
*
*/
public function dismiss_all_notification() {
require_once dirname( __FILE__ ) . DIRECTORY_SEPARATOR . "Notifications.php";
global $wpdb;
$wpdb->update( $wpdb->prefix . 'td_app_notifications', [ 'dismissed' => 1 ], [ 'dismissed' => 0 ] );
( new TD_Notifications() )->update_transients();
return new WP_REST_Response( array( 'success' => true ), 200 );
}
}
}

View File

@@ -0,0 +1,253 @@
<?php
class TD_Notifications {
private $_url;
private $_connection;
private $_request_params;
public function __construct() {
$this->_connection = TD_TTW_Connection::get_instance();
$this->_request_params = [
'user_id' => $this->_connection->ttw_id,
'user_email' => $this->_connection->ttw_email,
'last_notification_id' => get_option( 'td_last_notification_id' ),
];
$this->_url = TD_TTW_Connection::get_ttw_url() . '/wp-content/notifications.json';
}
public function handle_notifications() {
if ( $this->is_transients_exist() ) {
return;
}
$notifications = $this->get( $this->_request_params );
if ( ! $notifications || ! is_array( $notifications ) || is_wp_error( $notifications ) ) {
return;
}
foreach ( $notifications as $notification ) {
if ( $this->is_exist( $notification['notification_id'] ) || ( isset( $notification['end'] ) && $this->is_expired( $notification['end'] ) ) ) {
continue;
}
$this->add_notification( $notification );
}
}
public function check_notification() {
$this->handle_notifications();
$notifications = $this->get_notification();
return $notifications;
}
private function get_notification( $update_call = false ) {
global $wpdb;
$table_name = $wpdb->prefix . 'td_app_notifications';
$current_time = current_time( 'Y-m-d H:i:s' );
if ( $this->is_transients_exist() && ! $update_call ) {
return get_transient( 'td_app_notifications_transients' );
}
$active_notifications_query = $wpdb->prepare(
"SELECT * FROM $table_name
WHERE start <= %s
AND (end IS NULL OR end >= %s)
AND dismissed = 0
ORDER BY start DESC",
$current_time, $current_time
);
$active_notifications = $wpdb->get_results( $active_notifications_query, ARRAY_A );
$dismissed_notifications_query = $wpdb->prepare( " SELECT *
FROM $table_name
WHERE dismissed = 1
AND (end IS NULL OR end >= %s)
ORDER BY start DESC
", $current_time );
$dismissed_notifications = $wpdb->get_results( $dismissed_notifications_query, ARRAY_A );
if ( ! $active_notifications && ! $dismissed_notifications ) {
return false;
}
$notifications = [
'active' => $active_notifications,
'dismissed' => $dismissed_notifications
];
if ( ! $update_call ) {
$this->store_transients( $notifications );
}
return $notifications;
}
private function add_notification( $notification ) {
if ( ! $notification || ! is_array( $notification ) || empty( $notification ) ) {
return false;
}
if ( isset( $notification['have_license'] ) && is_array( $notification['have_license'] ) ) {
if ( ! $this->verify_access( $notification['have_license'], $notification['dont_have_license'] ) ) {
return;
}
}
global $wpdb;
$table_name = $wpdb->prefix . 'td_app_notifications';
if ( isset( $notification['btns'] ) ) {
foreach ( $notification['btns'] as $key => $value ) {
if ( $key === 'main' ) {
$notification['button1_label'] = sanitize_text_field( $value['text'] );
$notification['button1_action'] = esc_url_raw( $value['url'] );
}
if ( $key === 'alt' ) {
$notification['button2_label'] = sanitize_text_field( $value['text'] );
$notification['button2_action'] = esc_url_raw( $value['url'] );
}
}
}
if ( isset( $notification['btns'] ) ) {
unset( $notification['btns'] );
}
unset( $notification['have_license'] );
unset( $notification['dont_have_license'] );
$additional_data = [
'created' => current_time( 'Y-m-d H:i:s' ),
'updated' => current_time( 'Y-m-d H:i:s' ),
];
$notification = array_merge( $notification, $additional_data );
$last_notification_id = get_option( 'td_last_notification_id', 0 );
if ( isset( $notification['notification_id'] ) && $last_notification_id < $notification['notification_id'] ) {
update_option( 'td_last_notification_id', $notification['notification_id'] );
}
$wpdb->insert( $table_name, $notification );
}
private function verify_access( $have_license, $dont_have_license ) {
if ( ! is_array( $have_license ) && ! is_array( $dont_have_license ) ) {
return true;
}
$user_products = TD_Ian_Helper::get_user_product_ids();
if ( ! empty( $have_license ) && ! empty( $dont_have_license ) ) {
$has_any_license = ! empty( array_intersect( $user_products, $have_license ) );
$has_no_restricted_license = empty( array_intersect( $user_products, $dont_have_license ) );
return $has_any_license || $has_no_restricted_license;
}
if ( ! empty( $have_license ) ) {
return ! empty( array_intersect( $user_products, $have_license ) );
}
if ( ! empty( $dont_have_license ) ) {
return ! empty( array_intersect( $user_products, $dont_have_license ) );
}
return true;
}
// Check if the notification is already expired or not
private function is_expired( $end ) {
if ( ! $end || empty( $end ) ) {
return false;
}
$current_time = strtotime( current_time( 'Y-m-d H:i:s' ) );
return $current_time > strtotime( $end );
}
// Retrieve data from the server using the REST API
private function get( $args = [] ) {
$request_params = [
'body' => $args,
'headers' => [
'Content-Type' => 'application/json',
],
'timeout' => 30,
'sslverify' => false,
];
$notifications = wp_remote_get( $this->_url, $request_params );
if ( is_wp_error( $notifications ) ) {
return [];
}
$response_code = wp_remote_retrieve_response_code( $notifications );
if ( $response_code != 200 ) {
return [];
}
if ( is_wp_error( $notifications ) ) {
return false;
}
$notifications = json_decode( wp_remote_retrieve_body( $notifications ), true );
if ( ! is_array( $notifications ) ) {
return [];
}
return $notifications;
}
// Check if the notification already exists in the database
private function is_exist( $notification_id ) {
global $wpdb;
$table_name = $wpdb->prefix . 'td_app_notifications';
$notification = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $table_name WHERE notification_id = %d",
$notification_id ) );
if ( $notification ) {
return true;
}
return false;
}
// Check if the transients already exist
private function is_transients_exist() {
$transient_name = 'td_app_notifications_transients';
$transient = get_transient( $transient_name );
if ( $transient ) {
return true;
}
return false;
}
// Store the transients
private function store_transients( $notifications ) {
if ( ! $notifications || ! is_array( $notifications ) || is_wp_error( $notifications ) ) {
return;
}
set_transient( 'td_app_notifications_transients', $notifications, time() + DAY_IN_SECONDS );
}
public function update_transients() {
$this->store_transients( $this->get_notification( true ) );
}
}

View File

@@ -0,0 +1,19 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
return array(
'Notifications' => __( 'Notifications', 'thrive-dash' ),
'no_new_title' => __( 'Great Scott! Where\'d they all go?', 'thrive-dash' ),
'no_new' => __( 'You have no new notifications.', 'thrive-dash' ),
'no_dismissed' => __( 'You have no dismissed notifications.', 'thrive-dash' ),
'see_dismissed' => __( 'See Dismissed Notifications', 'thrive-dash' ),
'see_new' => __( 'See New Notifications', 'thrive-dash' ),
);

View File

@@ -0,0 +1,29 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
$product_key = TD_Ian_Helper::get_product_name_by_page( $this->current_page );
$dom_class = TD_Ian_Helper::class_by_product( $product_key );
$class = "td-app-notification-counter";
if ( $this->current_page === 'tcm_admin_dashboard' ) {
$class .= " tvd-right";
}
?>
<li class="<?php echo $class?>">
<span id="tvd-notifications-btn ian-notification" class="tvd-notifications-btn ian-icon-<?php echo $dom_class?>">
<span class="td-app-notification-counter-holder" style="display: none;"></span>
<svg width="20" height="20" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="1" y="0.793457" width="20" height="20" rx="1" stroke="#12394A" stroke-width="1.5"/>
<path d="M21 15.0793H14.5135C14.5135 15.0793 14.5135 17.9365 11.2703 17.9365C8.02703 17.9365 8.02703 15.0793 8.02703 15.0793H1" stroke="#12394A" stroke-width="1.5"/>
</svg>
</span>
</li>

View File

@@ -0,0 +1,18 @@
( function ( $ ) {
const $document = $( document );
$document.on( 'heartbeat-tick.wp-auth-check', function ( e, data ) {
if ( 'wp-auth-check' in data && ! data[ 'wp-auth-check' ] ) {
/* when opening the auth iframe popup, add our user key field so we can identify him */
setTimeout( function () {
$( '#wp-auth-check-frame' ).off( 'load.tvd' ).on( 'load.tvd', function () {
$( '#wp-auth-check-frame' ).contents().find( 'form#loginform' ).append( '<input type="hidden" name="tvd_auth_check_user_key" value="' + tvd_auth_check.userkey + '">' );
} );
} )
}
} );
/* after login, trigger and event on the document where other plugins can listen */
window.tvd_after_auth = function ( data ) {
$document.trigger( 'tvd_after_auth', data );
}
} )( jQuery );

View File

@@ -0,0 +1,115 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Class Tvd_Auth_Check
*/
class Tvd_Auth_Check {
/**
* Tvd_Auth_Check constructor.
*/
public function __construct() {
/**
* Actions used for handling the interim login ( login via popup in Thrive Theme Dashboard )
*/
add_action( 'login_footer', array( $this, 'login_footer' ) );
add_action( 'set_logged_in_cookie', array( $this, 'set_logged_in_cookie' ), 10, 4 );
add_action( 'admin_enqueue_scripts', array( __CLASS__, 'auth_enqueue_scripts' ) );
}
public static function auth_enqueue_scripts() {
tve_dash_enqueue_script( 'tvd-auth-check', TVE_DASH_URL . '/inc/auth-check/auth-check.js' );
wp_localize_script( 'tvd-auth-check', 'tvd_auth_check', array( 'userkey' => static::generate_editor_key() ) );
}
/**
* Generate a new editor key for the user and save it
*
* @return bool|string
*/
public static function generate_editor_key() {
if ( ! $id = get_current_user_id() ) {
return false;
}
$key = wp_create_nonce( 'tcb_editor_key' );
update_user_meta( $id, 'tcb_edit_key', $key );
return $key;
}
/**
* get the current editor key for the user
*
* @param mixed $id
*
* @return bool|mixed
*/
public function get_user_editor_key( $id ) {
if ( ! $id && ! ( $id = get_current_user_id() ) ) {
return null;
}
return get_user_meta( $id, 'tcb_edit_key', true );
}
public function login_footer() {
global $interim_login;
if ( empty( $interim_login ) || $interim_login !== 'success' || empty( $_POST ) || empty( $_POST['tvd_auth_check_user_key'] ) || empty( $this->tvd_interim_user_id ) ) {
return;
}
/**
* Problem: during the login POST, after login, the user does not seem to be actually available
*/
$user_id = $this->tvd_interim_user_id;
/**
* This is used to correctly re-generate the nonce
*/
$_COOKIE[ LOGGED_IN_COOKIE ] = $this->tvd_interim_login_cookie;
$user_key = $this->get_user_editor_key( $user_id );
wp_set_current_user( $user_id );
if ( $user_key === $_POST['tvd_auth_check_user_key'] ) {
/* pass data that we need after the login auth */
$data = apply_filters( 'tvd_auth_check_data', array(
'rest_nonce' => wp_create_nonce( 'wp_rest' ),
) );
include 'handle-login.php';
}
}
/**
* Helper function to store the actual value of the logged in cookie during the login process stared from the dashboard
*
* @param string $logged_in_cookie The logged-in cookie.
* @param int $expire The time the login grace period expires as a UNIX timestamp.
* Default is 12 hours past the cookie's expiration time.
* @param int $expiration The time when the logged-in authentication cookie expires as a UNIX timestamp.
* Default is 14 days from now.
* @param int $user_id User ID.
*/
public function set_logged_in_cookie( $logged_in_cookie, $expire, $expiration, $user_id ) {
global $interim_login;
if ( ! empty( $interim_login ) && ! empty( $_POST ) && ! empty( $_POST['tvd_auth_check_user_key'] ) ) {
$this->tvd_interim_user_id = $user_id;
$this->tvd_interim_login_cookie = $logged_in_cookie;
}
}
}
new Tvd_Auth_Check();

View File

@@ -0,0 +1,21 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
?>
<script type="text/javascript">
if ( window.parent && window.parent.tvd_auth_check ) {
if ( window.parent.tvd_auth_check.userkey === <?php echo json_encode( $user_key ) ?> ) {
window.parent.tvd_after_auth( <?php echo json_encode( $data ) ?> );
}
}
</script>

View File

@@ -0,0 +1,364 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
add_action( 'admin_menu', 'tve_dash_api_admin_menu', 20 );
add_action( 'admin_enqueue_scripts', 'tve_dash_api_admin_scripts' );
add_action( 'admin_notices', 'tve_dash_api_admin_notices', 9 );
add_action( 'wp_ajax_tve_dash_api_form_retry', 'tve_dash_api_form_retry' );
add_action( 'wp_ajax_tve_dash_api_delete_log', 'tve_dash_api_delete_log' );
if ( wp_doing_ajax() ) {
add_action( 'wp_ajax_tve_dash_api_handle_save', 'tve_dash_api_handle_save' );
add_action( 'wp_ajax_tve_dash_api_handle_redirect', 'tve_dash_api_api_handle_redirect' );
} else {
add_action( 'admin_init', 'tve_dash_api_handle_save' );
}
/*
* TTW API Videos URLs
*/
if ( is_admin() ) {
add_action( 'current_screen', 'tve_api_video_urls' );
}
/**
* Run on dash api connect screen
* Build transient from TTW API with videos URLs
*/
function tve_api_video_urls() {
if ( tve_get_current_screen_key() === 'admin_page_tve_dash_api_connect' ) {
require_once __DIR__ . '/classes/ApiVideos.php';
$api_videos = new ApiVideos();
}
}
/**
* FILTERS
*/
add_filter( 'tve_dash_localize', 'tve_dash_api_filter_localize' );
add_filter( 'tve_dash_include_ui', 'tve_dash_api_filter_ui_hooks' );
function tve_dash_api_admin_menu() {
remove_submenu_page( 'thrive_admin_options', 'thrive_font_manager' );
add_submenu_page( '', __( 'API Connections', 'thrive-dash' ), __( 'API Connections', 'thrive-dash' ), TVE_DASH_CAPABILITY, 'tve_dash_api_connect', 'tve_dash_api_connect' );
add_submenu_page( '', __( 'API Connections Error Log', 'thrive-dash' ), __( 'API Connections Error Log', 'thrive-dash' ), TVE_DASH_CAPABILITY, 'tve_dash_api_error_log', 'tve_dash_api_error_log' );
}
/**
* check for any expired connections (expired access tokens), or tokens that are about to expire and display global warnings / error messages
*/
function tve_dash_api_admin_notices() {
if ( tve_get_current_screen_key( 'base' ) === 'admin_page_tve_dash_api_connect' ) {
return;
}
require_once __DIR__ . '/misc.php';
$connected_apis = Thrive_Dash_List_Manager::get_available_apis( true );
$warnings = array();
foreach ( $connected_apis as $api_instance ) {
if ( ! $api_instance instanceof Thrive_Dash_List_Connection_Abstract || $api_instance->param( '_nd' ) ) {
continue;
}
$warnings = array_merge( $warnings, $api_instance->get_warnings() );
}
$nonce = sprintf( '<span class="nonce" style="display:none">%s</span>', wp_create_nonce( 'tve_api_dismiss' ) );
$template = '<div class="%s notice is-dismissible tve-api-notice"><p>%s</p>%s</div>';
$html = '';
foreach ( $warnings as $err ) {
$html .= sprintf( $template, 'error', $err, $nonce );
}
echo $html; // phpcs:ignore
}
/**
* main entry point
*/
function tve_dash_api_connect() {
require_once __DIR__ . '/misc.php';
$available_apis = Thrive_Dash_List_Manager::get_available_apis();
foreach ( $available_apis as $key => $api ) {
/** @var Thrive_Dash_List_Connection_Abstract $api */
if ( $api->is_connected() || $api->is_related() ) {
unset( $available_apis[ $key ] );
}
}
$connected_apis = Thrive_Dash_List_Manager::get_available_apis( true );
foreach ( $connected_apis as $key => $api ) {
if ( ! $api instanceof Thrive_Dash_List_Connection_Abstract || $api->is_related() ) {
unset( $connected_apis[ $key ] );
}
}
$api_types = Thrive_Dash_List_Manager::$API_TYPES;
$api_types = apply_filters( 'tve_filter_api_types', $api_types );
$types = array();
foreach ( $api_types as $type => $label ) {
$types[] = array(
'type' => $type,
'label' => $label,
);
}
Thrive_Dash_List_Manager::flash_messages();
include __DIR__ . '/views/admin-list.php';
}
/**
* check to see if we currently need to save some credentials, early in the admin section (e.g. a redirect from Oauth)
*/
function tve_dash_api_handle_save() {
if ( ! current_user_can( TVE_DASH_CAPABILITY ) ) {
wp_die( '' );
}
require_once __DIR__ . '/misc.php';
$is_google_drive_response = ! empty( $_REQUEST['state'] ) && strpos( sanitize_text_field( $_REQUEST['state'] ), 'connection_google_drive' ) === 0;
$is_constant_contact_v3_response = ! empty( $_REQUEST['state'] ) && strpos( sanitize_text_field( $_REQUEST['state'] ), 'connection_constant_contact_v3' ) === 0;
/**
* either a POST from a regular form, or an oauth redirect
*/
if (
( ( ! $is_google_drive_response && empty( $_REQUEST['api'] ) && empty( $_REQUEST['oauth_token'] ) && empty( $_REQUEST['disconnect'] ) )
&& ( ( ! $is_constant_contact_v3_response && empty( $_REQUEST['api'] ) && empty( $_REQUEST['oauth_token'] ) && empty( $_REQUEST['disconnect'] ) ) ) )
) {
return;
}
if ( $is_google_drive_response ) {
$api = 'google_drive';
} elseif ( $is_constant_contact_v3_response ) {
$api = 'constantcontact_v3';
} else {
$api = sanitize_text_field( $_REQUEST['api'] );
}
$doing_ajax = defined( 'DOING_AJAX' ) && DOING_AJAX;
$connection = Thrive_Dash_List_Manager::connection_instance( $api );
if ( is_null( $connection ) ) {
return;
}
$response = array(
'success' => false,
'message' => __( 'Unknown error occurred', 'thrive-dash' ),
);
if ( ! empty( $_REQUEST['disconnect'] ) ) {
$connection->disconnect()->success( $connection->get_title() . ' ' . __( 'is now disconnected', 'thrive-dash' ) );
//delete active conection for thrive ovation
$active_connection = get_option( 'tvo_api_delivery_service', false );
if ( $active_connection && $active_connection == $api ) {
delete_option( 'tvo_api_delivery_service' );
}
tve_dash_remove_api_from_one_click_signups( $api );
$response['success'] = true;
$response['message'] = __( 'Service disconnected', 'thrive-dash' );
} elseif ( ! empty( $_REQUEST['test'] ) ) {
$result = $connection->test_connection();
if ( is_array( $result ) && isset( $result['success'] ) && ! empty( $result['message'] ) ) {
$response = $result;
} else {
$response['success'] = is_string( $result ) ? false : $result;
$response['message'] = $response['success'] ? __( 'Connection works', 'thrive-dash' ) : __( 'Connection Error', 'thrive-dash' );
}
} else {
$saved = $connection->read_credentials();
$response['success'] = $saved === true;
$response['message'] = $saved === true ? __( 'Connection established', 'thrive-dash' ) : $saved;
}
/* Check if we need to upgrade an api */
if ( ! empty( $_REQUEST['api'] ) ) {
$upgraded_key = $_REQUEST['api'] . '-upgraded';
if ( ! empty( $_REQUEST[ $upgraded_key ] ) && $_REQUEST[ $upgraded_key ] === '1' && method_exists( $connection, 'upgrade' ) ) {
$response = $connection->upgrade();
}
}
if ( $doing_ajax ) {
exit( json_encode( $response ) );
}
$admin_url = admin_url( 'admin.php?page=tve_dash_api_connect' );
if ( $response['success'] !== true ) {
update_option( 'tve_dash_api_error', $response['message'] );
wp_redirect( $admin_url . '#failed/' . $api );
exit;
}
wp_redirect( $admin_url . '#done/' . $api );
exit();
}
/**
* Handles the creation of the authorization URL and redirection to that url for token generation purposes
*/
function tve_dash_api_api_handle_redirect() {
if ( ! current_user_can( TVE_DASH_CAPABILITY ) ) {
wp_die( '' );
}
if ( empty( $_REQUEST['api'] ) && empty( $_REQUEST['oauth_token'] ) && empty( $_REQUEST['disconnect'] ) ) {
return;
}
$doing_ajax = defined( 'DOING_AJAX' ) && DOING_AJAX;
require_once __DIR__ . '/misc.php';
$connection = Thrive_Dash_List_Manager::connection_instance( sanitize_text_field( $_REQUEST['api'] ) );
if ( is_null( $connection ) ) {
return;
}
$response = array(
'success' => false,
'message' => __( 'Unknown error occurred', 'thrive-dash' ),
);
$credentials = ! empty( $_POST['connection'] ) ? map_deep( $_POST['connection'], 'sanitize_text_field' ) : array();
$connection->set_credentials( $credentials );
$result = $connection->getAuthorizeUrl();
$response['success'] = ! ( ( filter_var( $result, FILTER_VALIDATE_URL ) ) === false );
$response['message'] = ! $response['success'] ? 'An unknown error has occurred' : $result;
if ( $doing_ajax ) {
exit( json_encode( $response ) );
}
wp_redirect( admin_url( 'admin.php?page=tve_dash_api_connect' ) . '#failed/' . sanitize_text_field( $_REQUEST['api'] ) );
exit();
}
/**
* Enqueue specific scripts for api connections page
*
* @param string $hook
*/
function tve_dash_api_admin_scripts( $hook ) {
$accepted_hooks = array(
'admin_page_tve_dash_api_connect',
'admin_page_tve_dash_api_error_log',
);
if ( ! in_array( $hook, $accepted_hooks ) ) {
return;
}
if ( $hook === 'admin_page_tve_dash_api_error_log' ) {
tve_dash_enqueue_script(
'tve-dash-api-admin-logs',
TVE_DASH_URL . '/inc/auto-responder/dist/admin-logs-list.min.js',
array(
'tve-dash-main-js',
'jquery',
'backbone',
)
);
return;
}
/**
* global admin JS file for notifications
*/
tve_dash_enqueue_script(
'tve-dash-api-admin-global',
TVE_DASH_URL . '/inc/auto-responder/dist/admin-global.min.js',
array(
'tve-dash-main-js',
'jquery',
'backbone',
)
);
$api_response = array(
'message' => get_option( 'tve_dash_api_error' ),
);
if ( ! empty( $api_response['message'] ) ) {
wp_localize_script( 'tve-dash-api-admin-global', 'tve_dash_api_error', $api_response );
delete_option( 'tve_dash_api_error' );
}
}
/**
* for now, just a dump of the error logs from the table
*/
function tve_dash_api_error_log() {
include plugin_dir_path( __FILE__ ) . 'views/admin-error-logs.php';
}
/**
* hide notices for a specific API connection
*/
function tve_dash_api_hide_notice() {
if ( ! empty( $_POST['nonce'] ) && ! wp_verify_nonce( sanitize_text_field( $_POST['nonce'] ), 'tve_api_dismiss' ) ) {
exit( '-1' );
}
$key = ! empty( $_POST['key'] ) ? sanitize_text_field( $_POST['key'] ) : '';
require_once __DIR__ . '/misc.php';
$connection = Thrive_Dash_List_Manager::connection_instance( $key );
$connection->set_param( '_nd', 1 )->save();
exit( '1' );
}
/**
* remove api connection from one click signups (new name: Signup Segue)
*/
function tve_dash_remove_api_from_one_click_signups( $api_name ) {
$one_click_signups = get_posts( array( 'post_type' => 'tve_lead_1c_signup' ) );
foreach ( $one_click_signups as $item ) {
$connections = get_post_meta( $item->ID, 'tve_leads_api_connections', true );
foreach ( $connections as $j => $connection ) {
if ( $connection['apiName'] == $api_name ) {
unset( $connections[ $j ] );
}
}
update_post_meta( $item->ID, 'tve_leads_api_connections', $connections );
}
}
function tve_dash_api_filter_localize( $localize ) {
$localize['actions']['api_handle_save'] = 'tve_dash_api_handle_save';
$localize['actions']['api_handle_redirect'] = 'tve_dash_api_handle_redirect';
return $localize;
}
function tve_dash_api_filter_ui_hooks( $hooks ) {
//this hook includes the general scripts from dash
//$hooks[] = 'admin_page_tve_dash_api_error_log';
return $hooks;
}

View File

@@ -0,0 +1,12 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
require_once( dirname( __FILE__ ) . '/admin.php' );

View File

@@ -0,0 +1,210 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class ApiVideos {
/**
* @var string
*/
private $_ttw_api_url_transient = 'ttw_api_urls';
/**
* @var string
*/
private $_ttw_url;
/**
* Transient lifetime [1 day in seconds]
*
* @var int
*/
protected $_cache_life_time = 86400;
/**
* Used for obfuscation
*
* @var array
*/
private $_randomize
= array(
'a' => 'F',
'b' => 'g',
'c' => 'R',
'd' => '6j',
'e' => 'k9t',
'f' => '#U',
'g' => 'x',
'h' => 'E',
'i' => '_',
'j' => '6',
'k' => '^',
'l' => 'Y',
'm' => '7hI',
'n' => 'm',
'o' => 'pI',
'u' => '5',
'1' => '2W7',
'2' => 'g',
'9' => 'T',
'5' => '3',
':' => 'p',
'/' => 'u',
't' => 'I',
'p' => 'o',
'x' => 'a',
'y' => 'e',
'z' => 'i',
'w' => 'u',
'6' => 'h',
'U' => 't',
'89' => '/',
);
/**
* Used in case of TTW API call failed [/api_videos endpoint]
*
* @var array
*/
private $_fallback_urls
= array(
'mailchimp' => 'ndkVpoJCffU',
'aweber' => 'lBybVnifWw4',
'getresponse' => 'G0IMbKP1Otw',
'mailpoet' => 'bkVO6nqyClA',
'wordpress' => 'KMqwr6OT3DA',
'ontraport' => '6AwBXF8w85o',
'everwebinar' => 'Oy7AutRjWHE',
'icontact' => 'sjWGb3UdvN4',
'convertkit' => 'nPDX_a7_pAM',
'activecampaign' => 'z27CqJQtrvQ',
'sendy' => 'jHP6u3rqoF0',
'drip' => 'MnujttxYH-M',
'constantcontact' => 'a1y_GJcUwO4',
'madmimi' => 'OXQzK9uSzsA',
'webinarjamstudio' => 'y7Rz0l794DE',
'gotowebinar' => '2NkRXez97p0',
'hubspot' => 'gqjp4-hTJdc',
'postmark' => 'k8l-KeObrwk',
'infusionsoft' => 'Ak4tLh29aC4',
'recaptcha' => '4LM0cIIhOVA',
'sparkpost' => 'HCsuzWcYq4I',
'mailgun' => 'DBNW6hGWYyc',
'awsses' => 'eC35eUXqlHw',
'mailerlite' => 'OKigVCbG0YE',
'campaignmonitor' => 'wbPX2bXUNxA',
'facebook' => 'jR4tBDEuwE4',
'google' => 'YZ2eeWBJQ5w',
'twitter' => '9_pkwfTrTPc',
'mailrelay' => 'gLlRZ1wdIjM',
'sendgrid' => 'sLfWAgEE_fo',
'sendinblue' => 'tZ8Pp7WJnzk',
'sgautorepondeur' => 'N3zqX5dprUc',
'sendlane' => 'aqtKcGSJaog',
'google_drive' => 'LNCiLKxo7V4',
'dropbox' => '-zYbSNvp2JQ',
'fluentcrm' => 'AFfuQrv--S4',
'slack' => 'IeRaTyBLu9s',
'sendowl' => 'cN1UGZ3Vblo',
'zapier' => 'iD2-RsTflPU',
'sendfox' => 'VOQCwapziqs',
'zoho' => '50j3THWW7sQ',
'klicktipp' => 'MBzZNteFSz4',
);
/**
* ApiVideos constructor.
*/
public function __construct() {
// URLs based on env
$this->_set_urls();
// Check and set api videos URLs transient and call TTW API for them
$this->_check_videos_transient();
}
/**
* URLs setter
*/
private function _set_urls() {
$this->_ttw_url = esc_url( defined( 'THRV_ENV' ) && is_string( THRV_ENV ) ? THRV_ENV : 'https://thrivethemes.com' );
}
/**
* Obfuscation
*
* @param $string
* @param bool $flip
*
* @return string
*/
protected function _obfuscate( $string, $flip = false ) {
if ( $flip ) {
$this->_randomize = array_flip( $this->_randomize );
}
return (string) str_replace( array_keys( $this->_randomize ), $this->_randomize, $string );
}
/**
* @return bool
*/
protected function _build_videos_transient() {
$headers = array(
'Content-Type' => 'application/json',
'website' => get_site_url(),
'tpm' => 'no',
);
$tpm_data = get_option( 'tpm_connection', array() );
// Build auth header for users with TPM [token received from TTW API]
if ( ! empty( $tpm_data ) && ! empty( $tpm_data['ttw_salt'] ) ) {
$headers['Authorization'] = $tpm_data['ttw_salt'];
$headers['userid'] = ! empty( $tpm_data['ttw_id'] ) ? $tpm_data['ttw_id'] : '';
$headers['tpm'] = 'yes';
}
// Build auth header for users without TPM
if ( empty( $headers['Authorization'] ) ) {
$headers['Authorization'] = $this->_obfuscate( get_site_url() );
$headers['userid'] = $this->_obfuscate( get_site_url() . md5( date( 'Y-m-d' ) ), true );
}
$args = array(
'headers' => $headers,
'sslverify' => false,
'timeout' => 20,
);
$request = wp_remote_get( $this->_ttw_url . '/api/v1/public/api_videos', $args );
$body = json_decode( wp_remote_retrieve_body( $request ) );
return set_transient( $this->_ttw_api_url_transient, (array) $this->_fallback_urls, $this->_cache_life_time );
}
/**
* Verify is transient is set or set it
*/
protected function _check_videos_transient() {
$video_urls_transient = get_transient( $this->_ttw_api_url_transient );
if ( ! $video_urls_transient ) {
$this->_build_videos_transient();
}
}
}

View File

@@ -0,0 +1,777 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_AWeber extends Thrive_Dash_List_Connection_Abstract {
const APP_ID = '10fd90de';
/**
* Get AWeber API keys from endpoint with transient caching
*
* @return array API keys or empty array on error
*/
private function get_aweber_api_keys() {
// Check transient first
if ( false !== $keys = get_transient( 'thrive_aweber_api_keys' ) ) {
return $keys;
}
$endpoint = 'https://thrivethemesapi.com/api/secrets/v1/api_key_aweber';
$response = wp_remote_get( $endpoint, array(
'timeout' => 10,
'sslverify' => true
) );
if ( is_wp_error( $response ) ) {
// Log transport-level error (namespaced correlation code)
$correlation_code = 'AWE-KEYS-NET-' . substr( wp_hash( uniqid( '', true ) ), 0, 8 );
$this->api_log_error( 'auth', array(
'endpoint' => $endpoint,
'correlation_code' => $correlation_code,
), sprintf( '%s. Please contact customer support at thrivethemes.com and mention code %s', $response->get_error_message(), $correlation_code ) );
return array();
}
$status_code = wp_remote_retrieve_response_code( $response );
if ( ! empty( $status_code ) && (int) $status_code !== 200 ) {
$correlation_code = 'AWE-KEYS-HTTP-' . substr( wp_hash( uniqid( '', true ) ), 0, 8 );
$error_message = sprintf( 'AWeber API key fetch failed: HTTP %d. Please contact customer support at thrivethemes.com and mention code %s', (int) $status_code, $correlation_code );
$this->api_log_error( 'auth', array(
'endpoint' => $endpoint,
'status_code' => (int) $status_code,
'correlation_code' => $correlation_code,
), $error_message );
return array();
}
$body = wp_remote_retrieve_body( $response );
$data = json_decode( $body, true );
if ( ! is_array( $data ) ||
! isset( $data['success'] ) ||
! $data['success'] ||
! isset( $data['data']['value']['consumer_key'] ) ||
! isset( $data['data']['value']['consumer_secret'] ) ) {
// Log application-level error shape
$correlation_code = 'AWE-KEYS-PAY-' . substr( wp_hash( uniqid( '', true ) ), 0, 8 );
$this->api_log_error( 'auth', array(
'endpoint' => $endpoint,
'correlation_code' => $correlation_code,
), sprintf( 'AWeber API key fetch returned unexpected payload. Please contact customer support at thrivethemes.com and mention code %s', $correlation_code ) );
return array();
}
$keys = array(
'consumer_key' => sanitize_text_field( $data['data']['value']['consumer_key'] ),
'consumer_secret' => sanitize_text_field( $data['data']['value']['consumer_secret'] )
);
// Cache for 24 hours
set_transient( 'thrive_aweber_api_keys', $keys, 24 * HOUR_IN_SECONDS );
return $keys;
}
/**
* Get consumer key with fallback
*
* @return string
*/
private function get_consumer_key() {
$keys = $this->get_aweber_api_keys();
return ! empty( $keys['consumer_key'] ) ? $keys['consumer_key'] : '';
}
/**
* Get consumer secret with fallback
*
* @return string
*/
private function get_consumer_secret() {
$keys = $this->get_aweber_api_keys();
return ! empty( $keys['consumer_secret'] ) ? $keys['consumer_secret'] : '';
}
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'autoresponder';
}
/**
* @return bool
*/
public function has_tags() {
return true;
}
/**
* get the authorization URL for the AWeber Application
*
* @return string
*/
public function getAuthorizeUrl() {
/** @var Thrive_Dash_Api_AWeber $aweber */
$aweber = $this->get_api();
$callback_url = admin_url( 'admin.php?page=tve_dash_api_connect&api=aweber' );
try {
list ( $request_token, $request_token_secret ) = $aweber->getRequestToken( $callback_url );
update_option( 'thrive_aweber_rts', $request_token_secret );
return $aweber->getAuthorizeUrl();
} catch ( Exception $e ) {
$correlation_code = 'AWE-OAUTH-REQ-' . substr( wp_hash( uniqid( '', true ) ), 0, 8 );
$this->api_log_error( 'auth', array(
'step' => 'request_token',
'callback' => $callback_url,
'api_url' => 'https://auth.aweber.com/1.0/oauth/request_token',
'correlation_code' => $correlation_code,
), sprintf( '%s. Please contact customer support at thrivethemes.com and mention code %s', $e->getMessage(), $correlation_code ) );
$this->error( $e->getMessage() );
return '';
}
}
/**
* @return bool|void
*/
public function is_connected() {
return $this->param( 'token' ) && $this->param( 'secret' );
}
/**
* @return string the API connection title
*/
public function get_title() {
return 'AWeber';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'aweber' );
}
/**
* should handle: read data from post / get, test connection and save the details
*
* on error, it should register an error message (and redirect?)
*
* @return mixed
*/
public function read_credentials() {
/** @var Thrive_Dash_Api_AWeber $aweber */
$aweber = $this->get_api();
$aweber->user->tokenSecret = get_option( 'thrive_aweber_rts' );
$aweber->user->requestToken = ! empty( $_REQUEST['oauth_token'] ) ? sanitize_text_field( $_REQUEST['oauth_token'] ) : '';
$aweber->user->verifier = ! empty( $_REQUEST['oauth_verifier'] ) ? sanitize_text_field( $_REQUEST['oauth_verifier'] ) : '';
try {
list( $accessToken, $accessTokenSecret ) = $aweber->getAccessToken();
$this->set_credentials( array(
'token' => $accessToken,
'secret' => $accessTokenSecret,
) );
} catch ( Exception $e ) {
$correlation_code = 'AWE-OAUTH-ACC-' . substr( wp_hash( uniqid( '', true ) ), 0, 8 );
$this->api_log_error( 'auth', array(
'step' => 'access_token',
'api_url' => 'https://auth.aweber.com/1.0/oauth/access_token',
'correlation_code' => $correlation_code,
), sprintf( '%s. Please contact customer support at thrivethemes.com and mention code %s', $e->getMessage(), $correlation_code ) );
$this->error( $e->getMessage() );
return false;
}
$result = $this->test_connection();
if ( $result !== true ) {
$this->error( sprintf( __( 'Could not test AWeber connection: %s', 'thrive-dash' ), $result ) );
return false;
}
$this->save();
/**
* Fetch all custom fields on connect so that we have them all prepared
* - TAr doesn't need to fetch them from API
*/
$this->get_api_custom_fields( array(), true, true );
return true;
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
/** @var Thrive_Dash_Api_AWeber $aweber */
$aweber = $this->get_api();
try {
$aweber->getAccount( $this->param( 'token' ), $this->param( 'secret' ) );
return true;
} catch ( Exception $e ) {
return $e->getMessage();
}
}
/**
* instantiate the API code required for this connection
*
* @return mixed
*/
protected function get_api_instance() {
return new Thrive_Dash_Api_AWeber( $this->get_consumer_key(), $this->get_consumer_secret() );
}
/**
* get all Subscriber Lists from this API service
*
* @return array
*/
protected function _get_lists() {
/** @var Thrive_Dash_Api_AWeber $aweber */
$aweber = $this->get_api();
try {
$lists = array();
$account = $aweber->getAccount( $this->param( 'token' ), $this->param( 'secret' ) );
foreach ( $account->lists as $item ) {
/** @var Thrive_Dash_Api_AWeber_Entry $item */
$lists [] = array(
'id' => $item->data['id'],
'name' => $item->data['name'],
);
}
return $lists;
} catch ( Exception $e ) {
$this->_error = $e->getMessage();
return false;
}
}
/**
* add a contact to a list
*
* @param $list_identifier
* @param array $arguments
*
* @return mixed
*/
public function add_subscriber( $list_identifier, $arguments ) {
try {
/** @var Thrive_Dash_Api_AWeber $aweber */
$aweber = $this->get_api();
$account = $aweber->getAccount( $this->param( 'token' ), $this->param( 'secret' ) );
$listURL = "/accounts/{$account->id}/lists/{$list_identifier}";
$list = $account->loadFromUrl( $listURL );
# create a subscriber
$params = array(
'email' => $arguments['email'],
'ip_address' => tve_dash_get_ip(),
);
if ( ! empty( $arguments['name'] ) ) {
$params['name'] = $arguments['name'];
}
if ( isset( $arguments['url'] ) ) {
$params['custom_fields']['Web Form URL'] = $arguments['url'];
}
// create custom fields
$custom_fields = $list->custom_fields;
try {
$custom_fields->create( array( 'name' => 'Web Form URL' ) );
} catch ( Exception $e ) {
}
if ( ! empty( $arguments['phone'] ) && ( $phone_field_name = $this->phoneCustomFieldExists( $list ) ) ) {
$params['custom_fields'][ $phone_field_name ] = $arguments['phone'];
}
if ( ! empty( $arguments['aweber_tags'] ) ) {
$params['tags'] = explode( ',', trim( $arguments['aweber_tags'], ' ,' ) );
$params['tags'] = array_map( 'trim', $params['tags'] );
}
if ( ( $existing_subscribers = $list->subscribers->find( array( 'email' => $params['email'] ) ) ) && $existing_subscribers->count() === 1 ) {
$subscriber = $existing_subscribers->current();
if ( ! empty( $arguments['name'] ) ) {
$subscriber->name = $params['name'];
}
if ( ! empty( $params['custom_fields'] ) ) {
$subscriber->custom_fields = $params['custom_fields'];
}
if ( empty( $params['tags'] ) || ! is_array( $params['tags'] ) ) {
$params['tags'] = array();
}
$tags = array_values( array_diff( $params['tags'], $subscriber->tags->getData() ) );
if ( ! empty( $tags ) ) {
$subscriber->tags = array(
'add' => $tags,
);
}
$new_subscriber = $subscriber->save() == 209;
} else {
$new_subscriber = $list->subscribers->create( $params );
}
if ( ! $new_subscriber ) {
return sprintf( __( "Could not add contact: %s to list: %s", 'thrive-dash' ), $arguments['email'], $list->name );
}
// Update custom fields
// Make another call to update custom mapped fields in order not to break the subscription call,
// if custom data doesn't pass API custom fields validation
$mapping = thrive_safe_unserialize( base64_decode( isset( $arguments['tve_mapping'] ) ? $arguments['tve_mapping'] : '' ) );
if ( ! empty( $mapping ) || ! empty( $arguments['automator_custom_fields'] ) ) {
$this->updateCustomFields( $list_identifier, $arguments, $params );
}
} catch ( Exception $e ) {
return $e->getMessage();
}
return true;
}
protected function phoneCustomFieldExists( $list ) {
$customFieldsURL = $list->custom_fields_collection_link;
$customFields = $list->loadFromUrl( $customFieldsURL );
foreach ( $customFields as $custom ) {
if ( stripos( $custom->name, 'phone' ) !== false ) {
//return the name of the phone custom field cos users can set its name as: Phone/phone/pHone/etc
//used in custom_fields for subscribers parameters
/** @see add_subscriber */
return $custom->name;
}
}
return false;
}
/**
* output any (possible) extra editor settings for this API
*
* @param array $params allow various different calls to this method
*/
public function get_extra_settings( $params = array() ) {
return $params;
}
/**
* output any (possible) extra editor settings for this API
*
* @param array $params allow various different calls to this method
*/
public function render_extra_editor_settings( $params = array() ) {
$this->output_controls_html( 'aweber/tags', $params );
}
/**
* Return the connection email merge tag
*
* @return String
*/
public static function get_email_merge_tag() {
return '{!email}';
}
/**
* @param array $params which may contain `list_id`
* @param bool $force make a call to API and invalidate cache
* @param bool $get_all where to get lists with their custom fields
*
* @return array
*/
public function get_api_custom_fields( $params, $force = false, $get_all = true ) {
$lists = $this->get_all_custom_fields( $force );
// Get custom fields for all list ids [used on localize in TAr]
if ( true === $get_all ) {
return $lists;
}
$list_id = isset( $params['list_id'] ) ? $params['list_id'] : null;
if ( '0' === $list_id ) {
$list_id = current( array_keys( $lists ) );
}
return array( $list_id => $lists[ $list_id ] );
}
/**
* Get all custom fields by list id
*
* @param $force calls the API and invalidate cache
*
* @return array|mixed
*/
public function get_all_custom_fields( $force ) {
// Serve from cache if exists and requested
$cached_data = $this->get_cached_custom_fields();
if ( false === $force && ! empty( $cached_data ) ) {
return $cached_data;
}
$custom_fields = array();
$lists = $this->_get_lists();
if ( is_array( $lists ) ) {
foreach ( $lists as $list ) {
if ( empty( $list['id'] ) ) {
continue;
}
$custom_fields[ $list['id'] ] = $this->getCustomFieldsByListId( $list['id'] );
}
}
$this->_save_custom_fields( $custom_fields );
return $custom_fields;
}
/**
* Get custom fields by list id
*
* @param $list_id
*
* @return array
*/
public function getCustomFieldsByListId( $list_id ) {
$fields = array();
if ( empty( $list_id ) ) {
return $fields;
}
try {
$account = $this->get_api()->getAccount( $this->param( 'token' ), $this->param( 'secret' ) );
$list_url = "/accounts/{$account->id}/lists/{$list_id}";
$list_obj = $account->loadFromUrl( $list_url );
// CF obj
$custom_fields_url = $list_obj->custom_fields_collection_link;
$custom_fields = $list_obj->loadFromUrl( $custom_fields_url );
foreach ( $custom_fields as $custom_field ) {
if ( ! empty( $custom_field->data['name'] ) && ! empty( $custom_field->data['id'] ) ) {
$fields[] = $this->_normalize_custom_field( $custom_field->data );
}
}
} catch ( Thrive_Dash_Api_AWeber_Exception $e ) {
}
return $fields;
}
/**
* Normalize custom field data
*
* @param $field
*
* @return array
*/
protected function _normalize_custom_field( $field ) {
$field = (array) $field;
return array(
'id' => isset( $field['id'] ) ? $field['id'] : '',
'name' => ! empty( $field['name'] ) ? $field['name'] : '',
'type' => '', // API does not have type
'label' => ! empty( $field['name'] ) ? $field['name'] : '',
);
}
/**
* Append custom fields to defaults
*
* @param array $params
*
* @return array
*/
public function get_custom_fields( $params = array() ) {
return array_merge( parent::get_custom_fields(), $this->_mapped_custom_fields );
}
/**
* Call the API in order to update subscriber's custom fields
*
* @param $list_identifier
* @param $arguments
* @param $data
*
* @return bool
*/
public function updateCustomFields( $list_identifier, $arguments, $data ) {
if ( ! $list_identifier || empty( $arguments ) || empty( $data['email'] ) ) {
return false;
}
$saved = false;
/** @var Thrive_Dash_Api_AWeber $aweber */
$aweber = $this->get_api();
$account = $aweber->getAccount( $this->param( 'token' ), $this->param( 'secret' ) );
$list_url = "/accounts/{$account->id}/lists/{$list_identifier}";
$list = $account->loadFromUrl( $list_url );
if ( empty( $arguments['automator_custom_fields'] ) ) {
$custom_fields = $this->buildMappedCustomFields( $list_identifier, $arguments );
} else {
$custom_fields = $arguments['automator_custom_fields'];
}
$existing_subscribers = $list->subscribers->find( array( 'email' => $data['email'] ) );
if ( $existing_subscribers && $existing_subscribers->count() === 1 && ! empty( $custom_fields ) ) {
$subscriber = $existing_subscribers->current();
$subscriber->custom_fields = $custom_fields;
$saved = $subscriber->save();
}
if ( ! $saved ) {
$this->api_log_error( $list_identifier, $custom_fields, __( 'Could not update custom fields', 'thrive-dash' ) );
}
return $saved;
}
/**
* Creates and prepare the mapping data from the subscription form
*
* @param $list_identifier
* @param $args
* @param array $custom_fields
*
* @return array
*/
public function buildMappedCustomFields( $list_identifier, $args, $custom_fields = array() ) {
if ( empty( $args['tve_mapping'] ) || ! tve_dash_is_bas64_encoded( $args['tve_mapping'] ) || ! is_serialized( base64_decode( $args['tve_mapping'] ) ) ) {
return $custom_fields;
}
$mapped_form_data = thrive_safe_unserialize( base64_decode( $args['tve_mapping'] ) );
if ( is_array( $mapped_form_data ) && $list_identifier ) {
$api_custom_fields = $this->buildCustomFieldsList();
// Loop trough allowed custom fields names
foreach ( $this->get_mapped_field_ids() as $mapped_field_name ) {
// Extract an array with all custom fields (siblings) names from the form data
// {ex: [mapping_url_0, .. mapping_url_n] / [mapping_text_0, .. mapping_text_n]}
$cf_form_fields = preg_grep( "#^{$mapped_field_name}#i", array_keys( $mapped_form_data ) );
// Matched "form data" for current allowed name
if ( ! empty( $cf_form_fields ) && is_array( $cf_form_fields ) ) {
// Pull form allowed data, sanitize it and build the custom fields array
foreach ( $cf_form_fields as $cf_form_name ) {
if ( empty( $mapped_form_data[ $cf_form_name ][ $this->_key ] ) ) {
continue;
}
$args[ $cf_form_name ] = $this->process_field( $args[ $cf_form_name ] );
$mapped_form_field_id = $mapped_form_data[ $cf_form_name ][ $this->_key ];
$field_label = $api_custom_fields[ $list_identifier ][ $mapped_form_field_id ];
$cf_form_name = str_replace( '[]', '', $cf_form_name );
if ( ! empty( $args[ $cf_form_name ] ) ) {
$args[ $cf_form_name ] = $this->process_field( $args[ $cf_form_name ] );
$custom_fields[ $field_label ] = sanitize_text_field( $args[ $cf_form_name ] );
}
}
}
}
}
return $custom_fields;
}
/**
* Build custom fields mapping for automations
*
* @param $automation_data
*
* @return array
*/
public function build_automation_custom_fields( $automation_data ) {
$mapped_data = array();
if ( $automation_data['mailing_list'] ) {
$api_custom_fields = $this->buildCustomFieldsList();
foreach ( $automation_data['api_fields'] as $pair ) {
$value = sanitize_text_field( $pair['value'] );
if ( $value ) {
$field_label = $api_custom_fields[ $automation_data['mailing_list'] ][ $pair['key'] ];
$mapped_data[ $field_label ] = $value;
}
}
}
return $mapped_data;
}
/**
* Create a simpler structure with [list_id] => [ field_id => field_name]
*
* @return array
*/
public function buildCustomFieldsList() {
$parsed = array();
foreach ( $this->get_all_custom_fields( false ) as $list_id => $merge_field ) {
array_map(
function ( $var ) use ( &$parsed, $list_id ) {
$parsed[ $list_id ][ $var['id'] ] = $var['name'];
},
$merge_field
);
}
return $parsed;
}
/**
* @param $email
* @param array $custom_fields
* @param array $extra
*
* @return false|int
*/
public function add_custom_fields( $email, $custom_fields = array(), $extra = array() ) {
try {
/** @var Thrive_Dash_Api_AWeber $api */
$api = $this->get_api();
$list_id = ! empty( $extra['list_identifier'] ) ? $extra['list_identifier'] : null;
$args = array(
'email' => $email,
);
if ( ! empty( $extra['name'] ) ) {
$args['name'] = $extra['name'];
}
$this->add_subscriber( $list_id, $args );
$account = $api->getAccount( $this->param( 'token' ), $this->param( 'secret' ) );
$list_url = "/accounts/{$account->id}/lists/{$list_id}";
$list = $account->loadFromUrl( $list_url );
$existing_subscribers = $list->subscribers->find( array( 'email' => $email ) );
if ( $existing_subscribers && $existing_subscribers->count() === 1 ) {
$subscriber = $existing_subscribers->current();
$prepared_fields = $this->prepare_custom_fields_for_api( $custom_fields, $list_id );
$subscriber->custom_fields = array_merge( $subscriber->data['custom_fields'], $prepared_fields );
$subscriber->save();
return $subscriber->id;
}
} catch ( Exception $e ) {
return false;
}
}
/**
* Prepare custom fields for api call
*
* @param array $custom_fields
* @param null $list_identifier
*
* @return array
*/
protected function prepare_custom_fields_for_api( $custom_fields = array(), $list_identifier = null ) {
if ( empty( $list_identifier ) ) { // list identifier required here
return array();
}
$api_fields = $this->get_api_custom_fields( array( 'list_id' => $list_identifier ), true );
if ( empty( $api_fields[ $list_identifier ] ) ) {
return array();
}
$prepared_fields = array();
foreach ( $api_fields[ $list_identifier ] as $field ) {
foreach ( $custom_fields as $key => $custom_field ) {
if ( (int) $field['id'] === (int) $key && $custom_field ) {
$prepared_fields[ $field['name'] ] = $custom_field;
unset( $custom_fields[ $key ] ); // avoid unnecessary loops
}
}
if ( empty( $custom_fields ) ) {
break;
}
}
return $prepared_fields;
}
public function get_automator_add_autoresponder_mapping_fields() {
return array( 'autoresponder' => array( 'mailing_list' => array( 'api_fields' ), 'tag_input' => array() ) );
}
public function get_automator_tag_autoresponder_mapping_fields() {
return array( 'autoresponder' => array( 'mailing_list', 'tag_input' ) );
}
public function has_custom_fields() {
return true;
}
}

View File

@@ -0,0 +1,646 @@
<?php /** @noinspection ALL */
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_ActiveCampaign extends Thrive_Dash_List_Connection_Abstract {
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'autoresponder';
}
/**
* @return string the API connection title
*/
public function get_title() {
return 'ActiveCampaign';
}
/**
* @return bool
*/
public function has_tags() {
return true;
}
public function has_custom_fields() {
return true;
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'activecampaign' );
}
/**
* should handle: read data from post / get, test connection and save the details
*
* on error, it should register an error message (and redirect?)
*
* @return mixed
*/
public function read_credentials() {
$api_url = ! empty( $_POST['connection']['api_url'] ) ? sanitize_text_field( $_POST['connection']['api_url'] ) : '';
$api_key = ! empty( $_POST['connection']['api_key'] ) ? sanitize_text_field( $_POST['connection']['api_key'] ) : '';
if ( empty( $api_key ) || empty( $api_url ) || empty( $_POST['connection'] ) ) {
return $this->error( __( 'Both API URL and API Key fields are required', 'thrive-dash' ) );
}
$this->set_credentials( compact( 'api_url', 'api_key' ) );
$result = $this->test_connection();
if ( $result !== true ) {
return $this->error( sprintf( __( 'Could not connect to ActiveCampaign using the provided details. Response was: <strong>%s</strong>', 'thrive-dash' ), $result ) );
}
/**
* finally, save the connection details
*/
$this->save();
/**
* Fetch all custom fields on connect so that we have them all prepared
* - TAr doesn't need to get them from API
*/
$this->get_api_custom_fields( array(), true, true );
return $this->success( __( 'ActiveCampaign connected successfully', 'thrive-dash' ) );
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
/** @var Thrive_Dash_Api_ActiveCampaign $api */
$api = $this->get_api();
try {
$api->call( 'account_view', array() );
return true;
} catch ( Thrive_Dash_Api_ActiveCampaign_Exception $e ) {
return $e->getMessage();
} catch ( Exception $e ) {
return $e->getMessage();
}
}
/**
* instantiate the API code required for this connection
*
* @return mixed
*/
protected function get_api_instance() {
$api_url = $this->param( 'api_url' );
$api_key = $this->param( 'api_key' );
return new Thrive_Dash_Api_ActiveCampaign( $api_url, $api_key );
}
/**
* get all Subscriber Lists from this API service
*
* @return array|bool for error
*/
protected function _get_lists() {
try {
$raw = $this->get_api()->getLists();
$lists = array();
foreach ( $raw as $list ) {
$lists [] = array(
'id' => $list['id'],
'name' => $list['name'],
);
}
return $lists;
} catch ( Thrive_Dash_Api_ActiveCampaign_Exception $e ) {
$this->_error = $e->getMessage();
return false;
} catch ( Exception $e ) {
$this->_error = $e->getMessage();
return false;
}
}
/**
* get all Subscriber Forms from this API service
*
* @return array|bool for error
*/
protected function _get_forms() {
try {
$raw = $this->get_api()->get_forms();
$forms = array();
$lists = $this->get_lists();
foreach ( $lists as $list ) {
$forms[ $list['id'] ][0] = array(
'id' => 0,
'name' => __( 'none', 'thrive-dash' ),
);
}
foreach ( $raw as $form ) {
foreach ( $form['lists'] as $list_id ) {
if ( empty( $forms[ $list_id ] ) ) {
$forms[ $list_id ] = array();
}
/**
* for some reason, I've seen an instance where forms were duplicated (2 or more of the same form were displayed in the list)
*/
$forms[ $list_id ][ $form['id'] ] = array(
'id' => $form['id'],
'name' => $form['name'],
);
}
}
return $forms;
} catch ( Thrive_Dash_Api_ActiveCampaign_Exception $e ) {
$this->_error = $e->getMessage();
return false;
} catch ( Exception $e ) {
$this->_error = $e->getMessage();
return false;
}
}
/**
* delete a contact from the list
*
* @param string $email
* @param array $arguments
*
* @return mixed
*/
public function delete_subscriber( $email, $arguments = array() ) {
$api = $this->get_api();
$contact = $api->call( 'contact_view_email', array( 'email' => $email ) );
if ( isset( $contact['result_code'] ) && $contact['result_code'] == 1 ) {
$body = array( 'id' => $contact['id'] );
$result = $api->call( 'contact_delete', $body, array() );
return isset( $result['result_code'] ) && $result['result_code'] == 1;
}
return true;
}
/**
* add a contact to a list
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return mixed
*/
public function add_subscriber( $list_identifier, $arguments ) {
/** @var Thrive_Dash_Api_ActiveCampaign $api */
$api = $this->get_api();
$name_array = array();
if ( ! empty( $arguments['name'] ) ) {
list( $first_name, $last_name ) = $this->get_name_parts( $arguments['name'] );
$name_array = array(
'firstname' => $first_name,
'lastName' => $last_name,
);
}
// Get contact
try {
$contact = $api->call( 'contact_view_email', array( 'email' => $arguments['email'] ) );
} catch ( Thrive_Dash_Api_ActiveCampaign_Exception $e ) {
return $e->getMessage();
} catch ( Exception $e ) {
return $e->getMessage();
}
$update = false;
if ( isset( $contact['result_code'] ) && $contact['result_code'] == 1 ) {
foreach ( $contact['lists'] as $list ) {
if ( $list['listid'] == $list_identifier ) {
$update = true;
}
}
}
// Prepared args for passing to subscribe/update methods
$prepared_args = array(
'email' => ! empty( $arguments['email'] ) ? sanitize_email( $arguments['email'] ) : '',
'phone' => empty( $arguments['phone'] ) ? '' : sanitize_text_field( $arguments['phone'] ),
'form_id' => empty( $arguments['activecampaign_form'] ) ? 0 : sanitize_text_field( $arguments['activecampaign_form'] ),
'organizationName' => '',
'tags' => ! empty( $arguments['activecampaign_tags'] ) ? trim( $arguments['activecampaign_tags'], ',' ) : '',
'ip' => null,
);
$prepared_args = array_merge( $prepared_args, $name_array );
// Add or update subscriber
try {
/**
* Try to add/update contact on a single api call so linkted automation will be properly triggered
*/
if ( ! empty( $arguments['tve_mapping'] ) ) {
$prepared_args['custom_fields'] = $this->buildMappedCustomFields( $arguments );
} else if ( ! empty( $arguments['automator_custom_fields'] ) ) {
$prepared_args['custom_fields'] = $arguments['automator_custom_fields'];
}
if ( isset( $contact['result_code'] ) && ( empty( $contact['result_code'] ) || false === $update ) ) {
$api->add_subscriber( $list_identifier, $prepared_args );
} else {
$prepared_args['contact'] = $contact;
$api->updateSubscriber( $list_identifier, $prepared_args );
}
$return = true;
} catch ( Thrive_Dash_Api_ActiveCampaign_Exception $e ) {
$return = $e->getMessage();
} catch ( Exception $e ) {
$return = $e->getMessage();
}
/**
* Add/update action failed so we try again by doing two separate requests
* one for add/update contact and another one for updating custom fields
*/
if ( true !== $return ) {
try {
if ( isset( $contact['result_code'] ) && ( empty( $contact['result_code'] ) || false === $update ) ) {
$api->add_subscriber( $list_identifier, $prepared_args );
} else {
$prepared_args['contact'] = $contact;
$api->updateSubscriber( $list_identifier, $prepared_args );
}
$return = true;
} catch ( Thrive_Dash_Api_ActiveCampaign_Exception $e ) {
$return = $e->getMessage();
} catch ( Exception $e ) {
$return = $e->getMessage();
}
// Update custom fields
// Make another call to update custom mapped fields in order not to break the subscription call,
// if custom data doesn't pass API custom fields validation
if ( true === $return && ! empty( $arguments['tve_mapping'] ) ) {
unset( $prepared_args['tags'] );
$this->updateCustomFields( $list_identifier, $arguments, $prepared_args );
}
}
return $return;
}
/**
* Update custom fields
*
* @param string|int $list_identifier
* @param array $arguments form data
* @param array $prepared_args prepared array for subscription
*
* @return bool|string
*/
public function updateCustomFields( $list_identifier, $arguments, $prepared_args ) {
if ( ! $list_identifier || empty( $arguments ) || empty( $prepared_args ) ) {
return false;
}
/** @var Thrive_Dash_Api_ActiveCampaign $api */
$api = $this->get_api();
try {
// Refresh the contact data for mapping custom fields
$prepared_args['contact'] = $api->call( 'contact_view_email', array( 'email' => $arguments['email'] ) );
// Build mapped fields array
$prepared_args['custom_fields'] = $this->buildMappedCustomFields( $arguments );
$api->updateSubscriber( $list_identifier, $prepared_args );
$return = true;
} catch ( Exception $e ) {
// Log api errors
$this->api_log_error( $list_identifier, $prepared_args, __METHOD__ . ': ' . $e->getMessage() );
$return = $e->getMessage();
}
return $return;
}
/**
* output any (possible) extra editor settings for this API
*
* @param array $params allow various different calls to this method
*
* @return array
*/
public function get_extra_settings( $params = array() ) {
$params['forms'] = $this->_get_forms();
if ( ! is_array( $params['forms'] ) ) {
$params['forms'] = array();
}
return $params;
}
/**
* output any (possible) extra editor settings for this API
*
* @param array $params allow various different calls to this method
*/
public function render_extra_editor_settings( $params = array() ) {
$params['forms'] = $this->_get_forms();
if ( ! is_array( $params['forms'] ) ) {
$params['forms'] = array();
}
$this->output_controls_html( 'activecampaign/forms-list', $params );
}
/**
* Return the connection email merge tag
*
* @return String
*/
public static function get_email_merge_tag() {
return '%EMAIL%';
}
/**
* @param $params
* @param bool $force
* @param bool $get_all
*
* @return array|mixed
*/
public function get_api_custom_fields( $params, $force = false, $get_all = false ) {
return $this->get_all_custom_fields( $force );
}
/**
* @param (bool) $force
*
* @return array|mixed
*/
public function get_all_custom_fields( $force ) {
$custom_data = array();
// Serve from cache if exists and requested
$cached_data = $this->get_cached_custom_fields();
if ( false === $force && ! empty( $cached_data ) ) {
return $cached_data;
}
// Needed custom fields type
$allowed_types = array(
'text',
'url',
'number',
'hidden',
);
// Build custom fields for every list
$custom_fields = $this->get_api()->getCustomFields();
if ( is_array( $custom_fields ) ) {
foreach ( $custom_fields as $field ) {
if ( ! empty( $field['type'] ) && in_array( $field['type'], $allowed_types, true ) && 1 === (int) $field['visible'] ) {
$custom_data[] = $this->normalize_custom_field( $field );
}
}
}
$this->_save_custom_fields( $custom_data );
return $custom_data;
}
/**
* @param array $field
*
* @return array
*/
protected function normalize_custom_field( $field ) {
$field = (array) $field;
return array(
'id' => ! empty( $field['id'] ) ? $field['id'] : '',
'name' => ! empty( $field['perstag'] ) ? $field['perstag'] : '',
'type' => $field['type'],
'label' => ! empty( $field['title'] ) ? $field['title'] : '',
);
}
/**
* Append custom fields to defaults
*
* @param array $params
*
* @return array
*/
public function get_custom_fields( $params = array() ) {
return array_merge( parent::get_custom_fields(), $this->_mapped_custom_fields );
}
/**
* Build mapped custom fields array based on form params
*
* @param $args
*
* @return array
*/
public function buildMappedCustomFields( $args ) {
$mapped_data = array();
// Should be always base_64 encoded of a serialized array
if ( empty( $args['tve_mapping'] ) || ! tve_dash_is_bas64_encoded( $args['tve_mapping'] ) || ! is_serialized( base64_decode( $args['tve_mapping'] ) ) ) {
return $mapped_data;
}
$form_data = thrive_safe_unserialize( base64_decode( $args['tve_mapping'] ) );
if ( is_array( $form_data ) ) {
$mapped_fields = $this->get_mapped_field_ids();
foreach ( $mapped_fields as $mapped_field_name ) {
// Extract an array with all custom fields (siblings) names from form data
// {ex: [mapping_url_0, .. mapping_url_n] / [mapping_text_0, .. mapping_text_n]}
$cf_form_fields = preg_grep( "#^{$mapped_field_name}#i", array_keys( $form_data ) );
// Matched "form data" for current allowed name
if ( ! empty( $cf_form_fields ) && is_array( $cf_form_fields ) ) {
// Pull form allowed data, sanitize it and build the custom fields array
foreach ( $cf_form_fields as $cf_form_name ) {
if ( empty( $form_data[ $cf_form_name ][ $this->_key ] ) ) {
continue;
}
$mapped_api_id = $form_data[ $cf_form_name ][ $this->_key ];
$cf_form_name = str_replace( '[]', '', $cf_form_name );
if ( ! empty( $args[ $cf_form_name ] ) ) {
$args[ $cf_form_name ] = $this->process_field( $args[ $cf_form_name ] );
$mapped_data["field[{$mapped_api_id}, 0]"] = sanitize_text_field( $args[ $cf_form_name ] );
}
}
}
}
}
return $mapped_data;
}
/**
* Build custom fields mapping for automations
*
* @param $automation_data
*
* @return array
*/
public function build_automation_custom_fields( $automation_data ) {
$mapped_data = array();
foreach ( $automation_data['api_fields'] as $pair ) {
$value = sanitize_text_field( $pair['value'] );
if ( $value ) {
$mapped_data["field[{$pair['key']}, 0]"] = $value;
}
}
return $mapped_data;
}
/**
* get relevant data from webhook trigger
*
* @param $request WP_REST_Request
*
* @return array
*/
public function get_webhook_data( $request ) {
$contact = $request->get_param( 'contact' );
return array( 'email' => empty( $contact['email'] ) ? '' : $contact['email'] );
}
/**
* @param $email
* @param array $custom_fields
* @param array $extra
*
* @return false|int|mixed
*/
public function add_custom_fields( $email, $custom_fields = array(), $extra = array() ) {
try {
/** @var Thrive_Dash_Api_ActiveCampaign $api */
$api = $this->get_api();
$list_id = ! empty( $extra['list_identifier'] ) ? $extra['list_identifier'] : null;
$args = array(
'email' => $email,
);
if ( ! empty( $extra['name'] ) ) {
$args['name'] = $extra['name'];
}
$this->add_subscriber( $list_id, $args );
$args['contact'] = $api->call( 'contact_view_email', array( 'email' => $email ) );
$args['custom_fields'] = $this->prepare_custom_fields_for_api( $custom_fields );
$api->updateSubscriber( $list_id, $args );
return $args['contact']['id'];
} catch ( Exception $e ) {
return false;
}
}
/**
* Prepare custom fields for api call
*
* @param array $custom_fields
* @param null $list_identifier
*
* @return array
*/
protected function prepare_custom_fields_for_api( $custom_fields = array(), $list_identifier = null ) {
$prepared_fields = array();
foreach ( $custom_fields as $key => $custom_field ) {
if ( $custom_field ) {
$prepared_fields["field[{$key}], 0"] = sanitize_text_field( $custom_field );
}
}
return $prepared_fields;
}
public function get_automator_add_autoresponder_mapping_fields() {
return array( 'autoresponder' => array( 'mailing_list' => array( 'form_list' ), 'api_fields' => array(), 'tag_input' => array() ) );
}
public function get_custom_fields_by_list( $list = null ) {
return $this->get_available_custom_fields();
}
public function has_forms() {
return true;
}
}

View File

@@ -0,0 +1,337 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_Awsses extends Thrive_Dash_List_Connection_Abstract {
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'email';
}
/**
* @return string the API connection title
*/
public function get_title() {
return 'Amazon SES';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'awsses' );
}
/**
* should handle: read data from post / get, test connection and save the details
*
* on error, it should register an error message (and redirect?)
*/
public function read_credentials() {
$ajax_call = defined( 'DOING_AJAX' ) && DOING_AJAX;
$key = ! empty( $_POST['connection']['key'] ) ? sanitize_text_field( $_POST['connection']['key'] ) : '';
if ( empty( $key ) ) {
return $ajax_call ? __( 'You must provide a valid Amazon Web Services Simple Email Service key', 'thrive-dash' ) : $this->error( __( 'You must provide a valid Amazon Web Services Simple Email Service key', 'thrive-dash' ) );
}
$secretkey = ! empty( $_POST['connection']['secretkey'] ) ? sanitize_text_field( $_POST['connection']['secretkey'] ) : '';
if ( empty( $secretkey ) ) {
return $ajax_call ? __( 'You must provide a valid Amazon Web Services Simple Email Service secret key', 'thrive-dash' ) : $this->error( __( 'You must provide a valid Amazon Web Services Simple Email Service secret key', 'thrive-dash' ) );
}
$email = ! empty( $_POST['connection']['email'] ) ? sanitize_email( $_POST['connection']['email'] ) : '';
if ( empty( $email ) ) {
return $ajax_call ? __( 'Email field must not be empty', 'thrive-dash' ) : $this->error( __( 'Email field must not be empty', 'thrive-dash' ) );
}
$country = ! empty( $_POST['connection']['country'] ) ? sanitize_text_field( $_POST['connection']['country'] ) : '';
$credentials = array(
'key' => $key,
'secretkey' => $secretkey,
'email' => $email,
'country' => $country,
);
$this->set_credentials( $credentials );
$result = $this->test_connection();
if ( $result !== true ) {
return $ajax_call ? sprintf( __( 'Could not connect to Amazon Web Services Simple Email Service using the provided key (<strong>%s</strong>)', 'thrive-dash' ), $result ) : $this->error( sprintf( __( 'Could not connect to Amazon Web Services Simple Email Service using the provided key (<strong>%s</strong>)', 'thrive-dash' ), $result ) );
}
/**
* finally, save the connection details
*/
$this->save();
$this->success( __( 'Amazon Web Services Simple Email Service connected successfully', 'thrive-dash' ) );
if ( $ajax_call ) {
return true;
}
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
$awsses = $this->get_api();
if ( isset( $_POST['connection']['email'] ) ) {
$from_email = sanitize_email( $_POST['connection']['email'] );
$to = sanitize_email( $_POST['connection']['email'] );
} else {
$credentials = Thrive_Dash_List_Manager::credentials( 'awsses' );
if ( isset( $credentials ) ) {
$from_email = $credentials['email'];
$to = $credentials['email'];
}
}
$subject = 'API connection test';
$html_content = 'This is a test email from Thrive Leads Amazon Web Services Simple Email Service API.';
$text_content = 'This is a test email from Thrive Leads Amazon Web Services Simple Email Service API.';
try {
$messsage = new Thrive_Dash_Api_Awsses_SimpleEmailServiceMessage();
$messsage->addTo( $to );
$messsage->setFrom( $from_email );
$messsage->setSubject( $subject );
$messsage->setMessageFromString( $text_content, $html_content );
$awsses->sendEmail( $messsage );
} catch ( Exception $e ) {
return $e->getMessage();
}
$connection = get_option( 'tve_api_delivery_service', false );
if ( $connection == false ) {
update_option( 'tve_api_delivery_service', 'awsses' );
}
return true;
/**
* just try getting a list as a connection test
*/
}
/**
* Send custom email
*
* @param $data
*
* @return bool|string true for success or error message for failure
*/
public function sendCustomEmail( $data ) {
$awsses = $this->get_api();
$credentials = Thrive_Dash_List_Manager::credentials( 'awsses' );
if ( isset( $credentials ) ) {
$from_email = $credentials['email'];
} else {
return false;
}
try {
$messsage = new Thrive_Dash_Api_Awsses_SimpleEmailServiceMessage();
$messsage->addTo( $data['email'] );
$messsage->setFrom( $from_email );
$messsage->setSubject( $data['subject'] );
$messsage->setMessageFromString( empty ( $data['text_content'] ) ? '' : $data['text_content'], empty ( $data['html_content'] ) ? '' : $data['html_content'] );
$awsses->sendEmail( $messsage );
} catch ( Exception $e ) {
return $e->getMessage();
}
return true;
}
/**
* Send the same email to multiple addresses
*
* @param $data
*
* @return bool|string
*/
public function sendMultipleEmails( $data ) {
$awsses = $this->get_api();
$credentials = Thrive_Dash_List_Manager::credentials( 'awsses' );
if ( isset( $credentials ) ) {
$from_email = $credentials['email'];
} else {
return false;
}
if ( ! empty( $data['from_name'] ) ) {
$from_email = $data['from_name'] . ' < ' . $from_email . ' >';
}
try {
$message = new Thrive_Dash_Api_Awsses_SimpleEmailServiceMessage();
$message->addTo( $data['emails'] );
$message->setFrom( $from_email );
$message->setSubject( $data['subject'] );
$message->setMessageFromString( empty ( $data['text_content'] ) ? '' : $data['text_content'], empty ( $data['html_content'] ) ? '' : $data['html_content'] );
if ( ! empty( $data['reply_to'] ) ) {
$message->addReplyTo( $data['reply_to'] );
}
if ( ! empty( $data['cc'] ) ) {
$message->addCC( $data['cc'] );
}
if ( ! empty( $data['bcc'] ) ) {
$message->addBCC( $data['bcc'] );
}
$awsses->sendEmail( $message );
} catch ( Exception $e ) {
return $e->getMessage();
}
/* Send confirmation email */
if ( ! empty( $data['send_confirmation'] ) ) {
try {
$message = new Thrive_Dash_Api_Awsses_SimpleEmailServiceMessage();
$message->addTo( $data['sender_email'] );
$message->setFrom( $from_email );
$message->addReplyTo( $from_email );
$message->setSubject( $data['confirmation_subject'] );
$message->setMessageFromString( empty ( $data['confirmation_text'] ) ? '' : $data['confirmation_text'], empty ( $data['confirmation_html'] ) ? '' : $data['confirmation_html'] );
$awsses->sendEmail( $message );
} catch ( Exception $e ) {
return $e->getMessage();
}
}
return true;
}
/**
* Send the email to the user
*
* @param $post_data
*
* @return bool|string
* @throws Exception
*
*/
public function sendEmail( $post_data ) {
$awsses = $this->get_api();
$credentials = $this->get_credentials();
$asset = get_post( $post_data['_asset_group'] );
if ( empty( $asset ) || ! ( $asset instanceof WP_Post ) || $asset->post_status !== 'publish' ) {
throw new Exception( sprintf( __( 'Invalid Asset Group: %s. Check if it exists or was trashed.', 'thrive-dash' ), $post_data['_asset_group'] ) );
}
$files = get_post_meta( $post_data['_asset_group'], 'tve_asset_group_files', true );
$subject = get_post_meta( $post_data['_asset_group'], 'tve_asset_group_subject', true );
if ( $subject == "" ) {
$subject = get_option( 'tve_leads_asset_mail_subject' );
}
$from_email = $credentials['email'];
$html_content = $asset->post_content;
if ( $html_content == "" ) {
$html_content = get_option( 'tve_leads_asset_mail_body' );
}
$attached_files = array();
foreach ( $files as $file ) {
$attached_files[] = '<a href="' . $file['link'] . '">' . $file['link_anchor'] . '</a><br/>';
}
$the_files = implode( '<br/>', $attached_files );
$html_content = str_replace( '[asset_download]', $the_files, $html_content );
$html_content = str_replace( '[asset_name]', $asset->post_title, $html_content );
$subject = str_replace( '[asset_name]', $asset->post_title, $subject );
if ( isset( $post_data['name'] ) && ! empty( $post_data['name'] ) ) {
$html_content = str_replace( '[lead_name]', $post_data['name'], $html_content );
$subject = str_replace( '[lead_name]', $post_data['name'], $subject );
} else {
$html_content = str_replace( '[lead_name]', '', $html_content );
$subject = str_replace( '[lead_name]', '', $subject );
}
$text_content = strip_tags( $html_content );
$messsage = new Thrive_Dash_Api_Awsses_SimpleEmailServiceMessage();
$messsage->addTo( $post_data['email'] );
$messsage->setFrom( $from_email );
$messsage->setSubject( $subject );
$messsage->setMessageFromString( $text_content, $html_content );
return $awsses->sendEmail( $messsage );
}
/**
* instantiate the API code required for this connection
*
* @return mixed
*/
protected function get_api_instance() {
switch ( $this->param( 'country' ) ) {
case 'ireland':
$country = "email.eu-west-1.amazonaws.com";
break;
case 'useast':
$country = "email.us-east-1.amazonaws.com";
break;
case 'uswest':
$country = "email.us-west-2.amazonaws.com";
break;
}
return new Thrive_Dash_Api_Awsses( $this->param( 'key' ), $this->param( 'secretkey' ), $country );
}
/**
* get all Subscriber Lists from this API service
*
* @return array|bool for error
*/
protected function _get_lists() {
}
/**
* add a contact to a list
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return mixed
*/
public function add_subscriber( $list_identifier, $arguments ) {
}
}

View File

@@ -0,0 +1,536 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class Thrive_Dash_List_Connection_CampaignMonitor extends Thrive_Dash_List_Connection_Abstract {
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'autoresponder';
}
/**
* @return string
*/
public function get_title() {
return 'Campaign Monitor';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$related_api = Thrive_Dash_List_Manager::connection_instance( 'campaignmonitoremail' );
if ( $related_api->is_connected() ) {
$this->set_param( 'new_connection', 1 );
}
$this->output_controls_html( 'campaignmonitor' );
}
/**
* Just saves the key in the database for optin and email api
*
* @return string|void
*/
public function read_credentials() {
$key = ! empty( $_POST['connection']['key'] ) ? sanitize_text_field( $_POST['connection']['key'] ) : '';
$email = ! empty( $_POST['connection']['email'] ) ? sanitize_email( $_POST['connection']['email'] ) : '';
if ( empty( $key ) ) {
return $this->error( __( 'You must provide a valid Campaign Monitor key', 'thrive-dash' ) );
}
$this->set_credentials( compact( 'key', 'email' ) );
$result = $this->test_connection();
if ( $result !== true ) {
return $this->error( sprintf( __( 'Could not connect to Campaign Monitor using the provided key (<strong>%s</strong>)', 'thrive-dash' ), $result ) );
}
/**
* finally, save the connection details
*/
$this->save();
/** @var Thrive_Dash_List_Connection_CampaignMonitorEmail $related_api */
$related_api = Thrive_Dash_List_Manager::connection_instance( 'campaignmonitoremail' );
if ( isset( $_POST['connection']['new_connection'] ) && (int) $_POST['connection']['new_connection'] === 1 ) {
/**
* Try to connect to the email service too
*/
$r_result = true;
if ( ! $related_api->is_connected() ) {
$r_result = $related_api->read_credentials();
}
if ( $r_result !== true ) {
$this->disconnect();
return $this->error( $r_result );
}
} else {
/**
* let's make sure that the api was not edited and disconnect it
*/
$related_api->set_credentials( array() );
Thrive_Dash_List_Manager::save( $related_api );
}
return $this->success( __( 'Campaign Monitor connected successfully', 'thrive-dash' ) );
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
/** @var Thrive_Dash_Api_CampaignMonitor $cm */
$cm = $this->get_api();
try {
$clients = $cm->get_clients();
$client = current( $clients );
$cm->get_client_lists( $client['id'] );
} catch ( Exception $e ) {
return $e->getMessage();
}
return true;
}
/**
* instantiate the API code required for this connection
*
* @return mixed
*/
protected function get_api_instance() {
return new Thrive_Dash_Api_CampaignMonitor( $this->param( 'key' ) );
}
/**
* get all Subscriber Lists from this API service
*
* @return array
*/
protected function _get_lists() {
$lists = array();
try {
/** @var Thrive_Dash_Api_CampaignMonitor $cm */
$cm = $this->get_api();
$clients = $cm->get_clients();
$client = current( $clients );
$lists = $cm->get_client_lists( $client['id'] );
} catch ( Exception $e ) {
}
return $lists;
}
/**
* add a contact to a list
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return bool|string true for success or string error message for failure
*/
public function add_subscriber( $list_identifier, $arguments ) {
try {
$subscriber = array();
/** @var Thrive_Dash_Api_CampaignMonitor $cm */
$cm = $this->get_api();
$subscriber['EmailAddress'] = $arguments['email'];
$subscriber['Resubscribe'] = true;
$subscriber['RestartSubscriptionBasedAutoresponders'] = true;
if ( ! empty( $arguments['name'] ) ) {
$subscriber['Name'] = $arguments['name'];
}
/** @var Thrive_Dash_Api_CampaignMonitor_List $list */
$list = $cm->get_list( $list_identifier );
$subscriber['CustomFields'] = empty( $arguments['CustomFields'] ) ? array() : $arguments['CustomFields'];
if ( ! empty( $arguments['phone'] ) ) {
$custom_fields = $list->get_custom_fields();
$_list_has_phone = false;
if ( ! empty( $custom_fields ) ) {
foreach ( $custom_fields as $field ) {
if ( isset( $field['name'] ) && $field['name'] === 'Phone' ) {
$_list_has_phone = true;
break;
}
}
}
if ( $_list_has_phone === false ) {
$custom_field = array(
'FieldName' => 'Phone',
'DataType' => 'Number',
'Options' => array(),
'VisibleInPreferenceCenter' => true,
);
$list->create_custom_field( $custom_field );
}
$subscriber['CustomFields'][] = array(
'Key' => 'Phone',
'Value' => (string) $arguments['phone'],
);
}
$_custom_fields = $this->_generate_custom_fields( array_merge( $arguments, array( 'list_id' => $list_identifier ) ) );
$subscriber['CustomFields'] = array_merge( $subscriber['CustomFields'], $_custom_fields );
if ( ! empty( $arguments['automator_custom_fields'] ) ) {
$subscriber['CustomFields'] = array_merge( $subscriber['CustomFields'], $arguments['automator_custom_fields'] );
}
$list->add_subscriber( $subscriber );
} catch ( Exception $e ) {
return $e->getMessage();
}
return true;
}
/**
* delete a contact from the list
*
* @param string $email
* @param array $arguments
*
* @return mixed
*/
public function delete_subscriber( $email, $arguments = array() ) {
$api = $this->get_api();
if ( ! empty( $arguments['list_identifier'] ) && ! empty( $email ) ) {
$list = $api->get_list( $arguments['list_identifier'] );
$list->delete_subscriber( $email );
return true;
}
return false;
}
/**
* Return the connection email merge tag
*
* @return String
*/
public static function get_email_merge_tag() {
return '[email]';
}
/**
* disconnect (remove) this API connection
*/
public function disconnect() {
$this->set_credentials( array() );
Thrive_Dash_List_Manager::save( $this );
/**
* disconnect the email service too
*/
$related_api = Thrive_Dash_List_Manager::connection_instance( 'campaignmonitoremail' );
$related_api->set_credentials( array() );
Thrive_Dash_List_Manager::save( $related_api );
return $this;
}
/**
* @param array $params which may contain `list_id`
* @param bool $force make a call to API and invalidate cache
* @param bool $get_all where to get lists with their custom fields
*
* @return array
*/
public function get_api_custom_fields( $params, $force = false, $get_all = true ) {
$cached_data = $this->get_cached_custom_fields();
if ( false === $force && ! empty( $cached_data ) ) {
return $cached_data;
}
/** @var Thrive_Dash_Api_CampaignMonitor $cm */
$cm = $this->get_api();
$custom_data = array();
$lists = array();
$allowed_types = array(
'Text',
);
try {
$clients = $cm->get_clients();
$client = current( $clients );
$lists = $cm->get_client_lists( $client['id'] );
} catch ( Exception $e ) {
}
foreach ( $lists as $list ) {
$custom_data[ $list['id'] ] = array();
try {
$custom_fields = $cm->get_list_custom_fields( $list['id'] );
foreach ( $custom_fields as $item ) {
if ( isset( $item['DataType'] ) && in_array( $item['DataType'], $allowed_types ) ) {
$custom_data[ $list['id'] ][] = $this->normalize_custom_field( $item );
}
}
} catch ( Exception $e ) {
}
}
$this->_save_custom_fields( $custom_data );
return $custom_data;
}
/**
* @param array $field
*
* @return array
*/
protected function normalize_custom_field( $field = array() ) {
return array(
'id' => ! empty( $field['Key'] ) ? $field['Key'] : '',
'name' => ! empty( $field['FieldName'] ) ? $field['FieldName'] : '',
'type' => ! empty( $field['DataType'] ) ? $field['DataType'] : '',
'label' => ! empty( $field['FieldName'] ) ? $field['FieldName'] : '',
);
}
/**
* Build custom fields mapping for automations
*
* @param $automation_data
*
* @return array
*/
public function build_automation_custom_fields( $automation_data ) {
$mapped_data = [];
foreach ( $automation_data['api_fields'] as $pair ) {
$mapped_data[] = array(
'Key' => $pair['key'],
'Value' => sanitize_text_field( $pair['value'] ),
);
}
return $mapped_data;
}
/**
* Generate custom fields array
*
* @param array $args
*
* @return array
*/
private function _generate_custom_fields( $args ) {
$custom_fields = $this->get_api_custom_fields( array() );
if ( empty( $custom_fields[ $args['list_id'] ] ) ) {
return array();
}
$custom_fields = $custom_fields[ $args['list_id'] ];
$mapped_custom_fields = $this->build_mapped_custom_fields( $args );
$result = array();
foreach ( $mapped_custom_fields as $key => $custom_field ) {
$field_key = strpos( $custom_field['type'], 'mapping_' ) !== false ? $custom_field['type'] . '_' . $key : $key;
$field_key = str_replace( '[]', '', $field_key );
if ( ! empty( $args[ $field_key ] ) ) {
$args[ $field_key ] = $this->process_field( $args[ $field_key ] );
}
$is_in_list = array_filter(
$custom_fields,
function ( $field ) use ( $custom_field ) {
return $custom_field['value'] === $field['id'];
}
);
if ( ! empty( $is_in_list ) && isset( $args[ $field_key ] ) ) {
$result[] = array(
'Key' => $custom_field['value'],
'Value' => sanitize_text_field( $args[ $field_key ] ),
);
}
}
return $result;
}
/**
* Build mapped custom fields array based on form params
*
* @param $args
*
* @return array
*/
public function build_mapped_custom_fields( $args ) {
$mapped_data = array();
// Should be always base_64 encoded of a serialized array
if ( empty( $args['tve_mapping'] ) || ! tve_dash_is_bas64_encoded( $args['tve_mapping'] ) || ! is_serialized( base64_decode( $args['tve_mapping'] ) ) ) {
return $mapped_data;
}
$form_data = thrive_safe_unserialize( base64_decode( $args['tve_mapping'] ) );
$mapped_fields = $this->get_mapped_field_ids();
foreach ( $mapped_fields as $mapped_field_name ) {
// {ex: [mapping_url_0, .. mapping_url_n] / [mapping_text_0, .. mapping_text_n]}
$cf_form_fields = preg_grep( "#^{$mapped_field_name}#i", array_keys( $form_data ) );
if ( ! empty( $cf_form_fields ) && is_array( $cf_form_fields ) ) {
foreach ( $cf_form_fields as $cf_form_name ) {
if ( empty( $form_data[ $cf_form_name ][ $this->_key ] ) ) {
continue;
}
$field_id = str_replace( $mapped_field_name . '_', '', $cf_form_name );
$mapped_data[ $field_id ] = array(
'type' => $mapped_field_name,
'value' => $form_data[ $cf_form_name ][ $this->_key ],
);
}
}
}
return $mapped_data;
}
/**
* @param $email
* @param array $custom_fields
* @param array $extra
*
* @return int
*/
public function add_custom_fields( $email, $custom_fields = array(), $extra = array() ) {
try {
/** @var Thrive_Dash_Api_CampaignMonitor $aweber */
$api = $this->get_api();
$list_id = ! empty( $extra['list_identifier'] ) ? $extra['list_identifier'] : null;
$args = array(
'email' => $email,
);
if ( ! empty( $extra['name'] ) ) {
$args['name'] = $extra['name'];
}
$args['CustomFields'] = $this->prepare_custom_fields_for_api( $custom_fields, $list_id );
$this->add_subscriber( $list_id, $args );
} catch ( Exception $e ) {
return $e->getMessage();
}
}
/**
* Get available custom fields for this api connection
*
* @param null $list_id
*
* @return array
*/
public function get_available_custom_fields( $list_id = null ) {
return $this->get_api_custom_fields( null, true );
}
/**
* Prepare custom fields for api call
*
* @param array $custom_fields
* @param null $list_identifier
*
* @return array
*/
protected function prepare_custom_fields_for_api( $custom_fields = array(), $list_identifier = null ) {
if ( empty( $list_identifier ) ) { // list identifier required here
return array();
}
$api_fields = $this->get_api_custom_fields( null, true );
if ( empty( $api_fields[ $list_identifier ] ) ) {
return array();
}
$prepared_fields = array();
foreach ( $api_fields[ $list_identifier ] as $field ) {
foreach ( $custom_fields as $key => $custom_field ) {
if ( $field['id'] === $key ) {
$prepared_fields[] = array(
'Key' => $key,
'Value' => $custom_field,
);
unset( $custom_fields[ $key ] ); // avoid unnecessary loops
}
}
if ( empty( $custom_fields ) ) {
break;
}
}
return $prepared_fields;
}
public function has_custom_fields() {
return true;
}
public function get_automator_add_autoresponder_mapping_fields() {
return array( 'autoresponder' => array( 'mailing_list' => array( 'api_fields' ) ) );
}
}

View File

@@ -0,0 +1,341 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class Thrive_Dash_List_Connection_CampaignMonitorEmail extends Thrive_Dash_List_Connection_Abstract {
/**
* Return if the connection is in relation with another connection so we won't show it in the API list
*
* @return bool
*/
public function is_related() {
return true;
}
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'email';
}
/**
* @return string
*/
public function get_title() {
return 'Campaign Monitor';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'campaignmonitoremail' );
}
/**
* Just saves the key in the database
*
* @return mixed|Thrive_Dash_List_Connection_Abstract
* @throws Exception
*/
public function read_credentials() {
$key = ! empty( $_POST['connection']['key'] ) ? sanitize_text_field( $_POST['connection']['key'] ) : '';
$email = ! empty( $_POST['connection']['email'] ) ? sanitize_email( $_POST['connection']['email'] ) : '';
if ( empty( $key ) ) {
return $this->error( __( 'You must provide a valid Campaign Monitor key', 'thrive-dash' ) );
}
$this->set_credentials( compact( 'key', 'email' ) );
$result = $this->test_connection();
if ( $result !== true ) {
return $this->error( sprintf( __( 'Could not connect to Campaign Monitor using the provided key (<strong>%s</strong>)', 'thrive-dash' ), $result ) );
}
/**
* finally, save the connection details
*/
$this->save();
/**
* Try to connect to the autoresponder too
*/
/** @var Thrive_Dash_List_Connection_CampaignMonitor $related_api */
$related_api = Thrive_Dash_List_Manager::connection_instance( 'campaignmonitor' );
$r_result = true;
if ( ! $related_api->is_connected() ) {
$_POST['connection']['new_connection'] = isset( $_POST['connection']['new_connection'] ) ? sanitize_text_field( $_POST['connection']['new_connection'] ) : 1;
$r_result = $related_api->read_credentials();
}
if ( $r_result !== true ) {
$this->disconnect();
return $this->error( $r_result );
}
return $this->success( __( 'Campaign Monitor connected successfully', 'thrive-dash' ) );
}
/**
* Tests if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
* @throws Exception
*/
public function test_connection() {
/** @var Thrive_Dash_Api_CampaignMonitor $cm */
$cm = $this->get_api();
$from_email = '';
$to = '';
if ( isset( $_POST['connection']['email'] ) ) {
$from_email = sanitize_email( $_POST['connection']['email'] );
$to = sanitize_email( $_POST['connection']['email'] );
} else {
$credentials = Thrive_Dash_List_Manager::credentials( 'campaignmonitoremail' );
if ( isset( $credentials ) ) {
$from_email = $credentials['email'];
$to = $credentials['email'];
}
}
$args = array(
'Subject' => 'API connection test',
'From' => $from_email,
'BBC' => null,
'Html' => 'This is a test email from Thrive Leads Campaign Monitor API.',
'Text' => 'This is a test email from Thrive Leads Campaign Monitor API.',
'To' => array(
$to,
),
'TrackOpens' => true,
'TrackClicks' => true,
'InlineCSS' => true,
);
try {
$clients = $cm->get_clients();
$current_client = current( $clients );
/** @var Thrive_Dash_Api_CampaignMonitor_ClassicEmail $email */
$email = $cm->transactional();
$email->set_client( $current_client['id'] );
$email->send( $args );
} catch ( Exception $e ) {
return $e->getMessage();
}
$connection = get_option( 'tve_api_delivery_service', false );
if ( $connection == false ) {
update_option( 'tve_api_delivery_service', 'campaignmonitoremail' );
}
return true;
}
/**
* Send the email to the user
*
* @param $post_data
*
* @return bool|string
* @throws Exception
*/
public function sendEmail( $post_data ) {
$cm = $this->get_api();
$asset = get_post( $post_data['_asset_group'] );
if ( empty( $asset ) || ! ( $asset instanceof WP_Post ) || $asset->post_status !== 'publish' ) {
throw new Exception( sprintf( __( 'Invalid Asset Group: %s. Check if it exists or was trashed.', 'thrive-dash' ), $post_data['_asset_group'] ) );
}
$files = get_post_meta( $post_data['_asset_group'], 'tve_asset_group_files', true );
$subject = get_post_meta( $post_data['_asset_group'], 'tve_asset_group_subject', true );
if ( $subject === '' ) {
$subject = get_option( 'tve_leads_asset_mail_subject' );
}
$credentials = Thrive_Dash_List_Manager::credentials( 'campaignmonitoremail' );
if ( isset( $credentials ) ) {
$from_email = $credentials['email'];
} else {
return false;
}
$html_content = $asset->post_content;
if ( $html_content === '' ) {
$html_content = get_option( 'tve_leads_asset_mail_body' );
}
$attached_files = array();
foreach ( $files as $file ) {
$attached_files[] = '<a href="' . $file['link'] . '">' . $file['link_anchor'] . '</a><br/>';
}
$the_files = implode( '<br/>', $attached_files );
$html_content = str_replace( '[asset_download]', $the_files, $html_content );
$html_content = str_replace( '[asset_name]', $asset->post_title, $html_content );
$subject = str_replace( '[asset_name]', $asset->post_title, $subject );
if ( isset( $post_data['name'] ) && ! empty( $post_data['name'] ) ) {
$html_content = str_replace( '[lead_name]', $post_data['name'], $html_content );
$subject = str_replace( '[lead_name]', $post_data['name'], $subject );
$visitor_name = $post_data['name'];
} else {
$html_content = str_replace( '[lead_name]', '', $html_content );
$subject = str_replace( '[lead_name]', '', $subject );
$visitor_name = '';
}
$text_content = strip_tags( $html_content );
$to = $post_data['email'];
if ( ! empty( $visitor_name ) ) {
$to = $visitor_name . ' <' . $to . '>';
}
$message = array(
'Subject' => $subject,
'Html' => $html_content,
'Text' => $text_content,
'BBC' => null,
'From' => $from_email,
'To' => $to,
'TrackOpens' => true,
'TrackClicks' => true,
'InlineCSS' => true,
);
try {
$clients = $cm->get_clients();
$current_client = current( $clients );
/** @var Thrive_Dash_Api_CampaignMonitor_ClassicEmail $email */
$email = $cm->transactional();
$email->set_client( $current_client['id'] );
$email->send( $message );
} catch ( Exception $e ) {
throw new Exception( $e->getMessage() );
}
return true;
}
/**
* Instantiates the API code required for this connection
*
* @return mixed
*/
protected function get_api_instance() {
return new Thrive_Dash_Api_CampaignMonitor( $this->param( 'key' ) );
}
/**
* Gets all Subscriber Lists from this API service
*
* @return array
*/
protected function _get_lists() {
return array();
}
/**
* Adds contact to a list
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return bool|string true for success or string error message for failure
*/
public function add_subscriber( $list_identifier, $arguments ) {
return true;
}
/**
* Send emails to the user
*
* @param array $data
*
* @return bool|string
*/
public function sendMultipleEmails( $data ) {
$cm = $this->get_api();
$message = array(
'Subject' => $data['subject'],
'Html' => $data['html_content'],
'Text' => '',
'BBC' => $data['bcc'],
'CC' => $data['cc'],
'From' => $data['from_name'] . '< ' . $data['from_email'] . ' >',
'ReplyTo' => empty( $data['reply_to'] ) ? '' : $data['reply_to'],
'To' => $data['emails'],
);
try {
$clients = $cm->get_clients();
$current_client = current( $clients );
/** @var Thrive_Dash_Api_CampaignMonitor_ClassicEmail $email */
$email = $cm->transactional();
$email->set_client( $current_client['id'] );
$email->send( $message );
} catch ( Exception $e ) {
return $e->getMessage();
}
if ( ! empty( $data['send_confirmation'] ) ) {
$confirmation_email = array(
'Subject' => $data['confirmation_subject'],
'Html' => $data['confirmation_html'],
'Text' => '',
'BBC' => '',
'CC' => '',
'From' => $data['from_name'] . '< ' . $data['from_email'] . ' >',
'To' => array( $data['sender_email'] ),
'ReplyTo' => $data['from_email'],
);
try {
$clients = $cm->get_clients();
$current_client = current( $clients );
/** @var Thrive_Dash_Api_CampaignMonitor_ClassicEmail $email */
$email = $cm->transactional();
$email->set_client( $current_client['id'] );
$email->send( $confirmation_email );
} catch ( Exception $e ) {
return $e->getMessage();
}
}
return true;
}
}

View File

@@ -0,0 +1,182 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_ConstantContact extends Thrive_Dash_List_Connection_Abstract {
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'autoresponder';
}
/**
* Application API Key
*/
const TOKEN_URL = 'https://api.constantcontact.com/mashery/account/';
/**
* @return string the API connection title
*/
public function get_title() {
return 'Constant Contact (Archived)';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'constant-contact' );
}
public function getTokenUrl() {
return self::TOKEN_URL;
}
/**
* should handle: read data from post / get, test connection and save the details
*
* on error, it should register an error message (and redirect?)
*
* @return mixed
*/
public function read_credentials() {
$api_key = ! empty( $_POST['connection']['api_key'] ) ? sanitize_text_field( $_POST['connection']['api_key'] ) : '';
$api_token = ! empty( $_POST['connection']['api_token'] ) ? sanitize_text_field( $_POST['connection']['api_token'] ) : '';
if ( empty( $api_key ) || empty( $api_token ) ) {
return $this->error( __( 'You must provide a valid Constant Contact API Key and API token', 'thrive-dash' ) );
}
$this->set_credentials( array( 'api_key' => $api_key, 'api_token' => $api_token ) );
$result = $this->test_connection();
if ( $result !== true ) {
return $this->error( sprintf( __( 'Could not connect to Constant Contact using the provided API Key and API Token (<strong>%s</strong>)', 'thrive-dash' ), $result ) );
}
/**
* finally, save the connection details
*/
$this->save();
return $this->success( __( 'Constant Contact connected successfully', 'thrive-dash' ) );
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
try {
/** @var Thrive_Dash_Api_ConstantContact $api */
$api = $this->get_api();
$api->getLists();
return true;
} catch ( Exception $e ) {
return $e->getMessage();
}
}
/**
* instantiate the API code required for this connection
*
* @return mixed
*/
protected function get_api_instance() {
return new Thrive_Dash_Api_ConstantContact( $this->param( 'api_key' ), $this->param( 'api_token' ) );
}
/**
* get all Subscriber Lists from this API service
*
* @return array|bool for error
*/
protected function _get_lists() {
try {
$lists = array();
/** @var Thrive_Dash_Api_ConstantContact $api */
$api = $this->get_api();
foreach ( $api->getLists() as $item ) {
$lists[] = array(
'id' => $item['id'],
'name' => $item['name'],
);
}
return $lists;
} catch ( Exception $e ) {
$this->_error = $e->getMessage();
return false;
}
}
/**
* add a contact to a list
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return mixed
*/
public function add_subscriber( $list_identifier, $arguments ) {
try {
/** @var Thrive_Dash_Api_ConstantContact $api */
$api = $this->get_api();
$user = array(
'email' => $arguments['email'],
);
list( $first_name, $last_name ) = explode( " ", ! empty( $arguments['name'] ) ? $arguments['name'] . " " : ' ' );
if ( ! empty( $arguments['phone'] ) ) {
$user['work_phone'] = $arguments['phone'];
}
if ( ! empty( $first_name ) ) {
$user['first_name'] = $first_name;
}
if ( ! empty( $last_name ) ) {
$user['last_name'] = $last_name;
}
$api->addContact( $list_identifier, $user );
} catch ( Exception $e ) {
return $e->getMessage();
}
return true;
}
/**
* Return the connection email merge tag
*
* @return String
*/
public static function get_email_merge_tag() {
return '{Email Address}';
}
}

View File

@@ -0,0 +1,441 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_ConstantContactV3 extends Thrive_Dash_List_Connection_Abstract {
public static function get_type() {
return 'autoresponder';
}
public function get_title() {
return 'Constant Contact';
}
public function has_tags() {
return true;
}
/**
* Builds an authorization URI - the user will be redirected to that URI and asked to give app access
*
* @return string
*/
public function getAuthorizeUrl() {
$this->save(); // save the client_id and client_secret for later use
return $this->get_api()->get_authorize_url();
}
/**
* whether or not this list is connected to the service (has been authenticated)
*
* @return bool
*/
public function is_connected() {
return $this->param( 'access_token' ) && $this->param( 'refresh_token' );
}
public function output_setup_form() {
$this->output_controls_html( 'constant-contact-v3' );
}
/**
* Called during the redirect from constant contact oauth flow
*
* _REQUEST contains a `code` parameter which needs to be sent back to g.api in exchange for an access token
*
* @return bool|mixed|string|Thrive_Dash_List_Connection_Abstract
*/
public function read_credentials() {
$code = empty( $_REQUEST['code'] ) ? '' : $_REQUEST['code'];
if ( empty( $code ) ) {
return $this->error( 'Missing `code` parameter' );
}
try {
/* get access token from constant contact API */
$response = $this->get_api()->get_access_token( $code );
if ( empty( $response['access_token'] ) ) {
throw new Thrive_Dash_Api_ConstantContactV3_Exception( 'Missing token from response data' );
}
$this->_credentials = array(
'client_id' => $this->param( 'client_id' ),
'client_secret' => $this->param( 'client_secret' ),
'access_token' => $response['access_token'],
'expires_at' => time() + $response['expires_in'],
'refresh_token' => $response['refresh_token'],
);
$this->save();
/**
* Fetch all custom fields on connect so that we have them all prepared
* - TAr doesn't need to get them from API
*/
$this->get_api_custom_fields( array(), true, true );
} catch ( Thrive_Dash_Api_ConstantContactV3_Exception $e ) {
echo 'caught ex: ' . esc_html( $e->getMessage() );
$this->_credentials = array();
$this->save();
$this->error( $e->getMessage() );
return false;
}
return true;
}
/**
* Test the connection to the service.
*
* @return void
*/
public function test_connection() {
$result = array(
'success' => true,
'message' => __( 'Connection works', 'thrive-dash' ),
);
try {
$this->get_api()->get_account_details(); // this will throw the exception if there is a connection problem
} catch ( Thrive_Dash_Api_ConstantContactV3_Exception $e ) {
$result['success'] = false;
$result['message'] = $e->getMessage();
}
return $result;
}
/**
* Instantiate the service and set any available data
*
* @return Thrive_Dash_Api_ConstantContactV3_Service
*/
protected function get_api_instance() {
$api = new Thrive_Dash_Api_ConstantContactV3_Service(
$this->param( 'client_id' ),
$this->param( 'client_secret' ),
$this->param( 'access_token' )
);
/* check for expired token and renew it */
if ( $this->param( 'refresh_token' ) && $this->param( 'expires_at' ) && time() > (int) $this->param( 'expires_at' ) ) {
$data = $api->refresh_access_token( $this->param( 'refresh_token' ) );
$this->_credentials['access_token'] = $data['access_token'];
$this->_credentials['refresh_token'] = $data['refresh_token'];
$this->_credentials['expires_at'] = time() + $data['expires_in'];
$this->save();
}
return $api;
}
protected function _get_lists() {
return $this->get_api()->getLists();
}
/**
* Add a subscriber to a list.
*
* @param string $list_identifier Contact list identifier.
* @param array $arguments Subscriber data.
* @return bool
*/
public function add_subscriber( $list_identifier, $arguments ) {
// add logic here.
$params = array(
'create_source' => 'Contact',
'list_memberships' => array( $list_identifier ),
);
if ( $arguments['email'] ) {
$params['email_address'] = array(
'address' => $arguments['email'],
'permission_to_send' => 'implicit',
);
}
if ( $arguments['name'] ) {
$split_name = $this->_splitFullName( $arguments['name'] );
$params['first_name'] = $split_name['first_name'];
$params['last_name'] = $split_name['last_name'];
}
if ( $arguments['first_name'] ) {
$params['first_name'] = $arguments['first_name'];
}
if ( $arguments['last_name'] ) {
$params['last_name'] = $arguments['last_name'];
}
if ( $arguments['phone'] ) {
$params['phone_number'] = $arguments['phone'];
}
// Handle tags - get or create tag IDs BEFORE contact creation.
if ( ! empty( $arguments['constantcontact_v3_tags'] ) ) {
$tag_names = explode( ',', trim( $arguments['constantcontact_v3_tags'], ' ,' ) );
$tag_names = array_map( 'trim', $tag_names );
$tag_names = array_filter( $tag_names ); // Remove empty tags.
// Get or create tag IDs.
$tag_ids = $this->get_or_create_tag_ids( $tag_names );
if ( ! empty( $tag_ids ) ) {
$params['taggings'] = $tag_ids; // Pass tag IDs to API wrapper.
}
}
$params = array_merge( $params, $this->_generateMappingFields( $arguments ) );
return $this->get_api()->addSubscriber( $params );
}
/**
* Get or create tag IDs.
*
* @param [type] $tag_names Tag names.
* @return array
*/
private function get_or_create_tag_ids( $tag_names ) {
$tag_ids = array();
try {
// Get all existing tags first - GET /contact_tags.
$existing_tags = $this->get_api()->getAllTags();
$tag_map = array();
// Create a map of tag name => tag_id (case-insensitive).
if ( is_array( $existing_tags ) && isset( $existing_tags['tags'] ) ) {
foreach ( $existing_tags['tags'] as $tag ) {
if ( isset( $tag['name'] ) && isset( $tag['tag_id'] ) ) {
$tag_map[ strtolower( trim( $tag['name'] ) ) ] = $tag['tag_id'];
}
}
}
// Process each tag name.
foreach ( $tag_names as $tag_name ) {
$tag_key = strtolower( trim( $tag_name ) );
// Check if tag already exists.
if ( isset( $tag_map[ $tag_key ] ) ) {
$tag_ids[] = $tag_map[ $tag_key ];
} else {
// Create new tag and get its ID.
$new_tag_id = $this->create_new_tag( $tag_name );
if ( $new_tag_id ) {
$tag_ids[] = $new_tag_id;
}
}
}
} catch ( Exception $e ) {
error_log( 'ConstantContactV3: Failed to get or create tag IDs - ' . $e->getMessage() );
}
return $tag_ids;
}
/**
* Create a new tag using POST /contact_tags.
*
* @param string $tag_name Tag name.
* @return int|null Tag ID.
*/
private function create_new_tag( $tag_name ) {
try {
$tag_data = array(
'name' => trim( $tag_name ),
'tag_source' => 'API', // Indicates this tag was created via API.
);
$result = $this->get_api()->createTag( $tag_data );
if ( is_array( $result ) && isset( $result['tag_id'] ) ) {
return $result['tag_id'];
}
} catch ( Exception $e ) {
error_log( 'ConstantContactV3: Failed to create tag "' . $tag_name . '" - ' . $e->getMessage() );
}
return false;
}
/**
* Get first name and last name from full name.
*
* @param string $full_name full name.
* @return array
*/
private function _splitFullName( $full_name = '' ) {
$full_name = trim( preg_replace( '/\s+/', ' ', $full_name ) );
$result = [
'first_name' => '',
'last_name' => '',
];
if ( empty( $full_name ) ) {
return $result;
}
$name_parts = explode( ' ', $full_name );
if ( count( $name_parts ) === 1 ) {
$result['first_name'] = $name_parts[0];
return $result;
}
$result['first_name'] = array_shift( $name_parts );
$result['last_name'] = implode( ' ', $name_parts );
return $result;
}
/**
* Return the connection email merge tag
*
* @return String
*/
public static function get_email_merge_tag() {
return '{$email}';
}
/**
* Get the custom fields for the API.
*
* @param array $params Parameters.
* @param boolean $force Force.
* @param boolean $get_all Get all.
* @return array
*/
public function get_api_custom_fields( $params, $force = false, $get_all = false ) {
// Serve from cache if exists and requested.
$cached_data = $this->get_cached_custom_fields();
if ( false === $force && ! empty( $cached_data ) ) {
return $cached_data;
}
$custom_data = $this->get_api()->getAllFields();
$this->_save_custom_fields( $custom_data );
return $custom_data;
}
/**
* Generate mapping fields array
*
* @param array $args
*
* @return array
*/
private function _generateMappingFields( $args = array() ) {
$mapping_fields = array();
$tve_mapping = unserialize( base64_decode( $args['tve_mapping'] ) );
if ( ! is_array( $tve_mapping ) || 0 === count( $tve_mapping ) ) {
return $mapping_fields;
}
foreach ( $tve_mapping as $key => $value ) {
$field_name = reset( $value );
$field_type = $value['_field'];
$field_value = $args[ $key ];
if ( 'date' === $field_type ) {
$field_value = $this->formatDateValue( $field_value );
}
if ( ! empty( $args[ $key ] ) ) {
// check if the field name is in this format 87a47d98-c8ef-11ef-a282-fa163eb4f69a then it is a custom field.
if ( preg_match( '/[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}/', $field_name ) ) {
$mapping_fields['custom_fields'][] = array(
'custom_field_id' => $field_name,
'value' => $field_value,
);
} else {
$mapping_fields[ $field_name ] = $field_value;
if ( 'birthday_day' === $field_name || 'birthday_month' === $field_name ) {
$mapping_fields[ $field_name ] = (int) $field_value;
}
}
}
}
return $mapping_fields;
}
/**
* Format date value to d/m/Y format.
*
* @param String $date_string Date string.
* @return String
*/
private function formatDateValue( $date_string ) {
$formatted_date = '';
// check if $date_string is in the format of M, d, Y.
if ( preg_match( '/[a-zA-Z]{3}, [0-9]{1,2}, [0-9]{4}/', $date_string ) ) {
$date_string = str_replace( ', ', '-', $date_string );
$formatted_date = gmdate( 'm/d/Y', strtotime( $date_string ) );
return $formatted_date;
}
// check if $date_string is in the format of d/m/Y but not m/d/Y.
if ( preg_match( '/^(0?[1-9]|[12][0-9]|3[01])\/(0?[1-9]|1[0-2])\/\d{4}$/', $date_string ) ) {
$date_parts = explode( '/', $date_string );
if ( checkdate( $date_parts[1], $date_parts[0], $date_parts[2] ) ) {
$formatted_date = gmdate( 'm/d/Y', strtotime( str_replace( '/', '-', $date_string ) ) );
return $formatted_date;
}
}
$formatted_date = gmdate( 'm/d/Y', strtotime( $date_string ) );
return $formatted_date;
}
/**
* Get available custom fields for this api connection
*
* @param null $list_id
*
* @return array
*/
public function get_available_custom_fields( $list_id = null ) {
return $this->get_api_custom_fields( null, true );
}
/**
* Define support for custom fields.
*
* @return boolean
*/
public function has_custom_fields() {
return true;
}
public function get_automator_add_autoresponder_mapping_fields() {
return array( 'autoresponder' => array( 'mailing_list', 'api_fields', 'tag_input' ) );
}
}

View File

@@ -0,0 +1,470 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_ConvertKit extends Thrive_Dash_List_Connection_Abstract {
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'autoresponder';
}
/**
* @return string the API connection title
*/
public function get_title() {
return 'ConvertKit / Seva';
}
/**
* @return bool
*/
public function has_tags() {
return true;
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'convertkit' );
}
/**
* should handle: read data from post / get, test connection and save the details
*
* on error, it should register an error message (and redirect?)
*
* @return mixed
*/
public function read_credentials() {
$key = ! empty( $_POST['connection']['key'] ) ? sanitize_text_field( $_POST['connection']['key'] ) : '';
if ( empty( $key ) ) {
return $this->error( __( 'You must provide a valid ConvertKit API Key', 'thrive-dash' ) );
}
$this->set_credentials( array( 'key' => $key ) );
$result = $this->test_connection();
if ( $result !== true ) {
return $this->error( sprintf( __( 'Could not connect to ConvertKit: %s', 'thrive-dash' ), $this->_error ) );
}
/**
* finally, save the connection details
*/
$this->save();
return $this->success( __( 'ConvertKit connected successfully', 'thrive-dash' ) );
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
return is_array( $this->_get_lists() );
}
/**
* instantiate the API code required for this connection
*
* @return Thrive_Dash_Api_ConvertKit
*/
protected function get_api_instance() {
return new Thrive_Dash_Api_ConvertKit( $this->param( 'key' ) );
}
/**
* get all Subscriber Lists from this API service
*
* ConvertKit has both sequences and forms
*
* @return array|string for error
*/
protected function _get_lists() {
/**
* just try getting the lists as a connection test
*/
try {
/** @var $api Thrive_Dash_Api_ConvertKit */
$api = $this->get_api();
$lists = array();
$data = $api->get_forms();
if ( ! empty( $data ) ) {
foreach ( $data as $form ) {
if ( ! empty( $form['archived'] ) ) {
continue;
}
$lists[] = array(
'id' => $form['id'],
'name' => $form['name'],
);
}
}
return $lists;
} catch ( Thrive_Dash_Api_ConvertKit_Exception $e ) {
$this->_error = $e->getMessage();
return false;
}
}
/**
* add a contact to a list
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return mixed
*/
public function add_subscriber( $list_identifier, $arguments ) {
try {
/** @var $api Thrive_Dash_Api_ConvertKit */
$api = $this->get_api();
$arguments['custom_fields_ids'] = $this->buildMappedCustomFields( $arguments );
$arguments['fields'] = new stdClass();
// Allow usage of single quote in name.
if ( isset( $arguments['name'] ) ) {
$arguments['name'] = str_replace( "\\'", "'", $arguments['name'] );
}
if ( ! empty( $arguments['custom_fields_ids'] ) ) {
$arguments['fields'] = $this->_generateCustomFields( $arguments );
} else if ( ! empty( $arguments['automator_custom_fields'] ) ) {
$arguments['fields'] = $arguments['automator_custom_fields'];
unset( $arguments['automator_custom_fields'] );
}
$api->subscribeForm( $list_identifier, $arguments );
} catch ( Exception $e ) {
return $e->getMessage();
}
return true;
}
/**
* Get custom fields
*
* @return array
*/
public function getCustomFields() {
/** @var Thrive_Dash_Api_ConvertKit $api */
$api = $this->get_api();
$fields = $api->getCustomFields();
return isset( $fields['custom_fields'] ) ? $fields['custom_fields'] : array();
}
/**
* @param array $args
*
* @return object
* @throws Thrive_Dash_Api_ConvertKit_Exception
*/
protected function _generateCustomFields( $args ) {
/** @var Thrive_Dash_Api_ConvertKit $api */
$api = $this->get_api();
$fields = $this->_getCustomFields( false );
$response = array();
$ids = $this->buildMappedCustomFields( $args );
foreach ( $fields as $field ) {
foreach ( $ids as $key => $id ) {
if ( (int) $field['id'] === (int) $id['value'] ) {
/**
* Ex cf: ck_field_84479_first_custom_field
* Needed Result: first_custom_field
*/
$_name = $field['name'];
$_name = str_replace( 'ck_field_', '', $_name );
$_name = explode( '_', $_name );
unset( $_name[0] );
$_name = implode( '_', $_name );
$name = strpos( $id['type'], 'mapping_' ) !== false ? $id['type'] . '_' . $key : $key;
$cf_form_name = str_replace( '[]', '', $name );
if ( ! empty( $args[ $cf_form_name ] ) ) {
$response[ $_name ] = $this->process_field( $args[ $cf_form_name ] );
}
}
}
}
if ( ! empty( $args['phone'] ) ) {
$phone_fields = $api->phoneFields( $args['phone'] );
$response['phone'] = isset( $phone_fields['phone'] ) ? $phone_fields['phone'] : '';
}
return (object) $response;
}
/**
* Build custom fields mapping for automations
*
* @param $automation_data
*
* @return object
*/
public function build_automation_custom_fields( $automation_data ) {
$mapped_data = [];
$fields = $this->_getCustomFields( false );
foreach ( $automation_data['api_fields'] as $pair ) {
$value = sanitize_text_field( $pair['value'] );
if ( $value ) {
foreach ( $fields as $field ) {
if ( (int) $field['id'] === (int) $pair['key'] ) {
/**
* Ex cf: ck_field_84479_first_custom_field
* Needed Result: first_custom_field
*/
$_name = $field['name'];
$_name = str_replace( 'ck_field_', '', $_name );
$_name = explode( '_', $_name );
unset( $_name[0] );
$_name = implode( '_', $_name );
$mapped_data[ $_name ] = $value;
}
}
}
}
return (object) $mapped_data;
}
/**
* Return the connection email merge tag
*
* @return String
*/
public static function get_email_merge_tag() {
return '{{subscriber.email_address}}';
}
/**
* @param $force
*
* @return array
*/
protected function _getCustomFields( $force ) {
// Serve from cache if exists and requested
$cached_data = $this->get_cached_custom_fields();
if ( false === $force && ! empty( $cached_data ) ) {
return $cached_data;
}
/** @var $api Thrive_Dash_Api_ConvertKit */
$api = $this->get_api();
$fields = $api->getCustomFields();
$fields = isset( $fields['custom_fields'] ) ? $fields['custom_fields'] : array();
foreach ( $fields as $key => $field ) {
$fields[ $key ] = $this->normalize_custom_field( $field );
}
$this->_save_custom_fields( $fields );
return $fields;
}
/**
* @param $params
* @param bool $force
* @param bool $get_all
*
* @return array
* @throws Thrive_Dash_Api_ConvertKit_Exception
*/
public function get_api_custom_fields( $params, $force = false, $get_all = false ) {
$response = $this->_getCustomFields( $force );
return is_array( $response ) ? $response : array();
}
protected function normalize_custom_field( $data ) {
$data['type'] = 'text';
return parent::normalize_custom_field( $data );
}
/**
* Build mapped custom fields array based on form params
*
* @param $args
*
* @return array
*/
public function buildMappedCustomFields( $args ) {
$mapped_data = array();
// Should be always base_64 encoded of a serialized array
if ( empty( $args['tve_mapping'] ) || ! tve_dash_is_bas64_encoded( $args['tve_mapping'] ) || ! is_serialized( base64_decode( $args['tve_mapping'] ) ) ) {
return $mapped_data;
}
$form_data = thrive_safe_unserialize( base64_decode( $args['tve_mapping'] ) );
$mapped_fields = $this->get_mapped_field_ids();
foreach ( $mapped_fields as $mapped_field_name ) {
// Extract an array with all custom fields (siblings) names from form data
// {ex: [mapping_url_0, .. mapping_url_n] / [mapping_text_0, .. mapping_text_n]}
$cf_form_fields = preg_grep( "#^{$mapped_field_name}#i", array_keys( $form_data ) );
// Matched "form data" for current allowed name
if ( ! empty( $cf_form_fields ) && is_array( $cf_form_fields ) ) {
// Pull form allowed data, sanitize it and build the custom fields array
foreach ( $cf_form_fields as $cf_form_name ) {
if ( empty( $form_data[ $cf_form_name ][ $this->_key ] ) ) {
continue;
}
$field_id = str_replace( $mapped_field_name . '_', '', $cf_form_name );
$mapped_data[ $field_id ] = array(
'type' => $mapped_field_name,
'value' => $form_data[ $cf_form_name ][ $this->_key ],
);
}
}
}
return $mapped_data;
}
/**
* @param $email
* @param array $custom_fields ex array( 'cf_name' => 'some nice cf value' )
* @param array $extra
*
* @return false|int|mixed
*/
public function add_custom_fields( $email, $custom_fields = array(), $extra = array() ) {
if ( empty( $extra['list_identifier'] ) ) {
return false;
}
try {
/** @var $api Thrive_Dash_Api_ConvertKit */
$api = $this->get_api();
$args = array(
'fields' => (object) $this->prepare_custom_fields_for_api( $custom_fields ),
'email' => $email,
'name' => ! empty( $extra['name'] ) ? $extra['name'] : '',
);
$subscriber = $api->subscribeForm( $extra['list_identifier'], $args );
return $subscriber['subscriber']['id'];
} catch ( Exception $e ) {
return false;
}
}
/**
* delete a contact from the list
*
* @param string $email
* @param array $arguments
*
* @return mixed
*/
public function delete_subscriber( $email, $arguments = array() ) {
$api = $this->get_api();
$result = $api->unsubscribeUser( $email, $arguments );
return isset( $result['subscriber']['id'] );
}
/**
* Get available custom fields for this api connection
*
* @param null $list_id
*
* @return array
*/
public function get_available_custom_fields( $list_id = null ) {
return $this->_getCustomFields( true );
}
/**
* Prepare custom fields for api call
*
* @param array $custom_fields
* @param null $list_identifier
*
* @return array
*/
public function prepare_custom_fields_for_api( $custom_fields = array(), $list_identifier = null ) {
$prepared_fields = array();
$cf_prefix = 'ck_field_';
$api_fields = $this->get_api_custom_fields( null, true );
foreach ( $api_fields as $field ) {
foreach ( $custom_fields as $key => $custom_field ) {
if ( (int) $field['id'] === (int) $key && $custom_field ) {
$str_to_replace = $cf_prefix . $field['id'] . '_';
$cf_key = str_replace( $str_to_replace, '', $field['name'] );
$prepared_fields[ $cf_key ] = $custom_field;
unset( $custom_fields[ $key ] ); // avoid unnecessary loops
}
}
if ( empty( $custom_fields ) ) {
break;
}
}
return $prepared_fields;
}
public function get_automator_add_autoresponder_mapping_fields() {
return array( 'autoresponder' => array( 'mailing_list' => array( 'api_fields' ), 'tag_input' => array() ) );
}
public function has_custom_fields() {
return true;
}
}

View File

@@ -0,0 +1,587 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_Drip extends Thrive_Dash_List_Connection_Abstract {
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'autoresponder';
}
/**
* Return the connection email merge tag
*
* @return String
*/
public static function get_email_merge_tag() {
return '{{ subscriber.email }}';
}
/**
* @return string the API connection title
*/
public function get_title() {
return 'Drip';
}
/**
* @return bool
*/
public function has_tags() {
return true;
}
public function has_custom_fields() {
return true;
}
/**
* @return bool
*/
public function has_optin() {
return true;
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'drip' );
}
/**
* should handle: read data from post / get, test connection and save the details
*
* on error, it should register an error message (and redirect?)
*
* @return mixed
*/
public function read_credentials() {
$token = ! empty( $_POST['connection']['token'] ) ? sanitize_text_field( $_POST['connection']['token'] ) : '';
$client_id = ! empty( $_POST['connection']['client_id'] ) ? sanitize_text_field( $_POST['connection']['client_id'] ) : '';
if ( empty( $token ) || empty( $client_id ) ) {
return $this->error( __( 'You must provide a valid Drip token and Client ID', 'thrive-dash' ) );
}
$this->set_credentials( array( 'token' => $token, 'client_id' => $client_id ) );
$result = $this->test_connection();
if ( $result !== true ) {
return $this->error( sprintf( __( 'Could not connect to Drip using the provided Token and Client ID (<strong>%s</strong>)', 'thrive-dash' ), $result ) );
}
/**
* finally, save the connection details
*/
$this->save();
return $this->success( __( 'Drip connected successfully', 'thrive-dash' ) );
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
try {
/** @var Thrive_Dash_Api_Drip $api */
$api = $this->get_api();
$accounts = $api->get_accounts();
if ( empty( $accounts ) || ! is_array( $accounts ) ) {
return __( 'Drip connection could not be validated!', 'thrive-dash' );
}
foreach ( $accounts['accounts'] as $account ) {
if ( $account['id'] === $this->param( 'client_id' ) ) {
return true;
}
}
return false;
} catch ( Exception $e ) {
return $e->getMessage();
}
}
/**
* add a contact to a list
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return mixed
*/
public function add_subscriber( $list_identifier, $arguments ) {
if ( ! empty( $arguments['name'] ) ) {
list( $first_name, $last_name ) = $this->get_name_parts( $arguments['name'] );
}
$phone = ! empty( $arguments['phone'] ) ? $arguments['phone'] : '';
$arguments['drip_optin'] = ! isset( $arguments['drip_optin'] ) ? 's' : $arguments['drip_optin'];
$double_optin = ! ( isset( $arguments['drip_optin'] ) && 's' === $arguments['drip_optin'] );
$field_first_name = isset( $arguments['drip_first_name_field'] ) ? $arguments['drip_first_name_field'] : 'thrive_first_name';
$field_last_name = isset( $arguments['drip_last_name_field'] ) ? $arguments['drip_last_name_field'] : 'thrive_last_name';
$url = wp_get_referer();
try {
/** @var Thrive_Dash_Api_Drip $api */
$api = $this->get_api();
$proprieties = new stdClass();
if ( isset( $first_name ) ) {
$proprieties->{$field_first_name} = $first_name;
}
if ( isset( $last_name ) ) {
$proprieties->{$field_last_name} = $last_name;
}
if ( isset( $phone ) ) {
$proprieties->thrive_phone = $phone;
}
$tags = ! empty( $arguments['drip_tags'] ) ? explode( ',', $arguments['drip_tags'] ) : array();
if ( isset( $arguments['drip_type'] ) && 'automation' === $arguments['drip_type'] ) {
$proprieties->thrive_referer = $url;
$proprieties->thrive_ip_address = sanitize_text_field( $_SERVER['REMOTE_ADDR'] ); //phpcs:ignore
if ( ! empty( $arguments['drip_field'] ) ) {
foreach ( $arguments['drip_field'] as $field => $field_value ) {
$proprieties->{$field} = $field_value;
}
}
}
if ( ! empty( $arguments['tve_mapping'] ) ) {
$fields = $this->prepare_api_custom_fields( $arguments );
$proprieties = (object) array_merge( (array) $proprieties, $fields );
} else if ( ! empty( $arguments['automator_custom_fields'] ) ) {
$proprieties = (object) array_merge( (array) $proprieties, $arguments['automator_custom_fields'] );
}
if ( ! empty( $tags ) ) {
foreach ( $tags as $tag ) {
$api->apply_tag( $arguments['email'], $tag, $this->param( 'client_id' ) );
}
}
$user = array(
'account_id' => $this->param( 'client_id' ),
'campaign_id' => $list_identifier,
'email' => $arguments['email'],
'ip_address' => sanitize_text_field( $_SERVER['REMOTE_ADDR'] ), // phpcs:ignore
'custom_fields' => $proprieties,
'status' => 'active',
);
if ( isset( $arguments['drip_type'] ) && 'list' === $arguments['drip_type'] ) {
$user['double_optin'] = $double_optin;
}
$lead = $api->create_or_update_subscriber( $user );
if ( empty( $user ) ) {
return __( 'User could not be subscribed', 'thrive-dash' );
}
if ( 'tag' !== $arguments['drip_type'] && ( ! isset( $arguments['drip_field'] ) || 'list' === $arguments['drip_type'] ) ) {
$client = array_shift( $lead['subscribers'] );
$api->subscribe_subscriber(
array(
'account_id' => $this->param( 'client_id' ),
'campaign_id' => $list_identifier,
'email' => $client['email'],
'double_optin' => $double_optin,
'tags' => $tags,
)
);
}
$api->record_event(
array(
'account_id' => $this->param( 'client_id' ),
'action' => 'Submitted a Thrive Leads form',
'email' => $arguments['email'],
'properties' => $proprieties,
)
);
return true;
} catch ( Thrive_Dash_Api_Drip_Exception_Unsubscribed $e ) {
//todo: rewrite this try
try {
$api->delete_subscriber( $user );
return $this->add_subscriber( $list_identifier, $arguments );
} catch ( Exception $e ) {
return $e->getMessage();
}
} catch ( Exception $e ) {
return $e->getMessage();
}
}
/**
* Allow the user to choose whether to have a single or a double optin for the form being edited
* It will hold the latest selected value in a cookie so that the user is presented by default with the same option selected the next time he edits such a form
*
* @param array $params
*
* @return mixed
*/
public function get_extra_settings( $params = array() ) {
$processed_params = array();
$params['optin'] = empty( $params['optin'] ) ? ( isset( $_COOKIE['tve_api_drip_optin'] ) ? sanitize_text_field( $_COOKIE['tve_api_drip_optin'] ) : 'd' ) : $params['optin'];
setcookie( 'tve_api_drip_optin', $params['optin'], strtotime( '+6 months' ), '/' );
if ( ! empty( $params ) ) {
foreach ( $params as $k => $v ) {
if ( strpos( $k, 'field[' ) !== false ) {
$key = str_replace( 'field[', '', $k );
$processed_params['proprieties'][ $key ] = $v;
} else {
$processed_params[ $k ] = $v;
}
}
}
return $processed_params;
}
/**
* Allow the user to choose whether to have a single or a double optin for the form being edited
* It will hold the latest selected value in a cookie so that the user is presented by default with the same option selected the next time he edits such a form
*
* @param array $params
*/
public function render_extra_editor_settings( $params = array() ) {
$processed_params = array();
$params['optin'] = empty( $params['optin'] ) ? ( isset( $_COOKIE['tve_api_drip_optin'] ) ? sanitize_text_field( $_COOKIE['tve_api_drip_optin'] ) : 'd' ) : $params['optin'];
setcookie( 'tve_api_drip_optin', $params['optin'], strtotime( '+6 months' ), '/' );
if ( ! empty( $params ) ) {
foreach ( $params as $k => $v ) {
if ( strpos( $k, 'field[' ) !== false ) {
$key = str_replace( 'field[', '', $k );
$processed_params['proprieties'][ $key ] = $v;
} else {
$processed_params[ $k ] = $v;
}
}
}
$this->output_controls_html( 'drip/optin-type', $processed_params );
$this->output_controls_html( 'drip/proprieties', $processed_params );
}
public function render_before_lists_settings( $params = array() ) {
$this->output_controls_html( 'drip/select-type', $params );
}
/**
* instantiate the API code required for this connection
*
* @return mixed
* @throws Exception
*/
protected function get_api_instance() {
return new Thrive_Dash_Api_Drip( $this->param( 'token' ) );
}
/**
* get all Subscriber Lists from this API service
*
* @return array|bool for error
*/
protected function _get_lists() {
try {
/** @var Thrive_Dash_Api_Drip $api */
$api = $this->get_api();
$campaigns = $api->get_campaigns(
array(
'account_id' => $this->param( 'client_id' ),
'status' => 'all',
)
);
if ( empty( $campaigns ) || ! is_array( $campaigns ) ) {
$this->_error = __( 'There is not Campaign in your Drip account to be fetched !', 'thrive-dash' );
return false;
}
$lists = array();
foreach ( $campaigns['campaigns'] as $campaign ) {
$lists[] = array(
'id' => $campaign['id'],
'name' => $campaign['name'],
);
}
return $lists;
} catch ( Exception $e ) {
$this->_error = $e->getMessage();
return false;
}
}
/**
* Append custom fields to defaults
*
* @param array $params
*
* @return array
*/
public function get_custom_fields( $params = array() ) {
return array_merge( parent::get_custom_fields(), $this->_mapped_custom_fields );
}
/**
* @param $params
* @param bool $force
* @param bool $get_all
*
* @return array|mixed
* @throws Exception
*/
public function get_api_custom_fields( $params, $force = false, $get_all = false ) {
return $this->get_all_custom_fields( $force );
}
/**
* Gets a list of fields from API or from cache
*
* @param (bool) $force true for fresh data or false from cache
*
* @return array|mixed
* @throws Exception
*/
public function get_all_custom_fields( $force ) {
$custom_data = array();
// Serves from cache if exists and requested
$cached_data = $this->get_cached_custom_fields();
if ( false === $force && ! empty( $cached_data ) ) {
return $cached_data;
}
/** @var Thrive_Dash_Api_Drip $api */
$api = $this->get_api();
// Build custom fields for every list
$custom_fields = $api->get_custom_fields(
array(
'account_id' => $this->param( 'client_id' ),
)
);
if ( is_array( $custom_fields ) ) {
foreach ( $custom_fields as $field ) {
$custom_data[] = $this->normalize_custom_field( $field );
}
}
$this->_save_custom_fields( $custom_data );
return $custom_data;
}
/**
* Brings an API field under a known form that TAr can understand
*
* @param string $field
*
* @return array
*/
protected function normalize_custom_field( $field ) {
return array(
'id' => $field,
'name' => $field,
'type' => $field,
'label' => $field,
);
}
/**
* Based on custom inputs set in form and their mapping
* - prepares a custom fields for Drip
*
* @param array $arguments POST sent by optin form
*
* @return array with drip custom field name as key and the value of inputs filled by the visitor
*/
public function prepare_api_custom_fields( $arguments ) {
$fields = array();
if ( empty( $arguments['tve_mapping'] ) ) {
return $fields;
}
$serialized = base64_decode( $arguments['tve_mapping'] );
$mapping = array();
if ( $serialized ) {
$mapping = thrive_safe_unserialize( $serialized );
}
if ( empty( $mapping ) ) {
return $fields;
}
foreach ( $mapping as $name => $field ) {
$name = str_replace( '[]', '', $name );
if ( ! empty( $field[ $this->_key ] ) && ! empty( $arguments[ $name ] ) ) {
$custom_field_name = $field[ $this->_key ];
$custom_field_value = $arguments[ $name ];
$fields[ $custom_field_name ] = is_array( $custom_field_value ) ? implode( ', ', $custom_field_value ) : $custom_field_value;
}
}
return $fields;
}
/**
* Build custom fields mapping for automations
*
* @param $automation_data
*
* @return array
*/
public function build_automation_custom_fields( $automation_data ) {
$mapped_data = array();
foreach ( $automation_data['api_fields'] as $pair ) {
$value = sanitize_text_field( $pair['value'] );
if ( $value ) {
$mapped_data[ $pair['key'] ] = $value;
}
}
return $mapped_data;
}
/**
* @param $email
* @param array $custom_fields
* @param array $extra
*
* @return false|int|mixed
*/
public function add_custom_fields( $email, $custom_fields = array(), $extra = array() ) {
try {
/** @var Thrive_Dash_Api_Drip $api */
$api = $this->get_api();
$list_id = ! empty( $extra['list_identifier'] ) ? $extra['list_identifier'] : null;
$args = array(
'email' => $email,
);
if ( ! empty( $extra['name'] ) ) {
$args['name'] = $extra['name'];
}
$this->add_subscriber( $list_id, $args );
$user = array(
'account_id' => $this->param( 'client_id' ),
'campaign_id' => $list_id,
'email' => $email,
'ip_address' => sanitize_text_field( $_SERVER['REMOTE_ADDR'] ), // phpcs:ignore
'custom_fields' => (object) $this->prepare_custom_fields_for_api( $custom_fields ),
);
$lead = $api->create_or_update_subscriber( $user );
return $lead['subscribers'][0]['id'];
} catch ( Exception $e ) {
return false;
}
}
/**
* get relevant data from webhook trigger
*
* @param $request WP_REST_Request
*
* @return array
*/
public function get_webhook_data( $request ) {
$contact = $request->get_param( 'subscriber' );
return array( 'email' => empty( $contact['email'] ) ? '' : $contact['email'] );
}
/**
* Prepare custom fields for api call
*
* @param array $custom_fields
* @param null $list_identifier
*
* @return array
*/
public function prepare_custom_fields_for_api( $custom_fields = array(), $list_identifier = null ) {
$prepared_fields = array();
$api_fields = $this->get_api_custom_fields( null, true );
foreach ( $api_fields as $field ) {
foreach ( $custom_fields as $key => $custom_field ) {
if ( $field['id'] === $key && $custom_field ) {
$prepared_fields[ $key ] = $custom_field;
unset( $custom_fields[ $key ] ); // avoid unnecessary loops
}
}
if ( empty( $custom_fields ) ) {
break;
}
}
return $prepared_fields;
}
public function get_automator_add_autoresponder_mapping_fields() {
return array( 'autoresponder' => array( 'mailing_list', 'optin', 'api_fields', 'tag_input' ) );
}
}

View File

@@ -0,0 +1,503 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Thrive Themes - https://thrivethemes.com
*/
/**
* Handle Email connection for Lead Generation.
* This connection will always be available but won't be displayed in TD, because no action is needed for it
*
* Class Thrive_Dash_List_Connection_Email
*/
class Thrive_Dash_List_Connection_Email extends Thrive_Dash_List_Connection_Abstract {
/**
* @return string the API connection title
*/
public function get_title() {
return 'Email';
}
/**
* Remove the api from dashboard
*
* @return bool
*/
public function is_related() {
return true;
}
/**
* Email connection will always be available
*
* @return bool
*/
public function is_connected() {
return true;
}
/**
* Noting to do here
*/
public function output_setup_form() {
}
/**
* @return true
*/
public function read_credentials() {
$this->set_credentials( array( 'connected' => true ) );
$this->save();
return true;
}
/**
* @return bool
*/
public function test_connection() {
return true;
}
/**
* Send the emails on lg submit, the name may be a bit inappropriate, but we have to stay with the general implementation
*
* @param array $list_identifier
* @param array $arguments
*
* @return array|string
*/
public function add_subscriber( $list_identifier, $arguments ) {
if ( ! is_array( $list_identifier ) ) {
return __( 'Failed to send email', 'thrive-dash' );
}
$response = array();
foreach ( $list_identifier as $connection ) {
$_list = $connection['list'];
if ( 'own_site' === $_list ) {
$_list = 'email';
}
$_instance = Thrive_Dash_List_Manager::connection_instance( $_list );
if ( ! method_exists( $_instance, 'sendMultipleEmails' ) ) {
continue;
}
$connection = array_merge( $connection, $arguments );
$response[ $_instance->get_key() ] = $_instance->sendMultipleEmails( $this->prepare_data_for_email_service( $connection ) );
}
return $response;
}
protected function get_api_instance() {
}
protected function _get_lists() {
return $this->get_connected_email_providers();
}
/**
* Get connected email providers
*
* @return array
*/
public function get_connected_email_providers() {
if ( function_exists( 'wp_mail_smtp' ) ) {
$own_site_name = 'WP Mail SMTP';
} else {
$own_site_name = 'Send emails from this site';
}
$providers = array(
array(
'id' => 'own_site',
'name' => $own_site_name,
),
);
foreach ( Thrive_Dash_List_Manager::get_available_apis( true, [ 'include_types' => [ 'email' ] ] ) as $email_provider ) {
/**
* @var Thrive_Dash_List_Connection_Abstract $email_provider
*/
$providers[] = array(
'id' => $email_provider->get_key(),
'name' => $email_provider->get_title(),
);
}
return $providers;
}
/**
* @param array $arguments
*
* @return bool
*/
public function sendMultipleEmails( $arguments ) {
$headers = 'Content-Type: text/html; charset=UTF-8 ' . "\r\n"
. 'From: ' . $arguments['from_name'] . ' <' . $arguments['from_email'] . ' > ' . "\r\n"
. 'Reply-To: ' . $arguments['reply_to'] . "\r\n"
. 'CC: ' . implode( ', ', $arguments['cc'] ) . "\r\n"
. 'BCC: ' . implode( ', ', $arguments['bcc'] ) . "\r\n";
$email_sent = wp_mail(
$arguments['emails'],
$arguments['subject'],
$arguments['html_content'],
$headers
);
/* Send confirmation email */
if ( $email_sent && $arguments['send_confirmation'] ) {
$arguments['reply_to'] = $arguments['from_email'];
$headers = 'Content-Type: text/html; charset=UTF-8 ' . "\r\n"
. 'From: ' . $arguments['from_name'] . ' <' . $arguments['from_email'] . ' > ' . "\r\n"
. 'Reply-To: ' . $arguments['reply_to'] . "\r\n";
$email_sent = wp_mail(
$arguments['sender_email'],
$arguments['confirmation_subject'],
$arguments['confirmation_html'],
$headers
);
}
return $email_sent;
}
/**
* Get any extra settings needed by the api
*
* @param array $arguments
*
* @return array
*/
public function get_extra_settings( $arguments = array() ) {
$response = array();
foreach ( Thrive_Dash_List_Manager::get_available_apis( true, [ 'include_types' => [ 'email' ] ] ) as $email_provider ) {
/**
* @var Thrive_Dash_List_Connection_Abstract $email_provider
*/
$response[ $email_provider->get_key() ] = array(
'from_email' => $email_provider->get_email_param(),
);
}
return $response;
}
/**
* Prepare data for email service
*
* @param array $arguments
*
* @return array
*/
public function prepare_data_for_email_service( $arguments ) {
$emails = array_map(
function ( $item ) {
return sanitize_email( trim( $item ) );
},
explode( ',', $arguments['to'] )
);
$cc = array();
$bcc = array();
if ( ! empty( $arguments['cc'] ) ) {
$cc = array_map(
function ( $item ) {
return sanitize_email( trim( $item ) );
},
explode( ',', $arguments['cc'] )
);
}
if ( ! empty( $arguments['bcc'] ) ) {
$bcc = array_map(
function ( $item ) {
return sanitize_email( trim( $item ) );
},
explode( ',', $arguments['bcc'] )
);
}
$confirmation_html = '';
$send_confirmation = false;
if ( ! empty( $arguments['send_confirmation_email'] ) && $arguments['send_confirmation_email'] ) {
$confirmation_html = $this->replace_shortcodes( $arguments['email_confirmation_message'], $arguments );
$send_confirmation = true;
}
$data = array(
'emails' => $emails,
'subject' => html_entity_decode( sanitize_text_field( $this->replace_shortcodes( $arguments['email_subject'], $arguments, true ) ) ),
'from_name' => sanitize_text_field( $arguments['from_name'] ),
'from_email' => sanitize_email( $arguments['from_email'] ),
'html_content' => $this->replace_shortcodes( $arguments['email_message'], $arguments ),
'reply_to' => sanitize_email( $arguments['email'] ),
'bcc' => $bcc,
'cc' => $cc,
'send_confirmation' => $send_confirmation,
'confirmation_html' => $confirmation_html,
'confirmation_subject' => html_entity_decode( sanitize_text_field( $this->replace_shortcodes( $arguments['email_confirmation_subject'], $arguments, true ) ) ),
'sender_email' => sanitize_email( trim( $arguments['email'] ) ),
);
/**
* Allow filter email output
*
* @param array $data
* @param array $arguments
*/
return apply_filters( 'tve_dash_email_data', $data, $arguments );
}
/**
* Get form fields of the form
*
* @param $message
* @param $args
* @param $time
*
* @return string
*/
public function get_email_fields( $message, $args, $time ) {
$has_shortcode = strpos( $args['email_message'], '[ form_fields ]' );
$labels = ! empty( $args['tve_labels'] ) ? thrive_safe_unserialize( base64_decode( $args['tve_labels'] ) ) : array();
if ( strpos( $message, '[all_form_fields]' ) !== false ) {
$has_shortcode = true;
}
ob_start();
include dirname( dirname( dirname( __FILE__ ) ) ) . '/views/includes/email.php';
$html = ob_get_clean();
$html .= $this->generate_custom_fields_html( $args, $labels );
return preg_replace( "/[\r\n]+/", "", $html );
}
/**
* Get all custom fields from request args
*
* @param array $args
*
* @return array
*/
private function _get_custom_fields( $args ) {
if ( empty( $args['tve_mapping'] ) ) {
$mapping = array();
} else {
$mapping = thrive_safe_unserialize( base64_decode( $args['tve_mapping'] ) );
}
$apis = Thrive_Dash_List_Manager::get_available_apis( true, [ 'include_types' => [ 'email', 'other' ] ] );
$custom_fields = array();
$excluded_fields = array( 'name', 'email', 'phone' );
foreach ( $apis as $api ) {
/** @var Thrive_Dash_List_Connection_Abstract $api */
$cf = $api->get_custom_fields();
$cf = wp_list_pluck( $cf, 'id' );
$custom_fields = array_merge( $custom_fields, $cf );
}
$custom_fields = array_unique( $custom_fields );
$custom_fields = array_filter(
$custom_fields,
function ( $field ) use ( $excluded_fields, $args ) {
if ( ! in_array( $field, $excluded_fields ) && array_key_exists( $field, $args ) ) {
return $field;
}
}
);
return array_merge( $custom_fields, array_keys( $mapping ) );
}
/**
* Generate the html for custom fields added in lg
*
* @param array $args
* @param array $labels
*
* @return string
*/
public function generate_custom_fields_html( $args, $labels ) {
$html = '';
foreach ( $this->_get_custom_fields( $args ) as $field ) {
$label = ! empty( $labels[ $field ] ) ? sanitize_text_field( $labels[ $field ] ) : __( 'Extra Data', 'thrive-dash' );
$is_extra_data = ! empty( $labels[ $field ] ) ? false : true;
if ( strpos( $field, 'textarea' ) !== false ) { /* preserve textarea formatting */
$value = ! empty( $args[ $field ] ) ? sanitize_textarea_field( $args[ $field ] ) : '';
} else {
$field = str_replace( '[]', '', $field );
if ( ! empty( $args[ $field ] ) ) {
$args[ $field ] = $this->process_field( $args[ $field ] );
}
$value = ! empty( $args[ $field ] ) ? sanitize_text_field( $args[ $field ] ) : '';
}
$value = stripslashes( nl2br( $value ) );
/**
* Filters a field value sent in the email message.
*
* @param string $value value to be sent in the email message
* @param string $field Field name that's being processed
* @param array $args form submission data
*
* @return string
*/
$value = apply_filters( 'thrive_email_message_field', $value, $field, $args );
if ( 'password' === $field || 'confirm_password' === $field ) {
$value = '******';
}
$_html = $is_extra_data && empty( $value ) ? '' : '<b>' . $label . ':</b> <span>' . $value . '</span><br>';
$html .= $_html;
}
return $html;
}
public function replace_shortcodes( $message, $args, $is_inline_field = false ) {
$timezone = get_option( 'gmt_offset' );
$time = date( 'H:i', time() + 3600 * ( $timezone + date( 'I' ) ) );
$first_name = empty( $args['name'] ) ? '' : $this->get_name_parts( $args['name'] )[0];
$fields_html = $this->get_email_fields( $message, $args, $time );
$to_replace = array(
'[wp_site_title]',
'[form_url_slug]',
'[first_name]',
'[user_email]',
'[phone]',
'[date]',
'[time]',
'[page_url]',
'[ip_address]',
'[device_settings]',
);
$values = array(
wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ),
trim( parse_url( $args['url'], PHP_URL_PATH ), '/' ),
$first_name,
$args['email'],
$args['phone'],
date_i18n( 'jS F, Y' ),
$time,
$args['url'],
tve_dash_get_ip(),
htmlspecialchars( isset( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_text_field( $_SERVER['HTTP_USER_AGENT'] ) : '' ),
);
if ( ! $is_inline_field ) {
$to_replace[] = '[all_form_fields]';
$to_replace[] = '[ form_fields ]';
$values[] = $fields_html;
$values[] = $fields_html;
}
/**
* Add custom fields to the shortcodes to be replaced in messages
*/
foreach ( $this->_get_custom_fields( $args ) as $field ) {
$to_replace[] = '[' . $field . ']';
$field = str_replace( '[]', '', $field );
if ( ! empty( $args[ $field ] ) ) {
$args[ $field ] = $this->process_field( $args[ $field ] );
}
$value = ! empty( $args[ $field ] ) ? sanitize_textarea_field( $args[ $field ] ) : '';
$value = stripslashes( nl2br( str_replace( ' ', '&nbsp;', $value ) ) );
$values[] = $value;
}
$message = str_replace( $to_replace, $values, $message );
/**
* Filter the email message being sent.
*
* @param string $message
* @param array $args submitted post data
*
* @return string
*/
$message = apply_filters( 'thrive_api_email_message', $message, $args );
return nl2br( $message );
}
/**
* Return the connection email merge tag
*
* @return String
*/
public static function get_email_merge_tag() {
return '[user_email]';
}
protected function set_custom_default_fields_mapping() {
$this->_default_form_fields = apply_filters(
'tve_dash_mapped_default_fields',
array(
array(
'id' => 'email',
'placeholder' => __( 'Email', 'thrive-dash' ),
'unique' => true,
'mandatory' => false,
),
array(
'id' => 'name',
'placeholder' => __( 'Name', 'thrive-dash' ),
'unique' => true,
'mandatory' => false,
),
array(
'id' => 'phone',
'placeholder' => __( 'Phone', 'thrive-dash' ),
'unique' => true,
'mandatory' => false,
),
) );
}
}

View File

@@ -0,0 +1,212 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_EverWebinar extends Thrive_Dash_List_Connection_Abstract {
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'webinar';
}
/**
* @return string
*/
public function get_title() {
return 'EverWebinar';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'everwebinar' );
}
/**
* @return mixed|Thrive_Dash_List_Connection_Abstract
*
*/
public function read_credentials() {
$key = ! empty( $_POST['connection']['key'] ) ? sanitize_text_field( $_POST['connection']['key'] ) : '';
if ( empty( $key ) ) {
return $this->error( __( 'You must provide a valid EverWebinar key', 'thrive-dash' ) );
}
$this->set_credentials( array( 'key' => $key ) );
$result = $this->test_connection();
if ( $result !== true ) {
return $this->error( sprintf( __( 'Could not connect to EverWebinar using the provided key (<strong>%s</strong>)', 'thrive-dash' ), $result ) );
}
/**
* finally, save the connection details
*/
$this->save();
return $this->success( __( 'EverWebinar connected successfully', 'thrive-dash' ) );
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string
*/
public function test_connection() {
try {
$webinars = $this->get_api()->get_webinars();
if ( ! $webinars ) {
return false;
}
return true;
} catch ( Thrive_Dash_Api_EverWebinar_Exception $e ) {
return $e->getMessage();
}
}
/**
* Compose name from email address
*
* @param $email_address
* @param string $split
*
* @return string
*/
public function nameFromEmail( $email_address, $split = '@' ) {
return ucwords( str_replace( array(
'_',
'.',
'-',
'+',
',',
':',
), ' ', strtolower( substr( $email_address, 0, strripos( $email_address, $split ) ) ) ) );
}
/**
* add contact to list
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return bool|mixed|Thrive_Dash_List_Connection_Abstract
*/
public function add_subscriber( $list_identifier, $arguments ) {
$args = array( 'schedule' => 0 );
if ( is_array( $arguments ) ) {
if ( isset( $arguments['everwebinar_schedule'] ) ) {
$args['schedule'] = $arguments['everwebinar_schedule'];
}
if ( isset( $arguments['email'] ) && ! empty( $arguments['email'] ) ) {
$args['email'] = $arguments['email'];
}
if ( isset( $arguments['name'] ) && ! empty( $arguments['name'] ) ) {
list( $first_name, $last_name ) = $this->get_name_parts( $arguments['name'] );
$args['first_name'] = $first_name;
$args['last_name'] = $last_name;
}
if ( ! empty( $args['email'] ) && empty( $arguments['name'] ) ) {
// First name is a required param, so we are building it for register forms with only email input
$args['first_name'] = $this->nameFromEmail( $args['email'] );
}
if ( isset( $arguments['phone'] ) && ! empty( $arguments['phone'] ) ) {
$args['phone'] = $arguments['phone'];
}
}
try {
$api = $this->get_api();
$webnar = $api->get_webinar_schedules( array( 'webinar_id' => $list_identifier ) );
if ( isset( $webnar['schedules'] ) ) {
$schedules = array_values( $webnar['schedules'] );
$args['schedule'] = $schedules[0]['schedule_id'];
}
$api->register_to_webinar( $list_identifier, $args );
} catch ( Exception $e ) {
return $this->error( $e->getMessage() );
}
return true;
}
/**
* @param array $params
*
* @return array
*/
public function get_extra_settings( $params = array() ) {
$webinar_id = '';
try {
// Used on webinar select/change ajax [in admin Lead generation]
if ( isset( $params['webinar_id'] ) ) {
$webinar_id = $params['webinar_id'];
} else {
$webinars = $this->get_api()->get_webinars();
if ( is_array( $webinars ) && isset( $webinars[0]['id'] ) ) {
$webinar_id = $webinars[0]['id'];
}
}
$params = $this->get_api()->get_webinar_schedules( array( 'webinar_id' => $webinar_id ) );
} catch ( Thrive_Dash_Api_EverWebinar_Exception $e ) {
}
return $params;
}
/**
* @return mixed|Thrive_Dash_Api_EverWebinar
* @throws Thrive_Dash_Api_EverWebinar_Exception
*/
protected function get_api_instance() {
return new Thrive_Dash_Api_EverWebinar( array(
'apiKey' => $this->param( 'key' ),
)
);
}
/**
* get all Subscriber Lists from this API service
*
* @return array|bool
*/
protected function _get_lists() {
/** @var Thrive_Dash_Api_EverWebinar $ever_webinar */
$ever_webinar = $this->get_api();
try {
return $ever_webinar->get_webinars();
} catch ( Exception $e ) {
$this->_error = $e->getMessage();
return false;
}
}
}

View File

@@ -0,0 +1,216 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class Thrive_Dash_List_Connection_Facebook extends Thrive_Dash_List_Connection_Abstract {
private static $scopes = 'email,public_profile';
protected $_key = 'facebook';
public $success_message = 'You are cool!';
/**
* Thrive_Dash_List_Connection_Facebook constructor.
*/
public function __construct() {
$this->set_credentials( Thrive_Dash_List_Manager::credentials( $this->_key ) );
}
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'social';
}
/**
* @return string the API connection title
*/
public function get_title() {
return 'Facebook';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'facebook' );
}
/**
* should handle: read data from post / get, test connection and save the details
*
* on error, it should register an error message (and redirect?)
*
* @return mixed
*/
public function read_credentials() {
$app_id = ! empty( $_REQUEST['app_id'] ) ? sanitize_text_field( $_REQUEST['app_id'] ) : '';
$app_secret = ! empty( $_REQUEST['app_secret'] ) ? sanitize_text_field( $_REQUEST['app_secret'] ) : '';
if ( empty( $app_id ) || empty( $app_secret ) ) {
return $this->error( __( 'Both Client ID and Client Secret fields are required', 'thrive-dash' ) );
}
$this->set_credentials( array(
'app_id' => $app_id,
'app_secret' => $app_secret,
) );
/* app has been authorized */
if ( isset( $_REQUEST['code'] ) ) {
$this->get_api()->getUser();
$this->save();
return true;
}
$result = $this->test_connection();
if ( $result !== true ) {
return $this->error( __( 'You must give access to Facebook <a target="_blank" href="' . $this->getAuthorizeUrl() . '">here</a>.', 'thrive-dash' ) );
}
/**
* finally, save the connection details
*/
$this->save();
return $this->success( __( 'Facebook connected successfully!', 'thrive-dash' ) );
}
/**
* test if the secret key is correct and it exists.
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
/** @var Thrive_Dash_Api_Facebook $api */
$api = $this->get_api();
$user = $api->getUser();
$ready = false;
if ( $user ) {
try {
$info = $api->api( '/me' );
if ( is_array( $info ) ) {
$ready = true;
}
} catch ( Tve_Facebook_Api_Exception $e ) {
$ready = array(
'success' => false,
'message' => __( 'You must give access to Facebook <a target="_blank" href="' . $this->getAuthorizeUrl() . '">here</a>.', 'thrive-dash' ),
);
}
} else {
$ready = array(
'success' => false,
'message' => __( 'You must give access to Facebook <a target="_blank" href="' . $this->getAuthorizeUrl() . '">here</a>.', 'thrive-dash' ),
);
}
return $ready;
}
/**
* @return string
*/
public function getAuthorizeUrl() {
/** @var Thrive_Dash_Api_Facebook $api */
$api = $this->get_api();
return $api->getLoginUrl( array(
'scope' => self::$scopes,
'redirect_uri' => add_query_arg( array(
'page' => 'tve_dash_api_connect',
'api' => 'facebook',
'app_id' => $this->param( 'app_id' ),
'app_secret' => $this->param( 'app_secret' ),
), admin_url( 'admin.php' ) ),
) );
}
/**
* Those functions do not apply
*
* @return Thrive_Dash_Api_Facebook
*/
protected function get_api_instance() {
$params = array(
'appId' => $this->param( 'app_id' ),
'secret' => $this->param( 'app_secret' ),
);
return new Thrive_Dash_Api_Facebook( $params );
}
/**
* @param $fbid
* @param $comment_id
*
* @return array|string|void
*/
public function get_comment( $fbid, $comment_id ) {
/** @var Thrive_Dash_Api_Facebook $api */
$api = $this->get_api();
$comment = array();
$user = $api->getUser();
if ( $user ) {
try {
$response = $api->api( '/' . $fbid . '_' . $comment_id );
if ( is_array( $response ) ) {
$comment = array(
'id' => $response['from']['id'],
'name' => $response['from']['name'],
'picture' => 'https://graph.facebook.com/' . $response['from']['id'] . '/picture?type=large',
'message' => $response['message'],
);
}
} catch ( Tve_Facebook_Api_Exception $e ) {
$comment = __( 'Error! The Facebook link provided is invalid', 'thrive-dash' );
}
} else {
$comment = __( 'Your Facebook connection expired. Go to API Connections to reactivate it!', 'thrive-dash' );
}
return $comment;
}
/**
* @return string
*/
public function custom_success_message() {
return ' ';
}
protected function _get_lists() {
}
public function add_subscriber( $list_identifier, $arguments ) {
}
}

View File

@@ -0,0 +1,89 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_FacebookPixel extends Thrive_Dash_List_Connection_Abstract {
public function get_title() {
return 'Facebook (Meta) Marketing API';
}
public static function get_type() {
return 'collaboration';
}
public function output_setup_form() {
$this->output_controls_html( 'facebookpixel' );
}
public function read_credentials() {
$access_token = ! empty( $_REQUEST['connection']['access_token'] ) ? sanitize_text_field( $_REQUEST['connection']['access_token'] ) : '';
$pixel_id = ! empty( $_REQUEST['connection']['pixel_id'] ) ? sanitize_text_field( $_REQUEST['connection']['pixel_id'] ) : '';
if ( empty( $access_token ) || empty( $pixel_id ) ) {
return $this->error( __( 'Both Pixel ID and Access token fields are required', 'thrive-dash' ) );
}
$this->set_credentials( array(
'pixel_id' => $pixel_id,
'access_token' => $access_token,
) );
$result = $this->test_connection();
if ( $result['success'] !== true ) {
return empty( $result['message'] ) ? $this->error( __( 'Incorrect Pixel ID or Access token, please try again.', 'thrive-dash' ) ) : $result['message'];
}
$this->save();
return $this->success( __( 'Facebook Pixel connected successfully', 'thrive-dash' ) );
}
public function test_connection() {
return $this->get_api()->send_test_event();
}
/**
* No need to implement this method
*
* @param $list_identifier
* @param $arguments
*
* @return mixed|void
*/
public function add_subscriber( $list_identifier, $arguments ) {
}
public function custom_success_message() {
return ' ';
}
/**
* Those functions do not apply
*
* @return Thrive_Dash_Api_FacebookPixel
*/
protected function get_api_instance() {
$params = array(
'pixel_id' => $this->param( 'pixel_id' ),
'access_token' => $this->param( 'access_token' ),
);
return new Thrive_Dash_Api_FacebookPixel( $params );
}
/**
* No need to implement this method
*/
protected function _get_lists() {
}
}

View File

@@ -0,0 +1,246 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_FileUpload_Dropbox
extends Thrive_Dash_List_Connection_Abstract
implements Thrive_Dash_List_Connection_FileUpload_Interface {
public static function get_type() {
return 'storage';
}
public function get_title() {
return 'Dropbox';
}
/**
* whether or not this list is connected to the service (has been authenticated)
*
* @return bool
*/
public function is_connected() {
return (bool) $this->param( 'access_token' );
}
public function output_setup_form() {
$this->output_controls_html( 'dropbox' );
}
/**
* Builds an authorization URI - the user will be redirected to that URI and asked to give app access
*
* @return string
*/
public function getAuthorizeUrl() {
$this->save(); // save the client_id and client_secret for later use
return $this->get_api()->get_authorize_url();
}
/**
* Called during the redirect from dropbox oauth flow
*
* _REQUEST contains a `code` parameter which needs to be sent back to g.api in exchange for an access token
*
* @return bool|mixed|string|Thrive_Dash_List_Connection_Abstract
*/
public function read_credentials() {
$code = empty( $_REQUEST['code'] ) ? '' : sanitize_text_field( $_REQUEST['code'] );
if ( empty( $code ) ) {
return $this->error( 'Missing `code` parameter' );
}
try {
/* get access token from dropbox */
$response = $this->get_api()->get_access_token( $code );
if ( empty( $response['access_token'] ) ) {
throw new Thrive_Dash_Api_Dropbox_Exception( 'Missing token from response data' );
}
$this->_credentials = array(
'client_id' => $this->param( 'client_id' ),
'client_secret' => $this->param( 'client_secret' ),
'access_token' => $response['access_token'],
'expires_at' => time() + $response['expires_in'],
'refresh_token' => $response['refresh_token'],
);
$this->save();
} catch ( Thrive_Dash_Api_Dropbox_Exception $e ) {
$this->_credentials = array();
$this->save();
$this->error( $e->getMessage() );
return false;
}
return true;
}
public function test_connection() {
$result = array(
'success' => true,
'message' => __( 'Connection works', 'thrive-dash' ),
);
try {
/**
* Just trigger a "check user" API call
* https://www.dropbox.com/developers/documentation/http/documentation#check-user
*/
$this->get_api()->check_user();
} catch ( Thrive_Dash_Api_Dropbox_Exception $e ) {
$result['success'] = false;
$result['message'] = $e->getMessage();
}
return $result;
}
/**
* Upload a file to the storage
*
* @param string $file_contents contents of the uploaded file
* @param string $folder_id folder identification
* @param array $metadata file metadata props, such as name
*
* @return string|WP_Error stored file id or WP_Error if any exceptions occured
*/
public function upload( $file_contents, $folder_id, $metadata ) {
$dropbox_request = array(
'path' => trim( $folder_id, '/' ) . '/' . $metadata['name'],
'autorename' => false,
);
try {
$file = $this->get_api()->upload( $file_contents, $dropbox_request );
} catch ( Thrive_Dash_Api_Dropbox_Exception $e ) {
if ( $folder_id && strpos( $e->getMessage(), 'path/no_write_permission' ) !== false ) {
/* try again, uploading to the root folder of the app */
return $this->upload( $file_contents, '', $metadata );
}
return new WP_Error( 'tcb_file_upload_error', $e->getMessage() );
}
return $file['id'];
}
/**
* Rename an uploaded file by applying a callback function on its name
* The callback function should return the new filename
*
* @param string $file_id file ID from dropbox
* @param callable $callback function to apply to get the new filename
*
* @return array information about the renamed file
*/
public function rename_file( $file_id, $callback ) {
$file = $this->get_file_data( $file_id );
if ( ! is_callable( $callback ) || empty( $file['path'] ) ) {
return $file;
}
try {
$new_name = $callback( $file['name'] );
$new_path = rtrim( dirname( $file['path'] ), '/' ) . '/' . $new_name;
if ( $new_name !== $file['name'] ) {
$this->get_api()->move_file( $file['path'], $new_path );
$file['url'] = dirname( $file['url'] ) . '/' . $callback( basename( $file['url'] ) );
$file['path'] = $new_path;
$file['name'] = $new_name;
}
} catch ( Thrive_Dash_Api_Dropbox_Exception $e ) {
}
return $file;
}
/**
* Deletes an uploaded file
*
* @param string $file_id
*
* @return true|WP_Error
*/
public function delete( $file_id ) {
try {
$this->get_api()->delete( $file_id );
$result = true;
} catch ( Thrive_Dash_Api_Dropbox_Exception $e ) {
$result = new WP_Error( 'tcb_file_upload_error', $e->getMessage() );
}
return $result;
}
/**
* Retrieve the full URL to a file stored on drive
*
* @param string $file_id
*
* @return array containing URL and original name
*/
public function get_file_data( $file_id ) {
// fallback to a default home url (??)
$data = array(
'url' => 'https://www.dropbox.com/home',
'name' => $file_id,
);
try {
$file = $this->get_api()->get_file( $file_id );
$data['url'] = $file['url'];
$data['name'] = $file['name'];
$data['path'] = $file['path_display'];
} catch ( Thrive_Dash_Api_Dropbox_Exception $e ) {
$data['error'] = $e->getMessage();
}
return $data;
}
public function add_subscriber( $list_identifier, $arguments ) {
}
/**
* Instantiate the service and set any available data
*
* @return Thrive_Dash_Api_Dropbox_Service
* @throws Thrive_Dash_Api_Dropbox_Exception
*/
protected function get_api_instance() {
$api = new Thrive_Dash_Api_Dropbox_Service(
$this->param( 'client_id' ),
$this->param( 'client_secret' ),
$this->param( 'access_token' )
);
/* check for expired token and renew it */
if ( $this->param( 'refresh_token' ) && $this->param( 'expires_at' ) && time() > (int) $this->param( 'expires_at' ) ) {
$data = $api->refresh_access_token( $this->param( 'refresh_token' ) );
$this->_credentials['access_token'] = $data['access_token'];
$this->_credentials['expires_at'] = time() + $data['expires_in'];
$this->save();
}
return $api;
}
protected function _get_lists() {
}
}

View File

@@ -0,0 +1,233 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_FileUpload_GoogleDrive
extends Thrive_Dash_List_Connection_Abstract
implements Thrive_Dash_List_Connection_FileUpload_Interface {
public static function get_type() {
return 'storage';
}
public function get_title() {
return 'Google Drive';
}
/**
* Builds an authorization URI - the user will be redirected to that URI and asked to give app access
*
* @return string
*/
public function getAuthorizeUrl() {
$this->save(); // save the client_id and client_secret for later use
return $this->get_api()->get_authorize_url();
}
/**
* whether or not this list is connected to the service (has been authenticated)
*
* @return bool
*/
public function is_connected() {
return $this->param( 'access_token' ) && $this->param( 'refresh_token' );
}
public function output_setup_form() {
$this->output_controls_html( 'google-drive' );
}
/**
* Called during the redirect from google oauth flow
*
* _REQUEST contains a `code` parameter which needs to be sent back to g.api in exchange for an access token
*
* @return bool|mixed|string|Thrive_Dash_List_Connection_Abstract
*/
public function read_credentials() {
$code = empty( $_REQUEST['code'] ) ? '' : $_REQUEST['code'];
if ( empty( $code ) ) {
return $this->error( 'Missing `code` parameter' );
}
try {
/* get access token from googleapis */
$response = $this->get_api()->get_access_token( $code );
if ( empty( $response['access_token'] ) ) {
throw new Thrive_Dash_Api_Google_Exception( 'Missing token from response data' );
}
$this->_credentials = array(
'client_id' => $this->param( 'client_id' ),
'client_secret' => $this->param( 'client_secret' ),
'access_token' => $response['access_token'],
'expires_at' => time() + $response['expires_in'],
'refresh_token' => $response['refresh_token'],
);
$this->save();
} catch ( Thrive_Dash_Api_Google_Exception $e ) {
echo 'caught ex: ' . esc_html( $e->getMessage() );
$this->_credentials = array();
$this->save();
$this->error( $e->getMessage() );
return false;
}
return true;
}
public function test_connection() {
$result = array(
'success' => true,
'message' => __( 'Connection works', 'thrive-dash' ),
);
try {
$this->get_api()->get_files();
} catch ( Thrive_Dash_Api_Google_Exception $e ) {
$result['success'] = false;
$result['message'] = $e->getMessage();
}
return $result;
}
/**
* Upload a file to the storage
*
* @param string $file_contents contents of the uploaded file
* @param string $folder_id folder identification
* @param array $metadata file metadata props, such as name
*
* @return string|WP_Error stored file id or WP_Error if any exceptions occured
*/
public function upload( $file_contents, $folder_id, $metadata ) {
$metadata['parents'] = array( $folder_id );
try {
$file = $this->get_api()->multipart_upload( $file_contents, $metadata );
} catch ( Thrive_Dash_Api_Google_Exception $e ) {
return new WP_Error( 'tcb_file_upload_error', $e->getMessage() );
}
return $file['id'];
}
/**
* Deletes an uploaded file
*
* @param string $file_id
*
* @return true|WP_Error
*/
public function delete( $file_id ) {
try {
$this->get_api()->delete( $file_id );
$result = true;
} catch ( Thrive_Dash_Api_Google_Exception $e ) {
$result = new WP_Error( 'tcb_file_upload_error', $e->getMessage() );
}
return $result;
}
/**
* Retrieve the full URL to a file stored on drive
*
* @param string $file_id
*
* @return array containing URL and original name
*/
public function get_file_data( $file_id ) {
// fallback to a default representation of a google file url
$data = array(
'url' => sprintf( 'https://drive.google.com/file/d/%s/view?usp=drivesdk', $file_id ),
'name' => $file_id,
);
try {
$file = $this->get_api()->get_file( $file_id, 'webViewLink,name' );
if ( ! empty( $file['webViewLink'] ) ) {
$data['url'] = $file['webViewLink'];
$data['name'] = $file['name'];
}
} catch ( Thrive_Dash_Api_Google_Exception $e ) {
}
return $data;
}
/**
* Rename an uploaded file by applying a callback function on its name
* The callback function should return the new filename
*
* @param string $file_id file ID from google
* @param callable $callback function to apply to get the new filename
*
* @return array information about the renamed file
*/
public function rename_file( $file_id, $callback ) {
// fallback to a default representation of a google file url
$file = $this->get_file_data( $file_id );
/* if file[name] is identical to file_id this means we could not retrieve actual filedata from the api */
if ( ! is_callable( $callback ) || $file['name'] === $file_id ) {
return $file;
}
try {
$new_name = $callback( $file['name'] );
if ( $new_name !== $file['name'] ) {
$this->get_api()->update_file_metadata( $file_id, array(
'name' => $new_name,
) );
$file['name'] = $new_name;
}
} catch ( Thrive_Dash_Api_Google_Exception $e ) {
}
return $file;
}
/**
* Instantiate the service and set any available data
*
* @return Thrive_Dash_Api_Google_Service
*/
protected function get_api_instance() {
$api = new Thrive_Dash_Api_Google_Service(
$this->param( 'client_id' ),
$this->param( 'client_secret' ),
$this->param( 'access_token' )
);
/* check for expired token and renew it */
if ( $this->param( 'refresh_token' ) && $this->param( 'expires_at' ) && time() > (int) $this->param( 'expires_at' ) ) {
$data = $api->refresh_access_token( $this->param( 'refresh_token' ) );
$this->_credentials['access_token'] = $data['access_token'];
$this->_credentials['expires_at'] = time() + $data['expires_in'];
$this->save();
}
return $api;
}
protected function _get_lists() {
}
public function add_subscriber( $list_identifier, $arguments ) {
}
}

View File

@@ -0,0 +1,57 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Interface Thrive_Dash_List_Connection_FileUpload_Interface
*
* Holds definitions for all the necessary functionality for connecting a file upload service with a Form element
*/
interface Thrive_Dash_List_Connection_FileUpload_Interface {
/**
* Upload a file to the storage
*
* @param string $file_contents contents of the uploaded file
* @param string $folder_id folder identification
* @param array $metadata file metadata props, such as name
*
* @return string|WP_Error stored file id or WP_Error if any exceptions occured
*/
public function upload( $file_contents, $folder_id, $metadata );
/**
* Retrieve data about a stored file
*
* @param string $file_id
*
* @return array containing URL and original name
*/
public function get_file_data( $file_id );
/**
* Deletes an uploaded file
*
* @param string $file_id
*
* @return true|WP_Error
*/
public function delete( $file_id );
/**
* Rename an uploaded file by applying a callback function on its name
* The callback function should return the new filename
*
* @param string $file_id file ID from google
* @param callable $callback function to apply to get the new filename
*
* @return array information about the renamed file
*/
public function rename_file( $file_id, $callback );
}

View File

@@ -0,0 +1,779 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
// FluentCRM CustomContactField class is loaded conditionally when needed.
class Thrive_Dash_List_Connection_FluentCRM extends Thrive_Dash_List_Connection_Abstract {
/**
* Key used for mapping custom fields
*
* @var string
*/
protected $_key = '_field';
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'autoresponder';
}
/**
* @return string
*/
public function get_title() {
return 'FluentCRM';
}
/**
* @return bool
*/
public function has_tags() {
return true;
}
/**
* @return bool
*/
public function has_optin() {
return true;
}
/**
* @return bool
*/
public function has_custom_fields() {
return true;
}
/**
* check whether or not the FluentCRM plugin is installed
*/
public function pluginInstalled() {
return function_exists( 'FluentCrmApi' );
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'fluentcrm' );
}
/**
* just save the key in the database
*
* @return mixed|void
*/
public function read_credentials() {
if ( ! $this->pluginInstalled() ) {
return $this->error( __( 'FluentCRM plugin must be installed and activated.', 'thrive-dash' ) );
}
$this->set_credentials( $this->post( 'connection', array() ) );
$result = $this->test_connection();
if ( $result !== true ) {
return $this->error( '<strong>' . $result . '</strong>)' );
}
/**
* finally, save the connection details
*/
$this->save();
return true;
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
if ( ! $this->pluginInstalled() ) {
return __( 'FluentCRM plugin must be installed and activated.', 'thrive-dash' );
}
return true;
}
/**
* add a contact to a list
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return mixed
*/
public function add_subscriber( $list_identifier, $arguments ) {
if ( ! $this->pluginInstalled() || ! function_exists( 'FluentCrmApi' ) ) {
return __( 'FluentCRM plugin is not installed / activated', 'thrive-dash' );
}
$name_array = array();
if ( ! empty( $arguments['name'] ) ) {
list( $first_name, $last_name ) = $this->get_name_parts( $arguments['name'] );
$name_array = array(
'first_name' => $first_name,
'last_name' => $last_name,
);
}
$prepared_args = array();
if ( ! empty( $arguments['phone'] ) ) {
$prepared_args['phone'] = sanitize_text_field( $arguments['phone'] );
}
// Handle default FluentCRM contact fields from direct arguments
$default_fields = array( 'city', 'state', 'country', 'address_line_1', 'postal_code', 'date_of_birth' );
foreach ( $default_fields as $field_name ) {
if ( ! empty( $arguments[ $field_name ] ) ) {
$prepared_args[ $field_name ] = sanitize_text_field( $arguments[ $field_name ] );
}
}
if ( ! empty( $arguments['tve_mapping'] ) ) {
// Use original automator logic when called from automator plugin
if ( $this->is_automator_context() ) {
// Original automator approach - simple and reliable
$prepared_args['custom_values'] = $this->buildMappedCustomFields( $arguments );
} else {
// Enhanced TAR approach with field separation
$mapped_fields = $this->buildMappedCustomFields( $arguments );
// Separate FluentCRM default contact fields from custom fields
$fluentcrm_default_fields = array( 'first_name', 'last_name', 'phone', 'country', 'state', 'city', 'address_line_1', 'address_line_2', 'postal_code', 'date_of_birth' );
$custom_values = array();
foreach ( $mapped_fields as $field_key => $field_value ) {
if ( in_array( $field_key, $fluentcrm_default_fields, true ) ) {
// Add to main contact data (these are FluentCRM's built-in contact fields)
$prepared_args[ $field_key ] = $field_value;
} else {
// Add to custom values (these are custom fields created in FluentCRM)
$custom_values[ $field_key ] = $field_value;
}
}
if ( ! empty( $custom_values ) ) {
$prepared_args['custom_values'] = $custom_values;
}
}
}
$prepared_args['tags'] = array();
$prepared_args['status'] = 'subscribed';
$tag_key = $this->get_tags_key();
if ( ! empty( $arguments[ $tag_key ] ) ) {
$prepared_args['tags'] = $this->importTags( $arguments[ $tag_key ] );
}
if ( isset( $arguments['fluentcrm_optin'] ) && 'd' === $arguments['fluentcrm_optin'] ) {
$prepared_args['status'] = 'pending';
}
$data = array(
'email' => $arguments['email'],
'lists' => array( $list_identifier ),
);
$data = array_merge( $data, $name_array, $prepared_args );
try {
$fluent = FluentCrmApi( 'contacts' );
$contact = $fluent->createOrUpdate( $data );
if ( $contact->status === 'pending' ) {
$contact->sendDoubleOptinEmail();
}
} catch ( Exception $exception ) {
return $exception->getMessage();
}
return true;
}
/**
* Import tags
*
* @return array true for success or error message for failure
*/
public function importTags( $tags ) {
$imported_tags = array();
$inserted_tags = array();
if ( ! empty( $tags ) ) {
$tags = explode( ',', trim( $tags, ' ,' ) );
foreach ( $tags as $tag ) {
$inserted_tags[] = array(
'title' => $tag,
);
}
$inserted_tags = FluentCrmApi( 'tags' )->importBulk( $inserted_tags );//[1,2,3]
foreach ( $inserted_tags as $new_tag ) {
$imported_tags[] = $new_tag->id;
}
}
return $imported_tags;
}
/**
* Build mapped custom fields array based on form params
*
* @param $args
*
* @return array
*/
public function buildMappedCustomFields( $args ) {
$mapped_data = array();
// Should be always base_64 encoded of a serialized array
if ( empty( $args['tve_mapping'] ) || ! tve_dash_is_bas64_encoded( $args['tve_mapping'] ) || ! is_serialized( base64_decode( $args['tve_mapping'] ) ) ) {
return $mapped_data;
}
$form_data = thrive_safe_unserialize( base64_decode( $args['tve_mapping'] ) );
if ( is_array( $form_data ) ) {
foreach ( $this->get_mapped_field_ids() as $mapped_field ) {
// Extract an array with all custom fields (siblings) names from form data
// {ex: [mapping_url_0, .. mapping_url_n] / [mapping_text_0, .. mapping_text_n]}
$custom_fields = preg_grep( "#^{$mapped_field}#i", array_keys( $form_data ) );
// Matched "form data" for current allowed name
if ( ! empty( $custom_fields ) && is_array( $custom_fields ) ) {
// Pull form allowed data, sanitize it and build the custom fields array
foreach ( $custom_fields as $cf_name ) {
if ( empty( $form_data[ $cf_name ][ $this->_key ] ) ) {
continue;
}
$field_id = $form_data[ $cf_name ][ $this->_key ];
// Check if this is a FluentCRM custom field (has fluentcrm key) or default field
$is_custom_field = ! empty( $form_data[ $cf_name ]['fluentcrm'] );
$actual_field_id = $is_custom_field ? $form_data[ $cf_name ]['fluentcrm'] : $field_id;
$clean_field_name = str_replace( '[]', '', $cf_name );
if ( ! empty( $args[ $clean_field_name ] ) ) {
$args[ $clean_field_name ] = $this->process_field( $args[ $clean_field_name ] );
// Get field type for proper sanitization from the original form_data key
$field_type = ! empty( $form_data[ $cf_name ]['_field'] ) ? $form_data[ $cf_name ]['_field'] : 'text';
// Convert mapping field types to FluentCRM field types
$fluentcrm_field_type = $this->convert_mapping_type_to_fluentcrm_type( $field_type );
// Use original cf_name for form_data lookup, but ensure we have a fallback
$field_config = isset( $form_data[ $cf_name ] ) ? $form_data[ $cf_name ] : array();
$field_config['type'] = $fluentcrm_field_type;
$sanitized_value = $this->sanitize_custom_field_value( $args[ $clean_field_name ], $field_config );
// Use the actual field ID (custom field slug or default field name)
$mapped_data[ $actual_field_id ] = $sanitized_value;
}
}
}
}
}
return $mapped_data;
}
/**
* Sanitize custom field value based on field type.
*
* @param mixed $value The field value to sanitize.
* @param array $field_config The field configuration.
*
* @return mixed Sanitized field value.
*/
protected function sanitize_custom_field_value( $value, $field_config = array() ) {
// Get field type from configuration if available
$field_type = ! empty( $field_config['type'] ) ? $field_config['type'] : 'text';
switch ( $field_type ) {
case 'checkbox':
// For checkbox fields, value should be an array or comma-separated string
if ( is_array( $value ) ) {
// Filter out empty values and sanitize
$sanitized_values = array_filter( array_map( 'sanitize_text_field', $value ) );
return array_values( $sanitized_values );
}
// If it's a string, split by comma and sanitize each part
if ( is_string( $value ) ) {
$values = explode( ',', $value );
$sanitized_values = array_filter( array_map( 'trim', array_map( 'sanitize_text_field', $values ) ) );
return array_values( $sanitized_values );
}
return array();
case 'select-one':
case 'radio':
// Single selection fields
return sanitize_text_field( $value );
case 'number':
return is_numeric( $value ) ? floatval( $value ) : 0;
case 'email':
return sanitize_email( $value );
case 'url':
return esc_url_raw( $value );
case 'date':
// Use robust timestamp approach for date conversion
return $this->convert_date_to_fluentcrm_format( $value );
case 'textarea':
return sanitize_textarea_field( $value );
case 'text':
default:
return sanitize_text_field( $value );
}
}
/**
* Convert date string to FluentCRM format using timestamp approach.
*
* @param string $date_string The date string to convert.
*
* @return string Formatted date string in Y-m-d format or empty string on failure.
*/
protected function convert_date_to_fluentcrm_format( $date_string ) {
if ( empty( $date_string ) || ! is_string( $date_string ) ) {
return '';
}
// Clean up the date string.
$date_string = trim( $date_string );
// Check if already in correct format and valid.
if ( preg_match( '/^\d{4}-\d{2}-\d{2}$/', $date_string ) ) {
$date_parts = explode( '-', $date_string );
if ( checkdate( (int) $date_parts[1], (int) $date_parts[2], (int) $date_parts[0] ) ) {
return $date_string;
}
}
// Try to convert to timestamp using various date formats.
$timestamp = $this->convert_date_to_timestamp( $date_string );
if ( false !== $timestamp ) {
// Convert timestamp to FluentCRM's expected Y-m-d format.
return gmdate( 'Y-m-d', $timestamp );
}
// Log the failure for debugging purposes.
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
error_log( sprintf( 'FluentCRM: Failed to convert date "%s" to valid format', $date_string ) );
}
return '';
}
/**
* Convert various date formats to Unix timestamp.
*
* @param string $date_string The date string to convert.
*
* @return int|false Unix timestamp or false on failure.
*/
protected function convert_date_to_timestamp( $date_string ) {
if ( empty( $date_string ) ) {
return false;
}
// Clean up the date string.
$date_string = trim( $date_string );
// List of possible date formats to try.
$formats = array(
'Y-m-d', // 2025-09-23 (ISO format)
'd/m/Y', // 23/09/2025 (European format)
'd/m/y', // 23/09/25
'm/d/Y', // 09/23/2025 (US format)
'm/d/y', // 09/23/25
'd-m-Y', // 23-09-2025
'm-d-Y', // 09-23-2025
'd.m.Y', // 23.09.2025 (German format)
'm.d.Y', // 09.23.2025
'Y/m/d', // 2025/09/23
'j/n/Y', // 23/9/2025 (no leading zeros)
'n/j/Y', // 9/23/2025 (no leading zeros)
'j-n-Y', // 23-9-2025 (no leading zeros)
'n-j-Y', // 9-23-2025 (no leading zeros)
);
// Try each format using DateTime::createFromFormat for precise parsing.
foreach ( $formats as $format ) {
try {
$date = DateTime::createFromFormat( $format, $date_string );
} catch ( Exception $e ) {
$date = false;
}
if ( false !== $date && $date->format( $format ) === $date_string ) {
// Validate the date is reasonable (not in the far future or past).
$timestamp = $date->getTimestamp();
$current_year = (int) gmdate( 'Y' );
$date_year = (int) $date->format( 'Y' );
// Allow dates from 1900 to 50 years in the future.
if ( $date_year >= 1900 && $date_year <= ( $current_year + 50 ) ) {
return $timestamp;
}
}
}
// Fallback to strtotime() for other formats, but with validation.
$timestamp = strtotime( $date_string );
if ( false !== $timestamp ) {
// Additional validation for strtotime results.
$date_year = (int) gmdate( 'Y', $timestamp );
$current_year = (int) gmdate( 'Y' );
// Ensure the year is reasonable.
if ( $date_year >= 1900 && $date_year <= ( $current_year + 50 ) ) {
return $timestamp;
}
}
return false;
}
/**
* Convert TAR mapping field types to FluentCRM field types.
*
* @param string $mapping_type The mapping field type from TAR.
*
* @return string The corresponding FluentCRM field type.
*/
protected function convert_mapping_type_to_fluentcrm_type( $mapping_type ) {
$type_mapping = array(
'mapping_text' => 'text',
'mapping_url' => 'url',
'mapping_phone' => 'text',
'mapping_hidden' => 'text',
'mapping_checkbox' => 'checkbox',
'mapping_select' => 'select-one',
'mapping_radio' => 'radio',
'mapping_textarea' => 'textarea',
'mapping_number' => 'number',
'mapping_email' => 'email',
'mapping_date' => 'date',
'date' => 'date', // Support for direct date field type
'number' => 'number', // Support for direct number field type
);
return isset( $type_mapping[ $mapping_type ] ) ? $type_mapping[ $mapping_type ] : 'text';
}
/**
* Detect if we're being called from the automator plugin.
*
* @return bool True if automator is calling, false otherwise.
*/
protected function is_automator_context() {
// Currently disabled - both TAR and automator use enhanced functionality
return false;
}
/**
* Get mapped field IDs for automator compatibility.
*
* @return array
*/
protected function get_mapped_field_ids() {
// For automator compatibility, use original field list
if ( $this->is_automator_context() ) {
return array( 'mapping_text', 'mapping_url', 'mapping_phone', 'mapping_hidden' );
}
// For TAR and enhanced functionality, use extended field list
return array(
'mapping_text', 'mapping_url', 'mapping_phone', 'mapping_hidden', 'mapping_checkbox', 'mapping_select', 'mapping_date', 'mapping_number',
'date', 'number', // Support for direct date and number fields (date_xxx, number_xxx)
'country', 'state', 'city', 'address_line_1', 'address_line_2', 'postal_code', 'date_of_birth'
);
}
/**
* instantiate the API code required for this connection
*
* @return mixed
*/
protected function get_api_instance() {
// no API instance needed here
return null;
}
/**
* get all Subscriber Lists from this API service
*
* @return array|bool
*/
protected function _get_lists() {
if ( ! $this->pluginInstalled() || ! function_exists( 'FluentCrmApi' ) ) {
$this->_error = __( 'FluentCRM plugin could not be found.', 'thrive-dash' );
return false;
}
$lists = array();
$list_api = FluentCrmApi( 'lists' );
// Get all the lists
$all_lists = $list_api->all();
foreach ( $all_lists as $list ) {
$lists[] = array(
'id' => $list->id,
'name' => $list->title,
);
}
return $lists;
}
public function get_tags() {
if ( ! $this->pluginInstalled() || ! function_exists( 'FluentCrmApi' ) ) {
$this->_error = __( 'FluentCRM plugin could not be found.', 'thrive-dash' );
return array();
}
$tags = array();
$tag_api = FluentCrmApi( 'tags' );
// Get all the tags
$all_tags = $tag_api->all();
foreach ( $all_tags as $tag ) {
$tags[] = array(
'id' => $tag->id,
'text' => $tag->title,
'selected' => false,
);
}
return $tags;
}
/**
* Get available custom fields for TAR (Thrive Architect).
* This method is used by TAR to retrieve custom fields for form mapping.
*
* @param null $list_id List ID (not used by FluentCRM).
*
* @return array
*/
public function get_available_custom_fields( $list_id = null ) {
// Force refresh to ensure we get the latest fields from FluentCRM
return $this->get_all_custom_fields( true );
}
/**
* Append custom fields to defaults
*
* @param array $params
*
* @return array
*/
public function get_custom_fields( $params = array() ) {
return array_merge( parent::get_custom_fields(), $this->_mapped_custom_fields );
}
/**
* @param $params
* @param bool $force
* @param bool $get_all
*
* @return array|mixed
*/
public function get_api_custom_fields( $params, $force = false, $get_all = false ) {
return $this->get_all_custom_fields( $force );
}
/**
* @param (bool) $force
*
* @return array|mixed
*/
public function get_all_custom_fields( $force ) {
$custom_data = array();
// Use original automator logic when called from automator
if ( $this->is_automator_context() ) {
// Original automator approach - only custom fields, text type only
if ( class_exists( 'FluentCrm\App\Models\CustomContactField' ) ) {
$cached_data = $this->get_cached_custom_fields();
if ( false === $force && ! empty( $cached_data ) ) {
return $cached_data;
}
try {
$global_fields_data = ( new \FluentCrm\App\Models\CustomContactField() )->getGlobalFields();
if ( isset( $global_fields_data['fields'] ) && is_array( $global_fields_data['fields'] ) ) {
$custom_fields = $global_fields_data['fields'];
if ( is_array( $custom_fields ) ) {
foreach ( $custom_fields as $field ) {
if ( ! empty( $field['type'] ) && $field['type'] === 'text' ) {
$custom_data[] = $this->normalize_custom_field( $field );
}
}
}
}
} catch ( Exception $e ) {
// Ignore errors
}
}
} else {
// Enhanced TAR approach - include default fields + all custom field types
$custom_data = array(
array( 'id' => 'first_name', 'name' => 'First Name', 'type' => 'text', 'label' => 'First Name' ),
array( 'id' => 'last_name', 'name' => 'Last Name', 'type' => 'text', 'label' => 'Last Name' ),
array( 'id' => 'phone', 'name' => 'Phone', 'type' => 'text', 'label' => 'Phone' ),
array( 'id' => 'city', 'name' => 'City', 'type' => 'text', 'label' => 'City' ),
array( 'id' => 'state', 'name' => 'State', 'type' => 'text', 'label' => 'State' ),
array( 'id' => 'country', 'name' => 'Country', 'type' => 'text', 'label' => 'Country' ),
array( 'id' => 'address_line_1', 'name' => 'Address Line 1', 'type' => 'text', 'label' => 'Address Line 1' ),
array( 'id' => 'address_line_2', 'name' => 'Address Line 2', 'type' => 'text', 'label' => 'Address Line 2' ),
array( 'id' => 'postal_code', 'name' => 'Postal Code', 'type' => 'text', 'label' => 'Postal Code' ),
array( 'id' => 'date_of_birth', 'name' => 'Date of Birth', 'type' => 'date', 'label' => 'Date of Birth' ),
);
if ( class_exists( 'FluentCrm\App\Models\CustomContactField' ) ) {
$cached_data = $this->get_cached_custom_fields();
if ( false === $force && ! empty( $cached_data ) ) {
return $cached_data;
}
try {
$global_fields_data = ( new \FluentCrm\App\Models\CustomContactField() )->getGlobalFields();
if ( is_array( $global_fields_data ) && isset( $global_fields_data['fields'] ) && is_array( $global_fields_data['fields'] ) ) {
$custom_fields = $global_fields_data['fields'];
if ( is_array( $custom_fields ) ) {
foreach ( $custom_fields as $field ) {
// Ensure we have the required field data
if ( ! empty( $field['slug'] ) && ! empty( $field['label'] ) &&
! empty( $field['type'] ) && $this->is_supported_field_type( $field['type'] ) ) {
$custom_data[] = $this->normalize_custom_field( $field );
}
}
}
}
} catch ( Exception $e ) {
// Ignore errors
}
}
}
$this->_save_custom_fields( $custom_data );
return $custom_data;
}
/**
* Check if field type is supported by FluentCRM integration.
*
* @param string $field_type The field type to check.
*
* @return bool True if supported, false otherwise.
*/
protected function is_supported_field_type( $field_type ) {
$supported_types = array(
'text',
'textarea',
'select-one',
'checkbox',
'radio',
'number',
'date',
'url',
'email',
);
return in_array( $field_type, $supported_types, true );
}
/**
* Normalize custom field data
*
* @param $field
*
* @return array
*/
protected function normalize_custom_field( $field ) {
$field = (array) $field;
$normalized = array(
'id' => ! empty( $field['slug'] ) ? sanitize_text_field( $field['slug'] ) : '',
'name' => ! empty( $field['label'] ) ? sanitize_text_field( $field['label'] ) : '',
'type' => ! empty( $field['type'] ) ? sanitize_text_field( $field['type'] ) : 'text',
'label' => ! empty( $field['label'] ) ? sanitize_text_field( $field['label'] ) : '',
);
// Add options for checkbox and select fields
if ( in_array( $field['type'], array( 'checkbox', 'select-one', 'radio' ), true ) && ! empty( $field['options'] ) ) {
if ( is_array( $field['options'] ) ) {
$normalized['options'] = array_map( 'sanitize_text_field', $field['options'] );
} elseif ( is_string( $field['options'] ) ) {
// Handle comma-separated options string
$options = explode( ',', $field['options'] );
$normalized['options'] = array_map( 'trim', array_map( 'sanitize_text_field', $options ) );
}
}
return $normalized;
}
/**
* Return the connection email merge tag
*
* @return String
*/
public static function get_email_merge_tag() {
return '{{contact.email}}';
}
public function get_automator_add_autoresponder_mapping_fields() {
return array( 'autoresponder' => array( 'mailing_list', 'api_fields', 'optin', 'tag_input' ) );
}
}

View File

@@ -0,0 +1,574 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_GetResponse extends Thrive_Dash_List_Connection_Abstract {
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'autoresponder';
}
/**
* @return string the API connection title
*/
public function get_title() {
return 'GetResponse';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'get-response' );
}
/**
* should handle: read data from post / get, test connection and save the details
*
* on error, it should register an error message (and redirect?)
*
* @return mixed
*/
public function read_credentials() {
$connection = $this->post( 'connection' );
$version = (string) ( isset( $connection['version'] ) ? $connection['version'] : '' );
if ( empty( $connection['key'] ) ) {
return $this->error( __( 'You must provide a valid GetResponse key', 'thrive-dash' ) );
}
if ( $version === '3' && empty( $connection['url'] ) ) {
return $this->error( __( 'You must provide a valid GetResponse V3 API URL', 'thrive-dash' ) );
}
$this->set_credentials( $connection );
$result = $this->test_connection();
if ( $result !== true ) {
return $this->error( sprintf( __( 'Could not connect to GetResponse using the provided key (<strong>%s</strong>)', 'thrive-dash' ), $result ) );
}
/**
* finally, save the connection details
*/
$this->save();
return $this->success( __( 'GetResponse connected successfully', 'thrive-dash' ) );
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
$gr = $this->get_api();
/**
* just try getting a list as a connection test
*/
$credentials = $this->get_credentials();
try {
if ( ! $credentials['version'] || $credentials['version'] == 2 ) {
/** @var Thrive_Dash_Api_GetResponse $gr */
$gr->getCampaigns();
} else {
/** @var Thrive_Dash_Api_GetResponseV3 $gr */
$gr->ping();
}
} catch ( Thrive_Dash_Api_GetResponse_Exception $e ) {
return $e->getMessage();
}
return true;
}
/**
* Instantiate the API code required for this connection
*
* @return Thrive_Dash_Api_GetResponse|Thrive_Dash_Api_GetResponseV3
*/
protected function get_api_instance() {
if ( ! $this->param( 'version' ) || $this->param( 'version' ) == 2 ) {
return new Thrive_Dash_Api_GetResponse( $this->param( 'key' ) );
}
$getresponse = new Thrive_Dash_Api_GetResponseV3( $this->param( 'key' ), $this->param( 'url' ) );
$enterprise_param = $this->param( 'enterprise' );
if ( ! empty( $enterprise_param ) ) {
$getresponse->enterprise_domain = $this->param( 'enterprise' );
}
return $getresponse;
}
/**
* get all Subscriber Lists from this API service
*
* @return array|false
*/
protected function _get_lists() {
/** @var Thrive_Dash_Api_GetResponse $gr */
$gr = $this->get_api();
try {
$lists = array();
$items = $gr->getCampaigns();
$credentials = $this->get_credentials();
if ( ! $credentials['version'] || $credentials['version'] == 2 ) {
foreach ( $items as $key => $item ) {
$lists [] = array(
'id' => $key,
'name' => $item->name,
);
}
} else {
foreach ( $items as $item ) {
$lists [] = array(
'id' => $item->campaignId,
'name' => $item->name,
);
}
}
return $lists;
} catch ( Exception $e ) {
$this->_error = $e->getMessage();
return false;
}
}
/**
* delete a contact from the list
*
* @param string $email
* @param array $arguments
*
* @return mixed
*/
public function delete_subscriber( $email, $arguments = array() ) {
$api = $this->get_api();
if ( ! empty( $email ) ) {
$contacts = $api->searchContacts(
array(
'query' => array(
'email' => $email,
),
)
);
if ( ! empty( $contacts ) ) {
foreach ( $contacts as $contact ) {
$api->deleteContact( $contact->contactId, array() );
}
}
return true;
}
return false;
}
/**
* add a contact to a list
*
* @param string $list_identifier
* @param array $arguments
*
* @return mixed
*/
public function add_subscriber( $list_identifier, $arguments ) {
/** @var Thrive_Dash_Api_GetResponseV3 $api */
$api = $this->get_api();
$credentials = $this->get_credentials();
$return = true;
$version = empty( $credentials['version'] ) ? 2 : (int) $credentials['version'];
try {
if ( 2 === $version ) {
if ( empty( $arguments['name'] ) ) {
$arguments['name'] = ' ';
}
/** @var Thrive_Dash_Api_GetResponse $api */
$api->addContact( $list_identifier, $arguments['name'], $arguments['email'], 'standard', (int) empty( $arguments['get-response_cycleday'] ) ? 0 : $arguments['get-response_cycleday'] );
} else {
$params = array(
'email' => $arguments['email'],
'dayOfCycle' => empty( $arguments['get-response_cycleday'] ) ? 0 : $arguments['get-response_cycleday'],
'campaign' => array(
'campaignId' => $list_identifier,
),
'ipAddress' => tve_dash_get_ip(),
);
if ( ! empty( $arguments['name'] ) ) {
$params['name'] = $arguments['name'];
}
// forward already inserted custom fields
if ( ! empty( $arguments['CustomFields'] ) ) {
$params['customFieldValues'] = $arguments['CustomFields'];
}
// Set / Create & set Phone as custom field
if ( ! empty( $arguments['phone'] ) ) {
$params = array_merge( $params, $this->setCustomPhone( $arguments, $params ) );
}
// Build custom fields data
$existing_custom_fields = ! empty( $params['customFieldValues'] ) ? $params['customFieldValues'] : array();
$mapped_custom_fields = $this->buildMappedCustomFields( $arguments, $existing_custom_fields );
if ( ! empty( $mapped_custom_fields ) ) {
$params = array_merge( $params, $mapped_custom_fields );
}
try {
/**
* this contact may be in other list but try to add it in the current on
*/
$api->addContact( $params );
return true;
} catch ( Exception $e ) {
}
/**
* we're talking about the same email but
* it is the same contact in multiple list
*/
$contacts = $api->searchContacts(
array(
'query' => array(
'email' => $params['email'],
),
)
);
if ( ! empty( $contacts ) ) {
foreach ( $contacts as $contact ) {
/**
* Update the subscriber only in current list
*/
if ( $contact->campaign->campaignId === $params['campaign']['campaignId'] ) {
$api->updateContact( $contact->contactId, $params );
}
}
}
}
} catch ( Exception $e ) {
$return = $e->getMessage();
}
return $return;
}
/**
* Build or add to existing custom fields array
*
* @param array $args
* @param array $mapped_data
*
* @return array
*/
public function buildMappedCustomFields( $args, $mapped_data = array() ) {
// Should be always base_64 encoded of a serialized array
if ( empty( $args['tve_mapping'] ) || ! tve_dash_is_bas64_encoded( $args['tve_mapping'] ) || ! is_serialized( base64_decode( $args['tve_mapping'] ) ) || ! is_array( $mapped_data ) ) {
return array();
}
$form_data = thrive_safe_unserialize( base64_decode( $args['tve_mapping'] ) );
if ( is_array( $form_data ) ) {
$mapped_fields = $this->get_mapped_field_ids();
foreach ( $mapped_fields as $mapped_field_name ) {
// Extract an array with all custom fields (siblings) names from form data
// {ex: [mapping_url_0, .. mapping_url_n] / [mapping_text_0, .. mapping_text_n]}
$cf_form_fields = preg_grep( "#^{$mapped_field_name}#i", array_keys( $form_data ) );
// Matched "form data" for current allowed name
if ( ! empty( $cf_form_fields ) && is_array( $cf_form_fields ) ) {
// Pull form allowed data, sanitize it and build the custom fields array
foreach ( $cf_form_fields as $cf_form_name ) {
if ( empty( $form_data[ $cf_form_name ][ $this->_key ] ) ) {
continue;
}
$mapped_api_id = $form_data[ $cf_form_name ][ $this->_key ];
$cf_form_name = str_replace( '[]', '', $cf_form_name );
if ( ! empty( $args[ $cf_form_name ] ) ) {
$args[ $cf_form_name ] = $this->process_field( $args[ $cf_form_name ] );
$mapped_data[] = array(
'customFieldId' => $mapped_api_id,
'value' => array( sanitize_text_field( $args[ $cf_form_name ] ) ),
);
}
}
}
}
}
return ! empty( $mapped_data ) ? array( 'customFieldValues' => $mapped_data ) : array();
}
/**
* Set / create&set a new phone custom field
*
* @param $arguments
* @param array $params
*
* @return array
*/
public function setCustomPhone( $arguments, $params = array() ) {
if ( empty( $arguments ) || ! is_array( $params ) ) {
return array();
}
$custom_fields = $this->get_api()->getCustomFields();
if ( is_array( $custom_fields ) ) {
$phone_field = array_values( wp_list_filter( $custom_fields, array( 'name' => 'thrvphone' ) ) );
/**
* We use a custom field to add phone filed for getResponse
* This because getResponse has a strict validation for built in phone number and very often added contacts
* with this custom field will fail
*/
if ( empty( $phone_field ) ) {
$field_args = array(
'name' => 'thrvphone',
'type' => 'number',
'hidden' => false,
'values' => array(),
);
$phone_field = $this->get_api()->setCustomField( $field_args );
}
if ( ! empty( $phone_field[0]->customFieldId ) ) {
$phone_value = str_replace( array( '-', '+', ' ' ), '', trim( $arguments['phone'] ) );
$params['customFieldValues'] = array(
array(
'customFieldId' => $phone_field[0]->customFieldId,
'value' => array( $phone_value ),
),
);
}
}
return $params;
}
/**
* Render extra html API setup form
*
* @param array $params
*
* @return array
*/
public function get_extra_settings( $params = array() ) {
return $params;
}
/**
* Render extra html API setup form
*
* @param array $params
*
* @see api-list.php
*
*/
public function render_extra_editor_settings( $params = array() ) {
$this->output_controls_html( 'getresponse/cycleday', $params );
}
/**
* Return the connection email merge tag
*
* @return String
*/
public static function get_email_merge_tag() {
return '[[email]]';
}
/**
* @param $params
* @param bool $force
* @param bool $get_all
*
* @return array|mixed
*/
public function get_api_custom_fields( $params, $force = false, $get_all = false ) {
// Serve from cache if exists and requested
$cached_data = $this->get_cached_custom_fields();
if ( false === $force && ! empty( $cached_data ) ) {
return $cached_data;
}
// Needed custom fields type [every API can have different naming type]
$allowed_types = array(
'text',
'url',
);
$custom_data = array();
try {
/** @var Thrive_Dash_Api_GetResponseV3 $api */
$custom_fields = $this->get_api()->getCustomFields();
if ( is_array( $custom_fields ) ) {
foreach ( $custom_fields as $field ) {
if ( ! empty( $field->type ) && in_array( $field->type, $allowed_types, true ) ) {
$custom_data[] = $this->normalize_custom_field( $field );
}
}
}
$this->_save_custom_fields( $custom_data );
} catch ( Thrive_Dash_Api_GetResponse_Exception $e ) {
}
return $custom_data;
}
/**
* @param array $field
*
* @return array
*/
protected function normalize_custom_field( $field ) {
$field = (object) $field;
return array(
'id' => ! empty( $field->customFieldId ) ? $field->customFieldId : '',
'name' => ! empty( $field->name ) ? $field->name : '',
'type' => ! empty( $field->type ) ? $field->type : '',
'label' => ! empty( $field->name ) ? $field->name : '',
);
}
/**
* Append custom fields to defaults
*
* @param array $params
*
* @return array
*/
public function get_custom_fields( $params = array() ) {
return array_merge( parent::get_custom_fields(), $this->_mapped_custom_fields );
}
/**
* Get available custom fields for this api connection
*
* @param null $list_id
*
* @return array
*/
public function get_available_custom_fields( $list_id = null ) {
return $this->get_api_custom_fields( null, true );
}
/**
* @param $email
* @param array $custom_fields
* @param array $extra
*
* @return int
*/
public function add_custom_fields( $email, $custom_fields = array(), $extra = array() ) {
try {
$api = $this->get_api();
$list_id = ! empty( $extra['list_identifier'] ) ? $extra['list_identifier'] : null;
$args = array(
'email' => $email,
);
if ( ! empty( $extra['name'] ) ) {
$args['name'] = $extra['name'];
}
$args['CustomFields'] = $this->prepare_custom_fields_for_api( $custom_fields, $list_id );
$this->add_subscriber( $list_id, $args );
} catch ( Exception $e ) {
return $e->getMessage();
}
}
/**
* Prepare custom fields for api call
*
* @param array $custom_fields
* @param null $list_identifier
*
* @return array
*/
public function prepare_custom_fields_for_api( $custom_fields = array(), $list_identifier = null ) {
$prepared_fields = array();
$api_fields = $this->get_api_custom_fields( null, true );
if ( empty( $custom_fields ) ) {
return $prepared_fields;
}
foreach ( $api_fields as $field ) {
foreach ( $custom_fields as $key => $custom_field ) {
if ( $field['id'] == $key ) {
$prepared_fields[] = array(
'customFieldId' => $field['id'],
'value' => array( $custom_field ),
);
}
}
}
return $prepared_fields;
}
}

View File

@@ -0,0 +1,436 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_GoToWebinar extends Thrive_Dash_List_Connection_Abstract {
/**
* Get GoToWebinar API keys from endpoint with transient caching
*
* @return array API keys or empty array on error
*/
private function get_gotowebinar_api_keys() {
// Check transient first
if ( false !== $keys = get_transient( 'thrive_gotowebinar_api_keys' ) ) {
return $keys;
}
$endpoint = 'https://thrivethemesapi.com/api/secrets/v1/api_key_gotowebinar';
$response = wp_remote_get( $endpoint, array(
'timeout' => 10,
'sslverify' => true
) );
if ( is_wp_error( $response ) ) {
$correlation_code = 'G2W-KEYS-NET-' . substr( wp_hash( uniqid( '', true ) ), 0, 8 );
$this->api_log_error( 'auth', array(
'endpoint' => $endpoint,
'correlation_code' => $correlation_code,
), sprintf( '%s. Please contact customer support at thrivethemes.com and mention code %s', $response->get_error_message(), $correlation_code ) );
return array();
}
$status_code = wp_remote_retrieve_response_code( $response );
if ( ! empty( $status_code ) && (int) $status_code !== 200 ) {
$correlation_code = 'G2W-KEYS-HTTP-' . substr( wp_hash( uniqid( '', true ) ), 0, 8 );
$error_message = sprintf( 'GoToWebinar API key fetch failed: HTTP %d. Please contact customer support at thrivethemes.com and mention code %s', (int) $status_code, $correlation_code );
$this->api_log_error( 'auth', array(
'endpoint' => $endpoint,
'status_code' => (int) $status_code,
'correlation_code' => $correlation_code,
), $error_message );
return array();
}
$body = wp_remote_retrieve_body( $response );
$data = json_decode( $body, true );
if ( ! is_array( $data ) ||
! isset( $data['success'] ) ||
! $data['success'] ||
! isset( $data['data']['value']['consumer_key'] ) ||
! isset( $data['data']['value']['consumer_secret'] ) ) {
$correlation_code = 'G2W-KEYS-PAY-' . substr( wp_hash( uniqid( '', true ) ), 0, 8 );
$this->api_log_error( 'auth', array(
'endpoint' => $endpoint,
'correlation_code' => $correlation_code,
), sprintf( 'GoToWebinar API key fetch returned unexpected payload. Please contact customer support at thrivethemes.com and mention code %s', $correlation_code ) );
return array();
}
$keys = array(
'consumer_key' => sanitize_text_field( $data['data']['value']['consumer_key'] ),
'consumer_secret' => sanitize_text_field( $data['data']['value']['consumer_secret'] )
);
// Cache for 24 hours
set_transient( 'thrive_gotowebinar_api_keys', $keys, 24 * HOUR_IN_SECONDS );
return $keys;
}
/**
* Get consumer key with fallback
*
* @return string
*/
private function get_consumer_key() {
$keys = $this->get_gotowebinar_api_keys();
return ! empty( $keys['consumer_key'] ) ? $keys['consumer_key'] : '';
}
/**
* Get consumer secret with fallback
*
* @return string
*/
private function get_consumer_secret() {
$keys = $this->get_gotowebinar_api_keys();
return ! empty( $keys['consumer_secret'] ) ? $keys['consumer_secret'] : '';
}
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'webinar';
}
/**
* check if the expires_at field is in the past
* GoToWebinar auth access tokens expire after about one year
*
* @return bool
*/
public function isExpired() {
if ( ! $this->is_connected() ) {
return false;
}
$expires_at = $this->param( 'expires_at' );
return time() > $expires_at;
}
/**
* get the expiry date and time user-friendly formatted
*/
public function getExpiryDate() {
return date( 'l, F j, Y H:i:s', $this->param( 'expires_at' ) );
}
/**
* @return string the API connection title
*/
public function get_title() {
return 'GoToWebinar';
}
/**
* these are called webinars, not lists
*
* @return string
*/
public function get_list_sub_title() {
return __( 'Choose from the following upcoming webinars', 'thrive-dash' );
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'gotowebinar' );
}
/**
* should handle: read data from post / get, test connection and save the details
*
* on error, it should register an error message (and redirect?)
*
* @return mixed
*/
public function read_credentials() {
if ( empty( $_POST['gtw_email'] ) || empty( $_POST['gtw_password'] ) ) {
return $this->error( __( 'Email and password are required', 'thrive-dash' ) );
}
$email = sanitize_text_field( $_POST['gtw_email'] );
$password = sanitize_text_field( $_POST['gtw_password'] );
$v = array(
'version' => ! empty( $_POST['connection']['version'] ) ? sanitize_text_field( $_POST['connection']['version'] ) : '',
'versioning' => ! empty( $_POST['connection']['versioning'] ) ? sanitize_text_field( $_POST['connection']['versioning'] ) : '',
);
/** @var Thrive_Dash_Api_GoToWebinar $api */
$api = $this->get_api();
try {
$api->directLogin( $email, $password, $v );
$credentials = $api->get_credentials();
// Add inbox notification for v2 connection
if ( TD_Inbox::instance()->api_is_connected( $this->get_key() ) && ! empty( $credentials['version'] ) && 2 === (int) $credentials['version'] && ! empty( $credentials['versioning'] ) ) {
$this->add_notification( 'added_v2' );
// Remove notification from api connection
TVE_Dash_InboxManager::instance()->remove_api_connection( $this->get_key() );
}
$this->set_credentials( $credentials );
/**
* finally, save the connection details
*/
$this->save();
return $this->success( 'GoToWebinar connected successfully' );
} catch ( Thrive_Dash_Api_GoToWebinar_Exception $e ) {
$correlation_code = 'G2W-AUTH-LOGIN-' . substr( wp_hash( uniqid( '', true ) ), 0, 8 );
$this->api_log_error( 'auth', array(
'step' => 'login',
'correlation_code' => $correlation_code,
), sprintf( '%s. Please contact customer support at thrivethemes.com and mention code %s', $e->getMessage(), $correlation_code ) );
return $this->error( sprintf( __( 'Could not connect to GoToWebinar using the provided data (%s)', 'thrive-dash' ), $e->getMessage() ) );
}
}
/**
* @param string $type
*
* @return bool
*/
public function add_notification( $type = '' ) {
if ( empty( $type ) ) {
return false;
}
$message = array();
$inbox_manager = TVE_Dash_InboxManager::instance();
switch ( $type ) {
case 'added_v2':
$message = array(
'title' => __( 'Your GoToWebinar Connection has been Updated!', 'thrive-dash' ),
'info' => 'Good job - you\'ve just upgraded your GoToWebinar connection to 2.0.<br /><br />
You don\'t need to make any changes to your existing forms - they will carry on working as before. <br /><br />
However, we highly recommend that you sign up through one of your webinar forms to make sure that everything is working as expected.<br /><br />
If you experience any issues, let our <a href="https://thrivethemes.com/forums/forum/general-discussion/" target="_blank">support team</a> know and we\'ll get to the bottom of this for you. <br /><br />
From your team at Thrive Themes ',
'type' => TD_Inbox_Message::TYPE_INBOX,
);
break;
}
if ( empty( $message ) ) {
return false;
}
try {
$message_obj = new TD_Inbox_Message( $message );
$inbox_manager->prepend( $message_obj );
$inbox_manager->push_notifications();
} catch ( Exception $e ) {
}
}
/**
* @return mixed|string
*/
public function getUsername() {
$credentials = (array) $this->get_credentials();
if ( ! empty( $credentials['username'] ) ) {
return $credentials['username'];
}
return '';
}
/**
* @return mixed|string
*/
public function getPassword() {
$credentials = (array) $this->get_credentials();
if ( ! empty( $credentials['password'] ) ) {
return $credentials['password'];
}
return '';
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
return true;
}
/**
* add a contact to a list
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return mixed
*/
public function add_subscriber( $list_identifier, $arguments ) {
/** @var Thrive_Dash_Api_GoToWebinar $api */
$api = $this->get_api();
$phone = isset( $arguments['phone'] ) ? $arguments['phone'] : null;
list( $first_name, $last_name ) = $this->get_name_parts( $arguments['name'] );
if ( empty( $last_name ) ) {
$last_name = $first_name;
}
if ( empty( $first_name ) && empty( $last_name ) ) {
list( $first_name, $last_name ) = $this->get_name_from_email( $arguments['email'] );
}
try {
$api->registerToWebinar( $list_identifier, $first_name, $last_name, $arguments['email'], $phone );
return true;
} catch ( Thrive_Dash_Api_GoToWebinar_Exception $e ) {
return $e->getMessage();
} catch ( Exception $e ) {
return $e->getMessage();
}
}
/**
*
* @return int the number of days in which this token will expire
*/
public function expiresIn() {
$expires_at = $this->param( 'expires_at' );
return (int) ( ( $expires_at - time() ) / ( 3600 * 24 ) );
}
/**
* check if the connection is about to expire in less than 30 days or it's already expired
*/
public function get_warnings() {
if ( ! $this->is_connected() ) {
return array();
}
$fix = '<a href="' . admin_url( 'admin.php?page=tve_dash_api_connect' ) . '#edit/' . $this->get_key() . '">' . __( 'Click here to renew the token', 'thrive-dash' ) . '</a>';
if ( $this->isExpired() ) {
return array(
sprintf( __( 'Thrive API Connections: The access token for %s has expired on %s.', 'thrive-dash' ), '<strong>' . $this->get_title() . '</strong>', '<strong>' .
$this->getExpiryDate() . '</strong>' ) . ' ' . $fix . '.',
);
}
$diff = $this->expiresIn();
if ( $diff > 30 ) {
return array();
}
$message = $diff == 0
?
__( 'Thrive API Connections: The access token for %s will expire today.', 'thrive-dash' )
:
( $diff == 1
?
__( 'Thrive API Connections: The access token for %s will expire tomorrow.', 'thrive-dash' )
:
__( 'Thrive API Connections: The access token for %s will expire in %s days.', 'thrive-dash' ) );
return array(
sprintf( $message, '<strong>' . $this->get_title() . '</strong>', '<strong>' . $diff . '</strong>' ) . ' ' . $fix . '.',
);
}
/**
* instantiate the API code required for this connection
*
* @return mixed|Thrive_Dash_Api_GoToWebinar
* @throws Thrive_Dash_Api_GoToWebinar_Exception
*/
protected function get_api_instance() {
$access_token = $organizer_key = null;
$settings = array();
if ( $this->is_connected() && ! $this->isExpired() ) {
$access_token = $this->param( 'access_token' );
$organizer_key = $this->param( 'organizer_key' );
$settings = array(
'version' => $this->param( 'version' ),
'versioning' => $this->param( 'versioning' ),
// used on class instances from [/v1/, /v2/ etc] namespace folder
'expires_in' => $this->param( 'expires_in' ),
'auth_type' => $this->param( 'auth_type' ),
'refresh_token' => $this->param( 'refresh_token' ),
'username' => $this->param( 'username' ),
'password' => $this->param( 'password' ),
);
}
$settings['auth_key'] = base64_encode( $this->get_consumer_key() . ':' . $this->get_consumer_secret() );
return new Thrive_Dash_Api_GoToWebinar( $this->get_consumer_key(), $access_token, $organizer_key, $settings );
}
/**
* get all Subscriber Lists from this API service
*
* @return array|bool for error
*/
protected function _get_lists() {
/** @var Thrive_Dash_Api_GoToWebinar $api */
$api = $this->get_api();
$lists = array();
try {
$all = $api->getUpcomingWebinars();
foreach ( $all as $item ) {
preg_match( '#register/(\d+)$#', $item['registrationUrl'], $m );
$id_from_registration_url = isset( $m[1] ) ? $m[1] : '';
$lists [] = array(
'id' => ! empty( $item['webinarKey'] ) ? $item['webinarKey'] : $id_from_registration_url,
'name' => $item['subject'] . ' (' . date( 'Y-m-d H:i:s', strtotime( $item['times'][0]['startTime'] ) ) . ')',
);
}
return $lists;
} catch ( Thrive_Dash_Api_GoToWebinar_Exception $e ) {
$this->_error = $e->getMessage();
return false;
}
}
}

View File

@@ -0,0 +1,108 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class Thrive_Dash_List_Connection_Google extends Thrive_Dash_List_Connection_Abstract {
protected $_key = 'google';
/**
* Thrive_Dash_List_Connection_Google constructor.
*/
public function __construct() {
$this->set_credentials( Thrive_Dash_List_Manager::credentials( $this->_key ) );
}
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'social';
}
/**
* @return string the API connection title
*/
public function get_title() {
return 'Google';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'google' );
}
/**
* should handle: read data from post / get, test connection and save the details
*
* on error, it should register an error message (and redirect?)
*
* @return mixed
*/
public function read_credentials() {
$client_id = ! empty( $_POST['client_id'] ) ? sanitize_text_field( $_POST['client_id'] ) : '';
$client_secret = ! empty( $_POST['client_secret'] ) ? sanitize_text_field( $_POST['client_secret'] ) : '';
$api_key = ! empty( $_POST['api_key'] ) ? sanitize_text_field( $_POST['api_key'] ) : '';
if ( empty( $client_id ) || empty( $client_secret ) ) {
return $this->error( __( 'Both Client ID and Client Secret fields are required', 'thrive-dash' ) );
}
$this->set_credentials( array( 'client_id' => $client_id, 'client_secret' => $client_secret, 'api_key' => $api_key ) );
$result = $this->test_connection();
if ( $result !== true ) {
return $this->error( sprintf( __( 'Incorrect Client ID.', 'thrive-dash' ), $result ) );
}
/**
* finally, save the connection details
*/
$this->save();
return $this->success( __( 'Google connected successfully!', 'thrive-dash' ) );
}
/**
* test if the secret key is correct, and it exists.
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
//TODO: implement testing the connection
return true;
}
/**
* @return string
*/
public function custom_success_message() {
return ' ';
}
/*
* Those functions do not apply
*/
protected function get_api_instance() {
}
protected function _get_lists() {
}
public function add_subscriber( $list_identifier, $arguments ) {
}
}

View File

@@ -0,0 +1,839 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_KlickTipp extends Thrive_Dash_List_Connection_Abstract {
/**
* Key used for mapping custom fields
*
* @var string
*/
protected $_key = '_field';
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'autoresponder';
}
/**
* @return string the API connection title
*/
public function get_title() {
return 'KlickTipp';
}
/**
* @return bool
*/
public function has_tags() {
return true;
}
/**
* Define support for custom fields.
*
* @return boolean
*/
public function has_custom_fields() {
return true;
}
public function push_tags( $tags, $data = array() ) {
if ( ! $this->has_tags() && ( ! is_array( $tags ) || ! is_string( $tags ) ) ) {
return $data;
}
$_key = $this->get_tags_key();
if ( ! isset( $data[ $_key ] ) ) {
$data[ $_key ] = array();
}
if ( isset( $data['klicktipp_tag'] ) ) {
$data[ $_key ][] = $data['klicktipp_tag'];
}
$existing_tags = $this->getTags();
/** @var Thrive_Dash_Api_KlickTipp $api */
$api = $this->get_api();
try {
$api->login();
} catch ( Thrive_Dash_Api_KlickTipp_Exception $e ) {
return $this->error( sprintf( __( 'Could not connect to Klick Tipp using the provided data (%s)', 'thrive-dash' ), $e->getMessage() ) );
}
foreach ( $tags as $key => $tag ) {
$tag = trim( $tag );
if ( empty( $tags ) ) {
continue;
}
if ( ! in_array( $tag, $existing_tags ) ) {
try {
$data[ $_key ][] = (int) $api->createTag( $tag );
} catch ( Thrive_Dash_Api_KlickTipp_Exception $e ) {
$this->error = $e->getMessage();
}
} else {
$data[ $_key ][] = array_search( $tag, $existing_tags );
}
}
return $data;
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'klicktipp' );
}
/**
* should handle: read data from post / get, test connection and save the details
*
* on error, it should register an error message (and redirect?)
*
* @return mixed
*/
public function read_credentials() {
$user = ! empty( $_POST['connection']['kt_user'] ) ? sanitize_text_field( $_POST['connection']['kt_user'] ) : '';
$password = ! empty( $_POST['connection']['kt_password'] ) ? sanitize_text_field( $_POST['connection']['kt_password'] ) : '';
if ( empty( $user ) || empty( $password ) ) {
return $this->error( __( 'Email and password are required', 'thrive-dash' ) );
}
$this->set_credentials(
array(
'user' => $user,
'password' => $password,
)
);
/** @var Thrive_Dash_Api_KlickTipp $api */
$api = $this->get_api();
try {
$api->login();
$result = $this->test_connection();
if ( $result !== true ) {
return $this->error( sprintf( __( 'Could not connect to Klick Tipp using the provided data: %s', 'thrive-dash' ), $this->_error ) );
}
/**
* finally, save the connection details
*/
$this->save();
return $this->success( __( 'Klick Tipp connected successfully!', 'thrive-dash' ) );
} catch ( Thrive_Dash_Api_KlickTipp_Exception $e ) {
return $this->error( sprintf( __( 'Could not connect to Klick Tipp using the provided data (%s)', 'thrive-dash' ), $e->getMessage() ) );
}
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
return is_array( $this->_get_lists() );
}
/**
* instantiate the API code required for this connection
*
* @return mixed
*/
protected function get_api_instance() {
return new Thrive_Dash_Api_KlickTipp( $this->param( 'user' ), $this->param( 'password' ) );
}
/**
* get all Subscriber Lists from this API service
*
* @return array|bool for error
*/
protected function _get_lists() {
/** @var Thrive_Dash_Api_KlickTipp $api */
$api = $this->get_api();
try {
$api->login();
} catch ( Thrive_Dash_Api_KlickTipp_Exception $e ) {
return $this->error( sprintf( __( 'Could not connect to Klick Tipp using the provided data (%s)', 'thrive-dash' ), $e->getMessage() ) );
}
try {
$all = $api->getLists();
$lists = array();
foreach ( $all as $id => $name ) {
if ( ! empty( $name ) ) {
$lists[] = array(
'id' => $id,
'name' => $name,
);
}
}
return $lists;
} catch ( Thrive_Dash_Api_KlickTipp_Exception $e ) {
$this->_error = $e->getMessage();
return false;
}
}
/**
* Subscribe an email. Requires to be logged in.
*
* @param mixed $list_identifier The id subscription process.
* @param mixed $arguments (optional) Additional fields of the subscriber.
*
* @return An object representing the Klicktipp subscriber object.
*/
public function add_subscriber( $list_identifier, $arguments ) {
/** @var Thrive_Dash_Api_KlickTipp $api */
$api = $this->get_api();
try {
$api->login();
} catch ( Thrive_Dash_Api_KlickTipp_Exception $e ) {
return $this->error( sprintf( __( 'Could not connect to Klick Tipp using the provided data (%s)', 'thrive-dash' ), $e->getMessage() ) );
}
// Handle tags - get or create tag IDs BEFORE contact creation.
$tag_ids = array();
$all_tag_names = array();
// Helper function to process tag string
$process_tags = function( $tags_string ) {
$tag_names = explode( ',', trim( $tags_string, ' ,' ) );
return array_filter( array_map( 'trim', $tag_names ) );
};
// Check for tags in all possible field names and collect them
if ( ! empty( $arguments['klicktipp_tags'] ) ) {
$all_tag_names = array_merge( $all_tag_names, $process_tags( $arguments['klicktipp_tags'] ) );
}
if ( ! empty( $arguments['tags'] ) ) {
$all_tag_names = array_merge( $all_tag_names, $process_tags( $arguments['tags'] ) );
}
// Also check for old single tag field (klicktipp_tag)
if ( ! empty( $arguments['klicktipp_tag'] ) && $arguments['klicktipp_tag'] !== '0' ) {
// This is a tag ID, we need to convert it to tag name
$existing_tags = $this->getTags();
if ( isset( $existing_tags[ $arguments['klicktipp_tag'] ] ) ) {
$old_tag_name = $existing_tags[ $arguments['klicktipp_tag'] ];
if ( ! in_array( $old_tag_name, $all_tag_names ) ) {
$all_tag_names[] = $old_tag_name;
}
}
}
// Remove duplicates and get tag IDs
if ( ! empty( $all_tag_names ) ) {
$all_tag_names = array_unique( $all_tag_names );
$tag_ids = $this->get_or_create_tag_ids( $all_tag_names ) ?? [];
}
// Prepare default fields
if ( ! empty( $arguments['name'] ) ) {
list( $first_name, $last_name ) = $this->get_name_parts( $arguments['name'] );
}
$fields = array();
if ( ! empty( $first_name ) ) {
$fields['fieldFirstName'] = $first_name;
}
if ( ! empty( $last_name ) ) {
$fields['fieldLastName'] = $last_name;
}
// Add phone
if ( ! empty( $arguments['phone'] ) ) {
$fields['fieldPhone'] = sanitize_text_field( $arguments['phone'] );
}
// Handle custom fields mapping
if ( ! empty( $arguments['tve_mapping'] ) ) {
$custom_fields = $this->generateCustomFields( $arguments );
$fields = array_merge( $fields, $custom_fields );
} elseif ( ! empty( $arguments['automator_custom_fields'] ) ) {
$fields = array_merge( $fields, $arguments['automator_custom_fields'] );
}
try {
$api->subscribe(
$arguments['email'],
$list_identifier,
$tag_ids,
! empty( $fields ) ? $fields : ''
);
// Tag user by email, array tags.
if ( ! empty( $tag_ids ) ) {
$api->tagByEmail( $arguments['email'], $tag_ids );
}
/**
* get redirect url if needed
*/
$return = true;
if ( isset( $_POST['_submit_option'] ) && $_POST['_submit_option'] == 'klicktipp-redirect' ) {
$return = $api->subscription_process_redirect( $list_identifier, $arguments['email'] );
}
$api->logout();
return $return;
} catch ( Thrive_Dash_Api_KlickTipp_Exception $e ) {
return $e->getMessage();
}
}
/**
* Get or create tag IDs.
*
* @param [type] $tag_names Tag names.
* @return array
*/
private function get_or_create_tag_ids( $tag_names ) {
$tag_ids = array();
try {
// Get all existing tags first - GET /contact_tags.
$existing_tags = $this->getTags();
$tag_map = array();
// Create a map of tag name => tag_id (case-insensitive).
if ( is_array( $existing_tags ) && ! empty( $existing_tags ) ) {
foreach ( $existing_tags as $tag_id => $tag_name ) {
if ( isset( $tag_name ) && isset( $tag_id ) ) {
$tag_map[ strtolower( trim( $tag_name ) ) ] = $tag_id;
}
}
}
// Process each tag name.
foreach ( $tag_names as $tag_name ) {
$tag_key = strtolower( trim( $tag_name ) );
// Check if tag already exists.
if ( isset( $tag_map[ $tag_key ] ) ) {
$tag_ids[] = $tag_map[ $tag_key ];
} else {
// Create new tag and get its ID.
$new_tag_id = $this->create_new_tag( $tag_name );
if ( $new_tag_id ) {
$tag_ids[] = $new_tag_id;
}
}
}
} catch ( Exception $e ) {
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
error_log( 'KlickTipp: Failed to get or create tag IDs - ' . $e->getMessage() );
}
}
return $tag_ids;
}
/**
* Create a new tag using POST /contact_tags.
*
* @param string $tag_name Tag name.
* @return int|null Tag ID.
*/
private function create_new_tag( $tag_name ) {
try {
$tag_data = trim( $tag_name );
$result = $this->get_api()->createTag( $tag_data );
if ( isset( $result ) && is_numeric( $result ) ) {
// Clear the tags cache since we created a new tag
$this->clearTagsCache();
return $result;
}
} catch ( Exception $e ) {
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
error_log( 'KlickTipp: Failed to create tag "' . $tag_name . '" - ' . $e->getMessage() );
}
}
return false;
}
/**
* Gets a list of tags through GET /tag API with 15-minute transient caching
*
* @return array
*/
public function getTags() {
// Create a unique cache key based on API credentials
$credentials = $this->get_credentials();
$cache_key = 'klicktipp_tags_' . md5( serialize( $credentials ) );
// Try to get cached tags first
$cached_tags = get_transient( $cache_key );
if ( false !== $cached_tags && is_array( $cached_tags ) ) {
// Sort cached tags alphabetically by value
asort( $cached_tags );
return $cached_tags;
}
$tags = array();
try {
/** @var Thrive_Dash_Api_KlickTipp $api */
$api = $this->get_api();
$tags = $api->getTags();
// Cache the tags for 15 minutes (900 seconds)
if ( is_array( $tags ) && ! empty( $tags ) ) {
// Sort tags alphabetically by value before caching
asort( $tags );
set_transient( $cache_key, $tags, 15 * MINUTE_IN_SECONDS );
}
} catch ( Exception $e ) {
// If API call fails but we have expired cache, use it
$expired_cache = get_transient( $cache_key . '_backup' );
if ( false !== $expired_cache && is_array( $expired_cache ) ) {
asort( $expired_cache );
return $expired_cache;
}
}
// Sort tags alphabetically by value
if ( is_array( $tags ) && ! empty( $tags ) ) {
asort( $tags );
// Store a backup cache that doesn't expire for fallback
set_transient( $cache_key . '_backup', $tags, YEAR_IN_SECONDS );
}
return $tags;
}
/**
* Clear the tags cache (useful when tags are created/updated)
*
* @return void
*/
public function clearTagsCache() {
$credentials = $this->get_credentials();
$cache_key = 'klicktipp_tags_' . md5( serialize( $credentials ) );
delete_transient( $cache_key );
delete_transient( $cache_key . '_backup' );
}
/**
* output any (possible) extra editor settings for this API
*
* @param array $params allow various different calls to this method
*/
public function get_extra_settings( $params = array() ) {
$params['tags'] = $this->getTags();
if ( ! is_array( $params['tags'] ) ) {
$params['tags'] = array();
}
return $params;
}
/**
* output any (possible) extra editor settings for this API
*
* @param array $params allow various different calls to this method
*/
public function render_extra_editor_settings( $params = array() ) {
$params['tags'] = $this->getTags();
if ( ! is_array( $params['tags'] ) ) {
$params['tags'] = array();
}
$this->output_controls_html( 'klicktipp/tags', $params );
}
/**
* Return the connection email merge tag
*
* @return String
*/
public static function get_email_merge_tag() {
return '%Subscriber:EmailAddress%';
}
public function get_automator_add_autoresponder_mapping_fields() {
return array( 'autoresponder' => array( 'mailing_list', 'api_fields', 'tag_select' ) );
}
public function get_automator_tag_autoresponder_mapping_fields() {
return array( 'autoresponder' => array( 'tag_select' ) );
}
/**
* Get API custom fields
*
* @param mixed $params
* @param bool $force
* @param bool $get_all
*
* @return array
*/
public function get_api_custom_fields( $params, $force = false, $get_all = false ) {
// Serve from cache if exists and requested
$cached_data = $this->get_cached_custom_fields();
if ( false === $force && ! empty( $cached_data ) ) {
return $cached_data;
}
$custom_data = array();
try {
/** @var Thrive_Dash_Api_KlickTipp $api */
$api = $this->get_api();
$api->login();
$custom_fields = $api->getCustomFields();
if ( is_array( $custom_fields ) ) {
foreach ( $custom_fields as $field ) {
$custom_data[] = $this->normalize_custom_field( $field );
}
}
$this->_save_custom_fields( $custom_data );
} catch ( Thrive_Dash_Api_KlickTipp_Exception $e ) {
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
error_log( 'KlickTipp: Failed to get custom fields - ' . $e->getMessage() );
}
}
return $custom_data;
}
/**
* Normalize custom field data
*
* @param array $field
*
* @return array
*/
protected function normalize_custom_field( $field ) {
$field = (array) $field;
return array(
'id' => ! empty( $field['id'] ) ? $field['id'] : '',
'name' => ! empty( $field['name'] ) ? $field['name'] : '',
'type' => $field['type'],
'label' => ! empty( $field['label'] ) ? $field['label'] : ( ! empty( $field['name'] ) ? $field['name'] : '' ),
);
}
/**
* Get available custom fields for this API connection
*
* @param null $list_id
*
* @return array
*/
public function get_available_custom_fields( $list_id = null ) {
return $this->get_api_custom_fields( null, true );
}
/**
* Append custom fields to defaults
*
* @param array $params
*
* @return array
*/
public function get_custom_fields( $params = array() ) {
return array_merge( parent::get_custom_fields(), $this->_mapped_custom_fields );
}
/**
* Build mapped custom fields array based on form params
*
* @param array $args
*
* @return array
*/
public function buildMappedCustomFields( $args ) {
$mapped_data = array();
// Should be always base_64 encoded of a serialized array
if ( empty( $args['tve_mapping'] ) || ! tve_dash_is_bas64_encoded( $args['tve_mapping'] ) || ! is_serialized( base64_decode( $args['tve_mapping'] ) ) ) {
return $mapped_data;
}
$form_data = thrive_safe_unserialize( base64_decode( $args['tve_mapping'] ) );
$mapped_fields = $this->get_mapped_field_ids();
foreach ( $mapped_fields as $mapped_field_name ) {
// Extract an array with all custom fields (siblings) names from form data
// {ex: [mapping_url_0, .. mapping_url_n] / [mapping_text_0, .. mapping_text_n]}
$cf_form_fields = preg_grep( "#^{$mapped_field_name}#i", array_keys( $form_data ) );
// Matched "form data" for current allowed name
if ( ! empty( $cf_form_fields ) && is_array( $cf_form_fields ) ) {
// Pull form allowed data, sanitize it and build the custom fields array
foreach ( $cf_form_fields as $cf_form_name ) {
if ( empty( $form_data[ $cf_form_name ][ $this->_key ] ) ) {
continue;
}
$field_id = str_replace( $mapped_field_name . '_', '', $cf_form_name );
$mapped_data[ $field_id ] = array(
'type' => $mapped_field_name,
'value' => $form_data[ $cf_form_name ][ $this->_key ],
);
}
}
}
return $mapped_data;
}
/**
* Generate custom fields array for API submission
*
* @param array $args
*
* @return array
*/
private function generateCustomFields( $args ) {
$custom_fields = $this->get_api_custom_fields( array() );
$ids = $this->buildMappedCustomFields( $args );
$result = array();
$processed_fields = 0;
$skipped_fields = 0;
foreach ( $ids as $key => $id ) {
// Find the matching field in API custom fields
$field = array_filter(
$custom_fields,
function ( $item ) use ( $id ) {
return $item['id'] === $id['value'];
}
);
$field = array_values( $field );
if ( ! isset( $field[0] ) ) {
$skipped_fields++;
continue;
}
$api_field_id = $field[0]['id'];
// Try multiple possible field names in args.
$possible_field_names = array();
// Method 1: Use the actual API field ID directly.
$possible_field_names[] = $api_field_id;
// Method 2: Use the mapping key-based name (original logic).
if ( strpos( $id['type'], 'mapping_' ) !== false ) {
$possible_field_names[] = $id['type'] . '_' . $key;
} else {
// For non-mapping fields, try both the key and the type_key pattern.
$possible_field_names[] = $key;
$possible_field_names[] = $id['type'] . '_' . $key; // This is the missing piece!
}
// Method 3: Use field name if different from ID.
if ( ! empty( $field[0]['name'] ) && $field[0]['name'] !== $api_field_id ) {
$possible_field_names[] = $field[0]['name'];
}
// Method 4: Use field label if different from name and ID.
if ( ! empty( $field[0]['label'] ) &&
$field[0]['label'] !== $api_field_id &&
$field[0]['label'] !== $field[0]['name'] ) {
$possible_field_names[] = $field[0]['label'];
}
$found_field_value = null;
// Find the first matching field value without nested loop.
$clean_field_names = array_map(
function ( $name ) {
return str_replace( '[]', '', $name );
},
$possible_field_names
);
$matching_fields = array_filter(
$clean_field_names,
function ( $clean_name ) use ( $args ) {
return isset( $args[ $clean_name ] ) && ! empty( $args[ $clean_name ] );
}
);
if ( ! empty( $matching_fields ) ) {
$first_matching_field = reset( $matching_fields );
$found_field_value = $args[ $first_matching_field ];
}
if ( null !== $found_field_value ) {
// Convert date fields to unix timestamp.
if ( 'date' === $id['type'] && ! empty( $found_field_value ) ) {
$timestamp = $this->convertDateToTimestamp( $found_field_value );
if ( false !== $timestamp ) {
$found_field_value = $timestamp;
} elseif ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
error_log( "WARNING: Failed to convert date '$found_field_value' to timestamp" );
}
}
$processed_value = $this->process_field( $found_field_value );
$result[ $api_field_id ] = $processed_value;
++$processed_fields;
} else {
++$skipped_fields;
}
}
return $result;
}
/**
* Convert various date formats to unix timestamp
*
* @param string $date_string The date string to convert
*
* @return int|false Unix timestamp or false on failure
*/
private function convertDateToTimestamp( $date_string ) {
if ( empty( $date_string ) ) {
return false;
}
// Clean up the date string.
$date_string = trim( $date_string );
// List of possible date formats to try.
$formats = array(
'd/m/Y', // 29/09/2025 (European format)
'd/m/y', // 29/09/25
'm/d/Y', // 09/29/2025 (US format)
'm/d/y', // 09/29/25
'Y-m-d', // 2025-09-29 (ISO format)
'd-m-Y', // 29-09-2025
'm-d-Y', // 09-29-2025
'd.m.Y', // 29.09.2025 (German format)
'm.d.Y', // 09.29.2025
);
// Try each format.
foreach ( $formats as $format ) {
$date = DateTime::createFromFormat( $format, $date_string );
if ( false !== $date ) {
$timestamp = $date->getTimestamp();
return $timestamp;
}
}
// Fallback to strtotime() for other formats.
$timestamp = strtotime( $date_string );
if ( false !== $timestamp ) {
return $timestamp;
}
return false;
}
/**
* Build custom fields mapping for automations.
*
* @param array $automation_data Automation data.
*
* @return array
*/
public function build_automation_custom_fields( $automation_data ) {
$mapped_data = array();
$fields = $this->get_api_custom_fields( array() );
if ( ! empty( $automation_data['api_fields'] ) && is_array( $automation_data['api_fields'] ) ) {
foreach ( $automation_data['api_fields'] as $pair ) {
foreach ( $fields as $field ) {
if ( $field['id'] === $pair['key'] ) {
$value = sanitize_text_field( $pair['value'] );
if ( $value ) {
$mapped_data[ $field['id'] ] = $value;
}
}
}
}
}
return $mapped_data;
}
/**
* Add custom fields to subscriber
*
* @param string $email Email.
* @param array $custom_fields Custom fields.
* @param array $extra Extra.
*
* @return bool|mixed
*/
public function add_custom_fields( $email, $custom_fields = array(), $extra = array() ) {
if ( empty( $email ) || empty( $custom_fields ) ) {
return false;
}
/** @var Thrive_Dash_Api_KlickTipp $api */
$api = $this->get_api();
try {
$api->login();
// Custom fields in KlickTipp are handled during subscription
// This method could be used for future API enhancements
return true;
} catch ( Thrive_Dash_Api_KlickTipp_Exception $e ) {
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
error_log( 'KlickTipp: Failed to add custom fields - ' . $e->getMessage() );
}
return false;
}
}
}

View File

@@ -0,0 +1,155 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_MadMimi extends Thrive_Dash_List_Connection_Abstract {
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'autoresponder';
}
/**
* @return string the API connection title
*/
public function get_title() {
return 'MadMimi';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'madmimi' );
}
/**
* should handle: read data from post / get, test connection and save the details
*
* on error, it should register an error message (and redirect?)
*
* @return mixed
*/
public function read_credentials() {
$key = ! empty( $_POST['connection']['key'] ) ? sanitize_text_field( $_POST['connection']['key'] ) : '';
$username = ! empty( $_POST['connection']['username'] ) ? sanitize_text_field( $_POST['connection']['username'] ) : '';
if ( empty( $key ) || empty( $username ) ) {
return $this->error( __( 'Username and API Key are required', 'thrive-dash' ) );
}
$this->set_credentials( array( 'key' => $key, 'username' => $username ) );
$result = $this->test_connection();
if ( $result !== true ) {
return $this->error( sprintf( __( 'Could not connect to MadMimi using the provided data', 'thrive-dash' ), $result ) );
}
/**
* finally, save the connection details
*/
$this->save();
return $this->success( __( 'MadMimi connected successfully', 'thrive-dash' ) );
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
/** @var Thrive_Dash_Api_MadMimi $api */
$api = $this->get_api();
/**
* just try getting the list of the promotions as a connection test
*/
try {
$api->getAudienceLists(); // this will throw the exception if there is a connection problem
} catch ( Thrive_Dash_Api_MadMimi_Exception $e ) {
return $e->getMessage();
}
return true;
}
/**
* instantiate the API code required for this connection
*
* @return mixed
*/
protected function get_api_instance() {
return new Thrive_Dash_Api_MadMimi( $this->param( 'key' ), $this->param( 'username' ) );
}
/**
* get all Subscriber Lists from this API service
*
* @return array|bool for error
*/
protected function _get_lists() {
/** @var Thrive_Dash_Api_MadMimi $api */
$api = $this->get_api();
try {
$lists = array();
$audienceList = $api->getAudienceLists();
foreach ( $audienceList as $key => $item ) {
$lists [] = array(
'id' => $item['name'],
'name' => $item['name'],
);
}
return $lists;
} catch ( Thrive_Dash_Api_MadMimi_Exception $e ) {
$this->_error = $e->getMessage();
return false;
}
}
/**
* add a contact to a list
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return mixed
*/
public function add_subscriber( $list_identifier, $arguments ) {
/** @var Thrive_Dash_Api_MadMimi $api */
$api = $this->get_api();
try {
$api->registerToAudienceList( $list_identifier, $arguments['name'], $arguments['email'] );
return true;
} catch ( Thrive_Dash_Api_MadMimi_Exception $e ) {
return $e->getMessage();
} catch ( Exception $e ) {
return $e->getMessage();
}
}
/**
* Return the connection email merge tag
*
* @return String
*/
public static function get_email_merge_tag() {
return '(email)';
}
}

View File

@@ -0,0 +1,490 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* MailPoet autoresponder integration for Thrive Architect Lead Generation
*/
class Thrive_Dash_List_Connection_MailPoet extends Thrive_Dash_List_Connection_Abstract {
/**
* Key used for mapping custom fields
*
* @var string
*/
protected $_key = '_field';
/**
* Constructor - initialize custom fields mapping
*
* @param string $key API connection key
*/
public function __construct( $key ) {
parent::__construct( $key );
$this->set_custom_fields_mapping();
}
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'autoresponder';
}
/**
* @return string
*/
public function get_title() {
return 'MailPoet';
}
/**
* @return bool
*/
public function has_tags() {
return false; // MailPoet uses segments/lists instead of tags
}
/**
* @return bool
*/
public function has_optin() {
return true;
}
/**
* @return bool
*/
public function has_custom_fields() {
return true;
}
/**
* Check whether or not the MailPoet plugin is installed
*
* @return bool
*/
public function pluginInstalled() {
return class_exists( '\MailPoet\API\API' );
}
/**
* Output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'mailpoet' );
}
/**
* Just save the key in the database
*
* @return mixed|void
*/
public function read_credentials() {
if ( ! $this->pluginInstalled() ) {
return $this->error( __( 'MailPoet plugin must be installed and activated.', 'thrive-dash' ) );
}
$connection_data = $this->post( 'connection', array() );
$connection_data['connected'] = true;
$this->set_credentials( $connection_data );
$result = $this->test_connection();
if ( $result !== true ) {
return $this->error( '<strong>' . $result . '</strong>' );
}
/**
* Finally, save the connection details.
*/
$this->save();
return true;
}
/**
* Test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
if ( ! $this->pluginInstalled() ) {
return __( 'MailPoet plugin must be installed and activated.', 'thrive-dash' );
}
try {
$api = \MailPoet\API\API::MP( 'v1' );
// Test by getting subscriber fields - this will fail if API is not working
$api->getSubscriberFields();
} catch ( Exception $exception ) {
return $exception->getMessage();
}
return true;
}
/**
* Add a contact to a list
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return mixed
*/
public function add_subscriber( $list_identifier, $arguments ) {
if ( ! $this->pluginInstalled() ) {
return __( 'MailPoet plugin is not installed / activated', 'thrive-dash' );
}
if ( empty( $arguments['email'] ) ) {
return __( 'Email address is required', 'thrive-dash' );
}
$prepared_args = array();
// Handle name
if ( ! empty( $arguments['name'] ) ) {
list( $first_name, $last_name ) = $this->get_name_parts( $arguments['name'] );
$prepared_args['first_name'] = sanitize_text_field( $first_name );
$prepared_args['last_name'] = sanitize_text_field( $last_name );
}
// Handle mapped fields from TAR
if ( ! empty( $arguments['tve_mapping'] ) ) {
$mapped_defaults = $this->buildMappedDefaultFields( $arguments );
$custom_fields = $this->buildMappedCustomFields( $arguments );
if ( ! empty( $mapped_defaults ) ) {
$prepared_args = array_merge( $prepared_args, $mapped_defaults );
}
if ( ! empty( $custom_fields ) ) {
$prepared_args = array_merge( $prepared_args, $custom_fields );
}
}
// Set subscriber status based on optin choice
$status = 'subscribed'; // Default to single optin
if ( isset( $arguments['mailpoet_optin'] ) && 'd' === $arguments['mailpoet_optin'] ) {
$status = 'unconfirmed'; // This will trigger double optin
}
$data = array_merge(
array(
'email' => sanitize_email( $arguments['email'] ),
'status' => $status,
),
$prepared_args
);
try {
$api = \MailPoet\API\API::MP( 'v1' );
// Add or update subscriber
$subscriber = $api->addSubscriber( $data, array( $list_identifier ) );
// Send confirmation email if double optin is enabled
if ( 'unconfirmed' === $status ) {
$api->sendConfirmationEmail( $subscriber['id'] );
}
} catch ( Exception $exception ) {
return $exception->getMessage();
}
return true;
}
/**
* Build mapped custom fields array (only actual custom fields)
*
* @param array $args Form arguments
*
* @return array Mapped custom fields data
*/
public function buildMappedCustomFields( $args ) {
if ( empty( $args['tve_mapping'] ) || ! is_array( $args['tve_mapping'] ) ) {
return array();
}
$custom_fields = array();
$available_fields = $this->get_all_custom_fields( false );
if ( empty( $available_fields ) ) {
return array();
}
// Create lookup array for available custom fields
$custom_field_ids = array();
$default_field_ids = $this->get_default_field_ids();
foreach ( $available_fields as $field ) {
if ( ! empty( $field['id'] ) && ! in_array( $field['id'], $default_field_ids, true ) ) {
$custom_field_ids[] = $field['id'];
}
}
foreach ( $args['tve_mapping'] as $form_field => $api_field ) {
if ( empty( $api_field ) || empty( $args[ $form_field ] ) ) {
continue;
}
// Only process actual custom fields (not default subscriber fields)
if ( in_array( $api_field, $custom_field_ids, true ) ) {
$custom_fields[ $api_field ] = sanitize_text_field( $args[ $form_field ] );
}
}
return $custom_fields;
}
/**
* Build mapped default fields array (first_name, last_name, etc.)
*
* @param array $args Form arguments
*
* @return array Mapped default fields data
*/
public function buildMappedDefaultFields( $args ) {
if ( empty( $args['tve_mapping'] ) || ! is_array( $args['tve_mapping'] ) ) {
return array();
}
$default_fields = array();
$allowed_defaults = $this->get_default_field_ids();
foreach ( $args['tve_mapping'] as $form_field => $api_field ) {
if ( empty( $api_field ) || empty( $args[ $form_field ] ) ) {
continue;
}
// Only process default subscriber fields
if ( in_array( $api_field, $allowed_defaults, true ) ) {
$default_fields[ $api_field ] = sanitize_text_field( $args[ $form_field ] );
}
}
return $default_fields;
}
/**
* Get default MailPoet subscriber field IDs
*
* @return array
*/
protected function get_default_field_ids() {
return array( 'first_name', 'last_name' );
}
/**
* Get all available fields (default + custom)
*
* @param bool $force Force refresh from API
*
* @return array
*/
public function get_all_custom_fields( $force ) {
$cached_data = $this->get_cached_custom_fields();
if ( false === $force && ! empty( $cached_data ) ) {
return $cached_data;
}
if ( ! $this->pluginInstalled() ) {
return array();
}
// Default MailPoet subscriber fields
$fields = array(
array( 'id' => 'first_name', 'name' => 'First Name', 'type' => 'text', 'label' => 'First Name' ),
array( 'id' => 'last_name', 'name' => 'Last Name', 'type' => 'text', 'label' => 'Last Name' ),
);
try {
$api = \MailPoet\API\API::MP( 'v1' );
$subscriber_fields = $api->getSubscriberFields();
if ( is_array( $subscriber_fields ) ) {
foreach ( $subscriber_fields as $field ) {
// Skip default fields (email, first_name, last_name)
if ( ! empty( $field['id'] ) && ! in_array( $field['id'], array( 'email', 'first_name', 'last_name' ), true ) ) {
$fields[] = array(
'id' => sanitize_text_field( $field['id'] ),
'name' => ! empty( $field['name'] ) ? sanitize_text_field( $field['name'] ) : $field['id'],
'type' => ! empty( $field['type'] ) ? sanitize_text_field( $field['type'] ) : 'text',
'label' => ! empty( $field['name'] ) ? sanitize_text_field( $field['name'] ) : $field['id'],
);
}
}
}
} catch ( Exception $e ) {
// Log error but continue with default fields
error_log( 'MailPoet API error: ' . $e->getMessage() );
}
$this->_save_custom_fields( $fields );
return $fields;
}
/**
* Get MailPoet lists/segments for TAR dropdown
*
* @param bool $use_cache Whether to use cached results
*
* @return array
*/
public function get_lists( $use_cache = true ) {
if ( ! $this->pluginInstalled() ) {
return array();
}
// Check cache first if requested
if ( $use_cache ) {
$cached_lists = get_transient( 'tve_mailpoet_lists_' . md5( $this->_key ) );
if ( false !== $cached_lists ) {
return $cached_lists;
}
}
try {
$api = \MailPoet\API\API::MP( 'v1' );
$segments = $api->getLists();
$lists = array();
if ( is_array( $segments ) ) {
foreach ( $segments as $segment ) {
if ( ! empty( $segment['id'] ) && ! empty( $segment['name'] ) ) {
$lists[] = array(
'id' => sanitize_text_field( $segment['id'] ),
'name' => sanitize_text_field( $segment['name'] ),
);
}
}
}
// Cache the results for 30 minutes
if ( ! empty( $lists ) ) {
set_transient( 'tve_mailpoet_lists_' . md5( $this->_key ), $lists, 30 * MINUTE_IN_SECONDS );
}
return $lists;
} catch ( Exception $exception ) {
error_log( 'MailPoet get lists error: ' . $exception->getMessage() );
return array();
}
}
/**
* Normalize custom field data
*
* @param array $field
*
* @return array
*/
protected function normalize_custom_field( $field ) {
$field = (array) $field;
return array(
'id' => ! empty( $field['id'] ) ? sanitize_text_field( $field['id'] ) : '',
'name' => ! empty( $field['name'] ) ? sanitize_text_field( $field['name'] ) : '',
'type' => ! empty( $field['type'] ) ? sanitize_text_field( $field['type'] ) : 'text',
'label' => ! empty( $field['name'] ) ? sanitize_text_field( $field['name'] ) : '',
);
}
/**
* Get available custom fields for this api connection
*
* @param null $list_id
*
* @return array
*/
public function get_available_custom_fields( $list_id = null ) {
return $this->get_all_custom_fields( true );
}
/**
* Get custom fields for TAR form builder (merges default + mapped fields)
*
* @param array $params
*
* @return array
*/
public function get_custom_fields( $params = array() ) {
return array_merge( parent::get_custom_fields(), $this->_mapped_custom_fields );
}
/**
* Get API custom fields for TAR (returns all available MailPoet fields)
*
* @param array $params
* @param bool $force
* @param bool $get_all
*
* @return array
*/
public function get_api_custom_fields( $params, $force = false, $get_all = false ) {
return $this->get_all_custom_fields( $force );
}
/**
* Get API instance (not needed for MailPoet since we use their API directly)
*
* @return null
*/
protected function get_api_instance() {
// No API instance needed here - we use MailPoet\API\API directly
return null;
}
/**
* Get all subscriber lists from MailPoet API service
*
* @return array|bool
*/
protected function _get_lists() {
if ( ! $this->pluginInstalled() ) {
$this->_error = __( 'MailPoet plugin must be installed and activated.', 'thrive-dash' );
return false;
}
try {
$api = \MailPoet\API\API::MP( 'v1' );
$segments = $api->getLists();
$lists = array();
if ( is_array( $segments ) ) {
foreach ( $segments as $segment ) {
if ( ! empty( $segment['id'] ) && ! empty( $segment['name'] ) ) {
$lists[] = array(
'id' => sanitize_text_field( $segment['id'] ),
'name' => sanitize_text_field( $segment['name'] ),
);
}
}
}
return $lists;
} catch ( Exception $exception ) {
$this->_error = sprintf( __( 'MailPoet API Error: %s', 'thrive-dash' ), $exception->getMessage() );
return false;
}
}
/**
* Return the connection email merge tag
*
* @return String
*/
public static function get_email_merge_tag() {
return '[subscriber:email]';
}
}

View File

@@ -0,0 +1,727 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class Thrive_Dash_List_Connection_MailRelay extends Thrive_Dash_List_Connection_Abstract {
/**
* Key used for mapping custom fields
*
* @var string
*/
protected $_key = '_field';
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'autoresponder';
}
/**
* @return string
*/
public function get_title() {
return 'MailRelay';
}
/**
* @return bool
*/
public function has_tags() {
return true;
}
/**
* @return bool
*/
public function has_custom_fields() {
return true;
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$related_api = Thrive_Dash_List_Manager::connection_instance( 'mailrelayemail' );
if ( $related_api->is_connected() ) {
$this->set_param( 'new_connection', 1 );
}
$this->output_controls_html( 'mailrelay' );
}
/**
* just save the key in the database
*
* @return mixed|void
*/
public function read_credentials() {
$connection = $this->post( 'connection' );
$key = ! empty( $connection['key'] ) ? $connection['key'] : '';
if ( empty( $key ) ) {
return $this->error( __( 'You must provide a valid MailRelay key', 'thrive-dash' ) );
}
$connection['url'] = isset( $connection['domain'] ) ? $connection['domain'] : $connection['url'];
$url = ! empty( $connection['url'] ) ? $connection['url'] : '';
if ( filter_var( $url, FILTER_VALIDATE_URL ) === false || empty( $url ) ) {
return $this->error( __( 'You must provide a valid MailRelay URL', 'thrive-dash' ) );
}
$this->set_credentials( $connection );
$result = $this->test_connection();
if ( $result !== true ) {
return $this->error( sprintf( __( 'Could not connect to MailRelay using the provided key (<strong>%s</strong>)', 'thrive-dash' ), $result ) );
}
/**
* finally, save the connection details
*/
$this->save();
/** @var Thrive_Dash_List_Connection_MailRelayEmail $related_api */
$related_api = Thrive_Dash_List_Manager::connection_instance( 'mailrelayemail' );
if ( isset( $connection['new_connection'] ) && (int) $connection['new_connection'] === 1 ) {
/**
* Try to connect to the email service too
*/
$r_result = true;
if ( ! $related_api->is_connected() ) {
$_POST['connection'] = $connection;
$r_result = $related_api->read_credentials();
}
if ( $r_result !== true ) {
$this->disconnect();
return $this->error( $r_result );
}
} else {
/**
* let's make sure that the api was not edited and disconnect it
*/
$related_api->set_credentials( array() );
Thrive_Dash_List_Manager::save( $related_api );
}
return $this->success( __( 'MailRelay connected successfully', 'thrive-dash' ) );
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
/** @var Thrive_Dash_Api_MailRelay $mr */
$mr = $this->get_api();
// Prevent fatal errors if API is not available
if ( ! $mr ) {
return 'MailRelay API classes not available';
}
try {
$mr->get_list();
} catch ( Thrive_Dash_Api_MailRelay_Exception $e ) {
return $e->getMessage();
} catch ( Exception $e ) {
return $e->getMessage();
}
return true;
}
/**
* instantiate the API code required for this connection
*
* @return Thrive_Dash_Api_MailRelay|Thrive_Dash_Api_MailRelayV1
*/
protected function get_api_instance() {
$url = $this->param( 'url' );
$api_key = $this->param( 'key' );
// Validate essential parameters to prevent fatal errors
if ( empty( $url ) || empty( $api_key ) ) {
return null;
}
// Check if required API classes exist to prevent fatal errors
if ( false !== strpos( $url, 'ipzmarketing' ) ) {
if ( ! class_exists( 'Thrive_Dash_Api_MailRelayV1' ) ) {
return null;
}
$instance = new Thrive_Dash_Api_MailRelayV1( $url, $api_key );
} else {
if ( ! class_exists( 'Thrive_Dash_Api_MailRelay' ) ) {
return null;
}
$instance = new Thrive_Dash_Api_MailRelay(
array(
'host' => $url,
'apiKey' => $api_key,
)
);
}
return $instance;
}
/**
* get all Subscriber Lists from this API service
*
* @return array
* @throws Thrive_Dash_Api_MailRelay_Exception
*/
protected function _get_lists() {
/** @var Thrive_Dash_Api_MailRelay $api */
$api = $this->get_api();
// Prevent fatal errors if API is not available
if ( ! $api ) {
return array();
}
$body = $api->get_list();
$lists = array();
foreach ( $body as $item ) {
$lists [] = array(
'id' => $item['id'],
'name' => $item['name'],
);
}
return $lists;
}
/**
* Add a subscriber
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return bool|string true for success or string error message for failure
*/
public function add_subscriber( $list_identifier, $arguments ) {
// Validate essential parameters to prevent fatal errors
if ( empty( $arguments ) || ! is_array( $arguments ) ) {
return 'Invalid arguments provided'; // String for backward compatibility
}
if ( empty( $arguments['email'] ) || ! is_email( $arguments['email'] ) ) {
return 'Valid email address required'; // String for backward compatibility
}
$api = $this->get_api();
if ( ! $api ) {
return 'Cannot establish API connection'; // String for backward compatibility
}
// Check if we have a custom list_id from any mapping_hidden field (flexible logic)
$custom_list_id = null;
// Look for any field that starts with "mapping_hidden" and has numeric value. We use this to populate group under MailRelay, targeting group id.
foreach ( $arguments as $field_name => $field_value ) {
if ( strpos( $field_name, 'mapping_hidden' ) === 0 && is_numeric( $field_value ) ) {
$custom_list_id = $field_value;
break; // Use the first numeric mapping_hidden field found
}
}
if ( $custom_list_id ) {
$list_identifier = $custom_list_id;
}
// Validate list_identifier
if ( empty( $list_identifier ) || ! is_numeric( $list_identifier ) ) {
return 'Valid list identifier required'; // String for backward compatibility
}
// Process tags if provided
$tags = array();
if ( ! empty( $arguments['mailrelay_tags'] ) && is_string( $arguments['mailrelay_tags'] ) ) {
$tags = explode( ',', $arguments['mailrelay_tags'] );
$tags = array_map( 'trim', $tags );
$tags = array_filter( $tags ); // Remove empty tags
}
// Process custom fields if provided
$custom_fields = array();
if ( ! empty( $arguments['tve_mapping'] ) && is_string( $arguments['tve_mapping'] ) ) {
$custom_fields = $this->prepare_api_custom_fields( $arguments );
// Validate that prepare_api_custom_fields returned an array
if ( ! is_array( $custom_fields ) ) {
$custom_fields = array();
}
}
// Prepare subscriber data
$args = array(
'email' => $arguments['email'],
);
if ( ! empty( $arguments['name'] ) ) {
$args['name'] = $arguments['name'];
}
// Collect ALL custom fields from different sources
$all_custom_fields = array();
// Add phone field if valid
if ( ! empty( $arguments['phone'] ) && is_string( $arguments['phone'] ) ) {
$all_custom_fields['f_phone'] = sanitize_text_field( $arguments['phone'] );
}
// Add processed custom fields from tve_mapping
if ( ! empty( $custom_fields ) && is_array( $custom_fields ) ) {
foreach ( $custom_fields as $field_key => $field_value ) {
// Validate field key and value
if ( empty( $field_key ) || ! is_string( $field_key ) || $field_value === '' ) {
continue;
}
// Only exclude mapping_hidden if it's numeric (used for group selection)
if ( $field_key === 'mapping_hidden' && is_numeric( $field_value ) ) {
// Skip - this is used for group selection
} else {
// Process as normal custom field
$all_custom_fields[ $field_key ] = sanitize_text_field( $field_value );
}
}
}
// Store all custom fields for later processing
if ( ! empty( $all_custom_fields ) ) {
$args['customFields'] = $all_custom_fields;
}
try {
// Add subscriber to list
$result = $api->add_subscriber( $list_identifier, $args );
// Handle API errors - return string for backward compatibility
if ( is_array( $result ) && isset( $result['error'] ) ) {
return $result['error']; // String error message for backward compatibility
}
// Process BOTH tags and custom fields together in ONE API call to avoid conflicts
if ( isset( $result['id'] ) && $api instanceof Thrive_Dash_Api_MailRelayV1 ) {
$all_fields_to_update = array();
// Handle tags first - validate tags array
if ( ! empty( $tags ) && is_array( $tags ) ) {
try {
$tags_field = $api->get_custom_field( 'mailrelay_tags' );
if ( empty( $tags_field ) ) {
$tags_field = $api->create_custom_field( array(
'label' => 'Tags',
'tag_name' => 'mailrelay_tags',
'field_type' => 'text',
) );
}
if ( is_array( $tags_field ) && ! empty( $tags_field['id'] ) ) {
$combined_tags = implode( ',', array_map( 'trim', $tags ) );
if ( ! empty( $combined_tags ) ) {
$all_fields_to_update[ $tags_field['id'] ] = $combined_tags;
}
}
} catch ( Exception $e ) {
// Continue processing other fields
}
}
// Handle custom fields - validate array first
if ( ! empty( $all_custom_fields ) && is_array( $all_custom_fields ) ) {
foreach ( $all_custom_fields as $field_key => $field_value ) {
// Validate field data before processing
if ( empty( $field_key ) || ! is_string( $field_key ) || $field_value === '' ) {
continue;
}
try {
// Get/create custom field
if ( $field_key === 'f_phone' ) {
$custom_field = $api->get_custom_field( 'thrive_phone' );
if ( empty( $custom_field ) ) {
$custom_field = $api->create_custom_field( array(
'label' => 'Phone',
'tag_name' => 'thrive_phone',
'field_type' => 'text',
) );
}
} else {
$custom_field = $api->get_custom_field( $field_key );
if ( empty( $custom_field ) ) {
$custom_field = $api->create_custom_field( array(
'label' => ucfirst( str_replace( '_', ' ', $field_key ) ),
'tag_name' => $field_key,
'field_type' => 'text',
) );
}
}
// Add to batch if field exists and has valid ID
if ( is_array( $custom_field ) && ! empty( $custom_field['id'] ) && is_numeric( $custom_field['id'] ) ) {
$all_fields_to_update[ $custom_field['id'] ] = $field_value;
}
} catch ( Exception $e ) {
// Continue processing other fields
}
}
}
// Make ONE single API call with ALL fields (tags + custom fields)
if ( ! empty( $all_fields_to_update ) && is_array( $all_fields_to_update ) ) {
try {
$api->update_subscriber_custom_fields( $arguments['email'], $all_fields_to_update );
} catch ( Exception $e ) {
// Continue if custom fields update fails
}
}
}
// Maintain backward compatibility for Automator plugin
if ( is_array( $result ) && isset( $result['id'] ) ) {
return true; // Success - maintain original return type
}
return $result;
} catch ( Exception $e ) {
// Return string error message for backward compatibility
return $e->getMessage();
}
}
/**
* Based on custom inputs set in form and their mapping
* - prepares custom fields for MailRelay
*
* @param array $arguments POST sent by optin form
*
* @return array with MailRelay custom field name as key and the value of inputs filled by the visitor
*/
public function prepare_api_custom_fields( $arguments ) {
$fields = array();
if ( empty( $arguments['tve_mapping'] ) ) {
return $fields;
}
$serialized = base64_decode( $arguments['tve_mapping'] );
$mapping = array();
if ( $serialized ) {
$mapping = thrive_safe_unserialize( $serialized );
}
if ( empty( $mapping ) ) {
return $fields;
}
// Use the correct key for field mapping
$field_key = '_field';
foreach ( $mapping as $form_field_name => $field ) {
$form_field_name = str_replace( '[]', '', $form_field_name );
if ( ! empty( $field[ $field_key ] ) && ! empty( $arguments[ $form_field_name ] ) ) {
$api_field_name = $field[ $field_key ];
$custom_field_value = $arguments[ $form_field_name ];
$fields[ $api_field_name ] = is_array( $custom_field_value ) ? implode( ', ', $custom_field_value ) : $custom_field_value;
}
}
return $fields;
}
/**
* Build custom fields mapping for automations
*
* @param $automation_data
*
* @return array
*/
public function build_automation_custom_fields( $automation_data ) {
$mapped_data = array();
foreach ( $automation_data['api_fields'] as $pair ) {
$value = sanitize_text_field( $pair['value'] );
if ( $value ) {
$mapped_data[ $pair['key'] ] = $value;
}
}
return $mapped_data;
}
/**
* @param $email
* @param array $custom_fields
* @param array $extra
*
* @return false|int|mixed
*/
public function add_custom_fields( $email, $custom_fields = array(), $extra = array() ) {
try {
/** @var Thrive_Dash_Api_MailRelay|Thrive_Dash_Api_MailRelayV1 $api */
$api = $this->get_api();
$list_id = ! empty( $extra['list_identifier'] ) ? $extra['list_identifier'] : null;
$args = array(
'email' => $email,
);
if ( ! empty( $extra['name'] ) ) {
$args['name'] = $extra['name'];
}
$this->add_subscriber( $list_id, $args );
$prepared_fields = $this->prepare_custom_fields_for_api( $custom_fields );
if ( ! empty( $prepared_fields ) ) {
// Update subscriber with custom fields via MailRelay API
if ( method_exists( $api, 'update_subscriber_custom_fields' ) ) {
$api->update_subscriber_custom_fields( $email, $prepared_fields );
}
}
return true;
} catch ( Exception $e ) {
return false;
}
}
/**
* Prepare custom fields for API call
*
* @param array $custom_fields
* @param null $list_identifier
*
* @return array
*/
protected function prepare_custom_fields_for_api( $custom_fields = array(), $list_identifier = null ) {
$prepared_fields = array();
foreach ( $custom_fields as $field_name => $field_value ) {
if ( ! empty( $field_value ) ) {
$prepared_fields[ $field_name ] = sanitize_text_field( $field_value );
}
}
return $prepared_fields;
}
/**
* Get all custom fields from MailRelay
*
* @param bool $force
*
* @return array
*/
public function get_all_custom_fields( $force = false ) {
$custom_data = array();
$cached_data = $this->get_cached_custom_fields();
if ( false === $force && ! empty( $cached_data ) ) {
return $cached_data;
}
/** @var Thrive_Dash_Api_MailRelay|Thrive_Dash_Api_MailRelayV1 $api */
$api = $this->get_api();
// Prevent fatal errors if API is not available
if ( ! $api ) {
return $this->get_default_custom_fields();
}
try {
// Check if it's V1 API with custom fields support
if ( $api instanceof Thrive_Dash_Api_MailRelayV1 ) {
// For V1 API, we can get all custom fields directly
$custom_fields = $api->get_all_custom_fields();
if ( is_array( $custom_fields ) ) {
foreach ( $custom_fields as $field ) {
$custom_data[] = $this->normalize_custom_field( $field );
}
}
} else {
// For regular API, get custom fields or use defaults
$custom_fields = $api->get_custom_fields();
if ( is_array( $custom_fields ) ) {
foreach ( $custom_fields as $field ) {
$custom_data[] = $this->normalize_custom_field( $field );
}
}
}
} catch ( Exception $e ) {
// Silently handle exceptions
}
// If no custom fields were found, provide some default ones
if ( empty( $custom_data ) ) {
$custom_data = $this->get_default_custom_fields();
}
$this->_save_custom_fields( $custom_data );
return $custom_data;
}
/**
* Get API custom fields (required for editor custom fields detection)
* This method is called by Thrive_Dash_List_Manager::getAvailableCustomFields()
*
* @param array $params
* @param bool $force
* @param bool $get_all
*
* @return array
*/
public function get_api_custom_fields( $params = array(), $force = false, $get_all = false ) {
return $this->get_all_custom_fields( $force );
}
/**
* Get available custom fields for this api connection (for API compatibility)
*
* @param null $list_id
*
* @return array
*/
public function get_available_custom_fields( $list_id = null ) {
return $this->get_all_custom_fields( true );
}
/**
* Brings an API field under a known form that TAr can understand
*
* @param string|array $field
*
* @return array
*/
protected function normalize_custom_field( $field ) {
if ( is_string( $field ) ) {
return array(
'id' => $field,
'name' => $field,
'type' => 'text',
'label' => $field,
);
}
$field = (array) $field;
return array(
'id' => isset( $field['tag_name'] ) ? $field['tag_name'] : ( isset( $field['name'] ) ? $field['name'] : '' ),
'name' => isset( $field['label'] ) ? $field['label'] : ( isset( $field['name'] ) ? $field['name'] : '' ),
'type' => isset( $field['field_type'] ) ? $field['field_type'] : ( isset( $field['type'] ) ? $field['type'] : 'text' ),
'label' => isset( $field['label'] ) ? $field['label'] : ( isset( $field['name'] ) ? $field['name'] : '' ),
);
}
/**
* Apply tag to subscriber (MailRelay-specific implementation)
*
* @param string $email
* @param string $tag
*
* @return bool
*/
protected function apply_tag( $email, $tag ) {
try {
/** @var Thrive_Dash_Api_MailRelay|Thrive_Dash_Api_MailRelayV1 $api */
$api = $this->get_api();
// For MailRelay, we might handle tags as custom fields or groups
// This depends on MailRelay's specific API capabilities
// For now, we'll store it as a custom field called 'tags'
if ( $api instanceof Thrive_Dash_Api_MailRelayV1 ) {
// Try to create or get a tags custom field
$tags_field = $api->get_custom_field( 'mailrelay_tags' );
if ( empty( $tags_field ) ) {
$tags_field = $api->create_custom_field( array(
'label' => 'Tags',
'tag_name' => 'mailrelay_tags',
'field_type' => 'text',
) );
}
}
return true;
} catch ( Exception $e ) {
return false;
}
}
/**
* Get default custom fields when API is not available
*
* @return array
*/
protected function get_default_custom_fields() {
$default_fields = array(
array( 'name' => 'company', 'label' => 'Company', 'type' => 'text' ),
array( 'name' => 'website', 'label' => 'Website', 'type' => 'text' ),
array( 'name' => 'custom_field_1', 'label' => 'Custom Field 1', 'type' => 'text' ),
array( 'name' => 'custom_field_2', 'label' => 'Custom Field 2', 'type' => 'text' ),
);
$custom_data = array();
foreach ( $default_fields as $field ) {
$custom_data[] = $this->normalize_custom_field( $field );
}
return $custom_data;
}
/**
* Return the connection email merge tag
*
* @return String
*/
public static function get_email_merge_tag() {
return '[email]';
}
/**
* disconnect (remove) this API connection
*/
public function disconnect() {
$this->set_credentials( array() );
Thrive_Dash_List_Manager::save( $this );
/**
* disconnect the email service too
*/
$related_api = Thrive_Dash_List_Manager::connection_instance( 'mailrelayemail' );
$related_api->set_credentials( array() );
Thrive_Dash_List_Manager::save( $related_api );
return $this;
}
}

View File

@@ -0,0 +1,363 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class Thrive_Dash_List_Connection_MailRelayEmail extends Thrive_Dash_List_Connection_Abstract {
/**
* Return if the connection is in relation with another connection so we won't show it in the API list
*
* @return bool
*/
public function is_related() {
return true;
}
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'email';
}
/**
* @return string
*/
public function get_title() {
return 'MailRelay';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'mailrelayemail' );
}
/**
* just save the key in the database
*
* @return mixed|void
*/
public function read_credentials() {
$connection = $this->post( 'connection' );
$key = ! empty( $connection['key'] ) ? $connection['key'] : '';
if ( empty( $key ) ) {
return $this->error( __( 'You must provide a valid MailRelay key', 'thrive-dash' ) );
}
$connection['domain'] = isset( $connection['url'] ) ? $connection['url'] : $connection['domain'];
$url = ! empty( $connection['domain'] ) ? $connection['domain'] : '';
if ( filter_var( $url, FILTER_VALIDATE_URL ) === false || empty( $url ) ) {
return $this->error( __( 'You must provide a valid MailRelay URL', 'thrive-dash' ) );
}
$this->set_credentials( $connection );
$result = $this->test_connection();
if ( $result !== true ) {
return $this->error( sprintf( __( 'Could not connect to MailRelay using the provided key (<strong>%s</strong>)', 'thrive-dash' ), $result ) );
}
/**
* finally, save the connection details
*/
$this->save();
/**
* Try to connect to the autoresponder too
*/
/** @var Thrive_Dash_List_Connection_MailRelay $related_api */
$related_api = Thrive_Dash_List_Manager::connection_instance( 'mailrelay' );
$r_result = true;
if ( ! $related_api->is_connected() ) {
$_POST['connection'] = $connection;
$_POST['connection']['new_connection'] = isset( $connection['new_connection'] ) ? absint( $connection['new_connection'] ) : 1;
$r_result = $related_api->read_credentials();
}
if ( $r_result !== true ) {
$this->disconnect();
return $this->error( $r_result );
}
return $this->success( __( 'MailRelay connected successfully', 'thrive-dash' ) );
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
/** @var Thrive_Dash_Api_MailRelay $mr */
$mr = $this->get_api();
$email = get_option( 'admin_email' );
$args = array(
'subject' => 'API connection test',
'html' => 'This is a test email from Thrive Leads MailRelay API.',
'emails' => array(
array(
'name' => '',
'email' => $email,
),
),
);
try {
$mr->sendEmail( $args );
} catch ( Thrive_Dash_Api_MailRelay_Exception $e ) {
return $e->getMessage();
}
$connection = get_option( 'tve_api_delivery_service', false );
if ( $connection == false ) {
update_option( 'tve_api_delivery_service', 'mailrelayemail' );
}
return true;
}
/**
* Send custom email
*
* @param $data
*
* @return bool|string true for success or error message for failure
*/
public function sendCustomEmail( $data ) {
$mr = $this->get_api();
try {
$message = array(
'html' => empty ( $data['html_content'] ) ? '' : $data['html_content'],
'subject' => $data['subject'],
'emails' => array(
array(
'email' => $data['email'],
'name' => '',
),
),
);
$mr->sendEmail( $message );
} catch ( Exception $e ) {
return $e->getMessage();
}
return true;
}
/**
* Send the same email to multiple addresses
*
* @param $data
*
* @return bool|string
*/
public function sendMultipleEmails( $data ) {
$mr = $this->get_api();
/**
* prepare $to
*/
$to = array();
$extra_emails = array();
if ( isset( $data['cc'] ) ) {
$extra_emails = $data['cc'];
}
if ( isset( $data['bcc'] ) ) {
$extra_emails = array_merge( $extra_emails, $data['bcc'] );
}
$emails = is_array( $extra_emails ) ? array_merge( $data['emails'], $extra_emails ) : $data['emails'];
foreach ( $emails as $email ) {
$temp = array(
'email' => $email,
'name' => '',
);
$to[] = $temp;
}
try {
$message = array(
'html' => empty ( $data['html_content'] ) ? '' : $data['html_content'],
'subject' => $data['subject'],
'emails' => $to,
);
$mr->sendEmail( $message );
} catch ( Exception $e ) {
return $e->getMessage();
}
if ( ! empty( $data['send_confirmation'] ) ) {
try {
$message = array(
'html' => empty ( $data['confirmation_html'] ) ? '' : $data['confirmation_html'],
'subject' => $data['confirmation_subject'],
'emails' => array(
array(
'email' => $data['sender_email'],
'name' => '',
),
),
);
$mr->sendEmail( $message );
} catch ( Exception $e ) {
return $e->getMessage();
}
}
return true;
}
/**
* Send the email to the user
*
* @param $post_data
*
* @return bool|string
* @throws Exception
*
*/
public function sendEmail( $post_data ) {
$mr = $this->get_api();
$asset = get_post( $post_data['_asset_group'] );
if ( empty( $asset ) || ! ( $asset instanceof WP_Post ) || $asset->post_status !== 'publish' ) {
throw new Exception( sprintf( __( 'Invalid Asset Group: %s. Check if it exists or was trashed.', 'thrive-dash' ), $post_data['_asset_group'] ) );
}
$files = get_post_meta( $post_data['_asset_group'], 'tve_asset_group_files', true );
$subject = get_post_meta( $post_data['_asset_group'], 'tve_asset_group_subject', true );
if ( $subject == "" ) {
$subject = get_option( 'tve_leads_asset_mail_subject' );
}
$credentials = Thrive_Dash_List_Manager::credentials( 'mailrelayemail' );
if ( isset( $credentials ) ) {
$from_email = get_option( 'admin_email' );
} else {
return false;
}
$html_content = $asset->post_content;
if ( $html_content == "" ) {
$html_content = get_option( 'tve_leads_asset_mail_body' );
}
$attached_files = array();
foreach ( $files as $file ) {
$attached_files[] = '<a href="' . $file['link'] . '">' . $file['link_anchor'] . '</a><br/>';
}
$the_files = implode( '<br/>', $attached_files );
$html_content = str_replace( '[asset_download]', $the_files, $html_content );
$html_content = str_replace( '[asset_name]', $asset->post_title, $html_content );
$subject = str_replace( '[asset_name]', $asset->post_title, $subject );
if ( isset( $post_data['name'] ) && ! empty( $post_data['name'] ) ) {
$html_content = str_replace( '[lead_name]', $post_data['name'], $html_content );
$subject = str_replace( '[lead_name]', $post_data['name'], $subject );
$visitor_name = $post_data['name'];
} else {
$html_content = str_replace( '[lead_name]', '', $html_content );
$subject = str_replace( '[lead_name]', '', $subject );
$visitor_name = '';
}
$html_content = str_replace( '"', "'", $html_content );
$message = array(
'subject' => $subject,
'html' => $html_content,
'emails' => array(
array(
'name' => $visitor_name,
'email' => $post_data['email'],
),
),
);
$result = $mr->sendEmail( $message );
return $result;
}
/**
* instantiate the API code required for this connection
*
* @return mixed
*/
protected function get_api_instance() {
if ( false !== strpos( $this->param( 'domain' ), 'ipzmarketing' ) ) {
$instance = new Thrive_Dash_Api_MailRelayV1( $this->param( 'domain' ), $this->param( 'key' ) );
} else {
$instance = new Thrive_Dash_Api_MailRelay( array(
'host' => $this->param( 'domain' ),
'apiKey' => $this->param( 'key' ),
) );
}
return $instance;
}
/**
* get all Subscriber Lists from this API service
*
* @return array
*/
protected function _get_lists() {
}
/**
* add a contact to a list
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return bool|string true for success or string error message for failure
*/
public function add_subscriber( $list_identifier, $arguments ) {
}
}

View File

@@ -0,0 +1,443 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_MailerLite extends Thrive_Dash_List_Connection_Abstract {
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'autoresponder';
}
/**
* @return string
*/
public function get_title() {
return 'MailerLite';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'mailerlite' );
}
/**
* just save the key in the database
*
* @return mixed|void
*/
public function read_credentials() {
$connection = $this->post( 'connection' );
$key = ! empty( $connection['key'] ) ? ( $connection['key'] ) : '';
if ( empty( $key ) ) {
return $this->error( __( 'You must provide a valid MailerLite key', 'thrive-dash' ) );
}
$this->set_credentials( $connection );
$result = $this->test_connection();
if ( $result !== true ) {
return $this->error( sprintf( __( 'Could not connect to MailerLite using the provided key (<strong>%s</strong>)', 'thrive-dash' ), $result ) );
}
/**
* finally, save the connection details
*/
$this->save();
return $this->success( __( 'MailerLite connected successfully', 'thrive-dash' ) );
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
$mailer = $this->get_api();
/**
* just try getting a list as a connection test
*/
try {
$groupsApi = $mailer->groups();
$groupsApi->get();
} catch ( Thrive_Dash_Api_MailerLite_MailerLiteSdkException $e ) {
return $e->getMessage();
}
return true;
}
/**
* instantiate the API code required for this connection
*
* @return mixed
* @throws Thrive_Dash_Api_MailerLite_MailerLiteSdkException
*/
protected function get_api_instance() {
$key = $this->param( 'key' );
$version = $this->param( 'version' );
if ( ! empty( $version ) && (int) $version === 2 ) {
return new Thrive_Dash_Api_MailerLiteV2( $key );
}
return new Thrive_Dash_Api_MailerLite( $key );
}
/**
* get all Subscriber Lists from this API service
*
* @return array
*/
protected function _get_lists() {
$api = $this->get_api();
try {
$groups_api = $api->groups();
$groups_api->limit( 10000 );
$lists_obj = $groups_api->get();
$lists = array();
foreach ( $lists_obj as $item ) {
$lists [] = array(
'id' => $item->id,
'name' => $item->name,
);
}
return $lists;
} catch ( Exception $e ) {
$this->_error = $e->getMessage() . ' ' . __( 'Please re-check your API connection details.', 'thrive-dash' );
return false;
}
}
/**
* add a contact to a list
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return bool|string true for success or string error message for failure
*/
public function add_subscriber( $list_identifier, $arguments ) {
$api = $this->get_api();
$version = (int) $this->param( 'version' );
if ( isset( $arguments['name'] ) ) {
list( $first_name, $last_name ) = $this->get_name_parts( $arguments['name'] );
}
if ( isset( $arguments['phone'] ) ) {
$phone = $arguments['phone'];
}
$args['fields'] = array();
$args['email'] = $arguments['email'];
if ( ! empty( $first_name ) ) {
$args['fields']['name'] = $first_name;
$args['name'] = $first_name;
}
if ( ! empty( $last_name ) ) {
$args['fields']['last_name'] = $last_name;
}
if ( ! empty( $phone ) ) {
$args['fields']['phone'] = $phone;
}
$args['resubscribe'] = 1;
try {
$groupsApi = $api->groups();
if ( empty( $arguments['automator_custom_fields'] ) ) {
$args['fields'] = array_merge( $args['fields'], $this->_generateCustomFields( $arguments ) );
} else {
$args['fields'] = array_merge( $args['fields'], $arguments['automator_custom_fields'] );
}
$groupsApi->add_subscriber( $list_identifier, $args );
return true;
} catch ( Thrive_Dash_Api_MailerLite_MailerLiteSdkException $e ) {
return $e->getMessage() ? $e->getMessage() : __( 'Unknown MailerLite Error', 'thrive-dash' );
} catch ( Exception $e ) {
return $e->getMessage() ? $e->getMessage() : __( 'Unknown Error', 'thrive-dash' );
}
}
/**
* Return the connection email merge tag
*
* @return String
*/
public static function get_email_merge_tag() {
return '{$email}';
}
/**
* @param $params
* @param bool $force
* @param bool $get_all
*
* @return array|mixed
*/
public function get_api_custom_fields( $params, $force = false, $get_all = false ) {
// Serve from cache if exists and requested
$cached_data = $this->get_cached_custom_fields();
if ( false === $force && ! empty( $cached_data ) ) {
return $cached_data;
}
$custom_data = array();
$allowed_types = $this->get_api()->fields()->get_allowed_types();
try {
$custom_fields = $this->get_api()->fields()->get();
if ( is_array( $custom_fields ) ) {
foreach ( $custom_fields as $field ) {
if ( ! empty( $field->type ) && in_array( $field->type, $allowed_types, true ) ) {
$custom_data[] = $this->get_api()->fields()->get_normalize_custom_field( $field );
}
}
}
} catch ( Exception $e ) {
}
$this->_save_custom_fields( $custom_data );
return $custom_data;
}
/**
* Generate custom fields array
*
* @param array $args
*
* @return array
*/
private function _generateCustomFields( $args ) {
$custom_fields = $this->get_api_custom_fields( array() );
$ids = $this->buildMappedCustomFields( $args );
$result = array();
foreach ( $ids as $key => $id ) {
$field = array_filter(
$custom_fields,
function ( $item ) use ( $id ) {
return (int) $item['id'] === (int) $id['value'];
}
);
$field = array_values( $field );
if ( ! isset( $field[0] ) ) {
continue;
}
$_name = $field[0]['key'] ?: $field[0]['name'];
$chunks = explode( ' ', $_name );
$chunks = array_map( 'strtolower', $chunks );
$field_key = implode( '_', $chunks );
$name = strpos( $id['type'], 'mapping_' ) !== false ? $id['type'] . '_' . $key : $key;
$cf_form_name = str_replace( '[]', '', $name );
$value = isset( $args[ $cf_form_name ] ) ? $this->process_field( $args[ $cf_form_name ] ) : '';
if ( $value ) {
$result[ $field_key ] = $value;
}
}
return $result;
}
/**
* Build custom fields mapping for automations
*
* @param $automation_data
*
* @return array
*/
public function build_automation_custom_fields( $automation_data ) {
$mapped_data = [];
$fields = $this->get_api_custom_fields( array() );
foreach ( $automation_data['api_fields'] as $pair ) {
$value = sanitize_text_field( $pair['value'] );
if ( $value ) {
foreach ( $fields as $field ) {
if ( (int) $field['id'] === (int) $pair['key'] ) {
$_name = $field['key'] ?: $field['name'];
$_name = explode( ' ', $_name );
$_name = array_map( 'strtolower', $_name );
$_name = implode( '_', $_name );
$mapped_data[ $_name ] = $value;
}
}
}
}
return $mapped_data;
}
/**
* Build mapped custom fields array based on form params
*
* @param $args
*
* @return array
*/
public function buildMappedCustomFields( $args ) {
$mapped_data = array();
// Should be always base_64 encoded of a serialized array
if ( empty( $args['tve_mapping'] ) || ! tve_dash_is_bas64_encoded( $args['tve_mapping'] ) || ! is_serialized( base64_decode( $args['tve_mapping'] ) ) ) {
return $mapped_data;
}
$form_data = thrive_safe_unserialize( base64_decode( $args['tve_mapping'] ) );
$mapped_fields = $this->get_mapped_field_ids();
foreach ( $mapped_fields as $mapped_field_name ) {
// Extract an array with all custom fields (siblings) names from form data
// {ex: [mapping_url_0, .. mapping_url_n] / [mapping_text_0, .. mapping_text_n]}
$cf_form_fields = preg_grep( "#^{$mapped_field_name}#i", array_keys( $form_data ) );
if ( ! empty( $cf_form_fields ) && is_array( $cf_form_fields ) ) {
foreach ( $cf_form_fields as $cf_form_name ) {
if ( empty( $form_data[ $cf_form_name ][ $this->_key ] ) ) {
continue;
}
$field_id = str_replace( $mapped_field_name . '_', '', $cf_form_name );
$mapped_data[ $field_id ] = array(
'type' => $mapped_field_name,
'value' => $form_data[ $cf_form_name ][ $this->_key ],
);
}
}
}
return $mapped_data;
}
/**
* @param $email
* @param array $custom_fields
* @param array $extra
*
* @return false|int
*/
public function add_custom_fields( $email, $custom_fields = array(), $extra = array() ) {
try {
$api = $this->get_api();
$groupsApi = $api->groups();
$subscribersApi = $api->subscribers();
$list_id = ! empty( $extra['list_identifier'] ) ? $extra['list_identifier'] : null;
$args = array(
'email' => $email,
'name' => ! empty( $extra['name'] ) ? $extra['name'] : '',
'fields' => array(),
);
$this->add_subscriber( $list_id, $args );
$args['fields'] = $this->prepare_custom_fields_for_api( $custom_fields );
$groupsApi->add_subscriber( $list_id, $args );
$subscriber = $subscribersApi->search( $email );
return ! empty( $subscriber[0] ) ? $subscriber[0]->id : 0;
} catch ( Exception $e ) {
return false;
}
}
/**
* Get available custom fields for this api connection
*
* @param null $list_id
*
* @return array
*/
public function get_available_custom_fields( $list_id = null ) {
return $this->get_api_custom_fields( null, true );
}
/**
* Prepare custom fields for api call
*
* @param array $custom_fields
* @param null $list_identifier
*
* @return array
*/
public function prepare_custom_fields_for_api( $custom_fields = array(), $list_identifier = null ) {
$prepared_fields = array();
$api_fields = $this->get_api_custom_fields( array( 'list_id' => $list_identifier ), true );
foreach ( $api_fields as $field ) {
foreach ( $custom_fields as $key => $custom_field ) {
if ( (int) $field['id'] === (int) $key && $custom_field ) {
$_name = $field['key'] ?: $field['name'];
$chunks = explode( ' ', $_name );
$chunks = array_map( 'strtolower', $chunks );
$cf_key = implode( '_', $chunks );
$prepared_fields[ $cf_key ] = $custom_field;
}
}
if ( empty( $custom_fields ) ) {
break;
}
}
return $prepared_fields;
}
public function get_automator_add_autoresponder_mapping_fields() {
return array( 'autoresponder' => array( 'mailing_list', 'api_fields' ) );
}
public function has_custom_fields() {
return true;
}
}

View File

@@ -0,0 +1,328 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_Mailgun extends Thrive_Dash_List_Connection_Abstract {
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'email';
}
/**
* @return string the API connection title
*/
public function get_title() {
return 'Mailgun';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'mailgun' );
}
/**
* should handle: read data from post / get, test connection and save the details
*
* on error, it should register an error message (and redirect?)
*/
public function read_credentials() {
$ajax_call = defined( 'DOING_AJAX' ) && DOING_AJAX;
$key = ! empty( $_POST['connection']['key'] ) ? sanitize_text_field( $_POST['connection']['key'] ) : '';
$domain = ! empty( $_POST['connection']['domain'] ) ? sanitize_text_field( $_POST['connection']['domain'] ) : '';
$zone = ! empty( $_POST['connection']['zone'] ) ? sanitize_text_field( $_POST['connection']['zone'] ) : '';
if ( empty( $key ) ) {
return $ajax_call ? __( 'You must provide a valid Mailgun key', 'thrive-dash' ) : $this->error( __( 'You must provide a valid Mailgun key', 'thrive-dash' ) );
}
if ( empty( $domain ) ) {
return $ajax_call ? __( 'The domain name field must not be empty', 'thrive-dash' ) : $this->error( __( 'The domain name field must not be empty', 'thrive-dash' ) );
}
$this->set_credentials( compact( 'key', 'domain', 'zone' ) );
$result = $this->test_connection();
if ( $result !== true ) {
return $ajax_call ? sprintf( __( 'Could not connect to Mailgun using the provided key (<strong>%s</strong>)', 'thrive-dash' ), $result ) : $this->error( sprintf( __( 'Could not connect to Mailgun using the provided key (<strong>%s</strong>)', 'thrive-dash' ), $result ) );
}
/**
* finally, save the connection details
*/
$this->save();
$this->success( __( 'Mailgun connected successfully', 'thrive-dash' ) );
if ( $ajax_call ) {
return true;
}
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
/** @var Thrive_Dash_Api_Mailgun $mailgun */
$mailgun = $this->get_api();
if ( isset( $_POST['connection']['domain'] ) ) {
$domain = sanitize_text_field( $_POST['connection']['domain'] );
} else {
$credentials = Thrive_Dash_List_Manager::credentials( 'mailgun' );
if ( isset( $credentials ) ) {
$domain = $credentials['domain'];
}
}
$from_email = get_option( 'admin_email' );
$to = $from_email;
$subject = 'API connection test';
$text_content = $html_content = 'This is a test email from Thrive Leads Mailgun API.';
try {
$mailgun->sendMessage( "$domain",
array(
'from' => $from_email,
'to' => $to,
'subject' => $subject,
'text' => $text_content,
'html' => $html_content,
'multipart' => true,
) );
} catch ( Exception $e ) {
return $e->getMessage();
}
$connection = get_option( 'tve_api_delivery_service', false );
if ( $connection == false ) {
update_option( 'tve_api_delivery_service', 'mailgun' );
}
return true;
/**
* just try getting a list as a connection test
*/
}
/**
* Send custom email
*
* @param $data
*
* @return bool|string true for success or error message for failure
*/
public function sendCustomEmail( $data ) {
$mailgun = $this->get_api();
$credentials = Thrive_Dash_List_Manager::credentials( 'mailgun' );
if ( isset( $credentials ) ) {
$domain = $credentials['domain'];
} else {
return false;
}
$from_email = get_option( 'admin_email' );
try {
$messsage = array(
'from' => $from_email,
'to' => $data['email'],
'subject' => $data['subject'],
'text' => empty ( $data['text_content'] ) ? '' : $data['text_content'],
'html' => empty ( $data['html_content'] ) ? '' : $data['html_content'],
'multipart' => true,
);
$mailgun->sendMessage( "$domain", $messsage );
} catch ( Exception $e ) {
return $e->getMessage();
}
return true;
}
/**
* Send the same email to multiple addresses
*
* @param $data
*
* @return bool|string
*/
public function sendMultipleEmails( $data ) {
$mailgun = $this->get_api();
$credentials = Thrive_Dash_List_Manager::credentials( 'mailgun' );
if ( isset( $credentials ) ) {
$domain = $credentials['domain'];
} else {
return false;
}
$from_email = get_option( 'admin_email' );
try {
$messsage = array(
'from' => $from_email,
'to' => $data['emails'],
'subject' => $data['subject'],
'text' => empty ( $data['text_content'] ) ? '' : $data['text_content'],
'html' => empty ( $data['html_content'] ) ? '' : $data['html_content'],
'h:Reply-To' => empty ( $data['reply_to'] ) ? '' : $data['reply_to'],
'multipart' => true,
);
$mailgun->sendMessage( "$domain", $messsage );
} catch ( Exception $e ) {
return $e->getMessage();
}
/* Send confirmation email */
if ( ! empty( $data['send_confirmation'] ) ) {
try {
$messsage = array(
'from' => $from_email,
'to' => array( $data['sender_email'] ),
'subject' => $data['confirmation_subject'],
'text' => '',
'html' => empty ( $data['confirmation_html'] ) ? '' : $data['confirmation_html'],
'h:Reply-To' => $from_email,
'multipart' => true,
);
$mailgun->sendMessage( "$domain", $messsage );
} catch ( Exception $e ) {
return $e->getMessage();
}
}
return true;
}
/**
* Send the email to the user
*
* @param $post_data
*
* @return bool|string
* @throws Exception
*
*/
public function sendEmail( $post_data ) {
$mailgun = $this->get_api();
$asset = get_post( $post_data['_asset_group'] );
if ( empty( $asset ) || ! ( $asset instanceof WP_Post ) || $asset->post_status !== 'publish' ) {
throw new Exception( sprintf( __( 'Invalid Asset Group: %s. Check if it exists or was trashed.', 'thrive-dash' ), $post_data['_asset_group'] ) );
}
$files = get_post_meta( $post_data['_asset_group'], 'tve_asset_group_files', true );
$subject = get_post_meta( $post_data['_asset_group'], 'tve_asset_group_subject', true );
if ( $subject == "" ) {
$subject = get_option( 'tve_leads_asset_mail_subject' );
}
$from_email = get_option( 'admin_email' );
$html_content = $asset->post_content;
if ( $html_content == "" ) {
$html_content = get_option( 'tve_leads_asset_mail_body' );
}
$attached_files = array();
foreach ( $files as $file ) {
$attached_files[] = '<a href="' . $file['link'] . '">' . $file['link_anchor'] . '</a><br/>';
}
$the_files = implode( '<br/>', $attached_files );
$html_content = str_replace( '[asset_download]', $the_files, $html_content );
$html_content = str_replace( '[asset_name]', $asset->post_title, $html_content );
$subject = str_replace( '[asset_name]', $asset->post_title, $subject );
if ( isset( $post_data['name'] ) && ! empty( $post_data['name'] ) ) {
$from_name = '<' . $post_data['name'] . '>';
$html_content = str_replace( '[lead_name]', $post_data['name'], $html_content );
$subject = str_replace( '[lead_name]', $post_data['name'], $subject );
$visitor_name = $post_data['name'];
} else {
$from_name = "";
$html_content = str_replace( '[lead_name]', '', $html_content );
$subject = str_replace( '[lead_name]', '', $subject );
$visitor_name = '';
}
$text_content = strip_tags( $html_content );
$credentials = Thrive_Dash_List_Manager::credentials( 'mailgun' );
if ( isset( $credentials ) ) {
$domain = $credentials['domain'];
}
$result = $mailgun->sendMessage( "$domain",
array(
'from' => $from_email,
'to' => $visitor_name . "<" . $post_data['email'] . ">",
'subject' => $subject,
'text' => $text_content,
'html' => $html_content,
'multipart' => true,
) );
return $result;
}
/**
* instantiate the API code required for this connection
*
* @return mixed
*/
protected function get_api_instance() {
$zone = $this->param( 'zone' );
$endpoint = $zone && $zone === 'europe' ? 'api.eu.mailgun.net' : 'api.mailgun.net';
return new Thrive_Dash_Api_Mailgun( $this->param( 'key' ), $endpoint );
}
/**
* get all Subscriber Lists from this API service
*
* @return array|bool for error
*/
protected function _get_lists() {
}
/**
* add a contact to a list
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return mixed
*/
public function add_subscriber( $list_identifier, $arguments ) {
}
}

View File

@@ -0,0 +1,185 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_Mailster extends Thrive_Dash_List_Connection_Abstract {
/**
* @return string
*/
public function get_title() {
return 'Mailster';
}
public function output_setup_form() {
$this->output_controls_html( 'mailster' );
}
/**
* @return bool|mixed|string|Thrive_Dash_List_Connection_Abstract
*/
public function read_credentials() {
if ( false === $this->pluginInstalled() ) {
return __( 'Mailster plugin not installed or activated', 'thrive-dash' );
}
$this->set_credentials( array( 'connected' => true ) );
$result = $this->test_connection();
if ( true !== $result ) {
return $this->error( '<strong>' . $result . '</strong>)' );
}
$this->save();
return true;
}
/**
* @return bool|string
*/
public function test_connection() {
if ( false === $this->pluginInstalled() ) {
return __( 'Mailster plugin not installed or activated', 'thrive-dash' );
}
return true;
}
/**
* Add subscriber
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return bool|string
*/
public function add_subscriber( $list_identifier, $arguments ) {
if ( false === $this->pluginInstalled() ) {
return __( 'Mailster plugin not installed or activated', 'thrive-dash' );
}
$mailster_instance = mailster( 'subscribers' );
$args = array(
'email' => $arguments['email'],
'status' => isset( $arguments['mailster_optin'] ) && 'd' === $arguments['mailster_optin'] ? 0 : 1,
);
if ( ! empty( $arguments['name'] ) ) {
list( $first_name, $last_name ) = $this->get_name_parts( $arguments['name'] );
$args['firstname'] = $first_name;
$args['lastname'] = $last_name;
}
$subscriber = $mailster_instance->get_by_mail( $arguments['email'] );
$subscriber_id = is_object( $subscriber )
? $mailster_instance->update( $args, true, true )
: $mailster_instance->add( $args );
if ( null !== $subscriber_id ) {
$mailster_instance->assign_lists( $subscriber_id, $list_identifier );
$mailster_instance->add_custom_value( $subscriber_id, $this->_get_custom_fields_from_args( $arguments ) );
return true;
}
return __( 'Mailster failed to add the subscriber', 'thrive-dash' );
}
/**
* Get the custom fields from available args
*
* @param $args
*
* @return array
*/
private function _get_custom_fields_from_args( $args ) {
$result = array();
foreach ( $this->get_custom_fields() as $field ) {
if ( isset( $args[ $field['id'] ] ) ) {
$result[ $field['id'] ] = $args[ $field['id'] ];
}
}
return $result;
}
protected function get_api_instance() {
}
/**
* @return bool|string|array
*/
protected function _get_lists() {
if ( false === $this->pluginInstalled() ) {
return __( 'Mailster plugin not installed or activated', 'thrive-dash' );
}
$lists = array();
foreach ( mailster( 'lists' )->get() as $list ) {
$lists[] = array(
'id' => $list->ID,
'name' => $list->name,
);
}
return $lists;
}
/**
* Chack if Mailster plugin is installed and activated
*
* @return bool
*/
public function pluginInstalled() {
return function_exists( 'mailster' );
}
/**
* Get custom fields
*
* @param array $params
*
* @return array
*/
public function get_custom_fields( $params = array() ) {
/**
* Add our default custom fields
*/
foreach ( array( 'name', 'phone' ) as $field ) {
mailster()->add_custom_field( $field );
}
$fields = mailster()->get_custom_fields();
$fields = wp_list_filter( $fields, array( 'type' => 'textfield' ) );
$response = array();
foreach ( $fields as $key => $field ) {
if ( ! empty( $field['name'] ) ) {
$response[] = array(
'id' => $key,
'placeholder' => $field['name'],
);
}
}
return $response;
}
}

View File

@@ -0,0 +1,482 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_Mandrill extends Thrive_Dash_List_Connection_Abstract {
/**
* Return if the connection is in relation with another connection so we won't show it in the API list
*
* @return bool
*/
public function is_related() {
return true;
}
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'email';
}
/**
* @return string the API connection title
*/
public function get_title() {
return 'Mandrill';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$related_api = Thrive_Dash_List_Manager::connection_instance( 'mailchimp' );
if ( $related_api->is_connected() ) {
$credentials = $related_api->get_credentials();
$this->set_param( 'mailchimp_key', $credentials['key'] );
}
$this->output_controls_html( 'mandrill' );
}
/**
* should handle: read data from post / get, test connection and save the details
*
* on error, it should register an error message (and redirect?)
*/
public function read_credentials() {
$mailchimp_key = ! empty( $_POST['connection']['mailchimp_key'] ) ? sanitize_text_field( $_POST['connection']['mailchimp_key'] ) : '';
$email = ! empty( $_POST['connection']['email'] ) ? sanitize_text_field( $_POST['connection']['email'] ) : '';
if ( isset( $_POST['connection']['mandrill-key'] ) && isset( $_POST['connection']['key'] ) ) {
$_POST['connection']['mailchimp_key'] = sanitize_text_field( $_POST['connection']['key'] );
$_POST['connection']['key'] = sanitize_text_field( $_POST['connection']['mandrill-key'] );
}
if ( empty( $_POST['connection']['key'] ) ) {
return $this->error( __( 'You must provide a valid Mandrill key', 'thrive-dash' ) );
}
if ( empty( $email ) ) {
return $this->error( __( 'Email field must not be empty', 'thrive-dash' ) );
}
$this->set_credentials( $this->post( 'connection' ) );
$result = $this->test_connection();
if ( $result !== true ) {
/**
* Doing this because Mandrill devs are retarded and because it's unprofessional for the end user to read 'gibberish'
*/
preg_match( '#"?(.+?)\{(.+)\}(")?$#', json_decode( $result ), $matches );
if ( ! empty( $matches ) ) {
$result = json_decode( '{' . $matches[2] . '}', true );
$message = false;
foreach ( $result as $level1 ) {
foreach ( $level1 as $level2 ) {
if ( ! $message ) {
$message = $level2;
}
}
}
} else {
$message = $result;
}
return $this->error( sprintf( __( 'Could not connect to Mandrill using the provided key (<strong>%s</strong>)', 'thrive-dash' ), $message ? $message : '' ) );
}
/**
* finally, save the connection details
*/
$this->save();
if ( ! empty( $mailchimp_key ) ) {
/**
* Try to connect to the email service too
*/
/** @var Thrive_Dash_List_Connection_Mandrill $related_api */
$related_api = Thrive_Dash_List_Manager::connection_instance( 'mailchimp' );
$r_result = true;
if ( ! $related_api->is_connected() ) {
$r_result = $related_api->read_credentials();
}
if ( $r_result !== true ) {
$this->disconnect();
return $this->error( $r_result );
}
}
return $this->success( __( 'Mandrill connected successfully', 'thrive-dash' ) );
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
$mandrill = $this->get_api();
if ( isset( $_POST['connection']['email'] ) ) {
$from_email = sanitize_text_field( $_POST['connection']['email'] );
$to = $from_email;
} else {
$credentials = Thrive_Dash_List_Manager::credentials( 'mandrill' );
if ( isset( $credentials ) ) {
$from_email = $credentials['email'];
$to = $credentials['email'];
} else {
return false;
}
}
$subject = 'API connection test';
$html_content = 'This is a test email from Thrive Leads Mandrill API.';
$text_content = 'This is a test email from Thrive Leads Mandrill API.';
$message = array(
'html' => $html_content,
'text' => $text_content,
'subject' => $subject,
'from_email' => $from_email,
'from_name' => '',
'to' => array(
array(
'email' => $to,
'name' => '',
'type' => 'to',
),
),
'headers' => array( 'Reply-To' => $from_email ),
'merge' => true,
'merge_language' => 'mailchimp',
);
$async = false;
$ip_pool = 'Main Pool';
try {
$result = $mandrill->messages->send( $message, $async, $ip_pool );
if ( isset( $result['body'] ) ) {
$body = json_decode( $result['body'] );
$body = $body[0];
if ( $body->status == 'rejected' ) {
if ( $body->reject_reason == 'unsigned' ) {
return $this->error( __( "The email filled in was not verified by Mandrill", 'thrive-dash' ) );
}
return $this->error( __( "Mandrill couldn't connect", 'thrive-dash' ) );
}
}
} catch ( Thrive_Dash_Api_Mandrill_Exceptions $e ) {
return $e->getMessage();
}
$connection = get_option( 'tve_api_delivery_service', false );
if ( $connection == false ) {
update_option( 'tve_api_delivery_service', 'mandrill' );
}
return true;
/**
* just try getting a list as a connection test
*/
}
/**
* Send custom email
*
* @param $data
*
* @return bool|string true for success or error message for failure
*/
public function sendCustomEmail( $data ) {
$mandrill = $this->get_api();
$credentials = Thrive_Dash_List_Manager::credentials( 'mandrill' );
if ( isset( $credentials ) ) {
$from_email = $credentials['email'];
} else {
return false;
}
try {
$message = array(
'html' => empty ( $data['html_content'] ) ? '' : $data['html_content'],
'text' => empty ( $data['text_content'] ) ? '' : $data['text_content'],
'subject' => $data['subject'],
'from_email' => $from_email,
'from_name' => '',
'to' => array(
array(
'email' => $data['email'],
'name' => '',
'type' => 'to',
),
),
'headers' => array( 'Reply-To' => $from_email ),
'merge' => true,
'merge_language' => 'mailchimp',
);
$async = false;
$ip_pool = 'Main Pool';
$mandrill->messages->send( $message, $async, $ip_pool );
} catch ( Exception $e ) {
return $e->getMessage();
}
return true;
}
/**
* Send the same email to multiple addresses
*
* @param $data
*
* @return bool|string
*/
public function sendMultipleEmails( $data ) {
$mandrill = $this->get_api();
$credentials = Thrive_Dash_List_Manager::credentials( 'mandrill' );
if ( isset( $credentials ) ) {
$from_email = $credentials['email'];
} else {
return false;
}
/**
* prepare $to
*/
$to = array();
$cc = isset( $data['cc'] ) ? $data['cc'] : array();
$bcc = isset( $data['bcc'] ) ? $data['bcc'] : array();
foreach ( $data['emails'] as $email ) {
$temp = array(
'email' => $email,
'name' => '',
'type' => 'to',
);
$to[] = $temp;
}
foreach ( $cc as $email ) {
$temp = array(
'email' => $email,
'name' => '',
'type' => 'cc',
);
$to[] = $temp;
}
foreach ( $bcc as $email ) {
$temp = array(
'email' => $email,
'name' => '',
'type' => 'bcc',
);
$to[] = $temp;
}
try {
$message = array(
'html' => empty ( $data['html_content'] ) ? '' : $data['html_content'],
'text' => empty ( $data['text_content'] ) ? '' : $data['text_content'],
'subject' => $data['subject'],
'from_email' => $from_email,
'from_name' => ! empty( $data['from_name'] ) ? $data['from_name'] : '',
'to' => $to,
'headers' => array( 'Reply-To' => empty ( $data['reply_to'] ) ? '' : $data['reply_to'] ),
'merge' => true,
'merge_language' => 'mailchimp',
);
$async = false;
$ip_pool = 'Main Pool';
$mandrill->messages->send( $message, $async, $ip_pool );
} catch ( Exception $e ) {
return $e->getMessage();
}
if ( ! empty( $data['send_confirmation'] ) ) {
try {
$message = array(
'html' => empty ( $data['confirmation_html'] ) ? '' : $data['confirmation_html'],
'text' => '',
'subject' => $data['confirmation_subject'],
'from_email' => $from_email,
'from_name' => ! empty( $data['from_name'] ) ? $data['from_name'] : '',
'to' => array(
array(
'email' => $data['sender_email'],
'name' => '',
'type' => 'to',
),
),
'headers' => array( 'Reply-To' => $from_email ),
'merge' => true,
'merge_language' => 'mailchimp',
);
$async = false;
$ip_pool = 'Main Pool';
$mandrill->messages->send( $message, $async, $ip_pool );
} catch ( Exception $e ) {
return $e->getMessage();
}
}
return true;
}
/**
* Send the email to the user
*
* @param $post_data
*
* @return bool|string
* @throws Exception
*
*/
public function sendEmail( $post_data ) {
$mandrill = $this->get_api();
$asset = get_post( $post_data['_asset_group'] );
if ( empty( $asset ) || ! ( $asset instanceof WP_Post ) || $asset->post_status !== 'publish' ) {
throw new Exception( sprintf( __( 'Invalid Asset Group: %s. Check if it exists or was trashed.', 'thrive-dash' ), $post_data['_asset_group'] ) );
}
$files = get_post_meta( $post_data['_asset_group'], 'tve_asset_group_files', true );
$subject = get_post_meta( $post_data['_asset_group'], 'tve_asset_group_subject', true );
if ( $subject == "" ) {
$subject = get_option( 'tve_leads_asset_mail_subject' );
}
$credentials = Thrive_Dash_List_Manager::credentials( 'mandrill' );
if ( isset( $credentials ) ) {
$from_email = $credentials['email'];
} else {
return false;
}
$html_content = $asset->post_content;
if ( $html_content == "" ) {
$html_content = get_option( 'tve_leads_asset_mail_body' );
}
$attached_files = array();
foreach ( $files as $file ) {
$attached_files[] = '<a href="' . $file['link'] . '">' . $file['link_anchor'] . '</a><br/>';
}
$the_files = implode( '<br/>', $attached_files );
$html_content = str_replace( '[asset_download]', $the_files, $html_content );
$html_content = str_replace( '[asset_name]', $asset->post_title, $html_content );
$subject = str_replace( '[asset_name]', $asset->post_title, $subject );
if ( isset( $post_data['name'] ) && ! empty( $post_data['name'] ) ) {
$from_name = $post_data['name'];
$html_content = str_replace( '[lead_name]', $post_data['name'], $html_content );
$subject = str_replace( '[lead_name]', $post_data['name'], $subject );
$visitor_name = $post_data['name'];
} else {
$from_name = "";
$html_content = str_replace( '[lead_name]', '', $html_content );
$subject = str_replace( '[lead_name]', '', $subject );
$visitor_name = '';
}
$text_content = strip_tags( $html_content );
$message = array(
'html' => $html_content,
'text' => $text_content,
'subject' => $subject,
'from_email' => $from_email,
'from_name' => '',
'to' => array(
array(
'email' => $post_data['email'],
'name' => $visitor_name,
'type' => 'to',
),
),
'headers' => array( 'Reply-To' => $from_email ),
'merge' => true,
'merge_language' => 'mailchimp',
);
$async = false;
$ip_pool = 'Main Pool';
$result = $mandrill->messages->send( $message, $async, $ip_pool );
return $result;
}
/**
* instantiate the API code required for this connection
*
* @return mixed
*/
protected function get_api_instance() {
return new Thrive_Dash_Api_Mandrill( $this->param( 'key' ) );
}
/**
* get all Subscriber Lists from this API service
*
* @return array|bool for error
*/
protected function _get_lists() {
}
/**
* add a contact to a list
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return mixed
*/
public function add_subscriber( $list_identifier, $arguments ) {
}
}

View File

@@ -0,0 +1,196 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_Ontraport extends Thrive_Dash_List_Connection_Abstract {
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'autoresponder';
}
/**
* @return string the API connection title
*/
public function get_title() {
return 'Ontraport';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'ontraport' );
}
/**
* should handle: read data from post / get, test connection and save the details
*
* on error, it should register an error message (and redirect?)
*
* @return mixed
*/
public function read_credentials() {
$key = ! empty( $_POST['connection']['key'] ) ? sanitize_text_field( $_POST['connection']['key'] ) : '';
$app_id = ! empty( $_POST['connection']['app_id'] ) ? sanitize_text_field( $_POST['connection']['app_id'] ) : '';
if ( empty( $key ) || empty( $app_id ) ) {
return $this->error( __( 'You must provide a valid Ontraport AppID/APIKey', 'thrive-dash' ) );
}
$this->set_credentials( $this->post( 'connection' ) );
$result = $this->test_connection();
if ( $result !== true ) {
return $this->error( sprintf( __( 'Could not connect to Ontraport: %s', 'thrive-dash' ), $this->_error ) );
}
/**
* finally, save the connection details
*/
$this->save();
$this->success( __( 'Ontraport connected successfully', 'thrive-dash' ) );
return true;
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
return is_array( $this->_get_lists() );
}
/**
* instantiate the API code required for this connection
*
* @return Thrive_Dash_Api_Ontraport
*/
protected function get_api_instance() {
return new Thrive_Dash_Api_Ontraport( $this->param( 'app_id' ), $this->param( 'key' ) );
}
/**
* get all Subscriber Lists from this API service
*
* Ontraport has both sequences and forms
*
* @return array|string for error
*/
protected function _get_lists() {
/**
* just try getting the lists as a connection test
*/
try {
$lists = array();
/** @var $op Thrive_Dash_Api_Ontraport */
$op = $this->get_api();
$data = $op->get_campaigns();
if ( ! empty( $data ) ) {
foreach ( $data as $id => $list ) {
$lists[] = array(
'id' => $id,
'name' => $list['name'],
);
}
}
return $lists;
} catch ( Thrive_Dash_Api_Ontraport_Exception $e ) {
$this->_error = $e->getMessage();
return false;
}
}
/**
* Get campaigns
*
* @param array $params
*
* @return array
*/
public function get_extra_settings( $params = array() ) {
$lists = array();
try {
$data = $this->get_api()->get_sequences();
if ( ! empty( $data ) ) {
foreach ( $data as $id => $list ) {
$lists['sequences'][] = array(
'id' => $id,
'name' => $list['name'],
);
}
}
} catch ( Exception $e ) {
return $lists;
}
return $lists;
}
/**
* add a contact to a list
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return mixed
*/
public function add_subscriber( $list_identifier, $arguments ) {
try {
list( $firstname, $lastname ) = $this->get_name_parts( $arguments['name'] );
$data = array(
'firstname' => $firstname,
'lastname' => $lastname,
'email' => $arguments['email'],
'type' => ! empty( $arguments['ontraport_ontraport_type'] ) ? $arguments['ontraport_ontraport_type'] : '',
);
if ( ! empty( $arguments['phone'] ) ) {
$data['phone'] = $arguments['phone'];
}
$this->get_api()->add_contact( $list_identifier, $data );
} catch ( Exception $e ) {
return $e->getMessage();
}
return true;
}
public static function get_email_merge_tag() {
return '[Email]';
}
}

View File

@@ -0,0 +1,289 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_Postmark extends Thrive_Dash_List_Connection_Abstract {
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'email';
}
/**
* @return string the API connection title
*/
public function get_title() {
return 'Postmark';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'postmark' );
}
/**
* should handle: read data from post / get, test connection and save the details
*
* on error, it should register an error message (and redirect?)
*/
public function read_credentials() {
$key = ! empty( $_POST['connection']['key'] ) ? sanitize_text_field( $_POST['connection']['key'] ) : '';
$email = ! empty( $_POST['connection']['email'] ) ? sanitize_text_field( $_POST['connection']['email'] ) : '';
if ( empty( $key ) ) {
return $this->error( __( 'You must provide a valid Postmark key', 'thrive-dash' ) );
}
if ( empty( $email ) ) {
return $this->error( __( 'Email field must not be empty', 'thrive-dash' ) );
}
$this->set_credentials( $this->post( 'connection' ) );
$result = $this->test_connection();
if ( $result !== true ) {
return $this->error( sprintf( __( 'Could not connect to Postmark using the provided key (<strong>%s</strong>)', 'thrive-dash' ), $result ) );
}
/**
* finally, save the connection details
*/
$this->save();
return $this->success( __( 'Postmark connected successfully', 'thrive-dash' ) );
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
$postmark = $this->get_api();
if ( isset( $_POST['connection']['email'] ) ) {
$from_email = sanitize_email( $_POST['connection']['email'] );
$to = $from_email;
} else {
$credentials = Thrive_Dash_List_Manager::credentials( 'postmark' );
if ( isset( $credentials ) ) {
$from_email = $credentials['email'];
$to = $credentials['email'];
}
}
$subject = 'API connection test';
$html_content = 'This is a test email from Thrive Leads Postmark API.';
$text_content = 'This is a test email from Thrive Leads Postmark API.';
try {
$postmark->sendEmail( $from_email, $to, $subject, $html_content, $text_content );
} catch ( Thrive_Dash_Api_Postmark_Exception $e ) {
return $e->getMessage();
}
$connection = get_option( 'tve_api_delivery_service', false );
if ( $connection == false ) {
update_option( 'tve_api_delivery_service', 'postmark' );
}
return true;
/**
* just try getting a list as a connection test
*/
}
/**
* Send custom email
*
* @param $data
*
* @return bool|string true for success or error message for failure
*/
public function sendCustomEmail( $data ) {
/**
* @var $postmark Thrive_Dash_Api_Postmark
*/
$postmark = $this->get_api();
$credentials = Thrive_Dash_List_Manager::credentials( 'postmark' );
if ( is_array( $credentials ) && ! empty( $credentials['email'] ) ) {
$from_email = $credentials['email'];
} else {
return false;
}
if ( ! empty( $data['from_name'] ) ) {
$from_email = $data['from_name'] . ' < ' . $from_email . ' >';
}
try {
$postmark->sendEmail(
$from_email,
$data['email'],
$data['subject'],
empty ( $data['html_content'] ) ? '' : $data['html_content'],
empty ( $data['text_content'] ) ? '' : $data['text_content'],
null,
null,
empty ( $data['reply_to'] ) ? '' : $data['reply_to'],
empty( $data['cc'] ) ? '' : implode( ', ', $data['cc'] ),
empty( $data['bcc'] ) ? '' : implode( ', ', $data['bcc'] )
);
} catch ( Thrive_Dash_Api_Postmark_Exception $e ) {
return $e->getMessage();
}
return true;
}
/**
* Send the same email to multiple addresses
*
* @param $data
*
* @return bool|string
*/
public function sendMultipleEmails( $data ) {
/**
* we should never fucking do that
* pls find a way to send all the emails at once
*/
foreach ( $data['emails'] as $email ) {
$data['email'] = $email;
$this->sendCustomEmail( $data );
}
/**
* Send confirmation email
*/
if ( ! empty( $data['send_confirmation'] ) ) {
$confirmation = array(
'email' => $data['sender_email'],
'from_name' => $data['from_name'],
'html_content' => $data['confirmation_html'],
'subject' => $data['confirmation_subject'],
);
$credentials = Thrive_Dash_List_Manager::credentials( 'postmark' );
if ( is_array( $credentials ) && ! empty( $credentials['email'] ) ) {
$confirmation['reply_to'] = $credentials['email'];
}
$this->sendCustomEmail( $confirmation );
}
}
/**
* Send the email to the user
*
* @param $post_data
*
* @return bool|string
* @throws Exception
*
*/
public function sendEmail( $post_data ) {
$postmark = $this->get_api();
$credentials = $this->get_credentials();
$asset = get_post( $post_data['_asset_group'] );
if ( empty( $asset ) || ! ( $asset instanceof WP_Post ) || $asset->post_status !== 'publish' ) {
throw new Exception( sprintf( __( 'Invalid Asset Group: %s. Check if it exists or was trashed.', 'thrive-dash' ), $post_data['_asset_group'] ) );
}
$files = get_post_meta( $post_data['_asset_group'], 'tve_asset_group_files', true );
$subject = get_post_meta( $post_data['_asset_group'], 'tve_asset_group_subject', true );
if ( $subject == "" ) {
$subject = get_option( 'tve_leads_asset_mail_subject' );
}
$from_email = $credentials['email'];
$html_content = $asset->post_content;
if ( $html_content == "" ) {
$html_content = get_option( 'tve_leads_asset_mail_body' );
}
$attached_files = array();
foreach ( $files as $file ) {
$attached_files[] = '<a href="' . $file['link'] . '">' . $file['link_anchor'] . '</a><br/>';
}
$the_files = implode( '<br/>', $attached_files );
$html_content = str_replace( '[asset_download]', $the_files, $html_content );
$html_content = str_replace( '[asset_name]', $asset->post_title, $html_content );
$subject = str_replace( '[asset_name]', $asset->post_title, $subject );
if ( isset( $post_data['name'] ) && ! empty( $post_data['name'] ) ) {
$html_content = str_replace( '[lead_name]', $post_data['name'], $html_content );
$subject = str_replace( '[lead_name]', $post_data['name'], $subject );
$visitor_name = $post_data['name'];
} else {
$html_content = str_replace( '[lead_name]', '', $html_content );
$subject = str_replace( '[lead_name]', '', $subject );
$visitor_name = '';
}
$text_content = strip_tags( $html_content );
$result = $postmark->sendEmail(
$from_email,
$post_data['email'],
$subject,
$html_content,
$text_content
);
return $result;
}
/**
* instantiate the API code required for this connection
*
* @return mixed
*/
protected function get_api_instance() {
return new Thrive_Dash_Api_Postmark( $this->param( 'key' ) );
}
/**
* get all Subscriber Lists from this API service
*
* @return array|bool for error
*/
protected function _get_lists() {
}
/**
* add a contact to a list
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return mixed
*/
public function add_subscriber( $list_identifier, $arguments ) {
}
}

View File

@@ -0,0 +1,137 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_ReCaptcha extends Thrive_Dash_List_Connection_Abstract {
public function __construct( $key ) {
parent::__construct( $key );
add_filter( 'tcb_spam_prevention_tools', [$this, 'add_spam_prevention_tool'] );
}
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'recaptcha';
}
/**
* @return string the API connection title
*/
public function get_title() {
return 'ReCaptcha';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'recaptcha' );
}
/**
* should handle: read data from post / get, test connection and save the details
*
* on error, it should register an error message (and redirect?)
*
* @return mixed
*/
public function read_credentials() {
$site = ! empty( $_POST['site_key'] ) ? sanitize_text_field( $_POST['site_key'] ) : '';
$secret = ! empty( $_POST['secret_key'] ) ? sanitize_text_field( $_POST['secret_key'] ) : '';
if ( empty( $site ) || empty( $secret ) ) {
return $this->error( __( 'Both Site Key and Secret Key fields are required', 'thrive-dash' ) );
}
//recreate credential object
$credentials = array(
'connection' => $this->post( 'connection' ),
'site_key' => $site,
'secret_key' => $secret,
);
$this->set_credentials( $credentials );
$result = $this->test_connection();
if ( $result !== true ) {
return $this->error( sprintf( __( 'Incorrect Secret Key.', 'thrive-dash' ), $result ) );
}
/**
* finally, save the connection details
*/
$this->save();
return $this->success( __( 'ReCaptcha connected successfully!', 'thrive-dash' ) );
}
/**
* test if the secret key is correct and it exists.
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
$CAPTCHA_URL = 'https://www.google.com/recaptcha/api/siteverify';
$_capthca_params = array(
'response' => '',
'secret' => $this->param( 'secret_key' ),
);
$request = tve_dash_api_remote_post( $CAPTCHA_URL, array( 'body' => $_capthca_params ) );
$response = json_decode( wp_remote_retrieve_body( $request ), true );
if ( ! empty( $response ) && isset( $response['error-codes'] ) && in_array( 'invalid-input-secret', $response['error-codes'] ) ) {
return false;
}
return true;
}
public function getSiteKey() {
$this->get_credentials();
return $this->param( 'site_key' );
}
public function add_spam_prevention_tool( $sp_tools ) {
array_push($sp_tools, $this->_key);
return $sp_tools;
}
/**
* @return string
*/
public function custom_success_message() {
return ' ';
}
/*
* Those functions do not apply
*/
protected function get_api_instance() {
}
protected function _get_lists() {
}
public function add_subscriber( $list_identifier, $arguments ) {
}
}

View File

@@ -0,0 +1,199 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class Thrive_Dash_List_Connection_SGAutorepondeur extends Thrive_Dash_List_Connection_Abstract {
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'autoresponder';
}
/**
* @return string
*/
public function get_title() {
return 'SG Autorepondeur';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'sg-autorepondeur' );
}
/**
* just save the key in the database
*
* @return mixed|void
*/
public function read_credentials() {
if ( empty( $_POST['connection']['memberid'] ) ) {
return $this->error( __( 'You must provide a valid SG-Autorepondeur Member ID', 'thrive-dash' ) );
}
if ( empty( $_POST['connection']['key'] ) ) {
return $this->error( __( 'You must provide a valid SG-Autorepondeur key', 'thrive-dash' ) );
}
$this->set_credentials( $this->post( 'connection' ) );
$result = $this->test_connection();
if ( $result !== true ) {
return $this->error( sprintf( __( 'Could not connect to SG-Autorepondeur using the provided key (<strong>%s</strong>)', 'thrive-dash' ), $result ) );
}
/**
* finally, save the connection details
*/
$this->save();
return $this->success( __( 'SG Autorepondeur connected successfully', 'thrive-dash' ) );
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
/**
* just try getting a list as a connection test
*/
try {
/** @var Thrive_Dash_Api_SGAutorepondeur $sg */
$sg = $this->get_api();
$sg->call( 'get_list' );
} catch ( Exception $e ) {
return $e->getMessage();
}
return true;
}
/**
* instantiate the API code required for this connection
*
* @return mixed
*/
protected function get_api_instance() {
return new Thrive_Dash_Api_SGAutorepondeur( $this->param( 'memberid' ), $this->param( 'key' ) );
}
/**
* get all Subscriber Lists from this API service
*
* @return array|bool
*/
protected function _get_lists() {
try {
/** @var Thrive_Dash_Api_SGAutorepondeur $sg */
$sg = $this->get_api();
$sg->set( 'limite', array( 0, 9999 ) );
$raw = $sg->call( 'get_list' );
$lists = array();
if ( empty( $raw->reponse ) ) {
return array();
}
foreach ( $raw->reponse as $item ) {
$lists [] = array(
'id' => $item->listeid,
'name' => $item->nom,
);
}
return $lists;
} catch ( Exception $e ) {
$this->_error = $e->getMessage() . ' ' . __( "Please re-check your API connection details.", 'thrive-dash' );
return false;
}
}
/**
* add a contact to a list
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return bool|string true for success or string error message for failure
*/
public function add_subscriber( $list_identifier, $arguments ) {
list( $first_name, $last_name ) = $this->get_name_parts( $arguments['name'] );
/** @var Thrive_Dash_Api_SGAutorepondeur $api */
$api = $this->get_api();
$email = strtolower( $arguments['email'] );
$api->set( 'listeid', $list_identifier );
$api->set( 'email', $email );
/**
* The names are inversed for a reason, SG will not accept
* sending only the first_name, so the first name needs to be set as the name
*/
if ( ! empty( $first_name ) && empty( $last_name ) ) {
$api->set( 'name', $first_name );
} elseif ( ! empty( $first_name ) && ! empty( $last_name ) ) {
$api->set( 'first_name', $first_name );
$api->set( 'name', $last_name );
}
if ( isset( $arguments['phone'] ) && ! empty( $arguments['phone'] ) ) {
$api->set( 'telephone', $arguments['phone'] );
}
try {
$api->call( 'set_subscriber' );
return true;
} catch ( Exception $e ) {
return $e->getMessage() ? $e->getMessage() : __( 'Unknown SG-Autorepondeur Error', 'thrive-dash' );
}
}
/**
* Return the connection email merge tag
*
* @return String
*/
public static function get_email_merge_tag() {
return '++email++';
}
/**
* disconnect (remove) this API connection
*/
public function disconnect() {
$this->set_credentials( array() );
Thrive_Dash_List_Manager::save( $this );
return $this;
}
}

View File

@@ -0,0 +1,277 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class Thrive_Dash_List_Connection_SendGrid extends Thrive_Dash_List_Connection_Abstract {
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'autoresponder';
}
/**
* @return string
*/
public function get_title() {
return 'SendGrid';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$related_api = Thrive_Dash_List_Manager::connection_instance( 'sendgridemail' );
if ( $related_api->is_connected() ) {
$this->set_param( 'new_connection', 1 );
}
$this->output_controls_html( 'sendgrid' );
}
/**
* just save the key in the database
*
* @return mixed|void
*/
public function read_credentials() {
$key = ! empty( $_POST['connection']['key'] ) ? sanitize_text_field( $_POST['connection']['key'] ) : '';
if ( empty( $key ) ) {
return $this->error( __( 'You must provide a valid SendGrid key', 'thrive-dash' ) );
}
$this->set_credentials( $this->post( 'connection' ) );
$result = $this->test_connection();
if ( $result !== true ) {
return $this->error( sprintf( __( 'Could not connect to SendGrid using the provided key (<strong>%s</strong>)', 'thrive-dash' ), $result ) );
}
/**
* finally, save the connection details
*/
$this->save();
/** @var Thrive_Dash_List_Connection_SendGridEmail $related_api */
$related_api = Thrive_Dash_List_Manager::connection_instance( 'sendgridemail' );
if ( isset( $_POST['connection']['new_connection'] ) && intval( $_POST['connection']['new_connection'] ) === 1 ) {
/**
* Try to connect to the email service too
*/
$r_result = true;
if ( ! $related_api->is_connected() ) {
$r_result = $related_api->read_credentials();
}
if ( $r_result !== true ) {
$this->disconnect();
return $this->error( $r_result );
}
} else {
/**
* let's make sure that the api was not edited and disconnect it
*/
$related_api->set_credentials( array() );
Thrive_Dash_List_Manager::save( $related_api );
}
return $this->success( __( 'SendGrid connected successfully', 'thrive-dash' ) );
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
/** @var Thrive_Dash_Api_SendGrid $sg */
$sg = $this->get_api();
try {
$sg->client->contactdb()->lists()->get();
} catch ( Thrive_Dash_Api_SendGrid_Exception $e ) {
return $e->getMessage();
}
return true;
}
/**
* instantiate the API code required for this connection
*
* @return Thrive_Dash_Api_SendGrid
*/
protected function get_api_instance() {
return new Thrive_Dash_Api_SendGrid( $this->param( 'key' ) );
}
/**
* get all Subscriber Lists from this API service
*
* @return array|bool
*/
protected function _get_lists() {
/** @var Thrive_Dash_Api_SendGrid $api */
$api = $this->get_api();
$response = $api->client->contactdb()->lists()->get();
if ( $response->statusCode() != 200 ) {
$body = $response->body();
$this->_error = ucwords( $body->errors['0']->message );
return false;
}
$body = $response->body();
$lists = array();
foreach ( $body->lists as $item ) {
$lists [] = array(
'id' => $item->id,
'name' => $item->name,
);
}
return $lists;
}
/**
* add a contact to a list
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return bool|string true for success or string error message for failure
*/
public function add_subscriber( $list_identifier, $arguments ) {
$args = new stdClass();
list( $first_name, $last_name ) = $this->get_name_parts( $arguments['name'] );
/** @var Thrive_Dash_Api_SendGrid $api */
$api = $this->get_api();
$args->email = $arguments['email'];
if ( ! empty( $first_name ) ) {
$args->first_name = $first_name;
}
if ( ! empty( $last_name ) ) {
$args->last_name = $last_name;
}
if ( ! empty( $arguments['phone'] ) ) {
$custom_field_id = '';
try {
$response = $api->client->contactdb()->custom_fields()->get();
$fields = $response->body();
foreach ( $fields->custom_fields as $custom_field ) {
if ( isset( $custom_field->name ) && ( $custom_field->name === 'phone' ) ) {
$custom_field_id = $custom_field->id;
}
}
if ( $custom_field_id ) {
try {
$response = $api->client->contactdb()->custom_fields()->_( $custom_field_id )->get();
} catch ( Thrive_Dash_Api_SendGrid_Exception $e ) {
return $e->getMessage();
}
$result = $response->body();
if ( isset( $result->errors ) ) {
$request_body = json_decode( '{
"name": "phone",
"type": "number"
}' );
$api->client->contactdb()->custom_fields()->post( $request_body );
}
$args->phone = $arguments['phone'];
}
} catch ( Thrive_Dash_Api_SendGrid_Exception $e ) {
return $e->getMessage();
}
}
try {
$response = $api->client->contactdb()->recipients()->post( array( $args ) );
} catch ( Thrive_Dash_Api_SendGrid_Exception $e ) {
return $e->getMessage();
}
$body = $response->body();
if ( $body->error_count == 0 ) {
$request_body = null;
$recipient_id = $body->persisted_recipients[0];
try {
$api->client->contactdb()->lists()->_( $list_identifier )->recipients()->_( $recipient_id )->post( $request_body );
} catch ( Thrive_Dash_Api_SendGrid_Exception $e ) {
return $e->getMessage();
}
return true;
}
return __( 'Unknown Sendgrid Error', 'thrive-dash' );
}
/**
* Return the connection email merge tag
*
* @return String
*/
public static function get_email_merge_tag() {
return '{$email}';
}
/**
* disconnect (remove) this API connection
*/
public function disconnect() {
$this->set_credentials( array() );
Thrive_Dash_List_Manager::save( $this );
/**
* disconnect the email service too
*/
$related_api = Thrive_Dash_List_Manager::connection_instance( 'sendgridemail' );
$related_api->set_credentials( array() );
Thrive_Dash_List_Manager::save( $related_api );
return $this;
}
}

View File

@@ -0,0 +1,352 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class Thrive_Dash_List_Connection_SendGridEmail extends Thrive_Dash_List_Connection_Abstract {
/**
* Return if the connection is in relation with another connection so we won't show it in the API list
*
* @return bool
*/
public function is_related() {
return true;
}
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'email';
}
/**
* @return string the API connection title
*/
public function get_title() {
return 'SendGrid';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'sendgridemail' );
}
/**
* should handle: read data from post / get, test connection and save the details
*
* on error, it should register an error message (and redirect?)
*/
public function read_credentials() {
$ajax_call = defined( 'DOING_AJAX' ) && DOING_AJAX;
$key = ! empty( $_POST['connection']['key'] ) ? sanitize_text_field( $_POST['connection']['key'] ) : '';
if ( empty( $key ) ) {
return $ajax_call ? __( 'You must provide a valid SendGrid key', 'thrive-dash' ) : $this->error( __( 'You must provide a valid SendGrid key', 'thrive-dash' ) );
}
$this->set_credentials( $this->post( 'connection' ) );
$result = $this->test_connection();
if ( $result !== true ) {
return $ajax_call ? sprintf( __( 'Could not connect to SendGrid using the provided key (<strong>%s</strong>)', 'thrive-dash' ), $result ) : $this->error( sprintf( __( 'Could not connect to SendGrid using the provided key (<strong>%s</strong>)', 'thrive-dash' ), $result ) );
}
/**
* finally, save the connection details
*/
$this->save();
/**
* Try to connect to the autoresponder too
*/
/** @var Thrive_Dash_List_Connection_SendGrid $related_api */
$related_api = Thrive_Dash_List_Manager::connection_instance( 'sendgrid' );
$r_result = true;
if ( ! $related_api->is_connected() ) {
$_POST['connection']['new_connection'] = isset( $_POST['connection']['new_connection'] ) ? sanitize_text_field( $_POST['connection']['new_connection'] ) : 1;
$r_result = $related_api->read_credentials();
}
if ( $r_result !== true ) {
$this->disconnect();
return $this->error( $r_result );
}
$this->success( __( 'SendGrid connected successfully', 'thrive-dash' ) );
if ( $ajax_call ) {
return true;
}
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
/** @var Thrive_Dash_Api_SendGridEmail $sg */
$sg = $this->get_api();
$email = new Thrive_Dash_Api_SendGridEmail_Email();
/**
* Try sending the email
*/
try {
$from_email = get_option( 'admin_email' );
$to = $from_email;
$subject = 'API connection test';
$html_content = 'This is a test email from Thrive Leads SendGrid Email API.';
$text_content = 'This is a test email from Thrive Leads SendGrid Email API.';
$email
->addTo( $to )
->setFrom( $from_email )
->setSubject( $subject )
->setText( $text_content )
->setHtml( $html_content );
$sg->send( $email );
} catch ( Thrive_Dash_Api_SendGridEmail_Exception $e ) {
return $e->getMessage();
}
$connection = get_option( 'tve_api_delivery_service', false );
if ( $connection == false ) {
update_option( 'tve_api_delivery_service', 'sendgridemail' );
}
return true;
/**
* just try getting a list as a connection test
*/
}
/**
* Send custom email
*
* @param $data
*
* @return bool|string true for success or error message for failure
*/
public function sendCustomEmail( $data ) {
$sg = $this->get_api();
$email = new Thrive_Dash_Api_SendGridEmail_Email();
$from_email = get_option( 'admin_email' );
/**
* Try sending the email
*/
try {
$email
->addTo( $data['email'] )
->setFrom( $from_email )
->setSubject( $data['subject'] )
->setText( empty ( $data['text_content'] ) ? '' : $data['text_content'] )
->setHtml( empty ( $data['html_content'] ) ? '' : $data['html_content'] );
$sg->send( $email );
} catch ( Exception $e ) {
return $e->getMessage();
}
return true;
}
/**
* Send the same email to multiple addresses
*
* @param $data
*
* @return bool|string
*/
public function sendMultipleEmails( $data ) {
$sg = $this->get_api();
$email = new Thrive_Dash_Api_SendGridEmail_Email();
$from_email = get_option( 'admin_email' );
$to = array_shift( $data['emails'] );
/**
* Try sending the email
*/
try {
$email
->addTo( $to )
->setFrom( $from_email )
->setFromName( empty( $data['from_name'] ) ? '' : $data['from_name'] )
->setReplyTo( empty( $data['reply_to'] ) ? '' : $data['reply_to'] )
->setCcs( empty( $data['cc'] ) ? array() : $data['cc'] )
->setBccs( empty( $data['bcc'] ) ? array() : $data['bcc'] )
->setSubject( $data['subject'] )
->setText( empty ( $data['text_content'] ) ? '' : $data['text_content'] )
->setHtml( empty ( $data['html_content'] ) ? '' : $data['html_content'] );
foreach ( $data['emails'] as $item ) {
$email->addCc( $item );
}
$sg->send( $email );
} catch ( Exception $e ) {
return $e->getMessage();
}
/* Send confirmation email */
if ( ! empty( $data['send_confirmation'] ) ) {
try {
$confirmation_email = new Thrive_Dash_Api_SendGridEmail_Email();
$confirmation_email
->addTo( array( $data['sender_email'] ) )
->setFrom( $from_email )
->setFromName( empty( $data['from_name'] ) ? '' : $data['from_name'] )
->setReplyTo( $from_email )
->setSubject( $data['confirmation_subject'] )
->setText( '' )
->setHtml( empty ( $data['confirmation_html'] ) ? '' : $data['confirmation_html'] );
$sg->send( $confirmation_email );
} catch ( Exception $e ) {
return $e->getMessage();
}
}
return true;
}
/**
* Send the email to the user
*
* @param $post_data
*
* @return bool|string
* @throws Exception
*
*/
public function sendEmail( $post_data ) {
if ( empty( $post_data['_asset_group'] ) ) {
return true;
}
$sg = $this->get_api();
$email = new Thrive_Dash_Api_SendGridEmail_Email();
$asset = get_post( $post_data['_asset_group'] );
if ( empty( $asset ) || ! ( $asset instanceof WP_Post ) || $asset->post_status !== 'publish' ) {
throw new Exception( sprintf( __( 'Invalid Asset Group: %s. Check if it exists or was trashed.', 'thrive-dash' ), $post_data['_asset_group'] ) );
}
$files = get_post_meta( $post_data['_asset_group'], 'tve_asset_group_files', true );
$subject = get_post_meta( $post_data['_asset_group'], 'tve_asset_group_subject', true );
if ( empty( $subject ) ) {
$subject = get_option( 'tve_leads_asset_mail_subject' );
}
$from_email = get_option( 'admin_email' );
$html_content = $asset->post_content;
if ( empty( $html_content ) ) {
$html_content = get_option( 'tve_leads_asset_mail_body' );
}
$the_files = '';
foreach ( $files as $file ) {
$the_files .= '<a href="' . $file['link'] . '">' . $file['link_anchor'] . '</a><br/><br/>';
}
$html_content = str_replace( '[asset_download]', $the_files, $html_content );
$html_content = str_replace( '[asset_name]', $asset->post_title, $html_content );
$subject = str_replace( '[asset_name]', $asset->post_title, $subject );
if ( isset( $post_data['name'] ) && ! empty( $post_data['name'] ) ) {
$html_content = str_replace( '[lead_name]', $post_data['name'], $html_content );
$subject = str_replace( '[lead_name]', $post_data['name'], $subject );
$visitor_name = $post_data['name'];
} else {
$from_name = "";
$html_content = str_replace( '[lead_name]', '', $html_content );
$subject = str_replace( '[lead_name]', '', $subject );
$visitor_name = '';
}
$text_content = strip_tags( $html_content );
$email
->addTo( $post_data['email'], $visitor_name )
->setFrom( $from_email )
->setSubject( $subject )
->setText( $text_content )
->setHtml( $html_content );
/**
* Try sending the email
*/
$result = $sg->send( $email );
return $result;
}
/**
* instantiate the API code required for this connection
*
* @return mixed
*/
protected function get_api_instance() {
$options = array(
'host' => 'api.sendgrid.com',
'endpoint' => '/api/mail.send.json',
'port' => null,
'url' => null,
);
return new Thrive_Dash_Api_SendGridEmail( $this->param( 'key' ), $options );
}
/**
* add a contact to a list
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return mixed
*/
public function add_subscriber( $list_identifier, $arguments ) {
return true;
}
/**
* get all Subscriber Lists from this API service
*
* @return array|bool for error
*/
protected function _get_lists() {
return true;
}
}

View File

@@ -0,0 +1,241 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_SendLayer extends Thrive_Dash_List_Connection_Abstract {
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'email';
}
/**
* @return string the API connection title
*/
public function get_title() {
return 'SendLayer';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'sendlayer' );
}
/**
* should handle: read data from post / get, test connection and save the details
*
* on error, it should register an error message (and redirect?)
*/
public function read_credentials() {
$ajax_call = defined( 'DOING_AJAX' ) && DOING_AJAX;
$key = ! empty( $_POST['connection']['key'] ) ? sanitize_text_field( $_POST['connection']['key'] ) : '';
if ( empty( $key ) ) {
return $ajax_call ? __( 'You must provide a valid SendLayer key', 'thrive-dash' ) : $this->error( __( 'You must provide a valid SendLayer key', 'thrive-dash' ) );
}
$this->set_credentials( compact( 'key' ) );
$result = $this->test_connection();
if ( $result !== true ) {
return $ajax_call ? sprintf( __( 'Could not connect to SendLayer using the provided key (<strong>%s</strong>)', 'thrive-dash' ), $result ) : $this->error( sprintf( __( 'Could not connect to SendLayer using the provided key (<strong>%s</strong>)', 'thrive-dash' ), $result ) );
}
/**
* finally, save the connection details
*/
$this->save();
$this->success( __( 'SendLayer connected successfully', 'thrive-dash' ) );
if ( $ajax_call ) {
return true;
}
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
/** @var Thrive_Dash_Api_SendLayer $sendlayer */
$sendlayer = $this->get_api();
$from_email = get_option( 'admin_email' );
$to = array( array( 'email' => $from_email ) );
$name = $from_email;
if ( is_user_logged_in() ) {
$user = wp_get_current_user();
$name = $user->display_name;
}
$subject = 'API connection test';
$text_content = $html_content = 'This is a test email from Thrive Leads SendLayer API.';
try {
$sendlayer->sendMessage([
'name' => $name,
'from' => $from_email,
'to' => $to,
'subject' => $subject,
'text' => $text_content,
'html' => $html_content,
'multipart' => true,
]);
} catch ( Exception $e ) {
return $e->getMessage();
}
$connection = get_option( 'tve_api_delivery_service', false );
if ( $connection == false ) {
update_option( 'tve_api_delivery_service', 'sendlayer' );
}
return true;
}
/**
* Send custom email
*
* @param $data
*
* @return bool|string true for success or error message for failure
*/
public function sendCustomEmail( $data ) {
$sendlayer = $this->get_api();
$from_email = get_option( 'admin_email' );
$site_name = html_entity_decode( get_option( 'blogname' ) );
try {
$message = array(
'name' => empty ( $data['from_name'] ) ? $site_name : $data['from_name'],
'from' => $from_email,
'to' => array( array( 'email' => $data['email'] ) ),
'subject' => $data['subject'],
'text' => empty ( $data['text_content'] ) ? '' : $data['text_content'],
'html' => empty ( $data['html_content'] ) ? '' : $data['html_content'],
'h:Reply-To' => empty ( $data['reply_to'] ) ? '' : $data['reply_to'],
'tags' => empty( $data['email_tags'] ) ? [] : $data['email_tags'],
'multipart' => true,
);
$sendlayer->sendMessage( $message );
} catch ( Exception $e ) {
return $e->getMessage();
}
return true;
}
/**
* Send the same email to multiple addresses
*
* @param $data
*
* @return bool|string
*/
public function sendMultipleEmails( $data ) {
$sendlayer = $this->get_api();
$emails = !empty($data['emails']) ? $data['emails'] : array();
$formatted_emails = array();
foreach($emails as $email) {
array_push($formatted_emails, array('email' => $email));
}
$from_email = get_option( 'admin_email' );
try {
$messsage = array(
'name' => empty ( $data['from_name'] ) ? '' : $data['from_name'],
'from' => $from_email,
'to' => $formatted_emails,
'subject' => $data['subject'],
'text' => empty ( $data['text_content'] ) ? '' : $data['text_content'],
'html' => empty ( $data['html_content'] ) ? '' : $data['html_content'],
'h:Reply-To' => empty ( $data['reply_to'] ) ? '' : $data['reply_to'],
'tags' => empty( $data['email_tags'] ) ? [] : $data['email_tags'],
'multipart' => true,
);
$sendlayer->sendMessage($messsage);
} catch ( Exception $e ) {
return $e->getMessage();
}
/* Send confirmation email */
if ( ! empty( $data['send_confirmation'] ) && !empty($data['sender_email']) ) {
try {
$messsage = array(
'name' => $from_email,
'from' => $from_email,
'to' => array(
array( 'email' => $data['sender_email'] )
),
'subject' => $data['confirmation_subject'],
'text' => '',
'html' => empty ( $data['confirmation_html'] ) ? '' : $data['confirmation_html'],
'h:Reply-To' => $from_email,
'multipart' => true,
);
$sendlayer->sendMessage( $messsage );
} catch ( Exception $e ) {
return $e->getMessage();
}
}
return true;
}
/**
* instantiate the API code required for this connection
*
* @return mixed
*/
protected function get_api_instance() {
$endpoint = "https://console.sendlayer.com/api";
return new Thrive_Dash_Api_SendLayer( $this->param( 'key' ), $endpoint );
}
/**
* get all Subscriber Lists from this API service
*
* used for abstract class
*/
protected function _get_lists() {
}
/**
* add a contact to a list
*
* @param mixed $list_identifier
* @param array $arguments
*
* used for abstract class
*/
public function add_subscriber( $list_identifier, $arguments ) {
}
}

View File

@@ -0,0 +1,127 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class Thrive_Dash_List_Connection_SendOwl extends Thrive_Dash_List_Connection_Abstract {
const sendowl_url = 'https://www.sendowl.com';
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'sellings';
}
/**
* @return string
*/
public function get_title() {
return 'SendOwl';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'sendowl' );
}
/**
* just save the key in the database
*
* @return mixed|void
*/
public function read_credentials() {
$key = ! empty( $_POST['connection']['key'] ) ? sanitize_text_field( $_POST['connection']['key'] ) : '';
if ( empty( $key ) ) {
return $this->error( __( 'You must provide a valid SendOwl key', 'thrive-dash' ) );
}
$url = self::sendowl_url;
$this->set_credentials( $this->post( 'connection' ) );
$result = $this->test_connection();
if ( $result !== true ) {
return $this->error( sprintf( __( 'Could not connect to SendOwl using the provided key (<strong>%s</strong>)', 'thrive-dash' ), $result ) );
}
/**
* finally, save the connection details
*/
$this->save();
return $this->success( __( 'SendOwl connected successfully', 'thrive-dash' ) );
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
/** @var Thrive_Dash_Api_SendOwl $so */
$so = $this->get_api();
try {
$so->getProducts();
} catch ( Thrive_Dash_Api_SendOwl_Exception $e ) {
return $e->getMessage();
}
return true;
}
/**
* add a contact to a list
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return bool|string true for success or string error message for failure
*/
public function add_subscriber( $list_identifier, $arguments ) {
}
/**
* instantiate the API code required for this connection
*
* @return mixed
*/
protected function get_api_instance() {
if ( empty( $this->param( 'key' ) ) || empty( $this->param( 'secret' ) ) ) {
return null;
}
return new Thrive_Dash_Api_SendOwl( array(
'apiKey' => $this->param( 'key' ),
'secretKey' => $this->param( 'secret' ),
)
);
}
/**
* get all Subscriber Lists from this API service
*
* @return array
*/
protected function _get_lists() {
return array();
}
}

View File

@@ -0,0 +1,517 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_Sendfox extends Thrive_Dash_List_Connection_Abstract {
/**
* Return api connection title
*
* @return string
*/
public function get_title() {
return 'Sendfox';
}
/**
* Output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'sendfox' );
}
/**
* Read data from post, test connection and save the details.
*
* Show error message on failure.
*
* @return mixed|Thrive_Dash_List_Connection_Abstract
*/
public function read_credentials() {
if ( empty( $_POST['connection']['api_key'] ) ) {
return $this->error( __( 'Api key is required', 'thrive-dash' ) );
}
$this->set_credentials( $this->post( 'connection' ) );
$result = $this->test_connection();
if ( true !== $result ) {
return $this->error( __( 'Could not connect to Sendfox using provided api key.', 'thrive-dash' ) );
}
/**
* Finally, save the connection details.
*/
$this->save();
return $this->success( __( 'Sendfox connected successfully', 'thrive-dash' ) );
}
/**
* Test connection to SendFox API.
*
* @return bool|string
*/
public function test_connection() {
return is_array( $this->_get_lists() );
}
/**
* Add subscriber to SendFox list.
*
* @param string $list_identifier The list identifier.
* @param array $arguments The subscriber arguments.
*
* @return bool
*/
public function add_subscriber( $list_identifier, $arguments ) {
try {
$api = $this->get_api();
list( $first_name, $last_name ) = $this->get_name_parts( $arguments['name'] );
$subscriber_args = array(
'email' => $arguments['email'],
'first_name' => $first_name,
'last_name' => $last_name,
);
// Add custom fields if they exist and are available.
$available_custom_fields = $this->get_api_custom_fields( array() );
if ( ! empty( $available_custom_fields ) ) {
$custom_fields = $this->_generateCustomFields( $arguments );
// Add phone field mapping if phone is provided.
if ( ! empty( $arguments['phone'] ) ) {
$phone_field = $this->find_phone_custom_field( $available_custom_fields );
if ( $phone_field ) {
$custom_fields[] = array(
'name' => $phone_field['name'],
'value' => sanitize_text_field( $arguments['phone'] ),
);
}
}
if ( ! empty( $custom_fields ) ) {
$subscriber_args['contact_fields'] = $custom_fields;
}
}
$api->add_subscriber( $list_identifier, $subscriber_args );
return true;
} catch ( Exception $e ) {
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
error_log( 'SendFox add_subscriber: Exception - ' . $e->getMessage() );
}
return false;
}
}
/**
* Get SendFox API instance.
*
* @return mixed|Thrive_Dash_Api_Sendfox
* @throws Exception When API key is missing.
*/
protected function get_api_instance() {
$api_key = $this->param( 'api_key' );
return new Thrive_Dash_Api_Sendfox( $api_key );
}
/**
* Get lists from SendFox API.
*
* @return array|bool
*/
protected function _get_lists() {
$result = array();
try {
$api = $this->get_api();
$lists = $api->getLists();
if ( isset( $lists['data'] ) && is_array( $lists['data'] ) ) {
/* First page of lists */
$result = $lists['data'];
/* For multiple pages */
if ( ! empty( $lists['total'] ) ) {
$lists_total = (int) $lists['total'];
$list_per_page = (int) $lists['per_page'];
$pagination_needed = (int) ( $lists_total / $list_per_page ) + 1;
/* Request pages >=2 and merge lists */
if ( $pagination_needed >= 2 ) {
for ( $i = 2; $i <= $pagination_needed; $i++ ) {
$response_pages = $api->getListsOnPage( $i );
if ( isset( $response_pages['data'] ) && is_array( $response_pages['data'] ) ) {
$result = array_merge( $result, $response_pages['data'] );
}
}
}
}
}
} catch ( Exception $e ) {
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
error_log( 'SendFox DEBUG: Error getting lists: ' . $e->getMessage() );
}
}
return $result;
}
/**
* Get API custom fields.
*
* @param array $params The parameters.
* @param bool $force Force refresh flag.
* @param bool $get_all Get all fields flag.
*
* @return array|mixed
*/
public function get_api_custom_fields( $params, $force = false, $get_all = false ) {
$cached_data = $this->get_cached_custom_fields();
if ( false === $force && ! empty( $cached_data ) ) {
return $cached_data;
}
$custom_data = array();
try {
$api = $this->get_api();
$custom_fields = $api->getContactFields();
if ( empty( $custom_fields['data'] ) ) {
$this->_save_custom_fields( $custom_data );
return $custom_data;
}
foreach ( $custom_fields['data'] as $field ) {
$normalized_field = $this->_normalizeCustomFields( $field );
$custom_data[] = $normalized_field;
}
} catch ( Exception $e ) {
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
error_log( 'SendFox DEBUG: Error getting custom fields: ' . $e->getMessage() );
}
}
$this->_save_custom_fields( $custom_data );
return $custom_data;
}
/**
* Normalize custom field data.
*
* @param array|object $field The field data.
*
* @return array
*/
protected function _normalizeCustomFields( $field ) {
$field = (array) $field;
return array(
'id' => isset( $field['id'] ) ? (string) $field['id'] : '',
'name' => ! empty( $field['name'] ) ? $field['name'] : '',
'type' => 'custom',
'label' => ! empty( $field['name'] ) ? $field['name'] : '',
);
}
/**
* Generate custom fields array.
*
* @param array $args The arguments array.
*
* @return array
*/
private function _generateCustomFields( $args ) {
$custom_fields = $this->get_api_custom_fields( array() );
$ids = $this->buildMappedCustomFields( $args );
$result = array();
if ( empty( $custom_fields ) || empty( $ids ) ) {
return $result;
}
// Create hash map for O(1) lookups instead of array_filter in loop.
$custom_fields_map = array();
foreach ( $custom_fields as $field ) {
$custom_fields_map[ $field['id'] ] = $field;
}
foreach ( $ids as $key => $id ) {
if ( ! isset( $custom_fields_map[ $id['value'] ] ) ) {
continue;
}
$field = $custom_fields_map[ $id['value'] ];
// Get the original field ID from the mapped data.
$original_id = isset( $id['original_id'] ) ? $id['original_id'] : $key;
// Use original field type for form field name construction to handle converted types.
$form_field_type = isset( $id['original_type'] ) ? $id['original_type'] : $id['type'];
$name = $form_field_type . '_' . $original_id;
$cf_form_name = str_replace( '[]', '', $name );
// Check if the form field exists before processing.
if ( ! isset( $args[ $cf_form_name ] ) ) {
continue;
}
$processed_value = $this->process_field( $args[ $cf_form_name ] );
$result[] = array(
'name' => $field['name'],
'value' => $processed_value,
);
}
return $result;
}
/**
* Build mapped custom fields array based on form params.
*
* @param array $args The form arguments.
*
* @return array
*/
public function buildMappedCustomFields( $args ) {
$mapped_data = array();
// Should be always base_64 encoded of a serialized array.
if ( empty( $args['tve_mapping'] ) || ! tve_dash_is_bas64_encoded( $args['tve_mapping'] ) || ! is_serialized( base64_decode( $args['tve_mapping'] ) ) ) {
return $mapped_data;
}
$form_data = thrive_safe_unserialize( base64_decode( $args['tve_mapping'] ) );
if ( empty( $form_data ) ) {
return $mapped_data;
}
$mapped_fields = $this->get_mapped_field_ids();
if ( empty( $mapped_fields ) ) {
return $mapped_data;
}
// Create a regex pattern from all mapped fields for single-pass matching.
$pattern_parts = array();
foreach ( $mapped_fields as $mapped_field_name ) {
$pattern_parts[] = preg_quote( $mapped_field_name, '/' );
}
$combined_pattern = '/^(' . implode( '|', $pattern_parts ) . ')_(.+)$/';
// Single loop with regex pattern matching - no nested loops.
foreach ( $form_data as $cf_form_name => $field_data ) {
if ( empty( $field_data[ $this->_key ] ) ) {
continue;
}
// Single regex match instead of nested loop.
if ( preg_match( $combined_pattern, $cf_form_name, $matches ) ) {
$mapped_field_name = $matches[1]; // The matched prefix.
$field_id = $matches[2]; // The extracted ID.
// Clean the field_id by removing brackets if present (for checkbox fields).
$clean_field_id = str_replace( '[]', '', $field_id );
// Construct the actual field name that should exist in args (without brackets).
$actual_field_name = $mapped_field_name . '_' . $clean_field_id;
// Check if the actual form field exists in the arguments.
if ( ! isset( $args[ $actual_field_name ] ) ) {
continue;
}
// Convert country, state and checkbox fields to mapping_text for SendFox.
$field_type = $mapped_field_name;
if ( 'country' === $mapped_field_name || 'state' === $mapped_field_name || 'checkbox' === $mapped_field_name ) {
$field_type = 'mapping_text';
}
// Use unique key to prevent overwrites when multiple field types map to same SendFox field.
$unique_key = $field_type . '_' . $mapped_field_name . '_' . $clean_field_id;
$mapped_data[ $unique_key ] = array(
'type' => $field_type,
'value' => $field_data[ $this->_key ],
'original_type' => $mapped_field_name,
'original_id' => $clean_field_id,
);
}
}
return $mapped_data;
}
/**
* Add custom fields to a contact.
*
* @param string $email The email address.
* @param array $custom_fields The custom fields array.
* @param array $extra Extra data array.
*
* @return int|bool
*/
public function add_custom_fields( $email, $custom_fields = array(), $extra = array() ) {
try {
$api = $this->get_api();
$list_id = ! empty( $extra['list_identifier'] ) ? $extra['list_identifier'] : null;
list( $first_name, $last_name ) = $this->get_name_parts( ! empty( $extra['name'] ) ? $extra['name'] : '' );
$subscriber_args = array(
'email' => $email,
'first_name' => $first_name,
'last_name' => $last_name,
);
if ( ! empty( $custom_fields ) ) {
$subscriber_args['contact_fields'] = $this->prepare_custom_fields_for_api( $custom_fields );
}
$api->add_subscriber( $list_id, $subscriber_args );
} catch ( Exception $e ) {
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
error_log( 'SendFox add_custom_fields: Exception - ' . $e->getMessage() );
}
return false;
}
}
/**
* Get available custom fields for this api connection.
*
* @param null $list_id The list ID.
*
* @return array
*/
public function get_available_custom_fields( $list_id = null ) {
return $this->get_api_custom_fields( null, true );
}
/**
* Prepare custom fields for api call.
*
* @param array $custom_fields The custom fields array.
* @param null $list_identifier The list identifier.
*
* @return array
*/
public function prepare_custom_fields_for_api( $custom_fields = array(), $list_identifier = null ) {
$prepared_fields = array();
$api_fields = $this->get_api_custom_fields( null, true );
if ( empty( $custom_fields ) || empty( $api_fields ) ) {
return $prepared_fields;
}
// Create hash map for O(1) lookups instead of nested loops.
$api_fields_map = array();
foreach ( $api_fields as $field ) {
$api_fields_map[ (string) $field['id'] ] = $field;
}
foreach ( $custom_fields as $key => $custom_field ) {
$field_id = (string) $key;
if ( isset( $api_fields_map[ $field_id ] ) ) {
$prepared_fields[] = array(
'name' => $api_fields_map[ $field_id ]['name'],
'value' => $custom_field,
);
}
}
return $prepared_fields;
}
/**
* Whether the current integration can provide custom fields
*
* @return bool
*/
public function has_custom_fields() {
return true;
}
/**
* Append custom fields to defaults.
*
* @param array $params The parameters.
*
* @return array
*/
public function get_custom_fields( $params = array() ) {
return array_merge( parent::get_custom_fields(), $this->_mapped_custom_fields );
}
/**
* Find phone custom field in available fields.
*
* @param array $available_fields The available custom fields.
* @return array|false The phone field data or false if not found.
*/
private function find_phone_custom_field( $available_fields ) {
// Create single regex pattern for all phone field patterns - no nested loops.
$phone_pattern = '/phone|mobile|telephone|cell/i';
// Use array_filter with single regex match for O(n) complexity.
$phone_fields = array_filter(
$available_fields,
function ( $field ) use ( $phone_pattern ) {
return preg_match( $phone_pattern, $field['name'] );
}
);
// Return first matching phone field.
return ! empty( $phone_fields ) ? reset( $phone_fields ) : false;
}
/**
* Process field value for SendFox API.
*
* @param mixed $field The field value to process.
*
* @return string
*/
public function process_field( $field ) {
// Handle arrays (multi-select, checkboxes).
if ( is_array( $field ) ) {
// Filter out empty values and join with comma-space.
$filtered_values = array_filter(
$field,
function ( $value ) {
return ! empty( trim( $value ) );
}
);
return implode( ', ', $filtered_values );
}
return stripslashes( (string) $field );
}
}

View File

@@ -0,0 +1,520 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_Sendinblue extends Thrive_Dash_List_Connection_Abstract {
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'autoresponder';
}
/**
* @return string the API connection title
*/
public function get_title() {
return 'SendinBlue';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$related_api = Thrive_Dash_List_Manager::connection_instance( 'sendinblueemail' );
if ( $related_api->is_connected() ) {
$this->set_param( 'new_connection', 1 );
}
$this->output_controls_html( 'sendinblue' );
}
/**
* should handle: read data from post / get, test connection and save the details
*
* on error, it should register an error message (and redirect?)
*/
public function read_credentials() {
$ajax_call = defined( 'DOING_AJAX' ) && DOING_AJAX;
$key = ! empty( $_POST['connection']['key'] ) ? sanitize_text_field( $_POST['connection']['key'] ) : '';
if ( empty( $key ) ) {
return $ajax_call ? __( 'You must provide a valid SendinBlue key', 'thrive-dash' ) : $this->error( __( 'You must provide a valid SendinBlue key', 'thrive-dash' ) );
}
$this->set_credentials( $this->post( 'connection' ) );
$result = $this->test_connection();
if ( $result !== true ) {
return $ajax_call ? sprintf( __( 'Could not connect to SendinBlue using the provided key (<strong>%s</strong>)', 'thrive-dash' ), $result ) : $this->error( sprintf( __( 'Could not connect to SendinBlue using the provided key (<strong>%s</strong>)', 'thrive-dash' ), $result ) );
}
/**
* finally, save the connection details
*/
$this->save();
/** @var Thrive_Dash_List_Connection_SendinblueEmail $related_api */
$related_api = Thrive_Dash_List_Manager::connection_instance( 'sendinblueemail' );
if ( isset( $_POST['connection']['new_connection'] ) && intval( $_POST['connection']['new_connection'] ) === 1 ) {
/**
* Try to connect to the email service too
*/
$r_result = true;
if ( ! $related_api->is_connected() ) {
$r_result = $related_api->read_credentials();
}
if ( $r_result !== true ) {
$this->disconnect();
return $this->error( $r_result );
}
} else {
/**
* let's make sure that the api was not edited and disconnect it
*/
$related_api->set_credentials( array() );
Thrive_Dash_List_Manager::save( $related_api );
}
$this->success( __( 'SendinBlue connected successfully', 'thrive-dash' ) );
if ( $ajax_call ) {
return true;
}
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
$sendinblue = $this->get_api();
try {
$sendinblue->get_account();
} catch ( Exception $e ) {
return $e->getMessage();
}
return true;
/**
* just try getting a list as a connection test
*/
}
/**
* instantiate the API code required for this connection
*
* @return mixed
*/
protected function get_api_instance() {
return new Thrive_Dash_Api_Sendinblue( "https://api.sendinblue.com/v2.0", $this->param( 'key' ) );
}
/**
* get all Subscriber Lists from this API service
*
* @return array|bool for error
*/
protected function _get_lists() {
/** @var Thrive_Dash_Api_Sendinblue $sendinblue */
$sendinblue = $this->get_api();
$data = array(
"page" => 1,
"page_limit" => 50,
);
try {
$lists = array();
$raw = $sendinblue->get_lists( $data );
if ( empty( $raw['data'] ) ) {
return array();
}
foreach ( $raw['data'] as $item ) {
$lists [] = array(
'id' => $item['id'],
'name' => $item['name'],
);
}
return $lists;
} catch ( Exception $e ) {
$this->_error = $e->getMessage() . ' ' . __( "Please re-check your API connection details.", 'thrive-dash' );
return false;
}
}
/**
* add a contact to a list
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return mixed
*/
public function add_subscriber( $list_identifier, $arguments ) {
if ( ! is_array( $arguments ) ) {
$arguments = (array) $arguments;
}
$merge_tags = array();
if ( ! empty( $arguments['name'] ) ) {
list( $first_name, $last_name ) = $this->get_name_parts( $arguments['name'] );
$merge_tags = array(
'NAME' => $first_name,
'FIRSTNAME' => $first_name,
'SURNAME' => $last_name,
'VORNAME' => $first_name,
'NACHNAME' => $last_name,
'LASTNAME' => $last_name,
);
}
/** @var Thrive_Dash_Api_Sendinblue $api */
$api = $this->get_api();
if ( ! empty( $arguments['phone'] ) ) {
// SendinBlue does not accept phone numbers starting with 0 or other special chars
$the_phone = ltrim( ( preg_replace( '/[^0-9]/', '', $arguments['phone'] ) ), '0' );
$merge_tags['SMS'] = $the_phone;
$merge_tags['PHONE'] = $the_phone;
$merge_tags['TELEFON'] = $the_phone;
}
$data = array(
'email' => $arguments['email'],
'attributes' => array_merge( $merge_tags, $this->_generate_custom_fields( $arguments ) ),
'listid' => array( $list_identifier ),
);
try {
$api->create_update_user( $data );
return true;
} catch ( Thrive_Dash_Api_SendinBlue_Exception $e ) {
return $e->getMessage() ? $e->getMessage() : __( 'Unknown SendinBlue Error', 'thrive-dash' );
} catch ( Exception $e ) {
return $e->getMessage() ? $e->getMessage() : __( 'Unknown Error', 'thrive-dash' );
}
}
/**
* disconnect (remove) this API connection
*/
public function disconnect() {
$this->set_credentials( array() );
Thrive_Dash_List_Manager::save( $this );
/**
* disconnect the email service too
*/
$related_api = Thrive_Dash_List_Manager::connection_instance( 'sendinblueemail' );
$related_api->set_credentials( array() );
Thrive_Dash_List_Manager::save( $related_api );
return $this;
}
/**
* Return the connection email merge tag
*
* @return String
*/
public static function get_email_merge_tag() {
return '{{ contact.EMAIL }}';
}
/**
* @param array $params which may contain `list_id`
* @param bool $force make a call to API and invalidate cache
* @param bool $get_all where to get lists with their custom fields
*
* @return array
*/
public function get_api_custom_fields( $params, $force = false, $get_all = true ) {
$cached_data = $this->get_cached_custom_fields();
if ( false === $force && ! empty( $cached_data ) ) {
return $cached_data;
}
/** @var Thrive_Dash_Api_Sendinblue $api */
$api = $this->get_api();
try {
$attributes = $api->get_attributes();
} catch ( Thrive_Dash_Api_SendinBlue_Exception $e ) {
// Maybe log this
}
$custom_fields = array();
$excluded_fields = array(
'NAME',
'FIRSTNAME',
'SURNAME',
'VORNAME',
'LASTNAME',
'SMS',
'PHONE',
'TELEFON',
);
if ( ! empty( $attributes['data']['normal_attributes'] ) ) {
foreach ( (array) $attributes['data']['normal_attributes'] as $attribute ) {
if ( ! empty( $attribute['type'] ) && ! in_array( $attribute['name'], $excluded_fields ) && 'text' === $attribute['type'] ) {
$custom_fields[] = $this->normalize_custom_field( $attribute );
}
}
}
$this->_save_custom_fields( $custom_fields );
return $custom_fields;
}
/**
* @param array $field
*
* @return array
*/
protected function normalize_custom_field( $field = array() ) {
return array(
'id' => ! empty( $field['name'] ) ? $field['name'] : '',
'name' => ! empty( $field['name'] ) ? $field['name'] : '',
'type' => ! empty( $field['type'] ) ? $field['type'] : '',
'label' => ! empty( $field['name'] ) ? $field['name'] : '',
);
}
/**
* Generate custom fields array
*
* @param array $args
*
* @return array
*/
private function _generate_custom_fields( $args ) {
$custom_fields = $this->get_api_custom_fields( array() );
$ids = $this->build_mapped_custom_fields( $args );
$result = array();
foreach ( $ids as $key => $id ) {
$field = array_filter(
$custom_fields,
function ( $item ) use ( $id ) {
return $item['id'] === $id['value'];
}
);
$field = array_values( $field );
if ( ! isset( $field[0] ) ) {
continue;
}
$name = strpos( $id['type'], 'mapping_' ) !== false ? $id['type'] . '_' . $key : $key;
$cf_form_name = str_replace( '[]', '', $name );
$result[ $field[0]['name'] ] = $this->process_field( $args[ $cf_form_name ] );
}
return $result;
}
/**
* Build mapped custom fields array based on form params
*
* @param $args
*
* @return array
*/
public function build_mapped_custom_fields( $args ) {
$mapped_data = array();
// Should be always base_64 encoded of a serialized array
if ( empty( $args['tve_mapping'] ) || ! tve_dash_is_bas64_encoded( $args['tve_mapping'] ) || ! is_serialized( base64_decode( $args['tve_mapping'] ) ) ) {
return $mapped_data;
}
$form_data = thrive_safe_unserialize( base64_decode( $args['tve_mapping'] ) );
$mapped_fields = $this->get_mapped_field_ids();
foreach ( $mapped_fields as $mapped_field_name ) {
// Extract an array with all custom fields (siblings) names from form data
// {ex: [mapping_url_0, .. mapping_url_n] / [mapping_text_0, .. mapping_text_n]}
$cf_form_fields = preg_grep( "#^{$mapped_field_name}#i", array_keys( $form_data ) );
if ( ! empty( $cf_form_fields ) && is_array( $cf_form_fields ) ) {
foreach ( $cf_form_fields as $cf_form_name ) {
if ( empty( $form_data[ $cf_form_name ][ $this->_key ] ) ) {
continue;
}
$field_id = str_replace( $mapped_field_name . '_', '', $cf_form_name );
$mapped_data[ $field_id ] = array(
'type' => $mapped_field_name,
'value' => $form_data[ $cf_form_name ][ $this->_key ],
);
}
}
}
return $mapped_data;
}
/**
* @param $email
* @param array $custom_fields
* @param array $extra
*
* @return int
*/
public function add_custom_fields( $email, $custom_fields = array(), $extra = array() ) {
try {
/** @var Thrive_Dash_Api_Sendinblue $api */
$api = $this->get_api();
$list_id = ! empty( $extra['list_identifier'] ) ? $extra['list_identifier'] : null;
$args = array(
'email' => $email,
);
if ( ! empty( $extra['name'] ) ) {
$args['name'] = $extra['name'];
}
$this->add_subscriber( $list_id, $args );
$args['attributes'] = $this->prepare_custom_fields_for_api( $custom_fields );
$subscriber = $api->create_update_user( $args );
return ! empty( $subscriber['data']['id'] ) ? $subscriber['data']['id'] : 0;
} catch ( Exception $e ) {
return false;
}
}
/**
* Get available custom fields for this api connection
*
* @param null $list_id
*
* @return array
*/
public function get_available_custom_fields( $list_id = null ) {
return $this->get_api_custom_fields( null, true );
}
/**
* Prepare custom fields for api call
*
* @param array $custom_fields
* @param null $list_identifier
*
* @return array
*/
public function prepare_custom_fields_for_api( $custom_fields = array(), $list_identifier = null ) {
$prepared_fields = array();
$api_fields = $this->get_api_custom_fields( null, true );
foreach ( $api_fields as $field ) {
foreach ( $custom_fields as $key => $custom_field ) {
if ( $custom_field && $field['id'] === $key ) {
$prepared_fields[ $key ] = $custom_field;
}
}
if ( empty( $custom_fields ) ) {
break;
}
}
return $prepared_fields;
}
/**
* Checks if a connection is V3
*
* @return bool
*/
public function is_v3() {
$is_v3 = $this->param( 'v3' );
return ! empty( $is_v3 );
}
/**
* Upgrades a connection from V2 to V3, by generating a V3 key
*
* @return string
*/
public function upgrade() {
$api = $this->get_api();
$api_key = $this->param( 'key' );
$upgrade_response = array();
$related_api = Thrive_Dash_List_Manager::connection_instance( 'sendinblueemail' );
try {
$upgrade_response = $api->upgrade_to_v3( $api_key );
$new_key = $upgrade_response['data']['value'];
$connection = array(
'v3' => true,
'key' => $new_key,
'new_connection' => '0',
);
$this->set_credentials( $connection );
/* Update also the credentials of the related api */
if ( $related_api->is_connected() ) {
$related_api->set_credentials( $connection );
$related_api->save();
}
$this->save();
} catch ( Exception $e ) {
return $e->getMessage();
}
return $upgrade_response;
}
}

View File

@@ -0,0 +1,408 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_SendinblueEmail extends Thrive_Dash_List_Connection_Abstract {
/**
* Return if the connection is in relation with another connection so we won't show it in the API list
*
* @return bool
*/
public function is_related() {
return true;
}
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'email';
}
/**
* @return string the API connection title
*/
public function get_title() {
return 'SendinBlue';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'sendinblueemail' );
}
/**
* should handle: read data from post / get, test connection and save the details
*
* on error, it should register an error message (and redirect?)
*/
public function read_credentials() {
$ajax_call = defined( 'DOING_AJAX' ) && DOING_AJAX;
$key = ! empty( $_POST['connection']['key'] ) ? sanitize_text_field( $_POST['connection']['key'] ) : '';
if ( empty( $key ) ) {
return $ajax_call ? __( 'You must provide a valid SendinBlue key', 'thrive-dash' ) : $this->error( __( 'You must provide a valid SendinBlue key', 'thrive-dash' ) );
}
$this->set_credentials( $this->post( 'connection' ) );
$result = $this->test_connection();
if ( $result !== true ) {
return $ajax_call ? sprintf( __( 'Could not connect to SendinBlue using the provided key (<strong>%s</strong>)', 'thrive-dash' ), $result ) : $this->error( sprintf( __( 'Could not connect to SendinBlue using the provided key (<strong>%s</strong>)', 'thrive-dash' ), $result ) );
}
/**
* finally, save the connection details
*/
$this->save();
/**
* Try to connect to the autoresponder too
*/
/** @var Thrive_Dash_List_Connection_Sendinblue $related_api */
$related_api = Thrive_Dash_List_Manager::connection_instance( 'sendinblue' );
$r_result = true;
if ( ! $related_api->is_connected() ) {
$_POST['connection']['new_connection'] = isset( $_POST['connection']['new_connection'] ) ? absint( $_POST['connection']['new_connection'] ) : 1;
$r_result = $related_api->read_credentials();
}
if ( $r_result !== true ) {
$this->disconnect();
return $this->error( $r_result );
}
$this->success( __( 'SendinBlue connected successfully', 'thrive-dash' ) );
if ( $ajax_call ) {
return true;
}
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
$sendinblue = $this->get_api();
$from_email = get_option( 'admin_email' );
$to = $from_email;
$subject = 'API connection test';
$html_content = 'This is a test email from Thrive Leads SendinBlue API.';
$text_content = 'This is a test email from Thrive Leads SendinBlue API.';
try {
$data = array(
"to" => array( $to => "" ),
"from" => array( $from_email, "" ),
"subject" => $subject,
"html" => $html_content,
"text" => $text_content,
);
$sendinblue->send_email( $data );
} catch ( Exception $e ) {
return $e->getMessage();
}
$connection = get_option( 'tve_api_delivery_service', false );
if ( $connection == false ) {
update_option( 'tve_api_delivery_service', 'sendinblueemail' );
}
return true;
/**
* just try getting a list as a connection test
*/
}
/**
* Send custom email
*
* @param $data
*
* @return bool|string true for success or error message for failure
*/
public function sendCustomEmail( $data ) {
$sendinblue = $this->get_api();
$from_email = get_option( 'admin_email' );
try {
$options = array(
"to" => array( $data['email'] => '' ),
"from" => array( $from_email, "" ),
"subject" => $data['subject'],
'html' => empty ( $data['html_content'] ) ? '' : $data['html_content'],
'text' => empty ( $data['text_content'] ) ? '' : $data['text_content'],
);
$sendinblue->send_email( $options );
} catch ( Exception $e ) {
return $e->getMessage();
}
return true;
}
/**
* Send the same email to multiple addresses
*
* @param $data
*
* @return bool|string
*/
public function sendMultipleEmails( $data ) {
$sendinblue = $this->get_api();
$from_email = get_option( 'admin_email' );
$to = array();
$extra_emails = array();
if ( ! empty( $data['cc'] ) ) {
$extra_emails[] = $data['cc'];
}
if ( ! empty( $data['bcc'] ) ) {
$extra_emails[] = $data['bcc'];
}
foreach ( array_merge( $data['emails'], $extra_emails ) as $email ) {
$to[ $email ] = '';
}
try {
$options = array(
'to' => $to,
'from' => array( $from_email, ! empty( $data['from_name'] ) ? '"' . $data['from_name'] . '"' : "" ),
'subject' => $data['subject'],
'html' => empty ( $data['html_content'] ) ? '' : $data['html_content'],
'replyto' => array( empty ( $data['reply_to'] ) ? '' : $data['reply_to'], "" ),
'text' => empty ( $data['text_content'] ) ? '' : $data['text_content'],
);
$sendinblue->send_email( $options );
} catch ( Exception $e ) {
return $e->getMessage();
}
/* Send confirmation email */
if ( ! empty( $data['send_confirmation'] ) ) {
try {
$options = array(
'to' => array( $data['sender_email'] => '' ),
'from' => array( $from_email, ! empty( $data['from_name'] ) ? '"' . $data['from_name'] . '"' : "" ),
'subject' => $data['confirmation_subject'],
'html' => empty ( $data['confirmation_html'] ) ? '' : $data['confirmation_html'],
'text' => '',
'replyto' => array( $from_email, '' ),
);
$sendinblue->send_email( $options );
} catch ( Exception $e ) {
return $e->getMessage();
}
}
return true;
}
/**
* Send the email to the user
*
* @param $post_data
*
* @return bool|string
* @throws Exception
*
*/
public function sendEmail( $post_data ) {
if ( empty( $post_data['_asset_group'] ) ) {
return true;
}
$sendinblue = $this->get_api();
$asset = get_post( $post_data['_asset_group'] );
if ( empty( $asset ) || ! ( $asset instanceof WP_Post ) || $asset->post_status !== 'publish' ) {
throw new Exception( sprintf( __( 'Invalid Asset Group: %s. Check if it exists or was trashed.', 'thrive-dash' ), $post_data['_asset_group'] ) );
}
$files = get_post_meta( $post_data['_asset_group'], 'tve_asset_group_files', true );
$subject = get_post_meta( $post_data['_asset_group'], 'tve_asset_group_subject', true );
if ( $subject == "" ) {
$subject = get_option( 'tve_leads_asset_mail_subject' );
}
$from_email = get_option( 'admin_email' );
$html_content = $asset->post_content;
if ( $html_content == "" ) {
$html_content = get_option( 'tve_leads_asset_mail_body' );
}
$attached_files = array();
foreach ( $files as $file ) {
$attached_files[] = '<a href="' . $file['link'] . '">' . $file['link_anchor'] . '</a><br/>';
}
$the_files = implode( '<br/>', $attached_files );
$html_content = str_replace( '[asset_download]', $the_files, $html_content );
$html_content = str_replace( '[asset_name]', $asset->post_title, $html_content );
$subject = str_replace( '[asset_name]', $asset->post_title, $subject );
if ( isset( $post_data['name'] ) && ! empty( $post_data['name'] ) ) {
$html_content = str_replace( '[lead_name]', $post_data['name'], $html_content );
$subject = str_replace( '[lead_name]', $post_data['name'], $subject );
$visitor_name = $post_data['name'];
} else {
$from_name = "";
$html_content = str_replace( '[lead_name]', '', $html_content );
$subject = str_replace( '[lead_name]', '', $subject );
$visitor_name = '';
}
$text_content = strip_tags( $html_content );
$data = array(
"to" => array( $post_data['email'] => $visitor_name ),
"from" => array( $from_email, "" ),
"subject" => $subject,
"html" => $html_content,
"text" => $text_content,
);
$result = $sendinblue->send_email( $data );
return $result;
}
/**
* instantiate the API code required for this connection
*
* @return mixed
*/
protected function get_api_instance() {
return new Thrive_Dash_Api_Sendinblue( "https://api.sendinblue.com/v2.0", $this->param( 'key' ) );
}
/**
* get all Subscriber Lists from this API service
*
* @return array|bool for error
*/
protected function _get_lists() {
$sendinblue = $this->get_api();
$data = array(
"page" => 1,
"page_limit" => 50,
);
try {
$lists = array();
$raw = $sendinblue->get_lists( $data );
if ( empty( $raw['data'] ) ) {
return array();
}
foreach ( $raw['data']['lists'] as $item ) {
$lists [] = array(
'id' => $item['id'],
'name' => $item['name'],
);
}
return $lists;
} catch ( Exception $e ) {
$this->_error = $e->getMessage() . ' ' . __( "Please re-check your API connection details.", 'thrive-dash' );
return false;
}
}
/**
* add a contact to a list
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return mixed
*/
public function add_subscriber( $list_identifier, $arguments ) {
list( $first_name, $last_name ) = $this->get_name_parts( $arguments['name'] );
$api = $this->get_api();
$merge_tags = array(
'NAME' => $first_name,
'SURNAME' => $last_name,
);
$data = array(
"email" => $arguments['email'],
"attributes" => $merge_tags,
"listid" => array( $list_identifier ),
);
try {
$api->create_update_user( $data );
return true;
} catch ( Thrive_Dash_Api_SendinBlue_Exception $e ) {
return $e->getMessage() ? $e->getMessage() : __( 'Unknown SendinBlue Error', 'thrive-dash' );
} catch ( Exception $e ) {
return $e->getMessage() ? $e->getMessage() : __( 'Unknown Error', 'thrive-dash' );
}
}
/**
* Return the connection email merge tag
*
* @return String
*/
public static function get_email_merge_tag() {
return '{EMAIL}';
}
/**
* Checks if a connection is V3
*
* @return bool
*/
public function is_v3() {
$is_v3 = $this->param( 'v3' );
return ! empty( $is_v3 );
}
}

View File

@@ -0,0 +1,435 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class Thrive_Dash_List_Connection_SendinblueEmailV3 extends Thrive_Dash_List_Connection_SendinblueEmail {
/**
* Return if the connection is in relation with another connection so we won't show it in the API list
*
* @return bool
*/
public function is_related() {
return true;
}
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'email';
}
/**
* @return string the API connection title
*/
public function get_title() {
return 'SendinBlue';
}
/**
* Output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'sendinblueemail' );
}
/**
* Should handle: read data from post / get, test connection and save the details
*
* on error, it should register an error message (and redirect?)
*/
public function read_credentials() {
$ajax_call = defined( 'DOING_AJAX' ) && DOING_AJAX;
$key = ! empty( $_POST['connection']['key'] ) ? $_POST['connection']['key'] : '';
if ( empty( $key ) ) {
$message = 'You must provide a valid Brevo key';
return $ajax_call ? __( $message, 'thrive-dash' ) : $this->error( __( $message, 'thrive-dash' ) );
}
/* For V3 we need to add this on the credentials list */
$_POST['connection']['v3'] = true;
$this->set_credentials( $_POST['connection'] );
$result = $this->test_connection();
if ( $result !== true ) {
$message = 'Could not connect to Brevo using the provided key (<strong>%s</strong>)';
return $ajax_call ? sprintf( __( $message, 'thrive-dash' ), $result ) : $this->error( sprintf( __( $message, 'thrive-dash' ), $result ) );
}
/**
* finally, save the connection details
*/
$this->save();
/**
* Try to connect to the autoresponder too
*/
/** @var Thrive_Dash_List_Connection_SendinblueV3 $related_api */
$related_api = Thrive_Dash_List_Manager::connection_instance( 'sendinblue' );
$response = true;
if ( ! $related_api->is_connected() ) {
$_POST['connection']['new_connection'] = isset( $_POST['connection']['new_connection'] ) ? $_POST['connection']['new_connection'] : 1;
$response = $related_api->read_credentials();
}
if ( $response !== true ) {
$this->disconnect();
return $this->error( $response );
}
$this->success( __( 'SendinBlue connected successfully', 'thrive-dash' ) );
if ( $ajax_call ) {
return true;
}
}
/**
* Test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
if ( ! $this->is_v3() ) {
return parent::test_connection();
}
$sendinblue = $this->get_api();
$from_email = get_option( 'admin_email' );
$to = $from_email;
$subject = 'API connection test';
$html_content = 'This is a test email from Thrive Leads SendinBlue API.';
$text_content = $html_content;
try {
$data = array(
'to' => array( array( 'email' => $to ) ),
'sender' => array( 'email' => $from_email ),
'subject' => $subject,
'htmlContent' => $html_content,
'textContent' => $text_content,
);
$sendinblue->send_email( $data );
} catch ( Exception $e ) {
return $e->getMessage();
}
$connection = get_option( 'tve_api_delivery_service', false );
if ( $connection === false ) {
update_option( 'tve_api_delivery_service', 'sendinblueemail-v3' );
}
return true;
}
/**
* Send custom email
*
* @param $data
*
* @return bool|string true for success or error message for failure
*/
public function sendCustomEmail( $data ) {
if ( ! $this->is_v3() ) {
return parent::sendCustomEmail( $data );
}
$sendinblue = $this->get_api();
$from_email = get_option( 'admin_email' );
try {
$options = array(
'to' => array( array( 'email' => $data['email'] ) ),
'sender' => array( 'email' => $from_email ),
'subject' => $data['subject'],
);
if ( ! empty ( $data['html_content'] ) ) {
$options['htmlContent'] = $data['html_content'];
}
if ( ! empty ( $data['text_content'] ) ) {
$options['textContent'] = $data['text_content'];
}
$sendinblue->send_email( $options );
} catch ( Exception $e ) {
return $e->getMessage();
}
return true;
}
/**
* Send the same email to multiple addresses
*
* @param $data
*
* @return bool|string
*/
public function sendMultipleEmails( $data ) {
if ( ! $this->is_v3() ) {
return parent::sendMultipleEmails( $data );
}
$sendinblue = $this->get_api();
$from_email = get_option( 'admin_email' );
$to = array();
$extra_emails = array();
foreach ( array_merge( $data['emails'], $extra_emails ) as $email ) {
$to[] = array( 'email' => $email );
}
try {
$options = array(
'to' => $to,
'sender' => array( 'email' => $from_email ),
'subject' => $data['subject'],
'htmlContent' => empty ( $data['html_content'] ) ? '' : $data['html_content'],
);
if ( ! empty ( $data['text_content'] ) ) {
$options['textContent'] = $data['text_content'];
}
if ( ! empty( $data['from_name'] ) ) {
$options['sender']['name'] = $data['from_name'];
}
if ( ! empty( $data['reply_to'] ) ) {
$options['reply_to'] = $data['reply_to'];
}
if ( ! empty( $data['cc'] ) ) {
$options['cc'] = $data['cc'];
}
if ( ! empty( $data['bcc'] ) ) {
$options['bcc'] = $data['bcc'];
}
$sendinblue->send_email( $options );
} catch ( Exception $e ) {
return $e->getMessage();
}
/* Send confirmation email */
if ( ! empty( $data['send_confirmation'] ) ) {
try {
$options = array(
'to' => array( array( 'email' => $data['sender_email'] ) ),
'sender' => array( 'email' => $from_email ),
'subject' => $data['confirmation_subject'],
'htmlContent' => empty ( $data['confirmation_html'] ) ? '' : $data['confirmation_html'],
'replyTo' => array( 'email' => $from_email ),
);
if ( ! empty( $data['from_name'] ) ) {
$options['sender']['name'] = $data['from_name'];
}
if ( ! empty ( $data['text_content'] ) ) {
$options['textContent'] = $data['text_content'];
}
$sendinblue->send_email( $options );
} catch ( Exception $e ) {
return $e->getMessage();
}
}
return true;
}
/**
* Send the email to the user
*
* @param $post_data
*
* @return bool|string
* @throws Exception
*
*/
public function sendEmail( $post_data ) {
if ( ! $this->is_v3() ) {
return parent::sendEmail( $post_data );
}
if ( empty( $post_data['_asset_group'] ) ) {
return true;
}
$sendinblue = $this->get_api();
$asset = get_post( $post_data['_asset_group'] );
if ( empty( $asset ) || ! ( $asset instanceof WP_Post ) || $asset->post_status !== 'publish' ) {
throw new Exception( sprintf( __( 'Invalid Asset Group: %s. Check if it exists or was trashed.', 'thrive-dash' ), $post_data['_asset_group'] ) );
}
$files = get_post_meta( $post_data['_asset_group'], 'tve_asset_group_files', true );
$subject = get_post_meta( $post_data['_asset_group'], 'tve_asset_group_subject', true );
if ( $subject === '' ) {
$subject = get_option( 'tve_leads_asset_mail_subject' );
}
$from_email = get_option( 'admin_email' );
$html_content = $asset->post_content;
if ( $html_content === '' ) {
$html_content = get_option( 'tve_leads_asset_mail_body' );
}
$attached_files = array();
foreach ( $files as $file ) {
$attached_files[] = '<a href="' . $file['link'] . '">' . $file['link_anchor'] . '</a><br/>';
}
$the_files = implode( '<br/>', $attached_files );
$html_content = str_replace( '[asset_download]', $the_files, $html_content );
$html_content = str_replace( '[asset_name]', $asset->post_title, $html_content );
$subject = str_replace( '[asset_name]', $asset->post_title, $subject );
$visitor_name = isset( $post_data['name'] ) && ! empty( $post_data['name'] ) ? $post_data['name'] : '';
$html_content = str_replace( '[lead_name]', $visitor_name, $html_content );
$subject = str_replace( '[lead_name]', $visitor_name, $subject );
$text_content = strip_tags( $html_content );
$to = array( 'email' => $post_data['email'] );
if ( ! empty( $visitor_name ) ) {
$to['name'] = $visitor_name;
}
$data = array(
'to' => array( $to ),
'sender' => array( 'email' => $from_email ),
'subject' => $subject,
'htmlContent' => $html_content,
'textContent' => $text_content,
);
return $sendinblue->send_email( $data );
}
/**
* Instantiate the API code required for this connection
*
* @return Thrive_Dash_Api_SendinblueV3
* @throws Exception
*/
protected function get_api_instance() {
if ( ! $this->is_v3() ) {
return parent::get_api_instance();
}
return new Thrive_Dash_Api_SendinblueV3( 'https://api.sendinblue.com/v3', $this->param( 'key' ) );
}
/**
* Get all Subscriber Lists from this API service
*
* @return array|bool for error
*/
protected function _get_lists() {
if ( ! $this->is_v3() ) {
return parent::_get_lists();
}
$sendinblue = $this->get_api();
$limit = 50;
$offset = 1;
try {
$lists = array();
$raw = $sendinblue->getLists( $limit, $offset );
if ( empty( $raw['data'] ) ) {
return array();
}
foreach ( $raw['data']['lists'] as $item ) {
$lists [] = array(
'id' => $item['id'],
'name' => $item['name'],
);
}
return $lists;
} catch ( Exception $e ) {
$this->_error = $e->getMessage() . ' ' . __( 'Please re-check your API connection details.', 'thrive-dash' );
return false;
}
}
/**
* add a contact to a list
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return bool|string|void
*/
public function add_subscriber( $list_identifier, $arguments ) {
if ( ! $this->is_v3() ) {
return parent::add_subscriber( $list_identifier, $arguments );
}
list( $first_name, $last_name ) = $this->get_name_parts( $arguments['name'] );
$api = $this->get_api();
$merge_tags = array(
'NAME' => $first_name,
'SURNAME' => $last_name,
);
$data = array(
'email' => $arguments['email'],
'attributes' => $merge_tags,
'listid' => array( $list_identifier ),
);
try {
$api->create_update_user( $data );
return true;
} catch ( Thrive_Dash_Api_SendinBlue_Exception $e ) {
return $e->getMessage() ?: __( 'Unknown SendinBlue Error', 'thrive-dash' );
} catch ( Exception $e ) {
return $e->getMessage() ?: __( 'Unknown Error', 'thrive-dash' );
}
}
/**
* Return the connection email merge tag
*
* @return String
*/
public static function get_email_merge_tag() {
return '{EMAIL}';
}
}

View File

@@ -0,0 +1,550 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class Thrive_Dash_List_Connection_SendinblueV3 extends Thrive_Dash_List_Connection_Sendinblue {
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'autoresponder';
}
/**
* @return string the API connection title
*/
public function get_title() {
return 'Brevo';
}
/**
* Output the setup form html
*
* @return void
*/
public function output_setup_form() {
$related_api = Thrive_Dash_List_Manager::connection_instance( 'sendinblueemail' );
if ( $related_api->is_connected() ) {
$this->set_param( 'new_connection', 1 );
}
$this->output_controls_html( 'sendinblue-v3' );
}
/**
* should handle: read data from post / get, test connection and save the details
*
* on error, it should register an error message (and redirect?)
*/
public function read_credentials() {
$ajax_call = defined( 'DOING_AJAX' ) && DOING_AJAX;
$key = ! empty( $_POST['connection']['key'] ) ? $_POST['connection']['key'] : '';
if ( empty( $key ) ) {
$message = 'You must provide a valid Brevo key';
return $ajax_call ? __( $message, 'thrive-dash' ) : $this->error( __( $message, 'thrive-dash' ) );
}
$this->set_credentials( $_POST['connection'] );
$result = $this->test_connection();
if ( $result !== true ) {
$message = 'Could not connect to Brevo using the provided key (<strong>%s</strong>)';
return $ajax_call ? sprintf( __( $message, 'thrive-dash' ), $result ) : $this->error( sprintf( __( $message, 'thrive-dash' ), $result ) );
}
/**
* finally, save the connection details
*/
$this->save();
/** @var Thrive_Dash_List_Connection_SendinblueEmail $related_api */
$related_api = Thrive_Dash_List_Manager::connection_instance( 'sendinblueemail' );
if ( isset( $_POST['connection']['new_connection'] ) && (int) $_POST['connection']['new_connection'] ) {
/**
* Try to connect to the email service too
*/
$r_result = true;
if ( ! $related_api->is_connected() ) {
$r_result = $related_api->read_credentials();
}
if ( $r_result !== true ) {
$this->disconnect();
return $this->error( $r_result );
}
} else {
/**
* let's make sure that the api was not edited and disconnect it
*/
$related_api->set_credentials( array() );
Thrive_Dash_List_Manager::save( $related_api );
}
$this->success( __( 'Brevo connected successfully', 'thrive-dash' ) );
if ( $ajax_call ) {
return true;
}
}
/**
* Test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
if ( ! $this->is_v3() ) {
return parent::test_connection();
}
$sendinblue = $this->get_api();
try {
$sendinblue->getAccount();
} catch ( Exception $e ) {
return $e->getMessage();
}
return true;
}
/**
* Instantiate the API code required for this connection
*
* @return Thrive_Dash_Api_SendinblueV3
* @throws Exception
*/
protected function get_api_instance() {
if ( ! $this->is_v3() ) {
return parent::get_api_instance();
}
return new Thrive_Dash_Api_SendinblueV3( 'https://api.sendinblue.com/v3', $this->param( 'key' ) );
}
/**
* Get all Subscriber Lists from this API service
*
* @return array|bool for error
*/
protected function _get_lists() {
if ( ! $this->is_v3() ) {
return parent::_get_lists();
}
/** @var Thrive_Dash_Api_Sendinblue $sendinblue */
$sendinblue = $this->get_api();
$data = array(
'limit' => 50,
'offset' => 0,
);
try {
$lists = array();
$raw = $sendinblue->getLists( $data );
if ( empty( $raw['lists'] ) ) {
return array();
}
if ( ! empty( $raw['count'] ) && $raw['count'] > $data['limit'] ) {
$total_loaded = count( $raw['lists'] );
$remaining_pages = (int) ( $raw['count'] / $data['limit'] ) + 1;
if ( $remaining_pages >= 2 ) {
for ( $i = 2; $i <= $remaining_pages; $i ++ ) {
$data['offset'] = $total_loaded;
$response = $sendinblue->getLists( $data );
if ( isset( $response['lists'] ) && is_array( $response['lists'] ) ) {
$raw['lists'] = array_merge( $raw['lists'], $response['lists'] );
}
$total_loaded = count( $raw['lists'] );
}
}
}
foreach ( $raw['lists'] as $item ) {
$lists [] = array(
'id' => $item['id'],
'name' => $item['name'],
);
}
return $lists;
} catch ( Exception $e ) {
$this->_error = $e->getMessage() . ' ' . __( 'Please re-check your API connection details.', 'thrive-dash' );
return false;
}
}
/**
* Add a contact to a list
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return mixed
*/
public function add_subscriber( $list_identifier, $arguments ) {
if ( ! is_array( $arguments ) ) {
$arguments = (array) $arguments;
}
if ( ! $this->is_v3() ) {
return parent::add_subscriber( $list_identifier, $arguments );
}
$merge_tags = array();
if ( ! empty( $arguments['name'] ) ) {
list( $first_name, $last_name ) = $this->get_name_parts( $arguments['name'] );
$merge_tags = array(
'NAME' => $first_name,
'FIRSTNAME' => $first_name,
'SURNAME' => $last_name,
'VORNAME' => $first_name,
'NACHNAME' => $last_name,
'LASTNAME' => $last_name,
'NOM' => $last_name,
'PRENOM' => $first_name,
);
}
/** @var Thrive_Dash_Api_SendinblueV3 $api */
$api = $this->get_api();
if ( ! empty( $arguments['phone'] ) ) {
// SendinBlue does not accept phone numbers starting with 0 or other special chars
$the_phone = ltrim( ( preg_replace( '/[^0-9]/', '', $arguments['phone'] ) ), '0' );
$merge_tags['SMS'] = $the_phone;
$merge_tags['PHONE'] = $the_phone;
$merge_tags['TELEFON'] = $the_phone;
}
if ( empty( $arguments['automator_custom_fields'] ) ) {
$attributes = array_merge( $merge_tags, $this->_generate_custom_fields( $arguments ) );
} else {
$attributes = array_merge( $merge_tags, $arguments['automator_custom_fields'] );
}
$data = array(
'email' => $arguments['email'],
'listIds' => array( (int) $list_identifier ),
'updateEnabled' => true,
);
if ( ! empty( $attributes ) ) {
$data['attributes'] = $attributes;
}
try {
$api->create_update_user( $data );
return true;
} catch ( Exception $e ) {
return $e->getMessage() ?: __( 'Unknown Error', 'thrive-dash' );
}
}
/**
* Disconnect (remove) this API connection
*/
public function disconnect() {
if ( ! $this->is_v3() ) {
return parent::disconnect();
}
$this->set_credentials( array() );
Thrive_Dash_List_Manager::save( $this );
/**
* disconnect the email service too
*/
$related_api = Thrive_Dash_List_Manager::connection_instance( 'sendinblueemail' );
$related_api->set_credentials( array() );
Thrive_Dash_List_Manager::save( $related_api );
return $this;
}
/**
* Return the connection email merge tag
*
* @return String
*/
public static function get_email_merge_tag() {
return '{{ contact.EMAIL }}';
}
/**
* @param array $params which may contain `list_id`
* @param bool $force make a call to API and invalidate cache
* @param bool $get_all where to get lists with their custom fields
*
* @return array
*/
public function get_api_custom_fields( $params, $force = false, $get_all = true ) {
if ( ! $this->is_v3() ) {
return parent::get_api_custom_fields( $params, $force, $get_all );
}
$cached_data = $this->get_cached_custom_fields();
if ( false === $force && ! empty( $cached_data ) ) {
return $cached_data;
}
/** @var Thrive_Dash_Api_Sendinblue $api */
$api = $this->get_api();
try {
$attributes = $api->get_attributes();
} catch ( Thrive_Dash_Api_SendinBlue_Exception $e ) {
// Maybe log this
}
$custom_fields = array();
$excluded_fields = array(
'NAME',
'FIRSTNAME',
'SURNAME',
'VORNAME',
'LASTNAME',
'SMS',
'PHONE',
'TELEFON',
);
if ( ! empty( $attributes['attributes'] ) ) {
foreach ( $attributes['attributes'] as $attribute ) {
if ( ! empty( $attribute['category'] ) && $attribute['category'] === 'normal' && ! empty( $attribute['type'] ) && ! in_array( $attribute['name'], $excluded_fields ) && 'text' === $attribute['type'] ) {
$custom_fields[] = $this->normalize_custom_field( $attribute );
}
}
}
$this->_save_custom_fields( $custom_fields );
return $custom_fields;
}
/**
* @param array $field
*
* @return array
*/
protected function normalize_custom_field( $field = array() ) {
return array(
'id' => ! empty( $field['name'] ) ? $field['name'] : '',
'name' => ! empty( $field['name'] ) ? $field['name'] : '',
'type' => ! empty( $field['type'] ) ? $field['type'] : '',
'label' => ! empty( $field['name'] ) ? $field['name'] : '',
);
}
/**
* Generate custom fields array
*
* @param array $args
*
* @return array
*/
private function _generate_custom_fields( $args ) {
$custom_fields = $this->get_api_custom_fields( array() );
$ids = $this->build_mapped_custom_fields( $args );
$result = array();
foreach ( $ids as $key => $id ) {
$field = array_filter(
$custom_fields,
function ( $item ) use ( $id ) {
return $item['id'] === $id['value'];
}
);
$field = array_values( $field );
if ( ! isset( $field[0] ) ) {
continue;
}
$name = strpos( $id['type'], 'mapping_' ) !== false ? $id['type'] . '_' . $key : $key;
$cf_form_name = str_replace( '[]', '', $name );
$result[ $field[0]['name'] ] = $this->process_field( $args[ $cf_form_name ] );
}
return $result;
}
/**
* Build custom fields mapping for automations
*
* @param $automation_data
*
* @return object
*/
public function build_automation_custom_fields( $automation_data ) {
$mapped_data = [];
$fields = $this->get_api_custom_fields( array() );
foreach ( $automation_data['api_fields'] as $pair ) {
foreach ( $fields as $field ) {
if ( $field['id'] == $pair['key'] ) {
$value = sanitize_text_field( $pair['value'] );
if ( $value ) {
$mapped_data[ $field['name'] ] = $value;
}
}
}
}
return $mapped_data;
}
/**
* Build mapped custom fields array based on form params
*
* @param $args
*
* @return array
*/
public function build_mapped_custom_fields( $args ) {
$mapped_data = array();
// Should be always base_64 encoded of a serialized array
if ( empty( $args['tve_mapping'] ) || ! tve_dash_is_bas64_encoded( $args['tve_mapping'] ) ) {
return $mapped_data;
}
$form_data = thrive_safe_unserialize( base64_decode( $args['tve_mapping'] ) );
$mapped_fields = $this->get_mapped_field_ids();
foreach ( $mapped_fields as $mapped_field_name ) {
// Extract an array with all custom fields (siblings) names from form data
// {ex: [mapping_url_0, .. mapping_url_n] / [mapping_text_0, .. mapping_text_n]}
$cf_form_fields = preg_grep( "#^{$mapped_field_name}#i", array_keys( $form_data ) );
if ( ! empty( $cf_form_fields ) && is_array( $cf_form_fields ) ) {
foreach ( $cf_form_fields as $cf_form_name ) {
if ( empty( $form_data[ $cf_form_name ][ $this->_key ] ) ) {
continue;
}
$field_id = str_replace( $mapped_field_name . '_', '', $cf_form_name );
$mapped_data[ $field_id ] = array(
'type' => $mapped_field_name,
'value' => $form_data[ $cf_form_name ][ $this->_key ],
);
}
}
}
return $mapped_data;
}
/**
* @param $email
* @param array $custom_fields
* @param array $extra
*
* @return int
*/
public function add_custom_fields( $email, $custom_fields = array(), $extra = array() ) {
if ( ! $this->is_v3() ) {
return parent::add_custom_fields( $email, $custom_fields = array(), $extra = array() );
}
try {
/** @var Thrive_Dash_Api_Sendinblue $api */
$api = $this->get_api();
$list_id = ! empty( $extra['list_identifier'] ) ? $extra['list_identifier'] : null;
$args = array(
'email' => $email,
);
if ( ! empty( $extra['name'] ) ) {
$args['name'] = $extra['name'];
}
$this->add_subscriber( $list_id, $args );
$args['attributes'] = $this->prepare_custom_fields_for_api( $custom_fields );
$subscriber = $api->create_update_user( $args );
return ! empty( $subscriber['data']['id'] ) ? $subscriber['data']['id'] : 0;
} catch ( Exception $e ) {
return false;
}
}
/**
* Get available custom fields for this api connection
*
* @param null $list_id
*
* @return array
*/
public function get_available_custom_fields( $list_id = null ) {
return $this->get_api_custom_fields( null, true );
}
/**
* Prepare custom fields for api call
*
* @param array $custom_fields
* @param null $list_identifier
*
* @return array
*/
public function prepare_custom_fields_for_api( $custom_fields = array(), $list_identifier = null ) {
$prepared_fields = array();
$api_fields = $this->get_api_custom_fields( null, true );
foreach ( $api_fields as $field ) {
foreach ( $custom_fields as $key => $custom_field ) {
if ( $custom_field && $field['id'] === $key ) {
$prepared_fields[ $key ] = $custom_field;
}
}
if ( empty( $custom_fields ) ) {
break;
}
}
return $prepared_fields;
}
public function get_automator_add_autoresponder_mapping_fields() {
return array( 'autoresponder' => array( 'mailing_list', 'api_fields' ) );
}
public function has_custom_fields() {
return true;
}
}

View File

@@ -0,0 +1,172 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_Sendlane extends Thrive_Dash_List_Connection_Abstract {
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'autoresponder';
}
/**
* @return string
*/
public function get_title() {
return 'SendLane';
}
/**
* @return bool
*/
public function has_tags() {
return true;
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'sendlane' );
}
/**
* @return mixed|Thrive_Dash_List_Connection_Abstract
*/
public function read_credentials() {
$connection = $this->post( 'connection', array() );
if ( empty( $connection['api_url'] ) || empty( $connection['api_key'] ) || empty( $connection['hash_key'] ) ) {
return $this->error( __( 'All fields are required!', 'thrive-dash' ) );
}
$this->set_credentials( $connection );
$result = $this->test_connection();
if ( $result !== true ) {
return $this->error( __( 'Could not connect to SendLane using the provided details', 'thrive-dash' ) );
}
/**
* finally, save the connection details
*/
$this->save();
return $this->success( __( 'SendLane connected successfully', 'thrive-dash' ) );
}
/**
* @return bool
*/
public function test_connection() {
return is_array( $this->_get_lists() );
}
/**
* @return mixed|Thrive_Dash_Api_Sendlane
* @throws Thrive_Dash_Api_Sendlane_Exception
*/
protected function get_api_instance() {
$api_url = $this->param( 'api_url' );
$api_key = $this->param( 'api_key' );
$hash_key = $this->param( 'hash_key' );
return new Thrive_Dash_Api_Sendlane( $api_key, $hash_key, $api_url );
}
/**
* @return array|bool
*/
protected function _get_lists() {
/** @var Thrive_Dash_Api_Sendlane $api */
$api = $this->get_api();
$result = $api->call( 'lists' );
$api->setConnectionStatus( $result['status'] );
/**
* Invalid connection
*/
if ( ! isset( $result['data'] ) || ! is_array( $result['data'] ) ) {
return false;
}
/**
* Valid connection but no lists found
*/
if ( isset( $result['data']['info'] ) ) {
return array();
}
/**
* Add id and name fields for each list
*/
foreach ( $result['data'] as $key => $list ) {
$result['data'][ $key ]['id'] = $list['list_id'];
$result['data'][ $key ]['name'] = $list['list_name'];
}
return $result['data'];
}
/**
* @param mixed $list_identifier
* @param array $arguments
*
* @return mixed|string
*/
public function add_subscriber( $list_identifier, $arguments ) {
$name_array = array();
if ( ! empty( $arguments['name'] ) ) {
list( $first_name, $last_name ) = $this->get_name_parts( $arguments['name'] );
$name_array = array(
'first_name' => $first_name,
'last_name' => $last_name,
);
}
/** @var Thrive_Dash_Api_Sendlane $api */
$api = $this->get_api();
$args = array(
'list_id' => $list_identifier,
'email' => $arguments['email'],
);
$args = array_merge( $args, $name_array );
if ( isset( $arguments['sendlane_tags'] ) ) {
$args['tag_names'] = trim( $arguments['sendlane_tags'] );
}
if ( isset( $arguments['phone'] ) ) {
$args['phone'] = $arguments['phone'];
}
return $api->call( 'list-subscriber-add', $args );
}
/**
* Return the connection email merge tag
*
* @return String
*/
public static function get_email_merge_tag() {
return 'VAR_EMAIL';
}
public function get_automator_add_autoresponder_mapping_fields() {
return array( 'autoresponder' => array( 'mailing_list', 'api_fields', 'tag_input' ) );
}
}

View File

@@ -0,0 +1,159 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_Sendy extends Thrive_Dash_List_Connection_Abstract {
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'autoresponder';
}
/**
* @return string the API connection title
*/
public function get_title() {
return 'Sendy';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'sendy' );
}
/**
* should handle: read data from post / get, test connection and save the details
*
* on error, it should register an error message (and redirect?)
*
* @return mixed
*/
public function read_credentials() {
$url = ! empty( $_POST['connection']['url'] ) ? sanitize_text_field( $_POST['connection']['url'] ) : '';
$lists = ! empty( $_POST['connection']['lists'] ) ? array_map( 'sanitize_text_field', $_POST['connection']['lists'] ) : array();
$lists = array_map( 'trim', $lists );
$lists = array_filter( $lists );
if ( empty( $url ) || empty( $lists ) ) {
return $this->error( 'Invalid URL or Lists IDs' );
}
$_POST['connection']['lists'] = $lists;
$this->set_credentials( $this->post( 'connection' ) );
$result = $this->test_connection();
if ( $result !== true ) {
return $this->error( __( 'Could not connect to Sendy', 'thrive-dash' ) );
}
$this->save();
return $this->success( 'Sendy connected successfully' );
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
/** @var Thrive_Dash_Api_Sendy $api */
$api = $this->get_api();
return $api->testUrl();
}
/**
* instantiate the API code required for this connection
*
* @return mixed
*/
protected function get_api_instance() {
return new Thrive_Dash_Api_Sendy( $this->param( 'url' ) );
}
/**
* get all Subscriber Lists from this API service
*
* @return array|bool for error
*/
protected function _get_lists() {
$lists = array();
foreach ( $this->param( 'lists' ) as $id ) {
$lists[] = array(
'id' => $id,
'name' => "#" . $id,
);
}
return $lists;
}
/**
* add a contact to a list
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return mixed
*/
public function add_subscriber( $list_identifier, $arguments ) {
/** @var Thrive_Dash_Api_Sendy $api */
$api = new Thrive_Dash_Api_Sendy( $this->param( 'url' ) );
try {
$api->subscribe( $arguments['email'], $list_identifier, $arguments['name'], $phone = isset( $arguments['phone'] ) ? $arguments['phone'] : null );
return true;
} catch ( Exception $e ) {
return $e->getMessage();
}
return false;
}
/**
* output any (possible) extra editor settings for this API
*
* @param array $params allow various different calls to this method
*/
public function get_extra_settings( $params = array() ) {
return $params;
}
/**
* output any (possible) extra editor settings for this API
*
* @param array $params allow various different calls to this method
*/
public function render_extra_editor_settings( $params = array() ) {
$this->output_controls_html( 'sendy/note', $params );
}
/**
* Return the connection email merge tag
*
* @return String
*/
public static function get_email_merge_tag() {
return '[Email]';
}
}

View File

@@ -0,0 +1,176 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_Slack extends Thrive_Dash_List_Connection_Abstract {
const SERVICE_URL = 'https://service-api.thrivethemes.com/integrations/slack';
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'collaboration';
}
/**
* get the authorization URL for the Slack Application
*
* @return string
*/
public function get_authorize_url() {
$query_params = [
'redirect_uri' => admin_url( 'admin.php?page=tve_dash_api_connect&api=slack' ),
];
$query_params['p'] = $this->calc_hash( $query_params );
$query_params = http_build_query(
$query_params,
'&'
);
$slack_url = defined( 'TD_SERVICE_API_URL' ) ? rtrim(TD_SERVICE_API_URL, '/') . '/integrations/slack' : static::SERVICE_URL;
return sprintf(
'%s%s%s',
$slack_url,
false === strpos( $slack_url, '?' ) ? '?' : '&',
$query_params
);
}
public function calc_hash( $data ) {
$secret_key = '@#$()%*%$^&*(#@$%@#$%93827456MASDFJIK3245';
return md5( $secret_key . serialize( $data ) . $secret_key );
}
/**
* @return bool|void
*/
public function is_connected() {
return ! empty( $this->param( 'token' ) );
}
/**
* @return string the API connection title
*/
public function get_title() {
return 'Slack';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'slack' );
}
/**
* should handle: read data from post / get, test connection and save the details
*
* on error, it should register an error message (and redirect?)
*
* @return mixed
*/
public function read_credentials() {
$slack = $this->get_api();
try {
$access_token = $slack->get_access_token();
$this->set_credentials( array(
'token' => $access_token,
) );
} catch ( Exception $e ) {
$this->error( $e->getMessage() );
return false;
}
$result = $this->test_connection();
if ( $result !== true ) {
$this->error( sprintf( __( 'Could not test Slack connection: %s', 'thrive-dash' ), $result ) );
return false;
}
$this->save();
return true;
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
$slack = $this->get_api();
try {
return $slack->verify_token( $this->param( 'token' ) );
} catch ( Exception $e ) {
return $e->getMessage();
}
}
/**
* instantiate the API code required for this connection
*
* @return mixed
*/
protected function get_api_instance() {
return new Thrive_Dash_Api_Slack();
}
public function _get_lists() {
return false;
}
public function add_subscriber( $list_identifier, $arguments ) {
return false;
}
public function get_channel_list() {
$slack = $this->get_api();
$credentials = $this->get_credentials();
if ( ! empty( $credentials['token'] ) ) {
return $slack->get_channel_list( $credentials['token'] );
}
return [];
}
public function post_message( $channel, $args ) {
$slack = $this->get_api();
$credentials = $this->get_credentials();
if ( ! empty( $credentials['token'] ) ) {
return $slack->post_message( $credentials['token'], $channel, $args );
}
return [];
}
public function custom_success_message() {
$link = '<a href="http://help.thrivethemes.com/en/articles/6593007-how-to-set-up-a-notification-in-slack-using-thrive-automator">' . __( 'See how this is done', 'thrive-dash' ) . '</a>';
return __( 'You can now use Slack actions in Thrive Automator', 'thrive-dash' ) .' '. $link;
}
}

View File

@@ -0,0 +1,386 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_SparkPost extends Thrive_Dash_List_Connection_Abstract {
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'email';
}
/**
* @return string the API connection title
*/
public function get_title() {
return 'SparkPost';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'sparkpost' );
}
/**
* should handle: read data from post / get, test connection and save the details
*
* on error, it should register an error message (and redirect?)
*/
public function read_credentials() {
$key = ! empty( $_POST['connection']['key'] ) ? sanitize_text_field( $_POST['connection']['key'] ) : '';
$email = ! empty( $_POST['connection']['domain'] ) ? sanitize_text_field( $_POST['connection']['domain'] ) : '';
if ( empty( $key ) ) {
return $this->error( __( 'You must provide a valid SparkPost key', 'thrive-dash' ) );
}
if ( empty( $email ) ) {
return $this->error( __( 'Email field must not be empty', 'thrive-dash' ) );
}
$this->set_credentials( $this->post( 'connection' ) );
$result = $this->test_connection();
if ( $result !== true ) {
return $this->error( sprintf( __( 'Could not connect to SparkPost using the provided key. <strong>%s</strong>', 'thrive-dash' ), $result ) );
}
/**
* finally, save the connection details
*/
$this->save();
return $this->success( __( 'SparkPost connected successfully', 'thrive-dash' ) );
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
$sparkpost = $this->get_api();
if ( isset( $_POST['connection']['domain'] ) ) {
$domain = sanitize_text_field( $_POST['connection']['domain'] );
} else {
$credentials = Thrive_Dash_List_Manager::credentials( 'sparkpost' );
if ( isset( $credentials ) ) {
$domain = $credentials['domain'];
}
}
$to = get_option( 'admin_email' );
$subject = 'API connection test';
$html_content = 'This is a test email from Thrive Leads SparkPost API.';
$text_content = 'This is a test email from Thrive Leads SparkPost API.';
try {
$options = array(
'from' => $domain,
'html' => $html_content,
'text' => $text_content,
'subject' => $subject,
'recipients' => array(
array(
'address' => array(
'email' => $to,
),
),
),
);
$sparkpost->transmission->send( $options );
} catch ( Thrive_Dash_Api_SparkPost_Exception $e ) {
return $e->getMessage();
}
$connection = get_option( 'tve_api_delivery_service', false );
if ( $connection == false ) {
update_option( 'tve_api_delivery_service', 'sparkpost' );
}
return true;
/**
* just try getting a list as a connection test
*/
}
/**
* Send custom email
*
* @param $data
*
* @return bool|string true for success or error message for failure
*/
public function sendCustomEmail( $data ) {
$sparkpost = $this->get_api();
$credentials = Thrive_Dash_List_Manager::credentials( 'sparkpost' );
if ( isset( $credentials ) ) {
$domain = $credentials['domain'];
}
try {
$options = array(
'from' => $domain,
'html' => empty ( $data['html_content'] ) ? '' : $data['html_content'],
'text' => empty ( $data['text_content'] ) ? '' : $data['text_content'],
'subject' => $data['subject'],
'recipients' => array(
array(
'address' => array(
'email' => $data['email'],
),
),
),
);
$sparkpost->transmission->send( $options );
} catch ( Thrive_Dash_Api_SparkPost_Exception $e ) {
return $e->getMessage();
}
return true;
}
/**
* Send the same email to multiple addresses
*
* @param $data
*
* @return bool|string
*/
public function sendMultipleEmails( $data ) {
$sparkpost = $this->get_api();
$credentials = Thrive_Dash_List_Manager::credentials( 'sparkpost' );
if ( isset( $credentials ) ) {
$from_email = $credentials['domain'];
}
$recipients = $this->_prepareRecipients( $data );
if ( ! empty( $data['from_name'] ) ) {
$domain = [
'name' => $data['from_name'],
'email' => $from_email,
];
} else {
$domain = $from_email;
}
try {
$options = array(
'from' => $domain,
'html' => empty ( $data['html_content'] ) ? '' : $data['html_content'],
'text' => empty ( $data['text_content'] ) ? '' : $data['text_content'],
'subject' => $data['subject'],
'recipients' => $recipients,
);
if ( ! empty( $data['reply_to'] ) ) {
$options['replyTo'] = $data['reply_to'];
}
$sparkpost->transmission->send( $options );
} catch ( Thrive_Dash_Api_SparkPost_Exception $e ) {
return $e->getMessage();
}
if ( ! empty( $data['send_confirmation'] ) ) {
try {
$confirmation = array(
'from' => $domain,
'html' => empty ( $data['confirmation_html'] ) ? '' : $data['confirmation_html'],
'text' => '',
'subject' => $data['confirmation_subject'],
'recipients' => array(
array(
'address' => array(
'email' => $data['sender_email'],
),
),
),
'replyTo' => $from_email,
);
$sparkpost->transmission->send( $confirmation );
} catch ( Thrive_Dash_Api_SparkPost_Exception $e ) {
return $e->getMessage();
}
}
return true;
}
/**
* Prepare email recipients
*
* @param array $data
*
* @return array
*/
private function _prepareRecipients( $data ) {
$recipients = array();
$first_email = current( $data['emails'] );
$data['cc'] = ! empty( $data['cc'] ) ? $data['cc'] : array();
$data['bcc'] = ! empty( $data['bcc'] ) ? $data['bcc'] : array();
$extra = array_merge( $data['cc'], $data['bcc'] );
foreach ( array_unique( $data['emails'] ) as $email ) {
$recipients[] = array(
'address' => array(
'email' => $email,
),
);
}
foreach ( array_unique( $extra ) as $email ) {
$recipients[] = array(
'address' => array(
'email' => $email,
'header_to' => $first_email,
),
);
}
return $recipients;
}
/**
* Send the email to the user
*
* @param $post_data
*
* @return bool|string
* @throws Exception
*
*/
public function sendEmail( $post_data ) {
$sparkpost = $this->get_api();
$credentials = $this->get_credentials();
if ( empty( $post_data['_asset_group'] ) ) {
return false;
}
$asset = get_post( $post_data['_asset_group'] );
if ( empty( $asset ) || ! ( $asset instanceof WP_Post ) || $asset->post_status !== 'publish' ) {
throw new Exception( sprintf( __( 'Invalid Asset Group: %s. Check if it exists or was trashed.', 'thrive-dash' ), $post_data['_asset_group'] ) );
}
$files = get_post_meta( $post_data['_asset_group'], 'tve_asset_group_files', true );
$subject = get_post_meta( $post_data['_asset_group'], 'tve_asset_group_subject', true );
if ( $subject == "" ) {
$subject = get_option( 'tve_leads_asset_mail_subject' );
}
$from = $credentials['domain'];
$html_content = $asset->post_content;
if ( $html_content == "" ) {
$html_content = get_option( 'tve_leads_asset_mail_body' );
}
$attached_files = array();
foreach ( $files as $file ) {
$attached_files[] = '<a href="' . $file['link'] . '">' . $file['link_anchor'] . '</a><br/>';
}
$the_files = implode( '<br/>', $attached_files );
$html_content = str_replace( '[asset_download]', $the_files, $html_content );
$html_content = str_replace( '[asset_name]', $asset->post_title, $html_content );
$subject = str_replace( '[asset_name]', $asset->post_title, $subject );
if ( isset( $post_data['name'] ) && ! empty( $post_data['name'] ) ) {
$html_content = str_replace( '[lead_name]', $post_data['name'], $html_content );
$subject = str_replace( '[lead_name]', $post_data['name'], $subject );
$visitor_name = $post_data['name'];
} else {
$html_content = str_replace( '[lead_name]', '', $html_content );
$subject = str_replace( '[lead_name]', '', $subject );
$visitor_name = '';
}
$text_content = strip_tags( $html_content );
$options = array(
'from' => $from,
'html' => $html_content,
'text' => $text_content,
'subject' => $subject,
'options' => array(),
'recipients' => array(
array(
'address' => array(
'email' => $post_data['email'],
),
),
),
);
$result = $sparkpost->transmission->send( $options );
return $result;
}
/**
* instantiate the API code required for this connection
*
* @return mixed
*/
protected function get_api_instance() {
return new Thrive_Dash_Api_SparkPost( $this->param( 'key' ) );
}
/**
* get all Subscriber Lists from this API service
*
* @return array|bool for error
*/
protected function _get_lists() {
}
/**
* add a contact to a list
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return mixed
*/
public function add_subscriber( $list_identifier, $arguments ) {
}
/**
* Get from email value
*
* @return string
*/
public function get_email_param() {
return $this->param( 'domain' );
}
}

View File

@@ -0,0 +1,246 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_Turnstile extends Thrive_Dash_List_Connection_Abstract {
public function __construct( $key ) {
parent::__construct( $key );
add_filter( 'tcb_spam_prevention_tools', [ $this, 'add_spam_prevention_tool' ] );
add_action( 'tve_load_turnstile', [ $this, 'enqueue_turnstile_scripts' ] );
}
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'recaptcha';
}
/**
* @return string the API connection title
*/
public function get_title() {
return 'Turnstile';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
do_action( 'tve_load_turnstile' );
$this->output_controls_html( 'turnstile' );
}
public function enqueue_turnstile_scripts() {
tve_dash_enqueue_script( 'tve-dash-turnstile', 'https://challenges.cloudflare.com/turnstile/v0/api.js' );
}
/**
* should handle: read data from post / get, test connection and save the details
*
* on error, it should register an error message (and redirect?)
*
* @return mixed
*/
public function read_credentials() {
$site = ! empty( $_POST['site_key'] ) ? sanitize_text_field( $_POST['site_key'] ) : '';
$secret = ! empty( $_POST['secret_key'] ) ? sanitize_text_field( $_POST['secret_key'] ) : '';
$token = ! empty( $_POST['api_token'] ) ? sanitize_text_field( $_POST['api_token'] ) : '';
$theme = ! empty( $_POST['theme'] ) ? sanitize_text_field( $_POST['theme'] ) : '';
$language = ! empty( $_POST['language'] ) ? sanitize_text_field( $_POST['language'] ) : '';
$appearance = ! empty( $_POST['appearance'] ) ? sanitize_text_field( $_POST['appearance'] ) : '';
$size = ! empty( $_POST['size'] ) ? sanitize_text_field( $_POST['size'] ) : '';
//extra i believe we don't need following fields for api call
if ( empty( $site ) || empty( $secret ) ) {
return $this->error( __( 'Both Site Key and Secret Key fields are required', 'thrive-dash' ) );
}
//recreate credential object
$credentials = array(
'connection' => $this->post( 'connection' ),
'site_key' => $site,
'secret_key' => $secret,
'api_token' => $token,
'theme' => $theme,
'language' => $language,
'appearance' => $appearance,
'size' => $size,
);
$old_token = $this->param( 'api_token' );
$this->set_credentials( $credentials );
if ( strcmp( $old_token, $token ) !== 0 ) {
if ( empty( $token ) ) {
return $this->error( __( 'Token is missing!', 'thrive-dash' ) );
}
$result = $this->test_connection();
if ( $result !== true ) {
$errorMessage = ! empty( $result['message'] ) ? $result['message'] : __( 'Incorrect Secret Key.', 'thrive-dash' );
return $this->error( sprintf( $errorMessage, $result ) );
}
}
/**
* finally, save the connection details
*/
$this->save();
return $this->success( __( 'Turnstile connected successfully!', 'thrive-dash' ) );
}
/**
* test if the secret key is correct and it exists.
*
* @return bool|array true for success or error details array for failure
*/
public function test_connection() {
$CAPTCHA_URL = 'https://challenges.cloudflare.com/turnstile/v0/siteverify';
$_capthca_params = array(
'response' => $this->param( 'api_token' ),
'secret' => $this->param( 'secret_key' ),
);
$request = tve_dash_api_remote_post( $CAPTCHA_URL, array( 'body' => $_capthca_params ) );
$response = json_decode( wp_remote_retrieve_body( $request ), true );
if ( ! empty( $response['error-codes'] ) ) {
$errorLists = $this->getErrorLists();
foreach ( $response['error-codes'] as $errorCode ) {
if ( 'timeout-or-duplicate' === $errorCode ) {
break;
}
if ( ! empty( $errorLists[ $errorCode ] ) ) {
return array(
'success' => false,
'message' => $errorLists[ $errorCode ],
'code' => $errorCode,
);
}
}
}
return true;
}
public function getErrorLists() {
$errorLists = array(
'missing-input-secret' => __( 'The secret parameter was not passed', 'thrive-dash' ),
'invalid-input-secret' => __( 'The secret parameter was invalid or did not exist', 'thrive-dash' ),
'missing-input-response' => __( 'The response parameter was not passed', 'thrive-dash' ),
'invalid-input-response' => __( 'The response parameter is invalid or has expired', 'thrive-dash' ),
'invalid-widget-id' => __( 'The widget ID extracted from the parsed site secret key was invalid or did not exist', 'thrive-dash' ),
'invalid-parsed-secret' => __( 'The secret extracted from the parsed site secret key was invalid', 'thrive-dash' ),
'bad-request' => __( 'The request was rejected because it was malformed', 'thrive-dash' ),
'internal-error' => __( 'An internal error happened while validating the response. The request can be retried', 'thrive-dash' ),
);
return $errorLists;
}
public function getSiteKey() {
$this->get_credentials();
return $this->param( 'site_key' );
}
public function add_spam_prevention_tool( $sp_tools ) {
array_push( $sp_tools, $this->_key );
return $sp_tools;
}
public function supportedLanguages() {
$languages = array(
'auto' => __( 'Auto', 'thrive-dash' ),
'en' => __( 'English (United States)', 'thrive-dash' ),
'ar' => __( 'Arabic (Egypt)', 'thrive-dash' ),
'bg' => __( 'Bulgarian (Bulgaria)', 'thrive-dash' ),
'cs' => __( 'Czech (Czech Republic)', 'thrive-dash' ),
'da' => __( 'Danish (Denmark)', 'thrive-dash' ),
'de' => __( 'German (Germany)', 'thrive-dash' ),
'el' => __( 'Greek (Greece)', 'thrive-dash' ),
'es' => __( 'Spanish (Spain)', 'thrive-dash' ),
'fa' => __( 'Farsi (Iran)', 'thrive-dash' ),
'fi' => __( 'Finnish (Finland)', 'thrive-dash' ),
'fr' => __( 'French (France)', 'thrive-dash' ),
'he' => __( 'Hebrew (Israel)', 'thrive-dash' ),
'hi' => __( 'Hindi (India)', 'thrive-dash' ),
'hr' => __( 'Croatian (Croatia)', 'thrive-dash' ),
'hu' => __( 'Hungarian (Hungary)', 'thrive-dash' ),
'id' => __( 'Indonesian (Indonesia)', 'thrive-dash' ),
'it' => __( 'Italian (Italy)', 'thrive-dash' ),
'ja' => __( 'Japanese (Japan)', 'thrive-dash' ),
'ko' => __( 'Korean (Korea)', 'thrive-dash' ),
'lt' => __( 'Lithuanian (Lithuania)', 'thrive-dash' ),
'ms' => __( 'Malay (Malaysia)', 'thrive-dash' ),
'nb' => __( 'Norwegian Bokmål (Norway)', 'thrive-dash' ),
'nl' => __( 'Dutch (Netherlands)', 'thrive-dash' ),
'pl' => __( 'Polish (Poland)', 'thrive-dash' ),
'pt' => __( 'Portuguese (Brazil)', 'thrive-dash' ),
'ro' => __( 'Romanian (Romania)', 'thrive-dash' ),
'ru' => __( 'Russian (Russia)', 'thrive-dash' ),
'sk' => __( 'Slovak (Slovakia)', 'thrive-dash' ),
'sl' => __( 'Slovenian (Slovenia)', 'thrive-dash' ),
'sr' => __( 'Serbian (Bosnia and Herzegovina)', 'thrive-dash' ),
'sv' => __( 'Swedish (Sweden)', 'thrive-dash' ),
'th' => __( 'Thai (Thailand)', 'thrive-dash' ),
'tlh' => __( 'Klingon (QonoS)', 'thrive-dash' ),
'tr' => __( 'Turkish (Turkey)', 'thrive-dash' ),
'uk' => __( 'Ukrainian (Ukraine)', 'thrive-dash' ),
'vi' => __( 'Vietnamese (Vietnam)', 'thrive-dash' ),
'zh-cn' => __( 'Chinese (Simplified, China)', 'thrive-dash' ),
'zh-tw' => __( 'Chinese (Traditional, Taiwan)', 'thrive-dash' ),
);
$result = array();
foreach ( $languages as $code => $name ) {
$result[ $code ] = array(
"value" => $code,
"name" => $name,
"html" => sprintf( '<option value="%s" <#- (item && item.language === "%s") ? selected="selected" : "" #> >%s</option>', $code, $code, $name ),
);
}
return $result;
}
/**
* @return string
*/
public function custom_success_message() {
return ' ';
}
/*
* Those functions do not apply
*/
protected function get_api_instance() {
}
protected function _get_lists() {
}
public function add_subscriber( $list_identifier, $arguments ) {
}
}

View File

@@ -0,0 +1,169 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
/**
* Class Thrive_Dash_List_Connection_Twitter
*/
class Thrive_Dash_List_Connection_Twitter extends Thrive_Dash_List_Connection_Abstract {
protected $_key = 'twitter';
protected $_logo_filename = 'x';
private $url = 'https://api.x.com/1.1/';
/**
* Thrive_Dash_List_Connection_Twitter constructor.
*/
public function __construct() {
$this->set_credentials( Thrive_Dash_List_Manager::credentials( $this->_key ) );
}
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'social';
}
/**
* @return string the API connection title
*/
public function get_title() {
return 'X';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'twitter' );
}
/**
* should handle: read data from post / get, test connection and save the details
*
* on error, it should register an error message (and redirect?)
*
* @return mixed
*/
public function read_credentials() {
$access_token = ! empty( $_POST['access_token'] ) ? sanitize_text_field( $_POST['access_token'] ) : '';
$token_secret = ! empty( $_POST['token_secret'] ) ? sanitize_text_field( $_POST['token_secret'] ) : '';
$api_key = ! empty( $_POST['api_key'] ) ? sanitize_text_field( $_POST['api_key'] ) : '';
$api_secret = ! empty( $_POST['api_secret'] ) ? sanitize_text_field( $_POST['api_secret'] ) : '';
if ( empty( $access_token ) || empty( $token_secret ) || empty( $api_key ) || empty( $api_secret ) ) {
return $this->error( __( 'All fields are required', 'thrive-dash' ) );
}
$this->set_credentials( array(
'access_token' => $access_token,
'token_secret' => $token_secret,
'api_key' => $api_key,
'api_secret' => $api_secret,
) );
$result = $this->test_connection();
if ( $result !== true ) {
return $this->error( sprintf( __( 'Incorrect credentials.', 'thrive-dash' ), $result ) );
}
/**
* finally, save the connection details
*/
$this->save();
return $this->success( __( 'X connected successfully!', 'thrive-dash' ) );
}
/**
* test if the credentials are correct.
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
$call = $this->url . 'account/verify_credentials.json';
/** @var Thrive_Dash_Api_Twitter $api */
$api = $this->get_api();
$call = $api->buildOauth( $call, 'GET' )->performRequest();
$response = json_decode( $call, true );
return empty( $response['errors'] );
}
/**
* Get Twitter comment
*
* @param $id
*
* @return array|string|void
*/
public function get_comment( $id ) {
/** @var Thrive_Dash_Api_Twitter $api */
$api = $this->get_api();
$call = $this->url . 'statuses/show.json';
$response = json_decode( $api->setGetfield( '?id=' . $id )->buildOauth( $call, 'GET' )->performRequest(), true );
if ( ! empty( $response ) && is_array( $response ) ) {
/* build the user picture so we can get the original one, not the small one */
$user_picture = 'https://x.com/' . $response['user']['screen_name'] . '/profile_image?size=original';
$comment = array(
'screen_name' => $response['user']['screen_name'],
'name' => $response['user']['name'],
'text' => $response['text'],
'url' => $response['user']['url'],
'picture' => $user_picture,
);
} else {
$comment = __( 'An error occured while getting the comment. Please verify your Twitter connection!', 'thrive-dash' );
}
return $comment;
}
/**
* @return string
*/
public function custom_success_message() {
return ' ';
}
public function add_subscriber( $list_identifier, $arguments ) {
}
/**
* @return Thrive_Dash_Api_Twitter
*/
protected function get_api_instance() {
$params = array(
'oauth_access_token' => $this->param( 'access_token' ),
'oauth_access_token_secret' => $this->param( 'token_secret' ),
'consumer_key' => $this->param( 'api_key' ),
'consumer_secret' => $this->param( 'api_secret' ),
);
return new Thrive_Dash_Api_Twitter( $params );
}
protected function _get_lists() {
}
}

View File

@@ -0,0 +1,167 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_WebinarJamStudio extends Thrive_Dash_List_Connection_Abstract {
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'webinar';
}
/**
* @return string the API connection title
*/
public function get_title() {
return 'WebinarJamStudio';
}
/**
* these are called webinars, not lists
*
* @return string
*/
public function get_list_sub_title() {
return 'Choose from the following upcoming webinars';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'webinarjamstudio' );
}
/**
* should handle: read data from post / get, test connection and save the details
*
* on error, it should register an error message (and redirect?)
*
* @return mixed
*/
public function read_credentials() {
$key = ! empty( $_POST['connection']['key'] ) ? sanitize_text_field( $_POST['connection']['key'] ) : '';
if ( empty( $key ) ) {
return $this->error( __( 'You must provide a valid WebinarJamStudio key', 'thrive-dash' ) );
}
$this->set_credentials( $this->post( 'connection' ) );
$result = $this->test_connection();
if ( $result !== true ) {
return $this->error( sprintf( __( 'Could not connect to WebinarJamStudio using the provided key (<strong>%s</strong>)', 'thrive-dash' ), $result ) );
}
/**
* finally, save the connection details
*/
$this->save();
return $this->success( __( 'WebinarJamStudio connected successfully', 'thrive-dash' ) );
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
/** @var Thrive_Dash_Api_WebinarJamStudio $api */
$api = $this->get_api();
/**
* just try getting the list of the webinars as a connection test
*/
try {
$api->getUpcomingWebinars(); // this will throw the exception if there is a connection problem
} catch ( Thrive_Dash_Api_WebinarJamStudio_Exception $e ) {
return $e->getMessage();
}
return true;
}
/**
* add a contact to a list
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return mixed
*/
public function add_subscriber( $list_identifier, $arguments ) {
/** @var Thrive_Dash_Api_WebinarJamStudio $api */
$api = $this->get_api();
try {
$name = empty( $arguments['name'] ) ? '' : $arguments['name'];
$phone = ! isset( $arguments['phone'] ) || empty( $arguments['phone'] ) ? '' : $arguments['phone'];
$webinar = $api->getWebinar( $list_identifier );
$schedule = 0;
if ( 4 === $api->getWebinarJamApiVersion() ) {
$schedule = isset( $webinar['webinar']['schedules'][0]['schedule'] ) ? $webinar['webinar']['schedules'][0]['schedule'] : $schedule;
}
$api->registerToWebinar( $list_identifier, $name, $arguments['email'], $phone, $schedule );
return true;
} catch ( Thrive_Dash_Api_WebinarJamStudio_Exception $e ) {
return $e->getMessage();
} catch ( Exception $e ) {
return $e->getMessage();
}
}
/**
* instantiate the API code required for this connection
*
* @return mixed
*/
protected function get_api_instance() {
return new Thrive_Dash_Api_WebinarJamStudio( $this->param( 'key' ), $this->param( 'version' ) );
}
/**
* get all Subscriber Lists from this API service
*
* @return array|bool for error
*/
protected function _get_lists() {
/** @var Thrive_Dash_Api_WebinarJamStudio $api */
$api = $this->get_api();
try {
$lists = array();
$webinars = $api->getUpcomingWebinars();
foreach ( $webinars as $key => $item ) {
$lists [] = array(
'id' => $item['webinar_id'],
'name' => $item['name'],
);
}
return $lists;
} catch ( Thrive_Dash_Api_WebinarJamStudio_Exception $e ) {
$this->_error = $e->getMessage();
return false;
}
}
}

View File

@@ -0,0 +1,479 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_Wordpress extends Thrive_Dash_List_Connection_Abstract {
protected $api_error_type = 'string';
private $acf_identifier = 'tve_acf_';
/**
* Set current error type output
*
* @param string $type
*
* @return $this
*/
public function set_error_type( $type = 'string' ) {
$this->api_error_type = $type;
return $this;
}
/**
* WordPress API Connection is always "connected"
*
* @return bool
*/
public function is_connected() {
return true;
}
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'other';
}
/**
* @return string
*/
public function get_title() {
return 'WordPress account';
}
/**
* this requires a special naming here, as it's about wordpress roles, not lists of subscribers
*
* @return string
*/
public function get_list_sub_title() {
return 'Choose the role which should be assigned to your subscribers';
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'wordpress' );
}
/**
* just save the key in the database
*
* @return mixed|void
*/
public function read_credentials() {
$registration_disabled = isset( $_POST['registration_disabled'] ) ? sanitize_text_field( $_POST['registration_disabled'] ) : 0;
$this->set_credentials( array(
'connected' => true,
'registration_disabled' => (int) $registration_disabled,
) );
/**
* finally, save the connection details
*/
$this->save();
return true;
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
/**
* wordpress integration is always supported
*/
return true;
}
/**
* instantiate the API code required for this connection
*
* @return mixed
*/
protected function get_api_instance() {
// no API instance needed here
return null;
}
/**
* get all Subscriber Lists from this API service
*
* @return array
*/
protected function _get_lists() {
$roles = array();
foreach ( $this->_getRoles() as $key => $role_data ) {
$roles[] = array(
'id' => $key,
'name' => $role_data['name'],
);
}
return $roles;
}
public function get_api_custom_fields( $params, $force = false, $get_all = false ) {
return $this->get_all_custom_fields( $force );
}
/**
* Get all custom fields by list id
*
* @param $force calls the API and invalidate cache
*
* @return array|mixed
*/
public function get_all_custom_fields( $force ) {
// Serve from cache if exists and requested
$cached_data = $this->get_cached_custom_fields();
if ( false === $force && ! empty( $cached_data ) ) {
return $cached_data;
}
$default_fields = array(
array(
'id' => 'nickname',
'label' => 'Nickname',
'name' => 'nickname',
'type' => 'TEXT',
),
array(
'id' => 'description',
'label' => 'Biographical Info',
'name' => 'description',
'type' => 'TEXT',
),
array(
'id' => 'user_url',
'label' => 'Website',
'name' => 'user_url',
'type' => 'TEXT',
),
);
$custom_fields = array();
$roles = $this->_get_lists();
if ( is_array( $roles ) ) {
foreach ( $roles as $role ) {
if ( empty( $role['id'] ) ) {
continue;
}
$fields = $default_fields;
foreach ( tvd_get_acf_user_external_fields( $role['id'] ) as $field ) {
$fields[ $field['name'] ] = array(
'id' => $this->acf_identifier . $field['name'],
'label' => $field['label'],
'name' => $field['name'],
'type' => 'TEXT',
);
}
$custom_fields[ $role['id'] ] = $fields;
}
}
$this->_save_custom_fields( $custom_fields );
return $custom_fields;
}
/**
* List of accepted roles
*
* @return array[]
*/
protected function _getRoles() {
/* get_editable_roles only loaded in the admin sections */
if ( ! function_exists( 'get_editable_roles' ) ) {
require_once( ABSPATH . '/wp-admin/includes/user.php' );
}
$user_roles = get_editable_roles();
unset( $user_roles['administrator'], $user_roles['editor'] );
return $user_roles;
}
/**
* Construct an error object to be sent as result. Depending on $this->api_error_type, formats the message as a string or an assoc array
*
* @param string|array $message
* @param string $field
*/
protected function build_field_error( $message, $field ) {
if ( $this->api_error_type !== 'string' && ! is_array( $message ) ) {
$message = array(
'field' => $field,
'error' => $message,
);
}
return $this->error( $message );
}
/**
* add a contact to a list
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return bool|string|Thrive_Dash_List_Connection_Wordpress
*/
public function add_subscriber( $list_identifier, $arguments ) {
/**
* If current request is not "trusted" ( form settings not saved in the database ), the only accepted role is "subscriber"
*/
if ( empty( $arguments['$$trusted'] ) ) {
$list_identifier = 'subscriber';
}
$error = null;
if ( $this->isDisabled() ) {
$error = $this->build_field_error( __( 'Registration has been disabled', 'thrive-dash' ), '' );
} elseif ( is_user_logged_in() ) {
$error = $this->build_field_error( __( 'You are already logged in. Please Logout in order to create a new user.', 'thrive-dash' ), '' );
} elseif ( empty( $arguments['email'] ) ) {
/* Use the same error messages as WordPress */
$error = $this->build_field_error( __( '<strong>Error</strong>: Please type your email address.' ), 'email' );
} elseif ( ! is_email( $arguments['email'] ) ) {
$error = $this->build_field_error( __( '<strong>Error</strong>: The email address isn&#8217;t correct.' ), 'email' );
}
if ( $error !== null ) {
return $error;
}
/* get profile fields from mapping */
$profile_fields = array( 'first_name', 'last_name', 'nickname', 'description', 'user_url' );
if ( ! empty( $arguments['tve_mapping'] ) ) {
foreach ( Thrive_Dash_List_Manager::decode_connections_string( $arguments['tve_mapping'] ) as $field_name => $spec ) {
$field_name = str_replace( '[]', '', $field_name );
if ( ! empty( $spec['wordpress'] ) ) {
if ( strpos( $field_name, 'mapping_' ) !== false ) {
$arguments[ $spec['wordpress'] ] = $this->process_field( $arguments[ $field_name ] );
}
if ( isset( $arguments[ $field_name ] ) && in_array( $spec['_field'], $profile_fields, true ) ) {
/* map specific user fields */
$arguments[ $spec['_field'] ] = $arguments[ $field_name ];
}
}
}
}
$username = $arguments['email'];
$user_id = username_exists( $username );
/**
* if we already have this username
*/
if ( $user_id ) {
$username .= rand( 3, 5 );
$user_id = null;
$arguments['username'] = $username;
}
if ( ! empty( $arguments['name'] ) ) {
list( $arguments['first_name'], $arguments['last_name'] ) = $this->get_name_parts( $arguments['name'] );
}
/**
* check if passwords parameters exist and if they are the same in case they're two
*/
if ( isset( $arguments['password'] ) ) {
if ( isset( $arguments['confirm_password'] ) && $arguments['password'] !== $arguments['confirm_password'] ) {
return $this->error( __( 'Passwords do not match', 'thrive-dash' ) );
}
if ( ! $user_id && email_exists( $arguments['email'] ) === false ) {
$user_data = array(
'user_login' => $username,
'user_pass' => $arguments['password'],
'user_email' => $arguments['email'],
);
foreach ( $profile_fields as $profile_field ) {
if ( ! empty( $arguments[ $profile_field ] ) ) {
$user_data[ $profile_field ] = $arguments[ $profile_field ];
}
}
/**
* Filter user data before creating a new user
*/
$user_data = apply_filters( 'tvd_create_user_data', $user_data );
$user_id = wp_insert_user( $user_data );
if ( $user_id ) {
$data = $arguments;
unset( $data['password'], $data['confirm_password'] );
do_action( 'thrive_register_form_through_wordpress_user', $user_id, $data );
$slug = strtolower( trim( preg_replace( '/[^A-Za-z0-9-]+/', '-', $data['_tcb_id'] ) ) );
do_action( 'thrive_register_form_through_wordpress_user_' . $slug, $user_id, $data );
}
} else {
return $this->build_field_error( __( '<strong>Error</strong>: This email is already registered. Please choose another one.' ), 'email' );
}
} else {
/* create a sanitized user_login string */
$sanitized_user_login = trim( sanitize_user( $arguments['email'], true ) );
$user_id = register_new_user( $sanitized_user_login, $arguments['email'] );
}
if ( $user_id instanceof WP_Error ) {
return $user_id->get_error_message();
}
$userdata = array( 'ID' => $user_id );
if ( array_key_exists( $list_identifier, $this->_getRoles() ) ) {
$userdata['role'] = $list_identifier;
}
foreach ( $profile_fields as $profile_field ) {
if ( ! empty( $arguments[ $profile_field ] ) ) {
$userdata[ $profile_field ] = $arguments[ $profile_field ];
$has_profile_update = true;
}
}
if ( isset( $has_profile_update ) ) {
wp_update_user( $userdata );
}
if ( tvd_has_external_fields_plugins() ) {
// if is acf plugin active, run through all of them and update the custom fields for the user
foreach ( $arguments as $key => $field ) {
if ( strpos( $key, $this->acf_identifier ) === 0 ) {
$id = explode( $this->acf_identifier, $key )[1];
update_field( $id, $field, 'user_' . $user_id );
}
}
}
if ( isset( $has_profile_update ) ) {
//WP has an hook for his action which expects 2 parameters
//we fake the second param
$old_data = new stdClass();
$old_data->user_pass = '';
do_action( 'profile_update', $user_id, $old_data, $userdata );
}
/**
* also, assign the selected role to the newly created user
*/
$user = new WP_User( $user_id );
do_action( 'tvd_after_create_wordpress_account', $user, $arguments );
return true;
}
/**
* Get API custom form fields. By default we have only name and phone
*
* @param array $params
*
* @return array
*/
public function get_custom_fields( $params = array() ) {
return array(
array(
'id' => 'name',
'placeholder' => __( 'Name', 'thrive-cb' ),
),
array(
'id' => 'password',
'placeholder' => __( 'Password', 'thrive-cb' ),
),
array(
'id' => 'confirm_password',
'placeholder' => __( 'Confirm password', 'thrive-cb' ),
),
);
}
/**
* This cannot be tested
*
* @return bool
*/
public function can_test() {
return false;
}
/**
* This cannot be deleted
*
* @return bool
*/
public function can_delete() {
return false;
}
/**
* Whether or not registration is currently disabled
*/
public function isDisabled() {
return ! empty( $this->_credentials['registration_disabled'] );
}
public function prepare_json() {
$message = $this->isDisabled() ? esc_attr__( 'Connection disabled', 'thrive-dash' ) : esc_attr__( 'Connection enabled', 'thrive-dash' );
return parent::prepare_json() + array(
'status_icon' => '<span data-tooltip="' . $message . '" class="tvd-api-status-icon tvd-tooltipped status-' . ( $this->isDisabled() ? 'red' : 'green' ) . '"></span>',
);
}
/**
* Get localization data needed for setting up this connection within a form
*
* @return array
*/
public function get_data_for_setup() {
/* build an error message */
$error_message = sprintf(
__( 'Your connection with WordPress is currently disabled and will not accept registrations. Enable your WordPress connection from the %sAPI dashboard %shere%s', 'thrive-dash' ),
'<strong>',
'<a href="' . admin_url( 'admin.php?page=tve_dash_api_connect#edit/wordpress/autoclose' ) . '" target="_blank">',
'</a></strong>'
);
return array(
'has_error' => $this->isDisabled(),
'error_html' => $error_message,
);
}
}

View File

@@ -0,0 +1,337 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_Zapier extends Thrive_Dash_List_Connection_Abstract {
/**
* Needed to decide webhook's name
*
* @var string
*/
protected $_hook_prefix = 'td_';
/**
* Needed to decide webhook's name
*
* @var string
*/
protected $_hook_suffix = '_webhook';
/**
* Accepted subscribe parameters
*
* @var array
*/
protected $_accepted_params
= array(
'first_name',
'last_name',
'full_name',
'name',
'email',
'message',
'phone',
'url',
'tags',
'number',
'date',
'zapier_send_ip',
'zapier_tags',
'zapier_source_url',
'zapier_thriveleads_group',
'zapier_thriveleads_type',
'zapier_thriveleads_name',
'optin_hook',
);
/**
* @return string
*/
public function get_title() {
return 'Zapier';
}
/**
* Template
*/
public function output_setup_form() {
$this->output_controls_html( 'zapier' );
}
/**
* Read credentials from $_POST and try to save them
*
* @return string|true
*/
public function read_credentials() {
$this->set_credentials(
array(
'api_key' => ! empty( $_POST['connection']['api_key'] ) ? sanitize_text_field( $_POST['connection']['api_key'] ) : '',
'blog_url' => ! empty( $_POST['connection']['blog_url'] ) ? sanitize_text_field( $_POST['connection']['blog_url'] ) : '',
)
);
$_test_passed = $this->test_connection();
if ( true === $_test_passed ) {
$this->save();
}
return $_test_passed;
}
/**
* Delete Zapier saved options
*
* @return $this|Thrive_Dash_List_Connection_Abstract
*/
public function before_disconnect() {
foreach ( array( 'td_api_key', 'td_optin_webhook', 'td_cf-optin_webhook' ) as $option_name ) {
delete_option( $option_name );
}
return $this;
}
/**
* @return true|string true on SUCCESS or error message on FAILURE
*/
public function test_connection() {
$_is_working = true;
/** @var Thrive_Dash_Api_Zapier $api */
$api = $this->get_api();
/** @var WP_Error|bool $response */
$response = $api->authenticate();
if ( is_wp_error( $response ) ) {
$_is_working = $response->get_error_message();
}
return $_is_working;
}
/**
* Calls a Zapier trigger in order to start the created Zapier flow with different integrations
* based on the received hook URL [for Lead Generation / or Contact Form]
*
* @param mixed $list_identifier
* @param array $arguments
*
* @return mixed|Thrive_Dash_List_Connection_Abstract
*/
public function add_subscriber( $list_identifier, $arguments ) {
$params = $this->_prepare_args( $arguments );
$subscribe_url = $this->_get_hook_url( $arguments );
if ( ! empty( $subscribe_url ) ) {
return $this->get_api()->trigger_subscribe( $subscribe_url, $params );
}
return $this->error( __( 'There was an error sending your message, please make sure your Zap is activated or contact support.', 'thrive-dash' ) );
}
/**
* Get the proper hook URL from options
*
* @param $arguments
*
* @return string
*/
private function _get_hook_url( $arguments ) {
// for Lead Generation
$hook_name = 'optin';
// for Contact Form
if ( ! empty( $arguments['optin_hook'] ) && in_array( 'optin_hook', $this->_accepted_params, true ) ) {
$hook_name = filter_var( $arguments['optin_hook'], FILTER_SANITIZE_STRING );
}
// Get subscribed hook option
return (string) get_option( $this->_get_option_name( $hook_name ), '' );
}
/**
* Build and sanitize param array
*
* @param $arguments
*
* @return array
*/
private function _prepare_args( $arguments ) {
$params = array();
if ( empty( $arguments ) || ! is_array( $arguments ) ) {
return $params;
}
foreach ( $arguments as $param => $value ) {
$param = (string) $param;
switch ( strtolower( $param ) ) {
case 'zapier_send_ip':
if ( 1 === (int) $value ) {
$params['ip_address'] = tve_dash_get_ip();
}
break;
case 'zapier_tags':
$params['tags'] = ! empty( $value ) ? filter_var_array( explode( ',', $value ), FILTER_SANITIZE_STRING ) : array();
break;
case 'zapier_thriveleads_group':
// Get title by Group ID
$params['thriveleads_group'] = (int) $value > 0 ? get_the_title( (int) $value ) : '';
break;
case 'zapier_thriveleads_type':
$params['thriveleads_type'] = filter_var( $value, FILTER_SANITIZE_STRING );
break;
case 'zapier_thriveleads_name':
$params['thriveleads_name'] = filter_var( $value, FILTER_SANITIZE_STRING );
break;
case 'url':
$params['website'] = filter_var( $value, FILTER_SANITIZE_URL );
break;
case 'number':
$params['number'] = filter_var( $value, FILTER_SANITIZE_NUMBER_INT );
break;
case 'date':
$params['date'] = filter_var( $value, FILTER_SANITIZE_STRING );
break;
default:
if ( ! empty( $value ) ) {
$params[ $param ] = filter_var( $value, FILTER_SANITIZE_STRING );
}
break;
}
}
$params['source_url'] = filter_var( $_SERVER['HTTP_REFERER'], FILTER_SANITIZE_URL ); // phpcs:ignore
// Format/Rename all the fields.
$messages = array();
$checkbox_count = 1;
$file_url_count = 1;
foreach ( $arguments as $key => $val ) {
if ( strpos( $key, 'mapping_textarea_' ) === 0 ) {
$messages[] = $arguments[ $key ];
} elseif ( strpos( $key, 'mapping_checkbox_' ) === 0 ) {
$params[ 'checkbox_' . $checkbox_count ] = $arguments[ $key ];
$checkbox_count++;
} elseif ( strpos( $key, 'mapping_file' ) === 0 ) {
$params[ 'file_url_' . $file_url_count ] = $val;
$file_url_count++;
}
}
if ( ! empty( $messages ) ) {
$params['message'] = $messages;
}
// print_r($params); die();
return $params;
}
/**
* @return mixed|Thrive_Dash_Api_Zapier
*/
protected function get_api_instance() {
return new Thrive_Dash_Api_Zapier( $this->param( 'api_key' ), $this->param( 'blog_url' ) );
}
/**
* @return array|bool
*/
protected function _get_lists() {
return array();
}
/**
* @return string
*/
public static function get_type() {
return 'integrations';
}
/**
* Used to populate the api value on connecting card
*
* @return string
*/
public function get_api_key() {
$api_key = get_option( 'td_api_key', null );
if ( empty( $api_key ) ) {
$api_key = tve_dash_generate_api_key();
update_option( 'td_api_key', $api_key );
}
return $api_key;
}
/**
* Used to populate the input value on connecting card
*
* @return string
*/
public function get_blog_url() {
return site_url();
}
/**
* @param $hook_name
*
* @return string
*/
protected function _get_option_name( $hook_name ) {
return $this->_hook_prefix . $hook_name . $this->_hook_suffix;
}
/**
* get relevant data from webhook trigger
*
* @param $request WP_REST_Request
*
* @return array
*/
public function get_webhook_data( $request ) {
$contact = $request->get_param( 'email' );
return array( 'email' => empty( $contact ) ? '' : $contact );
}
/**
* Return the connection email merge tag
*
* @return String
*/
public static function get_email_merge_tag() {
return '';
}
public function get_automator_add_autoresponder_mapping_fields() {
return array( 'autoresponder' => array( 'tag_input', 'api_fields' ) );
}
}

View File

@@ -0,0 +1,781 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Thrive Dash List Connection for Zoho.
*/
class Thrive_Dash_List_Connection_Zoho extends Thrive_Dash_List_Connection_Abstract {
/**
* API title
*
* @return string
*/
public function get_title() {
return 'Zoho';
}
/**
* Enable tags support.
*
* @return boolean
*/
public function has_tags() {
return true;
}
/**
* Output the setup form html.
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'zoho' );
}
/**
* Read and validate credentials.
*
* @return mixed|Thrive_Dash_List_Connection_Abstract
* @throws Exception When connection fails.
*/
public function read_credentials() {
$this->set_credentials( $this->post( 'connection' ) );
$result = $this->test_connection();
if ( true !== $result ) {
return $this->error( __( 'Could not connect to Zoho using provided credentials.', 'thrive-dash' ) );
}
$this->_save();
$this->saveOauthCredentials();
return $this->success( __( 'Zoho connected successfully', 'thrive-dash' ) );
}
/**
* Save OAuth details.
*
* @throws Exception When API connection fails.
*/
public function saveOauthCredentials() {
$api = $this->get_api();
$this->_credentials = array_merge( $this->_credentials, $api->getOauth()->getTokens() );
$this->_save();
}
/**
* Remove access code value from credentials since it's only valid once.
* Save the connection details.
*/
private function _save() {
unset( $this->_credentials['access_code'] );
$this->save();
}
/**
* Test the connection to Zoho.
*
* @return bool|string
*/
public function test_connection() {
return is_array( $this->_get_lists() );
}
/**
* Add subscriber to a list.
*
* @param string $list_identifier The list identifier.
* @param array $arguments The subscriber arguments.
*
* @return bool|mixed|string
*/
public function add_subscriber( $list_identifier, $arguments ) {
try {
$api = $this->get_api();
list( $first_name, $last_name ) = $this->get_name_parts( $arguments['name'] );
$contact_info = array(
'Contact Email' => $arguments['email'],
'First Name' => $first_name,
'Last Name' => $last_name,
);
if ( ! empty( $arguments['phone'] ) ) {
$contact_info['Phone'] = sanitize_text_field( $arguments['phone'] );
}
$custom_fields = $this->_generateCustomFields( $arguments );
$contact_info = array_merge( $contact_info, $custom_fields );
$args = array(
'listkey' => $list_identifier,
'contactinfo' => wp_json_encode( $contact_info ),
);
$api_result = $api->add_subscriber( $args );
// Handle tags if provided - tags need to be associated after contact is created.
// Since Zoho returns XML that gets parsed as null, we check for tags after successful API call.
if ( ! empty( $arguments['zoho_tags'] ) ) {
$this->handle_subscriber_tags( $arguments['email'], $arguments['zoho_tags'], $list_identifier );
}
return true;
} catch ( Exception $e ) {
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
error_log( 'Zoho add_subscriber: Exception - ' . $e->getMessage() );
}
return $e->getMessage();
}
}
/**
* Get API instance.
*
* @return mixed|Thrive_Dash_Api_Zoho
* @throws Exception When API initialization fails.
*/
protected function get_api_instance() {
return new Thrive_Dash_Api_Zoho( $this->get_credentials() );
}
/**
* Get lists.
*
* @return array|bool
*/
protected function _get_lists() {
$lists = array();
try {
/**
* @var Thrive_Dash_Api_Zoho $api
*/
$api = $this->get_api();
$result = $api->getLists();
if ( isset( $result['status'] ) && 'error' === $result['status'] ) {
return false;
}
if ( ! empty( $result['list_of_details'] ) && is_array( $result['list_of_details'] ) ) {
foreach ( $result['list_of_details'] as $list ) {
$lists[] = array(
'id' => $list['listkey'],
'name' => $list['listname'],
);
}
}
if ( $api->getOauth()->isAccessTokenNew() ) {
$this->saveOauthCredentials();
}
} catch ( Exception $e ) {
return false;
}
return $lists;
}
/**
* Get API custom fields.
*
* @param array $params The parameters.
* @param bool $force Force refresh flag.
* @param bool $get_all Get all fields flag.
*
* @return array|mixed
*/
public function get_api_custom_fields( $params, $force = false, $get_all = false ) {
$cached_data = $this->get_cached_custom_fields();
if ( false === $force && ! empty( $cached_data ) ) {
return $cached_data;
}
$custom_data = array();
try {
/** @var Thrive_Dash_Api_Zoho $api */
$api = $this->get_api();
$custom_fields = $api->getCustomFields();
if ( empty( $custom_fields['response']['fieldnames']['fieldname'] ) ) {
$this->_save_custom_fields( $custom_data );
return $custom_data;
}
foreach ( $custom_fields['response']['fieldnames']['fieldname'] as $field ) {
if ( 'custom' !== $field['TYPE'] ) {
continue;
}
$custom_data[] = $this->_normalizeCustomFields( $field );
}
} catch ( Exception $e ) {
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
error_log( 'Zoho: Exception in get_api_custom_fields - ' . $e->getMessage() );
}
}
$this->_save_custom_fields( $custom_data );
return $custom_data;
}
/**
* Normalize custom field data.
*
* @param array|object $field The field data.
*
* @return array
*/
protected function _normalizeCustomFields( $field ) {
$field = (array) $field;
return array(
'id' => isset( $field['FIELD_ID'] ) ? (string) $field['FIELD_ID'] : '',
'name' => ! empty( $field['FIELD_DISPLAY_NAME'] ) ? $field['FIELD_DISPLAY_NAME'] : '',
'type' => 'custom',
'label' => ! empty( $field['FIELD_DISPLAY_NAME'] ) ? $field['FIELD_DISPLAY_NAME'] : '',
);
}
/**
* Generate custom fields array.
*
* @param array $args The arguments array.
*
* @return array
*/
private function _generateCustomFields( $args ) {
$custom_fields = $this->get_api_custom_fields( array() );
$ids = $this->buildMappedCustomFields( $args );
$result = array();
// Create a lookup map to avoid nested loops - optimization for performance.
$custom_fields_map = array();
foreach ( $custom_fields as $custom_field ) {
$custom_fields_map[ $custom_field['id'] ] = $custom_field;
}
foreach ( $ids as $key => $id ) {
if ( ! isset( $custom_fields_map[ $id['value'] ] ) ) {
continue;
}
$field = $custom_fields_map[ $id['value'] ];
// Get the original field ID from the mapped data.
$original_id = isset( $id['original_id'] ) ? $id['original_id'] : $key;
// Use the original field type for building the form field name, not the converted type.
$form_field_type = isset( $id['original_type'] ) ? $id['original_type'] : $id['type'];
// Build the correct field name based on original field type and original ID.
if ( false !== strpos( $form_field_type, 'mapping_' ) ) {
// For mapping_ fields, use the format: mapping_type_originalid.
$name = $form_field_type . '_' . $original_id;
} else {
// For other fields (country, state, number, date, etc.), use the format: type_originalid.
$name = $form_field_type . '_' . $original_id;
}
$cf_form_name = str_replace( '[]', '', $name );
// Check if the form field exists before processing.
// For checkbox fields, we need to check without the [] suffix.
$actual_form_field_name = str_replace( '[]', '', $cf_form_name );
if ( ! isset( $args[ $actual_form_field_name ] ) ) {
continue;
}
$processed_value = $this->process_field( $args[ $actual_form_field_name ], $id['type'] );
$result[ $field['name'] ] = $processed_value;
}
return $result;
}
/**
* Build mapped custom fields array based on form params.
*
* @param array $args The form arguments.
*
* @return array
*/
public function buildMappedCustomFields( $args ) {
$mapped_data = array();
// Should be always base_64 encoded of a serialized array.
if ( empty( $args['tve_mapping'] ) || ! tve_dash_is_bas64_encoded( $args['tve_mapping'] ) || ! is_serialized( base64_decode( $args['tve_mapping'] ) ) ) {
return $mapped_data;
}
$form_data = thrive_safe_unserialize( base64_decode( $args['tve_mapping'] ) );
$mapped_fields = $this->get_mapped_field_ids();
foreach ( $mapped_fields as $mapped_field_name ) {
// Extract an array with all custom fields (siblings) names from form data.
// {ex: [mapping_url_0, .. mapping_url_n] / [mapping_text_0, .. mapping_text_n]}.
$cf_form_fields = preg_grep( "#^{$mapped_field_name}#i", array_keys( $form_data ) );
if ( ! empty( $cf_form_fields ) && is_array( $cf_form_fields ) ) {
foreach ( $cf_form_fields as $cf_form_name ) {
if ( empty( $form_data[ $cf_form_name ][ $this->_key ] ) ) {
continue;
}
$field_id = str_replace( $mapped_field_name . '_', '', $cf_form_name );
// Check if the actual form field exists in the arguments
// For checkbox fields, we need to check without the [] suffix
$actual_field_name = str_replace( '[]', '', $cf_form_name );
if ( ! isset( $args[ $actual_field_name ] ) ) {
continue;
}
// Convert country, state, and number fields for proper Zoho mapping.
$field_type = $mapped_field_name;
if ( 'country' === $mapped_field_name || 'state' === $mapped_field_name ) {
$field_type = 'mapping_text';
} elseif ( 'number' === $mapped_field_name ) {
$field_type = 'mapping_number';
} elseif ( 'date' === $mapped_field_name ) {
$field_type = 'mapping_date';
}
// Use a unique key that includes the original field type and ID to prevent overwrites.
// This ensures country_132 and state_132 don't overwrite each other.
$unique_key = $field_type . '_' . $mapped_field_name . '_' . $field_id;
$mapped_data[ $unique_key ] = array(
'type' => $field_type,
'value' => $form_data[ $cf_form_name ][ $this->_key ],
'original_id' => $field_id,
'original_type' => $mapped_field_name,
);
}
}
}
return $mapped_data;
}
/**
* Add custom fields to a contact.
*
* @param string $email The email address.
* @param array $custom_fields The custom fields array.
* @param array $extra Extra data array.
*
* @return int
*/
public function add_custom_fields( $email, $custom_fields = array(), $extra = array() ) {
try {
/** @var Thrive_Dash_Api_Zoho $api */
$api = $this->get_api();
$list_id = ! empty( $extra['list_identifier'] ) ? $extra['list_identifier'] : null;
list( $first_name, $last_name ) = $this->get_name_parts( ! empty( $extra['name'] ) ? $extra['name'] : '' );
$cf = array(
'Contact Email' => $email,
'First Name' => $first_name,
'Last Name' => $last_name,
);
$args = array(
'listkey' => $list_id,
'contactinfo' => wp_json_encode( array_merge( $cf, $this->prepare_custom_fields_for_api( $custom_fields ) ) ),
);
$api->add_subscriber( $args );
} catch ( Exception $e ) {
return false;
}
}
/**
* Get available custom fields for this api connection.
*
* @param null $list_id The list ID.
*
* @return array
*/
public function get_available_custom_fields( $list_id = null ) {
return $this->get_api_custom_fields( null, true );
}
/**
* Prepare custom fields for api call.
*
* @param array $custom_fields The custom fields array.
* @param null $list_identifier The list identifier.
*
* @return array
*/
public function prepare_custom_fields_for_api( $custom_fields = array(), $list_identifier = null ) {
$prepared_fields = array();
$api_fields = $this->get_api_custom_fields( null, true );
foreach ( $api_fields as $field ) {
foreach ( $custom_fields as $key => $custom_field ) {
if ( (string) $field['id'] === (string) $key ) {
$prepared_fields[ $field['name'] ] = $custom_field;
}
}
if ( empty( $custom_fields ) ) {
break;
}
}
return $prepared_fields;
}
/**
* Handle tags for a subscriber.
*
* @param string $email The subscriber email.
* @param string $tags_string The tags string.
* @param string $list_identifier The list identifier.
* @return void
*/
private function handle_subscriber_tags( $email, $tags_string, $list_identifier ) {
if ( empty( $tags_string ) ) {
return;
}
try {
// Parse tag names from comma-separated string.
$tag_names = explode( ',', trim( $tags_string, ' ,' ) );
$tag_names = array_map( 'trim', $tag_names );
$tag_names = array_filter( $tag_names ); // Remove empty tags.
if ( empty( $tag_names ) ) {
return;
}
// Get or create tag names.
$available_tag_names = $this->get_or_create_tag_names( $tag_names );
if ( ! empty( $available_tag_names ) ) {
// Associate each tag with the contact.
$api = $this->get_api();
foreach ( $available_tag_names as $tag_name ) {
$associate_args = array(
'tagName' => $tag_name,
'lead_email' => $email,
);
$result = $api->associateTag( $associate_args );
}
}
} catch ( Exception $e ) {
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
error_log( 'Zoho: Failed to handle subscriber tags - ' . $e->getMessage() );
}
}
}
/**
* Get or create tag names.
*
* @param array $tag_names The tag names array.
* @return array
*/
private function get_or_create_tag_names( $tag_names ) {
$available_tag_names = array();
try {
// Get all existing tags first.
$api = $this->get_api();
$existing_tags = $api->getAllTags();
$tag_map = array();
// Create a map of tag name => tag_name (case-insensitive).
// Parse the nested tag structure from Zoho API by flattening first to eliminate nested loops.
if ( ! empty( $existing_tags['tags'] ) && is_array( $existing_tags['tags'] ) ) {
// Flatten all tag containers into a single array of tag details.
$all_tag_details = call_user_func_array( 'array_merge', array_filter( $existing_tags['tags'], 'is_array' ) );
// Process all tag details in a single loop.
foreach ( $all_tag_details as $tag_details ) {
if ( isset( $tag_details['tag_name'] ) ) {
$tag_map[ strtolower( trim( $tag_details['tag_name'] ) ) ] = $tag_details['tag_name'];
}
}
}
// Process each tag name.
foreach ( $tag_names as $tag_name ) {
$tag_key = strtolower( trim( $tag_name ) );
// Check if tag already exists.
if ( isset( $tag_map[ $tag_key ] ) ) {
$available_tag_names[] = $tag_map[ $tag_key ];
} else {
// Create new tag.
$created_tag_name = $this->create_new_tag( $tag_name );
if ( $created_tag_name ) {
$available_tag_names[] = $created_tag_name;
}
}
}
} catch ( Exception $e ) {
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
error_log( 'Zoho: Exception in get_or_create_tag_names - ' . $e->getMessage() );
}
}
return $available_tag_names;
}
/**
* Create a new tag.
*
* @param string $tag_name The tag name.
* @return string|false Tag name on success, false on failure.
*/
private function create_new_tag( $tag_name ) {
try {
$api = $this->get_api();
$tag_data = array(
'name' => trim( $tag_name ),
);
$result = $api->createTag( $tag_data );
if ( isset( $result['status'] ) && 'success' === $result['status'] ) {
return trim( $tag_name );
}
} catch ( Exception $e ) {
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
error_log( 'Zoho: Exception in create_new_tag for "' . $tag_name . '" - ' . $e->getMessage() );
}
}
return false;
}
/**
* Process number field data to ensure proper Integer format for Zoho.
*
* @param mixed $field The number field data.
* @return string|int The processed number value.
*/
private function process_number_field( $field ) {
if ( is_numeric( $field ) ) {
return (int) $field;
}
if ( is_string( $field ) ) {
$cleaned = preg_replace( '/[^0-9.\-]/', '', trim( $field ) );
if ( is_numeric( $cleaned ) ) {
return (int) floatval( $cleaned );
}
}
if ( is_array( $field ) ) {
foreach ( $field as $value ) {
if ( is_numeric( $value ) ) {
return (int) $value;
}
}
}
return 0;
}
/**
* Process date field data to ensure proper DateTime format for Zoho.
*
* @param mixed $field The date field data.
* @return string The processed date value in YYYY-MM-DD format.
*/
private function process_date_field( $field ) {
if ( empty( $field ) ) {
return '';
}
if ( is_array( $field ) ) {
$date_string = reset( $field );
if ( empty( $date_string ) ) {
return '';
}
$date_string = (string) $date_string;
} else {
$date_string = (string) $field;
}
$date_string = trim( $date_string );
$formats_to_try = array(
// Date only formats
'd/m/Y',
'm/d/Y',
'd-m-Y',
'm-d-Y',
'Y-m-d',
'd.m.Y',
'm.d.Y',
'j/n/Y',
'n/j/Y',
'Y/m/d',
'd M Y',
'M d, Y',
'F j, Y',
// Date and time formats
'd/m/Y H:i',
'm/d/Y H:i',
'd-m-Y H:i',
'm-d-Y H:i',
'Y-m-d H:i',
'd/m/Y H:i:s',
'm/d/Y H:i:s',
'd-m-Y H:i:s',
'm-d-Y H:i:s',
'Y-m-d H:i:s',
// 12-hour formats with AM/PM
'd/m/Y g:i A',
'm/d/Y g:i A',
'd/m/Y h:i A',
'm/d/Y h:i A',
'd/m/Y g:i:s A',
'm/d/Y g:i:s A',
// ISO format variants
'Y-m-d\TH:i:s',
'Y-m-d\TH:i:s\Z',
'c',
);
foreach ( $formats_to_try as $format ) {
$date_obj = DateTime::createFromFormat( $format, $date_string );
if ( false !== $date_obj ) {
// If the format doesn't include time information, set to noon
if ( false === strpos( $format, 'H' ) && false === strpos( $format, 'g' ) && false === strpos( $format, 'h' ) ) {
$date_obj->setTime( 12, 0, 0 );
}
return $date_obj->format( 'Y-m-d\TH:i:s\Z' );
}
}
$timestamp = strtotime( $date_string );
if ( false !== $timestamp ) {
$date_obj = new DateTime();
$date_obj->setTimestamp( $timestamp );
// Only set to noon if the original string doesn't contain time information
if ( ! preg_match( '/\d{1,2}:\d{2}/', $date_string ) ) {
$date_obj->setTime( 12, 0, 0 );
}
return $date_obj->format( 'Y-m-d\TH:i:s\Z' );
}
return $date_string;
}
/**
* Get automator add autoresponder mapping fields.
* Adds tag input support for the automator.
*
* @return array
*/
public function get_automator_add_autoresponder_mapping_fields() {
return array( 'autoresponder' => array( 'mailing_list', 'api_fields', 'tag_input' ) );
}
/**
* Override process_field method to handle country fields properly.
*
* @param mixed $field The field value to process.
* @param string $field_type The type of the field (optional).
* @return string The processed field value.
*/
public function process_field( $field, $field_type = '' ) {
// Handle country fields specifically.
if ( false !== strpos( $field_type, 'country' ) ) {
return $this->process_country_field( $field );
}
// Handle number fields specifically for Zoho Integer field type.
if ( false !== strpos( $field_type, 'mapping_number' ) || false !== strpos( $field_type, 'number' ) ) {
return $this->process_number_field( $field );
}
// Handle date fields specifically for Zoho DateTime field type.
if ( false !== strpos( $field_type, 'mapping_date' ) || false !== strpos( $field_type, 'date' ) ) {
return $this->process_date_field( $field );
}
return parent::process_field( $field );
}
/**
* Process country field data to extract the appropriate text value for Zoho.
*
* @param mixed $field The country field data.
* @return string The country name or code as text.
*/
private function process_country_field( $field ) {
if ( is_string( $field ) && ! empty( $field ) ) {
return stripslashes( $field );
}
if ( is_array( $field ) ) {
$priority_keys = array(
'country_name',
'name',
'full_name',
'display_name',
'label',
'text',
'country_code',
'code',
'iso',
'alpha2',
'alpha3',
'value',
);
// Use array_intersect_key for better performance instead of nested loops.
$available_values = array_intersect_key( $field, array_flip( $priority_keys ) );
if ( ! empty( $available_values ) ) {
$first_value = reset( $available_values );
if ( ! empty( $first_value ) ) {
return stripslashes( (string) $first_value );
}
}
// Fallback to first scalar value.
foreach ( $field as $value ) {
if ( ! empty( $value ) && is_scalar( $value ) ) {
return stripslashes( (string) $value );
}
}
}
if ( is_object( $field ) ) {
return $this->process_country_field( (array) $field );
}
return stripslashes( (string) $field );
}
}

View File

@@ -0,0 +1,560 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Thrive_Dash_List_Connection_iContact extends Thrive_Dash_List_Connection_Abstract {
/**
* Key used for mapping custom fields
*
* @var string
*/
protected $_key = '_field';
/**
* Return the connection type
*
* @return String
*/
public static function get_type() {
return 'autoresponder';
}
/**
* @return string the API connection title
*/
public function get_title() {
return 'iContact';
}
/**
* Enable custom fields support
*/
public function has_custom_fields() {
return true;
}
/**
* output the setup form html
*
* @return void
*/
public function output_setup_form() {
$this->output_controls_html( 'iContact' );
}
/**
* should handle: read data from post / get, test connection and save the details
*
* on error, it should register an error message (and redirect?)
*
* @return mixed
*/
public function read_credentials() {
$apiId = ! empty( $_POST['connection']['appId'] ) ? sanitize_text_field( $_POST['connection']['appId'] ) : '';
$apiUsername = ! empty( $_POST['connection']['apiUsername'] ) ? sanitize_text_field( $_POST['connection']['apiUsername'] ) : '';
$apiPassword = ! empty( $_POST['connection']['apiPassword'] ) ? sanitize_text_field( $_POST['connection']['apiPassword'] ) : '';
if ( empty( $apiId ) || empty( $apiUsername ) || empty( $apiPassword ) ) {
return $this->error( __( 'You must provide a valid iContact AppID/Username/Password', 'thrive-dash' ) );
}
$this->set_credentials( $this->post( 'connection' ) );
$result = $this->test_connection();
if ( $result !== true ) {
return $this->error( sprintf( __( 'Could not connect to iContact: %s', 'thrive-dash' ), $result ) );
}
/**
* finally, save the connection details
*/
$this->save();
return $this->success( __( 'iContact connected successfully', 'thrive-dash' ) );
}
/**
* test if a connection can be made to the service using the stored credentials
*
* @return bool|string true for success or error message for failure
*/
public function test_connection() {
$lists = $this->_get_lists();
if ( $lists === false ) {
return $this->_error;
}
return true;
}
/**
* instantiate the API code required for this connection
*
* @return Thrive_Dash_Api_iContact
*/
protected function get_api_instance() {
return Thrive_Dash_Api_iContact::getInstance()->setConfig( $this->get_credentials() );
}
/**
* get all Subscriber Lists from this API service
*
* @return array|bool for error
*/
protected function _get_lists() {
$api = $this->get_api();
$lists = array();
try {
$data = $api->getLists();
if ( count( $data ) ) {
foreach ( $data as $item ) {
$lists[] = array(
'id' => $item->listId,
'name' => $item->name,
);
}
}
} catch ( Exception $e ) {
$this->_error = $e->getMessage();
return false;
}
return $lists;
}
/**
* add a contact to a list
*
* @param array $list_identifier
* @param array $arguments
*
* @return mixed true -> success; string -> error;
*/
public function add_subscriber( $list_identifier, $arguments ) {
$sEmail = $arguments['email'];
$sStatus = 'normal';
$sPrefix = null;
$sPhone = null;
list( $sFirstName, $sLastName ) = $this->get_name_parts( $arguments['name'] );
$sSuffix = null;
$sStreet = null;
$sStreet2 = null;
$sCity = null;
$sState = null;
$sPostalCode = null;
$sPhone = empty( $arguments['phone'] ) ? '' : $arguments['phone'];
// Prepare custom fields data
try {
$aCustomFields = $this->prepare_api_custom_fields( $arguments );
} catch ( Exception $e ) {
$aCustomFields = array(); // Continue without custom fields if there's an error
}
try {
/** @var Thrive_Dash_Api_iContact $api */
$api = $this->get_api();
$contact = $api->addContact( $sEmail, $sStatus, $sPrefix, $sFirstName, $sLastName, $sSuffix, $sStreet, $sStreet2, $sCity, $sState, $sPostalCode, $sPhone, null, null, $aCustomFields );
if ( empty( $contact ) || ! is_object( $contact ) || empty( $contact->contactId ) ) {
throw new Thrive_Dash_Api_iContact_Exception( 'Unable to save contact' );
}
$api->subscribeContactToList( $contact->contactId, $list_identifier );
return true;
} catch ( Thrive_Dash_Api_iContact_Exception $e ) {
return $e->getMessage();
} catch ( Exception $e ) {
return $e->getMessage();
}
}
/**
* Get custom fields from iContact API
*
* @param array $params
* @param bool $force
* @param bool $get_all
*
* @return array|mixed
*/
public function get_api_custom_fields( $params, $force = false, $get_all = false ) {
// Serve from cache if exists and requested
$cached_data = $this->get_cached_custom_fields();
if ( false === $force && ! empty( $cached_data ) ) {
return $cached_data;
}
$custom_data = array();
try {
/** @var Thrive_Dash_Api_iContact $api */
$api = $this->get_api();
$custom_fields = $api->getCustomFields();
if ( is_array( $custom_fields ) ) {
foreach ( $custom_fields as $field ) {
$normalized_field = $this->normalize_custom_field( $field );
$custom_data[] = $normalized_field;
}
}
$this->_save_custom_fields( $custom_data );
} catch ( Exception $e ) {
$this->_error = $e->getMessage();
}
return $custom_data;
}
/**
* Normalize custom field data from iContact API
*
* @param object $field
*
* @return array
*/
protected function normalize_custom_field( $field ) {
$field = (object) $field;
return array(
'id' => ! empty( $field->customFieldId ) ? $field->customFieldId : ( ! empty( $field->fieldName ) ? $field->fieldName : '' ),
'name' => ! empty( $field->fieldName ) ? $field->fieldName : ( ! empty( $field->name ) ? $field->name : '' ),
'type' => ! empty( $field->fieldType ) ? $field->fieldType : 'text',
'label' => ! empty( $field->publicName ) ? $field->publicName : ( ! empty( $field->fieldName ) ? $field->fieldName : '' ),
);
}
/**
* Get available custom fields for this api connection
*
* @param array $data
*
* @return array
*/
public function get_available_custom_fields( $data = array() ) {
return $this->get_api_custom_fields( null, true );
}
/**
* Prepare custom fields data for API submission
*
* @param array $arguments POST sent by optin form
*
* @return array with iContact custom field name as key and the value of inputs filled by the visitor
*/
public function prepare_api_custom_fields( $arguments ) {
$fields = array();
if ( empty( $arguments['tve_mapping'] ) ) {
return $fields;
}
try {
$serialized = base64_decode( $arguments['tve_mapping'] );
$mapping = array();
if ( $serialized ) {
$mapping = thrive_safe_unserialize( $serialized );
}
if ( empty( $mapping ) ) {
return $fields;
}
foreach ( $mapping as $name => $field ) {
$name = str_replace( '[]', '', $name );
// Check if field has a mapping and if arguments value is meaningful.
$has_meaningful_value = false;
if ( isset( $arguments[ $name ] ) ) {
if ( is_array( $arguments[ $name ] ) ) {
// For arrays, check if any element is non-empty.
$meaningful_values = array_filter(
$arguments[ $name ],
function ( $item ) {
return is_string( $item ) && ! empty( trim( $item ) );
}
);
$has_meaningful_value = ! empty( $meaningful_values );
} else {
// For non-arrays, use regular empty check
$has_meaningful_value = ! empty( $arguments[ $name ] );
}
}
if ( ! empty( $field[ $this->_key ] ) && $has_meaningful_value ) {
$custom_field_name = $field[ $this->_key ];
$custom_field_value = $arguments[ $name ];
// Check if field type is available in mapping data
$field_type = '';
if ( isset( $field['type'] ) ) {
$field_type = $field['type'];
} elseif ( isset( $field['_field_type'] ) ) {
$field_type = $field['_field_type'];
} elseif ( isset( $field['_field'] ) ) {
$field_type = $field['_field'];
}
// Format date fields properly for iContact API
if ( 'date' === strtolower( $field_type ) ) {
$custom_field_value = $this->format_date_value( $custom_field_value );
}
// Convert 'GDPR ACCEPTED' and checkbox values to 1 for iContact API
$custom_field_value = $this->convert_special_field_values( $custom_field_value, $field_type );
$fields[ $custom_field_name ] = is_array( $custom_field_value ) ? implode( ', ', $custom_field_value ) : $custom_field_value;
}
}
} catch ( Exception $e ) {
// Continue silently if there's an error
}
return $fields;
}
/**
* Convert GDPR ACCEPTED value and checkbox field values to 1 for iContact API
*
* @param mixed $value The field value to check and potentially convert
* @param string $field_type The field type to determine conversion logic
*
* @return mixed The converted value (1 for GDPR ACCEPTED or checkbox fields, otherwise original value)
*/
private function convert_special_field_values( $value, $field_type = '' ) {
// Convert 'GDPR ACCEPTED' to 1
if ( is_string( $value ) && 'GDPR ACCEPTED' === $value ) {
return 1;
}
// Convert checkbox field values to 1.
if ( 'mapping_checkbox' === $field_type && ! empty( $value ) ) {
return 1;
}
return $value;
}
/**
* Format date value to iContact's expected YYYY-MM-DD format
*
* @param string $date_string Date string to format
*
* @return string Formatted date string
*/
private function format_date_value( $date_string ) {
$formatted_date = '';
if ( empty( $date_string ) ) {
return $formatted_date;
}
// Check if $date_string is already in YYYY-MM-DD format
if ( preg_match( '/^\d{4}-\d{2}-\d{2}$/', $date_string ) ) {
// Validate the date
$date_parts = explode( '-', $date_string );
if ( checkdate( $date_parts[1], $date_parts[2], $date_parts[0] ) ) {
return $date_string;
}
}
// Check if $date_string is in the format of "M, d, Y" (e.g., "Jan, 15, 2024")
if ( preg_match( '/[a-zA-Z]{3}, [0-9]{1,2}, [0-9]{4}/', $date_string ) ) {
$date_string = str_replace( ', ', '-', $date_string );
$formatted_date = gmdate( 'Y-m-d', strtotime( $date_string ) );
return $formatted_date;
}
// Check if $date_string is in the format of "d/m/Y" (e.g., "15/01/2024")
if ( preg_match( '/^(0?[1-9]|[12][0-9]|3[01])\/(0?[1-9]|1[0-2])\/\d{4}$/', $date_string ) ) {
$date_parts = explode( '/', $date_string );
if ( checkdate( $date_parts[1], $date_parts[0], $date_parts[2] ) ) {
$formatted_date = gmdate( 'Y-m-d', strtotime( str_replace( '/', '-', $date_string ) ) );
return $formatted_date;
}
}
// Check if $date_string is in MM/DD/YYYY format
if ( preg_match( '/^(0?[1-9]|1[0-2])\/(0?[1-9]|[12][0-9]|3[01])\/\d{4}$/', $date_string ) ) {
$date_parts = explode( '/', $date_string );
if ( checkdate( $date_parts[0], $date_parts[1], $date_parts[2] ) ) {
$formatted_date = gmdate( 'Y-m-d', strtotime( $date_string ) );
return $formatted_date;
}
}
// Try to parse other common date formats and convert to YYYY-MM-DD
$timestamp = strtotime( $date_string );
if ( $timestamp !== false ) {
$formatted_date = gmdate( 'Y-m-d', $timestamp );
} else {
// If all else fails, return the original string
$formatted_date = $date_string;
}
return $formatted_date;
}
/**
* Format custom fields for API submission by checking field types
*
* @param array $custom_fields
*
* @return array
*/
private function format_custom_fields_for_api( $custom_fields ) {
$formatted_fields = array();
if ( empty( $custom_fields ) || ! is_array( $custom_fields ) ) {
return $formatted_fields;
}
try {
// Get available custom fields to check types, but only if we're not already in an error state
$available_fields = array();
$field_types = array();
// Try to get field types, but don't fail if this causes issues
try {
$available_fields = $this->get_api_custom_fields( null, false );
// Build a map of field names to types
if ( ! empty( $available_fields ) && is_array( $available_fields ) ) {
foreach ( $available_fields as $field ) {
if ( ! empty( $field['name'] ) && ! empty( $field['type'] ) ) {
$field_types[ $field['name'] ] = $field['type'];
}
// Also check by id if name doesn't match
if ( ! empty( $field['id'] ) && ! empty( $field['type'] ) ) {
$field_types[ $field['id'] ] = $field['type'];
}
}
}
} catch ( Exception $e ) {
// Continue silently if field types can't be retrieved
}
foreach ( $custom_fields as $field_name => $field_value ) {
$field_type = isset( $field_types[ $field_name ] ) ? $field_types[ $field_name ] : '';
// Format date fields properly for iContact API
if ( 'date' === strtolower( $field_type ) ) {
$field_value = $this->format_date_value( $field_value );
}
// Convert 'GDPR ACCEPTED' and checkbox values to 1 for iContact API
$field_value = $this->convert_special_field_values( $field_value, $field_type );
$formatted_fields[ $field_name ] = $field_value;
}
} catch ( Exception $e ) {
// Return original fields if formatting fails
return $custom_fields;
}
return $formatted_fields;
}
/**
* Add custom fields to existing contact
*
* @param string $email
* @param array $custom_fields
* @param array $extra
*
* @return int|false
*/
public function add_custom_fields( $email, $custom_fields = array(), $extra = array() ) {
try {
/** @var Thrive_Dash_Api_iContact $api */
$api = $this->get_api();
// First, find the contact by email to get the contact ID
$api->setLimit( 1 );
$api->addCustomQueryField( 'email', $email );
$contacts = $api->getContacts();
if ( empty( $contacts ) || ! is_array( $contacts ) ) {
return false;
}
$contact = $contacts[0];
$contactId = $contact->contactId;
// Format date fields before updating
$formatted_custom_fields = $this->format_custom_fields_for_api( $custom_fields );
// Update the contact with custom fields
$api->updateContact( $contactId, null, null, null, null, null, null, null, null, null, null, null, null, null, null, $formatted_custom_fields );
return $contactId;
} catch ( Exception $e ) {
return false;
}
}
/**
* Get custom fields by list
*
* @param null $list
*
* @return array
*/
public function get_custom_fields_by_list( $list = null ) {
return $this->get_available_custom_fields();
}
/**
* Build custom fields mapping for automations
*
* @param $automation_data
*
* @return array
*/
public function build_automation_custom_fields( $automation_data ) {
$mapped_data = array();
if ( ! empty( $automation_data['api_fields'] ) ) {
foreach ( $automation_data['api_fields'] as $pair ) {
$value = sanitize_text_field( $pair['value'] );
if ( $value ) {
// Convert 'GDPR ACCEPTED' and checkbox values to 1 for iContact API
$value = $this->convert_special_field_values( $value, isset( $pair['type'] ) ? $pair['type'] : '' );
$mapped_data[ $pair['key'] ] = $value;
}
}
}
// Format date fields for automation data
if ( ! empty( $mapped_data ) ) {
$mapped_data = $this->format_custom_fields_for_api( $mapped_data );
}
return $mapped_data;
}
}

Some files were not shown because too many files have changed in this diff Show More