Overview

Packages

  • ACF
  • Automation
    • Actions
    • Activation
    • LeadProfile
    • Menus
    • Queries
    • Rules
    • Triggers
  • CTA
    • Activation
    • AJAXListeners
    • Cloning
    • Core
    • Display
    • EditPage
    • Enqueues
    • GPLSettings
    • LeadsProfile
    • Loading
    • Menus
    • Notices
    • PlacementMetabox
    • PostType
    • Templates
    • Tracking
    • Variations
    • YOAST
  • InboundPro
    • Activation
    • AdminAJAX
    • AutoLoading
    • Cron
    • DataInterface
    • FieldMapping
    • Funnels
    • InboundNowAPI
    • Installer
    • LeadStatuses
    • Menus
    • Notifications
    • Ouath
    • Reports
    • Settings
    • Tracking
    • Translations
    • Updates
  • LandingPages
    • Activation
    • DataInterfaces
    • Management
    • Menus
    • NeedsAttention
    • Notices
    • Sidebars
    • Templates
    • Tracking
    • Variations
    • WelcomeScreen
    • Widgets
  • Leads
    • Activation
    • Akismet
    • BranchControl
    • BulkActions
    • Dashboard
    • Management
    • Notifications
    • Settings
    • Tracking
    • UserProfile
    • WPLogin
  • Mailer
    • Activation
    • Admin
    • ClickTracking
    • DataInterface
    • InboundForms
    • Leads
    • Management
    • Notifications
    • Scheduling
    • Sending
    • Settings
    • ShortcodesAndTokens
    • SparkPost
    • Templates
    • Unsubscribes
    • Variations
    • YoastSEO
  • None
  • Shared
    • APIs
    • CPT
    • DatabaseRoutines
    • DebugTricks
    • DoubleOptin
    • EventManagement
    • FieldMapping
    • InboundForms
    • LeadSorage
    • MarketingButton
    • Menus
    • Notifications
    • Shortcodes
    • ShortcodesAndTokens
    • StandAloneLicensing
    • Tracking
    • VisualEditor
  • xDepreciated

Classes

  • CTA_Activation
  • CTA_Activation_Update_Routines
  • CTA_Admin_Notices
  • CTA_Ajax_Listeners
  • CTA_Clone_Post
  • CTA_Conversion_Tracking
  • CTA_Dynamic_Widget
  • CTA_Enqueues
  • CTA_Load_Extensions
  • CTA_Menus
  • CTA_Metaboxes
  • CTA_Metaboxes_Global
  • CTA_Post_Type
  • CTA_Render
  • CTA_Settings
  • CTA_Static_Widget
  • CTA_Template_Manager
  • CTA_Template_Manager_List
  • CTA_Variations
  • CTA_WordPress_Leads
  • CTA_WordPress_SEO
  • Inbound_Ajax
  • Inbound_Akismet
  • Inbound_Analytics
  • Inbound_API
  • Inbound_API_Keys_Generation
  • Inbound_API_Keys_Table
  • Inbound_API_Wrapper
  • Inbound_Asset_Loader
  • Inbound_Automation_Action_Add_Remove_List
  • Inbound_Automation_Action_Add_Remove_Tag
  • Inbound_Automation_Action_Create_Lead
  • Inbound_Automation_Action_Create_User
  • Inbound_Automation_Action_Kill_Tasks
  • Inbound_Automation_Action_Relay_Data
  • Inbound_Automation_Action_Send_Email
  • Inbound_Automation_Action_Wait
  • Inbound_Automation_Activation
  • Inbound_Automation_Activation_Update_Routines
  • Inbound_Automation_Adminbar
  • Inbound_Automation_Lead_Profile
  • Inbound_Automation_Loader
  • Inbound_Automation_Plugin
  • Inbound_Automation_Post_Type
  • Inbound_Automation_Processing
  • Inbound_Automation_Query_Lead
  • Inbound_Automation_Query_User
  • Inbound_Automation_Trigger_inbound_double_optin_confirm
  • Inbound_Automation_Trigger_inbound_store_lead_post
  • Inbound_Automation_Trigger_inbound_track_link
  • Inbound_Automation_Trigger_Publish_Post
  • Inbound_Automation_Trigger_Save_Post_Deactivated
  • Inbound_Automation_Trigger_Set_Object_Terms
  • Inbound_Automation_Trigger_Update_Lead
  • Inbound_Automation_Trigger_User_Register
  • Inbound_Calls_To_Action_Plugin
  • Inbound_Confirm_Double_Optin
  • Inbound_Cron
  • Inbound_CTA_Quick_View
  • Inbound_Customizer
  • Inbound_Debug_Scripts
  • Inbound_Email_Meta
  • Inbound_Email_Preview
  • Inbound_Email_Template_Shortcodes
  • Inbound_Event_Report
  • Inbound_Events
  • Inbound_Events_Report
  • Inbound_Extension_Loads
  • Inbound_Forms
  • Inbound_Funnel_Reporting
  • Inbound_Impressions_Report
  • Inbound_Landing_Pages_Plugin
  • Inbound_Lead_Statuses
  • Inbound_Leads
  • Inbound_Leads_Custom_fields
  • Inbound_Leads_Plugin
  • Inbound_License
  • Inbound_List_Double_Optin
  • Inbound_Load_Shared
  • Inbound_Logging_Automation
  • Inbound_Login
  • Inbound_Mail_Daemon
  • Inbound_Mailer_ACF
  • Inbound_Mailer_Activation
  • Inbound_Mailer_Activation_Update_Routines
  • Inbound_Mailer_Ajax_Listeners
  • Inbound_Mailer_Clone_Post
  • Inbound_Mailer_Common_Settings
  • Inbound_Mailer_Customizer
  • Inbound_Mailer_Direct_Email_Leads
  • Inbound_Mailer_Enqueues
  • Inbound_Mailer_Forms_Integration
  • Inbound_Mailer_Load_Templates
  • Inbound_Mailer_Menus
  • Inbound_Mailer_Metaboxes
  • Inbound_Mailer_Notifications
  • Inbound_Mailer_Plugin
  • Inbound_Mailer_Post_Type
  • Inbound_Mailer_Scheduling
  • Inbound_Mailer_Settings
  • Inbound_Mailer_SparkPost
  • Inbound_Mailer_Stats_Report
  • Inbound_Mailer_Template_Manager
  • Inbound_Mailer_Template_Manager_List
  • Inbound_Mailer_Tokens
  • Inbound_Mailer_Tracking
  • Inbound_Mailer_Unsubscribe
  • Inbound_Mailer_Variations
  • Inbound_Mailer_WordPress_SEO
  • Inbound_Maintenance_Lists
  • Inbound_Marketing_Button
  • Inbound_Menus_Admin
  • Inbound_Menus_Adminbar
  • Inbound_Metaboxes_Automation
  • Inbound_Metaboxes_Leads
  • Inbound_Notifications
  • Inbound_Now_Store
  • Inbound_Options_API
  • Inbound_Pro_Activation
  • Inbound_Pro_Admin_Ajax_Listeners
  • Inbound_Pro_Automatic_Updates
  • Inbound_Pro_Downloads
  • Inbound_Pro_Notifications
  • Inbound_Pro_Oauth_Engine
  • Inbound_Pro_Plugin
  • Inbound_Pro_Settings
  • Inbound_Quick_View
  • Inbound_Reporting_Templates
  • Inbound_Search_And_Comment_Report
  • Inbound_Shared_ACF_BootStrap
  • Inbound_Shortcodes
  • Inbound_Shortcodes_Cookies
  • Inbound_Shortcodes_Fields
  • Inbound_SparkPost
  • Inbound_SparkPost_Stats
  • Inbound_Template_Utils
  • Inbound_Templating_Engine
  • Inbound_Tracking
  • Inbound_Translation_Updater
  • Inbound_Updater
  • Inbound_Upgrade_For_More_Reports
  • Inbound_Upgrade_Routines
  • Inbound_Visitor_Event_Report
  • Inbound_Visitor_Impressions_Report
  • Inbound_Visitors_Report
  • INBOUNDNOW_EXTEND
  • Landing_Pages_ACF
  • Landing_Pages_Activation
  • Landing_Pages_Activation_Update_Routines
  • Landing_Pages_Admin_Menus
  • Landing_Pages_Admin_Notices
  • Landing_Pages_Install
  • Landing_Pages_Load_Extensions
  • Landing_Pages_Meta
  • Landing_Pages_Metaboxes
  • Landing_Pages_Post_Type
  • Landing_Pages_Row_Actions
  • Landing_Pages_Settings
  • Landing_Pages_Sidebars
  • Landing_Pages_Split_Testing_Stats
  • Landing_Pages_Template_Management
  • Landing_Pages_Template_Switcher
  • Landing_Pages_Templates_List_Table
  • Landing_Pages_Variations
  • LandingPages_Welcome
  • Leads_Activation
  • Leads_Activation_Update_Routines
  • Leads_Admin_Notices
  • Leads_Batch_Processor
  • Leads_Branching
  • Leads_Dashboard
  • Leads_Field_Map
  • Leads_Manager
  • Leads_Post_Type
  • Leads_Settings
  • Leads_Tracking
  • Leads_User_Profile
  • LeadStorage
  • LP_EXTENSION_LICENSENING
  • LP_EXTENSION_UPDATER
  • LP_Variation_Rotation
  • LP_Widget_Conversion_Area

Functions

  • cta_check_active
  • cta_example_template_function
  • cta_load_dynamic_widget
  • CTA_Load_Extensions
  • cta_load_static_widget
  • CTA_Render
  • inbound_add_conversion_to_lead
  • inbound_automation_check_active
  • inbound_automation_load_definitions
  • inbound_automation_metaboxes
  • inbound_automation_processing
  • inbound_color
  • inbound_color_scheme
  • inbound_confirm_email_service_provider
  • inbound_email_kill_ie8
  • inbound_email_load_templates
  • inbound_form_add_lead_list
  • inbound_form_auto_publish
  • inbound_form_delete_transient
  • inbound_form_get_data
  • inbound_form_save
  • inbound_forms_change_columns
  • inbound_forms_cpt
  • inbound_forms_custom_columns
  • inbound_forms_default_content
  • inbound_get_form_names
  • inbound_get_parent_directory
  • inbound_Hex_2_RGB
  • inbound_inbound_email_example_template_function
  • inbound_load_lead_manager
  • inbound_load_token_engine
  • inbound_mailer_acf_integration
  • Inbound_Mailer_Common_Settings
  • Inbound_Mailer_Load_Templates
  • inbound_qtrans_disable
  • inbound_record_log
  • inbound_register_form_role_capabilities
  • inbound_shortcode_alert
  • inbound_shortcode_callout
  • inbound_shortcode_columns
  • inbound_shortcode_content_box
  • inbound_shortcode_divider
  • inbound_shortcode_empty_paragraph_fix
  • inbound_shortcode_four_fifth_columns
  • inbound_shortcode_full_columns
  • inbound_shortcode_gmap
  • inbound_shortcode_icon
  • inbound_shortcode_intro
  • inbound_shortcode_landing_pages
  • inbound_shortcode_leadp
  • inbound_shortcode_list_icons
  • inbound_shortcode_one_fifth_columns
  • inbound_shortcode_one_fourth_columns
  • inbound_shortcode_one_half_columns
  • inbound_shortcode_one_third_columns
  • inbound_shortcode_portfolio
  • inbound_shortcode_pricing
  • inbound_shortcode_profile
  • inbound_shortcode_social_links
  • inbound_shortcode_tabs
  • inbound_shortcode_teaser
  • inbound_shortcode_testimonial
  • inbound_shortcode_three_fifth_columns
  • inbound_shortcode_three_fourth_columns
  • inbound_shortcode_two_fifth_columns
  • inbound_shortcode_two_third_columns
  • inbound_shortcode_video
  • inbound_store_lead
  • inbound_template_brightness
  • inbound_template_color
  • Inbound_Templating_Engine
  • inbound_travis_check
  • inboundnow_add_master_license
  • json_encode_fallback
  • landingpage_fix_known_wp_title_isses
  • landingpages_is_active
  • load_CTA_Settings
  • load_CTA_Template_Manager
  • load_Inbound_API_Keys_Generation
  • load_Inbound_Lead_Statuses
  • load_Inbound_Leads_Custom_fields
  • load_inbound_mail_daemon
  • load_Inbound_Mailer_Settings
  • load_Inbound_Mailer_Template_Manager
  • load_Inbound_Pro_Downloads
  • lp_ab_testing_get_current_variation_id
  • lp_add_option
  • lp_body_class
  • lp_check_active
  • lp_content_area
  • lp_conversion_area
  • lp_discover_important_wrappers
  • lp_footer
  • lp_generate_drowndown
  • lp_get_parent_directory
  • lp_get_value
  • lp_global_config
  • lp_head
  • lp_in_admin_header
  • lp_init
  • lp_list_feature
  • lp_load_widgets
  • lp_main_headline
  • lp_manage_templates
  • lp_move_template_files
  • lp_rebuild_attributes
  • lp_templates_upload
  • mailer_check_active
  • wp_cta_check_active
  • wp_cta_kill_ie8
  • wp_cta_load_calls_to_action
  • wp_leads_get_page_final_id
  • wpl_url_to_postid
  • wpleads_add_lead_to_list
  • wpleads_check_active
  • wpleads_get_lead_lists_as_array
  • Overview
  • Package
  • Class
   1:    2:    3:    4:    5:    6:    7:    8:    9:   10:   11:   12:   13:   14:   15:   16:   17:   18:   19:   20:   21:   22:   23:   24:   25:   26:   27:   28:   29:   30:   31:   32:   33:   34:   35:   36:   37:   38:   39:   40:   41:   42:   43:   44:   45:   46:   47:   48:   49:   50:   51:   52:   53:   54:   55:   56:   57:   58:   59:   60:   61:   62:   63:   64:   65:   66:   67:   68:   69:   70:   71:   72:   73:   74:   75:   76:   77:   78:   79:   80:   81:   82:   83:   84:   85:   86:   87:   88:   89:   90:   91:   92:   93:   94:   95:   96:   97:   98:   99:  100:  101:  102:  103:  104:  105:  106:  107:  108:  109:  110:  111:  112:  113:  114:  115:  116:  117:  118:  119:  120:  121:  122:  123:  124:  125:  126:  127:  128:  129:  130:  131:  132:  133:  134:  135:  136:  137:  138:  139:  140:  141:  142:  143:  144:  145:  146:  147:  148:  149:  150:  151:  152:  153:  154:  155:  156:  157:  158:  159:  160:  161:  162:  163:  164:  165:  166:  167:  168:  169:  170:  171:  172:  173:  174:  175:  176:  177:  178:  179:  180:  181:  182:  183:  184:  185:  186:  187:  188:  189:  190:  191:  192:  193:  194:  195:  196:  197:  198:  199:  200:  201:  202:  203:  204:  205:  206:  207:  208:  209:  210:  211:  212:  213:  214:  215:  216:  217:  218:  219:  220:  221:  222:  223:  224:  225:  226:  227:  228:  229:  230:  231:  232:  233:  234:  235:  236:  237:  238:  239:  240:  241:  242:  243:  244:  245:  246:  247:  248:  249:  250:  251:  252:  253:  254:  255:  256:  257:  258:  259:  260:  261:  262:  263:  264:  265:  266:  267:  268:  269:  270:  271:  272:  273:  274:  275:  276:  277:  278:  279:  280:  281:  282:  283:  284:  285:  286:  287:  288:  289:  290:  291:  292:  293:  294:  295:  296:  297:  298:  299:  300:  301:  302:  303:  304:  305:  306:  307:  308:  309:  310:  311:  312:  313:  314:  315:  316:  317:  318:  319:  320:  321:  322:  323:  324:  325:  326:  327:  328:  329:  330:  331:  332:  333:  334:  335:  336:  337:  338:  339:  340:  341:  342:  343:  344:  345:  346:  347:  348:  349:  350:  351:  352:  353:  354:  355:  356:  357:  358:  359:  360:  361:  362:  363:  364:  365:  366:  367:  368:  369:  370:  371:  372:  373:  374:  375:  376:  377:  378:  379:  380:  381:  382:  383:  384:  385:  386:  387:  388:  389:  390:  391:  392:  393:  394:  395:  396:  397:  398:  399:  400:  401:  402:  403:  404:  405:  406:  407:  408:  409:  410:  411:  412:  413:  414:  415:  416:  417:  418:  419:  420:  421:  422:  423:  424:  425:  426:  427:  428:  429:  430:  431:  432:  433:  434:  435:  436:  437:  438:  439:  440:  441:  442:  443:  444:  445:  446:  447:  448:  449:  450:  451:  452:  453:  454:  455:  456:  457:  458:  459:  460:  461:  462:  463:  464:  465:  466:  467:  468:  469:  470:  471:  472:  473:  474:  475:  476:  477:  478:  479:  480:  481:  482:  483:  484:  485:  486:  487:  488:  489:  490:  491:  492:  493:  494:  495:  496:  497:  498:  499:  500:  501:  502:  503:  504:  505:  506:  507:  508:  509:  510:  511:  512:  513:  514:  515:  516:  517:  518:  519:  520:  521:  522:  523:  524:  525:  526:  527:  528:  529:  530:  531:  532:  533:  534:  535:  536:  537:  538:  539:  540:  541:  542:  543:  544:  545:  546:  547:  548:  549:  550:  551:  552:  553:  554:  555:  556:  557:  558:  559:  560:  561:  562:  563:  564:  565:  566:  567:  568:  569:  570:  571:  572:  573:  574:  575:  576:  577:  578:  579:  580:  581:  582:  583:  584:  585:  586:  587:  588:  589:  590:  591:  592:  593:  594:  595:  596:  597:  598:  599:  600:  601:  602:  603:  604:  605:  606:  607:  608:  609:  610:  611:  612:  613:  614:  615:  616:  617:  618:  619:  620:  621:  622:  623:  624:  625:  626:  627:  628:  629:  630:  631:  632:  633:  634:  635:  636:  637:  638:  639:  640:  641:  642:  643:  644:  645:  646:  647:  648:  649:  650:  651:  652:  653:  654:  655:  656:  657:  658:  659:  660:  661:  662:  663:  664:  665:  666:  667:  668:  669:  670:  671:  672:  673:  674:  675:  676:  677:  678:  679:  680:  681:  682:  683:  684:  685:  686:  687:  688:  689:  690:  691:  692:  693:  694:  695:  696:  697:  698:  699:  700:  701:  702:  703:  704:  705:  706:  707:  708:  709:  710:  711:  712:  713:  714:  715:  716:  717:  718:  719:  720:  721:  722:  723:  724:  725:  726:  727:  728:  729:  730:  731:  732:  733:  734:  735:  736:  737:  738:  739:  740:  741:  742:  743:  744:  745:  746:  747:  748:  749:  750:  751:  752:  753:  754:  755:  756:  757:  758:  759:  760:  761:  762:  763:  764:  765:  766:  767:  768:  769:  770:  771:  772:  773:  774:  775:  776:  777:  778:  779:  780:  781:  782:  783:  784:  785:  786:  787:  788:  789:  790:  791:  792:  793:  794:  795:  796:  797:  798:  799:  800:  801:  802:  803:  804:  805:  806:  807:  808:  809:  810:  811:  812:  813:  814:  815:  816:  817:  818:  819:  820:  821:  822:  823:  824:  825:  826:  827:  828:  829:  830:  831:  832:  833:  834:  835:  836:  837:  838:  839:  840:  841:  842:  843:  844:  845:  846:  847:  848:  849:  850:  851:  852:  853:  854:  855:  856:  857:  858:  859:  860:  861:  862:  863:  864:  865:  866:  867:  868:  869:  870:  871:  872:  873:  874:  875:  876:  877:  878:  879:  880:  881:  882:  883:  884:  885:  886:  887:  888:  889:  890:  891:  892:  893:  894:  895:  896:  897:  898:  899:  900:  901:  902:  903:  904:  905:  906:  907:  908:  909:  910:  911:  912:  913:  914:  915:  916:  917:  918:  919:  920:  921:  922:  923:  924:  925:  926:  927:  928:  929:  930:  931:  932:  933:  934:  935:  936:  937:  938:  939:  940:  941:  942:  943:  944:  945:  946:  947:  948:  949:  950:  951:  952:  953:  954:  955:  956:  957:  958:  959:  960:  961:  962:  963:  964:  965:  966:  967:  968:  969:  970:  971:  972:  973:  974:  975:  976:  977:  978:  979:  980:  981:  982:  983:  984:  985:  986:  987:  988:  989:  990:  991:  992:  993:  994:  995:  996:  997:  998:  999: 1000: 1001: 1002: 1003: 1004: 1005: 1006: 1007: 1008: 1009: 1010: 1011: 1012: 1013: 1014: 1015: 1016: 1017: 1018: 1019: 1020: 1021: 1022: 1023: 1024: 1025: 1026: 1027: 1028: 1029: 1030: 1031: 1032: 1033: 1034: 1035: 1036: 1037: 1038: 1039: 1040: 1041: 1042: 1043: 1044: 1045: 1046: 1047: 1048: 1049: 1050: 1051: 1052: 1053: 1054: 1055: 1056: 1057: 1058: 1059: 1060: 1061: 1062: 1063: 1064: 1065: 1066: 1067: 1068: 1069: 1070: 1071: 1072: 1073: 1074: 1075: 1076: 1077: 1078: 1079: 1080: 1081: 1082: 1083: 1084: 1085: 1086: 1087: 1088: 1089: 1090: 1091: 1092: 1093: 1094: 1095: 1096: 1097: 1098: 1099: 1100: 1101: 1102: 1103: 1104: 1105: 1106: 1107: 1108: 1109: 1110: 1111: 1112: 1113: 1114: 1115: 1116: 1117: 1118: 1119: 1120: 1121: 1122: 1123: 1124: 1125: 1126: 1127: 1128: 1129: 1130: 1131: 1132: 1133: 1134: 1135: 1136: 1137: 1138: 1139: 1140: 1141: 1142: 1143: 1144: 1145: 1146: 1147: 1148: 1149: 1150: 1151: 1152: 1153: 1154: 1155: 1156: 1157: 1158: 1159: 1160: 1161: 1162: 1163: 1164: 1165: 1166: 1167: 1168: 1169: 1170: 1171: 1172: 1173: 1174: 1175: 1176: 1177: 1178: 1179: 1180: 1181: 1182: 1183: 1184: 1185: 1186: 1187: 1188: 1189: 1190: 1191: 1192: 1193: 1194: 1195: 1196: 1197: 1198: 1199: 1200: 1201: 1202: 1203: 1204: 1205: 1206: 1207: 1208: 1209: 1210: 1211: 1212: 1213: 1214: 1215: 1216: 1217: 1218: 1219: 1220: 1221: 1222: 1223: 1224: 1225: 1226: 1227: 1228: 1229: 1230: 1231: 1232: 1233: 1234: 1235: 1236: 1237: 1238: 1239: 1240: 1241: 1242: 1243: 1244: 1245: 1246: 1247: 1248: 1249: 1250: 1251: 1252: 1253: 1254: 1255: 1256: 1257: 1258: 1259: 1260: 1261: 1262: 1263: 1264: 1265: 1266: 1267: 1268: 1269: 1270: 1271: 1272: 1273: 1274: 1275: 1276: 1277: 1278: 1279: 1280: 1281: 1282: 1283: 1284: 1285: 1286: 1287: 1288: 1289: 1290: 1291: 1292: 1293: 1294: 1295: 1296: 1297: 1298: 1299: 1300: 1301: 1302: 1303: 1304: 1305: 1306: 1307: 1308: 1309: 1310: 1311: 1312: 1313: 1314: 1315: 1316: 1317: 1318: 1319: 1320: 1321: 1322: 1323: 1324: 1325: 1326: 1327: 1328: 1329: 1330: 1331: 1332: 1333: 1334: 1335: 1336: 1337: 1338: 1339: 1340: 1341: 1342: 1343: 1344: 1345: 1346: 1347: 1348: 1349: 1350: 1351: 1352: 1353: 1354: 1355: 1356: 1357: 1358: 1359: 1360: 1361: 1362: 1363: 1364: 1365: 1366: 1367: 1368: 1369: 1370: 1371: 1372: 1373: 1374: 1375: 1376: 1377: 1378: 1379: 1380: 1381: 1382: 1383: 1384: 1385: 1386: 1387: 1388: 1389: 1390: 1391: 1392: 1393: 1394: 1395: 1396: 1397: 1398: 1399: 1400: 1401: 1402: 1403: 1404: 1405: 1406: 1407: 1408: 1409: 1410: 1411: 1412: 1413: 1414: 1415: 1416: 1417: 1418: 1419: 1420: 1421: 1422: 1423: 1424: 1425: 1426: 1427: 1428: 1429: 1430: 1431: 1432: 1433: 1434: 1435: 1436: 1437: 1438: 1439: 1440: 1441: 1442: 1443: 1444: 1445: 1446: 1447: 1448: 1449: 1450: 1451: 1452: 1453: 1454: 1455: 1456: 1457: 1458: 
<?php
/**
 * Class provides a front-facing JSON API that makes it possible to query & input data within the Leads database
 * @package     Shared
 * @subpackage  APIs
 */

/* Exit if accessed directly */
if (!defined('ABSPATH')) {
    exit;
}


/**
 * Inbound_API Class
 *
 * Renders API returns as a JSON array
 *
 */
class Inbound_API {

    /**
     * API Version
     */
    const VERSION = '1';

    /**
     * Pretty Print?
     *
     * @var bool
     * @since 1.5
     */
    static $pretty_print = false;

    /**
     * Log API requests?
     *
     * @var bool
     * @access static
     * @since 1.5
     */
    static $log_requests = true;

    /**
     * Is this a valid request?
     *
     * @var bool
     * @access static
     * @since 1.5
     */
    static $is_valid_request = false;

    /**
     * User ID Performing the API Request
     *
     * @var int
     * @access static
     * @since 1.5.1
     */
    static $user_id = 0;

    /**
     * Instance of EDD Stats class
     *
     * @var object
     * @access static
     */
    static $stats;

    /**
     * Response data to return
     *
     * @var array
     * @access static
     */
    static $data = array();

    /**
     *
     * @var bool
     * @access static
     */
    static $override = true;

    /**
     *
     * @var integer
     * @access static
     */
    static $results_per_page = 50;

    /**
     *
     * @var string
     * @access static
     */
    static $tracking_endpoint = 'inbound';

    /**
     * Initialize the Inbound Leads API
     *
     */
    public function __construct() {
        /* Create endpoint listeners */
        add_action('init', array(__CLASS__, 'add_endpoint'));

        /* Build Query Router */
        add_action('template_redirect', array(__CLASS__, 'process_api_query'), -1);
        add_action('template_redirect', array(__CLASS__, 'process_tracked_link'), -1);

        /* Determine if JSON_PRETTY_PRINT is available */
        self::$pretty_print = defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : null;

        /* Allow API request logging to be turned off */
        self::$log_requests = apply_filters('inbound_api_log_requests', self::$log_requests);

    }

    /**
     * Registers a new rewrite endpoint for accessing the API
     *
     * @access public
     * @param array $rewrite_rules WordPress Rewrite Rules
     *
     */
    public static function add_endpoint($rewrite_rules) {

        /* for API calls */
        add_rewrite_endpoint('inbound-api', EP_ALL);

        /* for click event tracking */
        self::$tracking_endpoint = apply_filters('inbound_event_endpoint', self::$tracking_endpoint);
        add_rewrite_endpoint(self::$tracking_endpoint, EP_ALL);
    }

    /**
     * Validate the API request
     *
     * Checks for the user's public key and token against the secret key
     *
     * @access private
     * @global object $wp_query WordPress Query
     * @uses Inbound_API::get_user()
     * @uses Inbound_API::invalid_key()
     * @uses Inbound_API::invalid_auth()
     * @return void
     */
    private static function validate_request() {
        global $wp_query;

        self::$override = false;

        /* Check for presence of keys and tokens */
        if (empty($_REQUEST['token']) || empty($_REQUEST['key'])) {
            self::missing_auth();
        }

        /* Retrieve the user by public API key and ensure they exist */
        if (!($user = self::get_user($_REQUEST['key']))) {
            self::invalid_key();
        } else {
            $token = urldecode($_REQUEST['token']);
            $secret = get_user_meta($user, 'inbound_user_secret_key', true);
            $public = urldecode($_REQUEST['key']);

            if (hash('md5', $secret . $public) === $token) {
                self::$is_valid_request = true;
            } else {
                self::invalid_auth();
            }
        }

    }

    /**
     * Retrieve the user ID based on the public key provided
     *
     * @access public
     * @global object $wpdb Used to query the database using the WordPress Database API
     *
     * @param string $key Public Key
     *
     * @return bool if user ID is found, false otherwise
     */
    public static function get_user($key = '') {
        global $wpdb, $wp_query;

        if (empty($key))
            $key = urldecode($_REQUEST['key']);

        if (empty($key)) {
            return false;
        }

        $user = get_transient(md5('inbound_api_user_' . $key));

        if (false === $user) {
            $user = $wpdb->get_var($wpdb->prepare("SELECT user_id FROM $wpdb->usermeta WHERE meta_key = 'inbound_user_public_key' AND meta_value = %s LIMIT 1", $key));
            set_transient(md5('inbound_api_user_' . $key), $user, DAY_IN_SECONDS);
        }

        if ($user != NULL) {
            self::$user_id = $user;
            return $user;
        }

        return false;
    }

    /**
     * Get tracked link arguments given a storage token
     * @param $token
     * @return array|mixed
     */
    public static function get_args_from_token($token) {
        global $wpdb;

        /* Pull record from database */
        $table_name = $wpdb->prefix . "inbound_tracked_links";
        $profiles = $wpdb->get_results("SELECT * FROM {$table_name} where `token` = '{$token}' ;");

        if (empty($profiles)) {
            return array();
        }

        /* Get first result & prepare args */
        $profile = $profiles[0];
        $args = unserialize($profile->args);

        return $args;
    }

    /**
     * Displays a missing authentication error if all the parameters aren't
     * provided
     *
     * @access private
     * @uses Inbound_API::output()
     */
    private static function missing_auth() {
        $error['error'] = __('You must specify both a token and API key!', 'inbound-pro');

        self::$data = $error;
        self::output(401);
    }

    /**
     * Displays an authentication failed error if the user failed to provide valid
     * credentials
     *
     * @access private
     * @uses Inbound_API::output()
     * @return void
     */
    private static function invalid_auth() {
        $error['error'] = __('Your request could not be authenticated! (check your token)', 'inbound-pro');

        self::$data = $error;
        self::output(401);
    }

    /**
     * Displays an invalid API key error if the API key provided couldn't be
     * validated
     *
     * @access private
     * @uses Inbound_API::output()
     * @return void
     */
    private static function invalid_key() {
        $error['error'] = __('Invalid API key!', 'inbound-pro');

        self::$data = $error;
        self::output(401);
    }

    /**
     * Validates parameter type
     *
     * @access private
     * @uses Inbound_API::output()
     * @param MIXED $value value to measure
     * @param $accepted value type desired
     * @return $value or die();
     */
    private static function validate_parameter($value, $key, $accepted) {

        if (gettype($value) == $accepted) {
            return $value;
        }

        $error['error'] = sprintf(__('Invalid parameter provided. Expecting a %1$s for \'%2$s\' while a field type with %3$s was provided', 'inbound-pro'), $accepted, $key, gettype($value));

        self::$data = $error;
        self::output(401);
    }

    /**
     * Displays an invalid parameter error
     *
     * @access private
     * @uses Inbound_API::output()
     * @return void
     */
    private static function invalid_parameter($key, $accepted, $provided) {
        $error['error'] = sprintf(__('Invalid parameter provided. Expecting %1$s for %2$s the %3$s was provided', 'inbound-pro'), $accepted, $key, $provided);

        self::$data = $error;
        self::output(401);
    }

    /**
     * Displays generic WP_Error
     *
     * @access private
     * @uses Inbound_API::output()
     * @return void
     */
    private static function throw_wp_error($error_obj) {
        $error['error'] = $error_obj->get_error_message();

        self::$data = $error;
        self::output(401);
    }


    /**
     * Listens for the API and then processes the API requests
     *
     * @access public
     * @global $wp_query
     * @return void
     */
    public static function process_api_query() {
        global $wp_query;

        /* Check for inbound-api var. Get out if not present */
        if (!isset($wp_query->query_vars['inbound-api'])) {
            return;
        }

        /* Check for a valid user and set errors if necessary */
        self::validate_request();

        /* Only proceed if no errors have been noted */
        if (!self::$is_valid_request) {
            return;
        }

        if (!defined('INBOUND_DOING_API')) {
            define('INBOUND_DOING_API', true);
        }

        /* Determine the kind of query */
        $query_type = self::get_query_type();

        $data = array();

        switch ($query_type) :

            case 'v1/leads' :
                /* get leads */
                $data = self::leads_get();
                BREAK;

            case 'v1/leads/add' :
                /* Add leads */
                $data = self::leads_add();
                BREAK;

            case 'v1/leads/modify' :
                /* Update lead records */
                $data = self::leads_update();
                BREAK;

            case 'v1/leads/delete' :
                /* delete leads */
                $data = self::leads_delete();
                BREAK;

            case 'v1/lists' :
                /* get lead lists */
                $data = self::lists_get();
                BREAK;

            case 'v1/lists/add' :
                /* add lead lists */
                $data = self::lists_add();
                BREAK;

            case 'v1/lists/modify' :
                /* add lead lists */
                $data = self::lists_update();
                BREAK;

            case 'v1/lists/delete' :
                /* delete lead lists */
                $data = self::lists_delete();
                BREAK;

            case 'v1/field-map' :
                /* add lead lists */
                $data = self::fieldmap_get();
                BREAK;

            case 'v1/analytics/track-link' :
                /* delete lead lists */
                $data = self::analytics_track_links();
                BREAK;

        endswitch;

        /* Allow extensions to setup their own return data */
        self::$data = apply_filters('inbound_api_output_data', $data, $query_type);


        /* Send out data to the output function */
        self::output();
    }

    /**
     * Determines the kind of query requested and also ensures it is a valid query
     *
     * @global $wp_query
     * @return string $query type of query to run
     */
    public static function get_query_type() {
        global $wp_query;

        /* Whitelist our query options */
        $accepted = apply_filters('inbound_api_valid_query_types', array(
            'v1/leads',
            'v1/leads/add',
            'v1/leads/modify',
            'v1/leads/delete',
            'v1/lists',
            'v1/lists/add',
            'v1/lists/modify',
            'v1/lists/delete',
            'v1/field-map',
            'v1/analytics/track-link',
        ));

        $query = isset($wp_query->query_vars['inbound-api']) ? $wp_query->query_vars['inbound-api'] : null;

        /* Make sure our query is valid */
        if (!in_array($query, $accepted)) {
            $error['error'] = __('Invalid endpoint: ' . $query, 'inbound-pro');

            self::$data = $error;
            self::output();
        }

        return $query;
    }

    /**
     * Get page number
     *
     * @access private
     * @global $wp_query
     * @return int $_REQUEST['page'] if page number returned (default: 1)
     */
    public static function get_paged() {
        global $wp_query;

        return isset($_REQUEST['page']) ? $_REQUEST['page'] : 1;
    }

    /**
     * Get number of results per page to return
     * uses REQUEST but falls back on self::$results_per_page
     *
     * @access private
     * @return int
     */
    public static function get_results_per_page() {
        return isset($_REQUEST['results_per_page']) ? $_REQUEST['results_per_page'] : self::$results_per_page;
    }

    /**
     * Sets up the dates used to retrieve leads
     *
     * @access public
     * @since 1.5.1
     * @param array $args Arguments to override defaults
     * @return array $dates
     */
    public static function get_dates($args = array()) {
        $dates = array();

        $defaults = array(
            'type' => '',
            'product' => null,
            'date' => null,
            'startdate' => null,
            'enddate' => null
        );

        $args = wp_parse_args($args, $defaults);

        $current_time = current_time('timestamp');

        if ('range' === $args['date']) {
            $startdate = strtotime($args['startdate']);
            $enddate = strtotime($args['enddate']);
            $dates['day_start'] = date('d', $startdate);
            $dates['day_end'] = date('d', $enddate);
            $dates['m_start'] = date('n', $startdate);
            $dates['m_end'] = date('n', $enddate);
            $dates['year'] = date('Y', $startdate);
            $dates['year_end'] = date('Y', $enddate);
        } else {
            /* Modify dates based on predefined ranges */
            switch ($args['date']) :

                case 'this_month' :
                    $dates['day'] = null;
                    $dates['m_start'] = date('n', $current_time);
                    $dates['m_end'] = date('n', $current_time);
                    $dates['year'] = date('Y', $current_time);
                    break;

                case 'last_month' :
                    $dates['day'] = null;
                    $dates['m_start'] = date('n', $current_time) == 1 ? 12 : date('n', $current_time) - 1;
                    $dates['m_end'] = $dates['m_start'];
                    $dates['year'] = date('n', $current_time) == 1 ? date('Y', $current_time) - 1 : date('Y', $current_time);
                    break;

                case 'today' :
                    $dates['day'] = date('d', $current_time);
                    $dates['m_start'] = date('n', $current_time);
                    $dates['m_end'] = date('n', $current_time);
                    $dates['year'] = date('Y', $current_time);
                    break;

                case 'yesterday' :
                    $month = date('n', $current_time) == 1 && date('d', $current_time) == 1 ? 12 : date('n', $current_time);
                    $days_in_month = cal_days_in_month(CAL_GREGORIAN, $month, date('Y', $current_time));
                    $yesterday = date('d', $current_time) == 1 ? $days_in_month : date('d', $current_time) - 1;
                    $dates['day'] = $yesterday;
                    $dates['m_start'] = $month;
                    $dates['m_end'] = $month;
                    $dates['year'] = $month == 1 && date('d', $current_time) == 1 ? date('Y', $current_time) - 1 : date('Y', $current_time);
                    break;

                case 'this_quarter' :
                    $month_now = date('n', $current_time);

                    $dates['day'] = null;

                    if ($month_now <= 3) {

                        $dates['m_start'] = 1;
                        $dates['m_end'] = 3;
                        $dates['year'] = date('Y', $current_time);

                    } else if ($month_now <= 6) {

                        $dates['m_start'] = 4;
                        $dates['m_end'] = 6;
                        $dates['year'] = date('Y', $current_time);

                    } else if ($month_now <= 9) {

                        $dates['m_start'] = 7;
                        $dates['m_end'] = 9;
                        $dates['year'] = date('Y', $current_time);

                    } else {

                        $dates['m_start'] = 10;
                        $dates['m_end'] = 12;
                        $dates['year'] = date('Y', $current_time);

                    }
                    break;

                case 'last_quarter' :
                    $month_now = date('n', $current_time);

                    $dates['day'] = null;

                    if ($month_now <= 3) {

                        $dates['m_start'] = 10;
                        $dates['m_end'] = 12;
                        $dates['year'] = date('Y', $current_time) - 1; /* Previous year */

                    } else if ($month_now <= 6) {

                        $dates['m_start'] = 1;
                        $dates['m_end'] = 3;
                        $dates['year'] = date('Y', $current_time);

                    } else if ($month_now <= 9) {

                        $dates['m_start'] = 4;
                        $dates['m_end'] = 6;
                        $dates['year'] = date('Y', $current_time);

                    } else {

                        $dates['m_start'] = 7;
                        $dates['m_end'] = 9;
                        $dates['year'] = date('Y', $current_time);

                    }
                    break;

                case 'this_year' :
                    $dates['day'] = null;
                    $dates['m_start'] = null;
                    $dates['m_end'] = null;
                    $dates['year'] = date('Y', $current_time);
                    break;

                case 'last_year' :
                    $dates['day'] = null;
                    $dates['m_start'] = null;
                    $dates['m_end'] = null;
                    $dates['year'] = date('Y', $current_time) - 1;
                    break;

            endswitch;
        }

        /**
         * Returns the filters for the dates used to retrieve earnings/sales
         *
         * @param object $dates The dates used for retrieving earnings/sales
         */

        return apply_filters('inbound_api_stat_dates', $dates);
    }


    /**
     * Retrieve the output data
     *
     * @access public
     * @return array
     */
    public static function get_output() {
        return self::$data;
    }

    /**
     * Output Query in either JSON/XML. The query data is outputted as JSON
     * by default
     *
     * @global $wp_query
     *
     * @param int $status_code
     */
    public static function output($status_code = 200) {
        global $wp_query;

        $format = apply_filters('inbound_api_output_format', 'json');

        status_header($status_code);

        do_action('inbound_api_output_before', self::$data);

        switch ($format) :

            case 'json' :

                header('Content-Type: application/json');
                if (!empty(self::$pretty_print)) {
                    echo json_encode(self::$data, self::$pretty_print);
                } else {
                    echo json_encode(self::$data);
                }

                break;


            default :

                /* Allow other formats to be added via extensions */
                do_action('inbound_api_output_' . $format, self::$data );

                break;

        endswitch;

        do_action('inbound_api_output_after', self::$data);

        die();
    }

    /**
     * Retrieve the user's token
     *
     * @access private
     * @param int $user_id
     * @return string
     */
    private static function get_token($user_id = 0) {
        $user = get_userdata($user_id);
        return hash('md5', $user->inbound_user_secret_key . $user->inbound_user_public_key);
    }

    /**
     *  Query designed to return leads based on conditions defined by user.
     *
     * @access public
     * @param ARRAY $params key/value pairs that will direct the building of WP_Query, optional
     */
    public static function leads_get($params = array()) {

        /* Merge POST & GET & @param vars into array variable */
        $params = array_merge($params, $_REQUEST);

        /* prepare WP_Query defaults */
        $args = self::leads_prepare_defaults($params);

        /* Prepare WP_Query arguments with tax_query rules */
        $args = self::leads_prepare_tax_query($args, $params);

        /* Prepare WP_Query arguments with meta_query rules */
        if (isset($params['meta_query'])) {
            $args['meta_query'] = self::validate_parameter($params['meta_query'], 'meta_query', 'array');
        }

        /* Run Query */
        $results = new WP_Query($args);

        /* If no results let them know */
        if (!$results) {
            $message['message'] = __('No leads were found given this query.', 'inbound-pro');
            self::$data = $message;
            self::output(401);
        }

        /* Secret mod to return results without additional data */
        if (isset($params['fields']) && $params['fields'] == 'ids') {
            return $results;
        }

        /* Get meta data for each result */
        $results = self::prepare_lead_results($results);

        return $results;
    }


    /**
     *  Sets the API defaults for the /leads/(get) endpoint
     *
     * @access public
     * @param ARRAY $params
     * @returns ARRAY $params
     */
    public static function leads_prepare_defaults($params) {

        $args['s'] = (isset($params['email'])) ? self::validate_parameter($params['email'], 'email', 'string') : '';
        $args['p'] = (isset($params['ID'])) ? self::validate_parameter(intval($params['ID']), 'ID', 'integer') : '';
        $args['posts_per_page'] = isset($params['results_per_page']) ? $params['results_per_page'] : self::get_results_per_page();
        $args['paged'] = (isset($params['page'])) ? self::validate_parameter(intval($params['page']), 'page', 'integer') : 1;
        $args['orderby'] = (isset($params['orderby'])) ? $params['orderby'] : 'date';

        if (isset($params['fields'])) {
            $args['fields'] = $params['fields'];
        }


        if ($args['orderby'] != 'rand') {
            $args['order'] = (isset($params['order'])) ? self::validate_parameter($params['order'], 'order_by', 'string') : 'DESC';
        }

        $args['post_type'] = 'wp-lead';

        return $args;
    }

    /**
     *  Builds a tax_query ARRAY from included parameters if applicable.
     *  Used for tag searches and lead list searches.
     *
     * @param ARRAY $args arguments for WP_Query
     * @param ARRAY $params includes param key/value pairs submitted to the api
     * @returns ARRAY $args
     */
    public static function leads_prepare_tax_query($args, $params) {

        /* if tax_query ovverride rules are manually set by user then use them  */
        if (isset($params['tax_query'])) {
            $args['tax_query'] = $params['tax_query'];
            return $args;
        }

        if (isset($params['include_lists']) || isset($params['exclude_lists']) || isset($params['include_tags']) || isset($params['exclude_tags'])) {
            $args['tax_query']['relation'] = 'AND';
        }

        if (isset($params['include_lists'])) {
            $args['tax_query'][] = array(
                'taxonomy' => 'wplead_list_category',
                'field' => 'term_id',
                'terms' => self::validate_parameter($params['include_lists'], 'include_lists', 'array'),
                'operator' => 'IN',
            );
        }

        if (isset($params['exclude_lists'])) {
            $args['tax_query'][] = array(
                'taxonomy' => 'wplead_list_category',
                'field' => 'term_id',
                'terms' => self::validate_parameter($params['exclude_lists'], 'exclude_lists', 'array'),
                'operator' => 'NOT IN',
            );
        }

        if (isset($params['include_tags'])) {
            $tags = self::get_tag_ids(self::validate_parameter($params['include_tags'], 'include_tags', 'array'));
            $args['tax_query'][] = array(
                'taxonomy' => 'lead-tags',
                'field' => 'term_id',
                'terms' => $tags,
                'operator' => 'AND'
            );
        }

        if (isset($params['exclude_tags'])) {
            $tags = self::get_tag_ids(self::validate_parameter($params['exclude_tags'], 'exclude_tags', 'array'));
            $args['tax_query'][] = array(
                'taxonomy' => 'lead-tags',
                'field' => 'ID',
                'terms' => $tags,
                'operator' => 'NOT IN'
            );
        }


        return $args;
    }


    /**
     *  Get tag ids from given names
     * @param ARRAY $tags contains array of tag names
     * @returns ARRAY $tag_ids contains array of tag term ids
     */
    public static function get_tag_ids($tags) {
        $tag_ids = array();

        foreach ($tags as $name) {
            $tag = get_term_by('name', $name, 'lead-tags');

            if ($tag) {
                $tag_ids[] = $tag->term_id;
            }
        }

        return $tag_ids;
    }


    /**
     *  Converts WP_Query object into array and imports additional lead data
     *
     * @param OBJECT $results WP_Query results
     * @return ARRAY $leads updated array of results
     */
    public static function prepare_lead_results($results) {

        if (!$results->have_posts()) {
            return null;
        }

        $leads = array();
        $leads['results_count'] = $results->found_posts;
        $leads['results_per_page'] = self::get_results_per_page();
        $leads['max_pages'] = $results->max_num_pages;

        while ($results->have_posts()) : $results->the_post();

            $ID = $results->post->ID;

            /* set ID */
            $leads['results'][$ID]['ID'] = $ID;

            /* set lead lists */
            $lists = get_the_terms($ID, 'wplead_list_category');
            $leads['results'][$ID]['lists'] = $lists;

            /* set lead tags */
            $tags = get_the_terms($ID, 'lead-tags');
            $leads['results'][$ID]['tags'] = $tags;

            /* set lead meta data */
            $meta_data = get_post_custom($ID);
            $leads['results'][$ID]['meta_data'] = $meta_data;

            /* set the lead sources */
            $leads['results'][$ID]['sources'] = Inbound_Events::get_lead_sources($ID);

        endwhile;

        return $leads;
    }

    /**
     *  Adds a lead to the wp-lead custom post type
     * @param ARRAY $params key/value pairs that will direct the building of WP_Query, optional
     */
    public static function leads_add($params = array()) {


        /* Merge POST & GET & @param vars into array variable */
        $params = array_merge($params, $_REQUEST);

        /* Account for Zapier */
        if (!isset($params['meta_data']) && file_get_contents('php://input')) {
            $params = json_decode(file_get_contents('php://input'), true);
        }

        /* check if meta_data is http query  */
        if (!is_array($params['meta_data']) && strstr($params['meta_data'], '=')) {
            parse_str($params['meta_data'], $params['meta_data']);
        }

        /* Make sure our meta_data field is setup correctly */
        self::validate_parameter($params['meta_data'], 'meta_data', 'array');

        $args = array(
            'post_title' => self::validate_parameter($params['meta_data']['wpleads_email_address'], 'meta_data[wpleads_email_address]', 'string'), /* validate email address */
            'post_status' => 'publish',
            'post_type' => 'wp-lead'
        );

        /* check if lead exists */
        $already_exists = self::leads_get(array('email' => $params['meta_data']['wpleads_email_address']));

        if ($already_exists) {
            $error['error'] = __('Lead already exists.', 'inbound-pro');

            self::$data = $error;
            self::output(401);
        }

        /* Insert Lead */
        $lead_id = wp_insert_post($args, true);

        /* Check for error and send message back if contains error */
        if (is_wp_error($lead_id)) {
            self::throw_wp_error($lead_id);
        }

        /* determine last name from first name */
        if (isset($params['meta_data']['wpleads_first_name']) && !isset($params['meta_data']['wpleads_last_name'])) {
            $split = explode(' ', $params['meta_data']['wpleads_first_name']);
            $params['meta_data']['wpleads_first_name'] = ($split[0]) ? $split[0] : $params['meta_data']['wpleads_first_name'];
            $params['meta_data']['wpleads_last_name'] = (isset($split[1])) ? $split[1] : '';
        }

        /* Add meta data to lead record */
        foreach ($params['meta_data'] as $key => $value) {
            update_post_meta($lead_id, $key, $value);
        }

        /* Add lead to lists */
        if (isset($params['lead_lists']) && !is_array($params['lead_lists'])) {
            $params['lead_lists'] = explode(',', $params['lead_lists']);
        }

        if (isset($params['lead_lists']) && self::validate_parameter($params['lead_lists'], 'lead_lists', 'array')) {
            foreach ($params['lead_lists'] as $list_id) {
                Inbound_Leads::add_lead_to_list($lead_id, $list_id);
            }
        }

        /* Add tag to leads */
        if (isset($params['tags']) && !is_array($params['tags']) && $params['tags']) {
            $params['tags'] = explode(',', $params['tags']);
        }

        if (isset($params['tags']) && self::validate_parameter($params['tags'], 'tags', 'array')) {
            foreach ($params['tags'] as $tag) {
                Inbound_Leads::add_tag_to_lead($lead_id, $tag);
            }
        }

        return self::leads_get(array('ID' => $lead_id));

    }

    /**
     *  Updates a Lead profile
     * @param ARRAY $params key/value pairs that will assist database queries
     * @global OBJECT $Inbound_Leads Inbound_Leads
     */
    public static function leads_update($params = array()) {


        /* Merge POST & GET & @param vars into array variable */
        $params = array_merge($params, $_REQUEST);

        /* Validate lead ID param */
        if (isset($params['ID'])) {
            self::validate_parameter(intval($params['ID']), 'ID', 'integer');
        }

        /* if email is set get lead ID by email */
        if (isset($params['email'])) {
            $result = self::leads_get(array('email' => $params['email']));
            if (isset($result['results'])) {
                $params['ID'] = key($result['results']);
            }
        }

        /* ID must be set by this point */
        if (!isset($params['ID'])) {
            $error['error'] = __('Valid ID or email address not set.', 'inbound-pro');
            self::$data = $error;
            self::output(401);
        }

        /* Update email address in post_title if email is being updated */
        if (isset($params['meta_data']['wpleads_email_address'])) {
            $args = array(
                'ID' => $params['ID'],
                'post_title' => self::validate_parameter($params['meta_data']['wpleads_email_address'], 'meta_data[wpleads_email_address]', 'string'),
                'post_status' => 'publish',
                'post_type' => 'wp-lead'
            );
            wp_update_post($args);
        }

        /* Update meta data */
        if (isset($params['meta_data'])) {

            /* Make sure our meta_data field is setup correctly */
            self::validate_parameter($params['meta_data'], 'meta_data', 'array');

            /* Loop through meta data fields and update key/value pairs */
            foreach ($params['meta_data'] as $key => $value) {
                update_post_meta($params['ID'], $key, $value);
            }
        }

        /* Add lead to lists  */
        if (isset($params['add_to_lists'])) {

            /* Make sure our add_to_lists field is setup correctly */
            self::validate_parameter($params['add_to_lists'], 'add_to_lists', 'array');

            /* Loop through list ids and add */
            foreach ($params['add_to_lists'] as $list_id) {
                Inbound_Leads::add_lead_to_list($params['ID'], $list_id);
            }
        }

        /* Remove lead from lists */
        if (isset($params['remove_from_lists'])) {

            /* Make sure our remove_from_lists field is setup correctly */
            self::validate_parameter($params['remove_from_lists'], 'remove_from_lists', 'array');

            /* Loop through list ids and remove */
            foreach ($params['remove_from_lists'] as $list_id) {
                Inbound_Leads::remove_lead_from_list($params['ID'], $list_id);
            }
        }

        /* add tags to lead */
        if (isset($params['add_tags'])) {

            /* Make sure our add_tags field is setup correctly */
            self::validate_parameter($params['add_tags'], 'add_tags', 'array');

            /* Loop through tags and add */
            foreach ($params['add_tags'] as $tag) {
                Inbound_Leads::add_tag_to_lead($params['ID'], $tag);
            }
        }

        /* remove tags from lead */
        if (isset($params['remove_tags'])) {

            /* Make sure our remove_tags field is setup correctly */
            self::validate_parameter($params['remove_tags'], 'remove_tags', 'array');

            /* Loop through tags and remove */
            foreach ($params['remove_tags'] as $tag) {
                Inbound_Leads::remove_tag_from_lead($params['ID'], $tag);
            }
        }

        return self::leads_get(array('ID' => $params['ID']));
    }

    /**
     *  Permanently deletes a lead profile
     * @param ARRAY $params key/value pairs
     */
    public static function leads_delete($params = array()) {

        /* Merge POST & GET & @param vars into array variable */
        $params = array_merge($params, $_REQUEST);

        /* Validate lead ID param */
        if (isset($params['ID'])) {
            self::validate_parameter(intval($params['ID']), 'ID', 'integer');
        } /* if email is set get lead ID by email */
        else if (isset($params['email'])) {
            $params['ID'] = self::leads_get_id_from_email($params['email']);

            self::validate_parameter($params['email'], 'email', 'string');

            /* perform lead lookup by email */
            $result = self::leads_get(array('email' => $params['email']));

            /* get lead id if lookup successful */
            if (isset($result['results'])) {
                $params['ID'] = key($result['results']);
            }
        }

        /* ID must be set by this point */
        if (!isset($params['ID'])) {
            $error['error'] = __('Valid ID or email address not set.', 'inbound-pro');
            self::$data = $error;
            self::output(401);
        }

        /* Delete lead */
        wp_delete_post($params['ID'], true);

        return array(
            'message' => __('Lead successfully deleted', 'inbound-pro'),
            'ID' => $params['ID']
        );
    }

    /**
     *  Get lead ID from lead email address
     * @param STRING $email lead email address
     * @return INT $id
     */
    public static function leads_get_id_from_email($email) {

        self::validate_parameter($email, 'email', 'string');

        /* perform lead lookup by email */
        $result = self::leads_get(array('email' => $email));

        /* get lead id if lookup successful */
        if (isset($result['results'])) {
            return key($result['results']);
        } else {
            return null;
        }

    }

    /**
     *  Gets all lead lists
     * @global OBJECT $Inbound_Leads Inbound_Leads
     */
    public static function lists_get() {


        return Inbound_Leads::get_lead_lists_as_array();
    }

    /**
     *  Create a new lead list
     * @global OBJECT $Inbound_Leads class Inbound_Leads
     */
    public static function lists_add($params = array()) {


        /* Merge POST & GET & @param vars into array variable */
        $params = array_merge($params, $_REQUEST);

        self::validate_parameter($params['name'], 'name', 'string');

        /* Prepare list description */
        if (isset($params['description'])) {
            self::validate_parameter($params['description'], 'description', 'string');
        } else {
            $params['description'] = '';
        }

        /* Prepare parent */
        if (isset($params['parent'])) {
            self::validate_parameter($params['parent'], 'parent', 'string');
        } else {
            $params['parent'] = '';
        }

        return Inbound_Leads::create_lead_list($params);
    }

    /**
     *  Updates a list's data
     * @global OBJECT $Inbound_Leads class Inbound_Leads
     * @return ARRAY
     */
    public static function lists_update($params = array()) {


        /* Merge POST & GET & @param vars into array variable */
        $params = array_merge($params, $_REQUEST);

        /* Get list id */
        if (isset($params['id'])) {
            self::validate_parameter(intval($params['id']), 'id', 'integer');
        } else {
            $error['error'] = __('This endpoint requires that the \'id\' be set.', 'inbound-pro');
            self::$data = $error;
            self::output(401);
        }

        /* Prepare new list name if available */
        if (isset($params['name'])) {
            self::validate_parameter($params['name'], 'name', 'string');
        } else {
            $params['name'] = '';
        }

        /* Prepare new list description if available */
        if (isset($params['description'])) {
            self::validate_parameter($params['description'], 'description', 'string');
        } else {
            $params['description'] = '';
        }

        /* Prepare new parent if available*/
        if (isset($params['parent'])) {
            self::validate_parameter(intval($params['parent']), 'parent', 'integer');
        } else {
            $params['parent'] = 0;
        }

        return Inbound_Leads::update_lead_list($params);
    }

    /**
     *  Deletes a lead list
     */
    public static function lists_delete($params = array()) {


        /* Merge POST & GET & @param vars into array variable */
        $params = array_merge($params, $_REQUEST);

        /* Get list id */
        if (isset($params['id'])) {
            self::validate_parameter(intval($params['id']), 'id', 'integer');
        } else {
            $error['error'] = __('This endpoint requires that the \'id\' be set.', 'inbound-pro');
            self::$data = $error;
            self::output(401);
        }

        return Inbound_Leads::delete_lead_list($params['id']);
    }

    /**
     *  Gets an array of mappable lead meta keys with their labels
     */
    public static function fieldmap_get() {
        $lead_fields = Leads_Field_Map::build_map_array();
        array_shift($lead_fields);
        return $lead_fields;
    }

    /**
     *  Generates random token
     * @param length
     */
    public static function generate_token($min = 7, $max = 11) {
        $length = mt_rand($min, $max);
        return substr(str_shuffle("0123456789iloveinboundnow"), 0, $length);
    }

    /**
     *  Stores tracked link data into wp_inbound_tracked_links table
     * @param ARRAY $args passed arguments
     */
    public static function analytics_get_tracking_code($args = array()) {
        global $wpdb;

        $table_name = $wpdb->prefix . "inbound_tracked_links";

        /* check args to see if token already exists */
        $results = $wpdb->get_results("SELECT * FROM $table_name WHERE args = '" . serialize($args) . "' LIMIT 1", ARRAY_A);
        if ($results) {
            return $results[0]['token'];
        }

        $token = self::generate_token();

        $wpdb->insert(
            $table_name,
            array(
                'token' => $token,
                'args' => serialize($args)
            )
        );

        /* return tracked link */
        return $token;
    }

    /**
     *  Generate tracked link
     */
    public static function analytics_track_links($params = array()) {

        /* Merge POST & GET & @param vars into array variable */
        $params = array_merge($params, $_REQUEST);

        /* lead email or lead id required */
        if (!isset($params['id']) && !isset($params['email_id']) && !isset($params['cta_id']) && !isset($params['page_id'])) {
            $error['error'] = __('This endpoint requires either the \'id\' or the \'email\' or the \'cta_id\'or the \'page_id\' parameter be set.', 'inbound-pro');
            self::$data = $error;
            self::output(401);
        }

        /* a link to mask is required */
        if (!isset($params['url']) && !isset($params['url'])) {
            $error['error'] = __('This endpoint requires the \'url\' parameter be set.', 'inbound-pro');
            self::$data = $error;
            self::output(401);
        }

        /* a tracking_id is required */
        if (!isset($params['tracking_id'])) {
            $error['error'] = __('This endpoint requires the \'tracking_id\' parameter be set.', 'inbound-pro');
            self::$data = $error;
            self::output(401);
        }

        $args = $params;

        unset($args['token']);
        unset($args['key']);


        /* Set custom_data */
        if (isset($params['custom_data'])) {
            self::validate_parameter($params['custom_data'], 'custom_data', 'array');

            $args = array_merge($args, $params['custom_data']);
        }

        /* get token args */
        $token = self::analytics_get_tracking_code($args);

        /* get tracked link */
        $tracked_link = get_site_url(get_current_blog_id(), self::$tracking_endpoint . '/' . $token);

        return array('url' => $tracked_link);
    }


    /**
     * Listens for the tracked links and update lead event profile
     *
     * @access public
     * @global $wp_query
     * @return void
     */
    public static function process_tracked_link() {
        global $wp_query, $wpdb;

        /* Check for inbound-api var. Get out if not present */
        if (!isset($wp_query->query_vars[self::$tracking_endpoint]) && (isset($_SERVER["REQUEST_URI"]) && !strstr($_SERVER["REQUEST_URI"], self::$tracking_endpoint . '/'))) {
            return;
        }

        /* discover token */
        $parts = explode(self::$tracking_endpoint . '/', $_SERVER["REQUEST_URI"]);
        $token = (isset($wp_query->query_vars[self::$tracking_endpoint])) ? $wp_query->query_vars[self::$tracking_endpoint] : $parts[1];

        /* Pull record from database */
        $args = self::get_args_from_token($token);

        /* If no results exist send user to homepage */
        if (!$args) {
            /* redirect to  url */
            header('Location: ' . get_site_url());
            exit;
        }

        /* get lead id from cookie if it exists */
        $lead_id_cookie = (isset($_COOKIE['wp_lead_id'])) ? $_COOKIE['wp_lead_id'] : 0;

        /* if lead_id is set then apply it to 'id' */
        $args['id'] = (isset($args['lead_id']) && $args['lead_id']) ? $args['lead_id'] : 0;

        /* if no lead_id so far then fall back on cookie value */
        $args['id'] = (isset($args['id']) && $args['id']) ? $args['id'] : $lead_id_cookie;

        /* cookie lead id if availabled and not cookied */
        if (!isset($_COOKIE['wp_lead_id']) && $args['id']) {
            setcookie('wp_lead_id', $args['id'], time() + (20 * 365 * 24 * 60 * 60), '/');
        }

        /* process extra lead events */
        if ($args['id']) {

            /* create redundant key */
            $args['lead_id'] = $args['id'];

            /* Add lead to lists */
            if (isset($args['add_lists']) && self::validate_parameter($args['add_lists'], 'add_lists', 'array')) {
                foreach ($args['add_lists'] as $list_id) {
                    Inbound_Leads::add_lead_to_list($args['id'], $list_id);
                }
            }

            /* Remove lead from lists */
            if (isset($args['remove_lists']) && self::validate_parameter($args['remove_lists'], 'remove_lists', 'array')) {

                foreach ($args['remove_lists'] as $list_id) {
                    Inbound_Leads::remove_lead_from_list($args['id'], $list_id);
                }
            }

            /* Add tag to leads */
            if (isset($args['add_tags']) && self::validate_parameter($args['add_tags'], 'add_tags', 'array')) {
                foreach ($args['add_tags'] as $tag) {
                    Inbound_Leads::add_tag_to_lead($args['id'], $tag);
                }
            }

            /* Remvoe tags from leads */
            if (isset($args['remove_tags']) && self::validate_parameter($args['remove_tags'], 'remove_tags', 'array')) {
                foreach ($args['remove_tags'] as $tag) {
                    Inbound_Leads::remove_tag_from_lead($args['id'], $tag);
                }
            }
        }

        /* check for known bots and ignore */
        if (isset($_SERVER['HTTP_USER_AGENT']) && preg_match('/bot|crawl|slurp|spider/i', $_SERVER['HTTP_USER_AGENT'])) {
            return;
        }

        /* Process tracked link extras */
        do_action('inbound_track_link', $args);

        /* redirect to  url */
        header('Location: ' . $args['url']);
        exit;
    }
}

new Inbound_API();

Inbound Pro Plugin - PHP Codex API documentation generated by ApiGen