From d10ad037a311d7aa39ff815d4ccc1eefb4b83283 Mon Sep 17 00:00:00 2001
From: Kevin Fourie
Date: Mon, 21 Jan 2008 19:43:23 +0000
Subject: [PATCH] Merge of Bryn Divey's work on Conditional Metadata into DEV branch.
---
lib/metadata/fieldsetregistry.inc.php | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
plugins/ktcore/KTCorePlugin.php | 2 ++
plugins/ktcore/KTWidgets.php | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
plugins/ktcore/admin/fieldsets/conditional.inc.php | 10 ++++++++++
resources/js/conditional_selection.js | 172 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
templates/ktcore/forms/widgets/conditional_selection.smarty | 28 ++++++++++++++++++++++++++++
templates/ktcore/metadata/conditional/conditional_admin_overview.smarty | 24 ------------------------
templates/ktcore/metadata/conditional/manageConditional.smarty | 30 +-----------------------------
8 files changed, 443 insertions(+), 62 deletions(-)
create mode 100755 resources/js/conditional_selection.js
create mode 100755 templates/ktcore/forms/widgets/conditional_selection.smarty
diff --git a/lib/metadata/fieldsetregistry.inc.php b/lib/metadata/fieldsetregistry.inc.php
index 7baeab1..4475318 100644
--- a/lib/metadata/fieldsetregistry.inc.php
+++ b/lib/metadata/fieldsetregistry.inc.php
@@ -97,12 +97,53 @@ class KTFieldsetRegistry {
// FIXME delegate.
$oFieldset =& $fieldsetOrType;
- if ($oFieldset->getIsConditional()) {
- return PEAR::raiseError(_kt("Conditional Fieldsets are not yet implemented"));
- } else {
+
$widgets = array();
$fields = $oFieldset->getFields();
+ if ($oFieldset->getIsConditional()) {
+ $iMasterId = $oFieldset->getMasterFieldId();
+
+ $oMasterField = DocumentField::get($iMasterId);
+
+ $newfields = array();
+ $newfields[] = $oMasterField;
+ foreach($fields as $oField) {
+ if($oField->getId() != $iMasterId) {
+ $newfields[] = $oField;
+ }
+ }
+
+ foreach ($newfields as $oField) {
+ $fname = 'metadata_' . $oField->getId();
+ $value = null;
+
+ if (!is_null($oDocument)) {
+ $oFL = DocumentFieldLink::getByDocumentAndField($oDocument, $oField);
+ if (!is_null($oFL) && (!PEAR::isError($oFL))) {
+ $value = $oFL->getValue();
+ }
+ }
+
+ $widgets[] = $this->oWF->get('ktcore.widgets.conditionalselection',
+ array(
+ 'label' => $oField->getName(),
+ 'required' => $oField->getIsMandatory(),
+ 'name' => $fname,
+ 'value' => $value,
+ 'description' => $oField->getDescription(),
+ 'vocab' => MetaData::getEnabledByDocumentField($oField),
+ 'id_method' => 'getName',
+ 'label_method' => 'getName',
+ 'unselected_label' => _kt("No selection."),
+ 'simple_select' => false,
+ 'master' => ($oField->getId() == $iMasterId),
+ 'masterid' => $iMasterId,
+ 'fieldset' => $oFieldset->getId(),
+ 'field' => $oField->getId(),
+ ));
+ }
+ } else {
foreach ($fields as $oField) {
$fname = 'metadata_' . $oField->getId();
@@ -165,13 +206,17 @@ class KTFieldsetRegistry {
}
}
- return array($this->oWF->get('ktcore.widgets.fieldset',array(
+
+ }
+
+ return array($this->oWF->get('ktcore.widgets.fieldset',
+ array(
'label' => $oFieldset->getName(),
'description' => $oFieldset->getDescription(),
'name' => $sContainerName,
'widgets' => $widgets,
)));
- }
+
}
@@ -184,7 +229,26 @@ class KTFieldsetRegistry {
// FIXME delegate.
$oFieldset =& $fieldsetOrType;
if ($oFieldset->getIsConditional()) {
- return PEAR::raiseError(_kt("Conditional Fieldsets are not yet implemented"));
+ $validators = array();
+ $fields = $oFieldset->getFields();
+
+ if ($bIncludeAuto) {
+ $widgets = $this->widgetsForFieldset($oFieldset, $sContainerName, $sDocument);
+ $validators = kt_array_merge($validators, $widgets[0]->getValidators());
+ }
+
+ foreach ($fields as $oField) {
+ $fname = 'metadata_' . $oField->getId();
+
+ // Change back to 'membership'
+ $validators[] = $this->oVF->get('ktcore.validators.membership',
+ array(
+ 'test' => $fname,
+ 'output' => $fname,
+ 'vocab' => MetaData::getEnabledValuesByDocumentField($oField),
+ 'id_method' => 'getName',
+ ));
+ }
} else {
$validators = array();
$fields = $oFieldset->getFields();
@@ -243,13 +307,14 @@ class KTFieldsetRegistry {
}
}
- return array($this->oVF->get('ktcore.validators.fieldset',array(
+ }
+ return array($this->oVF->get('ktcore.validators.fieldset',
+ array(
'test' => $sContainerName,
'output' => $sContainerName,
'validators' => $validators,
)));
}
}
-}
?>
diff --git a/plugins/ktcore/KTCorePlugin.php b/plugins/ktcore/KTCorePlugin.php
index 3e4b597..5e59514 100644
--- a/plugins/ktcore/KTCorePlugin.php
+++ b/plugins/ktcore/KTCorePlugin.php
@@ -181,6 +181,8 @@ class KTCorePlugin extends KTPlugin {
$this->registerWidget('KTDescriptorSelectionWidget', 'ktcore.widgets.descriptorselection', 'KTWidgets.php');
$this->registerWidget('KTCoreFolderCollectionWidget', 'ktcore.widgets.foldercollection', 'KTWidgets.php');
+ $this->registerWidget('KTCoreConditionalSelectionWidget', 'ktcore.widgets.conditionalselection', 'KTWidgets.php');
+
$this->registerPage('collection', 'KTCoreCollectionPage', 'KTWidgets.php');
$this->registerPage('notifications', 'KTNotificationOverflowPage', 'KTMiscPages.php');
diff --git a/plugins/ktcore/KTWidgets.php b/plugins/ktcore/KTWidgets.php
index ce22ff3..3226c47 100644
--- a/plugins/ktcore/KTWidgets.php
+++ b/plugins/ktcore/KTWidgets.php
@@ -767,4 +767,160 @@ class KTCoreCollectionPage extends KTStandardDispatcher {
}
-?>
+
+// based on the selection widget, this carries a mapping array,
+// which is converted to JSON and inserted into the output. javascript
+// enforces the various relationships between conditional fields.
+
+class KTCoreConditionalSelectionWidget extends KTCoreSelectionWidget {
+ var $sNamespace = 'ktcore.widgets.conditionalselection';
+
+ var $sIdMethod;
+ var $sLabelMethod;
+
+ var $bIsMaster;
+ var $bMappings;
+
+ function _getFieldIdForMetadataId($iMetadata) {
+ $sTable = 'metadata_lookup';
+ $sQuery = "SELECT document_field_id FROM " . $sTable . " WHERE id = ?";
+ $aParams = array($iMetadata);
+
+ $res = DBUtil::getOneResultKey(array($sQuery, $aParams), 'document_field_id');
+ if (PEAR::isError($res)) {
+ return false;
+ }
+ return $res;
+ }
+
+
+ function configure($aOptions) {
+ $res = parent::configure($aOptions);
+ if (PEAR::isError($res)) {
+ return $res;
+ }
+
+ $this->sIdMethod = KTUtil::arrayGet($aOptions, 'id_method', 'getId');
+ $this->sLabelMethod = KTUtil::arrayGet($aOptions, 'label_method');
+ if (empty($this->sLabelMethod)) {
+ return PEAR::raiseError(_kt('No label method specified.'));
+ }
+ $existing_entities = (array) KTUtil::arrayGet($aOptions, 'existing_entities');
+
+ if (empty($this->value)) {
+ $this->value = array();
+ foreach ($existing_entities as $oEntity) {
+ $this->value[] = call_user_func(array(&$oEntity, $this->sIdMethod));
+ }
+ }
+
+ $this->iField = KTUtil::arrayGet($aOptions, 'field');
+ $this->iMasterId = KTUtil::arrayGet($aOptions, 'masterid');
+
+ // if we're the master, we have to build the dependancy array and store it as JSON
+ // also, include the javascript
+ if(KTUtil::arrayGet($aOptions, 'master', false)) {
+ $this->bMaster = true;
+ $this->aJavascript = array('resources/js/conditional_selection.js');
+
+ $oFieldset = KTFieldset::get(KTUtil::arrayGet($aOptions, 'fieldset'));
+ $aLookups = array();
+ $aConnections = array();
+
+ foreach($oFieldset->getFields() as $oField) {
+ $c = array();
+
+ foreach($oField->getEnabledValues() as $oMetadata) {
+ $a = array();
+ // print '';
+
+ $nvals = KTMetadataUtil::getNextValuesForLookup($oMetadata->getId());
+ if($nvals) {
+ foreach($nvals as $i=>$aVals) {
+ $a = array_merge($a, $aVals);
+
+ foreach($aVals as $id) {
+ $field = $this->_getFieldIdForMetadataId($id);
+ // print 'id ' . $id . ' is in field ' . $field . " ";
+ if(!in_array($field, $c)) {
+ $c[] = $field;
+ }
+ }
+ }
+ }
+
+ $aLookups[$oMetadata->getId()] = $a;
+ }
+ $aConnections[$oField->getId()] = $c;
+ }
+
+ //exit(0);
+
+ $oJSON = new Services_JSON;
+ $this->sLookupsJSON = $oJSON->encode($aLookups);
+ $this->sConnectionsJSON = $oJSON->encode($aConnections);
+ }
+
+
+ $new_vocab = array();
+ foreach ($this->aVocab as $oEntity) {
+ $id = call_user_func(array(&$oEntity, $this->sIdMethod));
+ $label = call_user_func(array(&$oEntity, $this->sLabelMethod));
+ $new_vocab[$id] = array($label, $oEntity->getId());
+ }
+ $this->aVocab = $new_vocab;
+ }
+
+ function getWidget() {
+ $bHasErrors = false;
+ if (count($this->aErrors) != 0) { $bHasErrors = true; }
+
+ $this->sTemplate = 'ktcore/forms/widgets/conditional_selection';
+
+ $oTemplating =& KTTemplating::getSingleton();
+ $oTemplate = $oTemplating->loadTemplate($this->sTemplate);
+
+ $unselected = KTUtil::arrayGet($this->aOptions, 'unselected_label');
+ if (!empty($unselected)) {
+ $vocab = array();
+ $vocab[] = $unselected;
+ foreach ($this->aVocab as $k => $v) {
+ $vocab[$k] = $v;
+ }
+ $this->aVocab = $vocab;
+ if (empty($this->value)) {
+ $this->value = '0';
+ }
+ }
+
+ if ($this->bMulti) {
+ $this->_valuesearch = array();
+ $value = (array) $this->value;
+ foreach ($value as $v) {
+ $this->_valuesearch[$v] = true;
+ }
+ }
+
+ $aTemplateData = array(
+ 'context' => $this,
+ 'name' => $this->sName,
+ 'has_id' => ($this->sId !== null),
+ 'id' => $this->sId,
+ 'has_value' => ($this->value !== null),
+ 'value' => $this->value,
+ 'options' => $this->aOptions,
+ 'vocab' => $this->aVocab,
+ 'lookups' => $this->sLookupsJSON,
+ 'connections' => $this->sConnectionsJSON,
+ 'master' => $this->bMaster,
+ 'masterid' => $this->iMasterId,
+ 'field' => $this->iField,
+ );
+ return $oTemplate->render($aTemplateData);
+ }
+
+
+
+}
+
+
diff --git a/plugins/ktcore/admin/fieldsets/conditional.inc.php b/plugins/ktcore/admin/fieldsets/conditional.inc.php
index 6c23ecb..31065f2 100644
--- a/plugins/ktcore/admin/fieldsets/conditional.inc.php
+++ b/plugins/ktcore/admin/fieldsets/conditional.inc.php
@@ -414,6 +414,16 @@ ordering!");
$oField = $data['master_field'];
+ // remove all existing behaviors
+ $aFieldIds = array();
+ foreach($this->oFieldset->getFields() as $i) {
+ $aFieldIds[] = $i->getId();
+ }
+
+ $sTable = KTUtil::getTableName('field_behaviours');
+ $aQuery = array("DELETE FROM $sTable WHERE field_id IN (" . DBUtil::paramArray($aFieldIds) . ")", $aFieldIds);
+ $res = DBUtil::runQuery($aQuery);
+
$res = KTMetadataUtil::removeFieldOrdering($this->oFieldset);
$this->oFieldset->setMasterFieldId($oField->getId());
$res = $this->oFieldset->update();
diff --git a/resources/js/conditional_selection.js b/resources/js/conditional_selection.js
new file mode 100755
index 0000000..df27143
--- /dev/null
+++ b/resources/js/conditional_selection.js
@@ -0,0 +1,172 @@
+// 'lookups' and 'connections' are produced by the master conditional widget
+var NOSELECTION = 'No selection.';
+
+function ConditionalSelection() {
+}
+
+function in_array(a, val) {
+ if(!a.length) {
+ return;
+ }
+ for(var i=0;i
+var lookups_{$masterid} = {$lookups};
+var connections_{$masterid} = {$connections};
+
+{/if}
+
+
+{if empty($vocab)}
+ {$context->sEmptyMessage}
+{else}
+
+ {if $options.initial_string}
+ {$options.initial_string}
+ {/if}
+ {foreach item=lookup key=lookup_key from=$vocab}
+ {if is_array($lookup)}
+ {$lookup.0}
+ {else}
+ {$lookup}
+ {/if}
+ {/foreach}
+
+{/if}
diff --git a/templates/ktcore/metadata/conditional/conditional_admin_overview.smarty b/templates/ktcore/metadata/conditional/conditional_admin_overview.smarty
index 17aeb48..9e7a5eb 100644
--- a/templates/ktcore/metadata/conditional/conditional_admin_overview.smarty
+++ b/templates/ktcore/metadata/conditional/conditional_admin_overview.smarty
@@ -29,30 +29,6 @@ values in the other fields. Only lookup fields can be added to
-
- {i18n}Rename Behaviours{/i18n}
- {i18n}Rename Behaviours{/i18n}
-
-
-{if $oFieldset->getIsComplex()}
-{i18n}The fieldset is currently designated as Complex .{/i18n} {i18n}Changing the conditional type set will remove all existing field
-ordering!{/i18n}
-
-
-{i18n}Change to simple{/i18n}
-{i18n}Change to simple{/i18n}
-
-{else}
-
-{i18n}The fieldset is currently designated as Simple .{/i18n}
-
-{i18n}Change to complex{/i18n}
-{i18n}Change to complex{/i18n}
-
-{/if}
-
diff --git a/templates/ktcore/metadata/conditional/manageConditional.smarty b/templates/ktcore/metadata/conditional/manageConditional.smarty
index c878bc5..3bab28f 100644
--- a/templates/ktcore/metadata/conditional/manageConditional.smarty
+++ b/templates/ktcore/metadata/conditional/manageConditional.smarty
@@ -1,16 +1,11 @@
{i18n}Manage conditional fieldset{/i18n}
{i18n}Conditional fieldsets allow you to restrict the options
-a user has for values in some fields based on the values in other fields. There
-are two kinds of conditional fieldsets: Simple and Complex
-. Simple fieldsets should be sufficient for most things: they allow you to say that
+a user has for values in some fields based on the values in other fields, allowing you to say that
the values of one field are restricted to a certain subset of values if another field
has a specific value. For example, you could say that if the field "Street" is "Jeffrey",
then the field "Residents" must be one of "Jones","Smith" or "Friedman".{/i18n}
-{i18n}Complex fieldsets allow you to give far more detailed structure to
-your information: The value of "Residents" can depend not only on "Street", but on
-how the user was allowed to select the specific street (given another field).{/i18n}
{* don't show warnings until the basics are done. *}
@@ -42,29 +37,6 @@ to complete{/i18n}: {$sIncomplete}
{i18n}Conditional type{/i18n}
-{if $oFieldset->getIsComplex()}
-{i18n}The fieldset is currently designated as Complex {/i18n}
-
-{if ($oMasterField && empty($free_fields))}getId()}">{i18n}Manage
-complex conditional{/i18n}
{/if}
-
-
-
-{else}
-
-{i18n}The fieldset is currently designated as Simple {/i18n}
-
-{if ($oMasterField && empty($free_fields))}getId()}">{i18n}Manage simple conditional{/i18n}
-
-{/if}