Hello.
How can we calculate the price for product in btc to show via shortcode anywhere ?
]]>My functions stopped evaluating after switching to PHP8, throwing:
PHP Fatal error: Uncaught TypeError: Cannot access offset of type string on string in?/wp-content/plugins/calculate-values-with-shortcodes/calculate-values-shortcodes.php:26
Here’s the fix. Go to Plugins -> Plugin File Editor -> Select Calculate Values in the drop down.
Edit line 26 to read:
if (is_array($atts) && $atts["style"] == 'usd'){
Edit line 31 to read:
else if (is_array($atts) && $atts["style"] == 'percent'){
]]>
Been using this plugin for a few years now and find it quite handy for some situations. Somewhere along the line it started dropping the last decimal on me when it ends in zero regardless of what you set the dec= attribute to.
Thinking it may of been around the time I upgraded to php8.
My hack of a fix, not sure if it is the best way or how you should properly do it but it works for me if anyone else uses this and starts noticing the same issue.
I tweaked the output of the last elseif for when no int is set. Also be sure to remove any int settings from your shortcodes.
The 4th last line in calculate-values-shortcodes.php:
Originally:
return $result;
Change to:
return number_format($result,2,'.',',');
Now it forces the second decimal place, yay! Change your decimal and comma settings to your liking but the above is for 0,000.00 format.
Duct tape kind of fix.
Cheers,
Ryan
Bhagwad,
Thanks for this plugin. It’s quite useful. However i noticed it doesn’t support the mod function, while the EvalMath library already supports mod since 2016. You can see the documentation on this git page.
It’ll be great if you can update your plugin to have mod supported.
]]>Hello how ‘re you? The plugin is very useful (One of my best!), but I’m receiving a PHP error in pages that have it. I leave you a screen: https://prnt.sc/spboyg so you can check the messages from Query Monitor plugin & developer console.
Is a pricing page with only 5 tables, and between [calculate][/calculate] are prices shortcodes and discount shortcodes… Easy multiplications.
Also, It slows down the load time(No other shortcodes are working in the same pages, only #calculate).
Any ideas?
Thanks a lot!
Just installed it today and was getting an error outputted to the page when using the shortcode. The fix is here: https://www.ads-software.com/support/topic/not-working-2859/#post-11666875 . Just posting it here for quick reference for anyone else who stumbles upon it.
Would be great if plugin author could update it. Thanks for the plugin.
]]>Hi Bhagwad,
Thanks for this very useful plugin btw.
Hoping you can help look into 2 errors I am seeing that is filling up the php error log and causes the WP editor to crash, please se below;
Notice: Undefined offset: -1 in /home/evomone1/public_html/moneyactive.com.au/wp-content/plugins/calculate-values-with-shortcodes/evalmath.class.php on line 385
Warning: unexpected operator ‘*’ in /home/evomone1/public_html/moneyactive.com.au/wp-content/plugins/calculate-values-with-shortcodes/evalmath.class.php on line 360
Im calculating using field values from Formidable forms, everything works great, except for this issue.
Thanks,
Terry
Hi,
I did a formula with different personal shortcodes and it seems to be working fine… when I’m not connected as admin.
When I visit the page as admin, I get this error:
Warning: unexpected operator ‘+’ in /wp-content/plugins/calculate-values-with-shortcodes/evalmath.class.php on line 360
Thanks for your help
Best regards
Hey everyone! For some reason, I’m not getting notifications of support requests for this plugin.
So if you’re running into something, visit my page and send me a message in ADDITION to creating a support thread here.
Here’s the page to notify me: https://www.wp-tweaks.com/contact/
You can also leave a comment on the plugin page itself: https://www.wp-tweaks.com/how-to-calculate-values-in-wordpress-posts-and-pages/
]]>I am using the plugin “Favorites for WordPress” from https://favoriteposts.com/. I need to add a number to their Favorite Count which is a Real Integer / non-decimal value.
The value returned by your plugin is always “0”. This is the formula I am using:
[calculate] 5 + [favorite_count] [/calculate]
When I display [favorite_count] outside of the [calculate] shortcode it returns “1”. When I add 5+5 within the [calculate] shortcode it returns “10”. I have also tried other integer generating shortcodes and they do not work either – they always return a value of “0” when I try to perform an operation on them within the Calculate plugin.
Is there something I am missing? I am using version 2.1.1 of the plugin and WP 5.2.
Any support is appreciated.
Thanks
A
Hello,
I am trying to calculate field values from gravity form.
But I get a 0 value.
Total cost :?[calculate]{Price:84}+{Taxes:87}[/calculate]
If I type values, it works.
Thanks
]]>Hi,
My Shortcode has a comma in the number which breaks the calculation I’m trying to make.
Eg 1900/100*10 works but 1,900/100*10 doesnt.
I cant change the shortcode value – is there anything that you can suggest?
Great plugin!
Rick
]]>Hi there, I stumbled upon this plugin and it definitely looks a must-have for my website! I tried doing simple tests I can’t get it to work. It keeps throwing the same error I’m attaching below.
I’ve tried on both PHP 5.6 and 7.1 to no avail. Any clue on how to resolve the issue?
================================================================================ NAME EvalMath - safely evaluate math expressions SYNOPSIS evaluate('2+2'); // supports: order of operation; parentheses; negation; built-in functions $result = $m->evaluate('-8(5/2)^2*(1-sqrt(4))-8'); // create your own variables $m->evaluate('a = e^(ln(pi))'); // or functions $m->evaluate('f(x,y) = x^2 + y^2 - 2x*y + 1'); // and then use them $result = $m->evaluate('3*f(42,a)'); ?> DESCRIPTION Use the EvalMath class when you want to evaluate mathematical expressions from untrusted sources. You can define your own variables and functions, which are stored in the object. Try it, it's fun! METHODS $m->evalute($expr) Evaluates the expression and returns the result. If an error occurs, prints a warning and returns false. If $expr is a function assignment, returns true on success. $m->e($expr) A synonym for $m->evaluate(). $m->vars() Returns an associative array of all user-defined variables and values. $m->funcs() Returns an array of all user-defined functions. PARAMETERS $m->suppress_errors Set to true to turn off warnings when evaluating expressions $m->last_error If the last evaluation failed, contains a string describing the error. (Useful when suppress_errors is on). AUTHOR INFORMATION Copyright 2005, Miles Kaufmann. LICENSE Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1 Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR
AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ class EvalMath { var $suppress_errors = false; var $last_error = null; var $v = array('e'=>2.71,'pi'=>3.14); // variables (and constants) var $f = array(); // user-defined functions var $vb = array('e', 'pi'); // constants var $fb = array( // built-in functions 'sin','sinh','arcsin','asin','arcsinh','asinh', 'cos','cosh','arccos','acos','arccosh','acosh', 'tan','tanh','arctan','atan','arctanh','atanh', 'sqrt','abs','ln','log'); public function __construct() { // make the variables a little more accurate $this->v['pi'] = pi(); $this->v['e'] = exp(1); } function e($expr) { return $this->evaluate($expr); } function evaluate($expr) { $this->last_error = null; $expr = trim($expr); if (substr($expr, -1, 1) == ';') $expr = substr($expr, 0, strlen($expr)-1); // strip semicolons at the end //=============== // is it a variable assignment? if (preg_match('/^\s*([a-z]\w*)\s*=\s*(.+)$/', $expr, $matches)) { if (in_array($matches[1], $this->vb)) { // make sure we're not assigning to a constant return $this->trigger("cannot assign to constant '$matches[1]'"); } if (($tmp = $this->pfx($this->nfx($matches[2]))) === false) return false; // get the result and make sure it's good $this->v[$matches[1]] = $tmp; // if so, stick it in the variable array return $this->v[$matches[1]]; // and return the resulting value //=============== // is it a function assignment? } elseif (preg_match('/^\s*([a-z]\w*)\s*\(\s*([a-z]\w*(?:\s*,\s*[a-z]\w*)*)\s*\)\s*=\s*(.+)$/', $expr, $matches)) { $fnn = $matches[1]; // get the function name if (in_array($matches[1], $this->fb)) { // make sure it isn't built in return $this->trigger("cannot redefine built-in function '$matches[1]()'"); } $args = explode(",", preg_replace("/\s+/", "", $matches[2])); // get the arguments if (($stack = $this->nfx($matches[3])) === false) return false; // see if it can be converted to postfix for ($i = 0; $iv)) { $stack[$i] = $this->v[$token]; } else { return $this->trigger("undefined variable '$token' in function definition"); } } } $this->f[$fnn] = array('args'=>$args, 'func'=>$stack); return true; //=============== } else { return $this->pfx($this->nfx($expr)); // straight up evaluation, woo } } function vars() { $output = $this->v; unset($output['pi']); unset($output['e']); return $output; } function funcs() { $output = array(); foreach ($this->f as $fnn=>$dat) $output[] = $fnn . '(' . implode(',', $dat['args']) . ')'; return $output; } //===================== HERE BE INTERNAL METHODS ====================\\ // Convert infix to postfix notation function nfx($expr) { $index = 0; $stack = new EvalMathStack; $output = array(); // postfix form of expression, to be passed to pfx() $expr = trim(strtolower($expr)); $ops = array('+', '-', '*', '/', '^', '_'); $ops_r = array('+'=>0,'-'=>0,'*'=>0,'/'=>0,'^'=>1); // right-associative operator? $ops_p = array('+'=>0,'-'=>0,'*'=>1,'/'=>1,'_'=>1,'^'=>2); // operator precedence $expecting_op = false; // we use this in syntax-checking the expression // and determining when a - is a negation if (preg_match("/[^\w\s+*^\/()\.,-]/", $expr, $matches)) { // make sure the characters are all good return $this->trigger("illegal character '{$matches[0]}'"); } while(1) { // 1 Infinite Loop ;) $op = substr($expr, $index, 1); // get the first character at the current index // find out if we're currently at the beginning of a number/variable/function/parenthesis/operand $ex = preg_match('/^([a-z]\w*\(?|\d+(?:\.\d*)?|\.\d+|\()/', substr($expr, $index), $match); //=============== if ($op == '-' and !$expecting_op) { // is it a negation instead of a minus? $stack->push('_'); // put a negation on the stack $index++; } elseif ($op == '_') { // we have to explicitly deny this, because it's legal on the stack return $this->trigger("illegal character '_'"); // but not in the input expression //=============== } elseif ((in_array($op, $ops) or $ex) and $expecting_op) { // are we putting an operator on the stack? if ($ex) { // are we expecting an operator but have a number/variable/function/opening parethesis? $op = '*'; $index--; // it's an implicit multiplication } // heart of the algorithm: while($stack->count > 0 and ($o2 = $stack->last()) and in_array($o2, $ops) and ($ops_r[$op] ? $ops_p[$op] < $ops_p[$o2] : $ops_p[$op] <= $ops_p[$o2])) { $output[] = $stack->pop(); // pop stuff off the stack into the output } // many thanks: https://en.wikipedia.org/wiki/Reverse_Polish_notation#The_algorithm_in_detail $stack->push($op); // finally put OUR operator onto the stack $index++; $expecting_op = false; //=============== } elseif ($op == ')' and $expecting_op) { // ready to close a parenthesis? while (($o2 = $stack->pop()) != '(') { // pop off the stack back to the last ( if (is_null($o2)) return $this->trigger("unexpected ')'"); else $output[] = $o2; } if (preg_match("/^([a-z]\w*)\($/", $stack->last(2), $matches)) { // did we just close a function? $fnn = $matches[1]; // get the function name $arg_count = $stack->pop(); // see how many arguments there were (cleverly stored on the stack, thank you) $output[] = $stack->pop(); // pop the function and push onto the output if (in_array($fnn, $this->fb)) { // check the argument count if($arg_count > 1) return $this->trigger("too many arguments ($arg_count given, 1 expected)"); } elseif (array_key_exists($fnn, $this->f)) { if ($arg_count != count($this->f[$fnn]['args'])) return $this->trigger("wrong number of arguments ($arg_count given, " . count($this->f[$fnn]['args']) . " expected)"); } else { // did we somehow push a non-function on the stack? this should never happen return $this->trigger("internal error"); } } $index++; //=============== } elseif ($op == ',' and $expecting_op) { // did we just finish a function argument? while (($o2 = $stack->pop()) != '(') { if (is_null($o2)) return $this->trigger("unexpected ','"); // oops, never had a ( else $output[] = $o2; // pop the argument expression stuff and push onto the output } // make sure there was a function if (!preg_match("/^([a-z]\w*)\($/", $stack->last(2), $matches)) return $this->trigger("unexpected ','"); $stack->push($stack->pop()+1); // increment the argument count $stack->push('('); // put the ( back on, we'll need to pop back to it again $index++; $expecting_op = false; //=============== } elseif ($op == '(' and !$expecting_op) { $stack->push('('); // that was easy $index++; $allow_neg = true; //=============== } elseif ($ex and !$expecting_op) { // do we now have a function/variable/number? $expecting_op = true; $val = $match[1]; if (preg_match("/^([a-z]\w*)\($/", $val, $matches)) { // may be func, or variable w/ implicit multiplication against parentheses... if (in_array($matches[1], $this->fb) or array_key_exists($matches[1], $this->f)) { // it's a func $stack->push($val); $stack->push(1); $stack->push('('); $expecting_op = false; } else { // it's a var w/ implicit multiplication $val = $matches[1]; $output[] = $val; } } else { // it's a plain old var or num $output[] = $val; } $index += strlen($val); //=============== } elseif ($op == ')') { // miscellaneous error checking return $this->trigger("unexpected ')'"); } elseif (in_array($op, $ops) and !$expecting_op) { return $this->trigger("unexpected operator '$op'"); } else { // I don't even want to know what you did to get here return $this->trigger("an unexpected error occured"); } if ($index == strlen($expr)) { if (in_array($op, $ops)) { // did we end with an operator? bad. return $this->trigger("operator '$op' lacks operand"); } else { break; } } while (substr($expr, $index, 1) == ' ') { // step the index past whitespace (pretty much turns whitespace $index++; // into implicit multiplication if no operator is there) } } while (!is_null($op = $stack->pop())) { // pop everything off the stack and push onto output if ($op == '(') return $this->trigger("expecting ')'"); // if there are (s on the stack, ()s were unbalanced $output[] = $op; } return $output; } // evaluate postfix notation function pfx($tokens, $vars = array()) { if ($tokens == false) return false; $stack = new EvalMathStack; foreach ($tokens as $token) { // nice and easy // if the token is a binary operator, pop two values off the stack, do the operation, and push the result back on if (in_array($token, array('+', '-', '*', '/', '^'))) { if (is_null($op2 = $stack->pop())) return $this->trigger("internal error"); if (is_null($op1 = $stack->pop())) return $this->trigger("internal error"); switch ($token) { case '+': $stack->push($op1+$op2); break; case '-': $stack->push($op1-$op2); break; case '*': $stack->push($op1*$op2); break; case '/': if ($op2 == 0) return $this->trigger("division by zero"); $stack->push($op1/$op2); break; case '^': $stack->push(pow($op1, $op2)); break; } // if the token is a unary operator, pop one value off the stack, do the operation, and push it back on } elseif ($token == "_") { $stack->push(-1*$stack->pop()); // if the token is a function, pop arguments off the stack, hand them to the function, and push the result back on } elseif (preg_match("/^([a-z]\w*)\($/", $token, $matches)) { // it's a function! $fnn = $matches[1]; if (in_array($fnn, $this->fb)) { // built-in function: if (is_null($op1 = $stack->pop())) return $this->trigger("internal error"); $fnn = preg_replace("/^arc/", "a", $fnn); // for the 'arc' trig synonyms if ($fnn == 'ln') $fnn = 'log'; eval('$stack->push(' . $fnn . '($op1));'); // perfectly safe eval() } elseif (array_key_exists($fnn, $this->f)) { // user function // get args $args = array(); for ($i = count($this->f[$fnn]['args'])-1; $i >= 0; $i--) { if (is_null($args[$this->f[$fnn]['args'][$i]] = $stack->pop())) return $this->trigger("internal error"); } $stack->push($this->pfx($this->f[$fnn]['func'], $args)); // yay... recursion!!!! } // if the token is a number or variable, push it on the stack } else { if (is_numeric($token)) { $stack->push($token); } elseif (array_key_exists($token, $this->v)) { $stack->push($this->v[$token]); } elseif (array_key_exists($token, $vars)) { $stack->push($vars[$token]); } else { return $this->trigger("undefined variable '$token'"); } } } // when we're out of tokens, the stack should have a single element, the final result if ($stack->count != 1) return $this->trigger("internal error"); return $stack->pop(); } // trigger an error, but nicely, if need be function trigger($msg) { $this->last_error = $msg; if (!$this->suppress_errors) trigger_error($msg, E_USER_WARNING); return false; } } // for internal use class EvalMathStack { var $stack = array(); var $count = 0; function push($val) { $this->stack[$this->count] = $val; $this->count++; } function pop() { if ($this->count > 0) { $this->count--; return $this->stack[$this->count]; } return null; } function last($n=1) { return $this->stack[$this->count-$n]; } }
Great little plugin! It provides perfect currency format even within Toolset Type Views.
But, as per customer demand, I must not show decimals in a Model home pricing.
I tried:
[calculate int=”en_CA” dec=”0″]]350000.01[/calculate] results in : 350,000.00
[calculate int=”fr_CA” dec=”1″]350000.019[/calculate] results in : 350 000,00
[calculate int=”fr_CA” dec=’3′]0+350000.019[/calculate] results in : 350 000,02
The int attribute overrides the dec attribute. I cannot use it to comply with the customer request… ??
How about a third attribute forceDecimal= to override the override?
Thanks for reading this.
RB
]]>Hi there,
This plugin would help my project a lot! Unfortunately it doesn’t work on my website.
When I add a formula – a simple one without shortcodes – it won’t let me see the page anymore…
Do you have a solution/ a list of problems with answers?
Best regards,
Jochem
Can this plugin work with a point system like mycred
]]>I love the concept. I have mycred plugin installed and am wondering if it is possible to do calculations with balances produced by mycred shortcodes. For example [mycred_my_balance] shows the user’s point balance for a specific point type. If there are many point types, is it possible to do calculations – I tried and it shows zero, not sure why
]]>Hi, thanks for the plugin.
I have a website about bus routes.
I have been able to generate an excel table with the bus steps for each location.
For example
BUS 12
bus-stop1: 12:50 am
bus-stop2: 12:55 am
bus-stop3: 13.00 pm
etc
However, I would like to know if with this plugin I could show the arrival time instead of the schedules, that is to say something like this
BUS 12
bus-stop1: arrival in 10 minutes
bus-stop2: arrival in 15 minutes
bus-stop3: arrival in 20 minutes
Thanks for the help.
]]>