Commit 9d5f9fa4 authored by walper's avatar walper

[FIX] Fix trackerfield Dynamic-Item-List. IMPORTANT: This fix saves the itemId...

[FIX] Fix trackerfield Dynamic-Item-List. IMPORTANT: This fix saves the itemId of the referenced Item, not the native value! Thus it will break existing usecases.
Improvements/tested combinations: One can assign multiple DIL-Fields to one selection field (before it was just one).
Filterfield Combinations: category/category, itemlink/itemlink, itemlink/textfield (other equal fieldtypes should work as well). Category can only be used with category for security. 
Displayfields (to make the selection from) : category, itemlist, itemlink, textfield (other simple fields should work).
parent 3d617feb
...@@ -263,20 +263,22 @@ abstract class Tracker_Field_Abstract implements Tracker_Field_Interface, Tracke ...@@ -263,20 +263,22 @@ abstract class Tracker_Field_Abstract implements Tracker_Field_Interface, Tracke
} }
/** /**
* return the html for the output of a field without link, preprend... * return the html for the output of a field without link, prepend...
* @param array $context - key 'list_mode' defines weher to output for a list or a simple value * @param array $context - key 'list_mode' defines wether to output for a list or a simple value
* @return string $html * @return string $html
*/ */
protected function renderInnerOutput($context = array()) protected function renderInnerOutput($context = array())
{ {
$value = $this->getConfiguration('value');
$pvalue = $this->getConfiguration('pvalue', $value);
if (isset($context['list_mode']) && $context['list_mode'] === 'csv') { if (isset($context['list_mode']) && $context['list_mode'] === 'csv') {
$val = $this->getConfiguration('value');
$default = array('CR'=>'%%%', 'delimitorL'=>'"', 'delimitorR'=>'"'); $default = array('CR'=>'%%%', 'delimitorL'=>'"', 'delimitorR'=>'"');
$context = array_merge($default, $context); $context = array_merge($default, $context);
$val = str_replace(array("\r\n", "\n", '<br />', $context['delimitorL'], $context['delimitorR']), array($context['CR'], $context['CR'], $context['CR'], $context['delimitorL'].$context['delimitorL'], $context['delimitorR'].$context['delimitorR']), $val); $value = str_replace(array("\r\n", "\n", '<br />', $context['delimitorL'], $context['delimitorR']), array($context['CR'], $context['CR'], $context['CR'], $context['delimitorL'].$context['delimitorL'], $context['delimitorR'].$context['delimitorR']), $value);
return $val; return $value;
} else { } else {
return $this->getConfiguration('pvalue', $this->getConfiguration('value')); return $pvalue;
} }
} }
...@@ -302,8 +304,11 @@ abstract class Tracker_Field_Abstract implements Tracker_Field_Interface, Tracke ...@@ -302,8 +304,11 @@ abstract class Tracker_Field_Abstract implements Tracker_Field_Interface, Tracke
} }
/** /**
* Return the value for this item field * Return the value for this item field. Depending on fieldtype that could be the itemId of a linked field.
* * Value is looked for in:
* $this->itemData[fieldNumber]
* $this->definition['value']
* $this->itemData['fields'][permName]
* @param mixed $default the field value used if none is set * @param mixed $default the field value used if none is set
* @return mixed field value * @return mixed field value
*/ */
...@@ -346,14 +351,15 @@ abstract class Tracker_Field_Abstract implements Tracker_Field_Interface, Tracke ...@@ -346,14 +351,15 @@ abstract class Tracker_Field_Abstract implements Tracker_Field_Interface, Tracke
} }
/** /**
* Returns an option from the options array based on the numeric position. * Return option from the options array.
* For the list of options for a particular field check its getTypes() method. * For the list of options for a particular field check its getTypes() method.
* * Note: This function should be public, as long as certain low-level trackerlib functions need to be accessed directly.
* @param int $number * Otherwise one would be forced to get the options from fields like this: $myField['options_array'][0] ...
* @param bool $default * @param int $number | string $key. depending on type: based on the numeric array position, or by name.
* @param mixed $default - defaultValue to return if nothing found
* @return mixed * @return mixed
*/ */
protected function getOption($key, $default = false) public function getOption($key, $default = false)
{ {
if (is_numeric($key)) { if (is_numeric($key)) {
return $this->options->getParamFromIndex($key, $default); return $this->options->getParamFromIndex($key, $default);
......
...@@ -75,7 +75,6 @@ class Tracker_Field_DynamicList extends Tracker_Field_Abstract ...@@ -75,7 +75,6 @@ class Tracker_Field_DynamicList extends Tracker_Field_Abstract
function getFieldData(array $requestData = array()) function getFieldData(array $requestData = array())
{ {
$ins_id = $this->getInsertId(); $ins_id = $this->getInsertId();
return array( return array(
'value' => (isset($requestData[$ins_id])) 'value' => (isset($requestData[$ins_id]))
? $requestData[$ins_id] ? $requestData[$ins_id]
...@@ -86,26 +85,58 @@ class Tracker_Field_DynamicList extends Tracker_Field_Abstract ...@@ -86,26 +85,58 @@ class Tracker_Field_DynamicList extends Tracker_Field_Abstract
function renderInput($context = array()) function renderInput($context = array())
{ {
// REFACTOR: can't use list-tracker_field_values_ajax.php yet as it doesn't seem to filter // REFACTOR: can't use list-tracker_field_values_ajax.php yet as it doesn't seem to filter
// Modified to support multiple dynamic item list fields bound to the same $filterFieldIdHere
// When changing $filterFieldValueHere (i.e combobox) the $originalValue will be send as part of the request to the backend.
// The backend returns an json array('request' => $requestData, 'response' => $responseData).
// This way we can keep the default $originalValue, even when changing the selection forth and back.
// It fixes also the issue that, if more than one dynamic item list fields are set and use the same
// $filterFieldIdHere, then the initial value was wrong due to multiple fires of the handler.
$filterFieldIdHere = $this->getOption('filterFieldIdHere');
$trackerIdThere = $this->getOption('trackerId');
$listFieldIdThere = $this->getOption('listFieldIdThere');
$filterFieldIdThere = $this->getOption('filterFieldIdThere');
$statusThere = $this->getOption('statusThere');
$isMandatory = $this->getConfiguration('isMandatory');
$insertId = $this->getInsertId();
$originalValue = $this->getConfiguration('value');
TikiLib::lib('header')->add_jq_onready( TikiLib::lib('header')->add_jq_onready(
' '
$("input[name=ins_' . $this->getOption('filterFieldIdHere') . '], select[name=ins_' . $this->getOption('filterFieldIdHere') . ']").change(function(e, val) { var dilIsInit_'. $insertId. ' = false;
$("input[name=ins_' . $filterFieldIdHere . '], select[name=ins_' . $filterFieldIdHere . ']").change(function(e, val) {
if (val && dilIsInit_'. $insertId. ') {
return; // on init, only fire one time per select trigger eventhandler. otherwise each init would trigger all prev. registered handlers
}
dilIsInit_'. $insertId. ' = true;
$.getJSON( $.getJSON(
"tiki-tracker_http_request.php", "tiki-tracker_http_request.php",
{ {
trackerIdList: ' . $this->getOption('trackerId') . ', filterFieldIdHere: ' . $filterFieldIdHere . ',
fieldlist: ' . $this->getOption('listFieldIdThere') . ', trackerIdThere: ' . $trackerIdThere . ',
filterfield: ' . $this->getOption('filterFieldIdThere') . ', listFieldIdThere: ' . $listFieldIdThere . ',
status: "' . $this->getOption('statusThere') . '", filterFieldIdThere: ' . $filterFieldIdThere . ',
mandatory: "' . $this->getConfiguration('isMandatory') . '", statusThere: "' . $statusThere . '",
item: $(this).val() // We need the field value for the fieldId filterfield for the item $(this).val mandatory: "' . $isMandatory . '",
insertId: "' . $insertId . '", // need to pass $insertId in case we have more than one field bound to the same eventsource
originalValue: "' . $originalValue . '",
filterFieldValueHere: $(this).val() // We need the field value for the fieldId filterfield for the item $(this).val
}, },
// callback
function(data, status) { function(data, status) {
$ddl = $("select[name=' . $this->getInsertId() . ']"); if (data && data.request && data.response) {
$ddl.empty(); targetDDL = "select[name=" + data.request.insertId + "]";
var v, l; $ddl = $(targetDDL);
if (data) { $ddl.empty();
$.each( data, function (i,data) {
var v, l;
response = data.response;
$.each( response, function (i,data) {
if (data && data.length > 1) { if (data && data.length > 1) {
v = data[0]; v = data[0];
l = data[1]; l = data[1];
...@@ -118,44 +149,105 @@ $("input[name=ins_' . $this->getOption('filterFieldIdHere') . '], select[name=in ...@@ -118,44 +149,105 @@ $("input[name=ins_' . $this->getOption('filterFieldIdHere') . '], select[name=in
.val(v) .val(v)
.text(l) .text(l)
); );
}); }); // each
if (val) {
$ddl.val(val); if (data.request.originalValue) {
$ddl.val(data.request.originalValue);
} }
} }
if (jqueryTiki.chosen) { if (jqueryTiki.chosen) {
$ddl.trigger("chosen:updated"); $ddl.trigger("chosen:updated");
} }
$ddl.trigger("change"); $ddl.trigger("change");
} } // callback
); ); // getJSON
}).trigger("change", ["' . $this->getConfiguration('value') . '"]); }).trigger("change", "'. $insertId. '"); // closure
' '
); ); // add_jq_onready
return '<select name="' . $this->getInsertId() . '"></select>'; return '<select name="' . $insertId . '"></select>';
} }
// If you make changes here check also tiki-tracker_http_request.php as long as it is not integrated in ajax-services
// @TODO Move parts of this to getFieldData()
public function renderInnerOutput($context = array()) public function renderInnerOutput($context = array())
{ {
$trklib = TikiLib::lib('trk');
// remote tracker and remote field
$trackerIdThere = $this->getOption('trackerId');
$definition = Tracker_Definition::get($trackerIdThere);
$listFieldIdThere = $this->getOption('listFieldIdThere');
$listFieldThere = $definition->getField($listFieldIdThere);
// $listFieldThere above does not return any value for fieldtype category. Maybe a bug?
if (!isset($listFieldThere)) {
$listFieldThere = $trklib->get_tracker_field($listFieldIdThere);
}
$remoteItemId = $this->getValue();
$itemInfo = $trklib->get_tracker_item($remoteItemId);
switch ($listFieldThere['type']) {
// e = category
case 'e':
//$listFieldThere = array_merge($listFieldThere, array('value' => $remoteItemId));
$handler = $trklib->get_field_handler($listFieldThere, $itemInfo);
// array selected_categories etc.
$valueField = $handler->getFieldData();
// for some reason, need to apply the values back, otherwise renderOutput does not return a value - bug or intended?
$listFieldThere = array_merge($listFieldThere, $valueField);
$handler = $trklib->get_field_handler($listFieldThere, $itemInfo);
$context = array('showlinks' => 'n');
$labelField = $handler->renderOutput($context);
return $labelField;
break;
$definition = Tracker_Definition::get($this->getOption('trackerId')); // r = item-link requires $listFieldThere = array_merge($listFieldThere, array('value' => $remoteItemId));
$field = $definition->getField($this->getOption('listFieldIdThere')); case 'r':
$listFieldThere = array_merge($listFieldThere, array('value' => $remoteItemId));
if ($field['type'] == 'e' || $field['type'] == 'r') { $handler = $trklib->get_field_handler($listFieldThere, $itemInfo);
$item = $this->getItemData(); // do not inherit showlinks settings from remote items.
$item['ins_' . $this->getOption('listFieldIdThere')] = array($this->getValue()); $context = array('showlinks' => 'n');
$field['value'] = $this->getValue(); $labelField = $handler->renderOutput($context);
return $labelField;
$handler = TikiLib::lib('trk')->get_field_handler($field, $item); break;
$field = array_merge($field, $handler->getFieldData($item)); // get category field to build it's data arrays //l = item-list
$handler = TikiLib::lib('trk')->get_field_handler($field, $item); case 'l':
// show selected item of that list - requires match in tiki-tracker_http_request.php
return $handler->renderOutput($context); //$listFieldThere = array_merge($listFieldThere, array('value' => $remoteItemId));
} else { $handler = $trklib->get_field_handler($listFieldThere);
return parent::renderInnerOutput($context); $displayFieldIdThere = $handler->getOption('displayFieldIdThere');
// do not inherit showlinks settings from remote items.
$context = array('showlinks' => 'n');
foreach ($displayFieldIdThere as $displayFieldId) {
$displayField = $trklib->get_tracker_field($displayFieldId);
// not shure why this is needed - and only for some fieldtypes?
//renderOutput() in abstract checks only $this->definition['value'], not $this->itemdata
$displayField = array_merge($displayField, array('value' => $itemInfo[$displayFieldId]));
$handler = $trklib->get_field_handler($displayField, $itemInfo);
$labelFields[] = $handler->renderOutput($context);
}
$labelField = implode(' ', $labelFields);
return $labelField;
break;
// i.e textfield - requires $listFieldThere = array_merge($listFieldThere, array('value' => $itemInfo[$listFieldIdThere]));
default:
$listFieldThere = array_merge($listFieldThere, array('value' => $itemInfo[$listFieldIdThere]));
$handler = $trklib->get_field_handler($listFieldThere, $itemInfo);
// do not inherit showlinks settings from remote items.
$context = array('showlinks' => 'n');
$labelField = $handler->renderOutput($context);
return $labelField;
break;
} }
} }
......
This diff is collapsed.
...@@ -6,10 +6,16 @@ ...@@ -6,10 +6,16 @@
// //
// All Rights Reserved. See copyright.txt for details and a complete list of authors. // All Rights Reserved. See copyright.txt for details and a complete list of authors.
// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details. // Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
// $Id: tiki-tracker_http_request.php 48614 2013-11-21 05:48:54Z nkoth $ // $Id: tiki-tracker_http_request_itemslist.php 48614 2013-11-21 05:48:54Z nkoth $
// TODO - refactor to ajax-services then KILME // TODO - refactor to ajax-services then KILME
/**
* Handler for (XHR) requests from the trackerfield type itemslist.
* @see lib/core/Tracker/Field/ItemsList.php for furher details.
*/
require_once ('tiki-setup.php'); require_once ('tiki-setup.php');
include_once ('lib/trackers/trackerlib.php'); include_once ('lib/trackers/trackerlib.php');
if ($prefs['feature_categories'] == 'y') { if ($prefs['feature_categories'] == 'y') {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment