';
+ return $treeStr;
+
+ }
+
+ // I can't seem to do recursion in smarty, and recursive templates seems a bad solution.
+ // Come up with a better way to do this (? NBM)
+ function _evilTreeRenderer($treeToRender, $inputname) {
+ //global $default;
+ $treeStr = "";
+ $stack = array();
+ $exitstack = array();
+
+ // since the root is virtual, we need to fake it here.
+ // the inner section is generised.
+ $treeStr .= '
';
+ return $treeStr;
+
+ }
+
+ // I can't seem to do recursion in smarty, and recursive templates seems a bad solution.
+ // Come up with a better way to do this (? NBM)
+ function _evilTreeRenderer($treeToRender) {
+ //global $default;
+ $treeStr = "";
+ $stack = array();
+ $exitstack = array();
+
+ // since the root is virtual, we need to fake it here.
+ // the inner section is generised.
+ $treeStr .= '
';
+
+ return $treeStr;
+ }
+
+ // don't hate me.
+ function _evilActionHelper($iFieldId, $bIsKeyword, $current_node) {
+ $actionStr = " (";
+ if ($bIsKeyword === true) {
+ $actionStr .= 'unlink';
+ }
+ else
+ {
+ $actionStr .= 'add items ';
+ $actionStr .= '| delete';
+ }
+ $actionStr .= ")";
+ return $actionStr;
+ }
+
+}
+
+$oDispatcher = new ManageLookupTreeDispatcher();
+$oDispatcher->dispatch();
+
+?>
diff --git a/presentation/lookAndFeel/knowledgeTree/handleConditional.php b/presentation/lookAndFeel/knowledgeTree/handleConditional.php
new file mode 100644
index 0000000..87fde05
--- /dev/null
+++ b/presentation/lookAndFeel/knowledgeTree/handleConditional.php
@@ -0,0 +1,287 @@
+ rows.
+
+ $oFieldSet = DocumentFieldSet::get($fieldset_id);
+ if (empty($active_fields)) {
+ $res = $this->getMasterFieldInfo($oFieldSet);
+ $fieldsToRender[$oFieldSet->getMasterField()] = $res;
+ } else {
+ // urgh. we use this to generate our list of things to extract from the input.
+ $pairings = array();
+ foreach ($active_fields as $field_id) {
+ $current = KTUtil::arrayGet($_REQUEST, 'conditional_field_'.$field_id);
+ if ($current === null) {
+ return 'invalid input sequence.';
+ }
+ else {
+ $pairings[$field_id] = $current;
+ }
+
+ }
+ $res = $this->validatePath($oFieldSet, $pairings, true);
+ if ($res === true) {
+ return 'validated input.';
+ }
+ else if ($res === false) {
+ return 'invalid input';
+ }
+ // quick collation process.
+ foreach ($res as $aRow) {
+ $fieldsToRender[$aRow["document_field_id"]][] = $aRow;
+ }
+ }
+
+ $default->log->debug('validatePath: results '.print_r($fieldsToRender,true));
+
+ $oTemplating = new KTTemplating;
+
+ $oTemplate = $oTemplating->loadTemplate("ktcore/handle_conditional");
+ $aTemplateData = array(
+ "fieldset" => $oFieldSet->getId(),
+ "oldfields" => $pairings,
+ "fieldsToRender" => $fieldsToRender,
+ );
+ return $oTemplate->render($aTemplateData);
+ }
+
+ function handleOutput($data) {
+ print $data;
+ }
+
+ function getMasterFieldInfo($oFieldSet) {
+ global $default;
+ $masterField = $oFieldSet->getMasterField();
+ $sQuery = "SELECT md_cond.document_field_id AS document_field_id, md_cond.metadata_lookup_id AS val, md_lookup.name AS name FROM $default->md_condition_table AS md_cond LEFT JOIN $default->md_condition_chain_table AS md_chain ON (md_cond.id = md_chain.child_condition) LEFT JOIN $default->metadata_table AS md_lookup ON (md_cond.metadata_lookup_id = md_lookup.id) WHERE md_cond.document_field_id = ? ";
+ return DBUtil::getResultArray(array($sQuery, array($masterField)));
+ }
+
+ // either returns the set of pathid's for the input,
+ // or false (FIXME: should be PEAR::raiseError)
+ function validatePath($oFieldSet, $aPairings, $bPartial) {
+ /* An explanation of what happens below, since NBM's comment was "Put that crack-pipe back in the freezer."
+ *
+ * $aPairings are the inputs we were handed. Within these, there are 3
+ * important things:
+ * 1. we have a limited set of document_fields within the $oFieldSet.
+ * 2. one of these fields is the "master field" - the _ONLY_ one without
+ * any parent conditions.
+ * 3. some fields may get passed _out_ as
+ * which indicates that there is NO VALUE for that field (again, saved in the db as "-1" so we don't go mad.
+ *
+ * We essentially have 3 stacks: inputs, parent_conditions, free_field_ids
+ *
+ * $bPartial indicates what we need to do once we've run out of inputs to validate: either fail (if we don't have coverage, and its not partial)
+ * or return the possible next choices.
+ *
+ * We start with the master-field, and get its entry in the table. If it isn't there, fail.
+ * i. push its field onto the "parent_conditions" stack, and remove the field_id from the "option_fields".
+ * ii. remove its entry from the inputs.
+ * While we have inputs ->
+ * find any matches that have a (field_id, lookup_id) in the input set, and parent_condition in the parent_conditions stack.
+ * if no values found, FAIL - invalid input (we can't match what we've been given).
+ * otherwise ->
+ * remove them from the input stack, push their id's onto the parent_condition stack, and remove their field_id's from the field_id stack.
+ * If $bPartial == true ->
+ * get anything which has a parent_condition in the parent_condition set, and a field_id in the free_field_id's set -> this will give you
+ * the next set of "inputs" - (column, lookup) pairs with parent-rules that have been activated.
+ * If $bPartial == false and free_field_id's still has anything in it WE FAIL OUT.
+ */
+ global $default;
+ $free_field_ids = array();
+ $parent_conditions = array();
+ $inputs = $aPairings; // please tell me this does a copy ...
+
+ // step 1: generate free_field_ids.
+ $childFields = DocumentField::getList('parent_fieldset = '.$oFieldSet->getId());
+ foreach ($childFields as $oField) {
+ $free_field_ids[$oField->getId()] = 1; // placeholder.
+ }
+ $master_field = $oFieldSet->getMasterField(); // this is the id of the master field.
+ if (!array_key_exists($master_field, $inputs)) {
+ return false; // no master field in the input.
+ }
+
+ // step 2: get the first parent, to get the ball rolling.
+ $sQuery = "SELECT * FROM $default->md_condition_table WHERE document_field_id = ? and metadata_lookup_id = ? ";
+ $aParams = array($master_field, $inputs[$master_field]);
+ $res = DBUtil::getOneResult(array($sQuery, $aParams));
+
+ if (PEAR::isError($res)) {
+ return false; // no value matched on the master field input, the rest MUST fail.
+ }
+ else {
+ unset($free_field_ids[$master_field]); // master is no longer free.
+ $rule_id = $res["id"];
+ $parent_conditions[$rule_id] = 1;
+ unset($inputs[$master_field]);
+ }
+
+ $default->log->debug('validatePath: parent_conditions '.print_r($parent_conditions,true));
+
+
+ while (count($inputs) != 0) { // we'll return out inside here if necessary.
+ // check for items in inputs, with parents in parent_conditions.
+
+ // $testStr = "";
+ // $testarr = array();
+ // for ($i=0; $i<3; $i++) {
+ // $testarr[] = "( ? )";
+ // }
+ // $testStr = "(".join(" OR ", $testarr).")";
+ // return $testStr;
+
+ // we need something like "parent_conditions IN (1,2,3) AND ((f=1 AND v=2) OR (f=2 AND v=5) OR (f=4 AND v=7))
+ $sParentClause = "md_chain.parent_condition IN (";
+ $aInputParts = array();
+ for ($i=0; $i $lookid) {
+ $aInputs[] = $fid;
+ $aInputs[] = $lookid;
+ $aInputParts[] = '(md_cond.document_field_id = ? AND md_cond.metadata_lookup_id = ?)';
+ }
+ $sInputs = join(" OR ", $aInputParts);
+ $sInputs = '(' . $sInputs . ')';
+
+
+ $default->log->debug('validatePath: parent_conditions '.print_r($parent_conditions,true));
+
+ $sFieldClause = "md_cond.document_field_id IN (";
+ for ($i=0; $ilog->debug('validatePath: sParentClause '.print_r($sParentClause,true));
+
+ $sWhere = KTUtil::whereToString(array(array($sParentClause, array_keys($parent_conditions)), array($sInputs, $aInputs)));
+ $sQuery = "SELECT md_cond.id as rule_id, md_cond.document_field_id AS field_id FROM $default->md_condition_table AS md_cond LEFT JOIN $default->md_condition_chain_table AS md_chain ON (md_cond.id = md_chain.child_condition) WHERE ";
+ $default->log->debug('validatePath: '.print_r(array($sQuery . $sWhere[0], $sWhere[1]),true));
+ $res = DBUtil::getResultArray(array($sQuery . $sWhere[0], $sWhere[1]));
+ if (PEAR::isError($res)) {
+ return false;
+ }
+
+ // if there's anything is $res, its a match (must be - we can't have crossed chains.)
+ if (count($res) == 0) {
+ return false; // fail - no matches from inputs against parent_conditions.
+ } else {
+ // we must have a match - MAY have multiple matches.
+ foreach ($res as $aRow) {
+ $default->log->debug('validatePath: output_row '.print_r($aRow,true));
+ $parent_conditions[$aRow["rule_id"]] = 1; // add this as a possible parent condition.
+ unset($free_field_ids[$aRow["field_id"]]); // no longer free
+ unset($inputs[$aRow["field_id"]]); // no longer an un-processed input, so reduce the input-count.
+ }
+ }
+ }
+
+ // ok: we got this far, and have run out of inputs without running out of matches.
+ // IF we're looking for a partial match, and still have free fields, return the set of free-and-parent matches.
+ // OTHERWISE if we have free fields, fail
+ // finally, pass the input as valid.
+
+ if (($bPartial === true) and (count($free_field_ids) > 0)) {
+ // generate the set of matches for free_fields with appropriate parents.
+ // UNFORTUNATELY, there is no "nice" way to do this.
+ // Wax On. Wax Off.
+
+ $sParentClause = "md_chain.parent_condition IN (";
+ for ($i=0; $ilog->debug('validatePath: parent_conditions '.print_r($parent_conditions,true));
+
+ $sFieldClause = "md_cond.document_field_id IN (";
+ for ($i=0; $ilog->debug('validatePath: sParentClause '.print_r($sParentClause,true));
+
+ $aWhere = KTUtil::whereToString(array(array($sParentClause, array_keys($parent_conditions)), array($sFieldClause,array_keys($free_field_ids))));
+ $sQuery = "SELECT md_cond.document_field_id AS document_field_id, md_cond.metadata_lookup_id AS val, md_lookup.name as name FROM $default->md_condition_table AS md_cond LEFT JOIN $default->md_condition_chain_table AS md_chain ON (md_cond.id = md_chain.child_condition) LEFT JOIN $default->metadata_table AS md_lookup ON (md_cond.metadata_lookup_id = md_lookup.id) WHERE ";
+ $default->log->debug('validatePath: sParentClause '.print_r(array($sQuery . $aWhere[0], $aWhere[1]), true));
+ $sOrderClause = " ORDER BY document_field_id ASC, name ASC";
+ return DBUtil::getResultArray(array($sQuery . $aWhere[0] . $sOrderClause, $aWhere[1])); // FIXME catch errors?
+ } else if (count($free_field_ids) != 0) {
+ return false; // incomplete - could actually catch this at the start.
+ } else {
+ return true; // note - this ALSO matches whenever $bPartial is true, but we have completed. UP THE STACK: true => valid and committable.
+ }
+ }
+
+ // FIXME: this need s to move into MDCondition.inc, or manageConditionalMetadata.php
+ // actually, this needs to die - its DEBUG only, really.
+ function do_createCondition() {
+ global $default;
+ $fieldset_id = KTUtil::arrayGet($_REQUEST, 'fieldset_id');
+ $parent_id = KTUtil::arrayGet($_REQUEST, 'parent_id');
+ $field_id = KTUtil::arrayGet($_REQUEST, 'field_id');
+ $lookup_id = KTUtil::arrayGet($_REQUEST, 'lookup_id');
+
+ $resObj = MDConditionNode::createFromArray(array(
+ "iFieldId" => $field_id,
+ "iLookupId" => $lookup_id,
+ ));
+
+ $default->log->debug("CREATE_CONDITION_DEBUG: ".print_r($resObj,true));
+
+ $resObj2 = MDConditionChain::createFromArray(array(
+ "iParentCondition" => $parent_id, // may be null.
+ "iChildCondition" => $resObj->getId(),
+ ));
+
+ $default->log->debug("CREATE_CONDITION_DEBUG: ".print_r($resObj2,true));
+ }
+
+}
+
+$oDispatcher = new HandleConditionalDispatcher();
+$oDispatcher->dispatch();
+
+?>