Calculations.php 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. <?php
  2. final class NF_Conversion_Calculations implements NF_Conversion
  3. {
  4. private $operations = array(
  5. 'add' => '+',
  6. 'subtract' => '-',
  7. 'multiply' => '*',
  8. 'divide' => '/'
  9. );
  10. private $form = array();
  11. private $tax_rate;
  12. public function __construct( $form_data )
  13. {
  14. $this->form = $form_data;
  15. }
  16. public function run()
  17. {
  18. // Extract Calculations from Fields
  19. foreach( $this->form[ 'fields' ] as $key => $field ){
  20. if( 'tax' == $field[ 'type' ] ){
  21. $this->set_tax( $field[ 'default_value' ] );
  22. continue;
  23. }
  24. if( 'calc' != $field[ 'type' ] ) continue;
  25. $calculation = array(
  26. 'order' => $key,
  27. 'name' => $field[ 'key' ],
  28. 'eq' => '',
  29. 'dec' => $field[ 'calc_places' ]
  30. );
  31. switch( $field[ 'calc_method' ] ){
  32. case 'eq':
  33. $calculation[ 'eq' ] = $field[ 'calc_eq' ];
  34. break;
  35. case 'fields':
  36. $calculation[ 'eq' ] = trim( array_reduce( $field[ 'calc' ], array( $this, 'reduce_operations' ), '' ) );
  37. break;
  38. case 'auto':
  39. $calculation[ 'eq' ] = trim( array_reduce( $this->form[ 'fields' ], array( $this, 'reduce_auto_total' ), '' ) );
  40. break;
  41. }
  42. // Remove any leading `+`.
  43. $calculation[ 'eq' ] = ltrim( $calculation[ 'eq' ], '+' );
  44. // Handle opinionated "Total" calc and tax field.
  45. if( 'total' == $field[ 'calc_name' ] && isset( $this->tax_rate ) ){
  46. $calculation[ 'eq' ] = "( {$calculation[ 'eq' ]} ) * {$this->tax_rate}";
  47. }
  48. $this->form[ 'settings' ][ 'calculations' ][] = $calculation;
  49. }
  50. // Replace Field IDs with Merge Tags
  51. if( isset( $this->form[ 'settings' ][ 'calculations' ] ) ) {
  52. foreach ($this->form['fields'] as $field) {
  53. if( ! isset( $field[ 'id' ] ) ) continue;
  54. $search = 'field_' . $field['id'];
  55. $replace = $this->merge_tag( $field );
  56. foreach ($this->form['settings']['calculations'] as $key => $calculation) {
  57. $this->form['settings']['calculations'][ $key ]['eq'] = str_replace($search, $replace, $calculation['eq']);
  58. }
  59. }
  60. }
  61. // Convert Calc Fields to HTML Fields for displaying Calculations
  62. foreach( $this->form[ 'fields' ] as $key => $field ){
  63. if( 'tax' == $field[ 'type' ] ){
  64. $this->form[ 'fields' ][ $key ][ 'type' ] = 'html';
  65. $this->form[ 'fields' ][ $key ][ 'default' ] = "<strong>{$field[ 'label' ]}</strong><br /> {$field[ 'default_value' ]}";
  66. continue;
  67. }
  68. if( 'calc' != $field[ 'type' ] ) continue;
  69. $this->form[ 'fields' ][ $key ][ 'type' ] = 'html';
  70. if( 'html' == $field[ 'calc_display_type' ] ){
  71. // TODO: HTML Output fields seem to loose the label.
  72. $search = '[ninja_forms_calc]';
  73. $replace = $this->merge_tag( $field );
  74. $subject = $field[ 'calc_display_html' ];
  75. $this->form[ 'fields' ][ $key ][ 'default' ] = str_replace( $search, $replace, $subject );
  76. } else {
  77. $this->form[ 'fields' ][ $key ][ 'default' ] = '<strong>' . $field[ 'label' ] . '</strong><br />' . $this->merge_tag( $field );
  78. }
  79. }
  80. return $this->form;
  81. }
  82. private function reduce_operations( $eq, $calc )
  83. {
  84. $operation = $calc[ 'op' ];
  85. return ' ' . $eq . $this->operations[ $operation ] . ' field_' . $calc[ 'field' ] . ' ';
  86. }
  87. private function reduce_auto_total( $eq, $field )
  88. {
  89. if( ! isset( $field[ 'calc_auto_include' ] ) || 1 != $field[ 'calc_auto_include' ] ) return $eq;
  90. return $eq . '+ {field:' . $field[ 'key' ] . ':calc} ';
  91. }
  92. private function merge_tag( $field )
  93. {
  94. $tag = $field[ 'key' ];
  95. if( 'calc' == $field[ 'type' ] ){
  96. return '{calc:' . $tag . '}';
  97. } else {
  98. return '{field:' . $tag . ':calc}';
  99. }
  100. }
  101. /**
  102. * Sets a float formatted tax rate.
  103. * @param string|int|float $tax
  104. *
  105. * @return float|int
  106. */
  107. private function set_tax( $tax )
  108. {
  109. // ex 15% -> 1.15
  110. return $this->tax_rate = ( floatval( $tax ) + 100 ) / 100;
  111. }
  112. }
  113. add_filter( 'ninja_forms_after_upgrade_settings', 'ninja_forms_conversion_calculations' );
  114. function ninja_forms_conversion_calculations( $form_data ){
  115. $conversion = new NF_Conversion_Calculations( $form_data );
  116. return $conversion->run();
  117. }