Commit 9650f889b3dd6c2a51fc41dcb41cfdbb8fce9317
1 parent
fc322e3f
Merged in from STABLE trunk...
KTS-3691 "CLONE -Is there a way to prevent from checking in the wrong file?(SUP-1064)" Fixed. Added a config option to hide the checkbox for "Force Original Filename". KTS-3736 "User should be made aware that setting the field limit for document filenames and titles beyond 255 is futile as only 255 characters are allowed in the fields in the DB." Fixed. Added a better description of the config option. KTC-592 "Better default tooltip needed on mouse over than 'ACME Corporation'." Fixed. Added a better tooltip as the default value for the config option. Committed by: Megan Watson Reviewed by: Conrad Vermeulen KTS-3741 "The Property Preview Panel lacks a scroll bar" Fixed. Changed overflow css from hidden to auto. Committed by: Megan Watson Reviewed by: Conrad Vermeulen KTC-613 "Error occur when creating a link to a new RSS feed" Fixed. Removed the javascript for the tinymce editor which isn't used. Committed by: Megan Watson Reviewed by: Conrad Vermeulen KTS-3306 "Search should return folders" Implemented. KTS-3671 "Support for searching of symbolic links" Implemented. Committed By: Conrad Vermeulen Reviewed By: Megan Watson KTS-3306 "Search should return folders" Implemented. KTS-3671 "Support for searching of symbolic links" Implemented. Committed By: Conrad Vermeulen Reviewed By: Megan Watson KTS-3630 "matching metadata is not translated on results page" Fixed. Committed By: Conrad Vermeulen Reviewed By: Megan Watson git-svn-id: https://kt-dms.svn.sourceforge.net/svnroot/kt-dms/STABLE/branches/3.5.3a-Release-Branch@9404 c91229c3-7414-0410-bfa2-8a42b809f60b
Showing
19 changed files
with
842 additions
and
367 deletions
plugins/ktcore/KTDocumentActions.php
| @@ -599,7 +599,8 @@ class KTDocumentCheckInAction extends KTDocumentAction { | @@ -599,7 +599,8 @@ class KTDocumentCheckInAction extends KTDocumentAction { | ||
| 599 | $major_inc = sprintf('%d.%d', $this->oDocument->getMajorVersionNumber()+1, 0); | 599 | $major_inc = sprintf('%d.%d', $this->oDocument->getMajorVersionNumber()+1, 0); |
| 600 | $minor_inc = sprintf('%d.%d', $this->oDocument->getMajorVersionNumber(), $this->oDocument->getMinorVersionNumber()+1); | 600 | $minor_inc = sprintf('%d.%d', $this->oDocument->getMajorVersionNumber(), $this->oDocument->getMinorVersionNumber()+1); |
| 601 | 601 | ||
| 602 | - $oForm->setWidgets(array( | 602 | + // Set the widgets for the form |
| 603 | + $aWidgets = array( | ||
| 603 | array('ktcore.widgets.file', array( | 604 | array('ktcore.widgets.file', array( |
| 604 | 'label' => _kt('File'), | 605 | 'label' => _kt('File'), |
| 605 | 'description' => sprintf(_kt('Please specify the file you wish to upload. Unless you also indicate that you are changing its filename (see "Force Original Filename" below), this will need to be called <strong>%s</strong>'), htmlentities($this->oDocument->getFilename(),ENT_QUOTES,'UTF-8')), | 606 | 'description' => sprintf(_kt('Please specify the file you wish to upload. Unless you also indicate that you are changing its filename (see "Force Original Filename" below), this will need to be called <strong>%s</strong>'), htmlentities($this->oDocument->getFilename(),ENT_QUOTES,'UTF-8')), |
| @@ -618,14 +619,10 @@ class KTDocumentCheckInAction extends KTDocumentAction { | @@ -618,14 +619,10 @@ class KTDocumentCheckInAction extends KTDocumentAction { | ||
| 618 | 'description' => _kt('Please describe the changes you made to the document. Bear in mind that you can use a maximum of <strong>250</strong> characters.'), | 619 | 'description' => _kt('Please describe the changes you made to the document. Bear in mind that you can use a maximum of <strong>250</strong> characters.'), |
| 619 | 'name' => 'reason', | 620 | 'name' => 'reason', |
| 620 | )), | 621 | )), |
| 621 | - array('ktcore.widgets.boolean',array( | ||
| 622 | - 'label' => _kt('Force Original Filename'), | ||
| 623 | - 'description' => sprintf(_kt('If this is checked, the uploaded document must have the same filename as the original: <strong>%s</strong>'), htmlentities($this->oDocument->getFilename(),ENT_QUOTES,'UTF-8')), | ||
| 624 | - 'name' => 'forcefilename', | ||
| 625 | - 'value' => true, | ||
| 626 | - )), | ||
| 627 | - )); | ||
| 628 | - $oForm->setValidators(array( | 622 | + ); |
| 623 | + | ||
| 624 | + // Set the validators for the widgets | ||
| 625 | + $aValidators = array( | ||
| 629 | array('ktcore.validators.string', array( | 626 | array('ktcore.validators.string', array( |
| 630 | 'test' => 'reason', | 627 | 'test' => 'reason', |
| 631 | 'max_length' => 250, | 628 | 'max_length' => 250, |
| @@ -639,12 +636,27 @@ class KTDocumentCheckInAction extends KTDocumentAction { | @@ -639,12 +636,27 @@ class KTDocumentCheckInAction extends KTDocumentAction { | ||
| 639 | 'test' => 'file', | 636 | 'test' => 'file', |
| 640 | 'output' => 'file', | 637 | 'output' => 'file', |
| 641 | )), | 638 | )), |
| 642 | - array('ktcore.validators.boolean', array( | 639 | + ); |
| 640 | + | ||
| 641 | + // Add the "Force Original Filename" option if applicable | ||
| 642 | + global $default; | ||
| 643 | + if(!$default->disableForceFilenameOption){ | ||
| 644 | + $aWidgets[] = array('ktcore.widgets.boolean',array( | ||
| 645 | + 'label' => _kt('Force Original Filename'), | ||
| 646 | + 'description' => sprintf(_kt('If this is checked, the uploaded document must have the same filename as the original: <strong>%s</strong>'), htmlentities($this->oDocument->getFilename(),ENT_QUOTES,'UTF-8')), | ||
| 647 | + 'name' => 'forcefilename', | ||
| 648 | + 'value' => true, | ||
| 649 | + )); | ||
| 650 | + | ||
| 651 | + $aValidators[] = array('ktcore.validators.boolean', array( | ||
| 643 | 'test' => 'forcefilename', | 652 | 'test' => 'forcefilename', |
| 644 | 'output' => 'forcefilename', | 653 | 'output' => 'forcefilename', |
| 645 | - )), | ||
| 646 | - )); | 654 | + )); |
| 655 | + } | ||
| 647 | 656 | ||
| 657 | + // Add widgets and validators to the form | ||
| 658 | + $oForm->setWidgets($aWidgets); | ||
| 659 | + $oForm->setValidators($aValidators); | ||
| 648 | return $oForm; | 660 | return $oForm; |
| 649 | } | 661 | } |
| 650 | 662 | ||
| @@ -669,8 +681,16 @@ class KTDocumentCheckInAction extends KTDocumentAction { | @@ -669,8 +681,16 @@ class KTDocumentCheckInAction extends KTDocumentAction { | ||
| 669 | 681 | ||
| 670 | $extra_errors = array(); | 682 | $extra_errors = array(); |
| 671 | 683 | ||
| 672 | - if ($data['forcefilename'] && ($data['file']['name'] != $this->oDocument->getFilename())) { | ||
| 673 | - $extra_errors['file'] = sprintf(_kt('The file you uploaded was not called "%s". If you wish to change the filename, please set "Force Original Filename" below to false. '), htmlentities($this->oDocument->getFilename(),ENT_QUOTES,'UTF-8')); | 684 | + // If the filename is different to the original check if "Force Original Filename" is set and return an error if it is. |
| 685 | + $docFileName = $this->oDocument->getFilename(); | ||
| 686 | + if($data['file']['name'] != $docFileName){ | ||
| 687 | + global $default; | ||
| 688 | + | ||
| 689 | + if($default->disableForceFilenameOption){ | ||
| 690 | + $extra_errors['file'] = sprintf(_kt('The file you uploaded was not called "%s". The file must have the same name as the original file.'), htmlentities($docFileName,ENT_QUOTES,'UTF-8')); | ||
| 691 | + }else if ($data['forcefilename']) { | ||
| 692 | + $extra_errors['file'] = sprintf(_kt('The file you uploaded was not called "%s". If you wish to change the filename, please set "Force Original Filename" below to false. '), htmlentities($docFileName,ENT_QUOTES,'UTF-8')); | ||
| 693 | + } | ||
| 674 | } | 694 | } |
| 675 | 695 | ||
| 676 | if (!empty($res['errors']) || !empty($extra_errors)) { | 696 | if (!empty($res['errors']) || !empty($extra_errors)) { |
| @@ -679,7 +699,7 @@ class KTDocumentCheckInAction extends KTDocumentAction { | @@ -679,7 +699,7 @@ class KTDocumentCheckInAction extends KTDocumentAction { | ||
| 679 | 699 | ||
| 680 | $sReason = $data['reason']; | 700 | $sReason = $data['reason']; |
| 681 | 701 | ||
| 682 | - $sCurrentFilename = $this->oDocument->getFileName(); | 702 | + $sCurrentFilename = $docFileName; |
| 683 | $sNewFilename = $data['file']['name']; | 703 | $sNewFilename = $data['file']['name']; |
| 684 | 704 | ||
| 685 | $aOptions = array(); | 705 | $aOptions = array(); |
plugins/ktstandard/documentpreview/resources/container.css
plugins/ktstandard/documentpreview/resources/preview.js
| @@ -15,7 +15,7 @@ var showInfo = function(iDocId, sUrl, sDir, loading){ | @@ -15,7 +15,7 @@ var showInfo = function(iDocId, sUrl, sDir, loading){ | ||
| 15 | modal: true, | 15 | modal: true, |
| 16 | plain: false, | 16 | plain: false, |
| 17 | width: 500, | 17 | width: 500, |
| 18 | - height: 300, | 18 | + height: 360, |
| 19 | minWidth: 300, | 19 | minWidth: 300, |
| 20 | minHeight: 250 | 20 | minHeight: 250 |
| 21 | }); | 21 | }); |
plugins/rssplugin/loadFeed.inc.php
| @@ -48,7 +48,7 @@ | @@ -48,7 +48,7 @@ | ||
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | // Check if the feed matches a url | 50 | // Check if the feed matches a url |
| 51 | - if(!preg_match("/^http:\/\/([^\/]+)(.*)$/", $feed, $matches)){ | 51 | + if(!preg_match("/^http[s]?:\/\/([^\/]+)(.*)$/", $feed, $matches)){ |
| 52 | // If not, it is an internal feed | 52 | // If not, it is an internal feed |
| 53 | $aRSSArray = KTrss::getInternalFeed($user); | 53 | $aRSSArray = KTrss::getInternalFeed($user); |
| 54 | }else{ | 54 | }else{ |
plugins/rssplugin/rss2array.inc.php
| @@ -7,31 +7,31 @@ | @@ -7,31 +7,31 @@ | ||
| 7 | * Document Management Made Simple | 7 | * Document Management Made Simple |
| 8 | * Copyright (C) 2008 KnowledgeTree Inc. | 8 | * Copyright (C) 2008 KnowledgeTree Inc. |
| 9 | * Portions copyright The Jam Warehouse Software (Pty) Limited | 9 | * Portions copyright The Jam Warehouse Software (Pty) Limited |
| 10 | - * | 10 | + * |
| 11 | * This program is free software; you can redistribute it and/or modify it under | 11 | * This program is free software; you can redistribute it and/or modify it under |
| 12 | * the terms of the GNU General Public License version 3 as published by the | 12 | * the terms of the GNU General Public License version 3 as published by the |
| 13 | * Free Software Foundation. | 13 | * Free Software Foundation. |
| 14 | - * | 14 | + * |
| 15 | * This program is distributed in the hope that it will be useful, but WITHOUT | 15 | * This program is distributed in the hope that it will be useful, but WITHOUT |
| 16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | 16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| 17 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more | 17 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
| 18 | * details. | 18 | * details. |
| 19 | - * | 19 | + * |
| 20 | * You should have received a copy of the GNU General Public License | 20 | * You should have received a copy of the GNU General Public License |
| 21 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 21 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 22 | - * | ||
| 23 | - * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco, | 22 | + * |
| 23 | + * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco, | ||
| 24 | * California 94120-7775, or email info@knowledgetree.com. | 24 | * California 94120-7775, or email info@knowledgetree.com. |
| 25 | - * | 25 | + * |
| 26 | * The interactive user interfaces in modified source and object code versions | 26 | * The interactive user interfaces in modified source and object code versions |
| 27 | * of this program must display Appropriate Legal Notices, as required under | 27 | * of this program must display Appropriate Legal Notices, as required under |
| 28 | * Section 5 of the GNU General Public License version 3. | 28 | * Section 5 of the GNU General Public License version 3. |
| 29 | - * | 29 | + * |
| 30 | * In accordance with Section 7(b) of the GNU General Public License version 3, | 30 | * In accordance with Section 7(b) of the GNU General Public License version 3, |
| 31 | * these Appropriate Legal Notices must retain the display of the "Powered by | 31 | * these Appropriate Legal Notices must retain the display of the "Powered by |
| 32 | - * KnowledgeTree" logo and retain the original copyright notice. If the display of the | 32 | + * KnowledgeTree" logo and retain the original copyright notice. If the display of the |
| 33 | * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices | 33 | * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices |
| 34 | - * must display the words "Powered by KnowledgeTree" and retain the original | 34 | + * must display the words "Powered by KnowledgeTree" and retain the original |
| 35 | * copyright notice. | 35 | * copyright notice. |
| 36 | * Contributor( s): ______________________________________ | 36 | * Contributor( s): ______________________________________ |
| 37 | * | 37 | * |
| @@ -62,7 +62,7 @@ | @@ -62,7 +62,7 @@ | ||
| 62 | # if the URL looks ok | 62 | # if the URL looks ok |
| 63 | # | 63 | # |
| 64 | 64 | ||
| 65 | - if(preg_match("/^http:\/\/([^\/]+)(.*)$/", $url, $matches)){ | 65 | + if(preg_match("/^http[s]?:\/\/([^\/]+)(.*)$/", $url, $matches)){ |
| 66 | 66 | ||
| 67 | $host = $matches[1]; | 67 | $host = $matches[1]; |
| 68 | $uri = $matches[2]; | 68 | $uri = $matches[2]; |
plugins/rssplugin/templates/RSSPlugin/addfeed.smarty
| 1 | -{$context->oPage->requireJSResource("thirdpartyjs/tinymce/jscripts/tiny_mce/tiny_mce.js")} | ||
| 2 | -{capture assign=sJS} | ||
| 3 | -{literal} | ||
| 4 | -tinyMCE.init({ | ||
| 5 | - mode : "textareas", | ||
| 6 | - theme : "simple", | ||
| 7 | -}); | ||
| 8 | -{/literal} | ||
| 9 | -{/capture} | ||
| 10 | -{$context->oPage->requireJSStandalone($sJS)} | ||
| 11 | - | ||
| 12 | - | ||
| 13 | - | ||
| 14 | <h2>{i18n}New RSS Feed{/i18n}</h2> | 1 | <h2>{i18n}New RSS Feed{/i18n}</h2> |
| 15 | 2 | ||
| 16 | <p class="descriptiveText">{i18n}Create a rss feed which will be displayed on the dashboard{/i18n}</p> | 3 | <p class="descriptiveText">{i18n}Create a rss feed which will be displayed on the dashboard{/i18n}</p> |
plugins/rssplugin/templates/RSSPlugin/editfeed.smarty
| 1 | -{$context->oPage->requireJSResource("thirdpartyjs/tinymce/jscripts/tiny_mce/tiny_mce.js")} | ||
| 2 | -{capture assign=sJS} | ||
| 3 | -{literal} | ||
| 4 | -tinyMCE.init({ | ||
| 5 | - mode : "textareas", | ||
| 6 | - theme : "simple", | ||
| 7 | -}); | ||
| 8 | -{/literal} | ||
| 9 | -{/capture} | ||
| 10 | -{$context->oPage->requireJSStandalone($sJS)} | ||
| 11 | - | ||
| 12 | - | ||
| 13 | - | ||
| 14 | <h2>{i18n}Edit RSS Feed{/i18n}</h2> | 1 | <h2>{i18n}Edit RSS Feed{/i18n}</h2> |
| 15 | 2 | ||
| 16 | <p class="descriptiveText">{i18n}Edit a RSS feed{/i18n}</p> | 3 | <p class="descriptiveText">{i18n}Edit a RSS feed{/i18n}</p> |
search2.php
| @@ -35,15 +35,20 @@ | @@ -35,15 +35,20 @@ | ||
| 35 | * Contributor( s): ______________________________________ | 35 | * Contributor( s): ______________________________________ |
| 36 | */ | 36 | */ |
| 37 | 37 | ||
| 38 | +// TODO: do we have to serialise/unserialise the results. this is not optimal!!! | ||
| 39 | + | ||
| 38 | session_start(); | 40 | session_start(); |
| 39 | require_once("config/dmsDefaults.php"); | 41 | require_once("config/dmsDefaults.php"); |
| 42 | +require_once(KT_DIR . '/search2/indexing/indexerCore.inc.php'); | ||
| 43 | + | ||
| 40 | require_once(KT_LIB_DIR . "/unitmanagement/Unit.inc"); | 44 | require_once(KT_LIB_DIR . "/unitmanagement/Unit.inc"); |
| 41 | 45 | ||
| 42 | require_once(KT_LIB_DIR . "/templating/templating.inc.php"); | 46 | require_once(KT_LIB_DIR . "/templating/templating.inc.php"); |
| 43 | require_once(KT_LIB_DIR . "/dispatcher.inc.php"); | 47 | require_once(KT_LIB_DIR . "/dispatcher.inc.php"); |
| 44 | require_once(KT_LIB_DIR . "/widgets/forms.inc.php"); | 48 | require_once(KT_LIB_DIR . "/widgets/forms.inc.php"); |
| 45 | require_once(KT_LIB_DIR . "/actions/bulkaction.php"); | 49 | require_once(KT_LIB_DIR . "/actions/bulkaction.php"); |
| 46 | -require_once(KT_DIR . '/search2/search/search.inc.php'); | 50 | + |
| 51 | +require_once(KT_LIB_DIR . '/browse/DocumentCollection.inc.php'); | ||
| 47 | require_once(KT_LIB_DIR . '/documentmanagement/Document.inc'); | 52 | require_once(KT_LIB_DIR . '/documentmanagement/Document.inc'); |
| 48 | require_once(KT_LIB_DIR . '/browse/PartialQuery.inc.php'); | 53 | require_once(KT_LIB_DIR . '/browse/PartialQuery.inc.php'); |
| 49 | 54 | ||
| @@ -117,7 +122,6 @@ function search2QuerySort($sSortColumn, $sSortOrder) | @@ -117,7 +122,6 @@ function search2QuerySort($sSortColumn, $sSortOrder) | ||
| 117 | return; | 122 | return; |
| 118 | } | 123 | } |
| 119 | 124 | ||
| 120 | - | ||
| 121 | $results = unserialize($_SESSION['search2_results']); | 125 | $results = unserialize($_SESSION['search2_results']); |
| 122 | 126 | ||
| 123 | usort($results, 'search2queryCompare'); | 127 | usort($results, 'search2queryCompare'); |
| @@ -132,38 +136,70 @@ function search2QuerySort($sSortColumn, $sSortOrder) | @@ -132,38 +136,70 @@ function search2QuerySort($sSortColumn, $sSortOrder) | ||
| 132 | */ | 136 | */ |
| 133 | class Search2Query extends PartialQuery | 137 | class Search2Query extends PartialQuery |
| 134 | { | 138 | { |
| 135 | - function getFolderCount() { return 0; } | 139 | + function _count($type) |
| 140 | + { | ||
| 141 | + $count = 0; | ||
| 142 | + $results = unserialize($_SESSION['search2_results']); | ||
| 143 | + | ||
| 144 | + switch ($type) | ||
| 145 | + { | ||
| 146 | + case 'Document': | ||
| 147 | + return count($results['docs']) + count($results['shortdocs']); | ||
| 148 | + case 'Folder': | ||
| 149 | + return count($results['folders']) + count($results['shortfolders']); | ||
| 150 | + default: | ||
| 151 | + return 0; | ||
| 152 | + } | ||
| 153 | + } | ||
| 154 | + | ||
| 155 | + function getFolderCount() | ||
| 156 | + { | ||
| 157 | + return $this->_count('Folder'); | ||
| 158 | + } | ||
| 136 | function getDocumentCount() | 159 | function getDocumentCount() |
| 137 | { | 160 | { |
| 138 | - $results = $_SESSION['search2_results']; | ||
| 139 | - if(isset($results) && !empty($results)){ | ||
| 140 | - return count(unserialize($results)); | 161 | + return $this->_count('Document'); |
| 162 | + } | ||
| 163 | + | ||
| 164 | + function getItems($type, $iStart, $iSize, $sSortColumn, $sSortOrder) | ||
| 165 | + { | ||
| 166 | + // TODO: quick hack. do this more optimally!!!! | ||
| 167 | + $results = unserialize($_SESSION['search2_results']); | ||
| 168 | + | ||
| 169 | + switch ($type) | ||
| 170 | + { | ||
| 171 | + case 'Document': | ||
| 172 | + $type = 'docs'; | ||
| 173 | + break; | ||
| 174 | + case 'Folder': | ||
| 175 | + $type = 'folders'; | ||
| 176 | + break; | ||
| 141 | } | 177 | } |
| 142 | - return 0; | 178 | + |
| 179 | + $resultArray = $results[$type]; | ||
| 180 | + foreach($results['short' . $type] as $rec) | ||
| 181 | + { | ||
| 182 | + $resultArray[] = $rec; | ||
| 183 | + } | ||
| 184 | + | ||
| 185 | + $resultArray = array_slice($resultArray, $iStart, $iSize); | ||
| 186 | + $results = array(); | ||
| 187 | + foreach($resultArray as $rec) | ||
| 188 | + { | ||
| 189 | + $results[] = array('id'=>$rec->Id); | ||
| 190 | + } | ||
| 191 | + | ||
| 192 | + return $results; | ||
| 143 | } | 193 | } |
| 144 | 194 | ||
| 145 | function getFolders($iBatchSize, $iBatchStart, $sSortColumn, $sSortOrder, $sJoinClause = null, $aJoinParams = null) | 195 | function getFolders($iBatchSize, $iBatchStart, $sSortColumn, $sSortOrder, $sJoinClause = null, $aJoinParams = null) |
| 146 | { | 196 | { |
| 147 | - return array(); | 197 | + return $this->getItems('Folder', $iBatchStart, $iBatchSize, $sSortColumn, $sSortOrder); |
| 148 | } | 198 | } |
| 149 | 199 | ||
| 150 | function getDocuments($iBatchSize, $iBatchStart, $sSortColumn, $sSortOrder, $sJoinClause = null, $aJoinParams = null) | 200 | function getDocuments($iBatchSize, $iBatchStart, $sSortColumn, $sSortOrder, $sJoinClause = null, $aJoinParams = null) |
| 151 | { | 201 | { |
| 152 | - search2QuerySort($_GET['sort_on'], $_GET['sort_order']); | ||
| 153 | - $results = unserialize($_SESSION['search2_results']); | ||
| 154 | - | ||
| 155 | - $batch = array(); | ||
| 156 | - | ||
| 157 | - $no_results = count($results); | ||
| 158 | - for($i=0;$i<$no_results;$i++) | ||
| 159 | - { | ||
| 160 | - if ($i < $iBatchStart) continue; | ||
| 161 | - if ($i > $iBatchStart + $iBatchSize) continue; | ||
| 162 | - | ||
| 163 | - $batch[] = array('id'=>$results[$i]->DocumentID); | ||
| 164 | - } | ||
| 165 | - | ||
| 166 | - return $batch; | 202 | + return $this->getItems('Document', $iBatchStart, $iBatchSize, $sSortColumn, $sSortOrder); |
| 167 | } | 203 | } |
| 168 | } | 204 | } |
| 169 | 205 | ||
| @@ -208,10 +244,12 @@ class SearchDispatcher extends KTStandardDispatcher { | @@ -208,10 +244,12 @@ class SearchDispatcher extends KTStandardDispatcher { | ||
| 208 | { | 244 | { |
| 209 | $expr = parseExpression($query); | 245 | $expr = parseExpression($query); |
| 210 | 246 | ||
| 211 | - $result = $expr->evaluate(); | ||
| 212 | - usort($result, 'rank_compare'); | 247 | + $results = $expr->evaluate(); |
| 248 | + $results = resolveSearchShortcuts($results); | ||
| 213 | 249 | ||
| 214 | - $_SESSION['search2_results'] = serialize($result); | 250 | + usort($result['docs'], 'rank_compare'); |
| 251 | + | ||
| 252 | + $_SESSION['search2_results'] = serialize($results); | ||
| 215 | $_SESSION['search2_query'] = $query; | 253 | $_SESSION['search2_query'] = $query; |
| 216 | $_SESSION['search2_sort'] = 'rank'; | 254 | $_SESSION['search2_sort'] = 'rank'; |
| 217 | 255 | ||
| @@ -410,6 +448,15 @@ class SearchDispatcher extends KTStandardDispatcher { | @@ -410,6 +448,15 @@ class SearchDispatcher extends KTStandardDispatcher { | ||
| 410 | 448 | ||
| 411 | $results = unserialize($_SESSION['search2_results']); | 449 | $results = unserialize($_SESSION['search2_results']); |
| 412 | 450 | ||
| 451 | + // NOTE: sorting results (when it is implemented) might have to be done per section, as it is done with the browse view | ||
| 452 | + | ||
| 453 | + $resultArray = $results['docs']; | ||
| 454 | + foreach($results['folders'] as $f) $resultArray[] = $f; | ||
| 455 | + foreach($results['shortdocs'] as $d) $resultArray[] = $d; | ||
| 456 | + foreach($results['shortfolders'] as $f) $resultArray[] = $f; | ||
| 457 | + | ||
| 458 | + $results = $resultArray; | ||
| 459 | + | ||
| 413 | if (!is_array($results) || count($results) == 0) | 460 | if (!is_array($results) || count($results) == 0) |
| 414 | { | 461 | { |
| 415 | $results=array(); | 462 | $results=array(); |
search2/indexing/indexerCore.inc.php
| @@ -41,17 +41,142 @@ define('SEARCH2_INDEXER_DIR',realpath(dirname(__FILE__)) . '/'); | @@ -41,17 +41,142 @@ define('SEARCH2_INDEXER_DIR',realpath(dirname(__FILE__)) . '/'); | ||
| 41 | require_once('indexing/extractorCore.inc.php'); | 41 | require_once('indexing/extractorCore.inc.php'); |
| 42 | require_once(KT_DIR . '/plugins/ktcore/scheduler/schedulerUtil.php'); | 42 | require_once(KT_DIR . '/plugins/ktcore/scheduler/schedulerUtil.php'); |
| 43 | 43 | ||
| 44 | - | ||
| 45 | class IndexerInconsistencyException extends Exception {}; | 44 | class IndexerInconsistencyException extends Exception {}; |
| 46 | 45 | ||
| 46 | +// TODO: Query Result Items code should be moved into the Search section. It has less to do with indexing... | ||
| 47 | + | ||
| 47 | class QueryResultItem | 48 | class QueryResultItem |
| 48 | { | 49 | { |
| 49 | - protected $document_id; | 50 | + protected $id; |
| 50 | protected $title; | 51 | protected $title; |
| 51 | protected $rank; | 52 | protected $rank; |
| 52 | protected $text; | 53 | protected $text; |
| 53 | - protected $filesize; | ||
| 54 | protected $fullpath; | 54 | protected $fullpath; |
| 55 | + | ||
| 56 | + public function __construct($id, $title, $rank, $text, $fullpath) | ||
| 57 | + { | ||
| 58 | + $this->id = $id; | ||
| 59 | + $this->title = $title; | ||
| 60 | + $this->rank = $rank; | ||
| 61 | + $this->text = $text; | ||
| 62 | + $this->fullpath = $fullpath; | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + public function getId() { return $this->id; } | ||
| 66 | + | ||
| 67 | + public function getIsProxy() { return $this instanceof ProxyResultItem; } | ||
| 68 | + public function getIsFolder() { return substr(get_class($this), 0, 6) == 'Folder' ; } | ||
| 69 | + public function getIsDocument() { return substr(get_class($this), 0, 8) == 'Document' ; } | ||
| 70 | + | ||
| 71 | + public function setRank($value) | ||
| 72 | + { | ||
| 73 | + $this->rank = number_format($value,2,'.',','); | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + public function getIsLive() | ||
| 77 | + { | ||
| 78 | + return true; | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + public function setTitle($value) | ||
| 82 | + { | ||
| 83 | + $this->title = $value; | ||
| 84 | + } | ||
| 85 | + | ||
| 86 | + public function setText($value) | ||
| 87 | + { | ||
| 88 | + $this->text = $value; | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + public function getRelevance() { return (float) $this->rank; } | ||
| 92 | + public function getRank() { return $this->getRelevance(); } | ||
| 93 | + public function getText() { return (string) $this->text; } | ||
| 94 | + public function getTitle() { return (string) $this->title; } | ||
| 95 | + public function getFullPath() { return (string) $this->fullpath; } | ||
| 96 | + | ||
| 97 | + protected function __get($property) | ||
| 98 | + { | ||
| 99 | + if (empty($property)) | ||
| 100 | + { | ||
| 101 | + return ''; | ||
| 102 | + } | ||
| 103 | + | ||
| 104 | + $method = 'get' . $property; | ||
| 105 | + if (method_exists($this, $method)) | ||
| 106 | + { | ||
| 107 | + return $this->$method(); | ||
| 108 | + } | ||
| 109 | + return $this->getUnknown(); | ||
| 110 | + } | ||
| 111 | + | ||
| 112 | + protected function getUnknown() | ||
| 113 | + { | ||
| 114 | + return _kt('n/a'); | ||
| 115 | + } | ||
| 116 | + | ||
| 117 | + protected function __set($property, $value) | ||
| 118 | + { | ||
| 119 | + if (empty($property)) | ||
| 120 | + { | ||
| 121 | + return ''; | ||
| 122 | + } | ||
| 123 | + | ||
| 124 | + $method = 'set' . $property; | ||
| 125 | + if (method_exists($this, $method)) | ||
| 126 | + { | ||
| 127 | + return $this->$method($value); | ||
| 128 | + } | ||
| 129 | + throw new Exception("Unknown property '$property' to set on QueryResultItem"); | ||
| 130 | + } | ||
| 131 | +} | ||
| 132 | + | ||
| 133 | +class ProxyResultItem extends QueryResultItem | ||
| 134 | +{ | ||
| 135 | + protected $proxy; | ||
| 136 | + protected $proxyId; | ||
| 137 | + | ||
| 138 | + public function __construct($proxyId, $proxy) | ||
| 139 | + { | ||
| 140 | + parent::__construct($proxyId, $proxy->getTitle, $proxy->getRank(), $proxy->getText(), $proxy->getFullPath()); | ||
| 141 | + $this->proxyId = $proxyId; | ||
| 142 | + $this->proxy = $proxy; | ||
| 143 | + } | ||
| 144 | + | ||
| 145 | + public function getId() { return $this->proxyId; } | ||
| 146 | + public function getTitle() { return $this->proxy->getTitle(); } | ||
| 147 | + public function getRealId() { return $this->proxy->getId(); } | ||
| 148 | + | ||
| 149 | + protected function __get($property) | ||
| 150 | + { | ||
| 151 | + $method = 'get' . $property; | ||
| 152 | + | ||
| 153 | + if (method_exists($this, $method)) | ||
| 154 | + { | ||
| 155 | + return $this->$method(); | ||
| 156 | + } | ||
| 157 | + else | ||
| 158 | + { | ||
| 159 | + return $this->proxy->$method(); | ||
| 160 | + } | ||
| 161 | + } | ||
| 162 | + | ||
| 163 | + protected function __set($property, $value) | ||
| 164 | + { | ||
| 165 | + $method = 'set' . $property; | ||
| 166 | + if (method_exists($this, $method)) | ||
| 167 | + { | ||
| 168 | + return $this->$method($value); | ||
| 169 | + } | ||
| 170 | + else | ||
| 171 | + { | ||
| 172 | + return $this->proxy->$method($value); | ||
| 173 | + } | ||
| 174 | + } | ||
| 175 | +} | ||
| 176 | + | ||
| 177 | +class DocumentResultItem extends QueryResultItem | ||
| 178 | +{ | ||
| 179 | + protected $filesize; | ||
| 55 | protected $live; | 180 | protected $live; |
| 56 | protected $version; | 181 | protected $version; |
| 57 | protected $mimeType; | 182 | protected $mimeType; |
| @@ -78,17 +203,14 @@ class QueryResultItem | @@ -78,17 +203,14 @@ class QueryResultItem | ||
| 78 | protected $mimeDisplay; | 203 | protected $mimeDisplay; |
| 79 | protected $oemDocumentNo; | 204 | protected $oemDocumentNo; |
| 80 | 205 | ||
| 81 | - public function __construct($document_id, $rank=null, $title=null, $text=null) | 206 | + public function __construct($document_id, $rank=null, $title=null, $text=null, $fullpath = null) |
| 82 | { | 207 | { |
| 83 | - $this->document_id=(int) $document_id; | ||
| 84 | - $this->rank= $rank; | ||
| 85 | - $this->title=$title; | ||
| 86 | - $this->text = $text; | 208 | + parent::__construct($document_id, $title, $rank, $text, $fullpath); |
| 87 | $this->live = true; | 209 | $this->live = true; |
| 88 | $this->loadDocumentInfo(); | 210 | $this->loadDocumentInfo(); |
| 89 | } | 211 | } |
| 90 | 212 | ||
| 91 | - protected function __isset($property) | 213 | + /*protected function __isset($property) |
| 92 | { | 214 | { |
| 93 | switch($property) | 215 | switch($property) |
| 94 | { | 216 | { |
| @@ -101,8 +223,9 @@ class QueryResultItem | @@ -101,8 +223,9 @@ class QueryResultItem | ||
| 101 | throw new Exception("Unknown property '$property' to get on QueryResultItem"); | 223 | throw new Exception("Unknown property '$property' to get on QueryResultItem"); |
| 102 | } | 224 | } |
| 103 | return true; // should not be reached | 225 | return true; // should not be reached |
| 104 | - } | 226 | + }*/ |
| 105 | 227 | ||
| 228 | + // TODO: this is bad. must refactor to do the query on the group of documents. | ||
| 106 | public function loadDocumentInfo() | 229 | public function loadDocumentInfo() |
| 107 | { | 230 | { |
| 108 | global $default; | 231 | global $default; |
| @@ -127,7 +250,7 @@ class QueryResultItem | @@ -127,7 +250,7 @@ class QueryResultItem | ||
| 127 | LEFT JOIN users cbu ON d.creator_id=cbu.id | 250 | LEFT JOIN users cbu ON d.creator_id=cbu.id |
| 128 | LEFT JOIN users ou ON d.owner_id=ou.id | 251 | LEFT JOIN users ou ON d.owner_id=ou.id |
| 129 | WHERE | 252 | WHERE |
| 130 | - d.id=$this->document_id"; | 253 | + d.id=$this->id"; |
| 131 | 254 | ||
| 132 | $result = DBUtil::getOneResult($sql); | 255 | $result = DBUtil::getOneResult($sql); |
| 133 | 256 | ||
| @@ -186,107 +309,116 @@ class QueryResultItem | @@ -186,107 +309,116 @@ class QueryResultItem | ||
| 186 | 309 | ||
| 187 | $this->mimeType = $result['mimetype']; | 310 | $this->mimeType = $result['mimetype']; |
| 188 | $this->mimeIconPath = $result['mime_icon_path']; | 311 | $this->mimeIconPath = $result['mime_icon_path']; |
| 312 | + if (empty($this->mimeIconPath)) | ||
| 313 | + { | ||
| 314 | + $this->mimeIconPath = 'unspecified_type'; | ||
| 315 | + } | ||
| 189 | $this->mimeDisplay = $result['mime_display']; | 316 | $this->mimeDisplay = $result['mime_display']; |
| 190 | 317 | ||
| 191 | $this->storagePath = $result['storage_path']; | 318 | $this->storagePath = $result['storage_path']; |
| 192 | $this->status = Document::getStatusString($result['status_id']); | 319 | $this->status = Document::getStatusString($result['status_id']); |
| 193 | } | 320 | } |
| 194 | 321 | ||
| 195 | - protected function __get($property) | ||
| 196 | - { | ||
| 197 | - switch($property) | ||
| 198 | - { | ||
| 199 | - case null: return ''; | ||
| 200 | - case 'DocumentID': return (int) $this->document_id; | ||
| 201 | - case 'Relevance': | ||
| 202 | - case 'Rank': return (float) $this->rank; | ||
| 203 | - case 'Text': return (string) $this->text; | ||
| 204 | - case 'Title': return (string) $this->title; | ||
| 205 | - case 'FullPath': return (string) $this->fullpath; | ||
| 206 | - case 'IsLive': return (bool) $this->live; | ||
| 207 | - case 'Filesize': return $this->filesize; | ||
| 208 | - case 'Version': return (string) $this->version; | ||
| 209 | - case 'Filename': return (string)$this->filename; | ||
| 210 | - case 'FolderId': return (int)$this->folderId; | ||
| 211 | - case 'OemDocumentNo': return (string) $this->oemDocumentNo; | ||
| 212 | - case 'Document': | ||
| 213 | - if (is_null($this->document)) | 322 | + public function getDocumentID() { return $this->getId(); } |
| 323 | + public function getIsLive() { return (bool) $this->live; } | ||
| 324 | + public function getFilesize() { return $this->filesize; } | ||
| 325 | + public function getVersion() { return (string) $this->version; } | ||
| 326 | + public function getFilename() { return (string)$this->filename; } | ||
| 327 | + public function getFolderId() { return (int)$this->folderId; } | ||
| 328 | + public function getOemDocumentNo() { return (string) $this->oemDocumentNo; } | ||
| 329 | + public function getDocument() { if (is_null($this->document)) | ||
| 214 | { | 330 | { |
| 215 | - $this->document = Document::get($this->document_id); | 331 | + $this->document = Document::get($this->id); |
| 216 | } | 332 | } |
| 217 | - return $this->document; | ||
| 218 | - case 'IsAvailable': | ||
| 219 | - return $this->Document->isLive(); | ||
| 220 | - case 'CheckedOutUser': | ||
| 221 | - case 'CheckedOutBy': | ||
| 222 | - return (string) $this->checkedOutUser; | ||
| 223 | - case 'WorkflowOnly': | ||
| 224 | - case 'Workflow': | ||
| 225 | - return (string)$this->workflow; | ||
| 226 | - case 'WorkflowStateOnly': | ||
| 227 | - case 'WorkflowState': | ||
| 228 | - return (string)$this->workflowState; | ||
| 229 | - case 'WorkflowAndState': | ||
| 230 | - if (is_null($this->workflow)) | 333 | + return $this->document; } |
| 334 | + public function getIsAvailable() { return $this->Document->isLive(); } | ||
| 335 | + public function getCheckedOutUser() { return (string) $this->checkedOutUser; } | ||
| 336 | + public function getCheckedOutByr() { return $this->getCheckedOutUser(); } | ||
| 337 | + public function getWorkflowOnly() { return (string)$this->workflow; } | ||
| 338 | + public function getWorkflow() { return $this->getWorkflow(); } | ||
| 339 | + public function getWorkflowStateOnly() { return (string)$this->workflowState; } | ||
| 340 | + public function getWorkflowState() { return $this->getWorkflowStateOnly(); } | ||
| 341 | + public function getWorkflowAndState() { if (is_null($this->workflow)) | ||
| 231 | { | 342 | { |
| 232 | return ''; | 343 | return ''; |
| 233 | } | 344 | } |
| 234 | - return "$this->workflow - $this->workflowState"; | ||
| 235 | - case 'MimeType': | ||
| 236 | - return (string) $this->mimeType; | ||
| 237 | - case 'MimeIconPath': | ||
| 238 | - return (string) $this->mimeIconPath; | ||
| 239 | - case 'MimeDisplay': | ||
| 240 | - return (string) $this->mimeDisplay; | ||
| 241 | - case 'DateCheckedOut': | ||
| 242 | - return (string) $this->dateCheckedout; | ||
| 243 | - case 'ModifiedBy': | ||
| 244 | - return (string) $this->modifiedBy; | ||
| 245 | - case 'DateModified': | ||
| 246 | - return (string) $this->dateModified; | ||
| 247 | - case 'CreatedBy': | ||
| 248 | - return (string) $this->createdBy; | ||
| 249 | - case 'DateCreated': | ||
| 250 | - return (string) $this->dateCreated; | ||
| 251 | - case 'Owner': | ||
| 252 | - case 'OwnedBy': | ||
| 253 | - return (string) $this->owner; | ||
| 254 | - case 'IsImmutable': | ||
| 255 | - case 'Immutable': | ||
| 256 | - return (bool) $this->immutable; | ||
| 257 | - case 'Status': | ||
| 258 | - return $this->status; | ||
| 259 | - case 'StoragePath': | ||
| 260 | - return $this->storagePath; | ||
| 261 | - case 'DocumentType': | ||
| 262 | - return $this->documentType; | ||
| 263 | - case 'Permissions': | ||
| 264 | - return 'not available'; | ||
| 265 | - case 'CanBeReadByUser': | ||
| 266 | - if (!$this->live) | 345 | + return "$this->workflow - $this->workflowState"; } |
| 346 | + public function getMimeType() { return (string) $this->mimeType; } | ||
| 347 | + public function getMimeIconPath() { return (string) $this->mimeIconPath; } | ||
| 348 | + public function getMimeDisplay() { return (string) $this->mimeDisplay; } | ||
| 349 | + public function getDateCheckedOut() { return (string) $this->dateCheckedout; } | ||
| 350 | + public function getModifiedBy() { return (string) $this->modifiedBy; } | ||
| 351 | + public function getDateModified() { return (string) $this->dateModified; } | ||
| 352 | + public function getCreatedBy() { return (string) $this->createdBy; } | ||
| 353 | + public function getDateCreated() { return (string) $this->dateCreated; } | ||
| 354 | + public function getOwner() { return (string) $this->owner; } | ||
| 355 | + public function getOwnedBy() { return $this->getOwner(); } | ||
| 356 | + public function getIsImmutable() { return (bool) $this->immutable; } | ||
| 357 | + public function getImmutable() { return $this->getIsImmutable(); } | ||
| 358 | + public function getStatus() { return $this->status; } | ||
| 359 | + public function getStoragePath() { return $this->storagePath; } | ||
| 360 | + public function getDocumentType() { return $this->documentType; } | ||
| 361 | + public function getPermissions() { return 'not available'; } | ||
| 362 | + public function getCanBeReadByUser() { if (!$this->live) | ||
| 267 | return false; | 363 | return false; |
| 268 | if (Permission::userHasDocumentReadPermission($this->Document)) | 364 | if (Permission::userHasDocumentReadPermission($this->Document)) |
| 269 | return true; | 365 | return true; |
| 270 | if (Permission::adminIsInAdminMode()) | 366 | if (Permission::adminIsInAdminMode()) |
| 271 | return true; | 367 | return true; |
| 272 | - return false; | ||
| 273 | - default: | ||
| 274 | - throw new Exception("Unknown property '$property' to get on QueryResultItem"); | ||
| 275 | - } | ||
| 276 | - return ''; // Should not be reached | 368 | + return false; } |
| 369 | + | ||
| 370 | + | ||
| 371 | +} | ||
| 372 | + | ||
| 373 | +class FolderResultItem extends QueryResultItem | ||
| 374 | +{ | ||
| 375 | + protected $folder; | ||
| 376 | + protected $createdBy; | ||
| 377 | + protected $parentId; | ||
| 378 | + | ||
| 379 | + public function __construct($folder_id, $rank=null, $title=null, $text=null, $fullpath = null) | ||
| 380 | + { | ||
| 381 | + parent::__construct($folder_id, $title, $rank, $text, $fullpath); | ||
| 382 | + $this->loadDocumentInfo(); | ||
| 277 | } | 383 | } |
| 278 | 384 | ||
| 279 | - protected function __set($property, $value) | 385 | + public function getFolderID() { return $this->getId(); } |
| 386 | + public function getParentID() { return $this->parentId; } | ||
| 387 | + public function getCreatedBy() { return $this->createdBy; } | ||
| 388 | + public function getMimeIconPath() { return 'folder'; } | ||
| 389 | + public function getFolder() { | ||
| 390 | + return $this->folder; } | ||
| 391 | + | ||
| 392 | + public function loadDocumentInfo() | ||
| 280 | { | 393 | { |
| 281 | - switch($property) | 394 | + global $default; |
| 395 | + $this->folder = $folder = Folder::get($this->getFolderID()); | ||
| 396 | + if (PEAR::isError($folder)) | ||
| 282 | { | 397 | { |
| 283 | - case 'Rank': $this->rank = number_format($value,2,'.',','); break; | ||
| 284 | - case 'Title': $this->title = $value; break; | ||
| 285 | - case 'Text': $this->text = $value; break; | ||
| 286 | - default: | ||
| 287 | - throw new Exception("Unknown property '$property' to set on QueryResultItem"); | 398 | + throw new Exception('Database exception! There appears to be an error in the system: ' .$result->getMessage()); |
| 288 | } | 399 | } |
| 400 | + $this->title = $folder->getName(); | ||
| 401 | + $this->fullpath = '/' . $folder->getFullPath(); | ||
| 402 | + $this->parentId = $folder->getParentId(); | ||
| 403 | + | ||
| 404 | + $user = User::get($folder->getCreatorID()); | ||
| 405 | + $this->createdBy = (PEAR::isError($user))?_kt('Unknown'):$user->getName(); | ||
| 289 | } | 406 | } |
| 407 | + | ||
| 408 | +} | ||
| 409 | + | ||
| 410 | +class DocumentShortcutResultItem extends ProxyResultItem | ||
| 411 | +{ | ||
| 412 | + public function getDocumentID() { return $this->getId(); } | ||
| 413 | + public function getMimeIconPath() { return $this->proxy->getMimeIconPath() . '_shortcut'; } | ||
| 414 | + | ||
| 415 | +} | ||
| 416 | + | ||
| 417 | +class FolderShortcutResultItem extends ProxyResultItem | ||
| 418 | +{ | ||
| 419 | + public function getFolderID() { return $this->getId(); } | ||
| 420 | + public function getMimeIconPath() { return 'folder_shortcut'; } | ||
| 421 | + | ||
| 290 | } | 422 | } |
| 291 | 423 | ||
| 292 | function MatchResultCompare($a, $b) | 424 | function MatchResultCompare($a, $b) |
search2/indexing/indexers/JavaXMLRPCLuceneIndexer.inc.php
| @@ -187,10 +187,7 @@ class JavaXMLRPCLuceneIndexer extends Indexer | @@ -187,10 +187,7 @@ class JavaXMLRPCLuceneIndexer extends Indexer | ||
| 187 | { | 187 | { |
| 188 | try | 188 | try |
| 189 | { | 189 | { |
| 190 | - $item = new QueryResultItem($document_id); | ||
| 191 | - $item->Title = $hit->Title; | ||
| 192 | - $item->Text = $hit->Content; | ||
| 193 | - $item->Rank = $hit->Rank; | 190 | + $item = new DocumentResultItem($document_id, $hit->Rank, $hit->Title, $hit->Content); |
| 194 | 191 | ||
| 195 | if ($item->CanBeReadByUser) | 192 | if ($item->CanBeReadByUser) |
| 196 | { | 193 | { |
search2/search/expr.inc.php
| @@ -43,6 +43,8 @@ | @@ -43,6 +43,8 @@ | ||
| 43 | * | 43 | * |
| 44 | */ | 44 | */ |
| 45 | 45 | ||
| 46 | +// TODO: search expression evaluation needs some optimisation | ||
| 47 | + | ||
| 46 | require_once('indexing/indexerCore.inc.php'); | 48 | require_once('indexing/indexerCore.inc.php'); |
| 47 | require_once('search/fieldRegistry.inc.php'); | 49 | require_once('search/fieldRegistry.inc.php'); |
| 48 | require_once('search/exprConstants.inc.php'); | 50 | require_once('search/exprConstants.inc.php'); |
| @@ -157,11 +159,28 @@ class Expr | @@ -157,11 +159,28 @@ class Expr | ||
| 157 | 159 | ||
| 158 | protected $expr_id; | 160 | protected $expr_id; |
| 159 | 161 | ||
| 162 | + protected $context; | ||
| 163 | + | ||
| 160 | public function __construct() | 164 | public function __construct() |
| 161 | { | 165 | { |
| 162 | $this->expr_id = Expr::$node_id++; | 166 | $this->expr_id = Expr::$node_id++; |
| 163 | } | 167 | } |
| 164 | 168 | ||
| 169 | + public function appliesToContext() | ||
| 170 | + { | ||
| 171 | + return ExprContext::DOCUMENT; | ||
| 172 | + } | ||
| 173 | + | ||
| 174 | + public function setContext($context) | ||
| 175 | + { | ||
| 176 | + $this->context = $context; | ||
| 177 | + } | ||
| 178 | + | ||
| 179 | + public function getContext() | ||
| 180 | + { | ||
| 181 | + return $this->context; | ||
| 182 | + } | ||
| 183 | + | ||
| 165 | public function getExprId() | 184 | public function getExprId() |
| 166 | { | 185 | { |
| 167 | return $this->expr_id; | 186 | return $this->expr_id; |
| @@ -363,7 +382,7 @@ class FieldExpr extends Expr | @@ -363,7 +382,7 @@ class FieldExpr extends Expr | ||
| 363 | */ | 382 | */ |
| 364 | public function __toString() | 383 | public function __toString() |
| 365 | { | 384 | { |
| 366 | - return $this->alias; | 385 | + return $this->display; |
| 367 | } | 386 | } |
| 368 | 387 | ||
| 369 | public function toViz(&$str, $phase) | 388 | public function toViz(&$str, $phase) |
| @@ -406,6 +425,14 @@ class FieldExpr extends Expr | @@ -406,6 +425,14 @@ class FieldExpr extends Expr | ||
| 406 | } | 425 | } |
| 407 | } | 426 | } |
| 408 | 427 | ||
| 428 | +class ExprContext | ||
| 429 | +{ | ||
| 430 | + const DOCUMENT = 1; | ||
| 431 | + const FOLDER = 2; | ||
| 432 | + const DOCUMENT_AND_FOLDER = 3; | ||
| 433 | +} | ||
| 434 | + | ||
| 435 | + | ||
| 409 | class DBFieldExpr extends FieldExpr | 436 | class DBFieldExpr extends FieldExpr |
| 410 | { | 437 | { |
| 411 | /** | 438 | /** |
| @@ -966,24 +993,43 @@ class SQLQueryBuilder implements QueryBuilder | @@ -966,24 +993,43 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 966 | private $sql; | 993 | private $sql; |
| 967 | private $db; | 994 | private $db; |
| 968 | private $metadata; | 995 | private $metadata; |
| 996 | + private $context; | ||
| 969 | 997 | ||
| 970 | - public function __construct() | 998 | + public function __construct($context) |
| 971 | { | 999 | { |
| 972 | - $this->used_tables = array( | ||
| 973 | - 'documents'=>1, | ||
| 974 | - 'document_metadata_version'=>1, | ||
| 975 | - 'document_content_version'=>0, | ||
| 976 | - 'tag_words'=>0, | ||
| 977 | - 'document_fields_link'=>0 | ||
| 978 | - ); | ||
| 979 | - | ||
| 980 | - $this->aliases = array( | ||
| 981 | - 'documents'=>'d', | ||
| 982 | - 'document_metadata_version'=>'dmv', | ||
| 983 | - 'document_content_version'=>'dcv', | ||
| 984 | - 'tag_words'=>'tw', | ||
| 985 | - 'document_fields_link'=>'pdfl' | ||
| 986 | - ); | 1000 | + $this->context = $context; |
| 1001 | + | ||
| 1002 | + switch ($context) | ||
| 1003 | + { | ||
| 1004 | + case ExprContext::DOCUMENT: | ||
| 1005 | + $this->used_tables = array( | ||
| 1006 | + 'documents'=>1, | ||
| 1007 | + 'document_metadata_version'=>1, | ||
| 1008 | + 'document_content_version'=>0, | ||
| 1009 | + 'tag_words'=>0, | ||
| 1010 | + 'document_fields_link'=>0 | ||
| 1011 | + ); | ||
| 1012 | + | ||
| 1013 | + $this->aliases = array( | ||
| 1014 | + 'documents'=>'d', | ||
| 1015 | + 'document_metadata_version'=>'dmv', | ||
| 1016 | + 'document_content_version'=>'dcv', | ||
| 1017 | + 'tag_words'=>'tw', | ||
| 1018 | + 'document_fields_link'=>'pdfl' | ||
| 1019 | + ); | ||
| 1020 | + break; | ||
| 1021 | + case ExprContext::FOLDER: | ||
| 1022 | + $this->used_tables = array( | ||
| 1023 | + 'folders'=>1, | ||
| 1024 | + ); | ||
| 1025 | + | ||
| 1026 | + $this->aliases = array( | ||
| 1027 | + 'folders'=>'f', | ||
| 1028 | + ); | ||
| 1029 | + break; | ||
| 1030 | + default: | ||
| 1031 | + throw new Exception('This was not expected - Context = ' . $context); | ||
| 1032 | + } | ||
| 987 | 1033 | ||
| 988 | $this->sql = ''; | 1034 | $this->sql = ''; |
| 989 | $this->db = array(); | 1035 | $this->db = array(); |
| @@ -1013,8 +1059,15 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1013,8 +1059,15 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1013 | } | 1059 | } |
| 1014 | elseif ($expr->isDBExpr()) | 1060 | elseif ($expr->isDBExpr()) |
| 1015 | { | 1061 | { |
| 1016 | - $this->db[] = & $parent; | ||
| 1017 | - $this->used_tables[$expr->getTable()]++; | 1062 | + if (($this->context & $expr->appliesToContext()) == $this->context) |
| 1063 | + { | ||
| 1064 | + $this->db[] = & $parent; | ||
| 1065 | + $tablename = $expr->getTable(); | ||
| 1066 | + if (array_key_exists($tablename, $this->used_tables)) | ||
| 1067 | + { | ||
| 1068 | + $this->used_tables[$tablename]++; | ||
| 1069 | + } | ||
| 1070 | + } | ||
| 1018 | } | 1071 | } |
| 1019 | elseif ($expr->isOpExpr()) | 1072 | elseif ($expr->isOpExpr()) |
| 1020 | { | 1073 | { |
| @@ -1042,12 +1095,16 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1042,12 +1095,16 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1042 | 1095 | ||
| 1043 | if ($field->isMetadataField()) | 1096 | if ($field->isMetadataField()) |
| 1044 | { | 1097 | { |
| 1045 | - $this->metadata[] = $expr->getParent(); | 1098 | + $this->metadata[] = $expr->getParent(); |
| 1046 | } | 1099 | } |
| 1047 | elseif ($field->isDBExpr()) | 1100 | elseif ($field->isDBExpr()) |
| 1048 | { | 1101 | { |
| 1049 | - $this->db[] = $expr->getParent(); | ||
| 1050 | - $this->used_tables[$field->getTable()]++; | 1102 | + $this->db[] = $expr->getParent(); |
| 1103 | + $tablename = $field->getTable(); | ||
| 1104 | + if (array_key_exists($tablename, $this->used_tables)) | ||
| 1105 | + { | ||
| 1106 | + $this->used_tables[$tablename]++; | ||
| 1107 | + } | ||
| 1051 | } | 1108 | } |
| 1052 | } | 1109 | } |
| 1053 | } | 1110 | } |
| @@ -1076,29 +1133,40 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1076,29 +1133,40 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1076 | $left = $expr->left(); | 1133 | $left = $expr->left(); |
| 1077 | $right = $expr->right(); | 1134 | $right = $expr->right(); |
| 1078 | $isNot = $expr->not(); | 1135 | $isNot = $expr->not(); |
| 1079 | - if ($left->isMetadataField()) | 1136 | + if ($left->isMetadataField() ) |
| 1080 | { | 1137 | { |
| 1081 | - $offset = $this->resolveMetadataOffset($expr) + 1; | ||
| 1082 | - | ||
| 1083 | - $fieldset = $left->getField(); | ||
| 1084 | - $query = '('; | ||
| 1085 | - | ||
| 1086 | - if ($isNot) | ||
| 1087 | - { | ||
| 1088 | - $query .= "df$offset.name IS NULL OR "; | ||
| 1089 | - } | ||
| 1090 | - | ||
| 1091 | - $query .= '(' . "df$offset.name='$fieldset' AND " . $right->getSQL($left, "dfl$offset.value", $expr->op(), $isNot) . ')'; | ||
| 1092 | - | ||
| 1093 | - | ||
| 1094 | - $query .= ')'; | ||
| 1095 | - | 1138 | + if ($this->context == ExprContext::DOCUMENT) |
| 1139 | + { | ||
| 1140 | + $offset = $this->resolveMetadataOffset($expr) + 1; | ||
| 1141 | + | ||
| 1142 | + $fieldset = $left->getField(); | ||
| 1143 | + $query = '('; | ||
| 1144 | + | ||
| 1145 | + if ($isNot) | ||
| 1146 | + { | ||
| 1147 | + $query .= "df$offset.name IS NULL OR "; | ||
| 1148 | + } | ||
| 1149 | + | ||
| 1150 | + $query .= '(' . "df$offset.name='$fieldset' AND " . $right->getSQL($left, "dfl$offset.value", $expr->op(), $isNot) . ')'; | ||
| 1151 | + | ||
| 1152 | + $query .= ')'; | ||
| 1153 | + } | ||
| 1154 | + else | ||
| 1155 | + { | ||
| 1156 | + $query = 'false'; | ||
| 1157 | + } | ||
| 1096 | } | 1158 | } |
| 1097 | else | 1159 | else |
| 1098 | { | 1160 | { |
| 1099 | - $fieldname = $this->getFieldnameFromExpr($expr); | ||
| 1100 | - | ||
| 1101 | - $query = $right->getSQL($left, $left->modifyName($fieldname), $expr->op(), $isNot); | 1161 | + if ($this->context == ExprContext::FOLDER && $left->getContext() != ExprContext::FOLDER) |
| 1162 | + { | ||
| 1163 | + $query = 'false'; | ||
| 1164 | + } | ||
| 1165 | + else | ||
| 1166 | + { | ||
| 1167 | + $fieldname = $this->getFieldnameFromExpr($expr); | ||
| 1168 | + $query = $right->getSQL($left, $left->modifyName($fieldname), $expr->op(), $isNot); | ||
| 1169 | + } | ||
| 1102 | } | 1170 | } |
| 1103 | return $query; | 1171 | return $query; |
| 1104 | } | 1172 | } |
| @@ -1107,17 +1175,30 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1107,17 +1175,30 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1107 | { | 1175 | { |
| 1108 | if (count($this->metadata) + count($this->db) == 0) | 1176 | if (count($this->metadata) + count($this->db) == 0) |
| 1109 | { | 1177 | { |
| 1110 | - throw new Exception('nothing to do'); | 1178 | + // return empty result set |
| 1179 | + return 'select 1 from documents where false'; | ||
| 1111 | } | 1180 | } |
| 1112 | 1181 | ||
| 1113 | - // we are doing this because content table is dependant on metadata table | ||
| 1114 | - if ($this->used_tables['document_content_version'] > 0) $this->used_tables['document_metadata_version']++; | ||
| 1115 | - | ||
| 1116 | $sql = | 1182 | $sql = |
| 1117 | 'SELECT ' . "\n"; | 1183 | 'SELECT ' . "\n"; |
| 1118 | 1184 | ||
| 1119 | - $sql .= | 1185 | + if ($this->context == ExprContext::DOCUMENT) |
| 1186 | + { | ||
| 1187 | + // we are doing this because content table is dependant on metadata table | ||
| 1188 | + if ($this->used_tables['document_content_version'] > 0) | ||
| 1189 | + { | ||
| 1190 | + $this->used_tables['document_metadata_version']++; | ||
| 1191 | + } | ||
| 1192 | + | ||
| 1193 | + $sql .= | ||
| 1120 | ' DISTINCT d.id, dmv.name as title'; | 1194 | ' DISTINCT d.id, dmv.name as title'; |
| 1195 | + } | ||
| 1196 | + else | ||
| 1197 | + { | ||
| 1198 | + $sql .= | ||
| 1199 | + ' DISTINCT f.id, f.name as title'; | ||
| 1200 | + } | ||
| 1201 | + | ||
| 1121 | 1202 | ||
| 1122 | $offset=0; | 1203 | $offset=0; |
| 1123 | foreach($this->db as $expr) | 1204 | foreach($this->db as $expr) |
| @@ -1133,26 +1214,36 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1133,26 +1214,36 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1133 | } | 1214 | } |
| 1134 | 1215 | ||
| 1135 | $sql .= | 1216 | $sql .= |
| 1136 | - "\n" . 'FROM ' ."\n" . | ||
| 1137 | - ' documents d ' ."\n"; | 1217 | + "\n" . 'FROM ' ."\n"; |
| 1138 | 1218 | ||
| 1139 | - if ($this->used_tables['document_metadata_version'] > 0) | ||
| 1140 | - { | ||
| 1141 | - $sql .= ' INNER JOIN document_metadata_version dmv ON d.metadata_version_id=dmv.id' . "\n"; | ||
| 1142 | - } | ||
| 1143 | - if ($this->used_tables['document_content_version'] > 0) | ||
| 1144 | - { | ||
| 1145 | - $sql .= ' INNER JOIN document_content_version dcv ON dmv.content_version_id=dcv.id ' . "\n"; | ||
| 1146 | - } | ||
| 1147 | - if ($this->used_tables['document_fields_link'] > 0) | 1219 | + if ($this->context == ExprContext::DOCUMENT) |
| 1148 | { | 1220 | { |
| 1149 | - $sql .= ' LEFT JOIN document_fields_link pdfl ON dmv.id=pdfl.metadata_version_id ' . "\n"; | ||
| 1150 | - } | 1221 | + $primaryAlias = 'd'; |
| 1222 | + $sql .= ' documents d ' ."\n"; | ||
| 1151 | 1223 | ||
| 1152 | - if ($this->used_tables['tag_words'] > 0) | 1224 | + if ($this->used_tables['document_metadata_version'] > 0) |
| 1225 | + { | ||
| 1226 | + $sql .= ' INNER JOIN document_metadata_version dmv ON d.metadata_version_id=dmv.id' . "\n"; | ||
| 1227 | + } | ||
| 1228 | + if ($this->used_tables['document_content_version'] > 0) | ||
| 1229 | + { | ||
| 1230 | + $sql .= ' INNER JOIN document_content_version dcv ON dmv.content_version_id=dcv.id ' . "\n"; | ||
| 1231 | + } | ||
| 1232 | + if ($this->used_tables['document_fields_link'] > 0) | ||
| 1233 | + { | ||
| 1234 | + $sql .= ' LEFT JOIN document_fields_link pdfl ON dmv.id=pdfl.metadata_version_id ' . "\n"; | ||
| 1235 | + } | ||
| 1236 | + | ||
| 1237 | + if ($this->used_tables['tag_words'] > 0) | ||
| 1238 | + { | ||
| 1239 | + $sql .= ' LEFT OUTER JOIN document_tags dt ON dt.document_id=d.id ' . "\n" . | ||
| 1240 | + ' LEFT OUTER JOIN tag_words tw ON dt.tag_id = tw.id ' . "\n"; | ||
| 1241 | + } | ||
| 1242 | + } | ||
| 1243 | + else | ||
| 1153 | { | 1244 | { |
| 1154 | - $sql .= ' LEFT OUTER JOIN document_tags dt ON dt.document_id=d.id ' . "\n" . | ||
| 1155 | - ' LEFT OUTER JOIN tag_words tw ON dt.tag_id = tw.id ' . "\n"; | 1245 | + $primaryAlias = 'f'; |
| 1246 | + $sql .= ' folders f ' ."\n"; | ||
| 1156 | } | 1247 | } |
| 1157 | 1248 | ||
| 1158 | $offset = 0; | 1249 | $offset = 0; |
| @@ -1171,17 +1262,18 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1171,17 +1262,18 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1171 | $offset++; | 1262 | $offset++; |
| 1172 | } | 1263 | } |
| 1173 | 1264 | ||
| 1174 | - | ||
| 1175 | - | ||
| 1176 | - $offset=0; | ||
| 1177 | - foreach($this->metadata as $expr) | 1265 | + if ($this->context == ExprContext::DOCUMENT) |
| 1178 | { | 1266 | { |
| 1179 | - $offset++; | ||
| 1180 | - $field = $expr->left(); | 1267 | + $offset=0; |
| 1268 | + foreach($this->metadata as $expr) | ||
| 1269 | + { | ||
| 1270 | + $offset++; | ||
| 1271 | + $field = $expr->left(); | ||
| 1181 | 1272 | ||
| 1182 | - $fieldid = $field->getFieldId(); | ||
| 1183 | - $sql .= " LEFT JOIN document_fields_link dfl$offset ON dfl$offset.metadata_version_id=d.metadata_version_id AND dfl$offset.document_field_id=$fieldid" . "\n"; | ||
| 1184 | - $sql .= " LEFT JOIN document_fields df$offset ON df$offset.id=dfl$offset.document_field_id" . "\n"; | 1273 | + $fieldid = $field->getFieldId(); |
| 1274 | + $sql .= " LEFT JOIN document_fields_link dfl$offset ON dfl$offset.metadata_version_id=d.metadata_version_id AND dfl$offset.document_field_id=$fieldid" . "\n"; | ||
| 1275 | + $sql .= " LEFT JOIN document_fields df$offset ON df$offset.id=dfl$offset.document_field_id" . "\n"; | ||
| 1276 | + } | ||
| 1185 | } | 1277 | } |
| 1186 | 1278 | ||
| 1187 | // Add permissions sql for read access | 1279 | // Add permissions sql for read access |
| @@ -1189,15 +1281,16 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1189,15 +1281,16 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1189 | $permId = $oPermission->getID(); | 1281 | $permId = $oPermission->getID(); |
| 1190 | $oUser = User::get($_SESSION['userID']); | 1282 | $oUser = User::get($_SESSION['userID']); |
| 1191 | $aPermissionDescriptors = KTPermissionUtil::getPermissionDescriptorsForUser($oUser); | 1283 | $aPermissionDescriptors = KTPermissionUtil::getPermissionDescriptorsForUser($oUser); |
| 1192 | - $sPermissionDescriptors = (!empty($aPermissionDescriptors)) ? implode(',', $aPermissionDescriptors) : ''; | 1284 | + $sPermissionDescriptors = empty($aPermissionDescriptors)? -1: implode(',', $aPermissionDescriptors); |
| 1193 | 1285 | ||
| 1194 | - $sql .= 'LEFT JOIN folders f ON d.folder_id = f.id '. "\n"; | ||
| 1195 | - | ||
| 1196 | - $sql .= 'INNER JOIN permission_lookups AS PL ON f.permission_lookup_id = PL.id '. "\n"; | 1286 | + $sql .= "INNER JOIN permission_lookups AS PL ON $primaryAlias.permission_lookup_id = PL.id\n"; |
| 1197 | $sql .= 'INNER JOIN permission_lookup_assignments AS PLA ON PL.id = PLA.permission_lookup_id AND PLA.permission_id = '.$permId. " \n"; | 1287 | $sql .= 'INNER JOIN permission_lookup_assignments AS PLA ON PL.id = PLA.permission_lookup_id AND PLA.permission_id = '.$permId. " \n"; |
| 1288 | + $sql .= "WHERE PLA.permission_descriptor_id IN ($sPermissionDescriptors) AND "; | ||
| 1198 | 1289 | ||
| 1199 | - $sql .= "WHERE PLA.permission_descriptor_id IN ($sPermissionDescriptors) AND dmv.status_id=1 AND d.status_id=1 AND \n "; | ||
| 1200 | - | 1290 | + if ($this->context == ExprContext::DOCUMENT) |
| 1291 | + { | ||
| 1292 | + $sql .= "dmv.status_id=1 AND d.status_id=1 AND \n "; | ||
| 1293 | + } | ||
| 1201 | return $sql; | 1294 | return $sql; |
| 1202 | } | 1295 | } |
| 1203 | 1296 | ||
| @@ -1222,8 +1315,6 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1222,8 +1315,6 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1222 | 1315 | ||
| 1223 | private function resolveJoinOffset($expr) | 1316 | private function resolveJoinOffset($expr) |
| 1224 | { | 1317 | { |
| 1225 | - | ||
| 1226 | - | ||
| 1227 | $offset=0; | 1318 | $offset=0; |
| 1228 | foreach($this->db as $item) | 1319 | foreach($this->db as $item) |
| 1229 | { | 1320 | { |
| @@ -1242,11 +1333,18 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1242,11 +1333,18 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1242 | $right = $expr->right(); | 1333 | $right = $expr->right(); |
| 1243 | if (DefaultOpCollection::isBoolean($expr)) | 1334 | if (DefaultOpCollection::isBoolean($expr)) |
| 1244 | { | 1335 | { |
| 1245 | - $query = '(' . $this->buildCoreSQLExpr($left) . ' ' . $expr->op() . ' ' . $this->buildCoreSQLExpr($right) . ')'; | 1336 | + $query = '(' . $this->buildCoreSQLExpr($left) . ' ' . $expr->op() . ' ' . $this->buildCoreSQLExpr($right) . ')'; |
| 1246 | } | 1337 | } |
| 1247 | else | 1338 | else |
| 1248 | { | 1339 | { |
| 1249 | - $query = $this->getSQLEvalExpr($expr); | 1340 | + if (($this->context & $expr->appliesToContext()) == $this->context) |
| 1341 | + { | ||
| 1342 | + $query = $this->getSQLEvalExpr($expr); | ||
| 1343 | + } | ||
| 1344 | + else | ||
| 1345 | + { | ||
| 1346 | + $query = 'false'; | ||
| 1347 | + } | ||
| 1250 | } | 1348 | } |
| 1251 | 1349 | ||
| 1252 | return $query; | 1350 | return $query; |
| @@ -1259,7 +1357,11 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1259,7 +1357,11 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1259 | 1357 | ||
| 1260 | $sql = $this->buildCoreSQL(); | 1358 | $sql = $this->buildCoreSQL(); |
| 1261 | 1359 | ||
| 1262 | - $sql .= $this->buildCoreSQLExpr($expr); | 1360 | + $expr = $this->buildCoreSQLExpr($expr); |
| 1361 | + if ($expr != 'false') | ||
| 1362 | + { | ||
| 1363 | + $sql .= $expr; | ||
| 1364 | + } | ||
| 1263 | 1365 | ||
| 1264 | return $sql; | 1366 | return $sql; |
| 1265 | } | 1367 | } |
| @@ -1299,19 +1401,22 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1299,19 +1401,22 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1299 | $sql .= $value->getSQL($field, $left->modifyName($fieldname), $expr->op(), $expr->not()); | 1401 | $sql .= $value->getSQL($field, $left->modifyName($fieldname), $expr->op(), $expr->not()); |
| 1300 | } | 1402 | } |
| 1301 | 1403 | ||
| 1302 | - $moffset=0; | ||
| 1303 | - foreach($this->metadata as $expr) | 1404 | + if ($this->context == ExprContext::DOCUMENT) |
| 1304 | { | 1405 | { |
| 1305 | - $moffset++; | ||
| 1306 | - if ($offset++) | 1406 | + $moffset=0; |
| 1407 | + foreach($this->metadata as $expr) | ||
| 1307 | { | 1408 | { |
| 1308 | - $sql .= " $op\n " ; | ||
| 1309 | - } | 1409 | + $moffset++; |
| 1410 | + if ($offset++) | ||
| 1411 | + { | ||
| 1412 | + $sql .= " $op\n " ; | ||
| 1413 | + } | ||
| 1310 | 1414 | ||
| 1311 | - $field = $expr->left(); | ||
| 1312 | - $value = $expr->right(); | 1415 | + $field = $expr->left(); |
| 1416 | + $value = $expr->right(); | ||
| 1313 | 1417 | ||
| 1314 | - $sql .= $value->getSQL($field, "dfl$moffset.value", $expr->getOp()); | 1418 | + $sql .= $value->getSQL($field, "dfl$moffset.value", $expr->getOp()); |
| 1419 | + } | ||
| 1315 | } | 1420 | } |
| 1316 | 1421 | ||
| 1317 | return $sql; | 1422 | return $sql; |
| @@ -1331,7 +1436,6 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1331,7 +1436,6 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1331 | 1436 | ||
| 1332 | if (substr($col, 0, 4) == 'expr' && is_numeric(substr($col, 4))) | 1437 | if (substr($col, 0, 4) == 'expr' && is_numeric(substr($col, 4))) |
| 1333 | { | 1438 | { |
| 1334 | - | ||
| 1335 | $exprno = substr($col, 4); | 1439 | $exprno = substr($col, 4); |
| 1336 | if ($exprno <= count($this->db)) | 1440 | if ($exprno <= count($this->db)) |
| 1337 | { | 1441 | { |
| @@ -1379,8 +1483,6 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1379,8 +1483,6 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1379 | } | 1483 | } |
| 1380 | return '(' . implode(') AND (', $text) . ')'; | 1484 | return '(' . implode(') AND (', $text) . ')'; |
| 1381 | } | 1485 | } |
| 1382 | - | ||
| 1383 | - | ||
| 1384 | } | 1486 | } |
| 1385 | 1487 | ||
| 1386 | 1488 | ||
| @@ -1444,6 +1546,13 @@ class OpExpr extends Expr | @@ -1444,6 +1546,13 @@ class OpExpr extends Expr | ||
| 1444 | $this->has_text=$value; | 1546 | $this->has_text=$value; |
| 1445 | } | 1547 | } |
| 1446 | 1548 | ||
| 1549 | + public function setContext($context) | ||
| 1550 | + { | ||
| 1551 | + parent::setContext($context); | ||
| 1552 | + $this->left()->setContext($context); | ||
| 1553 | + $this->right()->setContext($context); | ||
| 1554 | + } | ||
| 1555 | + | ||
| 1447 | public function getHasDb() | 1556 | public function getHasDb() |
| 1448 | { | 1557 | { |
| 1449 | return $this->has_db; | 1558 | return $this->has_db; |
| @@ -1619,7 +1728,6 @@ class OpExpr extends Expr | @@ -1619,7 +1728,6 @@ class OpExpr extends Expr | ||
| 1619 | 1728 | ||
| 1620 | $point = null; | 1729 | $point = null; |
| 1621 | 1730 | ||
| 1622 | - | ||
| 1623 | if ($left_op_match && $right_op_match) { $point = 'point'; } | 1731 | if ($left_op_match && $right_op_match) { $point = 'point'; } |
| 1624 | 1732 | ||
| 1625 | $left_op_match_flex = $left_op_match || ($left->isOpExpr()); | 1733 | $left_op_match_flex = $left_op_match || ($left->isOpExpr()); |
| @@ -1682,6 +1790,11 @@ class OpExpr extends Expr | @@ -1682,6 +1790,11 @@ class OpExpr extends Expr | ||
| 1682 | return $this->getHasDb() && $this->getHasText(); | 1790 | return $this->getHasDb() && $this->getHasText(); |
| 1683 | } | 1791 | } |
| 1684 | 1792 | ||
| 1793 | + public function appliesToContext() | ||
| 1794 | + { | ||
| 1795 | + return $this->left()->appliesToContext() | $this->right()->appliesToContext(); | ||
| 1796 | + } | ||
| 1797 | + | ||
| 1685 | /** | 1798 | /** |
| 1686 | * Enter description here... | 1799 | * Enter description here... |
| 1687 | * | 1800 | * |
| @@ -1759,13 +1872,14 @@ class OpExpr extends Expr | @@ -1759,13 +1872,14 @@ class OpExpr extends Expr | ||
| 1759 | */ | 1872 | */ |
| 1760 | public function __toString() | 1873 | public function __toString() |
| 1761 | { | 1874 | { |
| 1762 | - $expr = $this->left_expr . ' ' . $this->op .' ' . $this->right_expr; | 1875 | + // _kt may not translate well here. |
| 1876 | + $expr = $this->left_expr . ' ' . _kt($this->op) .' ' . $this->right_expr; | ||
| 1763 | 1877 | ||
| 1764 | if (is_null($this->parent)) | 1878 | if (is_null($this->parent)) |
| 1765 | { | 1879 | { |
| 1766 | if ($this->not()) | 1880 | if ($this->not()) |
| 1767 | { | 1881 | { |
| 1768 | - $expr = "NOT $expr"; | 1882 | + $expr = _kt('NOT') . $expr; |
| 1769 | } | 1883 | } |
| 1770 | return $expr; | 1884 | return $expr; |
| 1771 | } | 1885 | } |
| @@ -1805,7 +1919,7 @@ class OpExpr extends Expr | @@ -1805,7 +1919,7 @@ class OpExpr extends Expr | ||
| 1805 | * @param array $rightres | 1919 | * @param array $rightres |
| 1806 | * @return array | 1920 | * @return array |
| 1807 | */ | 1921 | */ |
| 1808 | - protected static function intersect($leftres, $rightres) | 1922 | + protected static function _intersect($leftres, $rightres) |
| 1809 | { | 1923 | { |
| 1810 | if (empty($leftres) || empty($rightres)) | 1924 | if (empty($leftres) || empty($rightres)) |
| 1811 | { | 1925 | { |
| @@ -1814,7 +1928,7 @@ class OpExpr extends Expr | @@ -1814,7 +1928,7 @@ class OpExpr extends Expr | ||
| 1814 | $result = array(); | 1928 | $result = array(); |
| 1815 | foreach($leftres as $item) | 1929 | foreach($leftres as $item) |
| 1816 | { | 1930 | { |
| 1817 | - $document_id = $item->DocumentID; | 1931 | + $document_id = $item->Id; |
| 1818 | 1932 | ||
| 1819 | if (!$item->IsLive) | 1933 | if (!$item->IsLive) |
| 1820 | { | 1934 | { |
| @@ -1831,6 +1945,22 @@ class OpExpr extends Expr | @@ -1831,6 +1945,22 @@ class OpExpr extends Expr | ||
| 1831 | return $result; | 1945 | return $result; |
| 1832 | } | 1946 | } |
| 1833 | 1947 | ||
| 1948 | + protected static function intersect($leftres, $rightres) | ||
| 1949 | + { | ||
| 1950 | + return array( | ||
| 1951 | + 'docs'=>self::_intersect($leftres['docs'],$rightres['docs']), | ||
| 1952 | + 'folders'=>self::_intersect($leftres['folders'],$rightres['folders']) | ||
| 1953 | + ); | ||
| 1954 | + } | ||
| 1955 | + | ||
| 1956 | + protected static function union($leftres, $rightres) | ||
| 1957 | + { | ||
| 1958 | + return array( | ||
| 1959 | + 'docs'=>self::_union($leftres['docs'],$rightres['docs']), | ||
| 1960 | + 'folders'=>self::_union($leftres['folders'],$rightres['folders']) | ||
| 1961 | + ); | ||
| 1962 | + } | ||
| 1963 | + | ||
| 1834 | /** | 1964 | /** |
| 1835 | * The objective of this function is to merge the results so that there is a union of the results, | 1965 | * The objective of this function is to merge the results so that there is a union of the results, |
| 1836 | * but there should be no duplicates. | 1966 | * but there should be no duplicates. |
| @@ -1839,7 +1969,7 @@ class OpExpr extends Expr | @@ -1839,7 +1969,7 @@ class OpExpr extends Expr | ||
| 1839 | * @param array $rightres | 1969 | * @param array $rightres |
| 1840 | * @return array | 1970 | * @return array |
| 1841 | */ | 1971 | */ |
| 1842 | - protected static function union($leftres, $rightres) | 1972 | + protected static function _union($leftres, $rightres) |
| 1843 | { | 1973 | { |
| 1844 | if (empty($leftres)) | 1974 | if (empty($leftres)) |
| 1845 | { | 1975 | { |
| @@ -1855,15 +1985,15 @@ class OpExpr extends Expr | @@ -1855,15 +1985,15 @@ class OpExpr extends Expr | ||
| 1855 | { | 1985 | { |
| 1856 | if ($item->IsLive) | 1986 | if ($item->IsLive) |
| 1857 | { | 1987 | { |
| 1858 | - $result[$item->DocumentID] = $item; | 1988 | + $result[$item->Id] = $item; |
| 1859 | } | 1989 | } |
| 1860 | } | 1990 | } |
| 1861 | 1991 | ||
| 1862 | foreach($rightres as $item) | 1992 | foreach($rightres as $item) |
| 1863 | { | 1993 | { |
| 1864 | - if (!array_key_exists($item->DocumentID, $result) || $item->Rank > $result[$item->DocumentID]->Rank) | 1994 | + if (!array_key_exists($item->Id, $result) || $item->Rank > $result[$item->Id]->Rank) |
| 1865 | { | 1995 | { |
| 1866 | - $result[$item->DocumentID] = $item; | 1996 | + $result[$item->Id] = $item; |
| 1867 | } | 1997 | } |
| 1868 | } | 1998 | } |
| 1869 | return $result; | 1999 | return $result; |
| @@ -1996,7 +2126,7 @@ class OpExpr extends Expr | @@ -1996,7 +2126,7 @@ class OpExpr extends Expr | ||
| 1996 | { | 2126 | { |
| 1997 | if (empty($group)) { return array(); } | 2127 | if (empty($group)) { return array(); } |
| 1998 | 2128 | ||
| 1999 | - $exprbuilder = new SQLQueryBuilder(); | 2129 | + $exprbuilder = new SQLQueryBuilder($this->getContext()); |
| 2000 | 2130 | ||
| 2001 | if (count($group) == 1) | 2131 | if (count($group) == 1) |
| 2002 | { | 2132 | { |
| @@ -2020,11 +2150,18 @@ class OpExpr extends Expr | @@ -2020,11 +2150,18 @@ class OpExpr extends Expr | ||
| 2020 | 2150 | ||
| 2021 | foreach($rs as $item) | 2151 | foreach($rs as $item) |
| 2022 | { | 2152 | { |
| 2023 | - $document_id = $item['id']; | 2153 | + $id = $item['id']; |
| 2024 | $rank = $exprbuilder->getRanking($item); | 2154 | $rank = $exprbuilder->getRanking($item); |
| 2025 | - if (!array_key_exists($document_id, $results) || $rank > $results[$document_id]->Rank) | 2155 | + if (!array_key_exists($id, $results) || $rank > $results[$id]->Rank) |
| 2026 | { | 2156 | { |
| 2027 | - $results[$document_id] = new QueryResultItem($document_id, $rank, $item['title'], $exprbuilder->getResultText($item)); | 2157 | + if ($this->context == ExprContext::DOCUMENT) |
| 2158 | + { | ||
| 2159 | + $results[$id] = new DocumentResultItem($id, $rank, $item['title'], $exprbuilder->getResultText($item)); | ||
| 2160 | + } | ||
| 2161 | + else | ||
| 2162 | + { | ||
| 2163 | + $results[$id] = new FolderResultItem($id, $rank, $item['title'], $exprbuilder->getResultText($item)); | ||
| 2164 | + } | ||
| 2028 | } | 2165 | } |
| 2029 | } | 2166 | } |
| 2030 | 2167 | ||
| @@ -2034,7 +2171,10 @@ class OpExpr extends Expr | @@ -2034,7 +2171,10 @@ class OpExpr extends Expr | ||
| 2034 | 2171 | ||
| 2035 | private function exec_text_query($op, $group) | 2172 | private function exec_text_query($op, $group) |
| 2036 | { | 2173 | { |
| 2037 | - if (empty($group)) { return array(); } | 2174 | + if (($this->getContext() != ExprContext::DOCUMENT) || empty($group)) |
| 2175 | + { | ||
| 2176 | + return array(); | ||
| 2177 | + } | ||
| 2038 | 2178 | ||
| 2039 | $exprbuilder = new TextQueryBuilder(); | 2179 | $exprbuilder = new TextQueryBuilder(); |
| 2040 | 2180 | ||
| @@ -2060,12 +2200,21 @@ class OpExpr extends Expr | @@ -2060,12 +2200,21 @@ class OpExpr extends Expr | ||
| 2060 | } | 2200 | } |
| 2061 | 2201 | ||
| 2062 | return $results; | 2202 | return $results; |
| 2063 | - | ||
| 2064 | - | ||
| 2065 | } | 2203 | } |
| 2066 | 2204 | ||
| 2067 | - public function evaluate() | 2205 | + public function evaluate($context = ExprContext::DOCUMENT_AND_FOLDER) |
| 2068 | { | 2206 | { |
| 2207 | + if ($context == ExprContext::DOCUMENT_AND_FOLDER) | ||
| 2208 | + { | ||
| 2209 | + $docs = $this->evaluate(ExprContext::DOCUMENT); | ||
| 2210 | + $folders = $this->evaluate(ExprContext::FOLDER); | ||
| 2211 | + | ||
| 2212 | + return array( | ||
| 2213 | + 'docs' => $docs['docs'], | ||
| 2214 | + 'folders' => $folders['folders']); | ||
| 2215 | + } | ||
| 2216 | + $this->setContext($context); | ||
| 2217 | + | ||
| 2069 | $left = $this->left(); | 2218 | $left = $this->left(); |
| 2070 | $right = $this->right(); | 2219 | $right = $this->right(); |
| 2071 | $op = $this->op(); | 2220 | $op = $this->op(); |
| @@ -2075,12 +2224,12 @@ class OpExpr extends Expr | @@ -2075,12 +2224,12 @@ class OpExpr extends Expr | ||
| 2075 | { | 2224 | { |
| 2076 | $point = 'point'; | 2225 | $point = 'point'; |
| 2077 | } | 2226 | } |
| 2227 | + $resultContext = ($this->getContext() == ExprContext::DOCUMENT)?'docs':'folders'; | ||
| 2078 | 2228 | ||
| 2079 | if ($point == 'merge') | 2229 | if ($point == 'merge') |
| 2080 | { | 2230 | { |
| 2081 | - | ||
| 2082 | - $leftres = $left->evaluate(); | ||
| 2083 | - $rightres = $right->evaluate(); | 2231 | + $leftres = $left->evaluate($context); |
| 2232 | + $rightres = $right->evaluate($context); | ||
| 2084 | switch ($op) | 2233 | switch ($op) |
| 2085 | { | 2234 | { |
| 2086 | case ExprOp::OP_AND: | 2235 | case ExprOp::OP_AND: |
| @@ -2099,31 +2248,33 @@ class OpExpr extends Expr | @@ -2099,31 +2248,33 @@ class OpExpr extends Expr | ||
| 2099 | { | 2248 | { |
| 2100 | if ($this->isDBonly()) | 2249 | if ($this->isDBonly()) |
| 2101 | { | 2250 | { |
| 2102 | - $result = $this->exec_db_query($op, array($this)); | 2251 | + $result[$resultContext] = $this->exec_db_query($op, array($this)); |
| 2103 | } | 2252 | } |
| 2104 | elseif ($this->isTextOnly()) | 2253 | elseif ($this->isTextOnly()) |
| 2105 | { | 2254 | { |
| 2106 | - $result = $this->exec_text_query($op, array($this)); | 2255 | + $result[$resultContext] = $this->exec_text_query($op, array($this)); |
| 2107 | } | 2256 | } |
| 2108 | elseif (in_array($op, array(ExprOp::OP_OR, ExprOp::OP_AND))) | 2257 | elseif (in_array($op, array(ExprOp::OP_OR, ExprOp::OP_AND))) |
| 2109 | { | 2258 | { |
| 2259 | + // do we get to this??? | ||
| 2260 | + // TODO: remove me please.... the simpleQuery stuff should go??? | ||
| 2110 | $db_group = array(); | 2261 | $db_group = array(); |
| 2111 | $text_group = array(); | 2262 | $text_group = array(); |
| 2112 | $this->explore($left, $right, $db_group, 'db'); | 2263 | $this->explore($left, $right, $db_group, 'db'); |
| 2113 | $this->explore($left, $right, $text_group, 'text'); | 2264 | $this->explore($left, $right, $text_group, 'text'); |
| 2114 | 2265 | ||
| 2115 | - $db_result = $this->exec_db_query($op, $db_group); | ||
| 2116 | - $text_result = $this->exec_text_query($op, $text_group); | 2266 | + $db_result[$resultContext] = $this->exec_db_query($op, $db_group); |
| 2267 | + $text_result[$resultContext] = $this->exec_text_query($op, $text_group); | ||
| 2117 | 2268 | ||
| 2118 | switch ($op) | 2269 | switch ($op) |
| 2119 | { | 2270 | { |
| 2120 | case ExprOp::OP_AND: | 2271 | case ExprOp::OP_AND: |
| 2121 | if ($this->debug) print "\n\npoint: intersect\n\n"; | 2272 | if ($this->debug) print "\n\npoint: intersect\n\n"; |
| 2122 | - $result = OpExpr::intersect($db_result, $text_result); | 2273 | + $result[$resultContext] = OpExpr::intersect($db_result, $text_result); |
| 2123 | break; | 2274 | break; |
| 2124 | case ExprOp::OP_OR: | 2275 | case ExprOp::OP_OR: |
| 2125 | if ($this->debug) print "\n\nmerge: union\n\n"; | 2276 | if ($this->debug) print "\n\nmerge: union\n\n"; |
| 2126 | - $result = OpExpr::union($db_result, $text_result); | 2277 | + $result[$resultContext] = OpExpr::union($db_result, $text_result); |
| 2127 | break; | 2278 | break; |
| 2128 | default: | 2279 | default: |
| 2129 | throw new Exception('how did this happen??'); | 2280 | throw new Exception('how did this happen??'); |
| @@ -2141,9 +2292,9 @@ class OpExpr extends Expr | @@ -2141,9 +2292,9 @@ class OpExpr extends Expr | ||
| 2141 | } | 2292 | } |
| 2142 | 2293 | ||
| 2143 | $permResults = array(); | 2294 | $permResults = array(); |
| 2144 | - foreach($result as $idx=>$item) | 2295 | + foreach($result[$resultContext] as $idx=>$item) |
| 2145 | { | 2296 | { |
| 2146 | - $permResults[$idx] = $item; | 2297 | + $permResults[$resultContext][$idx] = $item; |
| 2147 | } | 2298 | } |
| 2148 | 2299 | ||
| 2149 | return $permResults; | 2300 | return $permResults; |
search2/search/exprConstants.inc.php
| @@ -6,31 +6,31 @@ | @@ -6,31 +6,31 @@ | ||
| 6 | * Document Management Made Simple | 6 | * Document Management Made Simple |
| 7 | * Copyright (C) 2008 KnowledgeTree Inc. | 7 | * Copyright (C) 2008 KnowledgeTree Inc. |
| 8 | * Portions copyright The Jam Warehouse Software (Pty) Limited | 8 | * Portions copyright The Jam Warehouse Software (Pty) Limited |
| 9 | - * | 9 | + * |
| 10 | * This program is free software; you can redistribute it and/or modify it under | 10 | * This program is free software; you can redistribute it and/or modify it under |
| 11 | * the terms of the GNU General Public License version 3 as published by the | 11 | * the terms of the GNU General Public License version 3 as published by the |
| 12 | * Free Software Foundation. | 12 | * Free Software Foundation. |
| 13 | - * | 13 | + * |
| 14 | * This program is distributed in the hope that it will be useful, but WITHOUT | 14 | * This program is distributed in the hope that it will be useful, but WITHOUT |
| 15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | 15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| 16 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more | 16 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
| 17 | * details. | 17 | * details. |
| 18 | - * | 18 | + * |
| 19 | * You should have received a copy of the GNU General Public License | 19 | * You should have received a copy of the GNU General Public License |
| 20 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 20 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 21 | - * | ||
| 22 | - * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco, | 21 | + * |
| 22 | + * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco, | ||
| 23 | * California 94120-7775, or email info@knowledgetree.com. | 23 | * California 94120-7775, or email info@knowledgetree.com. |
| 24 | - * | 24 | + * |
| 25 | * The interactive user interfaces in modified source and object code versions | 25 | * The interactive user interfaces in modified source and object code versions |
| 26 | * of this program must display Appropriate Legal Notices, as required under | 26 | * of this program must display Appropriate Legal Notices, as required under |
| 27 | * Section 5 of the GNU General Public License version 3. | 27 | * Section 5 of the GNU General Public License version 3. |
| 28 | - * | 28 | + * |
| 29 | * In accordance with Section 7(b) of the GNU General Public License version 3, | 29 | * In accordance with Section 7(b) of the GNU General Public License version 3, |
| 30 | * these Appropriate Legal Notices must retain the display of the "Powered by | 30 | * these Appropriate Legal Notices must retain the display of the "Powered by |
| 31 | - * KnowledgeTree" logo and retain the original copyright notice. If the display of the | 31 | + * KnowledgeTree" logo and retain the original copyright notice. If the display of the |
| 32 | * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices | 32 | * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices |
| 33 | - * must display the words "Powered by KnowledgeTree" and retain the original | 33 | + * must display the words "Powered by KnowledgeTree" and retain the original |
| 34 | * copyright notice. | 34 | * copyright notice. |
| 35 | * Contributor( s): ______________________________________ | 35 | * Contributor( s): ______________________________________ |
| 36 | * | 36 | * |
| @@ -51,6 +51,22 @@ class ExprOp | @@ -51,6 +51,22 @@ class ExprOp | ||
| 51 | const OP_OR = 'OR'; | 51 | const OP_OR = 'OR'; |
| 52 | const IS_NOT = 'is not'; | 52 | const IS_NOT = 'is not'; |
| 53 | 53 | ||
| 54 | + | ||
| 55 | + private static | ||
| 56 | + function init() | ||
| 57 | + { | ||
| 58 | + // this isn't really called, but used to help with translation. | ||
| 59 | + _kt('is'); | ||
| 60 | + _kt('contains'); | ||
| 61 | + _kt('between'); | ||
| 62 | + _kt('start with'); | ||
| 63 | + _kt('ends with'); | ||
| 64 | + _kt('like'); | ||
| 65 | + _kt('AND'); | ||
| 66 | + _kt('OR'); | ||
| 67 | + _kt('is not'); | ||
| 68 | + } | ||
| 69 | + | ||
| 54 | } | 70 | } |
| 55 | 71 | ||
| 56 | 72 |
search2/search/fields/CreatedByField.inc.php
| @@ -7,31 +7,31 @@ | @@ -7,31 +7,31 @@ | ||
| 7 | * Document Management Made Simple | 7 | * Document Management Made Simple |
| 8 | * Copyright (C) 2008 KnowledgeTree Inc. | 8 | * Copyright (C) 2008 KnowledgeTree Inc. |
| 9 | * Portions copyright The Jam Warehouse Software (Pty) Limited | 9 | * Portions copyright The Jam Warehouse Software (Pty) Limited |
| 10 | - * | 10 | + * |
| 11 | * This program is free software; you can redistribute it and/or modify it under | 11 | * This program is free software; you can redistribute it and/or modify it under |
| 12 | * the terms of the GNU General Public License version 3 as published by the | 12 | * the terms of the GNU General Public License version 3 as published by the |
| 13 | * Free Software Foundation. | 13 | * Free Software Foundation. |
| 14 | - * | 14 | + * |
| 15 | * This program is distributed in the hope that it will be useful, but WITHOUT | 15 | * This program is distributed in the hope that it will be useful, but WITHOUT |
| 16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | 16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| 17 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more | 17 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
| 18 | * details. | 18 | * details. |
| 19 | - * | 19 | + * |
| 20 | * You should have received a copy of the GNU General Public License | 20 | * You should have received a copy of the GNU General Public License |
| 21 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 21 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 22 | - * | ||
| 23 | - * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco, | 22 | + * |
| 23 | + * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco, | ||
| 24 | * California 94120-7775, or email info@knowledgetree.com. | 24 | * California 94120-7775, or email info@knowledgetree.com. |
| 25 | - * | 25 | + * |
| 26 | * The interactive user interfaces in modified source and object code versions | 26 | * The interactive user interfaces in modified source and object code versions |
| 27 | * of this program must display Appropriate Legal Notices, as required under | 27 | * of this program must display Appropriate Legal Notices, as required under |
| 28 | * Section 5 of the GNU General Public License version 3. | 28 | * Section 5 of the GNU General Public License version 3. |
| 29 | - * | 29 | + * |
| 30 | * In accordance with Section 7(b) of the GNU General Public License version 3, | 30 | * In accordance with Section 7(b) of the GNU General Public License version 3, |
| 31 | * these Appropriate Legal Notices must retain the display of the "Powered by | 31 | * these Appropriate Legal Notices must retain the display of the "Powered by |
| 32 | - * KnowledgeTree" logo and retain the original copyright notice. If the display of the | 32 | + * KnowledgeTree" logo and retain the original copyright notice. If the display of the |
| 33 | * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices | 33 | * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices |
| 34 | - * must display the words "Powered by KnowledgeTree" and retain the original | 34 | + * must display the words "Powered by KnowledgeTree" and retain the original |
| 35 | * copyright notice. | 35 | * copyright notice. |
| 36 | * Contributor( s): ______________________________________ | 36 | * Contributor( s): ______________________________________ |
| 37 | * | 37 | * |
| @@ -47,6 +47,25 @@ class CreatedByField extends DBFieldExpr | @@ -47,6 +47,25 @@ class CreatedByField extends DBFieldExpr | ||
| 47 | $this->matchField('name'); | 47 | $this->matchField('name'); |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | + public function appliesToContext() | ||
| 51 | + { | ||
| 52 | + return ExprContext::DOCUMENT | ExprContext::FOLDER; | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + public function setContext($context) | ||
| 56 | + { | ||
| 57 | + parent::setContext($context); | ||
| 58 | + switch($context) | ||
| 59 | + { | ||
| 60 | + case ExprContext::DOCUMENT: | ||
| 61 | + $this->table = 'documents'; | ||
| 62 | + break; | ||
| 63 | + case ExprContext::FOLDER: | ||
| 64 | + $this->table = 'folders'; | ||
| 65 | + break; | ||
| 66 | + } | ||
| 67 | + } | ||
| 68 | + | ||
| 50 | public function getInputRequirements() | 69 | public function getInputRequirements() |
| 51 | { | 70 | { |
| 52 | return array('value'=>array('type'=>FieldInputType::USER_LIST)); | 71 | return array('value'=>array('type'=>FieldInputType::USER_LIST)); |
search2/search/fields/FullPathField.inc.php
| @@ -7,31 +7,31 @@ | @@ -7,31 +7,31 @@ | ||
| 7 | * Document Management Made Simple | 7 | * Document Management Made Simple |
| 8 | * Copyright (C) 2008 KnowledgeTree Inc. | 8 | * Copyright (C) 2008 KnowledgeTree Inc. |
| 9 | * Portions copyright The Jam Warehouse Software (Pty) Limited | 9 | * Portions copyright The Jam Warehouse Software (Pty) Limited |
| 10 | - * | 10 | + * |
| 11 | * This program is free software; you can redistribute it and/or modify it under | 11 | * This program is free software; you can redistribute it and/or modify it under |
| 12 | * the terms of the GNU General Public License version 3 as published by the | 12 | * the terms of the GNU General Public License version 3 as published by the |
| 13 | * Free Software Foundation. | 13 | * Free Software Foundation. |
| 14 | - * | 14 | + * |
| 15 | * This program is distributed in the hope that it will be useful, but WITHOUT | 15 | * This program is distributed in the hope that it will be useful, but WITHOUT |
| 16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | 16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| 17 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more | 17 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
| 18 | * details. | 18 | * details. |
| 19 | - * | 19 | + * |
| 20 | * You should have received a copy of the GNU General Public License | 20 | * You should have received a copy of the GNU General Public License |
| 21 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 21 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 22 | - * | ||
| 23 | - * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco, | 22 | + * |
| 23 | + * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco, | ||
| 24 | * California 94120-7775, or email info@knowledgetree.com. | 24 | * California 94120-7775, or email info@knowledgetree.com. |
| 25 | - * | 25 | + * |
| 26 | * The interactive user interfaces in modified source and object code versions | 26 | * The interactive user interfaces in modified source and object code versions |
| 27 | * of this program must display Appropriate Legal Notices, as required under | 27 | * of this program must display Appropriate Legal Notices, as required under |
| 28 | * Section 5 of the GNU General Public License version 3. | 28 | * Section 5 of the GNU General Public License version 3. |
| 29 | - * | 29 | + * |
| 30 | * In accordance with Section 7(b) of the GNU General Public License version 3, | 30 | * In accordance with Section 7(b) of the GNU General Public License version 3, |
| 31 | * these Appropriate Legal Notices must retain the display of the "Powered by | 31 | * these Appropriate Legal Notices must retain the display of the "Powered by |
| 32 | - * KnowledgeTree" logo and retain the original copyright notice. If the display of the | 32 | + * KnowledgeTree" logo and retain the original copyright notice. If the display of the |
| 33 | * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices | 33 | * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices |
| 34 | - * must display the words "Powered by KnowledgeTree" and retain the original | 34 | + * must display the words "Powered by KnowledgeTree" and retain the original |
| 35 | * copyright notice. | 35 | * copyright notice. |
| 36 | * Contributor( s): ______________________________________ | 36 | * Contributor( s): ______________________________________ |
| 37 | * | 37 | * |
| @@ -47,6 +47,25 @@ class FullPathField extends DBFieldExpr | @@ -47,6 +47,25 @@ class FullPathField extends DBFieldExpr | ||
| 47 | $this->setAlias('FullPath'); | 47 | $this->setAlias('FullPath'); |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | + public function setContext($context) | ||
| 51 | + { | ||
| 52 | + parent::setContext($context); | ||
| 53 | + switch($context) | ||
| 54 | + { | ||
| 55 | + case ExprContext::DOCUMENT: | ||
| 56 | + $this->table = 'documents'; | ||
| 57 | + break; | ||
| 58 | + case ExprContext::FOLDER: | ||
| 59 | + $this->table = 'folders'; | ||
| 60 | + break; | ||
| 61 | + } | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + public function appliesToContext($context) | ||
| 65 | + { | ||
| 66 | + return ExprContext::DOCUMENT | ExprContext::FOLDER; | ||
| 67 | + } | ||
| 68 | + | ||
| 50 | public function getInputRequirements() | 69 | public function getInputRequirements() |
| 51 | { | 70 | { |
| 52 | return array('value'=>array('type'=>FieldInputType::TEXT)); | 71 | return array('value'=>array('type'=>FieldInputType::TEXT)); |
search2/search/fields/TitleField.inc.php
| @@ -7,31 +7,31 @@ | @@ -7,31 +7,31 @@ | ||
| 7 | * Document Management Made Simple | 7 | * Document Management Made Simple |
| 8 | * Copyright (C) 2008 KnowledgeTree Inc. | 8 | * Copyright (C) 2008 KnowledgeTree Inc. |
| 9 | * Portions copyright The Jam Warehouse Software (Pty) Limited | 9 | * Portions copyright The Jam Warehouse Software (Pty) Limited |
| 10 | - * | 10 | + * |
| 11 | * This program is free software; you can redistribute it and/or modify it under | 11 | * This program is free software; you can redistribute it and/or modify it under |
| 12 | * the terms of the GNU General Public License version 3 as published by the | 12 | * the terms of the GNU General Public License version 3 as published by the |
| 13 | * Free Software Foundation. | 13 | * Free Software Foundation. |
| 14 | - * | 14 | + * |
| 15 | * This program is distributed in the hope that it will be useful, but WITHOUT | 15 | * This program is distributed in the hope that it will be useful, but WITHOUT |
| 16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | 16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| 17 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more | 17 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
| 18 | * details. | 18 | * details. |
| 19 | - * | 19 | + * |
| 20 | * You should have received a copy of the GNU General Public License | 20 | * You should have received a copy of the GNU General Public License |
| 21 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 21 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 22 | - * | ||
| 23 | - * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco, | 22 | + * |
| 23 | + * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco, | ||
| 24 | * California 94120-7775, or email info@knowledgetree.com. | 24 | * California 94120-7775, or email info@knowledgetree.com. |
| 25 | - * | 25 | + * |
| 26 | * The interactive user interfaces in modified source and object code versions | 26 | * The interactive user interfaces in modified source and object code versions |
| 27 | * of this program must display Appropriate Legal Notices, as required under | 27 | * of this program must display Appropriate Legal Notices, as required under |
| 28 | * Section 5 of the GNU General Public License version 3. | 28 | * Section 5 of the GNU General Public License version 3. |
| 29 | - * | 29 | + * |
| 30 | * In accordance with Section 7(b) of the GNU General Public License version 3, | 30 | * In accordance with Section 7(b) of the GNU General Public License version 3, |
| 31 | * these Appropriate Legal Notices must retain the display of the "Powered by | 31 | * these Appropriate Legal Notices must retain the display of the "Powered by |
| 32 | - * KnowledgeTree" logo and retain the original copyright notice. If the display of the | 32 | + * KnowledgeTree" logo and retain the original copyright notice. If the display of the |
| 33 | * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices | 33 | * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices |
| 34 | - * must display the words "Powered by KnowledgeTree" and retain the original | 34 | + * must display the words "Powered by KnowledgeTree" and retain the original |
| 35 | * copyright notice. | 35 | * copyright notice. |
| 36 | * Contributor( s): ______________________________________ | 36 | * Contributor( s): ______________________________________ |
| 37 | * | 37 | * |
| @@ -39,13 +39,31 @@ | @@ -39,13 +39,31 @@ | ||
| 39 | 39 | ||
| 40 | class TitleField extends DBFieldExpr | 40 | class TitleField extends DBFieldExpr |
| 41 | { | 41 | { |
| 42 | - | ||
| 43 | public function __construct() | 42 | public function __construct() |
| 44 | { | 43 | { |
| 45 | parent::__construct('name', 'document_metadata_version', _kt('Title')); | 44 | parent::__construct('name', 'document_metadata_version', _kt('Title')); |
| 46 | $this->setAlias('Title'); | 45 | $this->setAlias('Title'); |
| 47 | } | 46 | } |
| 48 | 47 | ||
| 48 | + public function setContext($context) | ||
| 49 | + { | ||
| 50 | + parent::setContext($context); | ||
| 51 | + switch($context) | ||
| 52 | + { | ||
| 53 | + case ExprContext::DOCUMENT: | ||
| 54 | + $this->table = 'document_metadata_version'; | ||
| 55 | + break; | ||
| 56 | + case ExprContext::FOLDER: | ||
| 57 | + $this->table = 'folders'; | ||
| 58 | + break; | ||
| 59 | + } | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + public function appliesToContext() | ||
| 63 | + { | ||
| 64 | + return ExprContext::DOCUMENT | ExprContext::FOLDER; | ||
| 65 | + } | ||
| 66 | + | ||
| 49 | public function getInputRequirements() | 67 | public function getInputRequirements() |
| 50 | { | 68 | { |
| 51 | return array('value'=>array('type'=>FieldInputType::TEXT)); | 69 | return array('value'=>array('type'=>FieldInputType::TEXT)); |
search2/search/search.inc.php
| @@ -42,6 +42,8 @@ require_once('search/fieldRegistry.inc.php'); | @@ -42,6 +42,8 @@ require_once('search/fieldRegistry.inc.php'); | ||
| 42 | require_once('search/expr.inc.php'); | 42 | require_once('search/expr.inc.php'); |
| 43 | require_once(KT_LIB_DIR . '/security/Permission.inc'); | 43 | require_once(KT_LIB_DIR . '/security/Permission.inc'); |
| 44 | 44 | ||
| 45 | +// TODO: move standalone functions into a class.... what was I thinking? | ||
| 46 | + | ||
| 45 | function rank_compare($a, $b) | 47 | function rank_compare($a, $b) |
| 46 | { | 48 | { |
| 47 | if ($a->Rank == $b->Rank) | 49 | if ($a->Rank == $b->Rank) |
| @@ -66,6 +68,8 @@ function searchfix($str) | @@ -66,6 +68,8 @@ function searchfix($str) | ||
| 66 | return str_replace(array("\n","\r"), array('',''), addslashes($str)); | 68 | return str_replace(array("\n","\r"), array('',''), addslashes($str)); |
| 67 | } | 69 | } |
| 68 | 70 | ||
| 71 | +// TODO: replace manual json construction with json_encode(). | ||
| 72 | + | ||
| 69 | class SearchHelper | 73 | class SearchHelper |
| 70 | { | 74 | { |
| 71 | public static function correctPath($path) | 75 | public static function correctPath($path) |
| @@ -366,8 +370,6 @@ class SearchHelper | @@ -366,8 +370,6 @@ class SearchHelper | ||
| 366 | dtfl.document_type_id=$documentTypeID | 370 | dtfl.document_type_id=$documentTypeID |
| 367 | ORDER BY | 371 | ORDER BY |
| 368 | df.name"; | 372 | df.name"; |
| 369 | - | ||
| 370 | - | ||
| 371 | } | 373 | } |
| 372 | else | 374 | else |
| 373 | { | 375 | { |
| @@ -566,7 +568,8 @@ function processSearchExpression($query) | @@ -566,7 +568,8 @@ function processSearchExpression($query) | ||
| 566 | { | 568 | { |
| 567 | $expr = parseExpression($query); | 569 | $expr = parseExpression($query); |
| 568 | 570 | ||
| 569 | - $rs = $expr->evaluate(); | 571 | + $rs = $expr->evaluate(ExprContext::DOCUMENT); |
| 572 | + $rs = $rs['docs']; | ||
| 570 | usort($rs, 'rank_compare'); | 573 | usort($rs, 'rank_compare'); |
| 571 | 574 | ||
| 572 | $results = array(); | 575 | $results = array(); |
| @@ -629,4 +632,57 @@ function processSearchExpression($query) | @@ -629,4 +632,57 @@ function processSearchExpression($query) | ||
| 629 | } | 632 | } |
| 630 | } | 633 | } |
| 631 | 634 | ||
| 635 | +function resolveSearchShortcuts($result) | ||
| 636 | +{ | ||
| 637 | + $oPermission =& KTPermission::getByName('ktcore.permissions.read'); | ||
| 638 | + $permId = $oPermission->getID(); | ||
| 639 | + | ||
| 640 | + $oUser = User::get($_SESSION['userID']); | ||
| 641 | + $aPermissionDescriptors = KTPermissionUtil::getPermissionDescriptorsForUser($oUser); | ||
| 642 | + $sPermissionDescriptors = empty($aPermissionDescriptors)? -1: implode(',', $aPermissionDescriptors); | ||
| 643 | + | ||
| 644 | + $documentIds = implode(',',array_keys($result['docs'])); | ||
| 645 | + $linkedDocuments = array(); | ||
| 646 | + if (!empty($documentIds)) | ||
| 647 | + { | ||
| 648 | + $sql = "SELECT d.id, d.linked_document_id from documents d "; | ||
| 649 | + $sql .= 'INNER JOIN permission_lookups AS PL ON d.permission_lookup_id = PL.id '. "\n"; | ||
| 650 | + $sql .= 'INNER JOIN permission_lookup_assignments AS PLA ON PL.id = PLA.permission_lookup_id AND PLA.permission_id = '.$permId. " \n"; | ||
| 651 | + $sql .= " WHERE d.linked_document_id in ($documentIds) AND PLA.permission_descriptor_id IN ($sPermissionDescriptors)"; | ||
| 652 | + | ||
| 653 | + $rs = DBUtil::getResultArray($sql); | ||
| 654 | + | ||
| 655 | + foreach($rs as $row) | ||
| 656 | + { | ||
| 657 | + $id = $row['id']; | ||
| 658 | + $linked_id = $row['linked_document_id']; | ||
| 659 | + | ||
| 660 | + $result['shortdocs'][$id] = new DocumentShortcutResultItem($id, $result['docs'][$linked_id]); | ||
| 661 | + } | ||
| 662 | + } | ||
| 663 | + | ||
| 664 | + $folderIds = implode(',',array_keys($result['folders'])); | ||
| 665 | + $linkedFolders = array(); | ||
| 666 | + | ||
| 667 | + if (!empty($folderIds)) | ||
| 668 | + { | ||
| 669 | + | ||
| 670 | + $sql = "SELECT f.id, f.linked_folder_id from folders f "; | ||
| 671 | + $sql .= 'INNER JOIN permission_lookups AS PL ON f.permission_lookup_id = PL.id '. "\n"; | ||
| 672 | + $sql .= 'INNER JOIN permission_lookup_assignments AS PLA ON PL.id = PLA.permission_lookup_id AND PLA.permission_id = '.$permId. " \n"; | ||
| 673 | + $sql .= " WHERE f.linked_folder_id in ($folderIds) AND PLA.permission_descriptor_id IN ($sPermissionDescriptors)"; | ||
| 674 | + | ||
| 675 | + $rs = DBUtil::getResultArray($sql); | ||
| 676 | + | ||
| 677 | + foreach($rs as $row) | ||
| 678 | + { | ||
| 679 | + $id = $row['id']; | ||
| 680 | + $linked_id = $row['linked_folder_id']; | ||
| 681 | + | ||
| 682 | + $result['shortfolders'][$id] = new FolderShortcutResultItem($id, $result['folders'][$linked_id]); | ||
| 683 | + } | ||
| 684 | + } | ||
| 685 | + return $result; | ||
| 686 | +} | ||
| 687 | + | ||
| 632 | ?> | 688 | ?> |
sql/mysql/install/data.sql
| @@ -199,7 +199,7 @@ INSERT INTO `config_settings` VALUES | @@ -199,7 +199,7 @@ INSERT INTO `config_settings` VALUES | ||
| 199 | (25, 'session', 'Anonymous Login', 'Defines whether to allow anonymous users to log in automatically. Default is \'False\'. <br>Best practice is not to allow automatic login of anonymous users unless you understand KnowledgeTree\'s security mechanisms, and have sensibly applied the roles \'Everyone\' and \'Authenticated Users\'. ', 'allowAnonymousLogin', 'default', 'false', 'boolean', NULL, 1), | 199 | (25, 'session', 'Anonymous Login', 'Defines whether to allow anonymous users to log in automatically. Default is \'False\'. <br>Best practice is not to allow automatic login of anonymous users unless you understand KnowledgeTree\'s security mechanisms, and have sensibly applied the roles \'Everyone\' and \'Authenticated Users\'. ', 'allowAnonymousLogin', 'default', 'false', 'boolean', NULL, 1), |
| 200 | (26, 'ui', 'Company Logo', 'Specifies the path (relative to the KnowledgeTree directory) to the custom logo for the KnowledgeTree user interface. <br>The logo must be 50px tall, and on a white background.', 'companyLogo', 'default', '${rootUrl}/resources/companylogo.png', 'string', NULL, 1), | 200 | (26, 'ui', 'Company Logo', 'Specifies the path (relative to the KnowledgeTree directory) to the custom logo for the KnowledgeTree user interface. <br>The logo must be 50px tall, and on a white background.', 'companyLogo', 'default', '${rootUrl}/resources/companylogo.png', 'string', NULL, 1), |
| 201 | (27, 'ui', 'Company Logo Width', 'Defines the width, in pixels, of your custom logo.', 'companyLogoWidth', 'default', '313px', 'string', NULL, 1), | 201 | (27, 'ui', 'Company Logo Width', 'Defines the width, in pixels, of your custom logo.', 'companyLogoWidth', 'default', '313px', 'string', NULL, 1), |
| 202 | -(28, 'ui', 'Company Logo Title', 'Alternative text for the title of your custom company logo, for accessibility purposes.', 'companyLogoTitle', 'default', 'ACME Corporation', 'string', NULL, 1), | 202 | +(28, 'ui', 'Company Logo Title', 'Alternative text for the title of your custom company logo, for accessibility purposes.', 'companyLogoTitle', 'default', 'Add Company Name', 'string', NULL, 1), |
| 203 | (29, 'ui', 'Always Show All Results', 'Defines, where \'show all users\' is an available action, whether to display the full list of users and groups on page load, without requiring the user to click \'show all users\'. Default is \'False\'.', 'alwaysShowAll', 'default', 'false', 'boolean', NULL, 1), | 203 | (29, 'ui', 'Always Show All Results', 'Defines, where \'show all users\' is an available action, whether to display the full list of users and groups on page load, without requiring the user to click \'show all users\'. Default is \'False\'.', 'alwaysShowAll', 'default', 'false', 'boolean', NULL, 1), |
| 204 | (30, 'ui', 'Condensed Admin UI', 'Defines whether to use a condensed (compact) version of the KnowledgeTree user interface for the admin user. Default is \'False\'.', 'condensedAdminUI', 'default', 'false', 'boolean', NULL, 1), | 204 | (30, 'ui', 'Condensed Admin UI', 'Defines whether to use a condensed (compact) version of the KnowledgeTree user interface for the admin user. Default is \'False\'.', 'condensedAdminUI', 'default', 'false', 'boolean', NULL, 1), |
| 205 | (31, 'ui', 'Fake Mimetype', 'Defines whether browsers may provide the option to \'open\' a document from download. Default is \'False\'.<br>Change to \'True\' to prevent (most) browsers from giving users the \'Open\' option.', 'fakeMimetype', 'default', 'false', 'boolean', NULL, 1), | 205 | (31, 'ui', 'Fake Mimetype', 'Defines whether browsers may provide the option to \'open\' a document from download. Default is \'False\'.<br>Change to \'True\' to prevent (most) browsers from giving users the \'Open\' option.', 'fakeMimetype', 'default', 'false', 'boolean', NULL, 1), |
| @@ -270,10 +270,11 @@ INSERT INTO `config_settings` VALUES | @@ -270,10 +270,11 @@ INSERT INTO `config_settings` VALUES | ||
| 270 | (96, 'KnowledgeTree', 'Redirect To Browse View: Exceptions', 'Specifies that, when \'Redirect To Browse\' is set to \'True\' all users, except for the users listed in the text field below are redirected to the Browse view on log in. The users listed for this setting are directed to the KnowledgeTree Dashboard. To define exceptions, add user names in the text field as follows, e.g. admin, joebloggs, etc.', 'redirectToBrowseExceptions', '', '', 'string', NULL, 1), | 270 | (96, 'KnowledgeTree', 'Redirect To Browse View: Exceptions', 'Specifies that, when \'Redirect To Browse\' is set to \'True\' all users, except for the users listed in the text field below are redirected to the Browse view on log in. The users listed for this setting are directed to the KnowledgeTree Dashboard. To define exceptions, add user names in the text field as follows, e.g. admin, joebloggs, etc.', 'redirectToBrowseExceptions', '', '', 'string', NULL, 1), |
| 271 | (97, 'session', 'Allow Automatic Sign In', 'Defines whether to automatically create a user account on first login for any user who does not yet exist in the system. Default is \'False\'.', 'allowAutoSignup', 'default', 'false', 'boolean', 'string', 1), | 271 | (97, 'session', 'Allow Automatic Sign In', 'Defines whether to automatically create a user account on first login for any user who does not yet exist in the system. Default is \'False\'.', 'allowAutoSignup', 'default', 'false', 'boolean', 'string', 1), |
| 272 | (98, 'ldapAuthentication', 'Create Groups Automatically', 'Defines whether to allow LDAP groups to be created automatically. Default is \'False\'.', 'autoGroupCreation', 'default', 'false', 'boolean', 'string', 1), | 272 | (98, 'ldapAuthentication', 'Create Groups Automatically', 'Defines whether to allow LDAP groups to be created automatically. Default is \'False\'.', 'autoGroupCreation', 'default', 'false', 'boolean', 'string', 1), |
| 273 | -(99, 'browse', 'Truncate Document and Folder Titles in Browse View', 'Defines the length of the document or folder title displayed in the browse view.', 'titleCharLength', 'default', '40', 'numeric_string', 'string', 1), | 273 | +(99, 'browse', 'Truncate Document and Folder Titles in Browse View', 'Defines the maximum number of characters to display for a document or folder title in the browse view. The maximum allowable number of characters is 255.', 'titleCharLength', 'default', '40', 'numeric_string', 'string', 1), |
| 274 | (100, 'import', 'Disable Bulk Import', 'Disable the bulk import plugin', 'disableBulkImport', 'default', 'false', 'string', NULL, 1), | 274 | (100, 'import', 'Disable Bulk Import', 'Disable the bulk import plugin', 'disableBulkImport', 'default', 'false', 'string', NULL, 1), |
| 275 | (101, 'session', 'Enable version check', 'Compares the system version with the database version to determine if a database upgrade is needed.','dbversioncompare', 'default', 'true', 'boolean', NULL, 0), | 275 | (101, 'session', 'Enable version check', 'Compares the system version with the database version to determine if a database upgrade is needed.','dbversioncompare', 'default', 'true', 'boolean', NULL, 0), |
| 276 | -(102, 'tweaks', 'Update Document Version (Content) on Editing Metadata', 'The document version is equivalent to the document content version. When set to true the document version will be increased when the document metadata is updated.', 'updateContentVersion', 'default', 'false', 'boolean', NULL, 1); | 276 | +(102, 'tweaks', 'Update Document Version (Content) on Editing Metadata', 'The document version is equivalent to the document content version. When set to true the document version will be increased when the document metadata is updated.', 'updateContentVersion', 'default', 'false', 'boolean', NULL, 1), |
| 277 | +(103, 'tweaks', 'Always Force Original Filename on Checkin', 'When set to true, the checkbox for "Force Original Filename" will be hidden on check-in. This ensures that the filename will always stay the same.', 'disableForceFilenameOption', 'default', 'false', 'boolean', NULL, 1); | ||
| 277 | /*!40000 ALTER TABLE `config_settings` ENABLE KEYS */; | 278 | /*!40000 ALTER TABLE `config_settings` ENABLE KEYS */; |
| 278 | UNLOCK TABLES; | 279 | UNLOCK TABLES; |
| 279 | 280 |
sql/mysql/upgrade/3.5.3/length_config_setting.sql
| 1 | INSERT INTO `config_settings` (group_name, display_name, description, item, value, default_value, type, options, can_edit) VALUES | 1 | INSERT INTO `config_settings` (group_name, display_name, description, item, value, default_value, type, options, can_edit) VALUES |
| 2 | 2 | ||
| 3 | -('browse', 'Truncate Document and Folder Titles in Browse View', 'Defines the length of the document or folder title displayed in the | ||
| 4 | -browse view.', 'titleCharLength', 'default', '40', 'numeric_string', NULL, 1), | 3 | +('browse', 'Truncate Document and Folder Titles in Browse View', 'Defines the maximum number of characters to display for a document or folder title in the browse view. The maximum allowable number of characters is 255.', 'titleCharLength', 'default', '40', 'numeric_string', NULL, 1), |
| 5 | 4 | ||
| 6 | ('import', 'Disable Bulk Import', 'Disable the bulk import plugin', 'disableBulkImport', 'default', 'false', 'string', NULL, 1), | 5 | ('import', 'Disable Bulk Import', 'Disable the bulk import plugin', 'disableBulkImport', 'default', 'false', 'string', NULL, 1), |
| 7 | 6 | ||
| 8 | -('session', 'Enable version check', 'Compares the system version with the database version to determine if a database upgrade is needed.', | ||
| 9 | -'dbversioncompare', 'default', 'true', 'boolean', NULL, 0), | 7 | +('session', 'Enable version check', 'Compares the system version with the database version to determine if a database upgrade is needed.', 'dbversioncompare', 'default', 'true', 'boolean', NULL, 0), |
| 10 | 8 | ||
| 11 | -('tweaks', 'Update Document Version (Content) on Editing Metadata', 'The document version is equivalent to the document content version. When set to | ||
| 12 | -true the document version will be increased when the document metadata is updated.', 'updateContentVersion', 'default', 'false', 'boolean', NULL, 1); | ||
| 13 | \ No newline at end of file | 9 | \ No newline at end of file |
| 10 | +('tweaks', 'Update Document Version (Content) on Editing Metadata', 'The document version is equivalent to the document content version. When set to true the document version will be increased when the document metadata is updated.', 'updateContentVersion', 'default', 'false', 'boolean', NULL, 1), | ||
| 11 | + | ||
| 12 | +('tweaks', 'Always Force Original Filename on Checkin', 'When set to true, the checkbox for "Force Original Filename" will be hidden on check-in. This ensures that the filename will always stay the same.', 'disableForceFilenameOption', 'default', 'false', 'boolean', NULL, 1); | ||
| 13 | + | ||
| 14 | +UPDATE config_settings SET default_value = 'Add Company Name' WHERE group_name = 'ui' AND item = 'companyLogoTitle'; | ||
| 14 | \ No newline at end of file | 15 | \ No newline at end of file |
templates/ktcore/search2/search_results.smarty
| @@ -46,7 +46,6 @@ function saveSearch() | @@ -46,7 +46,6 @@ function saveSearch() | ||
| 46 | url='{/literal}{$rootUrl}{literal}/search2/ajax/saveExpr.php?txtName='+ escape(txtName.value) + | 46 | url='{/literal}{$rootUrl}{literal}/search2/ajax/saveExpr.php?txtName='+ escape(txtName.value) + |
| 47 | '&txtQuery=' + escape('{/literal}{$txtQuery|escape:'quotes'}{literal}'); | 47 | '&txtQuery=' + escape('{/literal}{$txtQuery|escape:'quotes'}{literal}'); |
| 48 | 48 | ||
| 49 | - | ||
| 50 | Ext.Ajax.request( | 49 | Ext.Ajax.request( |
| 51 | { | 50 | { |
| 52 | url: url, | 51 | url: url, |
| @@ -132,57 +131,82 @@ function onShowAll(showall) | @@ -132,57 +131,82 @@ function onShowAll(showall) | ||
| 132 | <table border=0 cellpadding="1" cellspacing="1" width="100%" align=center> | 131 | <table border=0 cellpadding="1" cellspacing="1" width="100%" align=center> |
| 133 | {assign var=cbid value=0} | 132 | {assign var=cbid value=0} |
| 134 | 133 | ||
| 135 | - {foreach item=document from=$results} | 134 | + {i18n arg_count=$numResults}Search results found: #count#{/i18n} |
| 135 | + <br/> | ||
| 136 | + <br/> | ||
| 137 | + | ||
| 138 | + {foreach item=hit from=$results} | ||
| 136 | <tr><td> | 139 | <tr><td> |
| 137 | - <input type="checkbox" name="selection_d[]" id="cb{$cbid}" value="{$document->DocumentID}"><nobr> <a href="{$rootUrl}/view.php?fDocumentId={$document->DocumentID}"><B>{$document->Title|truncate:80}</b></a> | ||
| 138 | - {if $document->Title != $document->Filename} | 140 | + <input type="checkbox" {if $hit->IsDocument}name="selection_d[]"{else}name="selection_f[]"{/if} id="cb{$cbid}" value="{$hit->Id}"><nobr> |
| 141 | + <span class="contenttype {$hit->MimeIconPath}"> | ||
| 142 | + | ||
| 143 | + {if $hit->IsDocument} | ||
| 144 | + <a href="{$rootUrl}/view.php?fDocumentId={$hit->Id}"><B>{$hit->Title|truncate:80}</b></a> | ||
| 145 | + {if $hit->Title != $hit->Filename} | ||
| 139 | | 146 | |
| 140 | - <font style=" color: green "> - Filename: {$document->Filename|truncate:40}</font> | 147 | + <font style=" color: green "> - {i18n}Filename:{/i18n} {$hit->Filename|truncate:40}</font> |
| 141 | {/if} | 148 | {/if} |
| 142 | - {if $document->IsAvailable} | 149 | + {if $hit->IsAvailable} |
| 143 | | 150 | |
| 144 | - <img src="{$rootUrl}/resources/graphics/download.png" title="Download Document" onclick="document.location='{$rootUrl}/action.php?kt_path_info=ktcore.actions.document.view&fDocumentId={$document->DocumentID}';"></a> | 151 | + <img src="{$rootUrl}/resources/graphics/download.png" title="Download Document" onclick="document.location='{$rootUrl}/action.php?kt_path_info=ktcore.actions.document.view&fDocumentId={$hit->Id}';"></a> |
| 145 | 152 | ||
| 146 | {/if} | 153 | {/if} |
| 147 | 154 | ||
| 148 | 155 | ||
| 149 | - {if !$document->IsAvailable} | 156 | + {if !$hit->IsAvailable} |
| 150 | | 157 | |
| 151 | <font style=" color: red "><B> * {i18n}NOT AVAILABLE{/i18n} * </B></font> | 158 | <font style=" color: red "><B> * {i18n}NOT AVAILABLE{/i18n} * </B></font> |
| 152 | {/if} | 159 | {/if} |
| 153 | 160 | ||
| 161 | + {else} | ||
| 162 | + <a href="{$rootUrl}/browse.php?fFolderId={$hit->RealId}{if $hit->IsProxy}&fShortcutFolder={$hit->Id}{/if}"><B>{$hit->Title|truncate:80}</b></a> | ||
| 163 | + | ||
| 164 | + {/if} | ||
| 165 | + | ||
| 154 | </nobr> | 166 | </nobr> |
| 155 | </td><td align=right> | 167 | </td><td align=right> |
| 156 | - <font style="color: green ">{i18n}Document ID:{/i18n} {$document->DocumentID}</font> | ||
| 157 | - | ||
| 158 | - <font style=" color: orange ">{i18n}Version:{/i18n} {$document->Version}</font></td> | 168 | + {if $hit->IsDocument} |
| 169 | + <font style="color: green ">{i18n}Document ID:{/i18n} {$hit->Id}</font> | ||
| 170 | + | ||
| 171 | + <font style=" color: orange ">{i18n}Version:{/i18n} {$hit->Version}</font></td> | ||
| 172 | + {else} | ||
| 173 | + <font style="color: green ">{i18n}Folder ID:{/i18n} {$hit->Id}</font> | ||
| 174 | + {/if} | ||
| 159 | </tr> | 175 | </tr> |
| 160 | - <tr><td colspan=2>{$document->Text}</td></tr> | ||
| 161 | - <tr><td><font style=" color: green "><a href="{$rootUrl}/browse.php?fFolderId={$document->FolderId}" tag="{$document->FullPath}">{$document->FullPath|truncate:40}</a>/{$document->Title|truncate:40} - {$document->Filesize}</font> | ||
| 162 | - | 176 | + <tr><td colspan=2>{$hit->Text}</td></tr> |
| 177 | + <tr><td> | ||
| 178 | + {if $hit->IsDocument} | ||
| 179 | + <font style=" color: green "><a href="{$rootUrl}/browse.php?fFolderId={$hit->FolderId}" tag="{$hit->FullPath}">{$hit->FullPath|truncate:40}</a>/{$hit->Title|truncate:40} - {$hit->Filesize}</font> | ||
| 180 | + {else} | ||
| 181 | + <font style=" color: green "><a href="{$rootUrl}/browse.php?fFolderId={$hit->FolderId}" tag="{$hit->FullPath}">{$hit->FullPath|truncate:40}</a></font> | ||
| 182 | + {/if} | ||
| 163 | </td> | 183 | </td> |
| 164 | <td align=right><nobr> | 184 | <td align=right><nobr> |
| 165 | <font style="color: orange "> | 185 | <font style="color: orange "> |
| 166 | - {i18n}Created By:{/i18n} {$document->CreatedBy} | ||
| 167 | - {i18n}on{/i18n} {$document->DateCreated} | 186 | + {i18n}Created By:{/i18n} {$hit->CreatedBy} |
| 187 | + {if $hit->IsDocument} | ||
| 188 | + {i18n}on{/i18n} {$hit->DateCreated} | ||
| 189 | + {/if} | ||
| 168 | </font> | 190 | </font> |
| 169 | </td> | 191 | </td> |
| 192 | + {if $hit->IsDocument} | ||
| 170 | <tr><td> | 193 | <tr><td> |
| 171 | {if $workflow != ''} | 194 | {if $workflow != ''} |
| 172 | - <font style="color: orange ">{i18n}Workflow:{/i18n} $document->Workflow}</font> | 195 | + <font style="color: orange ">{i18n}Workflow:{/i18n} $hit->Workflow}</font> |
| 173 | {/if} | 196 | {/if} |
| 174 | </td> | 197 | </td> |
| 175 | <td align=right><nobr> | 198 | <td align=right><nobr> |
| 176 | <font style="color: brown "> | 199 | <font style="color: brown "> |
| 177 | - {if $document->CheckedOutUser != ''} | ||
| 178 | - <b>{i18n}Checked out by:{/i18n} {$document->CheckedOutUser} | ||
| 179 | - {i18n}on{/i18n} {$document->DateCheckedOut}</b> | 200 | + {if $hit->CheckedOutUser != ''} |
| 201 | + <b>{i18n}Checked out by:{/i18n} {$hit->CheckedOutUser} | ||
| 202 | + {i18n}on{/i18n} {$hit->DateCheckedOut}</b> | ||
| 180 | {else} | 203 | {else} |
| 181 | - {i18n}Modified by:{/i18n} {$document->ModifiedBy} | ||
| 182 | - {i18n}on{/i18n} {$document->DateModified} | 204 | + {i18n}Modified by:{/i18n} {$hit->ModifiedBy} |
| 205 | + {i18n}on{/i18n} {$hit->DateModified} | ||
| 183 | {/if} | 206 | {/if} |
| 184 | </font> | 207 | </font> |
| 185 | </td> | 208 | </td> |
| 209 | + {/if} | ||
| 186 | 210 | ||
| 187 | <tr><td colspan=2><br></br></td></tr></tr> | 211 | <tr><td colspan=2><br></br></td></tr></tr> |
| 188 | 212 |