PageRenderTime 62ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/wp-content/plugins/wp-invoice/core/wpi_functions.php

https://bitbucket.org/sanders_nick/my-maxi-skirt
PHP | 3033 lines | 1883 code | 498 blank | 652 comment | 444 complexity | 255ba36bcefeac09f578acca1ffeb4b1 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, AGPL-1.0, GPL-3.0, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /**
  3. *
  4. * Handles all functions
  5. *
  6. */
  7. setlocale(LC_MONETARY, 'en_US');
  8. class WPI_Functions {
  9. /**
  10. * PHP function to echoing a message to JS console
  11. * Ported from WP-Property
  12. *
  13. * @since 3.0.3
  14. */
  15. function console_log($text = false) {
  16. global $wpi_settings;
  17. if(isset($wpi_settings['developer_mode']) && $wpi_settings['developer_mode'] != 'true') {
  18. return;
  19. }
  20. if(empty($text)) {
  21. return;
  22. }
  23. if(is_array($text) || is_object($text)) {
  24. $text = str_replace("\n", '', print_r($text, true));
  25. }
  26. //** Cannot use quotes */
  27. $text = str_replace('"', '-', $text);
  28. add_filter('wp_footer', create_function('$nothing,$echo_text = "'. $text .'"', 'echo \'<script type="text/javascript">if(typeof console == "object"){console.log("\' . $echo_text . \'");}</script>\'; '));
  29. add_filter('admin_footer', create_function('$nothing,$echo_text = "'. $text .'"', 'echo \'<script type="text/javascript">if(typeof console == "object"){console.log("\' . $echo_text . \'");}</script>\'; '));
  30. }
  31. /**
  32. * Retreives API key from UD servers.
  33. *
  34. * @todo Add loggin functionality so user can reference some log to see why key may not be updating.
  35. * @since 3.0.2
  36. *
  37. */
  38. function get_api_key($args = false){
  39. $defaults = array(
  40. 'return_all' => false,
  41. 'force_check' => false
  42. );
  43. $args = wp_parse_args( $args, $defaults );
  44. //** check if API key already exists */
  45. $ud_api_key = get_option('ud_api_key');
  46. //** if key exists, and we are not focing a check, return what we have */
  47. if($ud_api_key && !$args['force_check']) {
  48. return $ud_api_key;
  49. }
  50. $blogname = urlencode(str_replace(array('http://', 'https://'), '', get_bloginfo('url')));
  51. $system = 'wpi';
  52. $wpp_version = WP_INVOICE_VERSION_NUM;
  53. $check_url = "http://updates.usabilitydynamics.com/key_generator.php?system=$system&site=$blogname&system_version=$wpp_version";
  54. $response = @wp_remote_get($check_url);
  55. if(!$response) {
  56. return false;
  57. }
  58. //** Check for errors */
  59. if(is_object($response) && !empty($response->errors)) {
  60. /*
  61. foreach($response->errors as $errors) {
  62. $error_string .= implode(",", $errors);
  63. UD_F::log("API Check Error: " . $error_string);
  64. }
  65. */
  66. return false;
  67. }
  68. //** Quit if failture */
  69. if($response['response']['code'] != '200') {
  70. return false;
  71. }
  72. $response['body'] = trim($response['body']);
  73. //** If return is not in MD5 format, it is an error */
  74. if(strlen($response['body']) != 40) {
  75. if($args['return']) {
  76. return $response['body'];
  77. } else {
  78. /* UD_F::log("API Check Error: " . sprintf(__('An error occured during premium feature check: <b>%s</b>.','wpp'), $response['body'])); */
  79. return false;
  80. }
  81. }
  82. //** update wpi_key is DB */
  83. update_option('ud_api_key', $response['body']);
  84. // Go ahead and return, it should just be the API key
  85. return $response['body'];
  86. }
  87. /**
  88. * Function for performing a wpi_object search
  89. *
  90. *
  91. * @todo This function is not ready at all, it doesn't do any searching, just returns all invoices for testing datatables
  92. * @since 3.0
  93. *
  94. */
  95. static function query($search_vars = false) {
  96. global $wpdb;
  97. $sort_by = " ORDER BY post_modified DESC ";
  98. /** Start our SQL */
  99. $sql = "SELECT * FROM {$wpdb->posts} AS p WHERE post_type = 'wpi_object' ";
  100. if (!empty($search_vars)) {
  101. if (is_string($search_vars)) {
  102. $args = array();
  103. parse_str($search_vars, $args);
  104. $search_vars = $args;
  105. }
  106. /*
  107. $use_status_filter = false;
  108. if ( !empty( $search_vars['status'] ) ) {
  109. $use_status_filter = true;
  110. }
  111. */
  112. foreach ($search_vars as $primary_key => $key_terms) {
  113. //** Handle search_string differently, it applies to all meta values */
  114. if ($primary_key == 's') {
  115. /* First, go through the posts table */
  116. $tofind = strtolower($key_terms);
  117. $sql .= " AND (";
  118. $sql .= " p.ID IN (SELECT ID FROM {$wpdb->posts} WHERE LOWER(post_title) LIKE '%$tofind%')";
  119. /* Now go through the post meta table */
  120. $sql .= " OR p.ID IN (SELECT post_id FROM {$wpdb->postmeta} WHERE LOWER(meta_value) LIKE '%$tofind%')";
  121. $sql .= ")";
  122. continue;
  123. }
  124. // Type
  125. if ($primary_key == 'type') {
  126. if (empty($key_terms)) {
  127. continue;
  128. }
  129. if (is_array($key_terms)) {
  130. $key_terms = implode("','", $key_terms);
  131. }
  132. $sql .= " AND ";
  133. $sql .= " p.ID IN (SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = 'type' AND meta_value IN ('{$key_terms}'))";
  134. continue;
  135. }
  136. // Status
  137. if ($primary_key == 'status') {
  138. if (empty($key_terms)) {
  139. continue;
  140. }
  141. if (is_array($key_terms)) {
  142. $sql .= " AND (";
  143. $i = 0;
  144. foreach ($key_terms as $term) {
  145. if (empty($term)) {
  146. continue;
  147. }
  148. if ($i > 0) {
  149. $sql .= " OR ";
  150. }
  151. $sql .= " post_status = '{$term}' ";
  152. $i++;
  153. }
  154. $sql .= ")";
  155. }
  156. }
  157. /*
  158. if ( !$use_status_filter ) {
  159. $sql .= " AND ( post_status = 'active' ) ";
  160. }
  161. */
  162. // Recipient
  163. if ($primary_key == 'recipient') {
  164. if (empty($key_terms)) {
  165. continue;
  166. }
  167. $user = get_user_by('id', $key_terms);
  168. $sql .= " AND ";
  169. $sql .= " p.ID IN (SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = 'user_email' AND meta_value = '{$user->user_email}')";
  170. continue;
  171. }
  172. // Sorting
  173. if ($primary_key == 'sorting') {
  174. $sort_by = " ORDER BY {$key_terms['order_by']} {$key_terms['sort_dir']} ";
  175. }
  176. /* Date */
  177. if ($primary_key == 'm') {
  178. if (empty($key_terms) || (int) $key_terms == 0) {
  179. continue;
  180. }
  181. $key_terms = '' . preg_replace('|[^0-9]|', '', $key_terms);
  182. $sql .= " AND YEAR(post_date)=" . substr($key_terms, 0, 4);
  183. if (strlen($key_terms) > 5) {
  184. $sql .= " AND MONTH(post_date)=" . substr($key_terms, 4, 2);
  185. }
  186. if (strlen($key_terms) > 7) {
  187. $sql .= " AND DAYOFMONTH(post_date)=" . substr($key_terms, 6, 2);
  188. }
  189. if (strlen($key_terms) > 9) {
  190. $sql .= " AND HOUR(post_date)=" . substr($key_terms, 8, 2);
  191. }
  192. if (strlen($key_terms) > 11) {
  193. $sql .= " AND MINUTE(post_date)=" . substr($key_terms, 10, 2);
  194. }
  195. if (strlen($key_terms) > 13) {
  196. $sql .= " AND SECOND(post_date)=" . substr($key_terms, 12, 2);
  197. }
  198. }
  199. }
  200. }
  201. $sql = $sql . $sort_by;
  202. //echo $sql;
  203. $results = $wpdb->get_results($sql);
  204. return $results;
  205. }
  206. /**
  207. *
  208. * @global object $wpdb
  209. * @param array $search_vars
  210. * @param string $interval
  211. * @return mixed
  212. * @author odokienko@UD
  213. */
  214. static function get_sales_by ($search_vars = false, $interval="weekly") {
  215. global $wpdb;
  216. switch ($interval){
  217. case "weekly":
  218. $interval_function = 'WEEK';
  219. break;
  220. case 'daily':
  221. $interval_function = 'DAYOFYEAR';
  222. break;
  223. case 'monthly':
  224. default:
  225. $interval_function = 'MONTH';
  226. break;
  227. }
  228. if (!empty($search_vars)) {
  229. if (is_string($search_vars)) {
  230. $args = array();
  231. parse_str($search_vars, $args);
  232. $search_vars = $args;
  233. }
  234. foreach ($search_vars as $primary_key => $key_terms) {
  235. //** Handle search_string differently, it applies to all meta values */
  236. if ($primary_key == 's' && !empty($key_terms)) {
  237. /* First, go through the posts table */
  238. $tofind = strtolower($key_terms);
  239. $sql .= " AND (";
  240. $sql .= " LOWER(`{$wpdb->posts}`.post_title) LIKE '%$tofind%'";
  241. /* Now go through the post meta table */
  242. $sql .= " OR
  243. `{$wpdb->posts}`.ID IN (SELECT post_id FROM {$wpdb->postmeta} WHERE LOWER(meta_value) LIKE '%$tofind%')";
  244. $sql .= ")";
  245. continue;
  246. }
  247. // Type
  248. if ($primary_key == 'type') {
  249. if (empty($key_terms)) {
  250. continue;
  251. }
  252. if (is_array($key_terms)) {
  253. $key_terms = implode("','", $key_terms);
  254. }
  255. $sql .= " AND ";
  256. $sql .= " `{$wpdb->posts}`.ID IN (SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = 'type' AND meta_value IN ('{$key_terms}'))";
  257. continue;
  258. }
  259. // Status
  260. if ($primary_key == 'status') {
  261. if (empty($key_terms)) {
  262. continue;
  263. }
  264. if (is_array($key_terms)) {
  265. $sql .= " AND (";
  266. $i = 0;
  267. foreach ($key_terms as $term) {
  268. if (empty($term)) {
  269. continue;
  270. }
  271. if ($i > 0) {
  272. $sql .= " OR ";
  273. }
  274. $sql .= " `{$wpdb->posts}`.post_status = '{$term}' ";
  275. $i++;
  276. }
  277. $sql .= ")";
  278. }
  279. }
  280. /*
  281. if ( !$use_status_filter ) {
  282. $sql .= " AND ( post_status = 'active' ) ";
  283. }
  284. */
  285. // Recipient
  286. if ($primary_key == 'recipient') {
  287. if (empty($key_terms)) {
  288. continue;
  289. }
  290. $user = get_user_by('id', $key_terms);
  291. $sql .= " AND ";
  292. $sql .= " `{$wpdb->posts}`.ID IN (SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = 'user_email' AND meta_value = '{$user->user_email}')";
  293. continue;
  294. }
  295. /* Date */
  296. if ($primary_key == 'm') {
  297. if (empty($key_terms) || (int) $key_terms == 0) {
  298. continue;
  299. }
  300. $key_terms = '' . preg_replace('|[^0-9]|', '', $key_terms);
  301. $sql .= " AND YEAR(`{$wpdb->posts}`.post_date)=" . substr($key_terms, 0, 4);
  302. if (strlen($key_terms) > 5) {
  303. $sql .= " AND MONTH(`{$wpdb->posts}`.post_date)=" . substr($key_terms, 4, 2);
  304. }
  305. if (strlen($key_terms) > 7) {
  306. $sql .= " AND DAYOFMONTH(`{$wpdb->posts}`.post_date)=" . substr($key_terms, 6, 2);
  307. }
  308. if (strlen($key_terms) > 9) {
  309. $sql .= " AND HOUR(`{$wpdb->posts}`.post_date)=" . substr($key_terms, 8, 2);
  310. }
  311. if (strlen($key_terms) > 11) {
  312. $sql .= " AND MINUTE(`{$wpdb->posts}`.post_date)=" . substr($key_terms, 10, 2);
  313. }
  314. if (strlen($key_terms) > 13) {
  315. $sql .= " AND SECOND(`{$wpdb->posts}`.post_date)=" . substr($key_terms, 12, 2);
  316. }
  317. }
  318. }
  319. }
  320. $date_table = "
  321. select @maxDate - interval (a.a+(10*b.a)+(100*c.a)) day aDate from
  322. (select 0 as a union all select 1 union all select 2 union all select 3
  323. union all select 4 union all select 5 union all select 6 union all
  324. select 7 union all select 8 union all select 9) a, /*10 day range*/
  325. (select 0 as a union all select 1 union all select 2 union all select 3
  326. union all select 4 union all select 5 union all select 6 union all
  327. select 7 union all select 8 union all select 9) b, /*100 day range*/
  328. (select 0 as a union all select 1 union all select 2 union all select 3
  329. union all select 4 union all select 5 union all select 6 union all
  330. select 7 union all select 8 union all select 9) c, /*1000 day range*/
  331. (select
  332. @minDate := date_format(FROM_UNIXTIME((select min(time) from `{$wpdb->prefix}wpi_object_log` mn join {$wpdb->posts} on (mn.object_id=`{$wpdb->posts}`.id and `{$wpdb->posts}`.post_type = 'wpi_object' {$sql}))),'%Y-%m-%d'),
  333. @maxDate := date_format(FROM_UNIXTIME((select max(time) from `{$wpdb->prefix}wpi_object_log` mx join {$wpdb->posts} on (mx.object_id=`{$wpdb->posts}`.id and `{$wpdb->posts}`.post_type = 'wpi_object' {$sql}))),'%Y-%m-%d')
  334. ) e
  335. ";
  336. $sql = "
  337. SELECT distinct
  338. YEAR(datetable.aDate) as int_year,
  339. {$interval_function}(datetable.aDate) int_erval,
  340. sum(COALESCE(if (payment.action='refund',payment.value*-1,payment.value),0)) as sum_interval
  341. FROM ($date_table) datetable
  342. left join `{$wpdb->prefix}wpi_object_log` as payment on (
  343. datetable.aDate=date_format(FROM_UNIXTIME(payment.time),'%Y-%m-%d')
  344. and (
  345. payment.object_id in (
  346. select `{$wpdb->posts}`.id from `{$wpdb->posts}` where `{$wpdb->posts}`.post_type = 'wpi_object' {$sql}
  347. )
  348. )
  349. AND (payment.action = 'add_payment' or payment.action = 'refund')
  350. AND payment.attribute = 'balance'
  351. )
  352. WHERE datetable.aDate between @minDate and @maxDate
  353. GROUP BY 1,2
  354. ";
  355. $results = $wpdb->get_results($sql);
  356. return $results;
  357. }
  358. /**
  359. * Get Search filter fields
  360. *
  361. * @global array $wpi_settings
  362. * @global object $wpdb
  363. * @return type
  364. */
  365. function get_search_filters() {
  366. global $wpi_settings, $wpdb;
  367. $filters = array();
  368. $default = array(array(
  369. 'key' => 'all',
  370. 'label' => __('All'),
  371. 'amount' => 0
  372. ));
  373. if (isset($wpi_settings['types'])) {
  374. $f = $default;
  375. $i = 1;
  376. $all = 0;
  377. foreach ($wpi_settings['types'] as $key => $value) {
  378. $amount = $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->postmeta} WHERE meta_key = 'type' AND meta_value = '{$key}'");
  379. $all = $all + $amount;
  380. if ($amount > 0) {
  381. $f[$i]['key'] = $key;
  382. $f[$i]['label'] = $value['label'];
  383. $f[$i]['amount'] = $amount;
  384. $i++;
  385. }
  386. }
  387. if ($all > 0) {
  388. $f[0]['amount'] = $all;
  389. $filters['type'] = $f;
  390. }
  391. // If there is only 1 type - hide Types option
  392. if ($i == 2) {
  393. unset($filters['type']);
  394. }
  395. }
  396. if (!empty($wpi_settings['statuses'])) {
  397. $f = array();
  398. $amount = 0;
  399. $i = 1;
  400. $all = 0;
  401. foreach ($wpi_settings['statuses'] as $status) {
  402. $amount = $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_status = '{$status}' AND post_type = 'wpi_object'");
  403. $all = $all + $amount;
  404. if ($amount > 0) {
  405. $f[$i]['key'] = $status;
  406. $f[$i]['label'] = strtoupper(substr($status, 0, 1)) . substr($status, 1);
  407. $f[$i]['amount'] = $amount;
  408. $i++;
  409. }
  410. }
  411. if ($all > 0) {
  412. $filters['status'] = $f;
  413. }
  414. }
  415. return $filters;
  416. }
  417. /**
  418. * Convert a string to a url-like slug
  419. *
  420. * @param type $slug
  421. * @return type
  422. */
  423. function slug_to_label($slug = false) {
  424. if (!$slug)
  425. return;
  426. $slug = str_replace("_", " ", $slug);
  427. $slug = ucwords($slug);
  428. return $slug;
  429. }
  430. /**
  431. * Convert a string into a number. Allow invoice ID to be passed for currency symbol localization
  432. *
  433. * @global array $wpi_settings
  434. * @param type $amount
  435. * @param type $invoice_id
  436. * @return type
  437. */
  438. static function currency_format($amount, $invoice_id = false) {
  439. global $wpi_settings;
  440. if ($invoice_id) {
  441. $invoice = get_invoice($invoice_id);
  442. }
  443. $currency_symbol = !empty($wpi_settings['currency']['symbol'][$invoice['default_currency_code']]) ? $wpi_settings['currency']['symbol'][$invoice['default_currency_code']] : '$';
  444. $amount = (float) $amount;
  445. $thousands_separator_symbol = !isset( $wpi_settings['thousands_separator_symbol'] )?',':($wpi_settings['thousands_separator_symbol'] == '0'?'':$wpi_settings['thousands_separator_symbol']);
  446. return $currency_symbol . number_format($amount, 2, '.', $thousands_separator_symbol);
  447. }
  448. /**
  449. * Run numbers for reporting purposes.
  450. *
  451. * @global object $wpdb
  452. * @global type $wpi_reports
  453. * @return type
  454. */
  455. static function run_reports() {
  456. global $wpdb, $wpi_reports;
  457. //* Get all invoices */
  458. $invoice_ids = $wpdb->get_col("SELECT ID FROM {$wpdb->posts} WHERE post_type = 'wpi_object' ");
  459. $totals = array();
  460. $objects = array();
  461. $r = array(
  462. 'line_item_counts' => array()
  463. );
  464. foreach ($invoice_ids as $post_id) {
  465. $wpi_invoice_object = new WPI_Invoice();
  466. $wpi_invoice_object->load_invoice("id=$post_id");
  467. $objects[$post_id] = $wpi_invoice_object->data;
  468. }
  469. foreach ($objects as $object) {
  470. //** Total paid invoices per client */
  471. if ($object['post_status'] == 'paid') {
  472. $r['collected_client_value'][$object['user_email']] = !empty($r['client_value'][$object['user_email']]) ? $r['client_value'][$object['user_email']] : 0 + $object['subtotal'] + $object['total_tax'] - $object['total_discount'];
  473. $r['total_paid'][] = $objects[$object['ID']]['subtotal'] + $objects[$object['ID']]['total_tax'] - $objects[$object['ID']]['total_discount'];;
  474. foreach ($object['itemized_list'] as $list_item) {
  475. $r['collected_line_items'][$list_item['name']] = !empty($r['collected_line_items'][$list_item['name']]) ? $r['collected_line_items'][$list_item['name']] : 0 + $list_item['line_total_after_tax'];
  476. if (!empty($r['line_item_counts'][$list_item['name']])) {
  477. $r['line_item_counts'][$list_item['name']]++;
  478. } else {
  479. $r['line_item_counts'][$list_item['name']] = 1;
  480. }
  481. }
  482. }
  483. if ($object['post_status'] == 'active') {
  484. $r['uncollected_client_value'][$object['user_email']] = !empty($r['uncollected_client_value'][$object['user_email']]) ? $r['uncollected_client_value'][$object['user_email']] : 0 + $object['subtotal'] + $object['total_tax'] - $object['total_discount'];
  485. $r['total_unpaid'][] = $objects[$object['ID']]['subtotal'] + $objects[$object['ID']]['total_tax'] - $objects[$object['ID']]['total_discount'];
  486. }
  487. }
  488. if (isset($r['collected_line_items']) && is_array($r['collected_line_items'])) {
  489. arsort($r['collected_line_items']);
  490. }
  491. if (isset($r['uncollected_client_value']) && is_array($r['uncollected_client_value'])) {
  492. arsort($r['uncollected_client_value']);
  493. }
  494. if (isset($r['collected_client_value']) && is_array($r['collected_client_value'])) {
  495. arsort($r['collected_client_value']);
  496. }
  497. if (isset($r['total_paid']) && is_array($r['total_paid'])) {
  498. $r['total_paid'] = array_sum($r['total_paid']);
  499. }
  500. if (isset($r['total_unpaid']) && is_array($r['total_unpaid'])) {
  501. $r['total_unpaid'] = array_sum($r['total_unpaid']);
  502. }
  503. $wpi_reports = $r;
  504. return $r;
  505. }
  506. /**
  507. * Check if theme-specific stylesheet exists.
  508. *
  509. * get_option('template') seems better choice than get_option('stylesheet'), which returns the current theme's slug
  510. * which is a problem when a child theme is used. We want the parent theme's slug.
  511. *
  512. * @since 3.0
  513. *
  514. */
  515. static function has_theme_specific_stylesheet() {
  516. $theme_slug = get_option('template');
  517. if (file_exists(WPI_Path . "/core/template/theme-specific/{$theme_slug}.css")) {
  518. return true;
  519. }
  520. return false;
  521. }
  522. /**
  523. * Check if Payment method allowed
  524. * @param String $param
  525. * @return bool
  526. */
  527. function is_true($param) {
  528. if (empty($param))
  529. return false;
  530. return ( $param == 'true' || $param == 'on' || $param == 'yes' ) ? true : false;
  531. }
  532. /**
  533. * Fixes billing structure
  534. * @param array $wpi_settings_billings
  535. * @param array &$invoice_billings
  536. */
  537. function merge_billings($wpi_settings_billings, $invoice_billings) {
  538. if (!isset($invoice_billings) || !is_array($invoice_billings)) {
  539. $invoice_billings = array();
  540. }
  541. if (is_array($wpi_settings_billings)) {
  542. foreach ($wpi_settings_billings as $key => $value) {
  543. // TODO: Refactor on|yes|true off|no|false
  544. // WPI_Functions::is_true() used temporary
  545. if (!WPI_Functions::is_true($value['allow'])) {
  546. unset($invoice_billings[$key]);
  547. } else {
  548. if (!empty($invoice_billings[$key])) {
  549. if (!isset($invoice_billings[$key]['name'])) {
  550. $invoice_billings[$key]['name'] = $value['name'];
  551. }
  552. if (!isset($invoice_billings[$key]['allow'])) {
  553. $invoice_billings[$key]['allow'] = $value['allow'];
  554. }
  555. if (!isset($invoice_billings[$key]['default_option'])) {
  556. $invoice_billings[$key]['default_option'] = $value['default_option'];
  557. }
  558. if (!empty($value['settings'])) {
  559. foreach ($value['settings'] as $setting_key => $setting_value) {
  560. foreach ($setting_value as $setting_key_field => $setting_value_field) {
  561. if (!isset($invoice_billings[$key]['settings'][$setting_key][$setting_key_field])) {
  562. $invoice_billings[$key]['settings'][$setting_key][$setting_key_field] = $setting_value_field;
  563. }
  564. }
  565. }
  566. }
  567. } else {
  568. $invoice_billings[$key] = $value;
  569. }
  570. }
  571. }
  572. }
  573. }
  574. function set_default_payment_method($wpi_settings_billings, $invoice_data) {
  575. $settings_dpm = '';
  576. if (!empty($wpi_settings_billings) && is_array($wpi_settings_billings)) {
  577. foreach ($wpi_settings_billings as $method => $value) {
  578. if ($value['default_option'] == 'true') {
  579. $settings_dpm = $method;
  580. }
  581. }
  582. }
  583. $invoice_data['default_payment_method'] = $settings_dpm;
  584. }
  585. /**
  586. * Returns an array of users
  587. * Used for user-email auto-completion.
  588. * @uses $wpdb
  589. * @since 3.0
  590. * @return array. Users List
  591. *
  592. */
  593. function build_user_array() {
  594. global $wpdb;
  595. return $wpdb->get_results("SELECT display_name,user_email,ID FROM {$wpdb->prefix}users", ARRAY_A);
  596. }
  597. /**
  598. * Handle user data updating
  599. *
  600. * Typically called when saving an invoice.
  601. * @since 3.0
  602. */
  603. function update_user($userdata) {
  604. $user_id = email_exists($userdata['user_email']);
  605. if ($user_id) {
  606. $userdata['ID'] = $user_id;
  607. }
  608. if (empty($userdata['ID']) && empty($userdata['user_email'])) {
  609. return false;
  610. }
  611. if ($user_id) {
  612. $user_id = wp_update_user($userdata);
  613. } else {
  614. if (empty($userdata['user_login'])) {
  615. if (!empty($userdata['first_name']) && !empty($userdata['last_name'])) {
  616. $userdata['display_name'] = $userdata['first_name'] . ' ' . $userdata['last_name'];
  617. } else {
  618. }
  619. }
  620. $userdata['user_login'] = $userdata['user_email'];
  621. if(empty($userdata['user_pass'])) {
  622. $userdata['user_pass'] = wp_generate_password( 12, false);
  623. }
  624. $user_id = wp_insert_user($userdata);
  625. }
  626. // Prevent entering of wrong phone number to avoid errors on front-end
  627. if (!preg_match('/\A[\d.+?]{0,3}-[\d.+?]{0,3}-[\d.+?]{0,4}\Z/si', $userdata['phonenumber'])) {
  628. if (preg_match('/\A[\d.+?]{0,10}\Z/si', $userdata['phonenumber'])) {
  629. $phonenumber = $userdata['phonenumber'];
  630. $userdata['phonenumber'] = substr($phonenumber, 0, 3) . '-' . substr($phonenumber, 3, 3) . '-' . substr($phonenumber, 6, 4);
  631. } else {
  632. $userdata['phonenumber'] = '';
  633. }
  634. }
  635. if (!is_object($user_id) && $user_id > 0) {
  636. /* Update user's meta data */
  637. $non_meta_data = array(
  638. 'ID',
  639. 'first_name',
  640. 'last_name',
  641. 'nickname',
  642. 'description',
  643. 'user_pass',
  644. 'user_email',
  645. 'user_url',
  646. 'user_nicename',
  647. 'display_name',
  648. 'user_registered',
  649. 'role'
  650. );
  651. foreach ($userdata as $key => $value) {
  652. if (!in_array($key, $non_meta_data)) {
  653. update_user_meta($user_id, $key, $value);
  654. }
  655. }
  656. return $user_id;
  657. }
  658. return $user_id;
  659. }
  660. /**
  661. * Add itemized charge like itemized list item
  662. *
  663. * @param int $invoice_id
  664. * @param string $name
  665. * @param float $amount
  666. * @param float $tax
  667. * @return array
  668. */
  669. function add_itemized_charge($invoice_id, $name, $amount, $tax) {
  670. $post_id = wpi_invoice_id_to_post_id($invoice_id);
  671. $charge_items = get_post_meta($post_id, 'itemized_charges', true);
  672. $new_item = array(
  673. 'name' => $name,
  674. 'amount' => $amount,
  675. 'tax' => $tax,
  676. 'before_tax' => $amount,
  677. 'after_tax' => $amount + ($amount / 100 * $tax)
  678. );
  679. if (!empty($charge_items)) {
  680. $charge_items[] = $new_item;
  681. } else {
  682. $charge_items[0] = $new_item;
  683. }
  684. update_post_meta($post_id, 'itemized_charges', $charge_items);
  685. return end($charge_items);
  686. }
  687. /**
  688. * Loads invoice variables into post if it is a wpi_object
  689. *
  690. * @hooked_into setup_postdata()
  691. * @uses $wpdb
  692. * @since 3.0
  693. *
  694. */
  695. function the_post(&$post) {
  696. global $post;
  697. if ($post->post_type == 'wpi_object') {
  698. $this_invoice = new WPI_Invoice();
  699. $invoice_id = $post->ID;
  700. $this_invoice->load_invoice("id=$invoice_id");
  701. $t_post = (array) $post;
  702. $t_data = (array) $this_invoice->data;
  703. $t_post = WPI_Functions::array_merge_recursive_distinct($t_post, $t_data);
  704. $post = (object) $t_post;
  705. }
  706. }
  707. function objectToArray($object) {
  708. if (!is_object($object) && !is_array($object)) {
  709. return $object;
  710. }
  711. if (is_object($object)) {
  712. $object = get_object_vars($object);
  713. }
  714. return array_map(array('WPI_functions', 'objectToArray'), $object);
  715. }
  716. /**
  717. Generates a slug
  718. */
  719. function generateSlug($title) {
  720. $slug = preg_replace("/[^a-zA-Z0-9 ]/", "", $title);
  721. $slug = str_replace(" ", "_", $slug);
  722. return $slug;
  723. }
  724. /**
  725. * Figure out current page for front-end AJAX function
  726. */
  727. function current_page() {
  728. $pageURL = 'http';
  729. if (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on") {
  730. $pageURL .= "s";
  731. }
  732. $pageURL .= "://";
  733. if ($_SERVER["SERVER_PORT"] != "80") {
  734. $pageURL .= $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . $_SERVER["REQUEST_URI"];
  735. } else {
  736. $pageURL .= $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"];
  737. }
  738. return $pageURL;
  739. }
  740. /**
  741. Get users paid and pending invoices
  742. */
  743. function get_user_invoices($args) {
  744. global $wpdb;
  745. $defaults = array('user_id' => false, 'status' => false);
  746. extract(wp_parse_args($args, $defaults), EXTR_SKIP);
  747. // User email and id are the same thing
  748. if (!$user_id && isset($user_email))
  749. $user_id = $user_email;
  750. // If nothing is set, nothing we can do
  751. if (!isset($user_id))
  752. return;
  753. $users_invoices = $wpdb->get_col("
  754. SELECT post_id
  755. FROM {$wpdb->postmeta} postmeta
  756. JOIN {$wpdb->posts} posts ON posts.ID = postmeta.post_id
  757. WHERE postmeta.meta_key = 'user_email'
  758. AND postmeta.meta_value = '" . $user_id . "'
  759. AND posts.post_type = 'wpi_object'
  760. AND posts.post_status = '$status'
  761. ");
  762. // Nothing found
  763. if (!is_array($users_invoices))
  764. return false;
  765. $return = array();
  766. foreach ($users_invoices as $post_id) {
  767. $invoice_id = wpi_post_id_to_invoice_id($post_id);
  768. $this_invoice = new WPI_Invoice();
  769. $this_invoice->load_invoice("id={$invoice_id}");
  770. if (!empty($status) && $status != $this_invoice->data['post_status'])
  771. continue;
  772. // Do not include quotes
  773. if ($this_invoice->data['type'] != 'invoice') {
  774. continue;
  775. }
  776. $return[] = $this_invoice;
  777. }
  778. return $return;
  779. }
  780. /**
  781. Add message to notice queve
  782. */
  783. function add_message($message, $type = 'good', $class = '') {
  784. global $wpi_messages;
  785. if (!is_array($wpi_messages))
  786. $wpi_messages = array();
  787. array_push($wpi_messages, array('message' => $message, 'type' => $type, 'class' => $class));
  788. }
  789. /**
  790. Display messages in queve
  791. */
  792. function print_messages() {
  793. global $wpi_messages;
  794. if (count($wpi_messages) < 1)
  795. return;
  796. $update_messages = array();
  797. $warning_messages = array();
  798. echo "<div id='wpi_message_stack'>";
  799. foreach ($wpi_messages as $message) {
  800. if ($message['type'] == 'good') {
  801. array_push($update_messages, array('message' => $message['message'], 'class' => $message['class']));
  802. }
  803. if ($message['type'] == 'bad') {
  804. array_push($warning_messages, array('message' => $message['message'], 'class' => $message['class']));
  805. }
  806. }
  807. if (count($update_messages) > 0) {
  808. echo "<div class='wpi_message wpi_yellow_notification'>";
  809. foreach ($update_messages as $u_message)
  810. echo "<div class='wpi_message_holder {$message['class']}' >{$u_message['message']}</div>";
  811. echo "</div>";
  812. }
  813. if (count($warning_messages) > 0) {
  814. echo "<div class='wpi_message wpi_red_notification'>";
  815. foreach ($warning_messages as $w_message)
  816. echo "<div class='wpi_message_holder {$w_message['class']}' >{$w_message['message']}</div>";
  817. echo "</div>";
  818. }
  819. echo "</div>";
  820. }
  821. /**
  822. * Checks if particular template exists in the template folder
  823. *
  824. * @global array $wpi_settings
  825. * @param type $template
  826. * @return type
  827. */
  828. function wpi_use_custom_template($template) {
  829. global $wpi_settings;
  830. /* if custom templates are turned off, don't bother checking */
  831. if (!isset($wpi_settings['use_custom_templates']) || $wpi_settings['use_custom_templates'] != 'yes') {
  832. return false;
  833. }
  834. if (file_exists($wpi_settings['frontend_template_path'] . "$template")) {
  835. return true;
  836. }
  837. return false;
  838. }
  839. /**
  840. * Determine WPI front-end template path
  841. *
  842. * @global array $wpi_settings
  843. * @return type
  844. */
  845. function template_path() {
  846. global $wpi_settings;
  847. $use_custom_templates = false;
  848. if (file_exists(STYLESHEETPATH . "/wpi/")) {
  849. return STYLESHEETPATH . "/wpi/";
  850. }
  851. }
  852. /**
  853. * Display invoice status formatted for back-end
  854. *
  855. * @param type $invoice_id
  856. */
  857. function get_status($invoice_id) {
  858. $this_invoice = new WPI_Invoice();
  859. $this_invoice->load_invoice("id=$invoice_id");
  860. if (is_array($this_invoice->data['log'])) {
  861. foreach (array_reverse($this_invoice->data['log']) as $event) {
  862. if (empty($event['text'])) {
  863. continue;
  864. }
  865. ?>
  866. <tr class="wpi_event_<?php echo $event['action']; ?> <?php if ($event['action'] == 'add_charge' || $event['action'] == 'do_adjustment')
  867. echo "wpi_not_for_recurring"; ?>">
  868. <th><?php echo date(get_option('time_format') . ' ' . get_option('date_format'), $event['time']); ?> </th>
  869. <td><?php echo $event['text']; ?></td>
  870. </tr>
  871. <?php
  872. }
  873. } else {
  874. ?>
  875. <tr class="wpi_event_error">
  876. <th colspan='2'>No log entries.</th>
  877. </tr>
  878. <?php
  879. }
  880. }
  881. /**
  882. * Render itemized charges list
  883. *
  884. * @param int $post_id
  885. */
  886. function get_charges($post_id) {
  887. $charges_list = get_post_meta($post_id, 'itemized_charges', true);
  888. $result = '';
  889. ob_start();
  890. if (!empty($charges_list)) {
  891. foreach ($charges_list as $key => $value) {
  892. ?>
  893. <li class="wp_invoice_itemized_charge_row clearfix" id="wp_invoice_itemized_charge_row_<?php echo $key; ?>">
  894. <span class="id hidden"><?php echo $key; ?></span>
  895. <div class="flexible_width_holder">
  896. <div class="flexible_width_holder_content">
  897. <span class="row_delete">&nbsp;</span>
  898. <input class="item_name input_field" name="wpi_invoice[itemized_charges][<?php echo $key; ?>][name]" value="<?php echo stripslashes($value['name']); ?>" />
  899. </div>
  900. </div>
  901. <span class="fixed_width_holder">
  902. <span class="row_amount">
  903. <input autocomplete="off" value="<?php echo stripslashes($value['amount']); ?>" name="wpi_invoice[itemized_charges][<?php echo $key; ?>][amount]" id="amount_item_<?php echo $key; ?>" class="item_amount input_field">
  904. </span>
  905. <span class="row_charge_tax">
  906. <input autocomplete="off" value="<?php echo stripslashes($value['tax']); ?>" name="wpi_invoice[itemized_charges][<?php echo $key; ?>][tax]" id="charge_tax_item_<?php echo $key; ?>" class="item_charge_tax input_field">
  907. </span>
  908. <span class="row_total" id="total_item_<?php echo $key; ?>" ><?php echo $value['after_tax']; ?></span>
  909. </span>
  910. </li>
  911. <?php
  912. }
  913. $result .= ob_get_contents();
  914. ob_end_clean();
  915. }
  916. echo $result;
  917. }
  918. /**
  919. * Returns highest invoice ID
  920. *
  921. * @global object $wpdb
  922. * @return longint
  923. * @author korotkov@ud
  924. */
  925. function get_highest_custom_id() {
  926. global $wpdb;
  927. $invoices = get_posts(
  928. array(
  929. 'post_type' => 'wpi_object',
  930. 'numberposts' => 0,
  931. 'post_status' => 'any'
  932. )
  933. );
  934. if (!count($invoices)) {
  935. return false;
  936. }
  937. $id_array = array();
  938. foreach ($invoices as $invoice) {
  939. $id_array[] = get_post_meta($invoice->ID, 'invoice_id', true);
  940. /** Get custom IDs too */
  941. $custom_id = get_post_meta($invoice->ID, 'custom_id', true);
  942. if ( $custom_id ) {
  943. $id_array[] = $custom_id;
  944. }
  945. }
  946. return @max($id_array);
  947. }
  948. /**
  949. * Removes empty values from array
  950. *
  951. * @param array $array
  952. * @return array
  953. * @author korotkov@ud
  954. */
  955. function remove_blank_values($array) {
  956. if (!is_array($array))
  957. return false;
  958. foreach ($array as $key => $value) {
  959. if (!empty($value))
  960. $return[$key] = $value;
  961. }
  962. return $return;
  963. }
  964. /**
  965. * Run when a plugin is being activated
  966. * Handles the task of migrating from old version of WPI to new
  967. */
  968. function Activate() {
  969. global $wpdb, $wpi_settings;
  970. /* check if scheduler already sheduled */
  971. if(!wp_next_scheduled('wpi_hourly_event')){
  972. /* Setup WPI schedule to handle recurring invoices */
  973. wp_schedule_event(time(), 'hourly', 'wpi_hourly_event');
  974. }
  975. if(!wp_next_scheduled('wpi_update')){
  976. /* Scheduling daily update event */
  977. wp_schedule_event(time(), 'daily', 'wpi_update');
  978. }
  979. WPI_Functions::log(__("Schedule created with plugin activation.", WPI));
  980. /* Try to create new schema tables */
  981. WPI_Functions::create_new_schema_tables();
  982. /* Get previous activated version */
  983. $current_version = get_option('wp_invoice_version');
  984. /* If no version found at all, we do new install */
  985. if ($current_version == WP_INVOICE_VERSION_NUM) {
  986. WPI_Functions::log(__("Plugin activated. No older versions found, installing version ", WPI) . WP_INVOICE_VERSION_NUM . ".");
  987. } else if ((int) $current_version < 3) {
  988. /* Determine if legacy data exist */
  989. WPI_Legacy::init();
  990. WPI_Functions::log(__("Plugin activated.", WPI));
  991. }
  992. /* Update version */
  993. update_option('wp_invoice_version', WP_INVOICE_VERSION_NUM);
  994. WPI_Functions::check_for_premium_features();
  995. update_option('wpi_activation_time', time());
  996. }
  997. function Deactivate() {
  998. wp_clear_scheduled_hook('wpi_hourly_event');
  999. wp_clear_scheduled_hook('wpi_update');
  1000. WPI_Functions::log(__("Plugin deactivated.", WPI));
  1001. }
  1002. /**
  1003. * Called by profile_update action/hook
  1004. * Used to save profile settings for WP Users.
  1005. * @param int $user_id User ID
  1006. * @param object $old_user_data old value.
  1007. * @return bool True on successful update, false on failure.
  1008. */
  1009. function save_update_profile($user_id, $old_user_data) {
  1010. global $wpi_settings;
  1011. if (empty($user_id) || $user_id == 0) {
  1012. return false;
  1013. }
  1014. $custom_user_information = apply_filters('wpi_user_information', $wpi_settings['user_meta']['custom']);
  1015. $user_information = array_merge($wpi_settings['user_meta']['required'], $custom_user_information);
  1016. // On Adding/Editing Invoice user data exists in ['wpi_invoice']['user_data']
  1017. $data = !empty($_POST['wpi_invoice']['user_data']) ? $_POST['wpi_invoice']['user_data'] : $_POST;
  1018. if (!is_array($data)) {
  1019. return false;
  1020. }
  1021. foreach ($user_information as $field_id => $field_name) {
  1022. if (isset($data[$field_id])) {
  1023. update_user_meta($user_id, $field_id, $data[$field_id]);
  1024. }
  1025. }
  1026. }
  1027. /**
  1028. * Called by profile_update action/hook
  1029. * If user_email changed then it updates user invoices with new user_email
  1030. * @param type $user_id
  1031. * @param type $old_user_data
  1032. * @return boolean
  1033. * @author odokienko@UD
  1034. */
  1035. function protect_user_invoices($user_id, $old_user_data) {
  1036. global $wpdb;
  1037. if (empty($user_id) || $user_id == 0) {
  1038. return false;
  1039. }
  1040. $userdata = get_userdata($user_id);
  1041. if ($userdata->user_email != $old_user_data->user_email){
  1042. $wpdb->query("
  1043. UPDATE {$wpdb->postmeta} postmeta, {$wpdb->posts} posts
  1044. SET postmeta.meta_value = '" . $userdata->user_email . "'
  1045. WHERE posts.ID = postmeta.post_id
  1046. AND postmeta.meta_key = 'user_email'
  1047. AND postmeta.meta_value = '" . $old_user_data->user_email . "'
  1048. AND posts.post_type = 'wpi_object'
  1049. ");
  1050. WPI_Functions::console_log('WPI_Invoice::protect_user_invoices() '.__('user_email changed.', WPI));
  1051. }
  1052. }
  1053. /*
  1054. * Set Custom Screen Options
  1055. */
  1056. function wpi_screen_options() {
  1057. global $current_screen;
  1058. $output = '';
  1059. switch ($current_screen->id) {
  1060. case 'toplevel_page_wpi_main':
  1061. break;
  1062. case 'invoice_page_wpi_page_manage_invoice':
  1063. $output .= '
  1064. <div id="wpi_screen_meta" class="metabox-prefs">
  1065. <label for="wpi_itemized-list-tax">
  1066. <input type="checkbox" ' . (get_user_option('wpi_ui_display_itemized_tax') == 'true' ? 'checked="checked"' : '') . ' value="" id="wpi_itemized-list-tax" name="wpi_ui_display_itemized_tax" class="non-metabox-option">
  1067. Row Tax</label>
  1068. </div>';
  1069. break;
  1070. }
  1071. return $output;
  1072. }
  1073. /**
  1074. * Called by template_redirect to validate whether an invoice should be displayed
  1075. */
  1076. function validate_page_hash($md5_invoice_id) {
  1077. global $wpdb, $wpi_settings, $post, $invoice_id;
  1078. $invoice_id = $wpdb->get_var("SELECT meta_value FROM {$wpdb->postmeta} WHERE meta_key='invoice_id' AND MD5(meta_value) = '{$md5_invoice_id}'");
  1079. if (!$invoice_id) {
  1080. return false;
  1081. }
  1082. if ($wpi_settings['web_invoice_page'] != $post->ID) {
  1083. return false;
  1084. }
  1085. // Verify HTTPS. If its enforced, but not active, we reload page, and do the process again
  1086. //print_r( $_SERVER );
  1087. if (!function_exists('wp_https_redirect')) {
  1088. session_start();
  1089. if (!isset($_SESSION['https'])) {
  1090. if ( $wpi_settings['force_https'] == 'true' && (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on")) {
  1091. $_SESSION['https'] = 1;
  1092. header("Location: https://" . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']);
  1093. @session_destroy();
  1094. exit;
  1095. } else {
  1096. if (session_id() != '')
  1097. @session_destroy();
  1098. }
  1099. }
  1100. //Added to see how the invoice looks once it is created...
  1101. if ($wpi_settings['force_https'] == 'false') {
  1102. if (session_id() != '')
  1103. @session_destroy();
  1104. // Nothing should be done here, this function is simply for validating.
  1105. // If we got this far, means invoice_id and page are validated, and HTTPS is NOT enforced
  1106. return true;
  1107. //print $_SERVER['SERVER_NAME']; print $_SERVER['REQUEST_URI']; die;
  1108. //header("Location: http://" . $_SERVER['SERVER_NAME']'/wp-login.php');
  1109. //header("Location: http://localhost/wordpress/wp-login.php");
  1110. //exit;
  1111. }
  1112. }
  1113. // 5. Validation passed
  1114. return true;
  1115. }
  1116. /**
  1117. Displayed how many days it has been since a certain date.
  1118. */
  1119. function days_since($date1, $return_number = false) {
  1120. if (empty($date1))
  1121. return "";
  1122. if (is_array($date1))
  1123. $date1 = $date1[year] . "-" . $date1[month] . "-" . $date1[day];
  1124. $date2 = date("Y-m-d");
  1125. $date1 = date("Y-m-d", strtotime($date1));
  1126. // determine if future or past
  1127. if (strtotime($date2) < strtotime($date1))
  1128. $future = true;
  1129. $difference = abs(strtotime($date2) - strtotime($date1));
  1130. $days = round(((($difference / 60) / 60) / 24), 0);
  1131. if ($return_number)
  1132. return $days;
  1133. if ($days == 0) {
  1134. return __('Today', WPI);
  1135. } elseif ($days == 1) {
  1136. return($future ? __(" Tomorrow ", WPI) : __(" Yesterday ", WPI));
  1137. } elseif ($days > 1 && $days <= 6) {
  1138. return ($future ? __sprintf(__(" in %s days ", WPI), $days) : " ".$days." ".__("days ago", WPI));
  1139. } elseif ($days > 6) {
  1140. return date(get_option('date_format'), strtotime($date1));
  1141. }
  1142. }
  1143. /**
  1144. * Render money in format.
  1145. *
  1146. * @refactoring korotkov@ud
  1147. * @global array $wpi_settings
  1148. * @param type $number
  1149. * @return type
  1150. */
  1151. function money_format( $number ) {
  1152. global $wpi_settings;
  1153. return number_format( (float)$number, 2, '.', $wpi_settings['thousands_separator_symbol']?$wpi_settings['thousands_separator_symbol']:'' );
  1154. }
  1155. /**
  1156. We use this to merge two arrays.
  1157. Used when loading default billing data, and then being updated by invoice-specific data
  1158. Awesome function from http://us2.php.net/manual/en/function.array-merge-recursive.php
  1159. */
  1160. function &array_merge_recursive_distinct() {
  1161. $aArrays = func_get_args();
  1162. $aMerged = $aArrays[0];
  1163. for ($i = 1; $i < count($aArrays); $i++) {
  1164. if (is_array($aArrays[$i])) {
  1165. foreach ($aArrays[$i] as $key => $val) {
  1166. if (is_array($aArrays[$i][$key])) {
  1167. $aMerged[$key] = (isset($aMerged[$key]) && is_array($aMerged[$key]) ) ? WPI_Functions::array_merge_recursive_distinct($aMerged[$key], $aArrays[$i][$key]) : $aArrays[$i][$key];
  1168. } else {
  1169. $aMerged[$key] = $val;
  1170. }
  1171. }
  1172. }
  1173. }
  1174. return $aMerged;
  1175. }
  1176. /** @TODO: Update it to show Settings page link */
  1177. function set_plugin_page_settings_link($links) {
  1178. /* $settings_link = "<a href='{$core->options['links']['settings_page']}'>Settings</a>";
  1179. array_unshift($links, $settings_link); */
  1180. return $links;
  1181. }
  1182. // Checks whether all plugin tables exist via tables_exist function
  1183. function check_tables() {
  1184. global $wpdb;
  1185. if (!WPI_Functions::tables_exist()) {
  1186. $message = __("The plugin database tables are gone, deactivate and reactivate plugin to re-create them.", WPI);
  1187. }
  1188. WPI_UI::error_message($message);
  1189. }
  1190. function tables_exist() {
  1191. global $wpdb;
  1192. if (!$wpdb->query("SHOW TABLES LIKE '{$wpdb->base_prefix}wpi_object_log';"))
  1193. return false;
  1194. return true;
  1195. }
  1196. // Used for displaying variables in the UI, mostly for debugging
  1197. function qc($what, $force = false) {
  1198. global $wp_invoice_debug;
  1199. if (is_array($what)) {
  1200. $what = WPI_Functions::pretty_print_r($what, false);
  1201. }
  1202. if (is_array($what) || is_string($what)) { // this way we don't try and show classess
  1203. if ($wp_invoice_debug || $force) {
  1204. ?>
  1205. <div class="ui-state-error ui-corner-all" style="padding: 0 .7em;">
  1206. <p><span class="ui-icon ui-icon-alert" style="float: left; margin-right: .3em;"></span>
  1207. <span class="message_content"><?php echo $what; ?></span></p>
  1208. </div>
  1209. <?php
  1210. }
  1211. } else {
  1212. ?>
  1213. <div class="ui-state-error ui-corner-all" style="padding: 0 .7em;">
  1214. <p><span class="ui-icon ui-icon-alert" style="float: left; margin-right: .3em;"></span>
  1215. <span class="message_content"><pre><?php print_r($what); ?></pre></span></p>
  1216. </div>
  1217. <?php
  1218. }
  1219. // Add QC Message to Log
  1220. //WPI_Functions::log($what)
  1221. }
  1222. // Logs events and saved them into WordPress option 'wpi_log'
  1223. // This function is intended to ease troubleshooting later
  1224. function log($what) {
  1225. $wpi_log = get_option('wpi_log');
  1226. // If no session log created yet, create one
  1227. if (!is_array($wpi_log)) {
  1228. $wpi_log = array();
  1229. array_push($wpi_log, array(time(), "Log Started."));
  1230. }
  1231. // Insert event into session
  1232. array_push($wpi_log, array(time(), $what));
  1233. update_option('wpi_log', $wpi_log);
  1234. return true;
  1235. }
  1236. // Alternative to print_r
  1237. function pretty_print_r($data, $echo = false) {
  1238. // Clean $_REQUEST array
  1239. $result = '';
  1240. if ($data == $_REQUEST) {
  1241. foreach ($data as $key => $value) {
  1242. $pattern = "/PHPSESSID|ui-tab/";
  1243. if (preg_match($pattern, $key)) {
  1244. unset($data[$key]);
  1245. }
  1246. }
  1247. }
  1248. if (is_array($data)) { //If the given variable is an array, print using the print_r function.
  1249. $result .= "<pre class='wpi_class_pre'>\n";
  1250. $result .= print_r($data, true);
  1251. $result .= "</pre>";
  1252. } elseif (is_object($data)) {
  1253. $result .= "<pre>\n";
  1254. var_dump($data, true);
  1255. $result .= "</pre>";
  1256. } else {
  1257. $result .= "=========&gt; ";
  1258. $result .= var_dump($data, true);
  1259. $result .= " &lt;=========";
  1260. }
  1261. if ($echo == false)
  1262. return $result;
  1263. $echo;
  1264. }
  1265. function check_settings() {
  1266. global $wpi_settings;
  1267. if ($wpi_settings['web_invoice_page'] == '') {
  1268. $message .= __('Invoice page not selected. ', WPI);
  1269. $message .= __("Visit ", WPI) . "<a href='admin.php?page=wpi_page_settings'>".__('settings page', WPI)."</a>" . __(" to configure.", WPI);
  1270. }
  1271. if (!function_exists('curl_exec'))
  1272. $message .= __("cURL is not turned on on your server, credit card processing will not work. If you have access to your php.ini file, activate <b>extension=php_curl.dll</b>.", WPI);
  1273. WPI_UI::error_message($message);
  1274. }
  1275. function settings_action() {
  1276. if(isset($_REQUEST['wpi_settings']) ) {
  1277. if ($_REQUEST['page'] == 'wpi_page_settings') {
  1278. unset($_REQUEST);
  1279. wp_redirect(admin_url("admin.php?page=wpi_page_settings&message=updated"));
  1280. exit;
  1281. }
  1282. }
  1283. }
  1284. /**
  1285. Handles saving and updating
  1286. Can also handle AJAX save/update function
  1287. */
  1288. function save_invoice($invoice, $args = '') {
  1289. //die( json_encode($invoice) );
  1290. /* Set function additional params */
  1291. $defaults = array(
  1292. 'type' => 'default'
  1293. );
  1294. extract(wp_parse_args($args, $defaults), EXTR_SKIP);
  1295. if ($type != 'import') {
  1296. if (!wp_verify_nonce($_REQUEST['nonce'], 'wpi-update-invoice')) {
  1297. die('Security check');
  1298. }
  1299. }
  1300. /* Init New Invoice object from passed variables */
  1301. $ni = new WPI_Invoice();
  1302. $ni->set("ID={$invoice['ID']}");
  1303. $ni->set("invoice_id={$invoice['invoice_id']}");
  1304. //$ni->set("terms_acceptance_required={$invoice['terms_acceptance_required']}");
  1305. $ni->set("subject={$invoice['subject']}");
  1306. $ni->set("description={$invoice['description']}");
  1307. //$ni->set("watermark={$invoice['meta']['watermark']}");
  1308. if ($invoice['deposit'] == 'on' || $invoice['deposit'] == 'true') {
  1309. $ni->set("deposit_amount={$invoice['deposit_amount']}");
  1310. } else {
  1311. $ni->set("deposit_amount=0");
  1312. }
  1313. $ni->set("due_date_year={$invoice['due_date_year']}");
  1314. $ni->set("due_date_month={$invoice['due_date_month']}");
  1315. $ni->set("due_date_day={$invoice['due_date_day']}");
  1316. $ni->set("default_currency_code={$invoice['default_currency_code']}");
  1317. if (!empty($invoice['meta']['terms'])) {
  1318. $ni->set("terms={$invoice['meta']['terms']}");
  1319. }
  1320. $ni->set("tax={$invoice['meta']['tax']}");
  1321. $ni->set("custom_id={$invoice['meta']['custom_id']}");
  1322. /**
  1323. * DETECTING INVOICE TYPE
  1324. * (Changes for ability to use premium feature Quotes)
  1325. *
  1326. * @author Anton Korotkov
  1327. *
  1328. * There are three available types by default:
  1329. * - invoice
  1330. * - recurring
  1331. */
  1332. // 'invoice' is by default
  1333. $invoice_type = 'invoice';
  1334. // If $invoice object has type definition then use it
  1335. if ( !empty( $invoice['type'] ) ) {
  1336. $invoice_type = $invoice['type'];
  1337. }
  1338. // Save status of …

Large files files are truncated, but you can click here to view the full file