Commit 26e9877a353ba216bdc92b4988380d8bded464e1

Authored by Neil Blakey-Milner
1 parent f7807987

Integrate Manage Lookup Trees into document field management.


git-svn-id: https://kt-dms.svn.sourceforge.net/svnroot/kt-dms/trunk@4462 c91229c3-7414-0410-bfa2-8a42b809f60b
plugins/ktcore/admin/documentFields.php
@@ -537,6 +537,206 @@ class KTDocumentFieldDispatcher extends KTStandardDispatcher { @@ -537,6 +537,206 @@ class KTDocumentFieldDispatcher extends KTStandardDispatcher {
537 $this->successRedirectToMain(_('Fieldset deleted')); 537 $this->successRedirectToMain(_('Fieldset deleted'));
538 } 538 }
539 // }}} 539 // }}}
  540 +
  541 +
  542 +// {{{ TREE
  543 + // create and display the tree editing form.
  544 + function do_editTree() {
  545 + global $default;
  546 + // extract.
  547 + $field_id = KTUtil::arrayGet($_REQUEST, 'field_id');
  548 + $current_node = KTUtil::arrayGet($_REQUEST, 'current_node', 0);
  549 + $subaction = KTUtil::arrayGet($_REQUEST, 'subaction');
  550 +
  551 + // validate
  552 + if (empty($field_id)) { return $this->errorRedirectToMain(_("Must select a field to edit.")); }
  553 + $oField =& DocumentField::get($field_id);
  554 + if (PEAR::isError($oField)) { return $this->errorRedirectToMain(_("Invalid field.")); }
  555 +
  556 + // under here we do the subaction rendering.
  557 + // we do this so we don't have to do _very_ strange things with multiple actions.
  558 + //$default->log->debug("Subaction: " . $subaction);
  559 + $fieldTree =& new MDTree();
  560 + $fieldTree->buildForField($oField->getId());
  561 +
  562 + if ($subaction !== null) {
  563 + $target = 'editTree';
  564 + $msg = _('Changes saved.');
  565 + if ($subaction === "addCategory") {
  566 + $new_category = KTUtil::arrayGet($_REQUEST, 'category_name');
  567 + if (empty($new_category)) { return $this->errorRedirectTo("editTree", _("Must enter a name for the new category."), array("field_id" => $field_id)); }
  568 + else { $this->subact_addCategory($field_id, $current_node, $new_category, $fieldTree);}
  569 + $msg = _('Category added'). ': ' . $new_category;
  570 + }
  571 + if ($subaction === "deleteCategory") {
  572 + $this->subact_deleteCategory($fieldTree, $current_node);
  573 + $current_node = 0; // clear out, and don't try and render the newly deleted category.
  574 + $msg = _('Category removed.');
  575 + }
  576 + if ($subaction === "linkKeywords") {
  577 + $keywords = KTUtil::arrayGet($_REQUEST, 'keywordsToAdd');
  578 + $this->subact_linkKeywords($fieldTree, $current_node, $keywords);
  579 + $current_node = 0; // clear out, and don't try and render the newly deleted category.
  580 + $msg = _('Keywords added to category.');
  581 + }
  582 + if ($subaction === "unlinkKeyword") {
  583 + $keyword = KTUtil::arrayGet($_REQUEST, 'keyword_id');
  584 + $this->subact_unlinkKeyword($fieldTree, $keyword);
  585 + $msg = _('Keyword moved to base of tree.');
  586 + }
  587 + // now redirect
  588 + $query = 'field_id=' . $field_id;
  589 + return $this->successRedirectTo($target, $msg, $query);
  590 + }
  591 +
  592 + if ($fieldTree->root === null) {
  593 + return $this->errorRedirectToMain(_("Error building tree. Is this a valid tree-lookup field?"));
  594 + }
  595 +
  596 + // FIXME extract this from MDTree (helper method?)
  597 + $free_metadata = MetaData::getList('document_field_id = '.$oField->getId().' AND (treeorg_parent = 0 OR treeorg_parent IS NULL)');
  598 +
  599 + // render edit template.
  600 + $oTemplating = new KTTemplating;
  601 + $oTemplate = $oTemplating->loadTemplate("ktcore/edit_lookuptrees");
  602 + $renderedTree = $this->_evilTreeRenderer($fieldTree);
  603 +
  604 + $this->oPage->setTitle(_('Edit Lookup Tree'));
  605 +
  606 + //$this->oPage->requireJSResource('thirdparty/js/MochiKit/Base.js');
  607 +
  608 + $aTemplateData = array(
  609 + "field" => $oField,
  610 + "tree" => $fieldTree,
  611 + "renderedTree" => $renderedTree,
  612 + "currentNode" => $current_node,
  613 + "freechildren" => $free_metadata,
  614 + "context" => $this,
  615 + );
  616 + return $oTemplate->render($aTemplateData);
  617 + }
  618 +
  619 + function subact_addCategory($field_id, $current_node, $new_category, &$constructedTree) {
  620 + $newCategory = MDTreeNode::createFromArray(array (
  621 + "iFieldId" => $field_id,
  622 + "sName" => $new_category,
  623 + "iParentNode" => $current_node,
  624 + ));
  625 + if (PEAR::isError($newCategory))
  626 + {
  627 + return false;
  628 + }
  629 + $constructedTree->addNode($newCategory);
  630 + return true;
  631 + }
  632 +
  633 + function subact_deleteCategory(&$constructedTree, $current_node) {
  634 + $constructedTree->deleteNode($current_node);
  635 + return true;
  636 + }
  637 +
  638 + function subact_unlinkKeyword(&$constructedTree, $keyword) {
  639 + $oKW = MetaData::get($keyword);
  640 + $constructedTree->reparentKeyword($oKW->getId(), 0);
  641 + return true;
  642 + }
  643 +
  644 +
  645 + function subact_linkKeywords(&$constructedTree, $current_node, $keywords) {
  646 + foreach ($keywords as $md_id)
  647 + {
  648 + $constructedTree->reparentKeyword($md_id, $current_node);
  649 + }
  650 + return true;
  651 + }
  652 +
  653 + /* ----------------------- EVIL HACK --------------------------
  654 + *
  655 + * This whole thing needs to replaced, as soon as I work out how
  656 + * to non-sucking Smarty recursion.
  657 + */
  658 +
  659 + function _evilTreeRecursion($subnode, $treeToRender)
  660 + {
  661 + $treeStr = "<ul>";
  662 + foreach ($treeToRender->contents[$subnode] as $subnode_id => $subnode_val)
  663 + {
  664 + if ($subnode_id !== "leaves") {
  665 + $treeStr .= '<li class="treenode"><a class="pathnode" onclick="toggleElementClass(\'active\', this.parentNode);">' . $treeToRender->mapnodes[$subnode_val]->getName() . '</a>';
  666 + $treeStr .= $this->_evilActionHelper($treeToRender->field_id, false, $subnode_val);
  667 + $treeStr .= $this->_evilTreeRecursion($subnode_val, $treeToRender);
  668 + $treeStr .= '</li>';
  669 + }
  670 + else
  671 + {
  672 + foreach ($subnode_val as $leaf)
  673 + {
  674 + $treeStr .= '<li class="leafnode">' . $treeToRender->lookups[$leaf]->getName();
  675 + $treeStr .= $this->_evilActionHelper($treeToRender->field_id, true, $leaf);
  676 + $treeStr .= '</li>'; }
  677 + }
  678 + }
  679 + $treeStr .= '</ul>';
  680 + return $treeStr;
  681 +
  682 + }
  683 +
  684 + // I can't seem to do recursion in smarty, and recursive templates seems a bad solution.
  685 + // Come up with a better way to do this (? NBM)
  686 + function _evilTreeRenderer($treeToRender) {
  687 + //global $default;
  688 + $treeStr = "<!-- this is rendered with an unholy hack. sorry. -->";
  689 + $stack = array();
  690 + $exitstack = array();
  691 +
  692 + // since the root is virtual, we need to fake it here.
  693 + // the inner section is generised.
  694 + $treeStr .= '<ul class="kt_treenodes"><li class="treenode"><a class="pathnode" onclick="toggleElementClass(\'active\', this.parentNode);">Root</a>';
  695 + $treeStr .= ' (<a href="?action=editTree&field_id='.$treeToRender->field_id.'&current_node=0">edit</a>)';
  696 + $treeStr .= '<ul>';
  697 + //$default->log->debug("EVILRENDER: " . print_r($treeToRender, true));
  698 + foreach ($treeToRender->getRoot() as $node_id => $subtree_nodes)
  699 + {
  700 + //$default->log->debug("EVILRENDER: ".$node_id." => ".$subtree_nodes." (".($node_id === "leaves").")");
  701 + // leaves are handled differently.
  702 + if ($node_id !== "leaves") {
  703 + // $default->log->debug("EVILRENDER: " . print_r($subtree_nodes, true));
  704 + $treeStr .= '<li class="treenode"><a class="pathnode" onclick="toggleElementClass(\'active\', this.parentNode);">' . $treeToRender->mapnodes[$subtree_nodes]->getName() . '</a>';
  705 + $treeStr .= $this->_evilActionHelper($treeToRender->field_id, false, $subtree_nodes);
  706 + $treeStr .= $this->_evilTreeRecursion($subtree_nodes, $treeToRender);
  707 + $treeStr .= '</li>';
  708 + }
  709 + else
  710 + {
  711 + foreach ($subtree_nodes as $leaf)
  712 + {
  713 + $treeStr .= '<li class="leafnode">' . $treeToRender->lookups[$leaf]->getName();
  714 + $treeStr .= $this->_evilActionHelper($treeToRender->field_id, true, $leaf);
  715 + $treeStr .= '</li>';
  716 + }
  717 + }
  718 + }
  719 + $treeStr .= '</ul></li>';
  720 + $treeStr .= '</ul>';
  721 +
  722 + return $treeStr;
  723 + }
  724 +
  725 + // don't hate me.
  726 + function _evilActionHelper($iFieldId, $bIsKeyword, $current_node) {
  727 + $actionStr = " (";
  728 + if ($bIsKeyword === true) {
  729 + $actionStr .= '<a href="?action=editTree&field_id='.$iFieldId.'&keyword_id='.$current_node.'&subaction=unlinkKeyword">unlink</a>';
  730 + }
  731 + else
  732 + {
  733 + $actionStr .= '<a href="?action=editTree&field_id='.$iFieldId.'&current_node='.$current_node.'">add items</a> ';
  734 + $actionStr .= '| <a href="?action=editTree&field_id='.$iFieldId.'&current_node='.$current_node.'&subaction=deleteCategory">delete</a>';
  735 + }
  736 + $actionStr .= ")";
  737 + return $actionStr;
  738 + }
  739 +// }}}
540 } 740 }
541 741
542 ?> 742 ?>
plugins/ktcore/admin/manageLookupTrees.php deleted
1 -<?php  
2 -  
3 -require_once("../../../../../config/dmsDefaults.php");  
4 -  
5 -  
6 -  
7 -require_once(KT_LIB_DIR . "/templating/templating.inc.php");  
8 -require_once(KT_LIB_DIR . "/templating/kt3template.inc.php");  
9 -  
10 -require_once(KT_LIB_DIR . "/documentmanagement/DocumentField.inc");  
11 -require_once(KT_LIB_DIR . "/documentmanagement/MetaData.inc");  
12 -require_once(KT_LIB_DIR . "/documentmanagement/MDTree.inc");  
13 -require_once(KT_LIB_DIR . "/dispatcher.inc.php");  
14 -  
15 -class ManageLookupTreeDispatcher extends KTAdminDispatcher {  
16 - function do_main() {  
17 - $oTemplating = new KTTemplating;  
18 - $aTreeFields =& DocumentField::getList('has_lookuptree = 1');  
19 - $aLookupFields =& DocumentField::getList('has_lookup = 1 AND (has_lookuptree IS NULL or has_lookuptree = 0)');  
20 - $oTemplate = $oTemplating->loadTemplate("ktcore/manage_lookuptrees");  
21 - $aTemplateData = array(  
22 - "treefields" => $aTreeFields,  
23 - "lookupfields" => $aLookupFields,  
24 - );  
25 - return $oTemplate->render($aTemplateData);  
26 - }  
27 -  
28 - function do_createTree() {  
29 - // extract.  
30 - $field_id = KTUtil::arrayGet($_REQUEST, 'field_id');  
31 -  
32 - // validate  
33 - if (empty($field_id)) { return $this->errorRedirectToMain(_("Must select a field to convert.")); }  
34 - $oField =& DocumentField::get($field_id);  
35 - if (PEAR::isError($oField)) { return $this->errorRedirectToMain(_("Invalid field.")); }  
36 -  
37 - // set as a metadata tree.  
38 - $oField->setHasLookupTree(1);  
39 - $oField->update();  
40 - $this->errorRedirectToMain(sprintf(_("Converted %s to a tree."), $oField->getName()));  
41 - }  
42 -  
43 -  
44 - // create and display the tree editing form.  
45 - function do_editTree() {  
46 - global $default;  
47 - // extract.  
48 - $field_id = KTUtil::arrayGet($_REQUEST, 'field_id');  
49 - $current_node = KTUtil::arrayGet($_REQUEST, 'current_node', 0);  
50 - $subaction = KTUtil::arrayGet($_REQUEST, 'subaction');  
51 -  
52 - // validate  
53 - if (empty($field_id)) { return $this->errorRedirectToMain(_("Must select a field to edit.")); }  
54 - $oField =& DocumentField::get($field_id);  
55 - if (PEAR::isError($oField)) { return $this->errorRedirectToMain(_("Invalid field.")); }  
56 -  
57 - // under here we do the subaction rendering.  
58 - // we do this so we don't have to do _very_ strange things with multiple actions.  
59 - //$default->log->debug("Subaction: " . $subaction);  
60 - $fieldTree =& new MDTree();  
61 - $fieldTree->buildForField($oField->getId());  
62 -  
63 - if ($subaction !== null) {  
64 - $target = 'editTree';  
65 - $msg = _('Changes saved.');  
66 - if ($subaction === "addCategory") {  
67 - $new_category = KTUtil::arrayGet($_REQUEST, 'category_name');  
68 - if (empty($new_category)) { return $this->errorRedirectTo("editTree", _("Must enter a name for the new category."), array("field_id" => $field_id)); }  
69 - else { $this->subact_addCategory($field_id, $current_node, $new_category, $fieldTree);}  
70 - $msg = _('Category added'). ': ' . $new_category;  
71 - }  
72 - if ($subaction === "deleteCategory") {  
73 - $this->subact_deleteCategory($fieldTree, $current_node);  
74 - $current_node = 0; // clear out, and don't try and render the newly deleted category.  
75 - $msg = _('Category removed.');  
76 - }  
77 - if ($subaction === "linkKeywords") {  
78 - $keywords = KTUtil::arrayGet($_REQUEST, 'keywordsToAdd');  
79 - $this->subact_linkKeywords($fieldTree, $current_node, $keywords);  
80 - $current_node = 0; // clear out, and don't try and render the newly deleted category.  
81 - $msg = _('Keywords added to category.');  
82 - }  
83 - if ($subaction === "unlinkKeyword") {  
84 - $keyword = KTUtil::arrayGet($_REQUEST, 'keyword_id');  
85 - $this->subact_unlinkKeyword($fieldTree, $keyword);  
86 - $msg = _('Keyword moved to base of tree.');  
87 - }  
88 - // now redirect  
89 - $query = 'field_id=' . $field_id;  
90 - return $this->successRedirectTo($target, $msg, $query);  
91 - }  
92 -  
93 - if ($fieldTree->root === null) {  
94 - return $this->errorRedirectToMain(_("Error building tree. Is this a valid tree-lookup field?"));  
95 - }  
96 -  
97 - // FIXME extract this from MDTree (helper method?)  
98 - $free_metadata = MetaData::getList('document_field_id = '.$oField->getId().' AND (treeorg_parent = 0 OR treeorg_parent IS NULL)');  
99 -  
100 - // render edit template.  
101 - $oTemplating = new KTTemplating;  
102 - $oTemplate = $oTemplating->loadTemplate("ktcore/edit_lookuptrees");  
103 - $renderedTree = $this->_evilTreeRenderer($fieldTree);  
104 -  
105 - $this->oPage->setTitle(_('Edit Lookup Tree'));  
106 -  
107 - //$this->oPage->requireJSResource('thirdparty/js/MochiKit/Base.js');  
108 -  
109 - $aTemplateData = array(  
110 - "field" => $oField,  
111 - "tree" => $fieldTree,  
112 - "renderedTree" => $renderedTree,  
113 - "currentNode" => $current_node,  
114 - "freechildren" => $free_metadata,  
115 - "context" => $this,  
116 - );  
117 - return $oTemplate->render($aTemplateData);  
118 - }  
119 -  
120 - function subact_addCategory($field_id, $current_node, $new_category, &$constructedTree) {  
121 - $newCategory = MDTreeNode::createFromArray(array (  
122 - "iFieldId" => $field_id,  
123 - "sName" => $new_category,  
124 - "iParentNode" => $current_node,  
125 - ));  
126 - if (PEAR::isError($newCategory))  
127 - {  
128 - return false;  
129 - }  
130 - $constructedTree->addNode($newCategory);  
131 - return true;  
132 - }  
133 -  
134 - function subact_deleteCategory(&$constructedTree, $current_node) {  
135 - $constructedTree->deleteNode($current_node);  
136 - return true;  
137 - }  
138 -  
139 - function subact_unlinkKeyword(&$constructedTree, $keyword) {  
140 - $oKW = MetaData::get($keyword);  
141 - $constructedTree->reparentKeyword($oKW->getId(), 0);  
142 - return true;  
143 - }  
144 -  
145 -  
146 - function subact_linkKeywords(&$constructedTree, $current_node, $keywords) {  
147 - foreach ($keywords as $md_id)  
148 - {  
149 - $constructedTree->reparentKeyword($md_id, $current_node);  
150 - }  
151 - return true;  
152 - }  
153 -  
154 - /* ----------------------- EVIL HACK --------------------------  
155 - *  
156 - * This whole thing needs to replaced, as soon as I work out how  
157 - * to non-sucking Smarty recursion.  
158 - */  
159 -  
160 - function _evilTreeRecursion($subnode, $treeToRender)  
161 - {  
162 - $treeStr = "<ul>";  
163 - foreach ($treeToRender->contents[$subnode] as $subnode_id => $subnode_val)  
164 - {  
165 - if ($subnode_id !== "leaves") {  
166 - $treeStr .= '<li class="treenode"><a class="pathnode" onclick="toggleElementClass(\'active\', this.parentNode);">' . $treeToRender->mapnodes[$subnode_val]->getName() . '</a>';  
167 - $treeStr .= $this->_evilActionHelper($treeToRender->field_id, false, $subnode_val);  
168 - $treeStr .= $this->_evilTreeRecursion($subnode_val, $treeToRender);  
169 - $treeStr .= '</li>';  
170 - }  
171 - else  
172 - {  
173 - foreach ($subnode_val as $leaf)  
174 - {  
175 - $treeStr .= '<li class="leafnode">' . $treeToRender->lookups[$leaf]->getName();  
176 - $treeStr .= $this->_evilActionHelper($treeToRender->field_id, true, $leaf);  
177 - $treeStr .= '</li>'; }  
178 - }  
179 - }  
180 - $treeStr .= '</ul>';  
181 - return $treeStr;  
182 -  
183 - }  
184 -  
185 - // I can't seem to do recursion in smarty, and recursive templates seems a bad solution.  
186 - // Come up with a better way to do this (? NBM)  
187 - function _evilTreeRenderer($treeToRender) {  
188 - //global $default;  
189 - $treeStr = "<!-- this is rendered with an unholy hack. sorry. -->";  
190 - $stack = array();  
191 - $exitstack = array();  
192 -  
193 - // since the root is virtual, we need to fake it here.  
194 - // the inner section is generised.  
195 - $treeStr .= '<ul class="kt_treenodes"><li class="treenode"><a class="pathnode" onclick="toggleElementClass(\'active\', this.parentNode);">Root</a>';  
196 - $treeStr .= ' (<a href="manageLookupTrees.php?action=editTree&field_id='.$treeToRender->field_id.'&current_node=0">edit</a>)';  
197 - $treeStr .= '<ul>';  
198 - //$default->log->debug("EVILRENDER: " . print_r($treeToRender, true));  
199 - foreach ($treeToRender->getRoot() as $node_id => $subtree_nodes)  
200 - {  
201 - //$default->log->debug("EVILRENDER: ".$node_id." => ".$subtree_nodes." (".($node_id === "leaves").")");  
202 - // leaves are handled differently.  
203 - if ($node_id !== "leaves") {  
204 - // $default->log->debug("EVILRENDER: " . print_r($subtree_nodes, true));  
205 - $treeStr .= '<li class="treenode"><a class="pathnode" onclick="toggleElementClass(\'active\', this.parentNode);">' . $treeToRender->mapnodes[$subtree_nodes]->getName() . '</a>';  
206 - $treeStr .= $this->_evilActionHelper($treeToRender->field_id, false, $subtree_nodes);  
207 - $treeStr .= $this->_evilTreeRecursion($subtree_nodes, $treeToRender);  
208 - $treeStr .= '</li>';  
209 - }  
210 - else  
211 - {  
212 - foreach ($subtree_nodes as $leaf)  
213 - {  
214 - $treeStr .= '<li class="leafnode">' . $treeToRender->lookups[$leaf]->getName();  
215 - $treeStr .= $this->_evilActionHelper($treeToRender->field_id, true, $leaf);  
216 - $treeStr .= '</li>';  
217 - }  
218 - }  
219 - }  
220 - $treeStr .= '</ul></li>';  
221 - $treeStr .= '</ul>';  
222 -  
223 - return $treeStr;  
224 - }  
225 -  
226 - // don't hate me.  
227 - function _evilActionHelper($iFieldId, $bIsKeyword, $current_node) {  
228 - $actionStr = " (";  
229 - if ($bIsKeyword === true) {  
230 - $actionStr .= '<a href="manageLookupTrees.php?action=editTree&field_id='.$iFieldId.'&keyword_id='.$current_node.'&subaction=unlinkKeyword">unlink</a>';  
231 - }  
232 - else  
233 - {  
234 - $actionStr .= '<a href="manageLookupTrees.php?action=editTree&field_id='.$iFieldId.'&current_node='.$current_node.'">add items</a> ';  
235 - $actionStr .= '| <a href="manageLookupTrees.php?action=editTree&field_id='.$iFieldId.'&current_node='.$current_node.'&subaction=deleteCategory">delete</a>';  
236 - }  
237 - $actionStr .= ")";  
238 - return $actionStr;  
239 - }  
240 -  
241 -}  
242 -  
243 -$oDispatcher = new ManageLookupTreeDispatcher();  
244 -$oDispatcher->dispatch();  
245 -  
246 -?>  
templates/ktcore/metadata/editField.smarty
@@ -52,7 +52,7 @@ @@ -52,7 +52,7 @@
52 {if $oField->getHasLookup() and $oField->getHasLookupTree()} 52 {if $oField->getHasLookup() and $oField->getHasLookupTree()}
53 {assign var=iFieldId value=$oField->getId()} 53 {assign var=iFieldId value=$oField->getId()}
54 <a 54 <a
55 -href="{"manageLookupTrees"|generateControllerUrl:"action=editTree&field_id=$iFieldId"}">{i18n}Manage 55 +href="?action=editTree&field_id={$iFieldId}">{i18n}Manage
56 lookup tree{/i18n}</a> 56 lookup tree{/i18n}</a>
57 {/if} 57 {/if}
58 58