Commit 4e71de46f9da2abea452e495148dc6371da21a3f

Authored by Brad Shuttleworth
1 parent 397c868c

fix for KTS-60: Column Selection.


git-svn-id: https://kt-dms.svn.sourceforge.net/svnroot/kt-dms/trunk@5639 c91229c3-7414-0410-bfa2-8a42b809f60b
browse.php
... ... @@ -48,6 +48,8 @@ require_once(KT_LIB_DIR . "/permissions/permission.inc.php");
48 48  
49 49 require_once(KT_LIB_DIR . '/users/userhistory.inc.php');
50 50  
  51 +require_once(KT_LIB_DIR . '/browse/columnregistry.inc.php');
  52 +
51 53 /******* NBM's FAMOUS MOVECOLUMN HACK
52 54 *
53 55 * Also in /plugins/ktcore/KTDocumentActions.php
... ... @@ -218,43 +220,18 @@ class BrowseDispatcher extends KTStandardDispatcher {
218 220 }
219 221  
220 222 function do_main() {
221   - $collection = new DocumentCollection;
222   -
223   -
224   - $collection->addColumn(new SelectionColumn("Browse Selection","selection"));
225   - $collection->addColumn(new TitleColumn("Test 1 (title)","title"));
226   - $collection->addColumn(new DownloadColumn('','download'));
227   - $collection->addColumn(new DateColumn(_kt("Created"),"created", "getCreatedDateTime"));
228   - $collection->addColumn(new DateColumn(_kt("Last Modified"),"modified", "getLastModifiedDate"));
229   - $collection->addColumn(new UserColumn(_kt('Creator'),'creator_id','getCreatorID'));
230   - $collection->addColumn(new WorkflowColumn(_kt('Workflow State'),'workflow_state'));
231   -
232   -
233   - // setup the folderside add actions
234   - // FIXME do we want to use folder actions?
235   -
236   - $batchPage = (int) KTUtil::arrayGet($_REQUEST, "page", 0);
237   - $batchSize = 20;
  223 + $collection = new AdvancedCollection;
  224 + $oColumnRegistry = KTColumnRegistry::getSingleton();
  225 + $aColumns = $oColumnRegistry->getColumnsForView('ktcore.views.browse');
  226 + $collection->addColumns($aColumns);
238 227  
  228 + $aOptions = $collection->getEnvironOptions(); // extract data from the environment
239 229  
240   - $collection->setBatching($this->resultURL, $batchPage, $batchSize);
  230 + $aOptions['result_url'] = $this->resultURL;
241 231  
242   -
243   - // ordering. (direction and column)
244   - $displayOrder = KTUtil::arrayGet($_REQUEST, 'sort_order', "asc");
245   - if ($displayOrder !== "asc") { $displayOrder = "desc"; }
246   - $displayControl = KTUtil::arrayGet($_REQUEST, 'sort_on', "title");
247   -
248   -
249   - $collection->setSorting($displayControl, $displayOrder);
250   -
251   - // add in the query object.
252   - $qObj = $this->oQuery;
253   - $collection->setQueryObject($qObj);
254   -
255   - // breadcrumbs
256   - // FIXME handle breadcrumbs
257   - $collection->getResults();
  232 + $collection->setOptions($aOptions);
  233 + $collection->setQueryObject(new BrowseQuery("1", $this->oUser, array('ignorepermissions' => false)));
  234 +
258 235  
259 236 $oTemplating =& KTTemplating::getSingleton();
260 237 $oTemplate = $oTemplating->loadTemplate("kt3/browse");
... ...
docs/VERSION.txt
1   -3.0.3.3
  1 +3.0.3.4
... ...
lib/browse/BrowseColumns.inc.php
... ... @@ -65,9 +65,9 @@ class BrowseColumn {
65 65 $href .= $this->sort_direction = "asc";
66 66 }
67 67  
68   - return '<a href="' . $href . '">'.$text.'</a>';
69   -
  68 + return '<a href="' . $href . '">'.$text.'</a>';
70 69 }
  70 +
71 71 function renderData($aDataRow) {
72 72 if ($aDataRow["type"] == "folder") {
73 73 return $this->name . ": ". print_r($aDataRow["folder"]->getName(), true);
... ...
lib/browse/DocumentCollection.inc.php
... ... @@ -59,7 +59,7 @@ class DocumentCollection {
59 59  
60 60 var $sort_column;
61 61 var $sort_order;
62   -
  62 +
63 63 /* initialisation */
64 64  
65 65 // columns should be added in the "correct" order (e.g. display order)
... ... @@ -240,4 +240,319 @@ class DocumentCollection {
240 240 }
241 241 }
242 242  
  243 +/*
  244 + * Secondary class: AdvancedCollection
  245 + *
  246 + * Handles slightly more details of how the collections should work. Ultimately, this should
  247 + * replace DocumentCollection everywhere
  248 + */
  249 +
  250 +
  251 +class AdvancedCollection {
  252 +
  253 + // handle the sorting, etc.
  254 + var $_sFolderJoinClause = null;
  255 + var $_aFolderJoinParams = null;
  256 + var $_sFolderSortField = null;
  257 + var $_sDocumentJoinClause = null;
  258 + var $_aDocumentJoinParams = null;
  259 + var $_sDocumentSortField = null;
  260 + var $_queryObj = null;
  261 + var $sort_column;
  262 + var $sort_order;
  263 +
  264 + // current documents (in _this_ batch.)
  265 + var $activeset = null;
  266 +
  267 + var $_documentData = array(); // [docid] => array();
  268 + var $_folderData = array(); // [folderid] => array();
  269 + var $columns = array(); // the columns in use
  270 +
  271 + var $returnURL = null;
  272 +
  273 + var $folderCount = 0;
  274 + var $documentCount = 0;
  275 + var $itemCount = 0;
  276 + var $batchStart = 0; // if batch specified a "start".
  277 + var $batchPage = 0;
  278 + var $batchSize = 20; // size of the batch // FIXME make this configurable.
  279 +
  280 + var $aOptions = array();
  281 + var $bShowFolders = true;
  282 + var $bShowDocuments = true;
  283 +
  284 + var $_gotData = false;
  285 + var $_sorted = false;
  286 +
  287 +
  288 + /* initialisation */
  289 + function setOptions($aOptions) {
  290 + $this->aOptions = $aOptions;
  291 +
  292 + // batching
  293 + $this->batchPage = KTUtil::arrayGet($aOptions, 'batch_page', 0);
  294 + $this->batchSize = KTUtil::arrayGet($aOptions, 'batch_size', 25);
  295 + $this->batchStart = $this->batchPage * $this->batchSize;
  296 +
  297 + // visibility
  298 + $this->bShowFolders = KTUtil::arrayGet($aOptions, 'show_folders', true);
  299 + $this->bShowDocuments = KTUtil::arrayGet($aOptions, 'show_documents', true);
  300 +
  301 + // sorting
  302 + $this->sort_column = KTUtil::arrayGet($aOptions, 'sort_on', "ktcore.columns.title");
  303 + $this->sort_order = KTUtil::arrayGet($aOptions, 'sort_order', 'asc');
  304 +
  305 + // url options
  306 + $this->returnURL = KTUtil::arrayGet($aOptions, 'return_url', $_SERVER['PHP_SELF']);
  307 + }
  308 +
  309 +
  310 + // we use a lot of standard variable names for these (esp. in columns.)
  311 + // no need to replicate the code everywhere.
  312 + function getEnvironOptions() {
  313 + $aNewOptions = array();
  314 +
  315 + // batching
  316 + $aNewOptions['batch_page'] = (int) KTUtil::arrayGet($_REQUEST, "page", 0);
  317 + $aNewOptions['batch_size'] = KTUtil::arrayGet($_REQUEST, "page_size", 25);
  318 +
  319 + // ordering. (direction and column)
  320 + $aNewOptions['sort_on'] = KTUtil::arrayGet($_REQUEST, 'sort_on', "ktcore.columns.title");
  321 + $displayOrder = KTUtil::arrayGet($_REQUEST, 'sort_order', "asc");
  322 + if ($displayOrder !== "asc") { $displayOrder = "desc"; }
  323 + $aNewOptions['sort_order'] = $displayOrder;
  324 +
  325 + // probably URL
  326 + $aNewOptions['result_url'] = $_SERVER['PHP_SELF'];
  327 +
  328 + // return the environ options
  329 + return $aNewOptions;
  330 + }
  331 +
  332 + function setColumnOptions($sColumnNamespace, $aOptions) {
  333 + foreach ($this->columns as $key => $oColumn) {
  334 + if ($oColumn->namespace == $sColumnNamespace) {
  335 + $this->columns[$key]->setOptions($aOptions);
  336 + }
  337 + }
  338 + }
  339 +
  340 + // columns should be added in the "correct" order (e.g. display order)
  341 + function addColumn($oBrowseColumn) { array_push($this->columns, $oBrowseColumn); }
  342 + function addColumns($aColumns) { $this->columns = kt_array_merge($this->columns, $aColumns); }
  343 + function setQueryObject($oQueryObj) { $this->_queryObj = $oQueryObj; }
  344 +
  345 + /* fetch cycle */
  346 + function setSorting() {
  347 +
  348 + $this->_sorted = true;
  349 +
  350 + // defaults
  351 + $this->_sDocumentSortField = "DM.name";
  352 + $this->_sFolderSortField = "F.name";
  353 +
  354 + foreach ($this->columns as $key => $oColumn) {
  355 + if ($oColumn->namespace == $this->sort_column) {
  356 + $this->columns[$key]->setSortedOn(true);
  357 + $this->columns[$key]->setSortDirection($this->sort_order);
  358 +
  359 + // get the join params from the object.
  360 + $aFQ = $this->columns[$key]->addToFolderQuery();
  361 + $aDQ = $this->columns[$key]->addToDocumentQuery();
  362 +
  363 + $this->_sFolderJoinClause = $aFQ[0];
  364 + $this->_aFolderJoinParams = $aFQ[1];
  365 +
  366 + if ($aFQ[2]) { $this->_sFolderSortField = $aFQ[2]; }
  367 + $this->_sDocumentJoinClause = $aDQ[0];
  368 + $this->_aDocumentJoinParams = $aDQ[1];
  369 +
  370 + if ($aDQ[2]) {
  371 + $this->_sDocumentSortField = $aDQ[2]; }
  372 + } else {
  373 + $oColumn->setSortedOn(false);
  374 + }
  375 + }
  376 + }
  377 +
  378 +
  379 + // finally, generate the results. either (documents or folders) could be null/empty
  380 + // FIXME handle column-for-sorting (esp. md?)
  381 + function getResults() {
  382 +
  383 + if ($this->_gotInfo == true) {
  384 + return;
  385 + }
  386 +
  387 + // this impacts the query used.
  388 + if (!$this->_sorted) {
  389 + $this->setSorting();
  390 + }
  391 +
  392 + // work out how many of each item type we're going to expect.
  393 + if ($this->bShowFolders) {
  394 + $this->folderCount = $this->_queryObj->getFolderCount();
  395 + if (PEAR::isError($this->folderCount)) {
  396 + $_SESSION['KTErrorMessage'][] = $this->folderCount->toString();
  397 + $this->folderCount = 0;
  398 + }
  399 + } else {
  400 + $this->folderCount = 0;
  401 + }
  402 +
  403 + if ($this->bShowDocuments) {
  404 + $this->documentCount = $this->_queryObj->getDocumentCount();
  405 + if (PEAR::isError($this->documentCount)) {
  406 + $_SESSION['KTErrorMessage'][] = $this->documentCount->toString();
  407 + $this->documentCount = 0;
  408 + }
  409 + } else {
  410 + $this->documentCount = 0;
  411 + }
  412 +
  413 + $this->itemCount = $this->documentCount + $this->folderCount;
  414 +
  415 + // now we need the active set: this is based on the batchsize,
  416 + // batchstart. this is divided into folders/documents. (_no_ intermingling).
  417 + $folderSet = null;
  418 + $documentSet = null;
  419 +
  420 + // assume we have not documents. This impacts "where" our documents start.
  421 + //
  422 + $no_folders = true;
  423 + $documents_to_get = $this->batchSize;
  424 + $folders_to_get = 0;
  425 +
  426 + if ($this->batchStart < $this->folderCount) {
  427 + $no_folders = false;
  428 + $folders_to_get = $this->folderCount - $this->batchStart;
  429 + if ($folders_to_get > $this->batchSize) {
  430 + $folders_to_get = $this->batchSize;
  431 + $documents_to_get = 0;
  432 + } else {
  433 + $documents_to_get -= $folders_to_get; // batch-size less the folders.
  434 + }
  435 + }
  436 +
  437 + if ($no_folders) {
  438 + $this->batchStart -= $this->folderCount;
  439 + $documentSet = $this->_queryObj->getDocuments($documents_to_get,
  440 + $this->batchStart,
  441 + $this->_sDocumentSortField,
  442 + $this->sort_order,
  443 + $this->_sDocumentJoinClause,
  444 + $this->_aDocumentJoinParams);
  445 + } else {
  446 + $folderSet = $this->_queryObj->getFolders($folders_to_get,
  447 + $this->batchStart,
  448 + $this->_sFolderSortField,
  449 + $this->sort_order,
  450 + $this->_sFolderJoinQuery,
  451 + $this->_aFolderJoinParams);
  452 +
  453 + // if we're getting -any- documents this round, then get some.
  454 + if ($documents_to_get > 0) {
  455 + $documentSet = $this->_queryObj->getDocuments($documents_to_get,
  456 + 0,
  457 + $this->_sDocumentSortField,
  458 + $this->sort_order,
  459 + $this->_sDocumentJoinClause,
  460 + $this->_aDocumentJoinParams);
  461 + }
  462 + }
  463 +
  464 + if (PEAR::isError($folderSet)) {
  465 + $_SESSION['KTErrorMessage'][] = sprintf(_kt("Failed to retrieve folders: %s"), $folderSet->getMessage());
  466 + $folderSet = array();
  467 + $this->folderCount = 0;
  468 + }
  469 +
  470 + if (PEAR::isError($documentSet)) {
  471 + $_SESSION['KTErrorMessage'][] = sprintf(_kt("Failed to retrieve documents: %s"), $documentSet->getMessage());
  472 + //var_dump($documentSet); exit(0);
  473 + $documentSet = array();
  474 + $this->documentCount = 0;
  475 +
  476 + }
  477 +
  478 + $this->itemCount = $this->documentCount + $this->folderCount;
  479 +
  480 + $this->activeset = array(
  481 + "folders" => $folderSet,
  482 + "documents" => $documentSet,
  483 + );
  484 +
  485 + $this->_gotInfo = true; // don't do this twice ...
  486 + }
  487 +
  488 + // stub: fetch all relevant information about a document (that will reasonably be fetched).
  489 + function getDocumentInfo($iDocumentId) {
  490 + if (array_key_exists($iDocumentId, $this->_documentData)) {
  491 + return $this->_documentData[$iDocumentId];
  492 + } else {
  493 + $this->_documentData[$iDocumentId] = $this->_retrieveDocumentInfo($iDocumentId);
  494 + return $this->_documentData[$iDocumentId];
  495 + }
  496 + }
  497 +
  498 + function _retrieveDocumentInfo($iDocumentId) {
  499 + $row_info = array("docid" => $iDocumentId);
  500 + $row_info["type"] = "document";
  501 + $row_info["document"] =& Document::get($iDocumentId);
  502 + return $row_info;
  503 + }
  504 +
  505 + // FIXME get more document info.
  506 + function getFolderInfo($iFolderId) {
  507 + if (array_key_exists($iFolderId, $this->_folderData)) {
  508 + return $this->_folderData[$iFolderId];
  509 + } else {
  510 + $this->_folderData[$iFolderId] = $this->_retrieveFolderInfo($iFolderId);
  511 + return $this->_folderData[$iFolderId];
  512 + }
  513 + }
  514 +
  515 + // FIXME get more folder info.
  516 + function _retrieveFolderInfo($iFolderId) {
  517 + $row_info = array("folderid" => $iFolderId);
  518 + $row_info["type"] = "folder";
  519 + $row_info["folder"] =& Folder::get($iFolderId);
  520 +
  521 + return $row_info;
  522 + }
  523 +
  524 + // render a particular row.
  525 + function renderRow($iDocumentId) { ; }
  526 +
  527 + // link url for a particular page.
  528 + function pageLink($iPageNumber) {
  529 + $qs = sprintf("page=%s&sort_on=%s&sort_order=%s", $iPageNumber, $this->sort_column, $this->sort_order);
  530 + return KTUtil::addQueryString($this->returnURL, $qs);
  531 + }
  532 +
  533 + function render() {
  534 + $this->setSorting();
  535 + $this->getResults();
  536 +
  537 + // sort out the batch
  538 + $pagecount = (int) floor($this->itemCount / $this->batchSize);
  539 + if (($this->itemCount % $this->batchSize) != 0) {
  540 + $pagecount += 1;
  541 + }
  542 +
  543 + $oTemplating =& KTTemplating::getSingleton();
  544 + $oTemplate = $oTemplating->loadTemplate("kt3/document_collection");
  545 + $aTemplateData = array(
  546 + "context" => $this,
  547 + "pagecount" => $pagecount,
  548 + "currentpage" => $this->batchPage,
  549 + "returnURL" => $this->returnURL,
  550 + "columncount" => count($this->columns),
  551 + );
  552 +
  553 + // in order to allow OTHER things than batch to move us around, we do:
  554 + return $oTemplate->render($aTemplateData);
  555 + }
  556 +}
  557 +
243 558 ?>
... ...
lib/browse/advancedcolumns.inc.php 0 → 100644
  1 +<?php
  2 +
  3 +// more advanced, intelligent columns.
  4 +
  5 +class AdvancedColumn {
  6 + // the internal tracking name
  7 + var $namespace = 'ktcore.columns.base';
  8 +
  9 + var $label = '';
  10 + var $sort_on = false;
  11 + var $sort_direction = "asc";
  12 + var $sortable = false;
  13 + var $return_url = null;
  14 + var $aOptions;
  15 +
  16 + // no params - important
  17 + function AdvancedColumn() {
  18 + $this->label = _kt('Base Column');
  19 + }
  20 +
  21 + // meld the internal vars with those from the options.
  22 + function setOptions($aOptions = null) {
  23 + $this->aOptions = kt_array_merge($this->aOptions, $aOptions);
  24 + $this->sortable = KTUtil::arrayGet($this->aOptions, 'sortable', $this->sortable);
  25 + $this->return_url = KTUtil::arrayGet($this->aOptions, 'return_url', $this->return_url);
  26 + $this->sort_on = KTUtil::arrayGet($this->aOptions, 'sort_on', $this->sort_on);
  27 + $this->sort_direction = KTUtil::arrayGet($this->aOptions, 'sort_on', $this->sort_direction);
  28 + }
  29 +
  30 + /*
  31 + return the html for the header.
  32 +
  33 + "return url" : URL to return to (or null to use addQueryStringSelf)
  34 + */
  35 + function renderHeader() {
  36 + // short-circuit
  37 + if (empty($this->label)) { return ''; }
  38 + // for safety
  39 + $label = htmlentities($this->label, ENT_NOQUOTES, 'UTF-8');
  40 +
  41 + // without sorthing to sort on, don't bother.
  42 + if (empty($this->namespace)) {
  43 + $this->sortable = false; // if we haven't set which column we're sorted by, do nothing.
  44 + }
  45 +
  46 + // no sorting, no link
  47 + if (!$this->sortable) {
  48 + return $label;
  49 + }
  50 +
  51 + // merge the sorting options into the header.
  52 + $sort_order = $this->sort_direction == "asc" ? "desc" : "asc";
  53 + $qs = sprintf("sort_on=%s&sort_order=%s", $this->namespace, $sort_order);
  54 + if (is_null($this->return_url)) {
  55 + $url = KTUtil::addQueryStringSelf($qs);
  56 + } else {
  57 + $url = KTUtil::addQueryString($this->return_url, $qs);
  58 + }
  59 +
  60 + return sprintf('<a href="%s">%s</a>', $url, $label);
  61 + }
  62 +
  63 + function renderData($aDataRow) {
  64 + if ($aDataRow["type"] == "folder") {
  65 + return $this->name . ": ". $aDataRow["folder"]->getName();
  66 + } else {
  67 + return $this->name . ": ". $aDataRow["document"]->getName();
  68 + }
  69 + }
  70 +
  71 + function setSortedOn($bIsSortedOn) { $this->sort_on = $bIsSortedOn; }
  72 + function getSortedOn() { return $this->sort_on; }
  73 + function setSortDirection($sSortDirection) { $this->sort_direction = $sSortDirection; }
  74 + function getSortDirection() { return $this->sort_direction; }
  75 +
  76 + function addToFolderQuery() { return array(null, null, null); }
  77 + function addToDocumentQuery() { return array(null, null, null); }
  78 +
  79 + function getName() {
  80 + return $this->label;
  81 + }
  82 +
  83 + function getEntryId() {
  84 + return KTUtil::arrayGet($this->aOptions, 'column_id', null);
  85 + }
  86 +
  87 + function getRequiredInView() {
  88 + return KTUtil::arrayGet($this->aOptions, 'required_in_view', null);
  89 + }
  90 +
  91 +}
  92 +
  93 +?>
0 94 \ No newline at end of file
... ...
lib/browse/columnentry.inc.php 0 → 100644
  1 +<?php
  2 +
  3 +/**
  4 + * $Id: columnentry.inc.php 5492 2006-06-04 20:50:43Z bshuttle $
  5 + *
  6 + * Copyright (c) 2006 Jam Warehouse http://www.jamwarehouse.com
  7 + *
  8 + * This program is free software; you can redistribute it and/or modify
  9 + * it under the terms of the GNU General Public License as published by
  10 + * the Free Software Foundation; using version 2 of the License.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20 + *
  21 + * -------------------------------------------------------------------------
  22 + *
  23 + * You can contact the copyright owner regarding licensing via the contact
  24 + * details that can be found on the KnowledgeTree web site:
  25 + *
  26 + * http://www.ktdms.com/
  27 + */
  28 +
  29 +class KTColumnEntry extends KTEntity {
  30 +
  31 +
  32 + /** role object primary key */
  33 + var $sViewNamespace;
  34 + var $sColumnNamespace;
  35 + var $iPosition;
  36 + var $sConfigArray;
  37 + var $bRequired;
  38 +
  39 + var $_aFieldToSelect = array(
  40 + 'iId' => 'id',
  41 + 'sColumnNamespace' => 'column_namespace',
  42 + 'sViewNamespace' => 'view_namespace',
  43 + 'iPosition' => 'position',
  44 + 'sConfigArray' => 'config_array',
  45 + 'bRequired' => 'required'
  46 + );
  47 +
  48 + var $_bUsePearError = true;
  49 +
  50 + function getColumnNamespace() { return $this->sColumnNamespace; }
  51 + function setColumnNamespace($sNewValue) { $this->sColumnNamespace = $sNewValue; }
  52 + function getViewNamespace() { return $this->sViewNamespace; }
  53 + function setViewNamespace($sNewValue) { $this->sViewNamespace = $sNewValue; }
  54 + function getPosition() { return $this->iPosition; }
  55 + function setPosition($iNewValue) { $this->iPosition = $iNewValue; }
  56 + function getConfigArray() { return unserialize($this->sConfigArray); }
  57 + function setConfigArray($aNewValue) { $this->sConfigArray = serialize($aNewValue); }
  58 + function getRequired() { return $this->bRequired; }
  59 + function setRequired($bNewValue) { $this->bRequired = $bNewValue; }
  60 +
  61 +
  62 + function _fieldValues () { return array(
  63 + 'column_namespace' => $this->sColumnNamespace,
  64 + 'view_namespace' => $this->sViewNamespace,
  65 + 'config_array' => $this->sConfigArray,
  66 + 'position' => $this->iPosition,
  67 + 'required' => $this->bRequired,
  68 + );
  69 + }
  70 +
  71 + function _table () { return KTUtil::getTableName('column_entries'); }
  72 + function get($iEntryId) { return KTEntityUtil::get('KTColumnEntry', $iEntryId); }
  73 + function & getList($sWhereClause = null) { return KTEntityUtil::getList2('KTColumnEntry', $sWhereClause); }
  74 + function & createFromArray($aOptions) {
  75 + // transparently convert the options.
  76 +
  77 + $aOptions['configarray'] = serialize(KTUtil::arrayGet($aOptions, 'config', array()));
  78 + unset($aOptions['config']);
  79 +
  80 + return KTEntityUtil::createFromArray('KTColumnEntry', $aOptions);
  81 + }
  82 +
  83 + function & getByView($sViewNamespace, $aOptions = null) {
  84 + if (is_null($aOptions)) { $aOptions = array(); }
  85 + $aOptions['multi'] = true;
  86 + $aSelect = array('view_namespace' => $sViewNamespace);
  87 +
  88 + return KTEntityUtil::getByDict('KTColumnEntry', $aSelect, $aOptions);
  89 + }
  90 +
  91 +}
  92 +?>
0 93 \ No newline at end of file
... ...
lib/browse/columnregistry.inc.php 0 → 100644
  1 +<?php
  2 +
  3 +/**
  4 + * $Id: columnregistry.inc.php 5492 2006-06-04 20:50:43Z bshuttle $
  5 + *
  6 + * Copyright (c) 2006 Jam Warehouse http://www.jamwarehouse.com
  7 + *
  8 + * This program is free software; you can redistribute it and/or modify
  9 + * it under the terms of the GNU General Public License as published by
  10 + * the Free Software Foundation; using version 2 of the License.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20 + *
  21 + * -------------------------------------------------------------------------
  22 + *
  23 + * You can contact the copyright owner regarding licensing via the contact
  24 + * details that can be found on the KnowledgeTree web site:
  25 + *
  26 + * http://www.ktdms.com/
  27 + */
  28 +
  29 +require_once(KT_LIB_DIR . '/browse/columnentry.inc.php');
  30 +
  31 +class KTColumnRegistry {
  32 + var $columns = array();
  33 + var $views = array(); // should be in here
  34 + // {{{ getSingleton
  35 + function &getSingleton () {
  36 + if (!KTUtil::arrayGet($GLOBALS['_KT_PLUGIN'], 'oKTColumnRegistry')) {
  37 + $GLOBALS['_KT_PLUGIN']['oKTColumnRegistry'] =& new KTColumnRegistry;
  38 + }
  39 + return $GLOBALS['_KT_PLUGIN']['oKTColumnRegistry'];
  40 + }
  41 + // }}}
  42 +
  43 + function registerColumn($sName, $sNamespace, $sClass, $sFile) {
  44 + $this->columns[$sNamespace] = array(
  45 + 'name' => $sName,
  46 + 'namespace' => $sNamespace,
  47 + 'class' => $sClass,
  48 + 'file' => $sFile
  49 + );
  50 + }
  51 +
  52 + function getViewName($sNamespace) { return KTUtil::arrayGet($this->views, $sNamespace); }
  53 + function getViews() { return $this->views; }
  54 + function getColumns() { return $this->columns; }
  55 + function registerView($sName, $sNamespace) { $this->views[$sNamespace] = $sName; }
  56 +
  57 + function getColumnInfo($sNamespace) {
  58 + return KTUtil::arrayGet($this->columns, $sNamespace, null);
  59 + }
  60 +
  61 + function getColumn($sNamespace) {
  62 + $aInfo = KTUtil::arrayGet($this->columns, $sNamespace, null);
  63 + if (empty($aInfo)) {
  64 + return PEAR::raiseError(sprintf(_kt("No such column: %s"), $sNamespace));
  65 + }
  66 +
  67 + require_once($aInfo['file']);
  68 +
  69 + return new $aInfo['class'];
  70 + }
  71 +
  72 + function getColumnsForView($sViewNamespace) {
  73 + $view_entry = KTUtil::arrayGet($this->views, $sViewNamespace);
  74 + if (is_null($view_entry)) {
  75 + return PEAR::raiseError(sprintf(_kt("No such view: %s"), $sViewNamespace));
  76 + }
  77 +
  78 + $view_column_entries = KTColumnEntry::getByView($sViewNamespace);
  79 + if (PEAR::isError($view_column_entries)) {
  80 + return $view_column_entries;
  81 + }
  82 +
  83 + $view_columns = array();
  84 + foreach ($view_column_entries as $oEntry) {
  85 + $res = $this->getColumn($oEntry->getColumnNamespace());
  86 + if (PEAR::isError($res)) { return $res; }
  87 +
  88 + $aOptions = $oEntry->getConfigArray();
  89 + $aOptions['column_id'] = $oEntry->getId();
  90 + $aOptions['required_in_view'] = $oEntry->getRequired();
  91 + $res->setOptions($aOptions);
  92 +
  93 + $view_columns[] = $res;
  94 + }
  95 +
  96 + return $view_columns;
  97 + }
  98 +}
  99 +
  100 +?>
... ...
lib/plugins/plugin.inc.php
... ... @@ -52,6 +52,8 @@ class KTPlugin {
52 52 var $_aLanguage = array();
53 53 var $_aHelpLanguage = array();
54 54 var $_aWFTriggers = array();
  55 + var $_aColumns = array();
  56 + var $_aViews = array();
55 57  
56 58 function KTPlugin($sFilename = null) {
57 59 $this->sFilename = $sFilename;
... ... @@ -140,6 +142,15 @@ class KTPlugin {
140 142 function registerHelpLanguage($sPlugin, $sLanguage, $sBasedir) {
141 143 $this->_aHelpLanguage[$sLanguage] = array($sPlugin, $sLanguage, $sBasedir);
142 144 }
  145 +
  146 + function registerColumn($sName, $sNamespace, $sClassName, $sFile) {
  147 + $sFile = $this->_fixFilename($sFile);
  148 + $this->_aColumns[$sNamespace] = array($sName, $sNamespace, $sClassName, $sFile);
  149 + }
  150 +
  151 + function registerView($sName, $sNamespace) {
  152 + $this->_aViews[$sNamespace] = array($sName, $sNamespace);
  153 + }
143 154  
144 155 function _fixFilename($sFilename) {
145 156 if (empty($sFilename)) {
... ... @@ -198,6 +209,7 @@ class KTPlugin {
198 209 require_once(KT_LIB_DIR . "/i18n/i18nregistry.inc.php");
199 210 require_once(KT_LIB_DIR . "/help/help.inc.php");
200 211 require_once(KT_LIB_DIR . "/workflow/workflowutil.inc.php");
  212 + require_once(KT_LIB_DIR . "/browse/columnregistry.inc.php");
201 213  
202 214 $oPRegistry =& KTPortletRegistry::getSingleton();
203 215 $oTRegistry =& KTTriggerRegistry::getSingleton();
... ... @@ -209,6 +221,7 @@ class KTPlugin {
209 221 $oi18nRegistry =& KTi18nRegistry::getSingleton();
210 222 $oKTHelpRegistry =& KTHelpRegistry::getSingleton();
211 223 $oWFTriggerRegistry =& KTWorkflowTriggerRegistry::getSingleton();
  224 + $oColumnRegistry =& KTColumnRegistry::getSingleton();
212 225  
213 226 foreach ($this->_aPortlets as $k => $v) {
214 227 call_user_func_array(array(&$oPRegistry, 'registerPortlet'), $v);
... ... @@ -261,6 +274,14 @@ class KTPlugin {
261 274 foreach ($this->_aWFTriggers as $k => $v) {
262 275 call_user_func_array(array(&$oWFTriggerRegistry, 'registerWorkflowTrigger'), $v);
263 276 }
  277 +
  278 + foreach ($this->_aColumns as $k => $v) {
  279 + call_user_func_array(array(&$oColumnRegistry, 'registerColumn'), $v);
  280 + }
  281 +
  282 + foreach ($this->_aViews as $k => $v) {
  283 + call_user_func_array(array(&$oColumnRegistry, 'registerView'), $v);
  284 + }
264 285 }
265 286  
266 287 function setup() {
... ...
plugins/ktcore/KTColumns.inc.php 0 → 100644
  1 +<?php
  2 +
  3 +// more advanced, intelligent columns.
  4 +
  5 +require_once(KT_LIB_DIR . '/browse/advancedcolumns.inc.php');
  6 +
  7 +class AdvancedTitleColumn extends AdvancedColumn {
  8 +
  9 + var $namespace = 'ktcore.columns.title';
  10 + var $sortable = true;
  11 + var $aOptions = array();
  12 + var $aIconPaths = array();
  13 +
  14 + function setOptions($aOptions) {
  15 + parent::setOptions($aOptions);
  16 + }
  17 +
  18 + function AdvancedTitleColumn() {
  19 + $this->label = _kt("Title");
  20 + }
  21 +
  22 + // what is used for sorting
  23 + // query addition is:
  24 + // [0] => join claus
  25 + // [1] => join params
  26 + // [2] => ORDER
  27 +
  28 + function addToFolderQuery() {
  29 + return array(null,
  30 + null,
  31 + "F.name",
  32 + );
  33 + }
  34 + function addToDocumentQuery() {
  35 + return array(null,
  36 + null,
  37 + "DM.name"
  38 + );
  39 + }
  40 +
  41 +
  42 + function renderFolderLink($aDataRow) {
  43 + $outStr = '<a href="' . $this->buildFolderLink($aDataRow) . '">';
  44 + $outStr .= htmlentities($aDataRow["folder"]->getName(), ENT_NOQUOTES, 'UTF-8');
  45 + $outStr .= '</a> ';
  46 + return $outStr;
  47 + }
  48 +
  49 + function renderDocumentLink($aDataRow) {
  50 + $outStr = '<a href="' . $this->buildDocumentLink($aDataRow) . '" title="' . $aDataRow["document"]->getFilename().'">';
  51 + $outStr .= htmlentities($aDataRow["document"]->getName(), ENT_NOQUOTES, 'UTF-8');
  52 + $outStr .= '</a>';
  53 + return $outStr;
  54 + }
  55 +
  56 + function buildDocumentLink($aDataRow) {
  57 + return KTBrowseUtil::getUrlForDocument($aDataRow["document"]->getId());
  58 + }
  59 +
  60 + function buildFolderLink($aDataRow) {
  61 + if (is_null(KTUtil::arrayGet($this->aOptions, 'direct_folder'))) {
  62 + return KTUtil::addQueryStringSelf('fFolderId='.$aDataRow["folder"]->getId());
  63 + } else {
  64 + return KTBrowseUtil::getUrlForFolder($aDataRow['folder']);
  65 + }
  66 + }
  67 +
  68 + // use inline, since its just too heavy to even _think_ about using smarty.
  69 + function renderData($aDataRow) {
  70 + if ($aDataRow["type"] == "folder") {
  71 + $contenttype = 'folder';
  72 + $link = $this->renderFolderLink($aDataRow);
  73 + return sprintf('<span class="contenttype %s">%s</span>', $contenttype, $link);
  74 + } else {
  75 + $contenttype = $this->_mimeHelper($aDataRow["document"]->getMimeTypeId());
  76 + $link = $this->renderDocumentLink($aDataRow);
  77 + $size = $this->prettySize($aDataRow["document"]->getSize());
  78 + return sprintf('<span class="contenttype %s">%s (%s)</span>', $contenttype, $link, $size);
  79 + }
  80 + }
  81 +
  82 + function prettySize($size) {
  83 + $finalSize = $size;
  84 + $label = 'b';
  85 +
  86 + if ($finalSize > 1000) { $label='Kb'; $finalSize = floor($finalSize/1000); }
  87 + if ($finalSize > 1000) { $label='Mb'; $finalSize = floor($finalSize/1000); }
  88 + return $finalSize . $label;
  89 + }
  90 +
  91 + function _mimeHelper($iMimeTypeId) {
  92 + require_once(KT_LIB_DIR . '/mime.inc.php');
  93 + return KTMime::getIconPath($iMimeTypeId);
  94 + }
  95 +}
  96 +
  97 +/*
  98 + * Column to handle dates
  99 + */
  100 +
  101 +class AdvancedDateColumn extends AdvancedColumn {
  102 + var $document_field_function;
  103 + var $folder_field_function;
  104 + var $sortable = true;
  105 + var $document_sort_column;
  106 + var $folder_sort_column;
  107 + var $namespace = 'ktcore.columns.genericdate';
  108 +
  109 + function AdvancedDateColumn() {
  110 + $this->label = _kt('Generic Date Function');
  111 + }
  112 +
  113 + // use inline, since its just too heavy to even _think_ about using smarty.
  114 + function renderData($aDataRow) {
  115 + $outStr = '';
  116 + if (($aDataRow["type"] == "folder") && (!is_null($this->folder_field_function))) {
  117 + $res = call_user_func(array($aDataRow["folder"], $this->folder_field_function));
  118 + $dColumnDate = strtotime($res);
  119 +
  120 + // now reformat this into something "pretty"
  121 + return date("Y-m-d H:i", $dColumnDate);
  122 +
  123 + } else if (($aDataRow["type"] == "document") && (!is_null($this->document_field_function))) {
  124 + $res = call_user_func(array($aDataRow["document"], $this->document_field_function));
  125 + $dColumnDate = strtotime($res);
  126 +
  127 + // now reformat this into something "pretty"
  128 + return date("Y-m-d H:i", $dColumnDate);
  129 + } else {
  130 + return '&mdash;';
  131 + }
  132 + return $outStr;
  133 + }
  134 +
  135 + function addToFolderQuery() {
  136 + return array(null, null, null);
  137 + }
  138 + function addToDocumentQuery() {
  139 + return array(null, null, $this->name);
  140 + }
  141 +}
  142 +
  143 +class CreationDateColumn extends AdvancedDateColumn {
  144 + var $document_field_function = 'getCreatedDateTime';
  145 + var $folder_field_function = null;
  146 +
  147 + var $document_sort_column = "D.created";
  148 + var $folder_sort_column = null;
  149 + var $namespace = 'ktcore.columns.creationdate';
  150 +
  151 + function CreationDateColumn() {
  152 + $this->label = _kt('Created');
  153 + }
  154 +}
  155 +
  156 +class ModificationDateColumn extends AdvancedDateColumn {
  157 + var $document_field_function = 'getLastModifiedDate';
  158 + var $folder_field_function = null;
  159 +
  160 + var $document_sort_column = "D.modified";
  161 + var $folder_sort_column = null;
  162 + var $namespace = 'ktcore.columns.modificationdate';
  163 +
  164 + function ModificationDateColumn() {
  165 + $this->label = _kt('Modified');
  166 + }
  167 +}
  168 +
  169 +class AdvancedUserColumn extends AdvancedColumn {
  170 + var $document_field_function;
  171 + var $folder_field_function;
  172 + var $sortable = false; // by default
  173 + var $document_sort_column;
  174 + var $folder_sort_column;
  175 + var $namespace = 'ktcore.columns.genericuser';
  176 +
  177 + function AdvancedUserColumn() {
  178 + $this->label = null; // abstract.
  179 + }
  180 +
  181 + // use inline, since its just too heavy to even _think_ about using smarty.
  182 + function renderData($aDataRow) {
  183 + $iUserId = null;
  184 + if (($aDataRow["type"] == "folder") && (!is_null($this->folder_field_function))) {
  185 + if (method_exists($aDataRow['folder'], $this->folder_field_function)) {
  186 + $iUserId = call_user_func(array($aDataRow['folder'], $this->folder_field_function));
  187 + }
  188 + } else if (($aDataRow["type"] == "document") && (!is_null($this->document_field_function))) {
  189 + if (method_exists($aDataRow['document'], $this->document_field_function)) {
  190 + $iUserId = call_user_func(array($aDataRow['document'], $this->document_field_function));
  191 + }
  192 + }
  193 + if (is_null($iUserId)) {
  194 + return '&mdash;';
  195 + }
  196 + $oUser = User::get($iUserId);
  197 + if (PEAR::isError($oUser) || $oUser == false) {
  198 + return '&mdash;';
  199 + } else {
  200 + return htmlentities($oUser->getName(), ENT_NOQUOTES, 'UTF-8');
  201 + }
  202 + }
  203 +
  204 + function addToFolderQuery() {
  205 + return array(null, null, null);
  206 + }
  207 +
  208 + function addToDocumentQuery() {
  209 + return array(null, null, null);
  210 + }
  211 +}
  212 +
  213 +class CreatorColumn extends AdvancedUserColumn {
  214 + var $document_field_function = "getCreatorID";
  215 + var $folder_field_function = null;
  216 + var $sortable = true; // by default
  217 + var $namespace = 'ktcore.columns.creator';
  218 +
  219 + function CreatorColumn() {
  220 + $this->label = _kt("Creator"); // abstract.
  221 + }
  222 +
  223 + function addToFolderQuery() {
  224 + return array(null, null, null);
  225 + }
  226 + function addToDocumentQuery() {
  227 + $sUsersTable = KTUtil::getTableName('users');
  228 + $sJoinSQL = "LEFT JOIN $sUsersTable AS users_order_join ON (D.creator_id = users_order_join.id)";
  229 + return array($sJoinSQL, null, "users_order_join.name");
  230 + }
  231 +}
  232 +
  233 +class AdvancedSelectionColumn extends AdvancedColumn {
  234 + var $rangename = null;
  235 + var $show_folders = true;
  236 + var $show_documents = true;
  237 +
  238 + var $namespace = "ktcore.columns.selection";
  239 +
  240 + function AdvancedSelectionColumn() {
  241 + $this->label = '';
  242 + }
  243 +
  244 + function setOptions($aOptions) {
  245 + AdvancedColumn::setOptions($aOptions);
  246 + $this->rangename = KTUtil::arrayGet($this->aOptions, 'rangename', $this->rangename);
  247 + $this->show_folders = KTUtil::arrayGet($this->aOptions, 'show_folders', $this->show_folders);
  248 + $this->show_documents = KTUtil::arrayGet($this->aOptions, 'show_documents', $this->show_documents);
  249 + }
  250 +
  251 + function renderHeader($sReturnURL) {
  252 + global $main;
  253 + $main->requireJSResource("resources/js/toggleselect.js");
  254 +
  255 + return sprintf('<input type="checkbox" title="toggle all" onclick="toggleSelectFor(this, \'%s\')" />', $this->rangename);
  256 +
  257 + }
  258 +
  259 + // only include the _f or _d IF WE HAVE THE OTHER TYPE.
  260 + function renderData($aDataRow) {
  261 + $localname = $this->rangename;
  262 +
  263 + if (($aDataRow["type"] === "folder") && ($this->show_folders)) {
  264 + if ($this->show_documents) {
  265 + $localname .= "_f[]";
  266 + }
  267 + $v = $aDataRow["folderid"];
  268 + } else if (($aDataRow["type"] === "document") && $this->show_documents) {
  269 + if ($this->show_folders) {
  270 + $localname .= "_d[]";
  271 + }
  272 + $v = $aDataRow["docid"];
  273 + } else {
  274 + return '&nbsp;';
  275 + }
  276 +
  277 + return sprintf('<input type="checkbox" name="%s" onclick="activateRow(this)" value="%s"/>', $localname, $v);
  278 + }
  279 +
  280 +
  281 + // no label, but we do have a title
  282 + function getName() {
  283 + return _kt("Multiple Selection");
  284 + }
  285 +}
  286 +
  287 +
  288 +class AdvancedSingleSelectionColumn extends AdvancedSelectionColumn {
  289 + var $namespace = 'ktcore.columns.singleselection';
  290 +
  291 + function AdvancedSingleSelectionColumn() {
  292 + parent::AdvancedSelectionColumn();
  293 + $this->label = null;
  294 + }
  295 +
  296 + function renderHeader() {
  297 + return '&nbsp;';
  298 + }
  299 +
  300 + // only include the _f or _d IF WE HAVE THE OTHER TYPE.
  301 + function renderData($aDataRow) {
  302 + $localname = $this->name;
  303 +
  304 + if (($aDataRow["type"] === "folder") && ($this->show_folders)) {
  305 + if ($this->show_documents) {
  306 + $localname .= "_f";
  307 + }
  308 + $v = $aDataRow["folderid"];
  309 + } else if (($aDataRow["type"] === "document") && $this->show_documents) {
  310 + if ($this->show_folders) {
  311 + $localname .= "_d";
  312 + }
  313 + $v = $aDataRow["docid"];
  314 + } else {
  315 + return '&nbsp;';
  316 + }
  317 +
  318 + return '<input type="radio" name="' . $localname . '" value="' . $v . '"/>';
  319 + }
  320 +
  321 + // no label, but we do have a title
  322 + function getName() {
  323 + return _kt("Single Selection");
  324 + }
  325 +}
  326 +
  327 +
  328 +class AdvancedWorkflowColumn extends AdvancedColumn {
  329 + var $namespace = 'ktcore.columns.workflow_state';
  330 + var $sortable = false;
  331 +
  332 + function AdvancedWorkflowColumn() {
  333 + $this->label = _kt("Workflow State");
  334 + $this->sortable = false;
  335 + }
  336 +
  337 + // use inline, since its just too heavy to even _think_ about using smarty.
  338 + function renderData($aDataRow) {
  339 + // only _ever_ show this for documents.
  340 + if ($aDataRow["type"] === "folder") {
  341 + return '&nbsp;';
  342 + }
  343 +
  344 + $oWorkflow = KTWorkflowUtil::getWorkflowForDocument($aDataRow['document']);
  345 + $oState = KTWorkflowUtil::getWorkflowStateForDocument($aDataRow['document']);
  346 + if (($oState == null) || ($oWorkflow == null)) {
  347 + return '&mdash;';
  348 + } else {
  349 + return sprintf('%s <span class="descriptive">%s</span>',
  350 + htmlentities($oState->getName(), ENT_NOQUOTES, 'UTF-8'),
  351 + htmlentities($oWorkflow->getName(), ENT_NOQUOTES, 'UTF-8')
  352 + );
  353 + }
  354 + }
  355 +}
  356 +
  357 +class AdvancedDownloadColumn extends AdvancedColumn {
  358 +
  359 + var $namespace = 'ktcore.columns.download';
  360 +
  361 + function AdvancedDownloadColumn() {
  362 + $this->label = null;
  363 + }
  364 +
  365 + function renderData($aDataRow) {
  366 + // only _ever_ show this for documents.
  367 + if ($aDataRow["type"] === "folder") {
  368 + return '&nbsp;';
  369 + }
  370 +
  371 + $link = KTUtil::ktLink('action.php','ktcore.actions.document.view', 'fDocumentId=' . $aDataRow['document']->getId());
  372 + return sprintf('<a href="%s" class="ktAction ktDownload" title="%s">%s</a>', $link, _kt('Download Document'), _kt('Download Document'));
  373 + }
  374 +
  375 + function getName() { return _kt('Download'); }
  376 +}
  377 +
  378 +?>
0 379 \ No newline at end of file
... ...
plugins/ktcore/KTCorePlugin.php
... ... @@ -91,6 +91,18 @@ class KTCorePlugin extends KTPlugin {
91 91 $this->registerPortlet(array('administration'),
92 92 'KTAdminSectionNavigation', 'ktcore.portlets.adminnavigation',
93 93 'KTPortlets.php');
  94 +
  95 + $this->registerColumn(_kt("Title"), 'ktcore.columns.title', 'AdvancedTitleColumn', 'KTColumns.inc.php');
  96 + $this->registerColumn(_kt("Selection"), 'ktcore.columns.selection', 'AdvancedSelectionColumn', 'KTColumns.inc.php');
  97 + $this->registerColumn(_kt("Single Selection"), 'ktcore.columns.singleselection', 'AdvancedSingleSelectionColumn', 'KTColumns.inc.php');
  98 + $this->registerColumn(_kt("Workflow State"), 'ktcore.columns.workflow_state', 'AdvancedWorkflowColumn', 'KTColumns.inc.php');
  99 + $this->registerColumn(_kt("Creation Date"), 'ktcore.columns.creationdate', 'CreationDateColumn', 'KTColumns.inc.php');
  100 + $this->registerColumn(_kt("Modification Date"), 'ktcore.columns.modificationdate', 'ModificationDateColumn', 'KTColumns.inc.php');
  101 + $this->registerColumn(_kt("Creator"), 'ktcore.columns.creator', 'CreatorColumn', 'KTColumns.inc.php');
  102 + $this->registerColumn(_kt("Download File"), 'ktcore.columns.download', 'AdvancedDownloadColumn', 'KTColumns.inc.php');
  103 +
  104 + $this->registerView(_kt("Browse Documents"), 'ktcore.views.browse');
  105 + $this->registerView(_kt("Search"), 'ktcore.views.search');
94 106  
95 107 // workflow triggers
96 108 $this->registerWorkflowTrigger('ktcore.workflowtriggers.permissionguard', 'PermissionGuardTrigger', 'KTWorkflowTriggers.inc.php');
... ... @@ -185,6 +197,10 @@ class KTCorePlugin extends KTPlugin {
185 197 $this->registerAdminPage("cleanup", 'ManageCleanupDispatcher', 'misc',
186 198 _kt('Verify document storage'), _kt('Performs a check to see if the documents in your repositories all are stored on the back-end storage (usually on disk).'),
187 199 'admin/manageCleanup.php', null);
  200 + $this->registerAdminPage("views", 'ManageViewDispatcher', 'misc',
  201 + _kt('Manage views'), _kt('Allows you to specify the columns that are to be used by a particular view (e.g. Browse documents, Search)'),
  202 + 'admin/manageViews.php', null);
  203 +
188 204 // plugins
189 205  
190 206 }
... ...
plugins/ktcore/admin/manageViews.php 0 → 100644
  1 +<?php
  2 +
  3 +require_once(KT_LIB_DIR . '/templating/templating.inc.php');
  4 +require_once(KT_LIB_DIR . '/widgets/reorderdisplay.inc.php');
  5 +require_once(KT_LIB_DIR . '/dispatcher.inc.php');
  6 +require_once(KT_LIB_DIR . '/browse/columnregistry.inc.php');
  7 +
  8 +class ManageViewDispatcher extends KTAdminDispatcher {
  9 +
  10 + function check() {
  11 +
  12 + $this->aBreadcrumbs[] = array('url' => $_SERVER['PHP_SELF'], 'name' => _kt('Manage Views'));
  13 + return parent::check();
  14 + }
  15 +
  16 + function do_main() {
  17 + $oTemplating =& KTTemplating::getSingleton();
  18 + $oTemplate = $oTemplating->loadTemplate('ktcore/misc/columns/select_view');
  19 +
  20 + $oColumnRegistry =& KTColumnRegistry::getSingleton();
  21 +
  22 + $aViews = $oColumnRegistry->getViews();
  23 +
  24 + $aTemplateData = array(
  25 + 'context' => $this,
  26 + 'views' => $aViews,
  27 + );
  28 + return $oTemplate->render($aTemplateData);
  29 + }
  30 +
  31 + function do_editView() {
  32 + $oTemplating =& KTTemplating::getSingleton();
  33 + $oTemplate = $oTemplating->loadTemplate('ktcore/misc/columns/edit_view');
  34 +
  35 + $oColumnRegistry =& KTColumnRegistry::getSingleton();
  36 + $aColumns = $oColumnRegistry->getColumnsForView($_REQUEST['viewNS']);
  37 + //var_dump($aColumns); exit(0);
  38 + $aAllColumns = $oColumnRegistry->getColumns();
  39 +
  40 + $view_name = $oColumnRegistry->getViewName($_REQUEST['viewNS']);
  41 + $this->oPage->setTitle($view_name);
  42 + $this->oPage->setBreadcrumbDetails($view_name);
  43 +
  44 + $aOptions = array();
  45 + $vocab = array();
  46 + foreach ($aAllColumns as $aInfo) {
  47 + $vocab[$aInfo['namespace']] = $aInfo['name'];
  48 + }
  49 + $aOptions['vocab'] = $vocab;
  50 + $add_field = new KTLookupWidget(_kt("Columns"), _kt("Select a column to add to the view. Please note that while you can add multiple copies of a column, they will all behave as a single column"), 'column_ns', null, $this->oPage, true, null, $aErrors = null, $aOptions);
  51 +
  52 + $aTemplateData = array(
  53 + 'context' => $this,
  54 + 'current_columns' => $aColumns,
  55 + 'all_columns' => $aAllColumns,
  56 + 'view' => $_REQUEST['viewNS'],
  57 + 'add_field' => $add_field,
  58 + );
  59 + return $oTemplate->render($aTemplateData);
  60 + }
  61 +
  62 + function do_deleteEntry() {
  63 + $entry_id = KTUtil::arrayGet($_REQUEST, 'entry_id');
  64 + $view = KTUtil::arrayGet($_REQUEST, 'viewNS');
  65 +
  66 + // none of these conditions can be reached "normally".
  67 +
  68 + $oEntry = KTColumnEntry::get($entry_id);
  69 + if (PEAR::isError($oEntry)) {
  70 + $this->errorRedirectToMain(_kt("Unable to locate the entry"));
  71 + }
  72 +
  73 + if ($oEntry->getRequired()) {
  74 + $this->errorRedirectToMain(_kt("That column is required"));
  75 + }
  76 +
  77 + if ($oEntry->getViewNamespace() != $view) {
  78 + $this->errorRedirectToMain(_kt("That column is not for the specified view"));
  79 + }
  80 +
  81 + $res = $oEntry->delete();
  82 +
  83 + if (PEAR::isError($res)) {
  84 + $this->errorRedirectToMain(sprintf(_kt("Failed to remove that column: %s"), $res->getMessage()));
  85 + }
  86 +
  87 + $this->successRedirectTo("editView", _kt("Deleted Entry"), sprintf("viewNS=%s", $view));
  88 + }
  89 +
  90 + function do_addEntry() {
  91 + $column_ns = KTUtil::arrayGet($_REQUEST, 'column_ns');
  92 + $view = KTUtil::arrayGet($_REQUEST, 'viewNS');
  93 +
  94 + $this->startTransaction();
  95 +
  96 + $oEntry = KTColumnEntry::createFromArray(array(
  97 + 'ColumnNamespace' => $column_ns,
  98 + 'ViewNamespace' => $view,
  99 + 'Position' => 1000, // start it at the bottom
  100 + 'config' => array(), // stub, for now.
  101 + 'Required' => 0
  102 + ));
  103 +
  104 + $this->successRedirectTo("editView", _kt("Added Entry"), sprintf("viewNS=%s", $view));
  105 + }
  106 +
  107 +}
  108 +
  109 +?>
0 110 \ No newline at end of file
... ...
search/booleanSearch.php
... ... @@ -97,91 +97,91 @@ class BooleanSearchDispatcher extends KTStandardDispatcher {
97 97 }
98 98  
99 99 function do_saveSearch() {
100   - $this->startTransaction();
101   -
102   - $iSearchId = KTUtil::arrayGet($_REQUEST, 'fSearchId', false);
103   - $sName = KTUtil::arrayGet($_REQUEST, 'name', false);
104   - $sSearch = KTUtil::arrayGet($_REQUEST, 'boolean_search');
105   -
106   - if($iSearchId === false && $sName === false) {
107   - $this->errorRedirectTo('performSearch', _kt('Please either enter a name, or select a search to save over'), sprintf('boolean_search_id=%s', $sSearch));
108   - exit(0);
109   - }
110   -
111   - $datavars = $_SESSION['boolean_search'][$sSearch];
112   - if (!is_array($datavars)) {
113   - $datavars = unserialize($datavars);
  100 + $this->startTransaction();
  101 +
  102 + $iSearchId = KTUtil::arrayGet($_REQUEST, 'fSearchId', false);
  103 + $sName = KTUtil::arrayGet($_REQUEST, 'name', false);
  104 + $sSearch = KTUtil::arrayGet($_REQUEST, 'boolean_search');
  105 +
  106 + if($iSearchId === false && $sName === false) {
  107 + $this->errorRedirectTo('performSearch', _kt('Please either enter a name, or select a search to save over'), sprintf('boolean_search_id=%s', $sSearch));
  108 + exit(0);
114 109 }
115   -
116   - if (empty($datavars)) {
117   - $this->errorRedirectToMain(_kt('You need to have at least 1 condition.'));
  110 +
  111 + $datavars = $_SESSION['boolean_search'][$sSearch];
  112 + if (!is_array($datavars)) {
  113 + $datavars = unserialize($datavars);
  114 + }
  115 +
  116 + if (empty($datavars)) {
  117 + $this->errorRedirectToMain(_kt('You need to have at least 1 condition.'));
  118 + }
  119 +
  120 + if($iSearchId) {
  121 + $oSearch = KTSavedSearch::get($iSearchId);
  122 + if(PEAR::isError($oSearch) || $oSearch == false) {
  123 + $this->errorRedirectToMain(_kt('No such search'));
  124 + exit(0);
  125 + }
  126 + $oSearch->setSearch($datavars);
  127 + $oSearch = $oSearch->update();
  128 +
  129 + } else {
  130 + $sName = $this->oValidator->validateEntityName('KTSavedSearch',
  131 + KTUtil::arrayGet($_REQUEST, 'name'),
  132 + array('extra_condition' => 'not is_condition', 'redirect_to' => array('new')));
  133 +
  134 + $sNamespace = KTUtil::nameToLocalNamespace('Saved searches', $sName);
  135 +
  136 + $oSearch = KTSavedSearch::createFromArray(array('name' => $sName,
  137 + 'namespace' => $sNamespace,
  138 + 'iscondition' => false,
  139 + 'iscomplete' => true,
  140 + 'userid' => $this->oUser->getId(),
  141 + 'search' => $datavars,));
118 142 }
119   -
120   - if($iSearchId) {
121   - $oSearch = KTSavedSearch::get($iSearchId);
122   - if(PEAR::isError($oSearch) || $oSearch == false) {
123   - $this->errorRedirectToMain(_kt('No such search'));
124   - exit(0);
125   - }
126   - $oSearch->setSearch($datavars);
127   - $oSearch = $oSearch->update();
128   -
129   - } else {
130   - $sName = $this->oValidator->validateEntityName('KTSavedSearch',
131   - KTUtil::arrayGet($_REQUEST, 'name'),
132   - array('extra_condition' => 'not is_condition', 'redirect_to' => array('new')));
133   -
134   - $sNamespace = KTUtil::nameToLocalNamespace('Saved searches', $sName);
135   -
136   - $oSearch = KTSavedSearch::createFromArray(array('name' => $sName,
137   - 'namespace' => $sNamespace,
138   - 'iscondition' => false,
139   - 'iscomplete' => true,
140   - 'userid' => $this->oUser->getId(),
141   - 'search' => $datavars,));
142   - }
143   -
144   - $this->oValidator->notError($oSearch, array(
145   - 'redirect_to' => 'main',
146   - 'message' => _kt('Search not saved'),
147   - ));
148   -
149   - $this->commitTransaction();
  143 +
  144 + $this->oValidator->notError($oSearch, array(
  145 + 'redirect_to' => 'main',
  146 + 'message' => _kt('Search not saved'),
  147 + ));
  148 +
  149 + $this->commitTransaction();
150 150 $this->successRedirectTo('performSearch', _kt('Search saved'), sprintf('boolean_search_id=%s', $sSearch));
151 151 }
152 152  
153 153  
154 154 function do_deleteSearch() {
155   - $this->startTransaction();
156   -
157   - $iSearchId = KTUtil::arrayGet($_REQUEST, 'fSavedSearchId', false);
158   - $oSearch = KTSavedSearch::get($iSearchId);
159   - if(PEAR::isError($oSearch) || $oSearch == false) {
160   - $this->errorRedirectToMain(_kt('No such search'));
161   - exit(0);
162   - }
163   -
164   - $res = $oSearch->delete();
165   - $this->oValidator->notError($res, array(
166   - 'redirect_to' => 'main',
167   - 'message' => _kt('Error deleting search'),
168   - ));
169   -
170   - $this->commitTransaction();
171   -
172   - $iFolderId = KTUtil::arrayGet($_REQUEST, 'fFolderId', false);
173   - $iDocumentId = KTUtil::arrayGet($_REQUEST, 'fFolderId', false);
174   -
175   - if($iFolderId) {
176   - controllerRedirect('browse', 'fFolderId=' . $iFolderId);
177   - } else {
178   - controllerRedirect('viewDocument', 'fDocumentId=' . $iDocumentId);
179   - }
  155 + $this->startTransaction();
  156 +
  157 + $iSearchId = KTUtil::arrayGet($_REQUEST, 'fSavedSearchId', false);
  158 + $oSearch = KTSavedSearch::get($iSearchId);
  159 + if(PEAR::isError($oSearch) || $oSearch == false) {
  160 + $this->errorRedirectToMain(_kt('No such search'));
  161 + exit(0);
  162 + }
  163 +
  164 + $res = $oSearch->delete();
  165 + $this->oValidator->notError($res, array(
  166 + 'redirect_to' => 'main',
  167 + 'message' => _kt('Error deleting search'),
  168 + ));
  169 +
  170 + $this->commitTransaction();
  171 +
  172 + $iFolderId = KTUtil::arrayGet($_REQUEST, 'fFolderId', false);
  173 + $iDocumentId = KTUtil::arrayGet($_REQUEST, 'fFolderId', false);
  174 +
  175 + if($iFolderId) {
  176 + controllerRedirect('browse', 'fFolderId=' . $iFolderId);
  177 + } else {
  178 + controllerRedirect('viewDocument', 'fDocumentId=' . $iDocumentId);
  179 + }
180 180 }
181 181  
182 182 function do_editSearch() {
183 183 $sSearch = KTUtil::arrayGet($_REQUEST, 'boolean_search');
184   - $aSearch = $_SESSION['boolean_search'][$sSearch];
  184 + $aSearch = $_SESSION['boolean_search'][$sSearch];
185 185 if (!is_array($aSearch)) {
186 186 $aSearch = unserialize($aSearch);
187 187 }
... ... @@ -233,66 +233,58 @@ class BooleanSearchDispatcher extends KTStandardDispatcher {
233 233 }
234 234 $this->oPage->setBreadcrumbDetails($sTitle);
235 235  
236   - $collection = new DocumentCollection;
237   - $this->browseType = "Folder";
238   -
239   - //$collection->addColumn(new SelectionColumn("Browse Selection","selection"));
240   - $t =& new TitleColumn("Test 1 (title)","title");
241   - $t->setOptions(array('documenturl' => $GLOBALS['KTRootUrl'] . '/view.php'));
242   - $collection->addColumn($t);
243   - $collection->addColumn(new DownloadColumn('','download'));
244   - $collection->addColumn(new DateColumn(_kt("Created"),"created", "getCreatedDateTime"));
245   - $collection->addColumn(new DateColumn(_kt("Last Modified"),"modified", "getLastModifiedDate"));
246   - $collection->addColumn(new UserColumn(_kt('Creator'),'creator_id','getCreatorID'));
247   - $collection->addColumn(new WorkflowColumn(_kt('Workflow State'),'workflow_state'));
248 236  
  237 + $this->browseType = "Folder";
249 238 $searchable_text = KTUtil::arrayGet($_REQUEST, "fSearchableText");
250   -
251   - $batchPage = (int) KTUtil::arrayGet($_REQUEST, "page", 0);
252   - $batchSize = 20;
253   -
254 239 $sSearch = md5(serialize($aCriteriaSet));
255 240 $_SESSION['boolean_search'][$sSearch] = $aCriteriaSet;
256   - $resultURL = KTUtil::addQueryStringSelf("action=performSearch&boolean_search_id=" . urlencode($sSearch));
257   - $collection->setBatching($resultURL, $batchPage, $batchSize);
258 241  
259 242  
260   - // ordering. (direction and column)
261   - $displayOrder = KTUtil::arrayGet($_REQUEST, 'sort_order', "asc");
262   - if ($displayOrder !== "asc") { $displayOrder = "desc"; }
263   - $displayControl = KTUtil::arrayGet($_REQUEST, 'sort_on', "title");
264   -
265   - $collection->setSorting($displayControl, $displayOrder);
  243 + $collection = new AdvancedCollection;
  244 + $oColumnRegistry = KTColumnRegistry::getSingleton();
  245 + $aColumns = $oColumnRegistry->getColumnsForView('ktcore.views.search');
  246 + $collection->addColumns($aColumns);
  247 +
  248 + // set a view option
  249 + $aTitleOptions = array(
  250 + 'documenturl' => $GLOBALS['KTRootUrl'] . '/view.php',
  251 + );
  252 + $collection->setColumnOptions('ktcore.columns.title', $aTitleOptions);
  253 +
  254 + $aOptions = $collection->getEnvironOptions(); // extract data from the environment
  255 +
  256 + $aOptions['result_url'] = KTUtil::addQueryStringSelf("action=performSearch&boolean_search_id=" . urlencode($sSearch));
  257 +
  258 + $collection->setOptions($aOptions);
  259 + $collection->setQueryObject(new BooleanSearchQuery($aCriteriaSet));
266 260  
267   - // add in the query object.
268   - $qObj = new BooleanSearchQuery($aCriteriaSet);
269   - $collection->setQueryObject($qObj);
270 261  
  262 + //$a = new BooleanSearchQuery($aCriteriaSet);
  263 + //var_dump($a->getDocumentCount()); exit(0);
271 264  
272   - // form fields for saving the search
  265 + // form fields for saving the search
273 266 $save_fields = array();
274 267 $save_fields[] = new KTStringWidget(_kt('New search'), _kt('The name to save this search as'), 'name', null, $this->oPage, true);
275 268  
276   - $aUserSearches = KTSavedSearch::getUserSearches($this->oUser->getId(), true);
277   - if(count($aUserSearches)) {
278   - $aVocab = array('' => ' ---- ');
279   - foreach($aUserSearches as $oSearch) {
280   - $aVocab[$oSearch->getId()] = $oSearch->getName();
281   - }
282   -
283   - $aSelectOptions = array('vocab' => $aVocab);
284   - $save_fields[] = new KTLookupWidget(_kt('Existing search'), _kt('To save over one of your existing searches, select it here.'), 'fSearchId', null, $this->oPage, true, null, null, $aSelectOptions);
285   - }
286   -
287   - $collection->getResults();
  269 + $aUserSearches = KTSavedSearch::getUserSearches($this->oUser->getId(), true);
  270 + if(count($aUserSearches)) {
  271 + $aVocab = array('' => ' ---- ');
  272 + foreach($aUserSearches as $oSearch) {
  273 + $aVocab[$oSearch->getId()] = $oSearch->getName();
  274 + }
  275 +
  276 + $aSelectOptions = array('vocab' => $aVocab);
  277 + $save_fields[] = new KTLookupWidget(_kt('Existing search'), _kt('To save over one of your existing searches, select it here.'), 'fSearchId', null, $this->oPage, true, null, null, $aSelectOptions);
  278 + }
  279 +
288 280 $oTemplating =& KTTemplating::getSingleton();
289 281 $oTemplate = $oTemplating->loadTemplate("kt3/browse");
290 282 $aTemplateData = array(
291   - "context" => $this,
292   - "collection" => $collection,
293   - "custom_title" => $sTitle,
294   - "save_fields" => $save_fields,
295   - "boolean_search" => $sSearch,
  283 + "context" => $this,
  284 + "collection" => $collection,
  285 + "custom_title" => $sTitle,
  286 + "save_fields" => $save_fields,
  287 + "boolean_search" => $sSearch,
296 288 );
297 289 return $oTemplate->render($aTemplateData);
298 290 }
... ...
search/simpleSearch.php
... ... @@ -34,9 +34,10 @@ require_once(KT_LIB_DIR . &quot;/browse/DocumentCollection.inc.php&quot;);
34 34 require_once(KT_LIB_DIR . "/browse/BrowseColumns.inc.php");
35 35 require_once(KT_LIB_DIR . "/browse/PartialQuery.inc.php");
36 36  
37   -
38 37 require_once(KT_LIB_DIR . "/foldermanagement/Folder.inc");
39 38  
  39 +require_once(KT_LIB_DIR . '/browse/columnregistry.inc.php');
  40 +
40 41 class SimpleSearchTitleColumn extends TitleColumn {
41 42 function setSearch($sSearch) {
42 43 $this->sSearch = $sSearch;
... ... @@ -137,58 +138,40 @@ class SimpleSearchDispatcher extends KTStandardDispatcher {
137 138 $aErrorOptions = array(
138 139 "message" => _kt("Please provide a search term"),
139 140 );
140   - $searchable_text = KTUtil::arrayGet($_REQUEST, "fSearchableText");
  141 + $searchable_text = KTUtil::arrayGet($_REQUEST, "fSearchableText");
141 142 $this->oValidator->notEmpty($searchable_text, $aErrorOptions);
142 143  
143   - $collection = new DocumentCollection;
144   - $this->browseType = "Folder";
145   -
146   - //$collection->addColumn(new SelectionColumn("Browse Selection","selection"));
147   - /*
148   - $t = new SimpleSearchTitleColumn("Test 1 (title)","title");
149   - $t->setOptions(array('documenturl' => $GLOBALS['KTRootUrl'] . '/view.php'));
150   - $t->setSearch($searchable_text);
151   - */
152   -
153   - $t =& new TitleColumn("Test 1 (title)","title");
154   - $t->setOptions(array('documenturl' => $GLOBALS['KTRootUrl'] . '/view.php', 'direct_folder' => true));
155   - $collection->addColumn($t);
156   - $collection->addColumn(new DownloadColumn('','download'));
157   - $collection->addColumn(new DateColumn(_kt("Created"),"created", "getCreatedDateTime"));
158   - $collection->addColumn(new DateColumn(_kt("Last Modified"),"modified", "getLastModifiedDate"));
159   - $collection->addColumn(new UserColumn(_kt('Creator'),'creator_id','getCreatorID'));
160   - $collection->addColumn(new WorkflowColumn(_kt('Workflow State'),'workflow_state'));
161   -
162   - $batchPage = (int) KTUtil::arrayGet($_REQUEST, "page", 0);
163   - $batchSize = 20;
164   -
165   - $resultURL = KTUtil::addQueryStringSelf("fSearchableText=" . $searchable_text);
166   - $collection->setBatching($resultURL, $batchPage, $batchSize);
167   -
168   -
169   - // ordering. (direction and column)
170   - $displayOrder = KTUtil::arrayGet($_REQUEST, 'sort_order', "asc");
171   - if ($displayOrder !== "asc") { $displayOrder = "desc"; }
172   - $displayControl = KTUtil::arrayGet($_REQUEST, 'sort_on', "title");
173   -
174   - $collection->setSorting($displayControl, $displayOrder);
175   -
176   - // add in the query object.
177   - $qObj = new SimpleSearchQuery($searchable_text);
178   - $collection->setQueryObject($qObj);
179   -
180   - // breadcrumbs
181   - // FIXME handle breadcrumbs
182   - $collection->getResults();
183   -
184   - $oTemplating =& KTTemplating::getSingleton();
185   - $oTemplate = $oTemplating->loadTemplate("kt3/browse");
186   - $aTemplateData = array(
187   - "context" => $this,
188   - "collection" => $collection,
189   - );
190   - return $oTemplate->render($aTemplateData);
191   - }
  144 +
  145 + $this->browseType = "Folder";
  146 +
  147 +
  148 + $collection = new AdvancedCollection;
  149 + $oColumnRegistry = KTColumnRegistry::getSingleton();
  150 + $aColumns = $oColumnRegistry->getColumnsForView('ktcore.views.search');
  151 + $collection->addColumns($aColumns);
  152 +
  153 + // set a view option
  154 + $aTitleOptions = array(
  155 + 'documenturl' => $GLOBALS['KTRootUrl'] . '/view.php',
  156 + 'direct_folder' => true,
  157 + );
  158 + $collection->setColumnOptions('ktcore.columns.title', $aTitleOptions);
  159 +
  160 + $aOptions = $collection->getEnvironOptions(); // extract data from the environment
  161 +
  162 + $aOptions['result_url'] = KTUtil::addQueryStringSelf("fSearchableText=" . $searchable_text);
  163 +
  164 + $collection->setOptions($aOptions);
  165 + $collection->setQueryObject(new SimpleSearchQuery($searchable_text));
  166 +
  167 + $oTemplating =& KTTemplating::getSingleton();
  168 + $oTemplate = $oTemplating->loadTemplate("kt3/browse");
  169 + $aTemplateData = array(
  170 + "context" => $this,
  171 + "collection" => $collection,
  172 + );
  173 + return $oTemplate->render($aTemplateData);
  174 + }
192 175 }
193 176  
194 177 $oDispatcher = new SimpleSearchDispatcher();
... ...
templates/ktcore/misc/columns/edit_view.smarty 0 → 100644
  1 +<h2>{i18n}Edit View{/i18n}</h2>
  2 +
  3 +<p class="descriptiveText">{i18n}The columns included in this view are displayed below. To add additional columns into the
  4 +view, use the form below the list. To remove items, click on the "delete" icon next to the column name. Note that some columns may be required
  5 +in a given view. Also, while you can
  6 +have multiple copies of a given column in a specific view this is not recommended.{/i18n}</p>
  7 +
  8 +{if (!empty($current_columns))}
  9 +<table class="kt_collection narrow" cellspacing="0">
  10 + <thead>
  11 + <tr>
  12 + <th>{i18n}Column{/i18n}</th>
  13 + <th>{i18n}Delete{/i18n}</th>
  14 + </tr>
  15 + </thead>
  16 + <tbody>
  17 + {foreach from=$current_columns item=oColumn}
  18 + <tr>
  19 + <td>{$oColumn->getName()}</td>
  20 +
  21 + {if $oColumn->getRequiredInView()}
  22 + <td>&mdash;</td>
  23 + {else}
  24 + <td><a href="{addQS}action=deleteEntry&entry_id={$oColumn->getEntryId()}&viewNS={$view}{/addQS}" class="ktAction ktDelete">{i18n}Delete{/i18n}</a></td>
  25 + {/if}
  26 + </tr>
  27 + {/foreach}
  28 + </tbody>
  29 +</table>
  30 +{else}
  31 +<div class="ktInfo"><p>{i18n}No columns have been added to this view{/i18n}</p></div>
  32 +{/if}
  33 +
  34 +<form method="POST" action="{$smarty.server.PHP_SELF}">
  35 +<fieldset>
  36 + <legend>{i18n}Add a Column{/i18n}</legend>
  37 +
  38 + {$add_field->render()}
  39 +
  40 + <div class="form_actions">
  41 + <input type="submit" value="{i18n}Add Column to View{/i18n}"/>
  42 + <input type="hidden" name="action" value="addEntry" />
  43 + <input type="hidden" name="viewNS" value="{$view}" />
  44 + </div>
  45 +</fieldset>
  46 +</form>
0 47 \ No newline at end of file
... ...
templates/ktcore/misc/columns/select_view.smarty 0 → 100644
  1 +<h2>{i18n}Select View{/i18n}</h2>
  2 +
  3 +<p class="descriptiveText">{i18n}Views are the selections of documents and folders you will find throughout KnowledgeTree. Some of those
  4 +can be configured to use different kinds of columns (e.g. workflow state, the creator's name, etc.){/i18n}</p>
  5 +
  6 +<ul>
  7 +{foreach from=$views key=viewNS item=viewName}
  8 + <li><a href="{addQS}action=editView&viewNS={$viewNS}{/addQS}">{$viewName}</a></li>
  9 +{/foreach}
  10 +</ul>
0 11 \ No newline at end of file
... ...