This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "FusionForge".
The branch, master has been updated
via f355a23d0234af6cc54655f4ed5b82babc668701 (commit)
from 76285e70a9d6b6b1a77641523ac882f9a011c182 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
https://scm.fusionforge.org/anonscm/gitweb/?p=fusionforge/fusionforge.git;a=commitdiff;h=f355a23d0234af6cc54655f4ed5b82babc668701
commit f355a23d0234af6cc54655f4ed5b82babc668701
Author: Stéphane-Eymeric Bredthauer <[email protected]>
Date: Sun Mar 5 22:58:59 2017 +0100
Tracker: formula improvement
diff --git a/src/common/tracker/ArtifactExpression.class.php
b/src/common/tracker/ArtifactExpression.class.php
new file mode 100644
index 0000000..6f7d811
--- /dev/null
+++ b/src/common/tracker/ArtifactExpression.class.php
@@ -0,0 +1,117 @@
+<?php
+/**
+ * Artifact Expression
+*
+* Copyright 2017 Stéphane-Eymeric Bredthauer - TrivialDev
+* http://fusionforge.org/
+*
+* This file is part of FusionForge. FusionForge is free software;
+* you can redistribute it and/or modify it under the terms of the
+* GNU General Public License as published by the Free Software
+* Foundation; either version 2 of the Licence, or (at your option)
+* any later version.
+*
+* FusionForge is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with FusionForge; if not, write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+require_once $gfcommon.'include/FFError.class.php';
+require_once $gfwww.'include/expression.php';
+
+class ArtifactExpression extends FFError {
+
+ private $expression;
+ private $arithmeticOperators = array (
+
array('=','Assignment','a = b'),
+
array('+','Addition','a + b'),
+
array('-','Subtraction','a - b'),
+
array('-','Unary minus','-a'),
+
array('*','Multiplication','a * b'),
+
array('/','Division','a / b'),
+
array('%','Modulo (integer remainder)','a % b'),
+
array('^','Power','a ^ b')
+ );
+ private $comparisonOperators = array (
+
array('==','Equal to','a == b'),
+
array('!=','Not equal to','a != b'),
+
array('>','Greater than','a > b'),
+
array('<','Less than','a < b'),
+
array('>=','Greater than or equal to','a >= b'),
+
array('<=','Less than or equal to','a <= b'),
+
array('=~','Regex match','a =~ regex')
+ );
+ private $logicalOperators = array(
+
array('!','Logical negation (NOT)','!a'),
+
array('&&','Logical AND','a && b'),
+
array('||','Logical OR','a || b')
+ );
+
+ private $otherOperators = array(
+
array('?:','Conditional operator','a ? b : c')
+ );
+
+ private $functionsDescription = array();
+
+ public function __construct()
+ {
+ $this->functionsDescription = array('in_array'=>_('Test if a
value is in an (json) array'));
+
+ $this->expression = new Expression;
+ $this->expression->suppress_errors = true;
+ $this->expression->fb = array();
+ $this->expression->functions ['in_array'] = 'expr_in_array';
+ }
+
+ public function evaluate($expression) {
+ $return = null;
+ $this->clearError();
+ $lines = preg_split('/;\s*\R/',$expression);
+ foreach ($lines as $line) {
+ $line = preg_replace('/\R|\s/',' ', $line);
+ if (!preg_match('/^\s*#.*/',$line)) {
+ $return = $this->expression->evaluate($line);
+ if ($this->expression->last_error) {
+
$this->setError($this->expression->last_error);
+ }
+ }
+ }
+ return $return;
+ }
+
+ public function getVariables() {
+ return $this->expression->vars();
+ }
+
+ public function getFunctions () {
+ $builtInFunctions = $this->expression->fb;
+ $customFunctions = array_keys($this->expression->functions);
+ return array_merge($builtInFunctions, $customFunctions);
+ }
+
+ public function getUserDefineFunctions () {
+ return array_keys($this->expression->f);
+ }
+
+ public function getOperators() {
+ return array(
+ array(_('Arithmetic
operators'), $this->arithmeticOperators),
+ array(_('Comparison
operators'), $this->comparisonOperators),
+ array(_('Logical operators'),
$this->logicalOperators),
+ array(_('Other operators'),
$this->otherOperators)
+ );
+ }
+
+ public function getFunctionDescription($function) {
+ return $this->functionsDescription[$function];
+ }
+}
+function expr_in_array($value, $jsonArray) {
+ $array = json_decode($jsonArray, true);
+ return in_array($value, $array);
+}
\ No newline at end of file
diff --git a/src/common/tracker/actions/admin-updates.php
b/src/common/tracker/actions/admin-updates.php
index e94fc21..8859b4d 100644
--- a/src/common/tracker/actions/admin-updates.php
+++ b/src/common/tracker/actions/admin-updates.php
@@ -287,6 +287,58 @@ if (getStringFromRequest('add_extrafield')) {
}
//
+// Update formula for an extra field
+//
+} elseif (getStringFromRequest('update_box_formula')) {
+ $id = getStringFromRequest('id');
+ $formula = getStringFromRequest('formula');
+
+ $ac = new ArtifactExtraField($ath, $id);
+ if (!$ac || !is_object($ac)) {
+ $error_msg .= _('Unable to create ArtifactExtraField Object');
+ } elseif ($ac->isError()) {
+ $error_msg .= $ac->getErrorMessage();
+ } else {
+ if (!$ac->setFormula($formula)){
+ $error_msg .= _('Update field formula failed')._(':
').$ac->getErrorMessage();
+ $ac->clearError();
+ } else {
+ $feedback .= _('Field formula updated');
+ $next = 'update_box';
+ }
+ }
+
+//
+// Update formula for an extra field element
+//
+} elseif (getStringFromRequest('update_opt_formula')) {
+ $boxid = getStringFromRequest('boxid');
+ $is_default = getStringFromRequest('is_default', false);
+ $formula = getStringFromRequest('formula', '');
+ $ac = new ArtifactExtraField($ath,$boxid);
+ if (!$ac || !is_object($ac)) {
+ $error_msg .= _('Unable to create ArtifactExtraField Object');
+ } elseif ($ac->isError()) {
+ $error_msg .= $ac->getErrorMessage();
+ } else {
+ $id = getStringFromRequest('id');
+ $ao = new ArtifactExtraFieldElement($ac,$id);
+ if (!$ao || !is_object($ao)) {
+ $error_msg .= _('Unable to create
ArtifactExtraFieldElement Object');
+ } elseif ($ao->isError()) {
+ $error_msg .= $ao->getErrorMessage();
+ } else {
+ if (!$ao->setFormula($formula)){
+ $error_msg .= _('Update field formula
failed')._(': ').$ao->getErrorMessage();
+ $ao->clearError();
+ } else {
+ $feedback .= _('Field element formula updated');
+ $next = 'update_opt';
+ }
+ }
+ }
+
+//
// Update an Element
//
} elseif (getStringFromRequest('update_opt')) {
diff --git a/src/common/tracker/actions/ajax.php
b/src/common/tracker/actions/ajax.php
index db4b48b..38c8952 100644
--- a/src/common/tracker/actions/ajax.php
+++ b/src/common/tracker/actions/ajax.php
@@ -22,7 +22,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-require_once $gfwww.'include/expression.php';
+require_once $gfcommon.'tracker/ArtifactExpression.class.php';
global $group;
global $atid;
@@ -70,27 +70,37 @@ function get_formulas_results($group, $atid,
$extra_fields=array()){
exit();
}
- $expr = new Expression();
- $expr->suppress_errors = true;
+ $expr = new ArtifactExpression();
// Variable assignment
$extraFields = $at->getExtraFields();
foreach ($extraFields as $extraField) {
if (isset($extra_fields[$extraField['extra_field_id']])) {
$varAss = false;
- if
($extraField['field_type']==ARTIFACT_EXTRAFIELDTYPE_INTEGER) {
+ $type = $extraField['field_type'];
+ if ($type==ARTIFACT_EXTRAFIELDTYPE_INTEGER) {
$varAss =
$extraField['alias'].'='.$extra_fields[$extraField['extra_field_id']];
- } elseif
($extraField['field_type']==ARTIFACT_EXTRAFIELDTYPE_TEXT) {
- $varAss =
$extraField['alias'].'="'.$extra_fields[$extraField['extra_field_id']].'"';
- } elseif
($extraField['field_type']==ARTIFACT_EXTRAFIELDTYPE_SELECT) {
+ } elseif ($type==ARTIFACT_EXTRAFIELDTYPE_TEXT ||
+ $type==ARTIFACT_EXTRAFIELDTYPE_TEXTAREA
||
+
$type==ARTIFACT_EXTRAFIELDTYPE_RELATION) {
+ $varAss =
$extraField['alias'].'="'.addslashes($extra_fields[$extraField['extra_field_id']]).'"';
+ } elseif (in_array($type,
unserialize(ARTIFACT_EXTRAFIELDTYPEGROUP_SINGLECHOICE))) {
$ef = new ArtifactExtraField($at,
$extraField['extra_field_id']);
$efe = new
ArtifactExtraFieldElement($ef,$extra_fields[$extraField['extra_field_id']] );
- $varAss =
$extraField['alias'].'="'.$efe->getName().'"';
+ $varAss =
$extraField['alias'].'="'.addslashes($efe->getName()).'"';
+ } elseif (in_array($type,
unserialize(ARTIFACT_EXTRAFIELDTYPEGROUP_MULTICHOICE))) {
+ $var = array();
+ $ef = new ArtifactExtraField($at,
$extraField['extra_field_id']);
+ foreach
($extra_fields[$extraField['extra_field_id']] as $element_id) {
+ $efe = new
ArtifactExtraFieldElement($ef,$element_id);
+ $var[]= $efe->getName();
+ }
+ $varAss = $extraField['alias'].'=\''.
json_encode($var).'\'';
}
if ($varAss) {
$expr->evaluate($varAss);
- if ($expr->last_error) {
- $ret['message'] = $expr->last_error;
+ if ($expr->isError()) {
+ $ret['message'] =
$expr->getErrorMessage()._(':').' '.$varAss;
return json_encode($ret);
exit();
}
@@ -117,12 +127,12 @@ function get_formulas_results($group, $atid,
$extra_fields=array()){
if (in_array($extraField['field_type'],
unserialize(ARTIFACT_EXTRAFIELDTYPEGROUP_VALUE))) {
if (!empty($formula)) {
$value = $expr->evaluate($formula);
- if ($expr->last_error) {
- $ret['message'] =
$expr->last_error;
+ if ($expr->isError()) {
+ $ret['message'] =
$expr->getErrorMessage();
return json_encode($ret);
exit();
}
- $result [] = array(
'id'=>$extraField['extra_field_id'], 'value'=>$value,
'error'=>$expr->last_error );
+ $result [] = array(
'id'=>$extraField['extra_field_id'], 'value'=>$value,
'error'=>($expr->isError()?$expr->getErrorMessage():null));
}
} elseif (in_array($extraField['field_type'],
unserialize(ARTIFACT_EXTRAFIELDTYPEGROUP_CHOICE))) {
if (is_array($formula)) {
@@ -130,8 +140,8 @@ function get_formulas_results($group, $atid,
$extra_fields=array()){
$valueArr = array();
foreach ($formulas as $key=>$formula) {
$value =
$expr->evaluate($formula);
- if ($expr->last_error) {
- $ret['message'] =
$expr->last_error;
+ if ($expr->isError()) {
+ $ret['message'] =
$expr->getErrorMessage();
return
json_encode($ret);
exit();
}
@@ -142,7 +152,7 @@ function get_formulas_results($group, $atid,
$extra_fields=array()){
}
}
}
- $result [] = array(
'id'=>$extraField['extra_field_id'], 'value'=>$valueArr,
'error'=>$expr->last_error);
+ $result [] = array(
'id'=>$extraField['extra_field_id'], 'value'=>$valueArr,
'error'=>($expr->isError()?$expr->getErrorMessage():null));
}
}
}
diff --git a/src/common/tracker/views/form-editformula.php
b/src/common/tracker/views/form-editformula.php
new file mode 100644
index 0000000..5a1c954
--- /dev/null
+++ b/src/common/tracker/views/form-editformula.php
@@ -0,0 +1,255 @@
+<?php
+/**
+ * Formula Editor
+*
+* Copyright 2017, Stéphane-Eymeric Bredthauer - TrivialDev
+* http://fusionforge.org
+*
+* This file is part of FusionForge. FusionForge is free software;
+* you can redistribute it and/or modify it under the terms of the
+* GNU General Public License as published by the Free Software
+* Foundation; either version 2 of the Licence, or (at your option)
+* any later version.
+*
+* FusionForge is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with FusionForge; if not, write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+require_once $gfcommon.'tracker/ArtifactExpression.class.php';
+
+global $HTML;
+
+html_use_tablesorter();
+
+$title = sprintf(_('Manage Custom Fields for %s'), $ath->getName());
+$ath->adminHeader(array('title'=>$title, 'modal'=>1));
+
+$boxid = getIntFromRequest('boxid');
+if ($boxid) {
+ $ef_id = $boxid;
+ $efe_id = getIntFromRequest('id');
+} else {
+ $ef_id = getIntFromRequest('id');;
+ $efe_id = 0;
+}
+
+$ac = new ArtifactExtraField($ath,$ef_id);
+if (!$ac || !is_object($ac)) {
+ exit_error(_('Unable to create ArtifactExtraField Object'));
+} elseif ($ac->isError()) {
+ exit_error($ac->getErrorMessage());
+}
+
+if (!$efe_id) {
+ $formula = $ac->getFormula();
+} else {
+ $ao = new ArtifactExtraFieldElement($ac,$id);
+ if (!$ao || !is_object($ao)) {
+ exit_error(_('Unable to create ArtifactExtraFieldElement
Object'),'tracker');
+ } elseif ($ao->isError()) {
+ exit_error($ao->getErrorMessage(),'tracker');
+ }
+ $formula = $ao->getFormula();
+}
+
+$efarr = $ath->getExtraFields(array(),false,true);
+$eftypes=ArtifactExtraField::getAvailableTypes();
+$keys=array_keys($efarr);
+$rows=count($keys);
+echo html_ao('table',array('class'=>'fullwidth'));
+echo html_ao('tr');
+
+//variables
+echo html_ao('td',array('class'=>'onethirdwidth top'));
+echo html_e('p',array(),_('Variable'));
+if ($rows > 0) {
+ $title_arr = array();
+ $classth = array();
+ $title_arr[] = _('Custom Fields');
+ $classth[] = '';
+ $title_arr[] = _('Variable');
+ $classth[] = '';
+ $title_arr[] = _('Type');
+ $classth[] = '';
+ $title_arr[] = _('Elements Defined');
+ $classth[] = 'unsortable';
+ echo $HTML->listTableTop($title_arr, array(), 'full sortable',
'sortable_extrafields', $classth);
+ $rownb = 0;
+ for ($k=0; $k < $rows; $k++) {
+ $i=$keys[$k];
+ $rownb++;
+ $row_attrs =
array('class'=>$HTML->boxGetAltRowStyle($rownb,true));
+ $cells = array();
+ $cells[] = array($efarr[$i]['field_name'],
'class'=>'align-right');
+ $cells[] =
array(html_e('span',array('class'=>'insert'),$efarr[$i]['alias']),
'class'=>'align-right');
+ $cells[] = array($eftypes[$efarr[$i]['field_type']],
'class'=>'align-right');
+
+ //$id=str_replace('@','',$efarr[$i]['alias']);
+
+ /*
+ List of possible options for a user built
Selection Box
+ */
+
+ $elearray =
$ath->getExtraFieldElements($efarr[$i]['extra_field_id']);
+/*
+ if ($efarr[$i]['field_type'] ==
ARTIFACT_EXTRAFIELDTYPE_USER && !isset($roles)) {
+ $rolesarray = array();
+ $roles = $ath->getGroup()->getRoles();
+ foreach ($roles as $role) {
+
$rolesarray[$role->getID()]=$role->getName();
+ }
+ }
+ if ($efarr[$i]['field_type'] ==
ARTIFACT_EXTRAFIELDTYPE_RELEASE && !isset($packages)) {
+ $packagesarray = array();
+ $packages = $packages =
get_frs_packages($ath->getGroup());
+ foreach ($packages as $package) {
+
$packagesarray[$package->getID()]=$package->getName();
+ }
+ }
+*/
+
+ $content = '';
+ if (!empty($elearray)) {
+ $optrows=count($elearray);
+
+ for ($j=0; $j <$optrows; $j++) {
+ switch
($efarr[$i]['field_type']) {
+ case
ARTIFACT_EXTRAFIELDTYPE_USER:
+ $content .=
$rolesarray[$elearray[$j]['element_name']];
+ break;
+ case
ARTIFACT_EXTRAFIELDTYPE_RELEASE:
+ $content .=
$packagesarray[$elearray[$j]['element_name']];
+ break;
+ default:
+ $content .=
html_e('span',array('class'=>'insert'),$elearray[$j]['element_name']);
+ }
+ $content .= html_e('br');
+ }
+ }
+
+ $cells[] = array($content,
'class'=>'align-right');
+
+ echo $HTML->multiTableRow($row_attrs, $cells);
+ }
+ echo $HTML->listTableBottom();
+} else {
+ echo $HTML->warning_msg(_('You have not defined any custom fields'));
+}
+echo html_ac(html_ap() - 1);
+
+// Functions
+echo html_ao('td',array('class'=>'onethirdwidth top'));
+echo html_e('p',array(),_('Functions'));
+$expression = new ArtifactExpression();
+$functions = $expression->getFunctions();
+$title_arr = array();
+$classth = array();
+$title_arr[] = _('Fuction');
+$classth[] = '';
+$title_arr[] = _('Description');
+$classth[] = 'unsortable';
+echo $HTML->listTableTop($title_arr, array(), 'full sortable',
'sortable_fuction', $classth);
+
+$rownb = 0;
+foreach ($functions as $function) {
+ $rownb++;
+ $row_attrs = array('class'=>$HTML->boxGetAltRowStyle($rownb,true));
+ $cells = array();
+ $cells[] = array(html_e('span', array('class'=>'insert'), $function),
'class'=>'align-right');
+ $cells[] = array($expression->getFunctionDescription($function),
'class'=>'align-right');
+ echo $HTML->multiTableRow($row_attrs, $cells);
+}
+echo $HTML->listTableBottom();
+echo html_ac(html_ap() - 1);
+
+//Operators
+echo html_ao('td',array('class'=>'onethirdwidth top'));
+$operatorTypes = $expression->getOperators();
+foreach ($operatorTypes as $operatorType) {
+ echo html_e('p',array(),$operatorType[0]);
+ $title_arr = array();
+ $classth = array();
+ $title_arr[] = _('Operator');
+ $classth[] = '';
+ $title_arr[] = _('Description');
+ $classth[] = 'unsortable';
+ $title_arr[] = _('Exemple');
+ $classth[] = 'unsortable';
+ echo $HTML->listTableTop($title_arr, array(), 'full sortable',
'sortable_fuction', $classth);
+ $operators = $operatorType[1];
+ $rownb = 0;
+ foreach ($operators as $operator) {
+ $rownb++;
+ $row_attrs =
array('class'=>$HTML->boxGetAltRowStyle($rownb,true));
+ $cells = array();
+ $cells[] = array(html_e('span', array('class'=>'insert'),
$operator[0]), 'class'=>'align-right');
+ $cells[] = array($operator[1], 'class'=>'align-right');
+ $cells[] = array($operator[2], 'class'=>'align-right');
+ echo $HTML->multiTableRow($row_attrs, $cells);
+ }
+ echo $HTML->listTableBottom();
+}
+
+echo html_ac(html_ap() - 1);
+echo html_ac(html_ap() - 1);
+echo html_ac(html_ap() - 1);
+$javascript = <<<'EOS'
+$("span.insert").on('click', function(){
+ var formula = $('#formula');
+ var start = formula.prop('selectionStart');
+ var end = formula.prop('selectionEnd');
+ var value = formula.val();
+ formula.val(value.substring(0,
start)+$(this).text()+value.substring(end, value.length));
+ formula.prop({'selectionStart' : start+$(this).text().length,
'selectionEnd': start+$(this).text().length});
+ formula.focus();
+});
+$("textarea#formula").keydown(function(e) {
+ if(e.keyCode === 9) {
+ var start = $(this).prop('selectionStart');
+ var end = $(this).prop('selectionEnd');
+ var value = $(this).val();
+ $(this).val(value.substring(0,
start)+"\t"+value.substring(end));
+ this.selectionStart = this.selectionEnd = start + 1;
+ e.preventDefault();
+ }
+});
+EOS;
+echo html_e('script', array('type'=>'text/javascript'),
'//<![CDATA['."\n".'$(function(){'.$javascript.'});'."\n".'//]]>');
+
+echo html_e('h2', array(), _('Edit formula'));
+
+if (!$efe_id) {
+ echo $HTML->openForm(array('action' =>
'/tracker/admin/?group_id='.$group_id.'&id='.$ef_id.'&atid='.$ath->getID(),
'method' => 'post'));
+ echo html_e('input', array('type'=>'hidden',
'name'=>'update_box_formula', 'value'=>'y'));
+}else {
+ echo $HTML->openForm(array('action' =>
'/tracker/admin/?group_id='.$group_id.'&boxid='.$ef_id.'&atid='.$ath->getID().'&id='.$efe_id,
'method' => 'post'));
+ echo html_e('input', array('type'=>'hidden',
'name'=>'update_opt_formula', 'value'=>'y'));
+}
+
+echo html_e('textarea', array('id'=>'formula', 'name'=>'formula',
'class'=>'fullwidth', 'rows'=>10),$formula,false);
+
+echo html_ao('p');
+echo html_e('input', array('type'=>'submit', 'name'=>'post_changes',
'value'=>_('Update')));
+if (!$efe_id) {
+ echo html_e('input', array('type'=>'button',
'onclick'=>'location.href="/tracker/admin/?update_box=1&group_id='.$group_id.'&id='.$ef_id.'&atid='.$ath->getID().'";
return false;','value'=>_('Cancel')));
+}else {
+ echo html_e('input', array('type'=>'button',
'onclick'=>'location.href="/tracker/admin/?update_opt=1&id='&efe_id.'&group_id='.$group_id.'&atid='.$ath->getID().'&boxid='.$ef_id.'";
return false;','value'=>_('Cancel')));
+}
+echo html_ac(html_ap() - 1);
+
+echo $HTML->closeForm();
+
+echo html_e('p', array(), _('Use formula do define function, set variable, and
calculate the value of the current field'));
+echo html_e('p', array(), _('The instructions can contain tabs, spaces and
carriage returns'));
+echo html_e('p', array(), _('The instructions have to be terminated with a
semicolon'));
+echo html_e('p', array(), _('The instructions must be separated by carriage
returns'));
+echo html_e('p', array(), _('Each line that begins with a hash mark is a
comment'));
+echo html_e('p', array(), _('The last line must be the value to be calculated
from the field'));
+
+$ath->footer();
diff --git a/src/common/tracker/views/form-updateextrafield.php
b/src/common/tracker/views/form-updateextrafield.php
index 8651a0f..5341079 100644
--- a/src/common/tracker/views/form-updateextrafield.php
+++ b/src/common/tracker/views/form-updateextrafield.php
@@ -200,7 +200,10 @@ if (!$ac || !is_object($ac)) {
if (in_array($efType, array(ARTIFACT_EXTRAFIELDTYPE_TEXT,
ARTIFACT_EXTRAFIELDTYPE_INTEGER, ARTIFACT_EXTRAFIELDTYPE_TEXTAREA))) {
echo html_ao('p');
echo html_e('label', array('for'=>'formula'), _('Formula to
calculate field value'));
+ echo html_e('br');
echo html_e('textarea', array('type'=>'text',
'name'=>'formula', 'rows'=>4, 'cols'=>50), $ac->getFormula(), false);
+ echo html_e('br');
+ echo html_e('button',
array('onclick'=>'location.href="/tracker/admin/?edit_formula=1&group_id='.$group_id.'&id='.$id.'&atid='.$ath->getID().'";
return false;'),_('Edit formula'));
echo html_ac(html_ap() - 1);
} else {
echo html_e('input', array('type'=>'hidden', 'name'=>'formula',
'value'=>''));
diff --git a/src/common/tracker/views/form-updateextrafieldelement.php
b/src/common/tracker/views/form-updateextrafieldelement.php
index e798fd6..0233348 100644
--- a/src/common/tracker/views/form-updateextrafieldelement.php
+++ b/src/common/tracker/views/form-updateextrafieldelement.php
@@ -93,7 +93,8 @@ if (!$ac || !is_object($ac)) {
echo html_ao('p');
echo html_e('label', array('for'=>'formula'), html_e('strong',
array(), _('Formula')._(':')).html_e('br'));
- echo html_e('textarea', array('type'=>'text', 'id'=>'formula',
'name'=>'formula', 'rows'=>4, 'cols'=>50), $ao->getFormula(), false);
+ echo html_e('textarea', array('type'=>'text', 'id'=>'formula',
'name'=>'formula', 'rows'=>4, 'cols'=>50), $ao->getFormula(),
false).html_e('br');;
+ echo html_e('button',
array('onclick'=>'location.href="/tracker/admin/?edit_formula=1&group_id='.$group_id.'&id='.$id.'&atid='.$ath->getID().'&boxid='.$boxid.'";
return false;'),_('Edit formula'));
echo html_ac(html_ap()-1);
echo $HTML->warning_msg(_('It is not recommended that you
change the custom field name because other things are dependent upon it. When
you change the custom field name, all related items will be changed to the new
name.'));
diff --git a/src/www/include/expression.php b/src/www/include/expression.php
index a6e6f7b..01b502e 100644
--- a/src/www/include/expression.php
+++ b/src/www/include/expression.php
@@ -98,7 +98,7 @@ class Expression {
'cos', 'cosh', 'arccos', 'acos', 'arccosh', 'acosh',
'tan', 'tanh', 'arctan', 'atan', 'arctanh', 'atanh',
'sqrt', 'abs', 'ln', 'log');
- var $functions = array (); // function defined outside of Expression as
closures
+ var $functions = array (); // function defined outside of Expression
function __construct() {
// make the variables a little more accurate
$this->v ['pi'] = pi ();
@@ -178,7 +178,7 @@ class Expression {
$index = 0;
$stack = new ExpressionStack ();
$output = array (); // postfix form of expression, to be passed
to pfx()
- $expr = trim ( strtolower ( $expr ) );
+ $expr = trim ($expr);
$ops = array ('+', '-', '*', '/', '^', '_', '%', '>', '<',
'>=', '<=', '==', '!=', '=~', '&&', '||', '!', '?', ':', '?:');
$ops_r = array ('+' => 0, '-' => 0, '*' => 0, '/' => 0, '^' =>
1, '_' => 0, '%' => 0, '>' => 0, '<' => 0, '>=' => 0, '<=' => 0, '==' => 0,
'!=' => 0, '=~' => 0, '&&' => 0, '||' => 0, '!' => 0, '?' => 1, ':' => 0, '?:'
=> 0); // right-associative operator?
@@ -242,9 +242,9 @@ class Expression {
// heart of the algorithm:
$o2 = $stack->last ();
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]) ) {
- $val = $stack->pop ();
- if ($val != '?') {
- $output [] = $val; // pop stuff
off the stack into the output
+ $pop = $stack->pop ();
+ if ($pop != '?') {
+ $output [] = $pop; // pop stuff
off the stack into the output
} else {
$op = '?:';
break;
@@ -269,8 +269,8 @@ class Expression {
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)
- $val = $stack->pop();
- $output [] = $val; // pop the function
and push onto the output
+ $pop = $stack->pop();
+ $output [] = $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)" );
@@ -306,8 +306,8 @@ class Expression {
if ($first_argument) {
$first_argument = false;
} else {
- $val = $stack->pop ();
- $stack->push ( $val + 1 ); // increment
the argument count
+ $pop = $stack->pop ();
+ $stack->push ( $pop + 1 ); // increment
the argument count
}
$stack->push ( '(' ); // put the ( back on,
we'll need to pop back to it again
$index ++;
@@ -348,8 +348,8 @@ class Expression {
if (! preg_match (
"/^([a-z]\w*)\($/", $stack->last ( 2 ), $matches )) {
return $this->trigger (
"unexpected error" );
}
- $val = $stack->pop ();
- $stack->push ( $val + 1 ); //
increment the argument count
+ $pop = $stack->pop ();
+ $stack->push ( $pop + 1 ); //
increment the argument count
$stack->push ( '(' ); // put
the ( back on, we'll need to pop back to it again
}
}
@@ -519,12 +519,13 @@ class Expression {
}
$args [] = $stack->pop ();
}
+ $args = array_reverse($args);
$stack->push ( $reflection->invokeArgs
( $args ) );
}
// if the token is a number or variable, push
it on the stack
} else {
if (preg_match (
'/^([\[{](?>"(?:[^"]|\\")*"|[^[{\]}]|(?1))*[\]}])$/', $token ) || preg_match (
"/^(null|true|false)$/", $token )) { // json
-
// return $this->trigger("invalid json " . $token);
+ // return $this->trigger("invalid json
" . $token);
if ($token == 'null') {
$value = null;
} elseif ($token == 'true') {
diff --git a/src/www/themes/css/fusionforge.css
b/src/www/themes/css/fusionforge.css
index 3bdfd72..1e16c01 100644
--- a/src/www/themes/css/fusionforge.css
+++ b/src/www/themes/css/fusionforge.css
@@ -1115,3 +1115,8 @@ table.id_sortable th.headerSortDown span {
input[readonly], select[readonly] {
background-color:#ebebeb;
}
+
+span.insert {
+ cursor:pointer;
+ color:green;
+}
diff --git a/src/www/tracker/admin/index.php b/src/www/tracker/admin/index.php
index 690a17d..dd40e03 100644
--- a/src/www/tracker/admin/index.php
+++ b/src/www/tracker/admin/index.php
@@ -122,7 +122,7 @@ if ($group_id && $atid) {
'updownorder_opt', 'post_changes_order',
'post_changes_alphaorder', 'post_changes_default', 'copy_opt', 'add_canned',
'clone_tracker', 'edittemplate',
'update_canned', 'delete_canned', 'update_box',
'update_opt', 'delete', 'delete_opt', 'deleteextrafield','update_type',
- 'effort_units'
+ 'effort_units', 'edit_formula'
);
$action = '';
foreach ($actions as $a) {
@@ -242,6 +242,10 @@ if ($group_id && $atid) {
include $gfcommon.'tracker/actions/effort_units.php';
+ } elseif ($action == 'edit_formula') {
+
+ include $gfcommon.'tracker/views/form-editformula.php';
+
} else {
include $gfcommon.'tracker/actions/admin-tracker.php';
-----------------------------------------------------------------------
Summary of changes:
src/common/tracker/ArtifactExpression.class.php | 117 ++++++++++
src/common/tracker/actions/admin-updates.php | 52 +++++
src/common/tracker/actions/ajax.php | 42 ++--
src/common/tracker/views/form-editformula.php | 255 +++++++++++++++++++++
src/common/tracker/views/form-updateextrafield.php | 3 +
.../tracker/views/form-updateextrafieldelement.php | 3 +-
src/www/include/expression.php | 25 +-
src/www/themes/css/fusionforge.css | 5 +
src/www/tracker/admin/index.php | 6 +-
9 files changed, 478 insertions(+), 30 deletions(-)
create mode 100644 src/common/tracker/ArtifactExpression.class.php
create mode 100644 src/common/tracker/views/form-editformula.php
hooks/post-receive
--
FusionForge
_______________________________________________
Fusionforge-commits mailing list
[email protected]
http://lists.fusionforge.org/cgi-bin/mailman/listinfo/fusionforge-commits