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
}
/**
* return the html for the output of a field without link, preprend...
* @param array $context - key 'list_mode' defines weher to output for a list or a simple value
* return the html for the output of a field without link, prepend...
* @param array $context - key 'list_mode' defines wether to output for a list or a simple value
* @return string $html
*/
protected function renderInnerOutput($context = array())
{
$value = $this->getConfiguration('value');
$pvalue = $this->getConfiguration('pvalue', $value);
if (isset($context['list_mode']) && $context['list_mode'] === 'csv') {
$val = $this->getConfiguration('value');
$default = array('CR'=>'%%%', 'delimitorL'=>'"', 'delimitorR'=>'"');
$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);
return $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 $value;
} else {
return $this->getConfiguration('pvalue', $this->getConfiguration('value'));
return $pvalue;
}
}
......@@ -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
* @return mixed field value
*/
......@@ -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.
*
* @param int $number
* @param bool $default
* Note: This function should be public, as long as certain low-level trackerlib functions need to be accessed directly.
* Otherwise one would be forced to get the options from fields like this: $myField['options_array'][0] ...
* @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
*/
protected function getOption($key, $default = false)
public function getOption($key, $default = false)
{
if (is_numeric($key)) {
return $this->options->getParamFromIndex($key, $default);
......
......@@ -75,7 +75,6 @@ class Tracker_Field_DynamicList extends Tracker_Field_Abstract
function getFieldData(array $requestData = array())
{
$ins_id = $this->getInsertId();
return array(
'value' => (isset($requestData[$ins_id]))
? $requestData[$ins_id]
......@@ -86,26 +85,58 @@ class Tracker_Field_DynamicList extends Tracker_Field_Abstract
function renderInput($context = array())
{
// 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(
'
$("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(
"tiki-tracker_http_request.php",
{
trackerIdList: ' . $this->getOption('trackerId') . ',
fieldlist: ' . $this->getOption('listFieldIdThere') . ',
filterfield: ' . $this->getOption('filterFieldIdThere') . ',
status: "' . $this->getOption('statusThere') . '",
mandatory: "' . $this->getConfiguration('isMandatory') . '",
item: $(this).val() // We need the field value for the fieldId filterfield for the item $(this).val
filterFieldIdHere: ' . $filterFieldIdHere . ',
trackerIdThere: ' . $trackerIdThere . ',
listFieldIdThere: ' . $listFieldIdThere . ',
filterFieldIdThere: ' . $filterFieldIdThere . ',
statusThere: "' . $statusThere . '",
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) {
$ddl = $("select[name=' . $this->getInsertId() . ']");
$ddl.empty();
var v, l;
if (data) {
$.each( data, function (i,data) {
if (data && data.request && data.response) {
targetDDL = "select[name=" + data.request.insertId + "]";
$ddl = $(targetDDL);
$ddl.empty();
var v, l;
response = data.response;
$.each( response, function (i,data) {
if (data && data.length > 1) {
v = data[0];
l = data[1];
......@@ -118,44 +149,105 @@ $("input[name=ins_' . $this->getOption('filterFieldIdHere') . '], select[name=in
.val(v)
.text(l)
);
});
if (val) {
$ddl.val(val);
}); // each
if (data.request.originalValue) {
$ddl.val(data.request.originalValue);
}
}
if (jqueryTiki.chosen) {
$ddl.trigger("chosen:updated");
}
$ddl.trigger("change");
}
);
}).trigger("change", ["' . $this->getConfiguration('value') . '"]);
} // callback
); // getJSON
}).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())
{
$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'));
$field = $definition->getField($this->getOption('listFieldIdThere'));
if ($field['type'] == 'e' || $field['type'] == 'r') {
$item = $this->getItemData();
$item['ins_' . $this->getOption('listFieldIdThere')] = array($this->getValue());
$field['value'] = $this->getValue();
$handler = TikiLib::lib('trk')->get_field_handler($field, $item);
$field = array_merge($field, $handler->getFieldData($item)); // get category field to build it's data arrays
$handler = TikiLib::lib('trk')->get_field_handler($field, $item);
return $handler->renderOutput($context);
} else {
return parent::renderInnerOutput($context);
// r = item-link requires $listFieldThere = array_merge($listFieldThere, array('value' => $remoteItemId));
case 'r':
$listFieldThere = array_merge($listFieldThere, array('value' => $remoteItemId));
$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;
//l = item-list
case 'l':
// show selected item of that list - requires match in tiki-tracker_http_request.php
//$listFieldThere = array_merge($listFieldThere, array('value' => $remoteItemId));
$handler = $trklib->get_field_handler($listFieldThere);
$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 @@
//
// 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.
// $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
/**
* Handler for (XHR) requests from the trackerfield type itemslist.
* @see lib/core/Tracker/Field/ItemsList.php for furher details.
*/
require_once ('tiki-setup.php');
include_once ('lib/trackers/trackerlib.php');
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