CF7DBPlugin

Implementation for CF7DBPluginLifeCycle.

Defined (1)

The class is defined in the following location(s).

/CF7DBPlugin.php  
  1. class CF7DBPlugin extends CF7DBPluginLifeCycle implements CFDBDateFormatter { 
  2.  
  3. public function getPluginDisplayName() { 
  4. return 'Contact Form to DB Extension'; 
  5.  
  6. protected function getMainPluginFileName() { 
  7. return 'contact-form-7-db.php'; 
  8.  
  9. public function getOptionMetaData() { 
  10. return array( 
  11. //'_version' => array('Installed Version'), // For testing upgrades 
  12. //'Donated' => array(__('I have donated to this plugin', 'contact-form-7-to-database-extension'), 'false', 'true'),  
  13. 'IntegrateWithCF7' => array(__('Capture form submissions from Contact Form 7 Plugin', 'contact-form-7-to-database-extension'), 'true', 'false'),  
  14. 'IntegrateWithFSCF' => array(__('Capture form submissions from Fast Secure Contact Form Plugin', 'contact-form-7-to-database-extension'), 'true', 'false'),  
  15. 'IntegrateWithJetPackContactForm' => array(__('Capture form submissions from JetPack Contact Form', 'contact-form-7-to-database-extension'), 'true', 'false'),  
  16. 'IntegrateWithGravityForms' => array(__('Capture form submissions from Gravity Forms', 'contact-form-7-to-database-extension'), 'true', 'false'),  
  17. 'IntegrateWithWrContactForms' => array(__('Capture form submissions from WR ContactForm', 'contact-form-7-to-database-extension'), 'true', 'false'),  
  18. 'IntegrateWithQuform' => array(__('Capture form submissions from Quform', 'contact-form-7-to-database-extension'), 'true', 'false'),  
  19. 'IntegrateWithNinjaForms' => array(__('Capture form submissions from Ninja Forms', 'contact-form-7-to-database-extension'), 'true', 'false'),  
  20. 'IntegrateWithCalderaForms' => array(__('Capture form submissions from Caldera Forms', 'contact-form-7-to-database-extension'), 'true', 'false'),  
  21. 'IntegrateWithEnfoldThemForms' => array(__('Capture form submissions from Enfold Theme', 'contact-form-7-to-database-extension'), 'true', 'false'),  
  22. 'CanSeeSubmitData' => array(__('Can See Submission data', 'contact-form-7-to-database-extension'),  
  23. 'Administrator', 'Editor', 'Author', 'Contributor', 'Subscriber', 'Anyone'),  
  24. 'HideAdminPanelFromNonAdmins' => array(__('Allow only Administrators to see CFDB administration screens', 'contact-form-7-to-database-extension'), 'false', 'true'),  
  25. 'CanSeeSubmitDataViaShortcode' => array(__('Can See Submission when using shortcodes', 'contact-form-7-to-database-extension'),  
  26. 'Administrator', 'Editor', 'Author', 'Contributor', 'Subscriber', 'Anyone'),  
  27. 'CanChangeSubmitData' => array(__('Can Edit/Delete Submission data', 'contact-form-7-to-database-extension'),  
  28. 'Administrator', 'Editor', 'Author', 'Contributor', 'Subscriber', 'Anyone'),  
  29. 'GenerateSubmitTimeInCF7Email' => array(__('Generate [submit_time] tag for Contact Form 7 email', 'contact-form-7-to-database-extension'), 'false', 'true'),  
  30. 'FunctionsInShortCodes' => array(__('Allow Any Function in Short Codes', 'contact-form-7-to-database-extension') . 
  31. ' <a target="_blank" href="http://cfdbplugin.com/?page_id=1073">' . __('(Creates a security hole)', 'contact-form-7-to-database-extension') . '</a>', 'false', 'true'),  
  32. 'AllowRSS' => array(__('Allow RSS URLs', 'contact-form-7-to-database-extension') . 
  33. ' <a target="_blank" href="http://cfdbplugin.com/?p=918">' . __('(Creates a security hole)', 'contact-form-7-to-database-extension') . '</a>', 'false', 'true'),  
  34. 'Timezone' => array(__('Timezone to capture Submit Time. Blank will use WordPress Timezone setting. <a target="_blank" href="http://www.php.net/manual/en/timezones.php">Options</a>', 'contact-form-7-to-database-extension')),  
  35. 'MaxRows' => array(__('Maximum number of rows to retrieve from the DB for the Admin display', 'contact-form-7-to-database-extension')),  
  36. 'MaxVisibleRows' => array(__('#Rows (of maximum above) visible in the Admin datatable', 'contact-form-7-to-database-extension')),  
  37. 'HorizontalScroll' => array(__('Use fixed width in Admin datatable', 'contact-form-7-to-database-extension'), 'true', 'false'),  
  38. 'UseDataTablesJS' => array(__('Use Javascript-enabled tables in Admin Database page', 'contact-form-7-to-database-extension'), 'true', 'false'),  
  39. 'ShowLineBreaksInDataTable' => array(__('Show line breaks in submitted data table', 'contact-form-7-to-database-extension'), 'true', 'false'),  
  40. 'UseCustomDateTimeFormat' => array(__('Use Custom Date-Time Display Format (below)', 'contact-form-7-to-database-extension'), 'true', 'false'),  
  41. 'SubmitDateTimeFormat' => array('<a target="_blank" href="http://php.net/manual/en/function.date.php">' . __('Date-Time Display Format', 'contact-form-7-to-database-extension') . '</a>'),  
  42. 'ShowFileUrlsInExport' => array(__('Export URLs instead of file names for uploaded files', 'contact-form-7-to-database-extension'), 'false', 'true'),  
  43. 'NoSaveFields' => array(__('Do not save <u>fields</u> in DB named (comma-separated list, no spaces)', 'contact-form-7-to-database-extension')),  
  44. 'NoSaveForms' => array(__('Do not save <u>forms</u> in DB named (comma-separated list, no spaces)', 'contact-form-7-to-database-extension')),  
  45. 'SaveCookieData' => array(__('Save Cookie Data with Form Submissions', 'contact-form-7-to-database-extension'), 'false', 'true'),  
  46. 'SaveCookieNames' => array(__('Save only cookies in DB named (comma-separated list, no spaces, and above option must be set to true)', 'contact-form-7-to-database-extension')),  
  47. 'ShowQuery' => array(__('Show the query used to display results', 'contact-form-7-to-database-extension'), 'false', 'true'),  
  48. 'ErrorOutput' => array(__('Error output file (full path) or email address', 'contact-form-7-to-database-extension')),  
  49. 'DropOnUninstall' => array(__('Drop this plugin\'s Database table on uninstall', 'contact-form-7-to-database-extension'), 'false', 'true'),  
  50. //'SubmitTableNameOverride' => array(__('Use this table to store submission data rather than the default (leave blank for default)', 'contact-form-7-to-database-extension')) 
  51. ); 
  52.  
  53. protected function getOptionValueI18nString($optionValue) { 
  54. switch ($optionValue) { 
  55. case 'true': 
  56. return __('true', 'contact-form-7-to-database-extension'); 
  57. case 'false': 
  58. return __('false', 'contact-form-7-to-database-extension'); 
  59.  
  60. case 'Administrator': 
  61. return __('Administrator', 'contact-form-7-to-database-extension'); 
  62. case 'Editor': 
  63. return __('Editor', 'contact-form-7-to-database-extension'); 
  64. case 'Author': 
  65. return __('Author', 'contact-form-7-to-database-extension'); 
  66. case 'Contributor': 
  67. return __('Contributor', 'contact-form-7-to-database-extension'); 
  68. case 'Subscriber': 
  69. return __('Subscriber', 'contact-form-7-to-database-extension'); 
  70. case 'Anyone': 
  71. return __('Anyone', 'contact-form-7-to-database-extension'); 
  72. return $optionValue; 
  73.  
  74. public function upgrade() { 
  75. global $wpdb; 
  76. $upgradeOk = true; 
  77. $savedVersion = $this->getVersionSaved(); 
  78. if (!$savedVersion) { 
  79. // Was some code here from pre-version 1.2 that I removed b/c it is very old and not relevant. 
  80.  
  81. // A user reported an issue where the saved version in the DB would get cleared out 
  82. // after using the plugin for a week or so. Weird and not reproducible. But the problem is that 
  83. // it would make it re-run through the upgrades below even though they need not be applied. 
  84. // the ALTER TABLE statements would fail and product errors on the page. 
  85. // Without solving the underlying problem, I'm going to have upgrade actions be skipped 
  86. // in the case where no version is recorded in the DB. 
  87. } else { 
  88. if ($this->isVersionLessThan($savedVersion, '2.8.29')) { 
  89. if ($this->isVersionLessThan($savedVersion, '2.8.25')) { 
  90. if ($this->isVersionLessThan($savedVersion, '2.4.1')) { 
  91. if ($this->isVersionLessThan($savedVersion, '2.2')) { 
  92. if ($this->isVersionLessThan($savedVersion, '2.0')) { 
  93. if ($this->isVersionLessThan($savedVersion, '1.8')) { 
  94. if ($this->isVersionLessThan($savedVersion, '1.4.5')) { 
  95. if ($this->isVersionLessThan($savedVersion, '1.3.1')) { 
  96. // Version 1.3.1 update 
  97. $tableName = $this->getSubmitsTableName(); 
  98. $wpdb->show_errors(); 
  99. $upgradeOk &= false !== $wpdb->query("ALTER TABLE `$tableName` ADD COLUMN `field_order` INTEGER"); 
  100. $upgradeOk &= false !== $wpdb->query("ALTER TABLE `$tableName` ADD COLUMN `file` LONGBLOB"); 
  101. $upgradeOk &= false !== $wpdb->query("ALTER TABLE `$tableName` ADD INDEX `submit_time_idx` ( `submit_time` )"); 
  102. $wpdb->hide_errors(); 
  103.  
  104. // Version 1.4.5 update 
  105. if (!$this->getOption('CanSeeSubmitDataViaShortcode')) { 
  106. $this->addOption('CanSeeSubmitDataViaShortcode', 'Anyone'); 
  107.  
  108. // Misc 
  109. $submitDateTimeFormat = $this->getOption('SubmitDateTimeFormat'); 
  110. if (!$submitDateTimeFormat || $submitDateTimeFormat == '') { 
  111. $this->addOption('SubmitDateTimeFormat', 'Y-m-d H:i:s P'); 
  112.  
  113. // Version 1.8 update 
  114. if (!$this->getOption('MaxRows')) { 
  115. $this->addOption('MaxRows', '100'); 
  116. $tableName = $this->getSubmitsTableName(); 
  117. $wpdb->show_errors(); 
  118. /** $upgradeOk &= false !== */ 
  119. $wpdb->query("ALTER TABLE `$tableName` MODIFY COLUMN submit_time DECIMAL(16, 4) NOT NULL"); 
  120. /** $upgradeOk &= false !== */ 
  121. $wpdb->query("ALTER TABLE `$tableName` ADD INDEX `form_name_idx` ( `form_name` )"); 
  122. /** $upgradeOk &= false !== */ 
  123. $wpdb->query("ALTER TABLE `$tableName` ADD INDEX `form_name_field_name_idx` ( `form_name`, `field_name` )"); 
  124. $wpdb->hide_errors(); 
  125.  
  126. // Version 2.0 upgrade 
  127. $tableName = $this->getSubmitsTableName(); 
  128. $oldTableName = $this->prefixTableName('SUBMITS'); 
  129. @$wpdb->query("RENAME TABLE `$oldTableName` TO `$tableName`"); 
  130.  
  131. // Version 2.2 upgrade 
  132. $tableName = $this->getSubmitsTableName(); 
  133. $wpdb->query("ALTER TABLE `$tableName` DROP INDEX `form_name_field_name_idx`"); 
  134. $wpdb->query("ALTER TABLE `$tableName` ADD INDEX `field_name_idx` ( `field_name` )"); 
  135.  
  136. // Version 2.4.1 upgrade 
  137. $tableName = $this->getSubmitsTableName(); 
  138. $oldTableName = strtolower($tableName); 
  139. $wpdb->query("RENAME TABLE '$oldTableName' TO '$tableName'"); 
  140. // Version 2.8.25 update 
  141. $tableName = $this->getSTTableName(); 
  142. $wpdb->show_errors(); 
  143. $wpdb->query("CREATE TABLE IF NOT EXISTS `$tableName` (`submit_time` DECIMAL(16, 4) NOT NULL, PRIMARY KEY (submit_time))"); 
  144. $wpdb->hide_errors(); 
  145. // Version 2.8.29 update 
  146. // tyring this again b/c was not put into new installs 
  147. $tableName = $this->getSTTableName(); 
  148. $wpdb->show_errors(); 
  149. $wpdb->query("CREATE TABLE IF NOT EXISTS `$tableName` (`submit_time` DECIMAL(16, 4) NOT NULL, PRIMARY KEY (submit_time))"); 
  150. $wpdb->hide_errors(); 
  151.  
  152.  
  153. // Post-upgrade, set the current version in the options 
  154. $codeVersion = $this->getVersion(); 
  155. if ($upgradeOk && $codeVersion && $savedVersion != $codeVersion) { 
  156. $this->saveInstalledVersion($codeVersion); 
  157.  
  158. /** 
  159. * Called by install() 
  160. * You should: Prefix all table names with $wpdb->prefix 
  161. * Also good: additionally use the prefix for this plugin: 
  162. * $table_name = $wpdb->prefix . $this->prefix('MY_TABLE'); 
  163. * @return void 
  164. */ 
  165. protected function installDatabaseTables() { 
  166. global $wpdb; 
  167. $tableName = $this->getSubmitsTableName(); 
  168. $wpdb->show_errors(); 
  169. $wpdb->query("CREATE TABLE IF NOT EXISTS `$tableName` ( 
  170. `submit_time` DECIMAL(16, 4) NOT NULL,  
  171. `form_name` VARCHAR(127) CHARACTER SET utf8,  
  172. `field_name` VARCHAR(127) CHARACTER SET utf8,  
  173. `field_value` LONGTEXT CHARACTER SET utf8,  
  174. `field_order` INTEGER,  
  175. `file` LONGBLOB)"); 
  176. $wpdb->query("ALTER TABLE `$tableName` ADD INDEX `submit_time_idx` ( `submit_time` )"); 
  177. $wpdb->query("ALTER TABLE `$tableName` ADD INDEX `form_name_idx` ( `form_name` )"); 
  178. $wpdb->query("ALTER TABLE `$tableName` ADD INDEX `field_name_idx` ( `field_name` )"); 
  179. $tableName = $this->getSTTableName(); 
  180. $wpdb->query("CREATE TABLE IF NOT EXISTS `$tableName` (`submit_time` DECIMAL(16, 4) NOT NULL, PRIMARY KEY (submit_time))"); 
  181. $wpdb->hide_errors(); 
  182.  
  183.  
  184. /** 
  185. * Called by uninstall() 
  186. * You should: Prefix all table names with $wpdb->prefix 
  187. * Also good: additionally use the prefix for this plugin: 
  188. * $table_name = $wpdb->prefix . $this->prefix('MY_TABLE'); 
  189. * @return void 
  190. */ 
  191. protected function unInstallDatabaseTables() { 
  192. if ('true' == $this->getOption('DropOnUninstall', 'false')) { 
  193. global $wpdb; 
  194. $tableName = $this->getSubmitsTableName(); 
  195. $wpdb->query("DROP TABLE IF EXISTS `$tableName`"); 
  196. // $tables = array('SUBMITS'); 
  197. // foreach ($tables as $aTable) { 
  198. // $tableName = $this->prefixTableName($aTable); 
  199. // $wpdb->query("DROP TABLE IF EXISTS `$tableName`"); 
  200. // } 
  201.  
  202. protected function initOptions() { 
  203. // By default ignore CF7 metadata fields 
  204. $this->addOption('NoSaveFields', '/.*wpcf7.*/, _wpnonce'); 
  205.  
  206. public function add_wpcf7_noSaveFields() { 
  207. $nsfArray = explode(', ', $this->getOption('NoSaveFields', '')); 
  208. $wpcf7Fields = array('/.*wpcf7.*/', '_wpnonce'); 
  209. foreach ($wpcf7Fields as $aWpcf7) { 
  210. if (!in_array($aWpcf7, $nsfArray)) { 
  211. $nsfArray[] = $aWpcf7; 
  212. $this->updateOption('NoSaveFields', implode(', ', $nsfArray)); 
  213.  
  214. public function delete_wpcf7_fields($formName) { 
  215. global $wpdb; 
  216. $wpdb->query($wpdb->prepare( 
  217. 'delete from `' . $this->getSubmitsTableName() . 
  218. "` where `form_name` = '%s' and `field_name` in ('_wpcf7', '_wpcf7_version', '_wpcf7_unit_tag', '_wpnonce', '_wpcf7_is_ajax_call', '_wpcf7_captcha_challenge_captcha')",  
  219. $formName)); 
  220.  
  221. public function addActionsAndFilters() { 
  222. // Admin notices 
  223. add_action('admin_notices', array(&$this, 'addAdminNotices')); 
  224.  
  225. // Add the Admin Config page for this plugin 
  226.  
  227. // Add Config page as a top-level menu item on the Admin page 
  228. add_action('admin_menu', array(&$this, 'createAdminMenu')); 
  229.  
  230. // Add Database Options page 
  231. add_action('admin_menu', array(&$this, 'addSettingsSubMenuPage')); 
  232.  
  233. // Hook into Contact Form 7 when a form post is made to save the data to the DB 
  234. if ($this->getOption('IntegrateWithCF7', 'true') == 'true') { 
  235. require_once('CFDBIntegrationContactForm7.php'); 
  236. $integration = new CFDBIntegrationContactForm7($this); 
  237. $integration->registerHooks(); 
  238.  
  239. // Hook into Fast Secure Contact Form 
  240. if ($this->getOption('IntegrateWithFSCF', 'true') == 'true') { 
  241. require_once('CFDBIntegrationFSCF.php'); 
  242. $integration = new CFDBIntegrationFSCF($this); 
  243. $integration->registerHooks(); 
  244.  
  245. // Hook into JetPack Contact Form 
  246. if ($this->getOption('IntegrateWithJetPackContactForm', 'true') == 'true') { 
  247. require_once('CFDBIntegrationJetPack.php'); 
  248. $integration = new CFDBIntegrationJetPack($this); 
  249. $integration->registerHooks(); 
  250.  
  251. // Hook into Gravity Forms 
  252. if ($this->getOption('IntegrateWithGravityForms', 'true') == 'true') { 
  253. require_once('CFDBIntegrationGravityForms.php'); 
  254. $integration = new CFDBIntegrationGravityForms($this); 
  255. $integration->registerHooks(); 
  256.  
  257. // Hook to work with WR ContactForms 
  258. if ($this->getOption('IntegrateWithWrContactForms', 'true') == 'true') { 
  259. require_once('CFDBIntegrationWRContactForm.php'); 
  260. $integration = new CFDBIntegrationWRContactForm($this); 
  261. $integration->registerHooks(); 
  262.  
  263. // Hook to work with Quform 
  264. if ($this->getOption('IntegrateWithQuform', 'true') == 'true') { 
  265. require_once('CFDBIntegrationQuform.php'); 
  266. $integration = new CFDBIntegrationQuform($this); 
  267. $integration->registerHooks(); 
  268.  
  269. // Hook to work with Ninja Forms 
  270. if ($this->getOption('IntegrateWithNinjaForms', 'true') == 'true') { 
  271. require_once('CFDBIntegrationNinjaForms.php'); 
  272. $integration = new CFDBIntegrationNinjaForms($this); 
  273. $integration->registerHooks(); 
  274.  
  275. // Hook to work with Caldera Forms Forms 
  276. if ($this->getOption('IntegrateWithCalderaForms', 'true') == 'true') { 
  277. require_once('CFDBIntegrationCalderaForms.php'); 
  278. $integration = new CFDBIntegrationCalderaForms($this); 
  279. $integration->registerHooks(); 
  280.  
  281. // Enfold theme forms 
  282. if ($this->getOption('IntegrateWithEnfoldThemForms', 'true') == 'true') { 
  283. require_once('CFDBIntegrationEnfoldTheme.php'); 
  284. $enfold = new CFDBIntegrationEnfoldTheme($this); 
  285. $enfold->registerHooks(); 
  286.  
  287. // Have our own hook to receive form submissions independent of other plugins 
  288. add_action('cfdb_submit', array(&$this, 'saveFormData')); 
  289.  
  290. // Register Export URL 
  291. add_action('wp_ajax_nopriv_cfdb-export', array(&$this, 'ajaxExport')); 
  292. add_action('wp_ajax_cfdb-export', array(&$this, 'ajaxExport')); 
  293.  
  294. // Register Get File URL 
  295. add_action('wp_ajax_nopriv_cfdb-file', array(&$this, 'ajaxFile')); 
  296. add_action('wp_ajax_cfdb-file', array(&$this, 'ajaxFile')); 
  297.  
  298. // Register Get Form Fields URL 
  299. add_action('wp_ajax_nopriv_cfdb-getFormFields', array(&$this, 'ajaxGetFormFields')); 
  300. add_action('wp_ajax_cfdb-getFormFields', array(&$this, 'ajaxGetFormFields')); 
  301.  
  302. // Register Validate submit_time value (used in short code builder page) 
  303. add_action('wp_ajax_nopriv_cfdb-validate-submit_time', array(&$this, 'ajaxValidateSubmitTime')); 
  304. add_action('wp_ajax_cfdb-validate-submit_time', array(&$this, 'ajaxValidateSubmitTime')); 
  305.  
  306. // Login via Ajax instead of login form 
  307. add_action('wp_ajax_nopriv_cfdb-login', array(&$this, 'ajaxLogin')); 
  308. add_action('wp_ajax_cfdb-login', array(&$this, 'ajaxLogin')); 
  309.  
  310. add_action('wp_ajax_nopriv_cfdb-cleanup', array(&$this, 'ajaxCleanup')); 
  311. add_action('wp_ajax_cfdb-cleanup', array(&$this, 'ajaxCleanup')); 
  312.  
  313. // Shortcode to add a table to a page 
  314. $sc = new CFDBShortcodeTable(); 
  315. $sc->register(array('cf7db-table', 'cfdb-table')); // cf7db-table is deprecated 
  316.  
  317. // Shortcode to add a DataTable 
  318. $sc = new CFDBShortcodeDataTable(); 
  319. $sc->register('cfdb-datatable'); 
  320.  
  321. // Shortcode to add a JSON to a page 
  322. $sc = new CFDBShortcodeJson(); 
  323. $sc->register('cfdb-json'); 
  324.  
  325. // Shortcode to add a value (just text) to a page 
  326. $sc = new CFDBShortcodeValue(); 
  327. $sc->register('cfdb-value'); 
  328.  
  329. // Shortcode to add entry count to a page 
  330. $sc = new CFDBShortcodeCount(); 
  331. $sc->register('cfdb-count'); 
  332.  
  333. // Shortcode to add values wrapped in user-defined html 
  334. $sc = new CFDBShortcodeHtml(); 
  335. $sc->register('cfdb-html'); 
  336.  
  337. // Shortcode to generate Export URLs 
  338. $sc = new CFDBShortcodeExportUrl(); 
  339. $sc->register('cfdb-export-link'); 
  340.  
  341. // Shortcode to save data from non-CF7/FSCF forms 
  342. $sc = new CFDBShortCodeSavePostData(); 
  343. $sc->register('cfdb-save-form-post'); 
  344.  
  345. // Shortcode to save data Form Maker submissions 
  346. $sc = new CFDBShortCodeSaveFormMakerSubmission(); 
  347. $sc->register('cfdb-save-form-maker-post'); 
  348.  
  349. public function ajaxLogin() { 
  350. // Login the user 
  351. $key = 'kx82XcPjq8q8S!xafx%$&7p6'; 
  352. $creds = array(); 
  353. $user = null; 
  354. $password = null; 
  355.  
  356. if (!empty($_REQUEST['l'])) { 
  357. $userPass = CFDBDeobfuscate::deobfuscateHexString($_REQUEST['l'], $key); 
  358. $userPass = explode('/', $userPass, 2); 
  359. $count = count($userPass); 
  360. if ($count >= 1) { 
  361. $user = $userPass[0]; 
  362. if ($count > 1) { 
  363. $password = $userPass[1]; 
  364.  
  365. if (!$user) { 
  366. $user = !empty($_REQUEST['username']) ? $_REQUEST['username'] : null; 
  367. if (!$user) { 
  368. $user = !empty($_REQUEST['user_login']) ? $_REQUEST['user_login'] : null; 
  369.  
  370. if (!$password) { 
  371. $password = !empty($_REQUEST['password']) ? $_REQUEST['password'] : null; 
  372. if (!$password) { 
  373. $password = !empty($_REQUEST['user_password']) ? $_REQUEST['user_password'] : null; 
  374.  
  375. $creds['user_login'] = $user; 
  376. $creds['user_password'] = $password; 
  377. $creds['remember'] = !empty($_REQUEST['rememberme']) ? $_REQUEST['rememberme'] : null; 
  378. $user = wp_signon($creds, false); 
  379. if (is_wp_error($user)) { 
  380. echo $user->get_error_message(); 
  381. die; 
  382. wp_set_current_user($user->ID); 
  383.  
  384. // User is logged in. Now do the requested action 
  385. if (!empty($_REQUEST['cfdb-action'])) { 
  386. switch ($_REQUEST['cfdb-action']) { 
  387. case 'cfdb-export': 
  388. if (!$this->canUserDoRoleOption('CanSeeSubmitData')) { 
  389. echo '<strong>ERROR</strong>: user ' . $creds['user_login'] . ' is not authorized to export CFDB data'; 
  390. die; 
  391. $this->ajaxExport(); 
  392. break; 
  393.  
  394. default: 
  395. break; 
  396. die; 
  397.  
  398. public function ajaxExport() { 
  399. require_once('CF7DBPluginExporter.php'); 
  400. CF7DBPluginExporter::doExportFromPost(); 
  401. die(); 
  402.  
  403. public function ajaxFile() { 
  404. require_once('CFDBDie.php'); 
  405. if (!$this->canUserDoRoleOption('CanSeeSubmitData') && 
  406. !$this->canUserDoRoleOption('CanSeeSubmitDataViaShortcode')) { 
  407. CFDBDie::wp_die(__('You do not have sufficient permissions to access this page.', 'contact-form-7-to-database-extension')); 
  408. $submitTime = $_REQUEST['s']; 
  409. $formName = $_REQUEST['form']; 
  410. $fieldName = $_REQUEST['field']; 
  411. if (!$submitTime || !$formName || !$fieldName) { 
  412. CFDBDie::wp_die(__('Missing form parameters', 'contact-form-7-to-database-extension')); 
  413. $fileInfo = (array)$this->getFileFromDB($submitTime, $formName, $fieldName); 
  414. if ($fileInfo == null) { 
  415. CFDBDie::wp_die(__('No such file.', 'contact-form-7-to-database-extension')); 
  416.  
  417. require_once('CFDBMimeTypeExtensions.php'); 
  418. $mimeMap = new CFDBMimeTypeExtensions(); 
  419. $mimeType = $mimeMap->get_type_by_filename($fileInfo[0]); 
  420. if ($mimeType) { 
  421. header('Content-Type: ' . $mimeType); 
  422. header("Content-Disposition: inline; filename=\"$fileInfo[0]\""); 
  423. else { 
  424. header("Content-Disposition: attachment; filename=\"$fileInfo[0]\""); 
  425.  
  426. echo($fileInfo[1]); 
  427. die(); 
  428.  
  429. public function ajaxGetFormFields() { 
  430. if (!$this->canUserDoRoleOption('CanSeeSubmitData') || !isset($_REQUEST['form'])) { 
  431. die(); 
  432. header('Content-Type: application/json; charset=UTF-8'); 
  433. header("Pragma: no-cache"); 
  434. header("Expires: Thu, 01 Jan 1970 00:00:00 GMT"); 
  435. global $wpdb; 
  436. $tableName = $this->getSubmitsTableName(); 
  437. $formName = $_REQUEST['form']; 
  438. $rows = $wpdb->get_results("SELECT DISTINCT `field_name` FROM `$tableName` WHERE `form_name` = '$formName' ORDER BY field_order"); 
  439. $fields = array(); 
  440. if (!empty($rows)) { 
  441. $fields[] = 'Submitted'; 
  442. foreach ($rows as $aRow) { 
  443. $fields[] = $aRow->field_name; 
  444. $fields[] = 'submit_time'; 
  445. echo json_encode($fields); 
  446. die(); 
  447.  
  448. public function ajaxValidateSubmitTime() { 
  449. header('Content-Type: text/plain; charset=UTF-8'); 
  450. header("Pragma: no-cache"); 
  451. header("Expires: Thu, 01 Jan 1970 00:00:00 GMT"); 
  452. $submitTime = $_REQUEST['submit_time']; 
  453.  
  454. $invalid = false; 
  455. $time = $submitTime; 
  456. if (!is_numeric($submitTime)) { 
  457. if (version_compare(phpversion(), '5.1.0') == -1) { 
  458. $invalid = -1; 
  459. $this->setTimezone(); 
  460. $time = strtotime($submitTime); 
  461. if ($invalid === $time) { 
  462. echo htmlspecialchars(__('Invalid: ', 'contact-form-7-to-database-extension')); 
  463. else { 
  464. echo htmlspecialchars(__('Valid: ', 'contact-form-7-to-database-extension')); 
  465.  
  466. echo "'$submitTime' = $time"; 
  467.  
  468. if ($invalid !== $time) { 
  469. echo " = " . $this->formatDate($time); 
  470. die(); 
  471.  
  472. public function ajaxCleanup() { 
  473. if (!$this->canUserDoRoleOption('CanChangeSubmitData')) { 
  474. die(); 
  475. header('Content-Type: text/plain; charset=UTF-8'); 
  476. header("Pragma: no-cache"); 
  477. header("Expires: Thu, 01 Jan 1970 00:00:00 GMT"); 
  478. echo htmlspecialchars(__('Checking for conflicting entries. This may take a few minutes.', 'contact-form-7-to-database-extension')); 
  479. echo "\n"; 
  480. require_once('CFDBCleanupData.php'); 
  481. $cleanup = new CFDBCleanupData($this); 
  482.  
  483. echo htmlspecialchars(__('Phase 1 of 3...', 'contact-form-7-to-database-extension')); 
  484. $count = $cleanup->cleanupForms(); 
  485. echo htmlspecialchars(__('Database entries fixed: ', 'contact-form-7-to-database-extension')); 
  486. echo ($count); 
  487. echo "\n"; 
  488.  
  489. echo htmlspecialchars(__('Phase 2 of 3...', 'contact-form-7-to-database-extension')); 
  490. $count = $cleanup->deleteEmptyEntries(); 
  491. echo htmlspecialchars(__('Database entries fixed: ', 'contact-form-7-to-database-extension')); 
  492. echo ($count); 
  493. echo "\n"; 
  494.  
  495. echo htmlspecialchars(__('Phase 3 of 3...', 'contact-form-7-to-database-extension')); 
  496. $count = $cleanup->cleanupEntries(); 
  497. echo htmlspecialchars(__('Database entries fixed: ', 'contact-form-7-to-database-extension')); 
  498. echo ($count); 
  499. echo "\n"; 
  500. die(); 
  501.  
  502. public function addSettingsSubMenuPage() { 
  503. // $this->requireExtraPluginFiles(); 
  504. // $displayName = $this->getPluginDisplayName(); 
  505. // add_submenu_page('wpcf7', //$this->getDBPageSlug(),  
  506. // $displayName . ' Options',  
  507. // __('Database Options', 'contact-form-7-to-database-extension'),  
  508. // 'manage_options',  
  509. // get_class($this) . 'Settings',  
  510. // array(&$this, 'settingsPage')); 
  511.  
  512.  
  513. public function generateSubmitTime() { 
  514. global $wpdb; 
  515. $table = $this->getSTTableName(); 
  516. $time = 0; 
  517. $noDuplicate = false; 
  518. $tries = 0; 
  519. $wpdb->hide_errors(); // avoid submission page from hanging on DB error like table not exists 
  520. while (!$noDuplicate && ++$tries <= 20) { 
  521. // $tries breaks out of loop which would be infinite when table to insert into does not exist 
  522. $time = function_exists('microtime') ? microtime(true) : time(); 
  523. // Bug fix: on some systems microtime is in scientific notation when converted to string 
  524. $time = number_format($time, 4, '.', ''); 
  525. // Avoid duplicate submission with the same submit_time in the DB 
  526. $noDuplicate = $wpdb->query($wpdb->prepare("INSERT INTO $table VALUES (%s)", $time)); 
  527. return $time; 
  528.  
  529. /** 
  530. * Callback for saving form data. Originally based on Contact Form 7's callback object 
  531. * with submission data in $cf7->posted_data. However that has changed over time. 
  532. * FSCF sends an object matching this data structure. Other form plugins have their data 
  533. * transformed into the expected data structure via other callbacks in this class 
  534. * @param $cf7 object containing posted data 
  535. * @return bool 
  536. */ 
  537. public function saveFormData($cf7) { 
  538. try { 
  539. if (!empty($cf7->posted_data['submit_time']) && is_numeric($cf7->posted_data['submit_time'])) { 
  540. $time = $cf7->posted_data['submit_time']; 
  541. unset($cf7->posted_data['submit_time']); 
  542. unset($cf7->posted_data['submit_url']); 
  543. } else { 
  544. $time = $this->generateSubmitTime(); 
  545. $cf7->submit_time = $time; 
  546.  
  547. $ip = (isset($_SERVER['X_FORWARDED_FOR'])) ? $_SERVER['X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR']; 
  548.  
  549. // Set up to allow all this data to be filtered 
  550. $cf7->ip = $ip; 
  551. $user = null; 
  552. if (function_exists('is_user_logged_in') && is_user_logged_in()) { 
  553. $current_user = wp_get_current_user(); // WP_User 
  554. $user = $current_user->user_login; 
  555. $cf7->user = $user; 
  556. try { 
  557. $newCf7 = apply_filters('cfdb_form_data', $cf7); 
  558. if ($newCf7 && is_object($newCf7)) { 
  559. $cf7 = $newCf7; 
  560. $time = $cf7->submit_time; 
  561. $ip = $cf7->ip; 
  562. $user = $cf7->user; 
  563. else { 
  564. //$this->getErrorLog()->log('CFDB Error: No or invalid value returned from "cfdb_form_data" filter: ' . 
  565. // print_r($newCf7, true)); 
  566. // Returning null from cfdb_form_data is a way to stop from saving the form 
  567. return true; 
  568. catch (Exception $ex) { 
  569. $this->getErrorLog()->logException($ex); 
  570.  
  571. // Get title after applying filter 
  572. if (isset($cf7->title)) { 
  573. $title = $cf7->title; 
  574. } else { 
  575. $title = 'Unknown'; 
  576. $title = stripslashes($title); 
  577.  
  578. if ($this->fieldMatches($title, $this->getNoSaveForms())) { 
  579. return true; // Don't save in DB 
  580.  
  581. $tableName = $this->getSubmitsTableName(); 
  582. $parametrizedQuery = "INSERT INTO `$tableName` (`submit_time`, `form_name`, `field_name`, `field_value`, `field_order`) VALUES (%s, %s, %s, %s, %s)"; 
  583. $parametrizedFileQuery = "INSERT INTO `$tableName` (`submit_time`, `form_name`, `field_name`, `field_value`, `field_order`, `file`) VALUES (%s, %s, %s, %s, %s, %s)"; 
  584. $order = 0; 
  585. $noSaveFields = $this->getNoSaveFields(); 
  586. $foundUploadFiles = array(); 
  587. global $wpdb; 
  588.  
  589. // $hasDropBox = $this->getOption('dropbox'); 
  590. // if ($hasDropBox) { 
  591. // require_once('CFDBShortCodeSavePostData.php'); 
  592. // } 
  593. foreach ($cf7->posted_data as $name => $value) { 
  594. $nameClean = stripslashes($name); 
  595. if ($this->fieldMatches($nameClean, $noSaveFields)) { 
  596. continue; // Don't save in DB 
  597.  
  598. $value = is_array($value) ? implode($value, ', ') : $value; 
  599. $valueClean = stripslashes($value); 
  600.  
  601. // Check if this is a file upload field 
  602. $didSaveFile = false; 
  603. if ($cf7->uploaded_files && isset($cf7->uploaded_files[$nameClean])) { 
  604. $foundUploadFiles[] = $nameClean; 
  605. $filePath = $cf7->uploaded_files[$nameClean]; 
  606. if ($filePath) { 
  607. $content = file_get_contents($filePath); 
  608. $didSaveFile = $wpdb->query($wpdb->prepare($parametrizedFileQuery,  
  609. $time,  
  610. $title,  
  611. $nameClean,  
  612. $valueClean,  
  613. $order++,  
  614. $content)); 
  615. if (!$didSaveFile) { 
  616. $this->getErrorLog()->log("CFDB Error: could not save uploaded file, field=$nameClean, file=$filePath"); 
  617. if (!$didSaveFile) { 
  618. $wpdb->query($wpdb->prepare($parametrizedQuery,  
  619. $time,  
  620. $title,  
  621. $nameClean,  
  622. $valueClean,  
  623. $order++)); 
  624.  
  625. // Since Contact Form 7 version 3.1, it no longer puts the names of the files in $cf7->posted_data 
  626. // So check for them only only in $cf7->uploaded_files 
  627. // Update: This seems to have been reversed back to the original in Contact Form 7 3.2 or 3.3 
  628. if ($cf7->uploaded_files && is_array($cf7->uploaded_files)) { 
  629. foreach ($cf7->uploaded_files as $field => $filePath) { 
  630. if (!in_array($field, $foundUploadFiles) && 
  631. $filePath && 
  632. !$this->fieldMatches($field, $noSaveFields)) { 
  633. $fileName = basename($filePath); 
  634. $content = file_get_contents($filePath); 
  635. $didSaveFile = $wpdb->query($wpdb->prepare($parametrizedFileQuery,  
  636. $time,  
  637. $title,  
  638. $field,  
  639. $fileName,  
  640. $order++,  
  641. $content)); 
  642. if (!$didSaveFile) { 
  643. $this->getErrorLog()->log("CFDB Error: could not save uploaded file, field=$field, file=$filePath"); 
  644.  
  645. // Save Cookie data if that option is true 
  646. if ($this->getOption('SaveCookieData', 'false') == 'true' && is_array($_COOKIE)) { 
  647. $saveCookies = $this->getSaveCookies(); 
  648. foreach ($_COOKIE as $cookieName => $cookieValue) { 
  649. if (empty($saveCookies) || $this->fieldMatches($cookieName, $saveCookies)) { 
  650. $wpdb->query($wpdb->prepare($parametrizedQuery,  
  651. $time,  
  652. $title,  
  653. 'Cookie ' . $cookieName,  
  654. $cookieValue,  
  655. $order++)); 
  656.  
  657. // If the submitter is logged in, capture his id 
  658. if ($user) { 
  659. $order = ($order < 9999) ? 9999 : $order + 1; // large order num to try to make it always next-to-last 
  660. $wpdb->query($wpdb->prepare($parametrizedQuery,  
  661. $time,  
  662. $title,  
  663. 'Submitted Login',  
  664. $user,  
  665. $order)); 
  666.  
  667. // Capture the IP Address of the submitter 
  668. $order = ($order < 10000) ? 10000 : $order + 1; // large order num to try to make it always last 
  669. $wpdb->query($wpdb->prepare($parametrizedQuery,  
  670. $time,  
  671. $title,  
  672. 'Submitted From',  
  673. $ip,  
  674. $order)); 
  675.  
  676. catch (Exception $ex) { 
  677. $this->getErrorLog()->logException($ex); 
  678.  
  679. // Indicate success to WordPress so it continues processing other unrelated hooks. 
  680. return true; 
  681.  
  682. /** 
  683. * @param $fieldName string 
  684. * @param $patternsArray array 
  685. * @return boolean true if $fieldName is in $patternsArray or matches any element of it that is a regex 
  686. */ 
  687. public function fieldMatches($fieldName, $patternsArray) { 
  688. if (is_array($patternsArray)) { 
  689. foreach($patternsArray as $pattern) { 
  690. if ($fieldName == $pattern) { 
  691. return true; 
  692. if (strncmp($pattern, '/', 1) == 0) { 
  693. if (@preg_match($pattern , $fieldName)) { 
  694. return true; 
  695. return false; 
  696.  
  697. /** 
  698. * @param $time string form submit time 
  699. * @param $formName string form name 
  700. * @param $fieldName string field name (should be an upload file field) 
  701. * @return array of (file-name, file-contents) or null if not found 
  702. */ 
  703. public function getFileFromDB($time, $formName, $fieldName) { 
  704. global $wpdb; 
  705. $tableName = $this->getSubmitsTableName(); 
  706. $parametrizedQuery = "SELECT `field_value`, `file` FROM `$tableName` WHERE `submit_time` = %F AND `form_name` = %s AND `field_name` = '%s'"; 
  707. $rows = $wpdb->get_results($wpdb->prepare($parametrizedQuery, $time, $formName, $fieldName)); 
  708. if ($rows == null || count($rows) == 0) { 
  709. return null; 
  710.  
  711. return array($rows[0]->field_value, $rows[0]->file); 
  712.  
  713. /** 
  714. * Install page for this plugin in WP Admin 
  715. * @return void 
  716. */ 
  717. public function createAdminMenu() { 
  718. $roleAllowed = 'Administrator'; 
  719. $displayName = $this->getPluginDisplayName(); 
  720.  
  721. $hideFromNonAdmins = $this->getOption('HideAdminPanelFromNonAdmins', 'false') != 'false'; 
  722. if ($hideFromNonAdmins) { 
  723. $roleAllowed = 'Administrator'; 
  724. } else { 
  725. $roleAllowed = $this->getRoleOption('CanSeeSubmitData'); 
  726. if (!$roleAllowed) { 
  727. $roleAllowed = 'Administrator'; 
  728.  
  729. if (! $this->isUserRoleEqualOrBetterThan($roleAllowed)) { 
  730. return; 
  731.  
  732. $menuSlug = $this->getDBPageSlug(); 
  733.  
  734. //create new top-level menu 
  735. add_menu_page($displayName,  
  736. __('Contact Form DB', 'contact-form-7-to-database-extension'),  
  737. $this->roleToCapability($roleAllowed),  
  738. $menuSlug, //$this->getDBPageSlug(),  
  739. array(&$this, 'whatsInTheDBPage'),  
  740. $this->getPluginFileUrl('img/icon-bw-20x20.png')); 
  741.  
  742. // Needed for dialog in whatsInTheDBPage 
  743. if (strpos($_SERVER['REQUEST_URI'], $this->getDBPageSlug()) !== false) { 
  744. $pluginUrl = $this->getPluginFileUrl() . '/'; 
  745. wp_enqueue_script('jquery'); 
  746. wp_enqueue_script('jquery-ui-core'); 
  747. wp_enqueue_script('jquery-ui-dialog'); 
  748. wp_enqueue_script('CF7DBdes', $pluginUrl . 'des.js'); 
  749.  
  750. wp_enqueue_style('jquery-ui.css', $pluginUrl . 'jquery-ui/jquery-ui-1.8.21.custom.css'); 
  751.  
  752. // Datatables http://www.datatables.net 
  753. if ($this->getOption('UseDataTablesJS', 'true') == 'true') { 
  754. // wp_enqueue_style('datatables-demo', 'http://www.datatables.net/release-datatables/media/css/demo_table.css'); 
  755. // wp_enqueue_script('datatables', 'http://www.datatables.net/release-datatables/media/js/jquery.dataTables.js', array('jquery')); 
  756. wp_enqueue_style('datatables-demo', $pluginUrl .'DataTables/media/css/demo_table.css'); 
  757. wp_enqueue_script('datatables', $pluginUrl . 'DataTables/media/js/jquery.dataTables.min.js', array('jquery')); 
  758.  
  759. if ($this->canUserDoRoleOption('CanChangeSubmitData')) { 
  760. do_action_ref_array('cfdb_edit_enqueue', array()); 
  761.  
  762. // Would like to add ColReorder but it causes slowness and display issues with DataTable footer 
  763. //wp_enqueue_style('datatables-ColReorder', $pluginUrl .'DataTables/extras/ColReorder/media/css/ColReorder.css'); 
  764. //wp_enqueue_script('datatables-ColReorder', $pluginUrl . 'DataTables/extras/ColReorder/media/js/ColReorder.min.js', array('datatables', 'jquery')); 
  765.  
  766. if (strpos($_SERVER['REQUEST_URI'], $this->getShortCodeBuilderPageSlug()) !== false) { 
  767. wp_enqueue_script('jquery'); 
  768. $pluginUrl = $this->getPluginFileUrl() . '/'; 
  769. wp_enqueue_script('CF7DBdes', $pluginUrl . 'des.js'); 
  770.  
  771. // // Put page under CF7's "Contact" page 
  772. // add_submenu_page('wpcf7',  
  773. // $displayName . ' Submissions',  
  774. // __('Database', 'contact-form-7-to-database-extension'),  
  775. // $this->roleToCapability($roleAllowed),  
  776. // $this->getDBPageSlug(),  
  777. // array(&$this, 'whatsInTheDBPage')); 
  778.  
  779. add_submenu_page($menuSlug,  
  780. $displayName . ' Short Code Builder',  
  781. __('Short Code', 'contact-form-7-to-database-extension'),  
  782. $this->roleToCapability($roleAllowed),  
  783. $this->getShortCodeBuilderPageSlug(),  
  784. array(&$this, 'showShortCodeBuilderPage')); 
  785.  
  786. if ($this->isEditorActive() && $this->canUserDoRoleOption('CanSeeSubmitData')) { 
  787. add_submenu_page($menuSlug,  
  788. $displayName . ' Import',  
  789. __('Import', 'contact-form-7-to-database-extension'),  
  790. $this->roleToCapability($this->getRoleOption('CanChangeSubmitData')),  
  791. get_class($this) . 'Import',  
  792. array(&$this, 'showShortImportCsvPage')); 
  793.  
  794. add_submenu_page($menuSlug,  
  795. $displayName . ' Options',  
  796. __('Options', 'contact-form-7-to-database-extension'),  
  797. 'manage_options',  
  798. get_class($this) . 'Settings',  
  799. array(&$this, 'settingsPage')); 
  800.  
  801.  
  802. // // Put page under CF7's "Contact" page 
  803. // add_submenu_page('wpcf7',  
  804. // $displayName . ' Short Code Builder',  
  805. // __('Database Short Code', 'contact-form-7-to-database-extension'),  
  806. // $this->roleToCapability($roleAllowed),  
  807. // $this->getSortCodeBuilderPageSlug(),  
  808. // array(&$this, 'showShortCodeBuilderPage')); 
  809.  
  810. /** 
  811. * @return string WP Admin slug for page to view DB data 
  812. */ 
  813. public function getDBPageSlug() { 
  814. return get_class($this) . 'Submissions'; 
  815.  
  816. public function getShortCodeBuilderPageSlug() { 
  817. return get_class($this) . 'ShortCodeBuilder'; 
  818.  
  819. public function showShortCodeBuilderPage() { 
  820. require_once('CFDBViewShortCodeBuilder.php'); 
  821. $view = new CFDBViewShortCodeBuilder; 
  822. $view->display($this); 
  823.  
  824. public function showShortImportCsvPage() { 
  825. require_once('CFDBViewImportCsv.php'); 
  826. $view = new CFDBViewImportCsv; 
  827. $view->display($this); 
  828.  
  829. /** 
  830. * Display the Admin page for this Plugin that show the form data saved in the database 
  831. * @return void 
  832. */ 
  833. public function whatsInTheDBPage() { 
  834. if (isset($_REQUEST['submit_time'])) { 
  835. $submitTime = $_REQUEST['submit_time']; 
  836. require_once('ExportEntry.php'); 
  837. $exp = new ExportEntry(); 
  838. if (isset($_REQUEST['form_name']) && !empty($_REQUEST['form_name'])) { 
  839. $form = stripslashes($_REQUEST['form_name']); 
  840. } else { 
  841. global $wpdb; 
  842. $table = $this->getSubmitsTableName(); 
  843. $form = $wpdb->get_var($wpdb->prepare("SELECT form_name from $table where submit_time = %s LIMIT 1",  
  844. $submitTime)); 
  845.  
  846. ?> 
  847. <form action="<?php echo get_admin_url() . 'admin.php?page=' . $this->getDBPageSlug() . "&form_name=" . urlencode($form) ?>" method="post"> 
  848. <input name="form_name" type="hidden" value="<?php echo htmlspecialchars($form) ?>"/> 
  849. <input name="<?php echo htmlspecialchars($submitTime) ?>" type="hidden" value="row"/> 
  850. <?php wp_nonce_field(); ?> 
  851. <button id="delete" name="delete" onclick="this.form.submit();"><?php echo htmlspecialchars(__('Delete', 'contact-form-7-to-database-extension')); ?></button> 
  852. </form> 
  853. <?php 
  854. $exp->export($form, array('submit_time' => $submitTime)); 
  855. } else { 
  856. require_once('CFDBViewWhatsInDB.php'); 
  857. $view = new CFDBViewWhatsInDB; 
  858. $view->display($this); 
  859.  
  860. static $checkForCustomDateFormat = true; 
  861. static $customDateFormat = null; 
  862. static $dateFormat = null; 
  863. static $timeFormat = null; 
  864.  
  865. /** 
  866. * Format input date string 
  867. * @param $time int same as returned from PHP time() 
  868. * @return string formatted date according to saved options 
  869. */ 
  870. public function formatDate($time) { 
  871. // This method gets executed in a loop. Cache some variable to avoid 
  872. // repeated get_option calls to the database 
  873. if (CF7DBPlugin::$checkForCustomDateFormat) { 
  874. if ($this->getOption('UseCustomDateTimeFormat', 'true') == 'true') { 
  875. CF7DBPlugin::$customDateFormat = $this->getOption('SubmitDateTimeFormat', 'Y-m-d H:i:s P'); 
  876. else { 
  877. CF7DBPlugin::$dateFormat = get_option('date_format'); 
  878. CF7DBPlugin::$timeFormat = get_option('time_format'); 
  879. $this->setTimezone(); 
  880. CF7DBPlugin::$checkForCustomDateFormat = false; 
  881.  
  882. // Support Shamsi(Jalali) dates by looking for a plugin that can produce the correct text for the date 
  883. if (!function_exists('is_plugin_active') && @file_exists(ABSPATH . 'wp-admin/includes/plugin.php')) { 
  884. include_once(ABSPATH . 'wp-admin/includes/plugin.php'); 
  885. if (function_exists('is_plugin_active')) { 
  886. // See if wp-parsidate is active and if so, have it convert the date 
  887. // using its 'parsidate' function 
  888. if (is_plugin_active('wp-parsidate/wp-parsidate.php')) { 
  889. if (function_exists('parsidate')) { 
  890. if (CF7DBPlugin::$customDateFormat) { 
  891. return parsidate(CF7DBPlugin::$customDateFormat, $time); 
  892. else { 
  893. return parsidate(CF7DBPlugin::$dateFormat . ' ' . CF7DBPlugin::$timeFormat, $time); 
  894. // See if wp-jalali is active and if so, have it convert the date 
  895. // using its 'jdate' function 
  896. else if (is_plugin_active('wp-jalali/wp-jalali.php')) { 
  897. $jDateFile = WP_PLUGIN_DIR . '/wp-jalali/inc/jalali-core.php'; 
  898. if(@file_exists($jDateFile)) { 
  899. include_once($jDateFile); 
  900. if (function_exists('jdate')) { 
  901. //return jdate('l, F j, Y'); 
  902. if (CF7DBPlugin::$customDateFormat) { 
  903. return jdate(CF7DBPlugin::$customDateFormat, $time); 
  904. else { 
  905. return jdate(CF7DBPlugin::$dateFormat . ' ' . CF7DBPlugin::$timeFormat, $time); 
  906.  
  907. if (CF7DBPlugin::$customDateFormat) { 
  908. return date(CF7DBPlugin::$customDateFormat, $time); 
  909. else { 
  910. return date_i18n(CF7DBPlugin::$dateFormat . ' ' . CF7DBPlugin::$timeFormat, $time); 
  911.  
  912. /** 
  913. * @param $submitTime string PK for form submission 
  914. * @param $formName string 
  915. * @param $fieldName string 
  916. * @return string URL to download file 
  917. */ 
  918. public function getFileUrl($submitTime, $formName, $fieldName) { 
  919. return sprintf('%s?action=cfdb-file&s=%s&form=%s&field=%s',  
  920. admin_url('admin-ajax.php'),  
  921. $submitTime,  
  922. urlencode($formName),  
  923. urlencode($fieldName)); 
  924.  
  925. public function getFormFieldsAjaxUrlBase() { 
  926. return admin_url('admin-ajax.php') . '?action=cfdb-getFormFields&form='; 
  927.  
  928. public function getValidateSubmitTimeAjaxUrlBase() { 
  929. return admin_url('admin-ajax.php') . '?action=cfdb-validate-submit_time&submit_time='; 
  930.  
  931. /** 
  932. * @return array of string 
  933. */ 
  934. public function getNoSaveFields() { 
  935. return preg_split('/, |;/', $this->getOption('NoSaveFields'), -1, PREG_SPLIT_NO_EMPTY); 
  936.  
  937. /** 
  938. * @return array of string 
  939. */ 
  940. public function getNoSaveForms() { 
  941. return preg_split('/, |;/', $this->getOption('NoSaveForms'), -1, PREG_SPLIT_NO_EMPTY); 
  942.  
  943. /** 
  944. * @return array of string 
  945. */ 
  946. public function getSaveCookies() { 
  947. return preg_split('/, |;/', $this->getOption('SaveCookieNames'), -1, PREG_SPLIT_NO_EMPTY); 
  948.  
  949. /** 
  950. * @return string 
  951. */ 
  952. public function getSubmitsTableName() { 
  953. // $overrideTable = $this->getOption('SubmitTableNameOverride'); 
  954. // if ($overrideTable && "" != $overrideTable) { 
  955. // return $overrideTable; 
  956. // } 
  957. //return strtolower($this->prefixTableName('SUBMITS')); 
  958. global $wpdb; 
  959. return $wpdb->prefix . strtolower($this->prefix('SUBMITS')); 
  960.  
  961. public function getSTTableName() { 
  962. global $wpdb; 
  963. return $wpdb->prefix . strtolower($this->prefix('ST')); 
  964.  
  965. /** 
  966. * @return string URL to the Plugin directory. Includes ending "/" 
  967. */ 
  968. public function getPluginDirUrl() { 
  969. //return WP_PLUGIN_URL . '/' . str_replace(basename(__FILE__), '', plugin_basename(__FILE__)); 
  970. return $this->getPluginFileUrl('/'); 
  971.  
  972.  
  973. /** 
  974. * @param string $pathRelativeToThisPluginRoot points to a file with relative path from 
  975. * this plugin's root dir. I.e. file "des.js" in the root of this plugin has 
  976. * url = $this->getPluginFileUrl('des.js'); 
  977. * If it was in a sub-folder "js" then you would use 
  978. * $this->getPluginFileUrl('js/des.js'); 
  979. * @return string full url to input file 
  980. */ 
  981. public function getPluginFileUrl($pathRelativeToThisPluginRoot = '') { 
  982. return plugins_url($pathRelativeToThisPluginRoot, __FILE__); 
  983.  
  984.  
  985. /** 
  986. * @return string URL of the language translation file for DataTables oLanguage.sUrl parameter 
  987. * or null if it does not exist. 
  988. */ 
  989. public function getDataTableTranslationUrl() { 
  990. $url = null; 
  991. $locale = get_locale(); 
  992. $i18nDir = dirname(__FILE__) . '/dt_i18n/'; 
  993.  
  994. // See if there is a local file 
  995. if (is_readable($i18nDir . $locale . '.json')) { 
  996. $url = $this->getPluginFileUrl() . "/dt_i18n/$locale.json"; 
  997. else { 
  998. // Pull the language code from the $local string 
  999. // which is expected to look like "en_US" 
  1000. // where the first 2 or 3 letters are for lang followed by '_' 
  1001. $lang = null; 
  1002. if (substr($locale, 2, 1) == '_') { 
  1003. // 2-letter language codes 
  1004. $lang = substr($locale, 0, 2); 
  1005. else if (substr($locale, 3, 1) == '_') { 
  1006. // 3-letter language codes 
  1007. $lang = substr($locale, 0, 3); 
  1008. if ($lang && is_readable($i18nDir . $lang . '.json')) { 
  1009. $url = $this->getPluginFileUrl() . "/dt_i18n/$lang.json"; 
  1010. return $url; 
  1011.  
  1012. public function setTimezone() { 
  1013. $timezone = trim($this->getOption('Timezone')); 
  1014. if (empty($timezone)) { 
  1015. $timezone = get_option('timezone_string'); 
  1016. if (!empty($timezone)) { 
  1017. date_default_timezone_set($timezone); 
  1018.  
  1019. /** 
  1020. * @return boolean Is the CFDB Editor extension installed? 
  1021. */ 
  1022. public function isEditorInstalled() { 
  1023. return get_option('CFDBEditPlugin__installed', false) == true; 
  1024.  
  1025.  
  1026. /** 
  1027. * @return string|null get the CFDB Editor extension version string. 
  1028. * return null if not installed 
  1029. */ 
  1030. public function getEditorSavedVersion() { 
  1031. return get_option('CFDBEditPlugin__version', null); 
  1032.  
  1033. /** 
  1034. * @return array of CFDB Editor plugin data, see: http://codex.wordpress.org/Function_Reference/get_plugin_data 
  1035. */ 
  1036. public function getEditorPluginData() { 
  1037. $editPluginFile = WP_PLUGIN_DIR . 
  1038. '/contact-form-to-database-extension-edit/contact-form-to-database-extension-edit.php'; 
  1039. if(@file_exists($editPluginFile)) { 
  1040. $pluginData = get_plugin_data($editPluginFile); 
  1041. if (is_array($pluginData)) { 
  1042. return $pluginData; 
  1043. return array(); 
  1044.  
  1045. /** 
  1046. * @return bool if CFDB Editor extension plugin is activated 
  1047. */ 
  1048. public function isEditorActive() { 
  1049. $editPluginFile = 'contact-form-to-database-extension-edit/contact-form-to-database-extension-edit.php'; 
  1050. return function_exists('is_plugin_active') && is_plugin_active($editPluginFile); 
  1051.  
  1052.  
  1053. public function addAdminNotices() { 
  1054. if (!$this->isEditorActive()) { 
  1055. return; 
  1056. $requiredEditorVersion = '1.4.1'; 
  1057. $editorData = $this->getEditorPluginData(); 
  1058. if (isset($editorData['Version'])) { 
  1059. if (version_compare($editorData['Version'], $requiredEditorVersion) == -1) { 
  1060. $editorPluginName = version_compare($editorData['Version'], '1.4', '<') ? 'Contact Form to DB Extension Edit' : 'Contact Form DB Editor'; 
  1061. ?> 
  1062. <div id="message" class="error"> 
  1063. <?php echo htmlentities(__('Plugin should be updated: ', 'contact-form-7-to-database-extension')); ?><strong><?php echo $editorPluginName ?></strong><br/> 
  1064. <?php echo htmlentities(__('Current version: ', 'contact-form-7-to-database-extension')); echo $editorData['Version']; ?><br/> 
  1065. <?php echo htmlentities(__('Minimum required version: ', 'contact-form-7-to-database-extension')); echo $requiredEditorVersion; ?><br/> 
  1066. <a target="_cfdbeditupgrade" href="http://cfdbplugin.com/?page_id=939"><?php echo htmlentities(__('Download the latest version', 'contact-form-7-to-database-extension')); ?></a> 
  1067. </div> 
  1068. <?php 
  1069.  
  1070. /** 
  1071. * @return array of form names that have data in the DB 
  1072. */ 
  1073. public function getForms() { 
  1074. global $wpdb; 
  1075. $forms = array(); 
  1076. $tableName = $this->getSubmitsTableName(); 
  1077. $formsFromQuery = $wpdb->get_results("select distinct `form_name` from `$tableName` order by `form_name`"); 
  1078. foreach ($formsFromQuery as $aRow) { 
  1079. $forms[] = $aRow->form_name; 
  1080. return $forms; 
  1081.  
  1082. /** 
  1083. * return CFDBErrorLog 
  1084. */ 
  1085. public function getErrorLog() { 
  1086. $destination = trim($this->getOption('ErrorOutput', '')); 
  1087. return new CFDBErrorLog($this, $destination); 
  1088.