Page MenuHomeIn-Portal Phabricator

in-portal
No OneTemporary

File Metadata

Created
Fri, Nov 7, 1:35 PM

in-portal

Index: branches/RC/core/units/general/helpers/controls/minput_helper.php
===================================================================
--- branches/RC/core/units/general/helpers/controls/minput_helper.php (revision 10646)
+++ branches/RC/core/units/general/helpers/controls/minput_helper.php (revision 10647)
@@ -1,185 +1,185 @@
<?php
class MInputHelper extends kHelper {
/**
* Returns user education table name
*
* @param kDBItem $object
* @return string
*/
function getTable($prefix, $temp=false)
{
$table_name = $this->Application->getUnitOption($prefix, 'TableName');
return $temp ? $this->Application->GetTempName($table_name, 'prefix:'.$prefix) : $table_name;
}
function prepareMInputXML($records, $use_fields)
{
$xml = '';
foreach ($records as $record) {
$xml .= '<record>';
foreach ($record as $field_name => $field_value) {
if (!in_array($field_name, $use_fields)) {
continue;
}
- $xml .= '<field name="'.$field_name.'">'.$field_value.'</field>';
+ $xml .= '<field name="' . $field_name . '">' . htmlspecialchars($field_value) . '</field>';
}
$xml .= '</record>';
}
return $xml ? '<records>'.$xml.'</records>' : '';
}
function prepareErrorsXML(&$object, $fields_hash)
{
$xml = '';
foreach ($fields_hash as $field_name => $field_value) {
$object->SetField($field_name, $field_value);
if (!$object->ValidateField($field_name)) {
$xml .= '<field name="'.$field_name.'">'.$object->GetErrorMsg($field_name, false).'</field>';
}
}
return '<errors>'.$xml.'</errors>';
}
/**
* Validates MInput control fields
*
* @param kEvent $event
*/
function OnValidateMInputFields(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$items_info = $this->Application->GetVar($event->getPrefixSpecial(true));
if ($items_info) {
list ($id, $field_values) = each($items_info);
echo $this->prepareErrorsXML($object, $field_values);
}
$event->status = erSTOP;
}
function parseMInputXML($xml)
{
$xml_helper =& $this->Application->recallObject('kXMLHelper');
/* @var $xml_helper kXMLHelper */
$root_node =& $xml_helper->Parse($xml);
$root_node =& $root_node->FindChild('records');
if (!$root_node || !$root_node->firstChild) {
return false;
}
$records = Array ();
$current_node = $root_node->firstChild;
/* @var $current_node kXMLNode */
do {
$record = Array();
$sub_node =& $current_node->firstChild;
/* @var $current_node kXMLNode */
do {
$record[$sub_node->Attributes['NAME']] = $sub_node->Data;
}while ( ($sub_node =& $sub_node->NextSibling()) );
$records[] = $record;
} while (($current_node =& $current_node->NextSibling()));
return $records;
}
/**
* Loads selected values from sub_prefix to main item virtual field.
* Called from OnAfterItemLoad of main prefix.
*
* @param kEvent $event
* @param string $store_field main item's field name, to store values into
* @param string $sub_prefix prefix used to store info about selected items
* @param Array $use_fields fields, used in value string building
*/
function LoadValues(&$event, $store_field, $sub_prefix, $use_fields)
{
$object =& $event->getObject();
/* @var $object kDBItem */
-
- $sub_item =& $this->Application->recallObject($sub_prefix, null, Array('skip_autoload' => true));
+
+ $sub_item =& $this->Application->recallObject($sub_prefix, null, Array('skip_autoload' => true));
/* @var $sub_item kDBItem */
$foreign_key = $this->Application->getUnitOption($sub_prefix, 'ForeignKey');
$sql = 'SELECT *
FROM '.$this->getTable($sub_prefix, $object->IsTempTable()).'
WHERE '.$foreign_key.' = '.$object->GetID();
-
+
$selected_items = $this->Conn->Query($sql);
-
+
$field_names = array_keys( $sub_item->GetFieldValues() );
-
+
foreach ($selected_items as $key => $fields_hash) {
$sub_item->Clear();
$sub_item->SetDBFieldsFromHash($fields_hash);
-
+
// to fill *_date and *_time fields from main date fields
- $sub_item->UpdateFormattersSubFields();
-
+ $sub_item->UpdateFormattersSubFields();
+
foreach ($field_names as $field) {
- $field_options = $sub_item->GetFieldOptions($field);
+ $field_options = $sub_item->GetFieldOptions($field);
$formatter = array_key_exists('formatter', $field_options) ? $field_options['formatter'] : false;
-
+
if ($formatter == 'kDateFormatter') {
- $selected_items[$key][$field] = $sub_item->GetField($field);
+ $selected_items[$key][$field] = $sub_item->GetField($field);
}
else {
- $selected_items[$key][$field] = $sub_item->GetDBField($field);
+ $selected_items[$key][$field] = $sub_item->GetDBField($field);
}
}
}
$object->SetDBField($store_field, $this->prepareMInputXML($selected_items, $use_fields));
}
-
+
/**
* Saves data from minput control to subitem table (used from subitem hook)
*
* @param kEvent $sub_event
* @param string $store_field
*/
function SaveValues(&$sub_event, $store_field)
{
$main_object =& $sub_event->MasterEvent->getObject();
$affected_field = $main_object->GetDBField($store_field);
- $object =& $this->Application->recallObject($sub_event->getPrefixSpecial(), null, Array('skip_autoload' => true));
+ $object =& $this->Application->recallObject($sub_event->getPrefixSpecial(), null, Array('skip_autoload' => true));
/*@var $object kDBItem*/
-
+
$sub_table = $object->TableName;
$foreign_key = $this->Application->getUnitOption($sub_event->Prefix, 'ForeignKey');
-
+
$sql = 'DELETE FROM '.$sub_table.'
WHERE '.$foreign_key.' = '.$main_object->GetID();
-
+
$this->Conn->Query($sql);
-
+
if ($affected_field) {
$records = $this->parseMInputXML($affected_field);
$main_id = $main_object->GetID();
-
+
foreach ($records as $fields_hash) {
$object->Clear();
$fields_hash[$foreign_key] = $main_id;
$object->SetDBFieldsFromHash($fields_hash);
$object->Create();
}
}
}
}
?>
\ No newline at end of file
Property changes on: branches/RC/core/units/general/helpers/controls/minput_helper.php
___________________________________________________________________
Modified: cvs2svn:cvs-rev
## -1 +1 ##
-1.1.8.2
\ No newline at end of property
+1.1.8.3
\ No newline at end of property
Index: branches/RC/core/admin_templates/js/form_controls.js
===================================================================
--- branches/RC/core/admin_templates/js/form_controls.js (revision 10646)
+++ branches/RC/core/admin_templates/js/form_controls.js (revision 10647)
@@ -1,471 +1,480 @@
function MultiInputControl($field_name, $field_mask, $field_labels, $result_mask) {
this.FieldName = $field_name;
this.ValidateURL = '';
this.FieldMask = $field_mask;
this.FieldLabels = $field_labels;
this.ResultMask = $result_mask; // format of record in list
this.Permissions = new Array (); // action groups allowed
this.Messages = new Array (); // various phrase (errors, confirmations, button titles)
this.Controls = new Array (); // controls used for editing list content
this.Records = new Array (); // data to be submitted (needs to be parsed using formatters)
this.Errors = new Array (); // error messages in fields
this.InEditing = false;
}
MultiInputControl.prototype.registerControl = function($field_name, $type, $required) {
this.Controls[$field_name] = {'type' : $type, 'required' : $required};
}
MultiInputControl.prototype.getControl = function ($field, $appendix) {
$appendix = isset($appendix) ? '_' + $appendix : '';
return document.getElementById( this.FieldMask.replace('#FIELD_NAME#', $field) + $appendix );
}
MultiInputControl.prototype.getControlValue = function ($field) {
var $value = '';
switch (this.Controls[$field]['type']) {
case 'select':
var $control = this.getControl($field);
$value = $control.options[$control.selectedIndex].value;
break;
/*case 'datetime':
$value = this.getControl($field + '_date').value + ' ' + this.getControl($field + '_time').value;
break;*/
default:
$value = this.getControl($field).value;
break;
}
return $value;
}
MultiInputControl.prototype.setControlValue = function ($field, $value) {
switch (this.Controls[$field]['type']) {
case 'select':
var $i = 0;
var $control = this.getControl($field);
if ($value === null) {
$control.selectedIndex = 0;
}
while ($i < $control.options.length) {
if ($control.options[$i].value == $value) {
$control.selectedIndex = $i;
break;
}
$i++;
}
break;
/*case 'datetime':
$value = $value.split(' ');
this.getControl($field + '_date').value = $value[0];
this.getControl($field + '_time').value = $value[1];
break;*/
default:
this.getControl($field).value = ($value === null) ? '' : $value;
break;
}
}
MultiInputControl.prototype.formatValue = function ($field, $value) {
if (this.Controls[$field]['type'] == 'select') {
var $i = 0;
var $control = this.getControl($field);
while ($i < $control.options.length) {
if ($control.options[$i].value == $value) {
$value = $control.options[$i].innerHTML;
break;
}
$i++;
}
}
return $value;
}
MultiInputControl.prototype.formatLine = function($record_index) {
var $ret = this.ResultMask;
for (var $field_name in this.Controls) {
var $value = this.Records[$record_index][$field_name];
$ret = $ret.replace('#' + $field_name + '#', this.formatValue($field_name, $value));
}
return $ret;
}
MultiInputControl.prototype.makeRequest = function($request_type, $record, $skip_index) {
var $url = this.ValidateURL;
for (var $field_name in $record) {
$url += '&' + this.FieldMask.replace('#FIELD_NAME#', $field_name) + '=' + escape($record[$field_name]);
}
Request.makeRequest($url, this.BusyRequest, '', this.successCallback, this.errorCallback, [$request_type, $record, $skip_index], this);
}
MultiInputControl.prototype.AddRecord = function() {
var $record = this.prepareRecord();
if (this.InEditing) {
// already in editing
var $record_index = this.getControl(this.FieldName, 'minput').selectedIndex;
this.makeRequest('SaveRecord', $record, $record_index);
return ;
}
if (this.hasPermission('add')) {
this.makeRequest('AddRecord', $record, false);
}
}
MultiInputControl.prototype.EditRecord = function() {
var $record_index = this.getControl(this.FieldName, 'minput').selectedIndex;
if ($record_index == -1 || this.InEditing) {
// no record selected
return ;
}
this.InEditing = true;
var $edit_record = this.Records[$record_index];
for (var $field_name in $edit_record) {
this.setControlValue($field_name, $edit_record[$field_name]);
}
this.getControl(this.FieldName, 'add_button').value = this.Messages['save_button'];
this.getControl(this.FieldName, 'minput').disabled = true;
this.SetButtonState('edit', false);
this.SetButtonState('delete', false);
}
MultiInputControl.prototype.ResetControls = function() {
for (var $field_name in this.Controls) {
this.setControlValue($field_name, null);
}
this.Errors = new Array ();
}
MultiInputControl.prototype.CancelEditing = function() {
this.ResetControls();
this.getControl(this.FieldName, 'add_button').value = this.Messages['add_button'];
this.getControl(this.FieldName, 'minput').disabled = false;
this.SetButtonState('edit', true);
this.SetButtonState('delete', true);
this.InEditing = false;
}
MultiInputControl.prototype.ShowRecord = function($record_index) {
var $options = this.getControl(this.FieldName, 'minput').options;
if ($record_index < $options.length) {
// update existing record
$options[$record_index].innerHTML = this.formatLine($record_index);
}
else {
// create new record
var $new_option = document.createElement('OPTION');
$options.add($new_option, $options.length);
$new_option.value = $record_index; // will be used in move up/down & sorting (if any)
$new_option.innerHTML = this.formatLine($record_index);
}
}
MultiInputControl.prototype.DeleteRecords = function() {
if (!confirm(this.Messages['delete_confirm'])) {
return ;
}
var $control = this.getControl(this.FieldName, 'minput');
var $i = $control.length - 1;
while ($i >= 0) {
if ($control.options[$i].selected == true) {
this.Records.splice($i, 1);
$control.remove($i);
}
$i--;
}
this.SaveValues();
}
MultiInputControl.prototype.AddFromXML = function($xml) {
var $document = getDocumentFromXML($xml);
this.ProcessXMLNode($document);
}
MultiInputControl.prototype.ProcessXMLNode = function($node, $root_name) {
for (var $i = 0; $i < $node.childNodes.length; $i++) {
var $child = $node.childNodes.item($i);
if ($child.tagName == 'record') {
this.Records[this.Records.length] = new Array ();
this.ProcessXMLNode($child, $root_name);
this.ShowRecord(this.Records.length - 1);
}
else if ($child.tagName == 'field') {
if ($root_name == 'records') {
this.Records[this.Records.length - 1][$child.getAttribute('name')] = $child.firstChild.nodeValue;
}
else if ($root_name == 'errors') {
this.Errors[$child.getAttribute('name')] = $child.firstChild.nodeValue;
}
}
else if ($child.tagName == 'records') {
this.ProcessXMLNode($child, $child.tagName);
}
else if ($child.tagName == 'errors') {
this.Errors = new Array ();
this.ProcessXMLNode($child, $child.tagName);
}
}
}
MultiInputControl.prototype.LoadValues = function() {
var $current_value = this.getControl(this.FieldName).value;
if ($current_value) {
this.AddFromXML($current_value);
}
}
MultiInputControl.prototype.SaveValues = function() {
var $i = 0;
var $xml = '';
while ($i < this.Records.length) {
$xml += '<record>';
for (var $field_name in this.Controls) {
- $xml += '<field name="' + $field_name + '">' + this.Records[$i][$field_name] + '</field>';
+ $xml += '<field name="' + $field_name + '">' + this.htmlspecialchars(this.Records[$i][$field_name]) + '</field>';
}
$xml += '</record>';
$i++;
}
this.getControl(this.FieldName).value = $xml ? '<records>' + $xml + '</records>' : '';
}
+MultiInputControl.prototype.htmlspecialchars = function (string) {
+ string = string.replace(/&/g, '&amp;');
+ string = string.replace(/</g, '&lt;');
+ string = string.replace(/>/g, '&gt;');
+ string = string.replace(/\"/g, '&quot;');
+
+ return string;
+}
+
MultiInputControl.prototype.prepareRecord = function() {
var $record = new Array ();
for (var $field_name in this.Controls) {
$record[$field_name] = this.getControlValue($field_name);
}
return $record;
}
MultiInputControl.prototype.ValidateRecord = function($record, $skip_index) {
var $valid = true;
$valid = $valid && this.ValidateRequired($record);
$valid = $valid && this.ValidateUnique($record, $skip_index);
return $valid;
}
MultiInputControl.prototype.ValidateRequired = function($record) {
for (var $field_name in $record) {
if (this.Controls[$field_name]['required'] && !$record[$field_name]) {
alert(this.Messages['required_error']);
return false;
}
}
return true;
}
MultiInputControl.prototype.compareRecords = function($record_a, $record_b) {
var $equals = true;
for (var $field_name in $record_a) {
if ($record_a[$field_name] !== $record_b[$field_name]) {
return false;
}
}
return $equals;
}
MultiInputControl.prototype.ValidateUnique = function($record, $skip_index) {
var $i = 0;
if (!isset($skip_index)) {
$skip_index = -1;
}
while ($i < this.Records.length) {
if ($i != $skip_index && this.compareRecords($record, this.Records[$i])) {
alert(this.Messages['unique_error']);
return false;
}
$i++;
}
return true;
}
MultiInputControl.prototype.displayErrors = function() {
var $has_errors = false;
var $field_label = '';
for (var $field_name in this.Errors) {
$has_errors = true;
alert(this.FieldLabels[$field_name] + ': ' + this.Errors[$field_name]);
}
return $has_errors;
}
MultiInputControl.prototype.successCallback = function($request, $params, $object) {
if (Request.processRedirect($request) === true) {
return ;
}
var $document = getDocumentFromXML($request.responseText);
$object.ProcessXMLNode($document);
if ($object.displayErrors()) {
return ;
}
switch ($params[0]) {
case 'AddRecord':
if (!$object.ValidateRecord($params[1])) {
return ;
}
$object.Records.push($params[1]);
$object.ShowRecord($object.Records.length - 1);
$object.ResetControls();
break;
case 'SaveRecord':
if (!$object.ValidateRecord($params[1], $params[2])) {
return ;
}
$object.Records[$params[2]] = $params[1];
$object.ShowRecord($params[2]);
$object.CancelEditing();
break;
}
$object.SaveValues();
}
MultiInputControl.prototype.errorCallback = function($request, $params, $object) {
alert('AJAX Error; class: MultiInputControl; ' + Request.getErrorHtml($request));
}
MultiInputControl.prototype.SetMessage = function($pseudo, $message) {
this.Messages[$pseudo] = $message;
}
MultiInputControl.prototype.InitEvents = function() {
var $button = null;
var $var_name = this.FieldName;
$button = this.getControl(this.FieldName, 'add_button');
$button.onclick = function() { eval($var_name).AddRecord() };
if (this.hasPermission('add') || this.hasPermission('edit')) {
$button = this.getControl(this.FieldName, 'cancel_button');
$button.onclick = function() { eval($var_name).CancelEditing() };
}
if (this.hasPermission('edit')) {
$button = this.getControl(this.FieldName, 'edit_button');
$button.onclick = function() { eval($var_name).EditRecord() };
$button = this.getControl(this.FieldName, 'minput');
$button.ondblclick = function() { eval($var_name).EditRecord() };
}
if (this.hasPermission('delete')) {
$button = this.getControl(this.FieldName, 'delete_button');
$button.onclick = function() { eval($var_name).DeleteRecords() };
}
}
MultiInputControl.prototype.hasPermission = function ($perm_name) {
return in_array($perm_name, this.Permissions);
}
MultiInputControl.prototype.SetPermission = function ($perm_name, $perm_value) {
var $perm_index = array_search($perm_name, this.Permissions);
if ($perm_index != -1) {
// permission found
if (!$perm_value) {
this.Permissions = this.Permissions.splice($perm_index, 1);
}
}
else if ($perm_value) {
// permission not found
this.Permissions.push($perm_name);
}
}
MultiInputControl.prototype.SetButtonState = function ($button, $mode) {
if (!this.hasPermission($button)) {
return ;
}
var $button = this.getControl(this.FieldName, $button + '_button');
$button.disabled = !$mode;
$button.className = $mode ? 'button' : 'button-disabled';
}
// =======================================================================================
function EditPickerControl($field_name, $field_mask) {
this.FieldName = $field_name;
this.FieldMask = $field_mask;
this.Messages = new Array ();
this.InitEvents();
select_sort( this.getControl('available') );
}
EditPickerControl.prototype.getControl = function ($type) {
var $control_id = this.FieldMask + (isset($type) ? '_' + $type : '');
return document.getElementById($control_id);
}
EditPickerControl.prototype.SetMessage = function ($pseudo, $message) {
this.Messages[$pseudo] = $message;
}
EditPickerControl.prototype.SaveValues = function () {
this.getControl().value = select_to_string(this.getControl('selected'));
this.getControl('available_field').value = select_to_string(this.getControl('available'));
}
EditPickerControl.prototype.MoveLeft = function () {
move_selected(this.getControl('available'), this.getControl('selected'), this.Messages['nothing_selected']);
this.SaveValues();
}
EditPickerControl.prototype.MoveRight = function () {
move_selected(this.getControl('selected'), this.getControl('available'), this.Messages['nothing_selected']);
select_sort( this.getControl('available') );
this.SaveValues();
}
EditPickerControl.prototype.InitEvents = function() {
var $button = null;
var $var_name = this.FieldName;
$button = this.getControl('move_left_button');
$button.onclick = function() { eval($var_name).MoveLeft() };
$button = this.getControl('move_right_button');
$button.onclick = function() { eval($var_name).MoveRight() };
}
\ No newline at end of file
Property changes on: branches/RC/core/admin_templates/js/form_controls.js
___________________________________________________________________
Modified: cvs2svn:cvs-rev
## -1 +1 ##
-1.1.8.1
\ No newline at end of property
+1.1.8.2
\ No newline at end of property

Event Timeline