mirror of
https://git.code.sf.net/p/seeddms/code
synced 2025-06-18 02:59:27 +00:00
Compare commits
No commits in common. "master" and "5.0.2" have entirely different histories.
|
@ -1,8 +0,0 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
trim_trailing_whitespace = true
|
||||
indent_style = tab
|
||||
indent_size = 2
|
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -1,4 +0,0 @@
|
|||
*.tar.gz
|
||||
SeedDMS_*/*.tgz
|
||||
ext/*
|
||||
webapp/*
|
43
.htaccess
43
.htaccess
|
@ -1,43 +0,0 @@
|
|||
Options -Indexes
|
||||
|
||||
<IfModule mod_headers.c>
|
||||
Header set Strict-Transport-Security: "max-age=15768000; includeSubDomains; preload"
|
||||
Header set X-Content-Type-Options: "nosniff"
|
||||
</IfModule>
|
||||
|
||||
RewriteEngine On
|
||||
RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
|
||||
#RewriteRule "^favicon\.ico$" "-" [L]
|
||||
#RewriteRule "^(favicon\.ico)$" %{HTTP_HOST}/views/bootstrap/images/favicon.svg [L,NC]
|
||||
RewriteRule "^(favicon\.ico)" /views/bootstrap/images/favicon.svg [L,NC]
|
||||
|
||||
# Store the current location in an environment variable CWD to use
|
||||
# mod_rewrite in .htaccess files without knowing the RewriteBase
|
||||
RewriteCond $0#%{REQUEST_URI} ([^#]*)#(.*)\1$
|
||||
RewriteRule ^.*$ - [E=CWD:%2]
|
||||
|
||||
# Do not allow access on the other directories in www
|
||||
RewriteRule "^utils/.*$" "" [F]
|
||||
RewriteRule "^doc/.*$" "" [F]
|
||||
|
||||
# Anything below the following dirs will never be rewritten
|
||||
RewriteRule "^pdfviewer/.*$" "-" [L]
|
||||
RewriteRule "^views/.*/images.*$" "-" [L]
|
||||
RewriteRule "^out/images.*$" "-" [L]
|
||||
RewriteRule "^styles/.*$" "-" [L]
|
||||
|
||||
# Accessing a file in an extension is only possible in one
|
||||
# of the directories op, out. res
|
||||
# Added for old extensions which do not use routes
|
||||
RewriteRule ^ext/[^/]+/icon.(?:png|svg)$ - [L]
|
||||
RewriteCond %{REQUEST_URI} "ext/[^/]+/"
|
||||
RewriteRule !^ext/[^/]+/.*(?:op|out|res|node_modules) - [F]
|
||||
RewriteCond %{REQUEST_URI} "ext/[^/]+/res/.*$" [NC]
|
||||
RewriteRule !^ext/[^/]+/res/.*\.(?:css|js|png|gif|svg|ico|html|woff|ttf) - [F]
|
||||
RewriteCond %{REQUEST_FILENAME} -f
|
||||
RewriteRule ^ext/.*$ - [L]
|
||||
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_FILENAME} !-l
|
||||
RewriteRule ^.*$ %{ENV:CWD}index.php [QSA,L]
|
388
Gruntfile.js
388
Gruntfile.js
|
@ -1,388 +0,0 @@
|
|||
module.exports = function (grunt) {
|
||||
'use strict';
|
||||
|
||||
// if you set bootstrapDir to views/bootstrap/vendors then make sure
|
||||
// bootbox is not installed, because version 5 of bootbox will not work
|
||||
// with bootstrap 2
|
||||
var bootstrapDir = 'views/bootstrap4/vendors',
|
||||
tdkDir = 'views/tdk/vendors',
|
||||
nodeDir = 'node_modules';
|
||||
|
||||
grunt.initConfig({
|
||||
clean: {
|
||||
vendors: [ bootstrapDir ]
|
||||
},
|
||||
copy: {
|
||||
'bootstrap': {
|
||||
files: [{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/jquery/dist/*'
|
||||
],
|
||||
dest: bootstrapDir + '/jquery',
|
||||
flatten: true
|
||||
}, {
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/chartjs/chart.js',
|
||||
nodeDir + '/chartjs/README.md',
|
||||
nodeDir + '/chartjs/LICENSE'
|
||||
],
|
||||
dest: bootstrapDir + '/chartjs',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/cytoscape/dist/*',
|
||||
nodeDir + '/cytoscape-grid-guide/cytoscape-grid-guide.js'
|
||||
],
|
||||
dest: bootstrapDir + '/cytoscape',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/jqtree/tree.jquery.js',
|
||||
nodeDir + '/jqtree/jqtree.css'
|
||||
],
|
||||
dest: bootstrapDir + '/jqtree',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/noty/js/noty/jquery.noty.js'
|
||||
],
|
||||
dest: bootstrapDir + '/noty',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/noty/js/noty/themes/*'
|
||||
],
|
||||
dest: bootstrapDir + '/noty/themes',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/noty/js/noty/layouts/*'
|
||||
],
|
||||
dest: bootstrapDir + '/noty/layouts',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/select2/dist/js/*'
|
||||
],
|
||||
dest: bootstrapDir + '/select2/js',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/select2/dist/js/i18n/*'
|
||||
],
|
||||
dest: bootstrapDir + '/select2/js/i18n',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/select2/dist/css/*'
|
||||
],
|
||||
dest: bootstrapDir + '/select2/css',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/@ttskch/select2-bootstrap4-theme/dist/*'
|
||||
],
|
||||
dest: bootstrapDir + '/select2-bootstrap4-theme',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/vis-timeline/dist/*'
|
||||
],
|
||||
dest: bootstrapDir + '/vis-timeline',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/fine-uploader/jquery.fine-uploader/*'
|
||||
],
|
||||
dest: bootstrapDir + '/fine-uploader',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/jquery-validation/dist/*'
|
||||
],
|
||||
dest: bootstrapDir + '/jquery-validation',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/jquery-typeahead/dist/*'
|
||||
],
|
||||
dest: bootstrapDir + '/jquery-typeahead',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/bootbox/dist/*'
|
||||
],
|
||||
dest: bootstrapDir + '/bootbox',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/flot/source/jquery.canvaswrapper.js',
|
||||
nodeDir + '/flot/source/jquery.colorhelpers.js',
|
||||
nodeDir + '/flot/source/jquery.flot.*'
|
||||
],
|
||||
dest: bootstrapDir + '/flot',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/font-awesome/fonts/*'
|
||||
],
|
||||
dest: bootstrapDir + '/font-awesome/fonts',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/font-awesome/css/*'
|
||||
],
|
||||
dest: bootstrapDir + '/font-awesome/css',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/fullcalendar/LICENSE.txt',
|
||||
nodeDir + '/fullcalendar/dist/*'
|
||||
],
|
||||
dest: bootstrapDir + '/fullcalendar',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/fullcalendar/dist/locale/*'
|
||||
],
|
||||
dest: bootstrapDir + '/fullcalendar/locale',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/moment/LICENSE.txt',
|
||||
nodeDir + '/moment/min/*'
|
||||
],
|
||||
dest: bootstrapDir + '/moment',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/moment/dist/locale/*'
|
||||
],
|
||||
dest: bootstrapDir + '/moment/locale',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/popper.js/dist/umd/*'
|
||||
],
|
||||
dest: bootstrapDir + '/popper',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/perfect-scrollbar/dist/*'
|
||||
],
|
||||
dest: bootstrapDir + '/perfect-scrollbar',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/bootstrap/dist/js/bootstrap.min.js',
|
||||
nodeDir + '/bootstrap/dist/css/bootstrap.min.css'
|
||||
],
|
||||
dest: bootstrapDir + '/bootstrap',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/spectrum-colorpicker2/dist/spectrum.min.js',
|
||||
nodeDir + '/spectrum-colorpicker2/dist/spectrum.min.css'
|
||||
],
|
||||
dest: bootstrapDir + '/spectrum-colorpicker2',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/jquery-lazy/jquery.lazy.min.js',
|
||||
nodeDir + '/jquery-lazy/jquery.lazy.plugins.js'
|
||||
],
|
||||
dest: bootstrapDir + '/jquery-lazy',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/bootstrap-datepicker/dist/js/*'
|
||||
],
|
||||
dest: bootstrapDir + '/bootstrap-datepicker/js',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/bootstrap-datepicker/dist/css/*'
|
||||
],
|
||||
dest: bootstrapDir + '/bootstrap-datepicker/css',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/bootstrap-datepicker/dist/locales/*'
|
||||
],
|
||||
dest: bootstrapDir + '/bootstrap-datepicker/locales',
|
||||
flatten: true
|
||||
}]
|
||||
},
|
||||
'tdk': {
|
||||
files: [{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/jquery/dist/*'
|
||||
],
|
||||
dest: tdkDir + '/jquery',
|
||||
flatten: true
|
||||
}, {
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/@coreui/coreui/dist/js/*'
|
||||
],
|
||||
dest: tdkDir + '/@coreui/coreui/js',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/@coreui/coreui/dist/css/*'
|
||||
],
|
||||
dest: tdkDir + '/@coreui/coreui/css',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/@coreui/icons/css/*'
|
||||
],
|
||||
dest: tdkDir + '/@coreui/icons/css',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/@coreui/icons/fonts/*'
|
||||
],
|
||||
dest: tdkDir + '/@coreui/icons/fonts',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/popper.js/dist/esm/*'
|
||||
],
|
||||
dest: tdkDir + '/popper.js',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/perfect-scrollbar/dist/*'
|
||||
],
|
||||
dest: tdkDir + '/perfect-scrollbar',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/bootstrap/dist/js/*'
|
||||
],
|
||||
dest: tdkDir + '/bootstrap/js',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/bootstrap/dist/css/*'
|
||||
],
|
||||
dest: tdkDir + '/bootstrap/css',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/font-awesome/fonts/*'
|
||||
],
|
||||
dest: tdkDir + '/font-awesome/fonts',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/font-awesome/css/*'
|
||||
],
|
||||
dest: tdkDir + '/font-awesome/css',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/pace-progressbar/index.js'
|
||||
],
|
||||
dest: tdkDir + '/pace-progressbar',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/pace-progressbar/themes/*'
|
||||
],
|
||||
dest: tdkDir + '/pace-progressbar/themes',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/pace-progressbar/templates/*'
|
||||
],
|
||||
dest: tdkDir + '/pace-progressbar/templates',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/flag-icon-css/css/*'
|
||||
],
|
||||
dest: tdkDir + '/flag-icon-css/css',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/simple-line-icons/dist/fonts/*'
|
||||
],
|
||||
dest: tdkDir + '/simple-line-icons/fonts',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/simple-line-icons/dist/styles/*'
|
||||
],
|
||||
dest: tdkDir + '/simple-line-icons/css',
|
||||
flatten: true
|
||||
}]
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
grunt.registerTask('createVendorDir', 'Creates the necessary vendor directory', function() {
|
||||
// Create the bootstrapDir when it doesn't exists.
|
||||
if (!grunt.file.isDir(bootstrapDir)) {
|
||||
grunt.file.mkdir(bootstrapDir);
|
||||
|
||||
// Output a success message
|
||||
grunt.log.oklns(grunt.template.process(
|
||||
'Directory "<%= directory %>" was created successfully.',
|
||||
{ data: { directory: bootstrapDir } }
|
||||
));
|
||||
}
|
||||
});
|
||||
|
||||
grunt.registerTask('default', [ 'clean', 'createVendorDir', 'copy' ]);
|
||||
grunt.loadNpmTasks('grunt-contrib-clean');
|
||||
grunt.loadNpmTasks('grunt-contrib-copy');
|
||||
};
|
87
Makefile
87
Makefile
|
@ -1,34 +1,20 @@
|
|||
VERSION=$(shell php -r 'include("inc/inc.Version.php"); $$v=new SeedDMS_Version(); echo $$v->version();')
|
||||
SRC=CHANGELOG inc conf utils index.php .htaccess languages op out controllers doc TODO LICENSE webdav install restapi pdfviewer
|
||||
VIEWS ?= bootstrap bootstrap4
|
||||
VERSION=5.0.2
|
||||
SRC=CHANGELOG inc conf utils index.php languages views op out controllers doc drop-tables-innodb.sql styles js TODO LICENSE Makefile webdav install restapi
|
||||
# webapp
|
||||
|
||||
NODISTFILES=utils/importmail.php utils/seedddms-importmail utils/remote-email-upload utils/remote-upload utils/da-bv-reminder.php utils/seeddms-da-bv-reminder utils/relodge.php utils/seeddms-relodge .svn .gitignore
|
||||
EXTENSIONS := \
|
||||
dynamic_content.tar.gz\
|
||||
login_action.tar.gz\
|
||||
example.tar.gz
|
||||
|
||||
PHPDOC=~/Downloads/phpDocumentor.phar
|
||||
PHPDOC=~/Downloads/phpDocumentor-2.8.1/bin/phpdoc
|
||||
|
||||
dist:
|
||||
mkdir -p tmp/seeddms-$(VERSION)
|
||||
cp -a $(SRC) tmp/seeddms-$(VERSION)
|
||||
mkdir -p tmp/seeddms-$(VERSION)/views
|
||||
mkdir -p tmp/seeddms-$(VERSION)/styles
|
||||
for view in $(VIEWS) ; do \
|
||||
if [ -d "views/$$view" ] ; then \
|
||||
cp -a views/$$view tmp/seeddms-$(VERSION)/views ; \
|
||||
fi ; \
|
||||
if [ -d "styles/$$view" ] ; then \
|
||||
cp -a styles/$$view tmp/seeddms-$(VERSION)/styles ; \
|
||||
fi ; \
|
||||
done
|
||||
(cd tmp/seeddms-$(VERSION); rm -rf $(NODISTFILES); mv conf conf.template)
|
||||
(cd tmp; tar --exclude=.svn --exclude=.gitignore -czvf ../seeddms-$(VERSION).tar.gz seeddms-$(VERSION))
|
||||
(cd tmp; tar --exclude=.svn -czvf ../seeddms-$(VERSION).tar.gz seeddms-$(VERSION))
|
||||
rm -rf tmp
|
||||
|
||||
quickstart:
|
||||
php7.4 vendor/bin/phing -Dversion=$(VERSION) package
|
||||
|
||||
unittest:
|
||||
vendor/bin/phing -Dversion=$(VERSION) phpunitfast
|
||||
|
||||
pear:
|
||||
(cd SeedDMS_Core/; pear package)
|
||||
(cd SeedDMS_Lucene/; pear package)
|
||||
|
@ -47,52 +33,21 @@ webapp:
|
|||
(cd tmp; tar --exclude=.svn -czvf ../seeddms-webapp-$(VERSION).tar.gz seeddms-webapp-$(VERSION))
|
||||
rm -rf tmp
|
||||
|
||||
repository:
|
||||
mkdir -p tmp/seeddms-repository-$(VERSION)
|
||||
cp -a repository/www repository/utils repository/doc tmp/seeddms-repository-$(VERSION)
|
||||
rm -f tmp/seeddms-repository/utils/update-repository.log
|
||||
mkdir -p tmp/seeddms-repository-$(VERSION)/files
|
||||
mkdir -p tmp/seeddms-repository-$(VERSION)/accounts
|
||||
cp -a repository/files/.htaccess tmp/seeddms-repository-$(VERSION)/files
|
||||
cp -a repository/accounts/.htaccess tmp/seeddms-repository-$(VERSION)/accounts
|
||||
cp inc/inc.ClassExtensionMgr.php tmp/seeddms-repository-$(VERSION)/utils
|
||||
(cd tmp; tar --exclude=.svn -czvf ../seeddms-repository-$(VERSION).tar.gz seeddms-repository-$(VERSION))
|
||||
rm -rf tmp
|
||||
dynamic_content.tar.gz: ext/dynamic_content
|
||||
tar czvf dynamic_content.tar.gz ext/dynamic_content
|
||||
|
||||
example.tar.gz: ext/example
|
||||
tar czvf example.tar.gz ext/example
|
||||
|
||||
login_action.tar.gz: ext/login_action
|
||||
tar czvf login_action.tar.gz ext/login_action
|
||||
|
||||
extensions: $(EXTENSIONS)
|
||||
|
||||
doc:
|
||||
$(PHPDOC) -d SeedDMS_Core --ignore 'getusers.php,getfoldertree.php,config.php,reverselookup.php' --force -t html
|
||||
|
||||
# Download apigen with
|
||||
# composer create-project --no-dev apigen/apigen:^7.0@alpha tools/apigen
|
||||
apidoc:
|
||||
tools/apigen/bin/apigen SeedDMS_Core/Core --exclude "tests/*" --output html
|
||||
apigen generate -s SeedDMS_Core --exclude tests --skip-doc-prefix tests -d html
|
||||
|
||||
# Turn the package.xml file into CHANGELOG.md
|
||||
#
|
||||
# The idea is to form blocks of lines separated by an empty line.
|
||||
# Echo block consists of the version number, release date und notes.
|
||||
# This blocks are turned into single lines which are than sorted.
|
||||
# Afterwards the single lines are turned back into blocks.
|
||||
#
|
||||
# It first uses sgrep to extract the version, date und notes. This is
|
||||
# feed to sed to isolated the date and version and put them on separate
|
||||
# lines. Each version
|
||||
# forms a block of n lines with the first two being the version and date.
|
||||
# All remaining lines are notes. Blocks are separated by an empty line.
|
||||
# It's important to form blocks without ane empty lines because the following
|
||||
# awk will create a single line from each block which can then be sorted
|
||||
# (or simply reversed in order).
|
||||
# Because the blocks are listed in the wrong order (last version first and
|
||||
# previous version last, e.g. 5.1.29, 3.3.0, 3.3.1, ...., 5.1.27, 5.1.28) they
|
||||
# need to be reversed in order. This is done by turning each block into line
|
||||
# with the former new lines replaced by a '|'. So it's basically a '|' separated
|
||||
# csv file which is then reversed in order by 'sort -r'. In order to separate
|
||||
# blocks by a newline, each line of that output is appended by another
|
||||
# line break. Result is put back
|
||||
# into the original format by replacing all '|' by newline.
|
||||
#
|
||||
PKGFILE=SeedDMS_Core/package.xml
|
||||
changelog:
|
||||
@sgrep 'stag("DATE") .. etag("DATE") or ((stag("RELEASE") .. etag("RELEASE")) in (stag("VERSION") .. etag("VERSION"))) or inner(stag("NOTES") __ etag("NOTES"))' ${PKGFILE} | sed -e 's#^ *<date>\([-0-9]*\)</date><release>\([0-9.preRC]*\)</release>#\n\n\2 (\1)\n---------------------#' | awk -F'\n' -vRS='' -vOFS='|' '{$$1=$$1}1' | sort -V -r | sed 's/$$/\n/' | tr '|' '\n'
|
||||
|
||||
.PHONY: doc webdav webapp repository changelog
|
||||
.PHONY: webdav webapp
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
Extensions in SeedDMS
|
||||
=====================
|
||||
====================
|
||||
|
||||
Since verson 5.0.0 SeedDMS can be extended by extensions. Extensions
|
||||
can hook up functions into certain operations, e.g.
|
94
SeedDMS_Core/Core.php
Normal file
94
SeedDMS_Core/Core.php
Normal file
|
@ -0,0 +1,94 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of a document in the document management system
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Core
|
||||
* @license GPL2
|
||||
* @author Markus Westphal, Malcolm Cowe, Matteo Lucarelli,
|
||||
* Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe,
|
||||
* 2010 Matteo Lucarelli, 2010-2012 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @uses SeedDMS_DatabaseAccess
|
||||
*/
|
||||
define('USE_PDO', 1);
|
||||
if(defined('USE_PDO'))
|
||||
require_once('Core/inc.DBAccessPDO.php');
|
||||
else
|
||||
require_once('Core/inc.DBAccess.php');
|
||||
|
||||
/**
|
||||
* @uses SeedDMS_DMS
|
||||
*/
|
||||
require_once('Core/inc.ClassDMS.php');
|
||||
|
||||
/**
|
||||
* @uses SeedDMS_Object
|
||||
*/
|
||||
require_once('Core/inc.ClassObject.php');
|
||||
|
||||
/**
|
||||
* @uses SeedDMS_Folder
|
||||
*/
|
||||
require_once('Core/inc.ClassFolder.php');
|
||||
|
||||
/**
|
||||
* @uses SeedDMS_Document
|
||||
*/
|
||||
require_once('Core/inc.ClassDocument.php');
|
||||
|
||||
/**
|
||||
* @uses SeedDMS_Attribute
|
||||
*/
|
||||
require_once('Core/inc.ClassAttribute.php');
|
||||
|
||||
/**
|
||||
* @uses SeedDMS_Group
|
||||
*/
|
||||
require_once('Core/inc.ClassGroup.php');
|
||||
|
||||
/**
|
||||
* @uses SeedDMS_User
|
||||
*/
|
||||
require_once('Core/inc.ClassUser.php');
|
||||
|
||||
/**
|
||||
* @uses SeedDMS_KeywordCategory
|
||||
*/
|
||||
require_once('Core/inc.ClassKeywords.php');
|
||||
|
||||
/**
|
||||
* @uses SeedDMS_DocumentCategory
|
||||
*/
|
||||
require_once('Core/inc.ClassDocumentCategory.php');
|
||||
|
||||
/**
|
||||
* @uses SeedDMS_Notification
|
||||
*/
|
||||
require_once('Core/inc.ClassNotification.php');
|
||||
|
||||
/**
|
||||
* @uses SeedDMS_UserAccess
|
||||
* @uses SeedDMS_GroupAccess
|
||||
*/
|
||||
require_once('Core/inc.ClassAccess.php');
|
||||
|
||||
/**
|
||||
* @uses SeedDMS_Workflow
|
||||
*/
|
||||
require_once('Core/inc.ClassWorkflow.php');
|
||||
|
||||
/**
|
||||
*/
|
||||
require_once('Core/inc.AccessUtils.php');
|
||||
|
||||
/**
|
||||
* @uses SeedDMS_File
|
||||
*/
|
||||
require_once('Core/inc.FileUtils.php');
|
||||
|
||||
?>
|
90
SeedDMS_Core/Core/inc.AccessUtils.php
Normal file
90
SeedDMS_Core/Core/inc.AccessUtils.php
Normal file
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
/**
|
||||
* Some definitions for access control
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Core
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Markus Westphal, Malcolm Cowe, Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2002-2005 Markus Westphal,
|
||||
* 2006-2008 Malcolm Cowe, 2010 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Used to indicate that a search should return all
|
||||
* results in the ACL table. See {@link SeedDMS_Core_Folder::getAccessList()}
|
||||
*/
|
||||
define("M_ANY", -1);
|
||||
|
||||
/**
|
||||
* No rights at all
|
||||
*/
|
||||
define("M_NONE", 1);
|
||||
|
||||
/**
|
||||
* Read access only
|
||||
*/
|
||||
define("M_READ", 2);
|
||||
|
||||
/**
|
||||
* Read and write access only
|
||||
*/
|
||||
define("M_READWRITE", 3);
|
||||
|
||||
/**
|
||||
* Unrestricted access
|
||||
*/
|
||||
define("M_ALL", 4);
|
||||
|
||||
define ("O_GTEQ", ">=");
|
||||
define ("O_LTEQ", "<=");
|
||||
define ("O_EQ", "=");
|
||||
|
||||
/**
|
||||
* Folder notification
|
||||
*/
|
||||
define("T_FOLDER", 1); //TargetType = Folder
|
||||
|
||||
/**
|
||||
* Document notification
|
||||
*/
|
||||
define("T_DOCUMENT", 2); // " = Document
|
||||
|
||||
/**
|
||||
* Notify on all actions on the folder/document
|
||||
*/
|
||||
define("N_ALL", 0);
|
||||
|
||||
/**
|
||||
* Notify when object has been deleted
|
||||
*/
|
||||
define("N_DELETE", 1);
|
||||
|
||||
/**
|
||||
* Notify when object has been moved
|
||||
*/
|
||||
define("N_MOVE", 2);
|
||||
|
||||
/**
|
||||
* Notify when object has been updated (no new version)
|
||||
*/
|
||||
define("N_UPDATE", 3);
|
||||
|
||||
/**
|
||||
* Notify when document has new version
|
||||
*/
|
||||
define("N_NEW_VERSION", 4);
|
||||
|
||||
/**
|
||||
* Notify when version of document was deleted
|
||||
*/
|
||||
define("N_DELETE_VERSION", 5);
|
||||
|
||||
/**
|
||||
* Notify when version of document was deleted
|
||||
*/
|
||||
define("N_ADD_DOCUMENT", 6);
|
||||
|
||||
?>
|
76
SeedDMS_Core/Core/inc.ClassAccess.php
Normal file
76
SeedDMS_Core/Core/inc.ClassAccess.php
Normal file
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of user and group access object
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Core
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe,
|
||||
* 2010 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class to represent a user access right.
|
||||
* This class cannot be used to modify access rights.
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Core
|
||||
* @author Markus Westphal, Malcolm Cowe, Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe,
|
||||
* 2010 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Core_UserAccess { /* {{{ */
|
||||
var $_user;
|
||||
var $_mode;
|
||||
|
||||
function __construct($user, $mode) {
|
||||
$this->_user = $user;
|
||||
$this->_mode = $mode;
|
||||
}
|
||||
|
||||
function getUserID() { return $this->_user->getID(); }
|
||||
|
||||
function getMode() { return $this->_mode; }
|
||||
|
||||
function isAdmin() {
|
||||
return ($this->_mode == SeedDMS_Core_User::role_admin);
|
||||
}
|
||||
|
||||
function getUser() {
|
||||
return $this->_user;
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
|
||||
/**
|
||||
* Class to represent a group access right.
|
||||
* This class cannot be used to modify access rights.
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Core
|
||||
* @author Markus Westphal, Malcolm Cowe, Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe, 2010 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Core_GroupAccess { /* {{{ */
|
||||
var $_group;
|
||||
var $_mode;
|
||||
|
||||
function __construct($group, $mode) {
|
||||
$this->_group = $group;
|
||||
$this->_mode = $mode;
|
||||
}
|
||||
|
||||
function getGroupID() { return $this->_group->getID(); }
|
||||
|
||||
function getMode() { return $this->_mode; }
|
||||
|
||||
function getGroup() {
|
||||
return $this->_group;
|
||||
}
|
||||
} /* }}} */
|
||||
?>
|
948
SeedDMS_Core/Core/inc.ClassAttribute.php
Normal file
948
SeedDMS_Core/Core/inc.ClassAttribute.php
Normal file
|
@ -0,0 +1,948 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of the attribute object in the document management system
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Core
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2012 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class to represent an attribute in the document management system
|
||||
*
|
||||
* Attributes are key/value pairs which can be attachted to documents,
|
||||
* folders and document content. The number of attributes is unlimited.
|
||||
* Each attribute has a value and is related to an attribute definition,
|
||||
* which holds the name and other information about the attribute.
|
||||
*
|
||||
* @see SeedDMS_Core_AttributeDefinition
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Core
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2012-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Core_Attribute { /* {{{ */
|
||||
/**
|
||||
* @var integer id of attribute
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected $_id;
|
||||
|
||||
/**
|
||||
* @var object SeedDMS_Core_Object folder, document or document content
|
||||
* this attribute belongs to
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected $_obj;
|
||||
|
||||
/**
|
||||
* @var object SeedDMS_Core_AttributeDefinition definition of this attribute
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected $_attrdef;
|
||||
|
||||
/**
|
||||
* @var mixed value of this attribute
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected $_value;
|
||||
|
||||
/**
|
||||
* @var integer validation error
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected $_validation_error;
|
||||
|
||||
/**
|
||||
* @var object SeedDMS_Core_DMS reference to the dms instance this attribute belongs to
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected $_dms;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param integer $id internal id of attribute
|
||||
* @param SeedDMS_Core_Object $obj object this attribute is attached to
|
||||
* @param SeedDMS_Core_AttributeDefinition $attrdef reference to the attribute definition
|
||||
* @param string $value value of the attribute
|
||||
*/
|
||||
function __construct($id, $obj, $attrdef, $value) { /* {{{ */
|
||||
$this->_id = $id;
|
||||
$this->_obj = $obj;
|
||||
$this->_attrdef = $attrdef;
|
||||
$this->_value = $value;
|
||||
$this->_validation_error = 0;
|
||||
$this->_dms = null;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Set reference to dms
|
||||
*
|
||||
* @param SeedDMS_Core_DMS $dms
|
||||
*/
|
||||
function setDMS($dms) { /* {{{ */
|
||||
$this->_dms = $dms;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Get internal id of attribute
|
||||
*
|
||||
* @return integer id
|
||||
*/
|
||||
function getID() { return $this->_id; }
|
||||
|
||||
/**
|
||||
* Return attribute value as stored in database
|
||||
*
|
||||
* This function will return the value of multi value attributes
|
||||
* including the separator char.
|
||||
*
|
||||
* @return string the attribute value as it is stored in the database.
|
||||
*/
|
||||
function getValue() { return $this->_value; }
|
||||
|
||||
/**
|
||||
* Return attribute values as an array
|
||||
*
|
||||
* This function returns the attribute value as an array. The array
|
||||
* has one element for non multi value attributes and n elements for
|
||||
* multi value attributes.
|
||||
*
|
||||
* @return array the attribute values
|
||||
*/
|
||||
function getValueAsArray() { /* {{{ */
|
||||
if($this->_attrdef->getMultipleValues()) {
|
||||
return explode($this->_value[0], substr($this->_value, 1));
|
||||
} else {
|
||||
return array($this->_value);
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Set a value of an attribute
|
||||
*
|
||||
* The attribute is completely deleted if the value is an empty string
|
||||
* or empty array. An array of values is only allowed if the attribute may
|
||||
* have multiple values. If an array is passed and the attribute may
|
||||
* have only a single value, then the first element of the array will
|
||||
* be taken.
|
||||
*
|
||||
* @param string $values value as string or array to be set
|
||||
* @return boolean true if operation was successfull, otherwise false
|
||||
*/
|
||||
function setValue($values) { /* {{{*/
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
if($this->_attrdef->getMultipleValues()) {
|
||||
/* Multiple values without a value set is not allowed */
|
||||
if(!$valuesetstr = $this->_attrdef->getValueSet())
|
||||
return false;
|
||||
$valueset = $this->_attrdef->getValueSetAsArray();
|
||||
|
||||
if(is_array($values)) {
|
||||
if($values) {
|
||||
$error = false;
|
||||
foreach($values as $v) {
|
||||
if(!in_array($v, $valueset)) { $error = true; break; }
|
||||
}
|
||||
if($error)
|
||||
return false;
|
||||
$valuesetstr = $this->_attrdef->getValueSet();
|
||||
$value = $valuesetstr[0].implode($valuesetstr[0], $values);
|
||||
} else {
|
||||
$value = '';
|
||||
}
|
||||
} else {
|
||||
if($values) {
|
||||
if($valuesetstr[0] != $values[0])
|
||||
$values = explode($valuesetstr[0], $values);
|
||||
else
|
||||
$values = explode($valuesetstr[0], substr($values, 1));
|
||||
|
||||
$error = false;
|
||||
foreach($values as $v) {
|
||||
if(!in_array($v, $valueset)) { $error = true; break; }
|
||||
}
|
||||
if($error)
|
||||
return false;
|
||||
$value = $valuesetstr[0].implode($valuesetstr[0], $values);
|
||||
} else {
|
||||
$value = $values;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(is_array($values)) {
|
||||
if($values)
|
||||
$value = $values[0];
|
||||
else
|
||||
$value = '';
|
||||
} else {
|
||||
$value = $values;
|
||||
}
|
||||
}
|
||||
|
||||
switch(get_class($this->_obj)) {
|
||||
case $this->_dms->getClassname('document'):
|
||||
if(trim($value) === '')
|
||||
$queryStr = "DELETE FROM tblDocumentAttributes WHERE `document` = " . $this->_obj->getID() . " AND `attrdef` = " . $this->_attrdef->getId();
|
||||
else
|
||||
$queryStr = "UPDATE tblDocumentAttributes SET value = ".$db->qstr($value)." WHERE `document` = " . $this->_obj->getID() . " AND `attrdef` = " . $this->_attrdef->getId();
|
||||
break;
|
||||
case $this->_dms->getClassname('documentcontent'):
|
||||
if(trim($value) === '')
|
||||
$queryStr = "DELETE FROM tblDocumentContentAttributes WHERE `content` = " . $this->_obj->getID() . " AND `attrdef` = " . $this->_attrdef->getId();
|
||||
else
|
||||
$queryStr = "UPDATE tblDocumentContentAttributes SET value = ".$db->qstr($value)." WHERE `content` = " . $this->_obj->getID() . " AND `attrdef` = " . $this->_attrdef->getId();
|
||||
break;
|
||||
case $this->_dms->getClassname('folder'):
|
||||
if(trim($value) === '')
|
||||
$queryStr = "DELETE FROM tblFolderAttributes WHERE `folder` = " . $this->_obj->getID() . " AND `attrdef` = " . $this->_attrdef->getId();
|
||||
else
|
||||
$queryStr = "UPDATE tblFolderAttributes SET value = ".$db->qstr($value)." WHERE `folder` = " . $this->_obj->getID() . " AND `attrdef` = " . $this->_attrdef->getId();
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if (!$db->getResult($queryStr))
|
||||
return false;
|
||||
|
||||
$this->_value = $value;
|
||||
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Validate attribute value
|
||||
*
|
||||
* This function checks if the attribute values fits the attribute
|
||||
* definition.
|
||||
* If the validation fails the validation error will be set which
|
||||
* can be requested by SeedDMS_Core_Attribute::getValidationError()
|
||||
*
|
||||
* @return boolean true if validation succeds, otherwise false
|
||||
*/
|
||||
function validate() { /* {{{ */
|
||||
$attrdef = $this->_attrdef();
|
||||
$result = $attrdef->validate($this->_value);
|
||||
$this->_validation_error = $attrdef->getValidationError();
|
||||
return $result;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Get validation error from last validation
|
||||
*
|
||||
* @return integer error code
|
||||
*/
|
||||
function getValidationError() { return $this->_validation_error; }
|
||||
|
||||
/**
|
||||
* Get definition of attribute
|
||||
*
|
||||
* @return object attribute definition
|
||||
*/
|
||||
function getAttributeDefinition() { return $this->_attrdef; }
|
||||
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Class to represent an attribute definition in the document management system
|
||||
*
|
||||
* Attribute definitions specify the name, type, object type, minimum and
|
||||
* maximum values and a value set. The object type determines the object
|
||||
* an attribute may be attached to. If the object type is set to object_all
|
||||
* the attribute can be used for documents, document content and folders.
|
||||
*
|
||||
* The type of an attribute specifies the skalar data type.
|
||||
*
|
||||
* Attributes for which multiple values are allowed must have the
|
||||
* multiple flag set to true and specify a value set. A value set
|
||||
* is a string consisting of n separated values. The separator is the
|
||||
* first char of the value set. A possible value could be '|REV-A|REV-B'
|
||||
* If multiple values are allowed, then minvalues and maxvalues may
|
||||
* restrict the allowed number of values.
|
||||
*
|
||||
* @see SeedDMS_Core_Attribute
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Core
|
||||
* @author Markus Westphal, Malcolm Cowe, Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2012 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Core_AttributeDefinition { /* {{{ */
|
||||
/**
|
||||
* @var integer id of attribute definition
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected $_id;
|
||||
|
||||
/**
|
||||
* @var string name of attribute definition
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected $_name;
|
||||
|
||||
/**
|
||||
* @var string object type of attribute definition. This can be one of
|
||||
* type_int, type_float, type_string, type_boolean, type_url, or type_email.
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected $_type;
|
||||
|
||||
/**
|
||||
* @var string type of attribute definition. This can be one of objtype_all,
|
||||
* objtype_folder, objtype_document, or objtype_documentcontent.
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected $_objtype;
|
||||
|
||||
/**
|
||||
* @var boolean whether an attribute can have multiple values
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected $_multiple;
|
||||
|
||||
/**
|
||||
* @var integer minimum values of an attribute
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected $_minvalues;
|
||||
|
||||
/**
|
||||
* @var integer maximum values of an attribute
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected $_maxvalues;
|
||||
|
||||
/**
|
||||
* @var string list of possible values of an attribute
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected $_valueset;
|
||||
|
||||
/**
|
||||
* @var string regular expression the value must match
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected $_regex;
|
||||
|
||||
/**
|
||||
* @var integer validation error
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected $_validation_error;
|
||||
|
||||
/**
|
||||
* @var object SeedDMS_Core_DMS reference to the dms instance this attribute definition belongs to
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected $_dms;
|
||||
|
||||
/*
|
||||
* Possible skalar data types of an attribute
|
||||
*/
|
||||
const type_int = '1';
|
||||
const type_float = '2';
|
||||
const type_string = '3';
|
||||
const type_boolean = '4';
|
||||
const type_url = '5';
|
||||
const type_email = '6';
|
||||
const type_date = '7';
|
||||
|
||||
/*
|
||||
* The object type for which a attribute may be used
|
||||
*/
|
||||
const objtype_all = '0';
|
||||
const objtype_folder = '1';
|
||||
const objtype_document = '2';
|
||||
const objtype_documentcontent = '3';
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param integer $id internal id of attribute definition
|
||||
* @param string $name name of attribute
|
||||
* @param integer $objtype type of object for which this attribute definition
|
||||
* may be used.
|
||||
* @param integer $type skalar type of attribute
|
||||
* @param boolean $multiple set to true if multiple values are allowed
|
||||
* @param integer $minvalues minimum number of values
|
||||
* @param integer $maxvalues maximum number of values
|
||||
* @param string $valueset separated list of allowed values, the first char
|
||||
* is taken as the separator
|
||||
*/
|
||||
function __construct($id, $name, $objtype, $type, $multiple, $minvalues, $maxvalues, $valueset, $regex) { /* {{{ */
|
||||
$this->_id = $id;
|
||||
$this->_name = $name;
|
||||
$this->_type = $type;
|
||||
$this->_objtype = $objtype;
|
||||
$this->_multiple = $multiple;
|
||||
$this->_minvalues = $minvalues;
|
||||
$this->_maxvalues = $maxvalues;
|
||||
$this->_valueset = $valueset;
|
||||
$this->_separator = '';
|
||||
$this->_regex = $regex;
|
||||
$this->_dms = null;
|
||||
$this->_validation_error = 0;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Set reference to dms
|
||||
*
|
||||
* @param SeedDMS_Core_DMS $dms
|
||||
*/
|
||||
function setDMS($dms) { /* {{{ */
|
||||
$this->_dms = $dms;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Get internal id of attribute definition
|
||||
*
|
||||
* @return integer id
|
||||
*/
|
||||
function getID() { return $this->_id; }
|
||||
|
||||
/**
|
||||
* Get name of attribute definition
|
||||
*
|
||||
* @return string name
|
||||
*/
|
||||
function getName() { return $this->_name; }
|
||||
|
||||
function setName($name) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "UPDATE tblAttributeDefinitions SET name =".$db->qstr($name)." WHERE id = " . $this->_id;
|
||||
$res = $db->getResult($queryStr);
|
||||
if (!$res)
|
||||
return false;
|
||||
|
||||
$this->_name = $name;
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Get object type of attribute definition
|
||||
*
|
||||
* This can be one of objtype_all,
|
||||
* objtype_folder, objtype_document, or objtype_documentcontent.
|
||||
*
|
||||
* @return integer type
|
||||
*/
|
||||
function getObjType() { return $this->_objtype; }
|
||||
|
||||
/**
|
||||
* Set object type of attribute definition
|
||||
*
|
||||
* This can be one of objtype_all,
|
||||
* objtype_folder, objtype_document, or objtype_documentcontent.
|
||||
*
|
||||
* @param integer $objtype type
|
||||
*/
|
||||
function setObjType($objtype) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "UPDATE tblAttributeDefinitions SET objtype =".intval($objtype)." WHERE id = " . $this->_id;
|
||||
$res = $db->getResult($queryStr);
|
||||
if (!$res)
|
||||
return false;
|
||||
|
||||
$this->_objtype = $objtype;
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Get type of attribute definition
|
||||
*
|
||||
* This can be one of type_int, type_float, type_string, type_boolean,
|
||||
* type_url, type_email.
|
||||
*
|
||||
* @return integer type
|
||||
*/
|
||||
function getType() { return $this->_type; }
|
||||
|
||||
/**
|
||||
* Set type of attribute definition
|
||||
*
|
||||
* This can be one of type_int, type_float, type_string, type_boolean,
|
||||
* type_url, type_email.
|
||||
*
|
||||
* @param integer $type type
|
||||
*/
|
||||
function setType($type) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "UPDATE tblAttributeDefinitions SET type =".intval($type)." WHERE id = " . $this->_id;
|
||||
$res = $db->getResult($queryStr);
|
||||
if (!$res)
|
||||
return false;
|
||||
|
||||
$this->_type = $type;
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Check if attribute definition allows multi values for attribute
|
||||
*
|
||||
* @return boolean true if attribute may have multiple values
|
||||
*/
|
||||
function getMultipleValues() { return $this->_multiple; }
|
||||
|
||||
/**
|
||||
* Set if attribute definition allows multi values for attribute
|
||||
*
|
||||
* @param boolean $mv true if attribute may have multiple values, otherwise
|
||||
* false
|
||||
*/
|
||||
function setMultipleValues($mv) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "UPDATE tblAttributeDefinitions SET multiple =".intval($mv)." WHERE id = " . $this->_id;
|
||||
$res = $db->getResult($queryStr);
|
||||
if (!$res)
|
||||
return false;
|
||||
|
||||
$this->_multiple = $mv;
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Return minimum number of values for attributes
|
||||
*
|
||||
* Attributes with multiple values may be limited to a range
|
||||
* of values. This functions returns the minimum number of values.
|
||||
*
|
||||
* @return integer minimum number of values
|
||||
*/
|
||||
function getMinValues() { return $this->_minvalues; }
|
||||
|
||||
function setMinValues($minvalues) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "UPDATE tblAttributeDefinitions SET minvalues =".intval($minvalues)." WHERE id = " . $this->_id;
|
||||
$res = $db->getResult($queryStr);
|
||||
if (!$res)
|
||||
return false;
|
||||
|
||||
$this->_minvalues = $minvalues;
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Return maximum number of values for attributes
|
||||
*
|
||||
* Attributes with multiple values may be limited to a range
|
||||
* of values. This functions returns the maximum number of values.
|
||||
*
|
||||
* @return integer maximum number of values
|
||||
*/
|
||||
function getMaxValues() { return $this->_maxvalues; }
|
||||
|
||||
function setMaxValues($maxvalues) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "UPDATE tblAttributeDefinitions SET maxvalues =".intval($maxvalues)." WHERE id = " . $this->_id;
|
||||
$res = $db->getResult($queryStr);
|
||||
if (!$res)
|
||||
return false;
|
||||
|
||||
$this->_maxvalues = $maxvalues;
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Get the value set as saved in the database
|
||||
*
|
||||
* This is a string containing the list of valueѕ separated by a
|
||||
* delimiter which also precedes the whole string, e.g. '|Yes|No'
|
||||
*
|
||||
* Use {@link SeedDMS_Core_AttributeDefinition::getValueSetAsArray()}
|
||||
* for a list of values returned as an array.
|
||||
*
|
||||
* @return string value set
|
||||
*/
|
||||
function getValueSet() { /* {{{ */
|
||||
return $this->_valueset;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Get the whole value set as an array
|
||||
*
|
||||
* @return array values of value set or false if the value set has
|
||||
* less than 2 chars
|
||||
*/
|
||||
function getValueSetAsArray() { /* {{{ */
|
||||
if(strlen($this->_valueset) > 1)
|
||||
return explode($this->_valueset[0], substr($this->_valueset, 1));
|
||||
else
|
||||
return array();
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Get the n'th value of a value set
|
||||
*
|
||||
* @param interger $index
|
||||
* @return string n'th value of value set or false if the index is
|
||||
* out of range or the value set has less than 2 chars
|
||||
*/
|
||||
function getValueSetValue($ind) { /* {{{ */
|
||||
if(strlen($this->_valueset) > 1) {
|
||||
$tmp = explode($this->_valueset[0], substr($this->_valueset, 1));
|
||||
if(isset($tmp[$ind]))
|
||||
return $tmp[$ind];
|
||||
else
|
||||
return false;
|
||||
} else
|
||||
return false;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Set the value set
|
||||
*
|
||||
* A value set is a list of values allowed for an attribute. The values
|
||||
* are separated by a char which must also be the first char of the
|
||||
* value set string.
|
||||
*
|
||||
* @param string $valueset
|
||||
* @return boolean true if value set could be set, otherwise false
|
||||
*/
|
||||
function setValueSet($valueset) { /* {{{ */
|
||||
/*
|
||||
$tmp = array();
|
||||
foreach($valueset as $value) {
|
||||
$tmp[] = str_replace('"', '""', $value);
|
||||
}
|
||||
$valuesetstr = implode(",", $tmp);
|
||||
*/
|
||||
$valuesetstr = $valueset;
|
||||
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "UPDATE tblAttributeDefinitions SET valueset =".$db->qstr($valuesetstr)." WHERE id = " . $this->_id;
|
||||
$res = $db->getResult($queryStr);
|
||||
if (!$res)
|
||||
return false;
|
||||
|
||||
$this->_valueset = $valueset;
|
||||
$this->_separator = substr($valueset, 0, 1);
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Get the regular expression as saved in the database
|
||||
*
|
||||
* @return string regular expression
|
||||
*/
|
||||
function getRegex() { /* {{{ */
|
||||
return $this->_regex;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Set the regular expression
|
||||
*
|
||||
* A value of the attribute must match this regular expression.
|
||||
*
|
||||
* @param string $regex
|
||||
* @return boolean true if regex could be set, otherwise false
|
||||
*/
|
||||
function setRegex($regex) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "UPDATE tblAttributeDefinitions SET regex =".$db->qstr($regex)." WHERE id = " . $this->_id;
|
||||
$res = $db->getResult($queryStr);
|
||||
if (!$res)
|
||||
return false;
|
||||
|
||||
$this->_regex = $regex;
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Check if the attribute definition is used
|
||||
*
|
||||
* Checks all documents, folders and document content whether at least
|
||||
* one of them referenceѕ this attribute definition
|
||||
*
|
||||
* @return boolean true if attribute definition is used, otherwise false
|
||||
*/
|
||||
function isUsed() { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "SELECT * FROM tblDocumentAttributes WHERE attrdef=".$this->_id;
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if (is_array($resArr) && count($resArr) == 0) {
|
||||
$queryStr = "SELECT * FROM tblFolderAttributes WHERE attrdef=".$this->_id;
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if (is_array($resArr) && count($resArr) == 0) {
|
||||
$queryStr = "SELECT * FROM tblDocumentContentAttributes WHERE attrdef=".$this->_id;
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if (is_array($resArr) && count($resArr) == 0) {
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Return a list of documents, folders, document contents where this
|
||||
* attribute definition is used
|
||||
*
|
||||
* @param integer $limit return not more the n objects of each type
|
||||
* @return boolean true if attribute definition is used, otherwise false
|
||||
*/
|
||||
function getStatistics($limit=0) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$result = array('docs'=>array(), 'folders'=>array(), 'contents'=>array());
|
||||
if($this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_all ||
|
||||
$this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_document) {
|
||||
$queryStr = "SELECT * FROM tblDocumentAttributes WHERE attrdef=".$this->_id;
|
||||
if($limit)
|
||||
$queryStr .= " limit ".(int) $limit;
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if($resArr) {
|
||||
foreach($resArr as $rec) {
|
||||
if($doc = $this->_dms->getDocument($rec['document'])) {
|
||||
$result['docs'][] = $doc;
|
||||
}
|
||||
}
|
||||
}
|
||||
$queryStr = "SELECT count(*) c, value FROM tblDocumentAttributes WHERE attrdef=".$this->_id." GROUP BY value ORDER BY c DESC";
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if($resArr) {
|
||||
$result['frequencies']['document'] = $resArr;
|
||||
}
|
||||
}
|
||||
|
||||
if($this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_all ||
|
||||
$this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_folder) {
|
||||
$queryStr = "SELECT * FROM tblFolderAttributes WHERE attrdef=".$this->_id;
|
||||
if($limit)
|
||||
$queryStr .= " limit ".(int) $limit;
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if($resArr) {
|
||||
foreach($resArr as $rec) {
|
||||
if($folder = $this->_dms->getFolder($rec['folder'])) {
|
||||
$result['folders'][] = $folder;
|
||||
}
|
||||
}
|
||||
}
|
||||
$queryStr = "SELECT count(*) c, value FROM tblFolderAttributes WHERE attrdef=".$this->_id." GROUP BY value ORDER BY c DESC";
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if($resArr) {
|
||||
$result['frequencies']['folder'] = $resArr;
|
||||
}
|
||||
}
|
||||
|
||||
if($this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_all ||
|
||||
$this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_documentcontent) {
|
||||
$queryStr = "SELECT * FROM tblDocumentContentAttributes WHERE attrdef=".$this->_id;
|
||||
if($limit)
|
||||
$queryStr .= " limit ".(int) $limit;
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if($resArr) {
|
||||
foreach($resArr as $rec) {
|
||||
if($content = $this->_dms->getDocumentContent($rec['content'])) {
|
||||
$result['contents'][] = $content;
|
||||
}
|
||||
}
|
||||
}
|
||||
$queryStr = "SELECT count(*) c, value FROM tblDocumentContentAttributes WHERE attrdef=".$this->_id." GROUP BY value ORDER BY c DESC";
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if($resArr) {
|
||||
$result['frequencies']['content'] = $resArr;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Remove the attribute definition
|
||||
* Removal is only executed when the definition is not used anymore.
|
||||
*
|
||||
* @return boolean true on success or false in case of an error
|
||||
*/
|
||||
function remove() { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
if($this->isUsed())
|
||||
return false;
|
||||
|
||||
// Delete user itself
|
||||
$queryStr = "DELETE FROM tblAttributeDefinitions WHERE id = " . $this->_id;
|
||||
if (!$db->getResult($queryStr)) return false;
|
||||
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Get all documents and folder by a given attribute value
|
||||
*
|
||||
* @param string $attrvalue value of attribute
|
||||
* @param integer $limit limit number of documents/folders
|
||||
* @return array array containing list of documents and folders
|
||||
*/
|
||||
public function getObjects($attrvalue, $limit) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$result = array('docs'=>array(), 'folders'=>array(), 'contents'=>array());
|
||||
if($this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_all ||
|
||||
$this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_document) {
|
||||
$queryStr = "SELECT * FROM tblDocumentAttributes WHERE attrdef=".$this->_id." AND value=".$db->qstr($attrvalue);
|
||||
if($limit)
|
||||
$queryStr .= " limit ".(int) $limit;
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if($resArr) {
|
||||
foreach($resArr as $rec) {
|
||||
if($doc = $this->_dms->getDocument($rec['document'])) {
|
||||
$result['docs'][] = $doc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_all ||
|
||||
$this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_folder) {
|
||||
$queryStr = "SELECT * FROM tblFolderAttributes WHERE attrdef=".$this->_id." AND value=".$db->qstr($attrvalue);
|
||||
if($limit)
|
||||
$queryStr .= " limit ".(int) $limit;
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if($resArr) {
|
||||
foreach($resArr as $rec) {
|
||||
if($folder = $this->_dms->getFolder($rec['folder'])) {
|
||||
$result['folders'][] = $folder;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Validate value against attribute definition
|
||||
*
|
||||
* This function checks if the given value fits the attribute
|
||||
* definition.
|
||||
* If the validation fails the validation error will be set which
|
||||
* can be requested by SeedDMS_Core_Attribute::getValidationError()
|
||||
*
|
||||
* @param string|array $attrvalue attribute value
|
||||
* @return boolean true if validation succeds, otherwise false
|
||||
*/
|
||||
function validate($attrvalue) { /* {{{ */
|
||||
if($this->getMultipleValues()) {
|
||||
if(is_string($attrvalue))
|
||||
$values = explode($attrvalue[0], substr($attrvalue, 1));
|
||||
else
|
||||
$values = $attrvalue;
|
||||
} else {
|
||||
$values = array($attrvalue);
|
||||
}
|
||||
|
||||
$this->_validation_error = 0;
|
||||
if($this->getMinValues() > count($values)) {
|
||||
$this->_validation_error = 1;
|
||||
return false;
|
||||
}
|
||||
if($this->getMaxValues() && $this->getMaxValues() < count($values)) {
|
||||
$this->_validation_error = 2;
|
||||
return false;
|
||||
}
|
||||
|
||||
switch((string) $this->getType()) {
|
||||
case self::type_int:
|
||||
$success = true;
|
||||
foreach($values as $value) {
|
||||
$success &= preg_match('/^[0-9]*$/', $value) ? true : false;
|
||||
}
|
||||
break;
|
||||
case self::type_float:
|
||||
$success = true;
|
||||
foreach($values as $value) {
|
||||
$success &= is_numeric($value);
|
||||
}
|
||||
break;
|
||||
case self::type_string:
|
||||
$success = true;
|
||||
if(trim($this->getRegex()) != '') {
|
||||
foreach($values as $value) {
|
||||
$success &= preg_match($this->getRegex(), $value) ? true : false;
|
||||
}
|
||||
}
|
||||
if(!$success)
|
||||
$this->_validation_error = 3;
|
||||
break;
|
||||
case self::type_boolean:
|
||||
$success = true;
|
||||
foreach($values as $value) {
|
||||
$success &= preg_match('/^[01]$/', $value);
|
||||
}
|
||||
break;
|
||||
case self::type_email:
|
||||
$success = true;
|
||||
foreach($values as $value) {
|
||||
}
|
||||
if(!$success)
|
||||
$this->_validation_error = 5;
|
||||
break;
|
||||
case self::type_url:
|
||||
$success = true;
|
||||
foreach($values as $value) {
|
||||
$success &= preg_match('/^http(s)?:\/\/[a-z0-9-]+(.[a-z0-9-]+)*(:[0-9]+)?(\/.*)?$/i', $value);
|
||||
}
|
||||
if(!$success)
|
||||
$this->_validation_error = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check if value is in value set */
|
||||
if($valueset = $this->getValueSetAsArray()) {
|
||||
foreach($values as $value) {
|
||||
if(!in_array($value, $valueset)) {
|
||||
$success = false;
|
||||
$this->_validation_error = 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $success;
|
||||
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Get validation error from last validation
|
||||
*
|
||||
* @return integer error code
|
||||
*/
|
||||
function getValidationError() { return $this->_validation_error; }
|
||||
|
||||
} /* }}} */
|
||||
?>
|
2231
SeedDMS_Core/Core/inc.ClassDMS.php
Normal file
2231
SeedDMS_Core/Core/inc.ClassDMS.php
Normal file
File diff suppressed because it is too large
Load Diff
4506
SeedDMS_Core/Core/inc.ClassDocument.php
Normal file
4506
SeedDMS_Core/Core/inc.ClassDocument.php
Normal file
File diff suppressed because it is too large
Load Diff
118
SeedDMS_Core/Core/inc.ClassDocumentCategory.php
Normal file
118
SeedDMS_Core/Core/inc.ClassDocumentCategory.php
Normal file
|
@ -0,0 +1,118 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of document categories in the document management system
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Core
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class to represent a document category in the document management system
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Core
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C)2011 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Core_DocumentCategory {
|
||||
/**
|
||||
* @var integer $_id id of document category
|
||||
* @access protected
|
||||
*/
|
||||
protected $_id;
|
||||
|
||||
/**
|
||||
* @var string $_name name of category
|
||||
* @access protected
|
||||
*/
|
||||
protected $_name;
|
||||
|
||||
/**
|
||||
* @var object $_dms reference to dms this category belongs to
|
||||
* @access protected
|
||||
*/
|
||||
protected $_dms;
|
||||
|
||||
function __construct($id, $name) { /* {{{ */
|
||||
$this->_id = $id;
|
||||
$this->_name = $name;
|
||||
$this->_dms = null;
|
||||
} /* }}} */
|
||||
|
||||
function setDMS($dms) { /* {{{ */
|
||||
$this->_dms = $dms;
|
||||
} /* }}} */
|
||||
|
||||
function getID() { return $this->_id; }
|
||||
|
||||
function getName() { return $this->_name; }
|
||||
|
||||
function setName($newName) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "UPDATE tblCategory SET name = ".$db->qstr($newName)." WHERE id = ". $this->_id;
|
||||
if (!$db->getResult($queryStr))
|
||||
return false;
|
||||
|
||||
$this->_name = $newName;
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
function isUsed() { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "SELECT * FROM tblDocumentCategory WHERE categoryID=".$this->_id;
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if (is_array($resArr) && count($resArr) == 0)
|
||||
return false;
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
function getCategories() { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "SELECT * FROM tblCategory";
|
||||
return $db->getResultArray($queryStr);
|
||||
} /* }}} */
|
||||
|
||||
function addCategory($keywords) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "INSERT INTO tblCategory (category) VALUES (".$db->qstr($keywords).")";
|
||||
return $db->getResult($queryStr);
|
||||
} /* }}} */
|
||||
|
||||
function remove() { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "DELETE FROM tblCategory WHERE id = " . $this->_id;
|
||||
if (!$db->getResult($queryStr))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
function getDocumentsByCategory() { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "SELECT * FROM tblDocumentCategory where categoryID=".$this->_id;
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if (is_bool($resArr) && !$resArr)
|
||||
return false;
|
||||
|
||||
$documents = array();
|
||||
foreach ($resArr as $row) {
|
||||
array_push($documents, $this->_dms->getDocument($row["documentID"]));
|
||||
}
|
||||
return $documents;
|
||||
} /* }}} */
|
||||
|
||||
}
|
||||
|
||||
?>
|
1630
SeedDMS_Core/Core/inc.ClassFolder.php
Normal file
1630
SeedDMS_Core/Core/inc.ClassFolder.php
Normal file
File diff suppressed because it is too large
Load Diff
441
SeedDMS_Core/Core/inc.ClassGroup.php
Normal file
441
SeedDMS_Core/Core/inc.ClassGroup.php
Normal file
|
@ -0,0 +1,441 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of the group object in the document management system
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Core
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe,
|
||||
* 2010 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class to represent a user group in the document management system
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Core
|
||||
* @author Markus Westphal, Malcolm Cowe, Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe, 2010 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Core_Group {
|
||||
/**
|
||||
* The id of the user group
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
protected $_id;
|
||||
|
||||
/**
|
||||
* The name of the user group
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_name;
|
||||
|
||||
/**
|
||||
* Back reference to DMS this user group belongs to
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
protected $_dms;
|
||||
|
||||
function __construct($id, $name, $comment) { /* {{{ */
|
||||
$this->_id = $id;
|
||||
$this->_name = $name;
|
||||
$this->_comment = $comment;
|
||||
$this->_dms = null;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Create an instance of a group object
|
||||
*
|
||||
* @param string|integer $id Id, name of group, depending
|
||||
* on the 3rd parameter.
|
||||
* @param object $dms instance of dms
|
||||
* @param string $by search by group name if set to 'name'.
|
||||
* Search by Id of group if left empty.
|
||||
* @return object instance of class SeedDMS_Core_Group
|
||||
*/
|
||||
public static function getInstance($id, $dms, $by='') { /* {{{ */
|
||||
$db = $dms->getDB();
|
||||
|
||||
switch($by) {
|
||||
case 'name':
|
||||
$queryStr = "SELECT * FROM `tblGroups` WHERE `name` = ".$db->qstr($id);
|
||||
break;
|
||||
default:
|
||||
$queryStr = "SELECT * FROM `tblGroups` WHERE id = " . (int) $id;
|
||||
}
|
||||
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if (is_bool($resArr) && $resArr == false)
|
||||
return false;
|
||||
else if (count($resArr) != 1) //wenn, dann wohl eher 0 als > 1 ;-)
|
||||
return false;
|
||||
|
||||
$resArr = $resArr[0];
|
||||
|
||||
$group = new self($resArr["id"], $resArr["name"], $resArr["comment"]);
|
||||
$group->setDMS($dms);
|
||||
return $group;
|
||||
} /* }}} */
|
||||
|
||||
public static function getAllInstances($orderby, $dms) { /* {{{ */
|
||||
$db = $dms->getDB();
|
||||
|
||||
switch($orderby) {
|
||||
default:
|
||||
$queryStr = "SELECT * FROM tblGroups ORDER BY name";
|
||||
}
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
|
||||
if (is_bool($resArr) && $resArr == false)
|
||||
return false;
|
||||
|
||||
$groups = array();
|
||||
for ($i = 0; $i < count($resArr); $i++) {
|
||||
$group = new self($resArr[$i]["id"], $resArr[$i]["name"], $resArr[$i]["comment"]);
|
||||
$group->setDMS($dms);
|
||||
$groups[$i] = $group;
|
||||
}
|
||||
|
||||
return $groups;
|
||||
} /* }}} */
|
||||
|
||||
function setDMS($dms) { /* {{{ */
|
||||
$this->_dms = $dms;
|
||||
} /* }}} */
|
||||
|
||||
function getID() { return $this->_id; }
|
||||
|
||||
function getName() { return $this->_name; }
|
||||
|
||||
function setName($newName) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "UPDATE tblGroups SET name = ".$db->qstr($newName)." WHERE id = " . $this->_id;
|
||||
if (!$db->getResult($queryStr))
|
||||
return false;
|
||||
|
||||
$this->_name = $newName;
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
function getComment() { return $this->_comment; }
|
||||
|
||||
function setComment($newComment) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "UPDATE tblGroups SET comment = ".$db->qstr($newComment)." WHERE id = " . $this->_id;
|
||||
if (!$db->getResult($queryStr))
|
||||
return false;
|
||||
|
||||
$this->_comment = $newComment;
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
function getUsers() { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
if (!isset($this->_users)) {
|
||||
$queryStr = "SELECT `tblUsers`.* FROM `tblUsers` ".
|
||||
"LEFT JOIN `tblGroupMembers` ON `tblGroupMembers`.`userID`=`tblUsers`.`id` ".
|
||||
"WHERE `tblGroupMembers`.`groupID` = '". $this->_id ."'";
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if (is_bool($resArr) && $resArr == false)
|
||||
return false;
|
||||
|
||||
$this->_users = array();
|
||||
|
||||
$classname = $this->_dms->getClassname('user');
|
||||
foreach ($resArr as $row) {
|
||||
$user = new $classname($row["id"], $row["login"], $row["pwd"], $row["fullName"], $row["email"], $row["language"], $row["theme"], $row["comment"], $row["role"], $row['hidden']);
|
||||
array_push($this->_users, $user);
|
||||
}
|
||||
}
|
||||
return $this->_users;
|
||||
} /* }}} */
|
||||
|
||||
function getManagers() { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "SELECT `tblUsers`.* FROM `tblUsers` ".
|
||||
"LEFT JOIN `tblGroupMembers` ON `tblGroupMembers`.`userID`=`tblUsers`.`id` ".
|
||||
"WHERE `tblGroupMembers`.`groupID` = '". $this->_id ."' AND tblGroupMembers.manager = 1";
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if (is_bool($resArr) && $resArr == false)
|
||||
return false;
|
||||
|
||||
$managers = array();
|
||||
|
||||
$classname = $this->_dms->getClassname('user');
|
||||
foreach ($resArr as $row) {
|
||||
$user = new $classname($row["id"], $row["login"], $row["pwd"], $row["fullName"], $row["email"], $row["language"], $row["theme"], $row["comment"], $row["role"], $row['hidden']);
|
||||
array_push($managers, $user);
|
||||
}
|
||||
return $managers;
|
||||
} /* }}} */
|
||||
|
||||
function addUser($user,$asManager=false) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "INSERT INTO tblGroupMembers (groupID, userID, manager) VALUES (".$this->_id.", ".$user->getID(). ", " . ($asManager?"1":"0") ." )";
|
||||
$res = $db->getResult($queryStr);
|
||||
|
||||
if (!$res) return false;
|
||||
|
||||
unset($this->_users);
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
function removeUser($user) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "DELETE FROM tblGroupMembers WHERE groupID = ".$this->_id." AND userID = ".$user->getID();
|
||||
$res = $db->getResult($queryStr);
|
||||
|
||||
if (!$res) return false;
|
||||
unset($this->_users);
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
// $asManager=false: verify if user is in group
|
||||
// $asManager=true : verify if user is in group as manager
|
||||
function isMember($user,$asManager=false) { /* {{{ */
|
||||
if (isset($this->_users)&&!$asManager) {
|
||||
foreach ($this->_users as $usr)
|
||||
if ($usr->getID() == $user->getID())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
$db = $this->_dms->getDB();
|
||||
if ($asManager) $queryStr = "SELECT * FROM tblGroupMembers WHERE groupID = " . $this->_id . " AND userID = " . $user->getID() . " AND manager = 1";
|
||||
else $queryStr = "SELECT * FROM tblGroupMembers WHERE groupID = " . $this->_id . " AND userID = " . $user->getID();
|
||||
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
|
||||
if (is_bool($resArr) && $resArr == false) return false;
|
||||
if (count($resArr) != 1) return false;
|
||||
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
function toggleManager($user) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
if (!$this->isMember($user)) return false;
|
||||
|
||||
if ($this->isMember($user,true)) $queryStr = "UPDATE tblGroupMembers SET manager = 0 WHERE groupID = ".$this->_id." AND userID = ".$user->getID();
|
||||
else $queryStr = "UPDATE tblGroupMembers SET manager = 1 WHERE groupID = ".$this->_id." AND userID = ".$user->getID();
|
||||
|
||||
if (!$db->getResult($queryStr)) return false;
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Delete user group
|
||||
* This function deletes the user group and all it references, like access
|
||||
* control lists, notifications, as a child of other groups, etc.
|
||||
*
|
||||
* @param object $user the user doing the removal (needed for entry in
|
||||
* review log.
|
||||
* @return boolean true on success or false in case of an error
|
||||
*/
|
||||
function remove($user) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$db->startTransaction();
|
||||
|
||||
$queryStr = "DELETE FROM tblGroupMembers WHERE groupID = " . $this->_id;
|
||||
if (!$db->getResult($queryStr)) {
|
||||
$db->rollbackTransaction();
|
||||
return false;
|
||||
}
|
||||
$queryStr = "DELETE FROM tblACLs WHERE groupID = " . $this->_id;
|
||||
if (!$db->getResult($queryStr)) {
|
||||
$db->rollbackTransaction();
|
||||
return false;
|
||||
}
|
||||
$queryStr = "DELETE FROM tblNotify WHERE groupID = " . $this->_id;
|
||||
if (!$db->getResult($queryStr)) {
|
||||
$db->rollbackTransaction();
|
||||
return false;
|
||||
}
|
||||
$queryStr = "DELETE FROM tblMandatoryReviewers WHERE reviewerGroupID = " . $this->_id;
|
||||
if (!$db->getResult($queryStr)) {
|
||||
$db->rollbackTransaction();
|
||||
return false;
|
||||
}
|
||||
$queryStr = "DELETE FROM tblMandatoryApprovers WHERE approverGroupID = " . $this->_id;
|
||||
if (!$db->getResult($queryStr)) {
|
||||
$db->rollbackTransaction();
|
||||
return false;
|
||||
}
|
||||
$queryStr = "DELETE FROM tblWorkflowTransitionGroups WHERE groupid = " . $this->_id;
|
||||
if (!$db->getResult($queryStr)) {
|
||||
$db->rollbackTransaction();
|
||||
return false;
|
||||
}
|
||||
$queryStr = "DELETE FROM tblGroups WHERE id = " . $this->_id;
|
||||
if (!$db->getResult($queryStr)) {
|
||||
$db->rollbackTransaction();
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO : update document status if reviewer/approver has been deleted
|
||||
|
||||
|
||||
$reviewStatus = $this->getReviewStatus();
|
||||
foreach ($reviewStatus as $r) {
|
||||
$queryStr = "INSERT INTO `tblDocumentReviewLog` (`reviewID`, `status`, `comment`, `date`, `userID`) ".
|
||||
"VALUES ('". $r["reviewID"] ."', '-2', 'Review group removed from process', ".$db->getCurrentDatetime().", '". $user->getID() ."')";
|
||||
$res=$db->getResult($queryStr);
|
||||
if(!$res) {
|
||||
$db->rollbackTransaction();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$approvalStatus = $this->getApprovalStatus();
|
||||
foreach ($approvalStatus as $a) {
|
||||
$queryStr = "INSERT INTO `tblDocumentApproveLog` (`approveID`, `status`, `comment`, `date`, `userID`) ".
|
||||
"VALUES ('". $a["approveID"] ."', '-2', 'Approval group removed from process', ".$db->getCurrentDatetime().", '". $user->getID() ."')";
|
||||
$res=$db->getResult($queryStr);
|
||||
if(!$res) {
|
||||
$db->rollbackTransaction();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$db->commitTransaction();
|
||||
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
function getReviewStatus($documentID=null, $version=null) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
if (!$db->createTemporaryTable("ttreviewid")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$status = array();
|
||||
|
||||
// See if the group is assigned as a reviewer.
|
||||
$queryStr = "SELECT `tblDocumentReviewers`.*, `tblDocumentReviewLog`.`status`, ".
|
||||
"`tblDocumentReviewLog`.`comment`, `tblDocumentReviewLog`.`date`, ".
|
||||
"`tblDocumentReviewLog`.`userID` ".
|
||||
"FROM `tblDocumentReviewers` ".
|
||||
"LEFT JOIN `tblDocumentReviewLog` USING (`reviewID`) ".
|
||||
"LEFT JOIN `ttreviewid` on `ttreviewid`.`maxLogID` = `tblDocumentReviewLog`.`reviewLogID` ".
|
||||
"WHERE `ttreviewid`.`maxLogID`=`tblDocumentReviewLog`.`reviewLogID` ".
|
||||
($documentID==null ? "" : "AND `tblDocumentReviewers`.`documentID` = '". (int) $documentID ."' ").
|
||||
($version==null ? "" : "AND `tblDocumentReviewers`.`version` = '". (int) $version ."' ").
|
||||
"AND `tblDocumentReviewers`.`type`='1' ".
|
||||
"AND `tblDocumentReviewers`.`required`='". $this->_id ."' ";
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if (is_bool($resArr) && $resArr == false)
|
||||
return false;
|
||||
if (count($resArr)>0) {
|
||||
foreach ($resArr as $res)
|
||||
$status[] = $res;
|
||||
}
|
||||
return $status;
|
||||
} /* }}} */
|
||||
|
||||
function getApprovalStatus($documentID=null, $version=null) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
if (!$db->createTemporaryTable("ttapproveid")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$status = array();
|
||||
|
||||
// See if the group is assigned as an approver.
|
||||
$queryStr = "SELECT `tblDocumentApprovers`.*, `tblDocumentApproveLog`.`status`, ".
|
||||
"`tblDocumentApproveLog`.`comment`, `tblDocumentApproveLog`.`date`, ".
|
||||
"`tblDocumentApproveLog`.`userID` ".
|
||||
"FROM `tblDocumentApprovers` ".
|
||||
"LEFT JOIN `tblDocumentApproveLog` USING (`approveID`) ".
|
||||
"LEFT JOIN `ttapproveid` on `ttapproveid`.`maxLogID` = `tblDocumentApproveLog`.`approveLogID` ".
|
||||
"WHERE `ttapproveid`.`maxLogID`=`tblDocumentApproveLog`.`approveLogID` ".
|
||||
($documentID==null ? "" : "AND `tblDocumentApprovers`.`documentID` = '". (int) $documentID ."' ").
|
||||
($version==null ? "" : "AND `tblDocumentApprovers`.`version` = '". (int) $version ."' ").
|
||||
"AND `tblDocumentApprovers`.`type`='1' ".
|
||||
"AND `tblDocumentApprovers`.`required`='". $this->_id ."' ";
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if (is_bool($resArr) && $resArr == false)
|
||||
return false;
|
||||
if (count($resArr)>0) {
|
||||
foreach ($resArr as $res)
|
||||
$status[] = $res;
|
||||
}
|
||||
|
||||
return $status;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Get a list of documents with a workflow
|
||||
*
|
||||
* @param int $documentID optional document id for which to retrieve the
|
||||
* reviews
|
||||
* @param int $version optional version of the document
|
||||
* @return array list of all workflows
|
||||
*/
|
||||
function getWorkflowStatus($documentID=null, $version=null) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = 'select distinct d.*, c.groupid from tblWorkflowTransitions a left join tblWorkflows b on a.workflow=b.id left join tblWorkflowTransitionGroups c on a.id=c.transition left join tblWorkflowDocumentContent d on b.id=d.workflow where d.document is not null and a.state=d.state and c.groupid='.$this->_id;
|
||||
if($documentID) {
|
||||
$queryStr .= ' AND d.document='.(int) $documentID;
|
||||
if($version)
|
||||
$queryStr .= ' AND d.version='.(int) $version;
|
||||
}
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if (is_bool($resArr) && $resArr == false)
|
||||
return false;
|
||||
$result = array();
|
||||
if (count($resArr)>0) {
|
||||
foreach ($resArr as $res) {
|
||||
$result[] = $res;
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Get all notifications of group
|
||||
*
|
||||
* @param integer $type type of item (T_DOCUMENT or T_FOLDER)
|
||||
* @return array array of notifications
|
||||
*/
|
||||
function getNotifications($type=0) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
$queryStr = "SELECT `tblNotify`.* FROM `tblNotify` ".
|
||||
"WHERE `tblNotify`.`groupID` = ". $this->_id;
|
||||
if($type) {
|
||||
$queryStr .= " AND `tblNotify`.`targetType` = ". (int) $type;
|
||||
}
|
||||
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if (is_bool($resArr) && !$resArr)
|
||||
return false;
|
||||
|
||||
$notifications = array();
|
||||
foreach ($resArr as $row) {
|
||||
$not = new SeedDMS_Core_Notification($row["target"], $row["targetType"], $row["userID"], $row["groupID"]);
|
||||
$not->setDMS($this);
|
||||
array_push($notifications, $not);
|
||||
}
|
||||
|
||||
return $notifications;
|
||||
} /* }}} */
|
||||
|
||||
}
|
||||
?>
|
143
SeedDMS_Core/Core/inc.ClassKeywords.php
Normal file
143
SeedDMS_Core/Core/inc.ClassKeywords.php
Normal file
|
@ -0,0 +1,143 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of keyword categories in the document management system
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Core
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe,
|
||||
* 2010 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class to represent a keyword category in the document management system
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Core
|
||||
* @author Markus Westphal, Malcolm Cowe, Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe,
|
||||
* 2010 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Core_KeywordCategory {
|
||||
/**
|
||||
* @var integer $_id id of keyword category
|
||||
* @access protected
|
||||
*/
|
||||
protected $_id;
|
||||
|
||||
/**
|
||||
* @var integer $_ownerID id of user who is the owner
|
||||
* @access protected
|
||||
*/
|
||||
protected $_ownerID;
|
||||
|
||||
/**
|
||||
* @var string $_name name of category
|
||||
* @access protected
|
||||
*/
|
||||
protected $_name;
|
||||
|
||||
/**
|
||||
* @var object $_dms reference to dms this category belongs to
|
||||
* @access protected
|
||||
*/
|
||||
protected $_dms;
|
||||
|
||||
function __construct($id, $ownerID, $name) {
|
||||
$this->_id = $id;
|
||||
$this->_name = $name;
|
||||
$this->_ownerID = $ownerID;
|
||||
$this->_dms = null;
|
||||
}
|
||||
|
||||
function setDMS($dms) {
|
||||
$this->_dms = $dms;
|
||||
}
|
||||
|
||||
function getID() { return $this->_id; }
|
||||
|
||||
function getName() { return $this->_name; }
|
||||
|
||||
function getOwner() {
|
||||
if (!isset($this->_owner))
|
||||
$this->_owner = $this->_dms->getUser($this->_ownerID);
|
||||
return $this->_owner;
|
||||
}
|
||||
|
||||
function setName($newName) {
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "UPDATE tblKeywordCategories SET name = ".$db->qstr($newName)." WHERE id = ". $this->_id;
|
||||
if (!$db->getResult($queryStr))
|
||||
return false;
|
||||
|
||||
$this->_name = $newName;
|
||||
return true;
|
||||
}
|
||||
|
||||
function setOwner($user) {
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "UPDATE tblKeywordCategories SET owner = " . $user->getID() . " WHERE id " . $this->_id;
|
||||
if (!$db->getResult($queryStr))
|
||||
return false;
|
||||
|
||||
$this->_ownerID = $user->getID();
|
||||
$this->_owner = $user;
|
||||
return true;
|
||||
}
|
||||
|
||||
function getKeywordLists() {
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "SELECT * FROM tblKeywords WHERE category = " . $this->_id . " order by `keywords`";
|
||||
return $db->getResultArray($queryStr);
|
||||
}
|
||||
|
||||
function editKeywordList($listID, $keywords) {
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "UPDATE tblKeywords SET keywords = ".$db->qstr($keywords)." WHERE id = $listID";
|
||||
return $db->getResult($queryStr);
|
||||
}
|
||||
|
||||
function addKeywordList($keywords) {
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "INSERT INTO tblKeywords (category, keywords) VALUES (" . $this->_id . ", ".$db->qstr($keywords).")";
|
||||
return $db->getResult($queryStr);
|
||||
}
|
||||
|
||||
function removeKeywordList($listID) {
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "DELETE FROM tblKeywords WHERE id = $listID";
|
||||
return $db->getResult($queryStr);
|
||||
}
|
||||
|
||||
function remove() {
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$db->startTransaction();
|
||||
$queryStr = "DELETE FROM tblKeywords WHERE category = " . $this->_id;
|
||||
if (!$db->getResult($queryStr)) {
|
||||
$db->rollbackTransaction();
|
||||
return false;
|
||||
}
|
||||
|
||||
$queryStr = "DELETE FROM tblKeywordCategories WHERE id = " . $this->_id;
|
||||
if (!$db->getResult($queryStr)) {
|
||||
$db->rollbackTransaction();
|
||||
return false;
|
||||
}
|
||||
|
||||
$db->commitTransaction();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
116
SeedDMS_Core/Core/inc.ClassNotification.php
Normal file
116
SeedDMS_Core/Core/inc.ClassNotification.php
Normal file
|
@ -0,0 +1,116 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of a notification object
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Core
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class to represent a notification
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Core
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Core_Notification { /* {{{ */
|
||||
/**
|
||||
* @var integer id of target (document or folder)
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected $_target;
|
||||
|
||||
/**
|
||||
* @var integer document or folder
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected $_targettype;
|
||||
|
||||
/**
|
||||
* @var integer id of user to notify
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected $_userid;
|
||||
|
||||
/**
|
||||
* @var integer id of group to notify
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected $_groupid;
|
||||
|
||||
/**
|
||||
* @var object reference to the dms instance this user belongs to
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected $_dms;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param integer $target id of document/folder this notification is
|
||||
* attached to.
|
||||
* @param integer $targettype 1 = target is document, 2 = target is a folder
|
||||
* @param integer $userid id of user. The id is -1 if the notification is
|
||||
* for a group.
|
||||
* @param integer $groupid id of group. The id is -1 if the notification is
|
||||
* for a user.
|
||||
*/
|
||||
function __construct($target, $targettype, $userid, $groupid) { /* {{{ */
|
||||
$this->_target = $target;
|
||||
$this->_targettype = $targettype;
|
||||
$this->_userid = $userid;
|
||||
$this->_groupid = $groupid;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Set instance of dms this object belongs to
|
||||
*
|
||||
* @param object $dms instance of dms
|
||||
*/
|
||||
function setDMS($dms) { /* {{{ */
|
||||
$this->_dms = $dms;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Get id of target (document/object) this notification is attachted to
|
||||
*
|
||||
* @return integer id of target
|
||||
*/
|
||||
function getTarget() { return $this->_target; }
|
||||
|
||||
/**
|
||||
* Get type of target
|
||||
*
|
||||
* @return integer type of target (1=document/2=object)
|
||||
*/
|
||||
function getTargetType() { return $this->_targettype; }
|
||||
|
||||
/**
|
||||
* Get user for this notification
|
||||
*
|
||||
* @return integer id of user or -1 if this notification does not belong
|
||||
* to a user
|
||||
*/
|
||||
function getUser() { return $this->_dms->getUser($this->_userid); }
|
||||
|
||||
/**
|
||||
* Get group for this notification
|
||||
*
|
||||
* @return integer id of group or -1 if this notification does not belong
|
||||
* to a group
|
||||
*/
|
||||
function getGroup() { return $this->_dms->getGroup($this->_groupid); }
|
||||
} /* }}} */
|
||||
?>
|
276
SeedDMS_Core/Core/inc.ClassObject.php
Normal file
276
SeedDMS_Core/Core/inc.ClassObject.php
Normal file
|
@ -0,0 +1,276 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of an generic object in the document management system
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Core
|
||||
* @license GPL2
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2012 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Class to represent a generic object in the document management system
|
||||
*
|
||||
* This is the base class for generic objects in SeedDMS.
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Core
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2012 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Core_Object { /* {{{ */
|
||||
/**
|
||||
* @var integer unique id of object
|
||||
*/
|
||||
protected $_id;
|
||||
|
||||
/**
|
||||
* @var array list of attributes
|
||||
*/
|
||||
protected $_attributes;
|
||||
|
||||
/**
|
||||
* @var object back reference to document management system
|
||||
*/
|
||||
public $_dms;
|
||||
|
||||
function __construct($id) { /* {{{ */
|
||||
$this->_id = $id;
|
||||
$this->_dms = null;
|
||||
} /* }}} */
|
||||
|
||||
/*
|
||||
* Set dms this object belongs to.
|
||||
*
|
||||
* Each object needs a reference to the dms it belongs to. It will be
|
||||
* set when the object is created.
|
||||
* The dms has a references to the currently logged in user
|
||||
* and the database connection.
|
||||
*
|
||||
* @param object $dms reference to dms
|
||||
*/
|
||||
function setDMS($dms) { /* {{{ */
|
||||
$this->_dms = $dms;
|
||||
} /* }}} */
|
||||
|
||||
/*
|
||||
* Return the internal id of the document
|
||||
*
|
||||
* @return integer id of document
|
||||
*/
|
||||
function getID() { return $this->_id; }
|
||||
|
||||
/**
|
||||
* Returns all attributes set for the object
|
||||
*
|
||||
* @return array list of objects of class SeedDMS_Core_Attribute
|
||||
*/
|
||||
function getAttributes() { /* {{{ */
|
||||
if (!$this->_attributes) {
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
switch(get_class($this)) {
|
||||
case $this->_dms->getClassname('document'):
|
||||
$queryStr = "SELECT * FROM tblDocumentAttributes WHERE document = " . $this->_id." ORDER BY `id`";
|
||||
break;
|
||||
case $this->_dms->getClassname('documentcontent'):
|
||||
$queryStr = "SELECT * FROM tblDocumentContentAttributes WHERE content = " . $this->_id." ORDER BY `id`";
|
||||
break;
|
||||
case $this->_dms->getClassname('folder'):
|
||||
$queryStr = "SELECT * FROM tblFolderAttributes WHERE folder = " . $this->_id." ORDER BY `id`";
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if (is_bool($resArr) && !$resArr) return false;
|
||||
|
||||
$this->_attributes = array();
|
||||
|
||||
foreach ($resArr as $row) {
|
||||
$attrdef = $this->_dms->getAttributeDefinition($row['attrdef']);
|
||||
$attr = new SeedDMS_Core_Attribute($row["id"], $this, $attrdef, $row["value"]);
|
||||
$attr->setDMS($this->_dms);
|
||||
$this->_attributes[$attrdef->getId()] = $attr;
|
||||
}
|
||||
}
|
||||
return $this->_attributes;
|
||||
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Returns an attribute of the object for the given attribute definition
|
||||
*
|
||||
* @return array|string value of attritbute or false. The value is an array
|
||||
* if the attribute is defined as multi value
|
||||
*/
|
||||
function getAttribute($attrdef) { /* {{{ */
|
||||
if (!$this->_attributes) {
|
||||
$this->getAttributes();
|
||||
}
|
||||
|
||||
if (isset($this->_attributes[$attrdef->getId()])) {
|
||||
return $this->_attributes[$attrdef->getId()];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Returns an attribute value of the object for the given attribute definition
|
||||
*
|
||||
* @return array|string value of attritbute or false. The value is an array
|
||||
* if the attribute is defined as multi value
|
||||
*/
|
||||
function getAttributeValue($attrdef) { /* {{{ */
|
||||
if (!$this->_attributes) {
|
||||
$this->getAttributes();
|
||||
}
|
||||
|
||||
if (isset($this->_attributes[$attrdef->getId()])) {
|
||||
$value = $this->_attributes[$attrdef->getId()]->getValue();
|
||||
if($attrdef->getMultipleValues()) {
|
||||
$sep = substr($value, 0, 1);
|
||||
return(explode($sep, substr($value, 1)));
|
||||
} else {
|
||||
return $value;
|
||||
}
|
||||
} else
|
||||
return false;
|
||||
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Returns an attribute value of the object for the given attribute definition
|
||||
*
|
||||
* This is a short cut for getAttribute($attrdef)->getValueAsArray() but
|
||||
* first checks if the object has an attribute for the given attribute
|
||||
* definition.
|
||||
*
|
||||
* @return array value of attritbute or false. The value is always an array
|
||||
* even if the attribute is not defined as multi value
|
||||
*/
|
||||
function getAttributeValueAsArray($attrdef) { /* {{{ */
|
||||
if (!$this->_attributes) {
|
||||
$this->getAttributes();
|
||||
}
|
||||
|
||||
if (isset($this->_attributes[$attrdef->getId()])) {
|
||||
return $this->_attributes[$attrdef->getId()]->getValueAsArray();
|
||||
} else
|
||||
return false;
|
||||
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Returns an attribute value of the object for the given attribute definition
|
||||
*
|
||||
* This is a short cut for getAttribute($attrdef)->getValueAsString() but
|
||||
* first checks if the object has an attribute for the given attribute
|
||||
* definition.
|
||||
*
|
||||
* @return string value of attritbute or false. The value is always a string
|
||||
* even if the attribute is defined as multi value
|
||||
*/
|
||||
function getAttributeValueAsString($attrdef) { /* {{{ */
|
||||
if (!$this->_attributes) {
|
||||
$this->getAttributes();
|
||||
}
|
||||
|
||||
if (isset($this->_attributes[$attrdef->getId()])) {
|
||||
return $this->_attributes[$attrdef->getId()]->getValue();
|
||||
} else
|
||||
return false;
|
||||
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Set an attribute of the object for the given attribute definition
|
||||
*
|
||||
* @param object $attrdef definition of attribute
|
||||
* @param array|sting $value value of attribute, for multiple values this
|
||||
* must be an array
|
||||
* @return boolean true if operation was successful, otherwise false
|
||||
*/
|
||||
function setAttributeValue($attrdef, $value) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
if (!$this->_attributes) {
|
||||
$this->getAttributes();
|
||||
}
|
||||
switch($attrdef->getType()) {
|
||||
case SeedDMS_Core_AttributeDefinition::type_boolean:
|
||||
$value = ($value === true || $value != '' || $value == 1) ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
if($attrdef->getMultipleValues() && is_array($value)) {
|
||||
$sep = substr($attrdef->getValueSet(), 0, 1);
|
||||
$value = $sep.implode($sep, $value);
|
||||
}
|
||||
if(!isset($this->_attributes[$attrdef->getId()])) {
|
||||
switch(get_class($this)) {
|
||||
case $this->_dms->getClassname('document'):
|
||||
$queryStr = "INSERT INTO tblDocumentAttributes (document, attrdef, value) VALUES (".$this->_id.", ".$attrdef->getId().", ".$db->qstr($value).")";
|
||||
break;
|
||||
case $this->_dms->getClassname('documentcontent'):
|
||||
$queryStr = "INSERT INTO tblDocumentContentAttributes (content, attrdef, value) VALUES (".$this->_id.", ".$attrdef->getId().", ".$db->qstr($value).")";
|
||||
break;
|
||||
case $this->_dms->getClassname('folder'):
|
||||
$queryStr = "INSERT INTO tblFolderAttributes (folder, attrdef, value) VALUES (".$this->_id.", ".$attrdef->getId().", ".$db->qstr($value).")";
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
$res = $db->getResult($queryStr);
|
||||
if (!$res)
|
||||
return false;
|
||||
|
||||
$attr = new SeedDMS_Core_Attribute($db->getInsertID(), $this, $attrdef, $value);
|
||||
$attr->setDMS($this->_dms);
|
||||
$this->_attributes[$attrdef->getId()] = $attr;
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->_attributes[$attrdef->getId()]->setValue($value);
|
||||
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Remove an attribute of the object for the given attribute definition
|
||||
*
|
||||
* @return boolean true if operation was successful, otherwise false
|
||||
*/
|
||||
function removeAttribute($attrdef) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
if (!$this->_attributes) {
|
||||
$this->getAttributes();
|
||||
}
|
||||
if(isset($this->_attributes[$attrdef->getId()])) {
|
||||
switch(get_class($this)) {
|
||||
case $this->_dms->getClassname('document'):
|
||||
$queryStr = "DELETE FROM tblDocumentAttributes WHERE document=".$this->_id." AND attrdef=".$attrdef->getId();
|
||||
break;
|
||||
case $this->_dms->getClassname('documentcontent'):
|
||||
$queryStr = "DELETE FROM tblDocumentContentAttributes WHERE content=".$this->_id." AND attrdef=".$attrdef->getId();
|
||||
break;
|
||||
case $this->_dms->getClassname('folder'):
|
||||
$queryStr = "DELETE FROM tblFolderAttributes WHERE folder=".$this->_id." AND attrdef=".$attrdef->getId();
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
$res = $db->getResult($queryStr);
|
||||
if (!$res)
|
||||
return false;
|
||||
|
||||
unset($this->_attributes[$attrdef->getId()]);
|
||||
}
|
||||
return true;
|
||||
} /* }}} */
|
||||
} /* }}} */
|
||||
?>
|
1362
SeedDMS_Core/Core/inc.ClassUser.php
Normal file
1362
SeedDMS_Core/Core/inc.ClassUser.php
Normal file
File diff suppressed because it is too large
Load Diff
1113
SeedDMS_Core/Core/inc.ClassWorkflow.php
Normal file
1113
SeedDMS_Core/Core/inc.ClassWorkflow.php
Normal file
File diff suppressed because it is too large
Load Diff
314
SeedDMS_Core/Core/inc.DBAccess.php
Normal file
314
SeedDMS_Core/Core/inc.DBAccess.php
Normal file
|
@ -0,0 +1,314 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of database access
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Core
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe,
|
||||
* 2010 Matteo Lucarelli, 2010 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Include the adodb database abstraction
|
||||
*/
|
||||
require_once "adodb/adodb.inc.php";
|
||||
|
||||
/**
|
||||
* Class to represent the database access for the document management
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Core
|
||||
* @author Markus Westphal, Malcolm Cowe, Matteo Lucarelli, Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe, 2010 Matteo Lucarelli, 2010 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Core_DatabaseAccess {
|
||||
var $_debug;
|
||||
var $_driver;
|
||||
var $_hostname;
|
||||
var $_database;
|
||||
var $_user;
|
||||
var $_passw;
|
||||
var $_conn;
|
||||
var $_connected;
|
||||
var $_ttreviewid;
|
||||
var $_ttapproveid;
|
||||
var $_ttstatid;
|
||||
var $_ttcontentid;
|
||||
var $_intransaction;
|
||||
|
||||
/*
|
||||
Backup functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Return list of all database tables
|
||||
*
|
||||
* This function is used to retrieve a list of database tables for backup
|
||||
*
|
||||
* @return array list of table names
|
||||
*/
|
||||
function TableList() {
|
||||
return $this->_conn->MetaTables("TABLES");
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor of SeedDMS_Core_DatabaseAccess
|
||||
*
|
||||
* Sets all database parameters but does not connect.
|
||||
*
|
||||
* @param string $driver the database type e.g. mysql, sqlite
|
||||
* @param string $hostname host of database server
|
||||
* @param string $user name of user having access to database
|
||||
* @param string $passw password of user
|
||||
* @param string $database name of database
|
||||
*/
|
||||
function __construct($driver, $hostname, $user, $passw, $database = false) {
|
||||
$this->_driver = $driver;
|
||||
$this->_hostname = $hostname;
|
||||
$this->_database = $database;
|
||||
$this->_user = $user;
|
||||
$this->_passw = $passw;
|
||||
$this->_connected = false;
|
||||
$this->_intransaction = 0;
|
||||
// $tt*****id is a hack to ensure that we do not try to create the
|
||||
// temporary table twice during a single connection. Can be fixed by
|
||||
// using Views (MySQL 5.0 onward) instead of temporary tables.
|
||||
// CREATE ... IF NOT EXISTS cannot be used because it has the
|
||||
// unpleasant side-effect of performing the insert again even if the
|
||||
// table already exists.
|
||||
//
|
||||
// See createTemporaryTable() method for implementation.
|
||||
$this->_ttreviewid = false;
|
||||
$this->_ttapproveid = false;
|
||||
$this->_ttstatid = false;
|
||||
$this->_ttcontentid = false;
|
||||
$this->_debug = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to database
|
||||
*
|
||||
* @return boolean true if connection could be established, otherwise false
|
||||
*/
|
||||
function connect() { /* {{{ */
|
||||
$this->_conn = ADONewConnection($this->_driver);
|
||||
if ($this->_database)
|
||||
$this->_conn->Connect($this->_hostname, $this->_user, $this->_passw, $this->_database);
|
||||
else
|
||||
$this->_conn->Connect($this->_hostname, $this->_user, $this->_passw);
|
||||
|
||||
if (!$this->_conn)
|
||||
return false;
|
||||
|
||||
$this->_conn->SetFetchMode(ADODB_FETCH_ASSOC);
|
||||
$this->_conn->Execute('SET NAMES utf8');
|
||||
$this->_connected = true;
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Make sure a database connection exisits
|
||||
*
|
||||
* This function checks for a database connection. If it does not exists
|
||||
* it will reconnect.
|
||||
*
|
||||
* @return boolean true if connection is established, otherwise false
|
||||
*/
|
||||
function ensureConnected() { /* {{{ */
|
||||
if (!$this->_connected) return $this->connect();
|
||||
else return true;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Sanitize String used in database operations
|
||||
*
|
||||
* @param string text
|
||||
* @return string sanitized string
|
||||
*/
|
||||
function qstr($text) { /* {{{ */
|
||||
return $this->_conn->qstr($text);
|
||||
} /* }}} */
|
||||
|
||||
|
||||
/**
|
||||
* Execute SQL query and return result
|
||||
*
|
||||
* Call this function only with sql query which return data records.
|
||||
*
|
||||
* @param string $queryStr sql query
|
||||
* @return array/boolean data if query could be executed otherwise false
|
||||
*/
|
||||
function getResultArray($queryStr) { /* {{{ */
|
||||
$resArr = array();
|
||||
|
||||
$res = $this->_conn->Execute($queryStr);
|
||||
if (!$res) {
|
||||
if($this->_debug)
|
||||
echo "error: ".$queryStr."<br />";
|
||||
return false;
|
||||
}
|
||||
$resArr = $res->GetArray();
|
||||
$res->Close();
|
||||
return $resArr;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Execute SQL query
|
||||
*
|
||||
* Call this function only with sql query which do not return data records.
|
||||
*
|
||||
* @param string $queryStr sql query
|
||||
* @param boolean $silent not used anymore. This was used when this method
|
||||
* still issued an error message
|
||||
* @return boolean true if query could be executed otherwise false
|
||||
*/
|
||||
function getResult($queryStr, $silent=false) { /* {{{ */
|
||||
$res = $this->_conn->Execute($queryStr);
|
||||
if(!$res) {
|
||||
if($this->_debug)
|
||||
echo "error: ".$queryStr."<br />";
|
||||
}
|
||||
|
||||
return $res;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Return the id of the last instert record
|
||||
*
|
||||
* @return integer id used in last autoincrement
|
||||
*/
|
||||
function getInsertID() { /* {{{ */
|
||||
return $this->_conn->Insert_ID();
|
||||
} /* }}} */
|
||||
|
||||
function startTransaction() { /* {{{ */
|
||||
if(!$this->_intransaction) {
|
||||
$this->_conn->BeginTrans();
|
||||
}
|
||||
$this->_intransaction++;
|
||||
} /* }}} */
|
||||
|
||||
function rollbackTransaction() { /* {{{ */
|
||||
if($this->_intransaction == 1) {
|
||||
$this->_conn->RollbackTrans();
|
||||
}
|
||||
$this->_intransaction--;
|
||||
} /* }}} */
|
||||
|
||||
function commitTransaction() { /* {{{ */
|
||||
if($this->_intransaction == 1) {
|
||||
$this->_conn->CommitTrans();
|
||||
}
|
||||
$this->_intransaction--;
|
||||
} /* }}} */
|
||||
|
||||
function getErrorMsg() { /* {{{ */
|
||||
return $this->_conn->ErrorMsg();
|
||||
} /* }}} */
|
||||
|
||||
function getErrorNo() { /* {{{ */
|
||||
return $this->_conn->ErrorNo();
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Create various temporary tables to speed up and simplify sql queries
|
||||
*/
|
||||
function createTemporaryTable($tableName, $override=false) { /* {{{ */
|
||||
if (!strcasecmp($tableName, "ttreviewid")) {
|
||||
$queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttreviewid` (PRIMARY KEY (`reviewID`), INDEX (`maxLogID`)) ".
|
||||
"SELECT `tblDocumentReviewLog`.`reviewID`, ".
|
||||
"MAX(`tblDocumentReviewLog`.`reviewLogID`) AS `maxLogID` ".
|
||||
"FROM `tblDocumentReviewLog` ".
|
||||
"GROUP BY `tblDocumentReviewLog`.`reviewID` ".
|
||||
"ORDER BY `tblDocumentReviewLog`.`reviewLogID`";
|
||||
if (!$this->_ttreviewid) {
|
||||
if (!$this->getResult($queryStr))
|
||||
return false;
|
||||
$this->_ttreviewid=true;
|
||||
}
|
||||
else {
|
||||
if (is_bool($override) && $override) {
|
||||
if (!$this->getResult("DELETE FROM `ttreviewid`"))
|
||||
return false;
|
||||
if (!$this->getResult($queryStr))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return $this->_ttreviewid;
|
||||
}
|
||||
else if (!strcasecmp($tableName, "ttapproveid")) {
|
||||
$queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttapproveid` (PRIMARY KEY (`approveID`), INDEX (`maxLogID`)) ".
|
||||
"SELECT `tblDocumentApproveLog`.`approveID`, ".
|
||||
"MAX(`tblDocumentApproveLog`.`approveLogID`) AS `maxLogID` ".
|
||||
"FROM `tblDocumentApproveLog` ".
|
||||
"GROUP BY `tblDocumentApproveLog`.`approveID` ".
|
||||
"ORDER BY `tblDocumentApproveLog`.`approveLogID`";
|
||||
if (!$this->_ttapproveid) {
|
||||
if (!$this->getResult($queryStr))
|
||||
return false;
|
||||
$this->_ttapproveid=true;
|
||||
}
|
||||
else {
|
||||
if (is_bool($override) && $override) {
|
||||
if (!$this->getResult("DELETE FROM `ttapproveid`"))
|
||||
return false;
|
||||
if (!$this->getResult($queryStr))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return $this->_ttapproveid;
|
||||
}
|
||||
else if (!strcasecmp($tableName, "ttstatid")) {
|
||||
$queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttstatid` (PRIMARY KEY (`statusID`), INDEX (`maxLogID`)) ".
|
||||
"SELECT `tblDocumentStatusLog`.`statusID`, ".
|
||||
"MAX(`tblDocumentStatusLog`.`statusLogID`) AS `maxLogID` ".
|
||||
"FROM `tblDocumentStatusLog` ".
|
||||
"GROUP BY `tblDocumentStatusLog`.`statusID` ".
|
||||
"ORDER BY `tblDocumentStatusLog`.`statusLogID`";
|
||||
if (!$this->_ttstatid) {
|
||||
if (!$this->getResult($queryStr))
|
||||
return false;
|
||||
$this->_ttstatid=true;
|
||||
}
|
||||
else {
|
||||
if (is_bool($override) && $override) {
|
||||
if (!$this->getResult("DELETE FROM `ttstatid`"))
|
||||
return false;
|
||||
if (!$this->getResult($queryStr))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return $this->_ttstatid;
|
||||
}
|
||||
else if (!strcasecmp($tableName, "ttcontentid")) {
|
||||
$queryStr = "CREATE TEMPORARY TABLE `ttcontentid` (PRIMARY KEY (`document`), INDEX (`maxVersion`)) ".
|
||||
"SELECT `tblDocumentContent`.`document`, ".
|
||||
"MAX(`tblDocumentContent`.`version`) AS `maxVersion` ".
|
||||
"FROM `tblDocumentContent` ".
|
||||
"GROUP BY `tblDocumentContent`.`document` ".
|
||||
"ORDER BY `tblDocumentContent`.`document`";
|
||||
if (!$this->_ttcontentid) {
|
||||
if (!$this->getResult($queryStr))
|
||||
return false;
|
||||
$this->_ttcontentid=true;
|
||||
}
|
||||
else {
|
||||
if (is_bool($override) && $override) {
|
||||
if (!$this->getResult("DELETE FROM `ttcontentid`"))
|
||||
return false;
|
||||
if (!$this->getResult($queryStr))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return $this->_ttcontentid;
|
||||
}
|
||||
return false;
|
||||
} /* }}} */
|
||||
}
|
||||
|
||||
?>
|
493
SeedDMS_Core/Core/inc.DBAccessPDO.php
Normal file
493
SeedDMS_Core/Core/inc.DBAccessPDO.php
Normal file
|
@ -0,0 +1,493 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of database access using PDO
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Core
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2012 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class to represent the database access for the document management
|
||||
* This class uses PDO for the actual database access.
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Core
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2012 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Core_DatabaseAccess {
|
||||
/**
|
||||
* @var boolean set to true for debug mode
|
||||
*/
|
||||
public $_debug;
|
||||
|
||||
/**
|
||||
* @var string name of database driver (mysql or sqlite)
|
||||
*/
|
||||
protected $_driver;
|
||||
|
||||
/**
|
||||
* @var string name of hostname
|
||||
*/
|
||||
protected $_hostname;
|
||||
|
||||
/**
|
||||
* @var int port number of database
|
||||
*/
|
||||
protected $_port;
|
||||
|
||||
/**
|
||||
* @var string name of database
|
||||
*/
|
||||
protected $_database;
|
||||
|
||||
/**
|
||||
* @var string name of database user
|
||||
*/
|
||||
protected $_user;
|
||||
|
||||
/**
|
||||
* @var string password of database user
|
||||
*/
|
||||
protected $_passw;
|
||||
|
||||
/**
|
||||
* @var object internal database connection
|
||||
*/
|
||||
private $_conn;
|
||||
|
||||
/**
|
||||
* @var boolean set to true if connection to database is established
|
||||
*/
|
||||
private $_connected;
|
||||
|
||||
/**
|
||||
* @var boolean set to true if temp. table for tree view has been created
|
||||
*/
|
||||
private $_ttreviewid;
|
||||
|
||||
/**
|
||||
* @var boolean set to true if temp. table for approvals has been created
|
||||
*/
|
||||
private $_ttapproveid;
|
||||
|
||||
/**
|
||||
* @var boolean set to true if temp. table for doc status has been created
|
||||
*/
|
||||
private $_ttstatid;
|
||||
|
||||
/**
|
||||
* @var boolean set to true if temp. table for doc content has been created
|
||||
*/
|
||||
private $_ttcontentid;
|
||||
|
||||
/**
|
||||
* @var boolean set to true if in a database transaction
|
||||
*/
|
||||
private $_intransaction;
|
||||
|
||||
/**
|
||||
* Return list of all database tables
|
||||
*
|
||||
* This function is used to retrieve a list of database tables for backup
|
||||
*
|
||||
* @return array list of table names
|
||||
*/
|
||||
function TableList() { /* {{{ */
|
||||
switch($this->_driver) {
|
||||
case 'mysql':
|
||||
$sql = "select TABLE_NAME as name from information_schema.tables where TABLE_SCHEMA='".$this->_database."' and TABLE_TYPE='BASE TABLE'";
|
||||
break;
|
||||
case 'sqlite':
|
||||
$sql = "select tbl_name as name from sqlite_master where type='table'";
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
$arr = $this->getResultArray($sql);
|
||||
$res = array();
|
||||
foreach($arr as $tmp)
|
||||
$res[] = $tmp['name'];
|
||||
return $res;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Constructor of SeedDMS_Core_DatabaseAccess
|
||||
*
|
||||
* Sets all database parameters but does not connect.
|
||||
*
|
||||
* @param string $driver the database type e.g. mysql, sqlite
|
||||
* @param string $hostname host of database server
|
||||
* @param string $user name of user having access to database
|
||||
* @param string $passw password of user
|
||||
* @param string $database name of database
|
||||
*/
|
||||
function __construct($driver, $hostname, $user, $passw, $database = false) { /* {{{ */
|
||||
$this->_driver = $driver;
|
||||
$tmp = explode(":", $hostname);
|
||||
$this->_hostname = $tmp[0];
|
||||
$this->_port = null;
|
||||
if(!empty($tmp[1]))
|
||||
$this->_port = $tmp[1];
|
||||
$this->_database = $database;
|
||||
$this->_user = $user;
|
||||
$this->_passw = $passw;
|
||||
$this->_connected = false;
|
||||
// $tt*****id is a hack to ensure that we do not try to create the
|
||||
// temporary table twice during a single connection. Can be fixed by
|
||||
// using Views (MySQL 5.0 onward) instead of temporary tables.
|
||||
// CREATE ... IF NOT EXISTS cannot be used because it has the
|
||||
// unpleasant side-effect of performing the insert again even if the
|
||||
// table already exists.
|
||||
//
|
||||
// See createTemporaryTable() method for implementation.
|
||||
$this->_ttreviewid = false;
|
||||
$this->_ttapproveid = false;
|
||||
$this->_ttstatid = false;
|
||||
$this->_ttcontentid = false;
|
||||
$this->_debug = false;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Connect to database
|
||||
*
|
||||
* @return boolean true if connection could be established, otherwise false
|
||||
*/
|
||||
function connect() { /* {{{ */
|
||||
switch($this->_driver) {
|
||||
case 'mysql':
|
||||
case 'mysqli':
|
||||
case 'mysqlnd':
|
||||
$dsn = $this->_driver.":dbname=".$this->_database.";host=".$this->_hostname;
|
||||
if($this->_port)
|
||||
$dsn .= ";port=".$this->_port;
|
||||
break;
|
||||
case 'sqlite':
|
||||
$dsn = $this->_driver.":".$this->_database;
|
||||
break;
|
||||
}
|
||||
$this->_conn = new PDO($dsn, $this->_user, $this->_passw);
|
||||
if (!$this->_conn)
|
||||
return false;
|
||||
|
||||
switch($this->_driver) {
|
||||
case 'mysql':
|
||||
$this->_conn->exec('SET NAMES utf8');
|
||||
/* Turn this on if you want strict checking of default values, etc. */
|
||||
// $this->_conn->exec("SET SESSION sql_mode = 'STRICT_TRANS_TABLES'");
|
||||
break;
|
||||
case 'sqlite':
|
||||
$this->_conn->exec('PRAGMA foreign_keys = ON');
|
||||
break;
|
||||
}
|
||||
$this->_connected = true;
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Make sure a database connection exisits
|
||||
*
|
||||
* This function checks for a database connection. If it does not exists
|
||||
* it will reconnect.
|
||||
*
|
||||
* @return boolean true if connection is established, otherwise false
|
||||
*/
|
||||
function ensureConnected() { /* {{{ */
|
||||
if (!$this->_connected) return $this->connect();
|
||||
else return true;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Sanitize String used in database operations
|
||||
*
|
||||
* @param string text
|
||||
* @return string sanitized string
|
||||
*/
|
||||
function qstr($text) { /* {{{ */
|
||||
return $this->_conn->quote($text);
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Execute SQL query and return result
|
||||
*
|
||||
* Call this function only with sql query which return data records.
|
||||
*
|
||||
* @param string $queryStr sql query
|
||||
* @return array/boolean data if query could be executed otherwise false
|
||||
*/
|
||||
function getResultArray($queryStr) { /* {{{ */
|
||||
$resArr = array();
|
||||
|
||||
$res = $this->_conn->query($queryStr);
|
||||
if ($res === false) {
|
||||
if($this->_debug)
|
||||
echo "error: ".$queryStr."<br />";
|
||||
return false;
|
||||
}
|
||||
$resArr = $res->fetchAll(PDO::FETCH_ASSOC);
|
||||
// $res->Close();
|
||||
return $resArr;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Execute SQL query
|
||||
*
|
||||
* Call this function only with sql query which do not return data records.
|
||||
*
|
||||
* @param string $queryStr sql query
|
||||
* @param boolean $silent not used anymore. This was used when this method
|
||||
* still issued an error message
|
||||
* @return boolean true if query could be executed otherwise false
|
||||
*/
|
||||
function getResult($queryStr, $silent=false) { /* {{{ */
|
||||
$res = $this->_conn->exec($queryStr);
|
||||
if($res === false) {
|
||||
if($this->_debug)
|
||||
echo "error: ".$queryStr."<br />";
|
||||
return false;
|
||||
} else
|
||||
return true;
|
||||
|
||||
return $res;
|
||||
} /* }}} */
|
||||
|
||||
function startTransaction() { /* {{{ */
|
||||
if(!$this->_intransaction) {
|
||||
$this->_conn->beginTransaction();
|
||||
}
|
||||
$this->_intransaction++;
|
||||
} /* }}} */
|
||||
|
||||
function rollbackTransaction() { /* {{{ */
|
||||
if($this->_intransaction == 1) {
|
||||
$this->_conn->rollBack();
|
||||
}
|
||||
$this->_intransaction--;
|
||||
} /* }}} */
|
||||
|
||||
function commitTransaction() { /* {{{ */
|
||||
if($this->_intransaction == 1) {
|
||||
$this->_conn->commit();
|
||||
}
|
||||
$this->_intransaction--;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Return the id of the last instert record
|
||||
*
|
||||
* @return integer id used in last autoincrement
|
||||
*/
|
||||
function getInsertID() { /* {{{ */
|
||||
return $this->_conn->lastInsertId();
|
||||
} /* }}} */
|
||||
|
||||
function getErrorMsg() { /* {{{ */
|
||||
$info = $this->_conn->errorInfo();
|
||||
return($info[2]);
|
||||
} /* }}} */
|
||||
|
||||
function getErrorNo() { /* {{{ */
|
||||
return $this->_conn->errorCode();
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Create various temporary tables to speed up and simplify sql queries
|
||||
*/
|
||||
function createTemporaryTable($tableName, $override=false) { /* {{{ */
|
||||
if (!strcasecmp($tableName, "ttreviewid")) {
|
||||
switch($this->_driver) {
|
||||
case 'sqlite':
|
||||
$queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttreviewid` AS ".
|
||||
"SELECT `tblDocumentReviewLog`.`reviewID`, ".
|
||||
"MAX(`tblDocumentReviewLog`.`reviewLogID`) AS `maxLogID` ".
|
||||
"FROM `tblDocumentReviewLog` ".
|
||||
"GROUP BY `tblDocumentReviewLog`.`reviewID` ".
|
||||
"ORDER BY `tblDocumentReviewLog`.`reviewLogID`";
|
||||
break;
|
||||
default:
|
||||
$queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttreviewid` (PRIMARY KEY (`reviewID`), INDEX (`maxLogID`)) ".
|
||||
"SELECT `tblDocumentReviewLog`.`reviewID`, ".
|
||||
"MAX(`tblDocumentReviewLog`.`reviewLogID`) AS `maxLogID` ".
|
||||
"FROM `tblDocumentReviewLog` ".
|
||||
"GROUP BY `tblDocumentReviewLog`.`reviewID` ".
|
||||
"ORDER BY `tblDocumentReviewLog`.`reviewLogID`";
|
||||
}
|
||||
if (!$this->_ttreviewid) {
|
||||
if (!$this->getResult($queryStr))
|
||||
return false;
|
||||
$this->_ttreviewid=true;
|
||||
}
|
||||
else {
|
||||
if (is_bool($override) && $override) {
|
||||
if (!$this->getResult("DELETE FROM `ttreviewid`"))
|
||||
return false;
|
||||
if (!$this->getResult($queryStr))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return $this->_ttreviewid;
|
||||
}
|
||||
else if (!strcasecmp($tableName, "ttapproveid")) {
|
||||
switch($this->_driver) {
|
||||
case 'sqlite':
|
||||
$queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttapproveid` AS ".
|
||||
"SELECT `tblDocumentApproveLog`.`approveID`, ".
|
||||
"MAX(`tblDocumentApproveLog`.`approveLogID`) AS `maxLogID` ".
|
||||
"FROM `tblDocumentApproveLog` ".
|
||||
"GROUP BY `tblDocumentApproveLog`.`approveID` ".
|
||||
"ORDER BY `tblDocumentApproveLog`.`approveLogID`";
|
||||
break;
|
||||
default:
|
||||
$queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttapproveid` (PRIMARY KEY (`approveID`), INDEX (`maxLogID`)) ".
|
||||
"SELECT `tblDocumentApproveLog`.`approveID`, ".
|
||||
"MAX(`tblDocumentApproveLog`.`approveLogID`) AS `maxLogID` ".
|
||||
"FROM `tblDocumentApproveLog` ".
|
||||
"GROUP BY `tblDocumentApproveLog`.`approveID` ".
|
||||
"ORDER BY `tblDocumentApproveLog`.`approveLogID`";
|
||||
}
|
||||
if (!$this->_ttapproveid) {
|
||||
if (!$this->getResult($queryStr))
|
||||
return false;
|
||||
$this->_ttapproveid=true;
|
||||
}
|
||||
else {
|
||||
if (is_bool($override) && $override) {
|
||||
if (!$this->getResult("DELETE FROM `ttapproveid`"))
|
||||
return false;
|
||||
if (!$this->getResult($queryStr))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return $this->_ttapproveid;
|
||||
}
|
||||
else if (!strcasecmp($tableName, "ttstatid")) {
|
||||
switch($this->_driver) {
|
||||
case 'sqlite':
|
||||
$queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttstatid` AS ".
|
||||
"SELECT `tblDocumentStatusLog`.`statusID` AS `statusID`, ".
|
||||
"MAX(`tblDocumentStatusLog`.`statusLogID`) AS `maxLogID` ".
|
||||
"FROM `tblDocumentStatusLog` ".
|
||||
"GROUP BY `tblDocumentStatusLog`.`statusID` ".
|
||||
"ORDER BY `tblDocumentStatusLog`.`statusLogID`";
|
||||
break;
|
||||
default:
|
||||
$queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttstatid` (PRIMARY KEY (`statusID`), INDEX (`maxLogID`)) ".
|
||||
"SELECT `tblDocumentStatusLog`.`statusID`, ".
|
||||
"MAX(`tblDocumentStatusLog`.`statusLogID`) AS `maxLogID` ".
|
||||
"FROM `tblDocumentStatusLog` ".
|
||||
"GROUP BY `tblDocumentStatusLog`.`statusID` ".
|
||||
"ORDER BY `tblDocumentStatusLog`.`statusLogID`";
|
||||
}
|
||||
if (!$this->_ttstatid) {
|
||||
if (!$this->getResult($queryStr))
|
||||
return false;
|
||||
$this->_ttstatid=true;
|
||||
}
|
||||
else {
|
||||
if (is_bool($override) && $override) {
|
||||
if (!$this->getResult("DELETE FROM `ttstatid`"))
|
||||
return false;
|
||||
if (!$this->getResult($queryStr))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return $this->_ttstatid;
|
||||
}
|
||||
else if (!strcasecmp($tableName, "ttcontentid")) {
|
||||
switch($this->_driver) {
|
||||
case 'sqlite':
|
||||
$queryStr = "CREATE TEMPORARY TABLE `ttcontentid` AS ".
|
||||
"SELECT `tblDocumentContent`.`document` AS `document`, ".
|
||||
"MAX(`tblDocumentContent`.`version`) AS `maxVersion` ".
|
||||
"FROM `tblDocumentContent` ".
|
||||
"GROUP BY `tblDocumentContent`.`document` ".
|
||||
"ORDER BY `tblDocumentContent`.`document`";
|
||||
break;
|
||||
default:
|
||||
$queryStr = "CREATE TEMPORARY TABLE `ttcontentid` (PRIMARY KEY (`document`), INDEX (`maxVersion`)) ".
|
||||
"SELECT `tblDocumentContent`.`document`, ".
|
||||
"MAX(`tblDocumentContent`.`version`) AS `maxVersion` ".
|
||||
"FROM `tblDocumentContent` ".
|
||||
"GROUP BY `tblDocumentContent`.`document` ".
|
||||
"ORDER BY `tblDocumentContent`.`document`";
|
||||
}
|
||||
if (!$this->_ttcontentid) {
|
||||
if (!$this->getResult($queryStr))
|
||||
return false;
|
||||
$this->_ttcontentid=true;
|
||||
}
|
||||
else {
|
||||
if (is_bool($override) && $override) {
|
||||
if (!$this->getResult("DELETE FROM `ttcontentid`"))
|
||||
return false;
|
||||
if (!$this->getResult($queryStr))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return $this->_ttcontentid;
|
||||
}
|
||||
return false;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Return sql statement for extracting the date part from a field
|
||||
* containing a unix timestamp
|
||||
*
|
||||
* @param string $fieldname name of field containing the timestamp
|
||||
* @return string sql code
|
||||
*/
|
||||
function getDateExtract($fieldname, $format='%Y-%m-%d') { /* {{{ */
|
||||
switch($this->_driver) {
|
||||
case 'mysql':
|
||||
return "from_unixtime(`".$fieldname."`, ".$this->qstr($format).")";
|
||||
break;
|
||||
case 'sqlite':
|
||||
return "strftime(".$this->qstr($format).", `".$fieldname."`, 'unixepoch')";
|
||||
break;
|
||||
}
|
||||
return '';
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Return sql statement for returning the current date and time
|
||||
* in format Y-m-d H:i:s
|
||||
*
|
||||
* @return string sql code
|
||||
*/
|
||||
function getCurrentDatetime() { /* {{{ */
|
||||
switch($this->_driver) {
|
||||
case 'mysql':
|
||||
return "CURRENT_TIMESTAMP";
|
||||
break;
|
||||
case 'sqlite':
|
||||
return "datetime('now', 'localtime')";
|
||||
break;
|
||||
}
|
||||
return '';
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Return sql statement for returning the current timestamp
|
||||
*
|
||||
* @return string sql code
|
||||
*/
|
||||
function getCurrentTimestamp() { /* {{{ */
|
||||
switch($this->_driver) {
|
||||
case 'mysql':
|
||||
return "UNIX_TIMESTAMP()";
|
||||
break;
|
||||
case 'sqlite':
|
||||
return "strftime('%s', 'now')";
|
||||
break;
|
||||
}
|
||||
return '';
|
||||
} /* }}} */
|
||||
}
|
||||
|
||||
?>
|
218
SeedDMS_Core/Core/inc.FileUtils.php
Normal file
218
SeedDMS_Core/Core/inc.FileUtils.php
Normal file
|
@ -0,0 +1,218 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of various file system operations
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Core
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2002-2005 Markus Westphal,
|
||||
* 2006-2008 Malcolm Cowe, 2010 Matteo Lucarelli,
|
||||
* 2010 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class to represent a user in the document management system
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Core
|
||||
* @author Markus Westphal, Malcolm Cowe, Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2002-2005 Markus Westphal,
|
||||
* 2006-2008 Malcolm Cowe, 2010 Matteo Lucarelli,
|
||||
* 2010 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Core_File {
|
||||
static function renameFile($old, $new) { /* {{{ */
|
||||
return @rename($old, $new);
|
||||
} /* }}} */
|
||||
|
||||
static function removeFile($file) { /* {{{ */
|
||||
return @unlink($file);
|
||||
} /* }}} */
|
||||
|
||||
static function copyFile($source, $target) { /* {{{ */
|
||||
return @copy($source, $target);
|
||||
} /* }}} */
|
||||
|
||||
static function moveFile($source, $target) { /* {{{ */
|
||||
if (!@copyFile($source, $target))
|
||||
return false;
|
||||
return @removeFile($source);
|
||||
} /* }}} */
|
||||
|
||||
static function fileSize($file) { /* {{{ */
|
||||
if(!$a = fopen($file, 'r'))
|
||||
return false;
|
||||
fseek($a, 0, SEEK_END);
|
||||
$filesize = ftell($a);
|
||||
fclose($a);
|
||||
return $filesize;
|
||||
} /* }}} */
|
||||
|
||||
static function format_filesize($size, $sizes = array('Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB')) { /* {{{ */
|
||||
if ($size == 0) return('0 Bytes');
|
||||
return (round($size/pow(1024, ($i = floor(log($size, 1024)))), 2) . ' ' . $sizes[$i]);
|
||||
} /* }}} */
|
||||
|
||||
static function parse_filesize($str) { /* {{{ */
|
||||
preg_replace('/\s\s+/', ' ', $str);
|
||||
if(strtoupper(substr($str, -1)) == 'B') {
|
||||
$value = (int) substr($str, 0, -2);
|
||||
$unit = substr($str, -2, 1);
|
||||
} else {
|
||||
$value = (int) substr($str, 0, -1);
|
||||
$unit = substr($str, -1);
|
||||
}
|
||||
switch(strtoupper($unit)) {
|
||||
case 'G':
|
||||
return $value * 1024 * 1024 * 1024;
|
||||
break;
|
||||
case 'M':
|
||||
return $value * 1024 * 1024;
|
||||
break;
|
||||
case 'K':
|
||||
return $value * 1024;
|
||||
break;
|
||||
default;
|
||||
return $value;
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
} /* }}} */
|
||||
|
||||
static function checksum($file) { /* {{{ */
|
||||
return md5_file($file);
|
||||
} /* }}} */
|
||||
|
||||
static function renameDir($old, $new) { /* {{{ */
|
||||
return @rename($old, $new);
|
||||
} /* }}} */
|
||||
|
||||
static function makeDir($path) { /* {{{ */
|
||||
|
||||
if( !is_dir( $path ) ){
|
||||
$res=@mkdir( $path , 0777, true);
|
||||
if (!$res) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
/* some old code
|
||||
if (strncmp($path, DIRECTORY_SEPARATOR, 1) == 0) {
|
||||
$mkfolder = DIRECTORY_SEPARATOR;
|
||||
}
|
||||
else {
|
||||
$mkfolder = "";
|
||||
}
|
||||
$path = preg_split( "/[\\\\\/]/" , $path );
|
||||
for( $i=0 ; isset( $path[$i] ) ; $i++ )
|
||||
{
|
||||
if(!strlen(trim($path[$i])))continue;
|
||||
$mkfolder .= $path[$i];
|
||||
|
||||
if( !is_dir( $mkfolder ) ){
|
||||
$res=@mkdir( "$mkfolder" , 0777);
|
||||
if (!$res) return false;
|
||||
}
|
||||
$mkfolder .= DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
// patch from alekseynfor safe_mod or open_basedir
|
||||
|
||||
global $settings;
|
||||
$path = substr_replace ($path, "/", 0, strlen($settings->_contentDir));
|
||||
$mkfolder = $settings->_contentDir;
|
||||
|
||||
$path = preg_split( "/[\\\\\/]/" , $path );
|
||||
|
||||
for( $i=0 ; isset( $path[$i] ) ; $i++ )
|
||||
{
|
||||
if(!strlen(trim($path[$i])))continue;
|
||||
$mkfolder .= $path[$i];
|
||||
|
||||
if( !is_dir( $mkfolder ) ){
|
||||
$res= @mkdir( "$mkfolder" , 0777);
|
||||
if (!$res) return false;
|
||||
}
|
||||
$mkfolder .= DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
return true;
|
||||
*/
|
||||
} /* }}} */
|
||||
|
||||
static function removeDir($path) { /* {{{ */
|
||||
$handle = @opendir($path);
|
||||
while ($entry = @readdir($handle) )
|
||||
{
|
||||
if ($entry == ".." || $entry == ".")
|
||||
continue;
|
||||
else if (is_dir($path . $entry))
|
||||
{
|
||||
if (!self::removeDir($path . $entry . "/"))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!@unlink($path . $entry))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@closedir($handle);
|
||||
return @rmdir($path);
|
||||
} /* }}} */
|
||||
|
||||
static function copyDir($sourcePath, $targetPath) { /* {{{ */
|
||||
if (mkdir($targetPath, 0777)) {
|
||||
$handle = @opendir($sourcePath);
|
||||
while ($entry = @readdir($handle) ) {
|
||||
if ($entry == ".." || $entry == ".")
|
||||
continue;
|
||||
else if (is_dir($sourcePath . $entry)) {
|
||||
if (!self::copyDir($sourcePath . $entry . "/", $targetPath . $entry . "/"))
|
||||
return false;
|
||||
} else {
|
||||
if (!@copy($sourcePath . $entry, $targetPath . $entry))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@closedir($handle);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
static function moveDir($sourcePath, $targetPath) { /* {{{ */
|
||||
if (!copyDir($sourcePath, $targetPath))
|
||||
return false;
|
||||
return removeDir($sourcePath);
|
||||
} /* }}} */
|
||||
|
||||
// code by Kioob (php.net manual)
|
||||
static function gzcompressfile($source,$level=false) { /* {{{ */
|
||||
$dest=$source.'.gz';
|
||||
$mode='wb'.$level;
|
||||
$error=false;
|
||||
if($fp_out=@gzopen($dest,$mode)) {
|
||||
if($fp_in=@fopen($source,'rb')) {
|
||||
while(!feof($fp_in))
|
||||
@gzwrite($fp_out,fread($fp_in,1024*512));
|
||||
@fclose($fp_in);
|
||||
}
|
||||
else $error=true;
|
||||
@gzclose($fp_out);
|
||||
}
|
||||
else $error=true;
|
||||
|
||||
if($error) return false;
|
||||
else return $dest;
|
||||
} /* }}} */
|
||||
}
|
||||
?>
|
1030
SeedDMS_Core/package.xml
Normal file
1030
SeedDMS_Core/package.xml
Normal file
File diff suppressed because it is too large
Load Diff
10
SeedDMS_Core/tests/config.php
Normal file
10
SeedDMS_Core/tests/config.php
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
$g_config['type'] = 'mysql';
|
||||
$g_config['hostname'] = 'localhost';
|
||||
$g_config['user'] = 'letodms';
|
||||
$g_config['passwd'] = 'letodms';
|
||||
$g_config['name'] = 'letodms';
|
||||
|
||||
$g_config['contentDir'] = '/tmp/content';
|
||||
$g_config['contentOffsetDir'] = '/tmp/content';
|
||||
?>
|
25
SeedDMS_Core/tests/getfoldertree.php
Normal file
25
SeedDMS_Core/tests/getfoldertree.php
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
include("config.php");
|
||||
include("SeedDMS/SeedDMS_Core.php");
|
||||
|
||||
$db = new SeedDMS_Core_DatabaseAccess($g_config['type'], $g_config['hostname'], $g_config['user'], $g_config['passwd'], $g_config['name']);
|
||||
$db->connect() or die ("Could not connect to db-server \"" . $g_config['hostname'] . "\"");
|
||||
|
||||
$dms = new SeedDMS_Core_DMS($db, $g_config['contentDir'], $g_config['contentOffsetDir']);
|
||||
|
||||
function tree($folder, $indent='') {
|
||||
echo $indent."D ".$folder->getName()."\n";
|
||||
$subfolders = $folder->getSubFolders();
|
||||
foreach($subfolders as $subfolder) {
|
||||
tree($subfolder, $indent.' ');
|
||||
}
|
||||
$documents = $folder->getDocuments();
|
||||
foreach($documents as $document) {
|
||||
echo $indent." ".$document->getName()."\n";
|
||||
}
|
||||
}
|
||||
|
||||
$folder = $dms->getFolder(1);
|
||||
tree($folder);
|
||||
|
||||
?>
|
14
SeedDMS_Core/tests/getusers.php
Normal file
14
SeedDMS_Core/tests/getusers.php
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
include("config.php");
|
||||
include("SeedDMS/SeedDMS_Core.php");
|
||||
|
||||
$db = new SeedDMS_Core_DatabaseAccess($g_config['type'], $g_config['hostname'], $g_config['user'], $g_config['passwd'], $g_config['name']);
|
||||
$db->connect() or die ("Could not connect to db-server \"" . $g_config['hostname'] . "\"");
|
||||
|
||||
$dms = new SeedDMS_Core_DMS($db, $g_config['contentDir'], $g_config['contentOffsetDir']);
|
||||
|
||||
$users = $dms->getAllUsers();
|
||||
foreach($users as $user)
|
||||
echo $user->getId()." ".$user->getLogin()." ".$user->getFullname()."\n";
|
||||
|
||||
?>
|
44
SeedDMS_Core/tests/reverselookup.php
Normal file
44
SeedDMS_Core/tests/reverselookup.php
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
include("config.php");
|
||||
include("SeedDMS/SeedDMS_Core.php");
|
||||
|
||||
$db = new SeedDMS_Core_DatabaseAccess($g_config['type'], $g_config['hostname'], $g_config['user'], $g_config['passwd'], $g_config['name']);
|
||||
$db->connect() or die ("Could not connect to db-server \"" . $g_config['hostname'] . "\"");
|
||||
|
||||
$dms = new SeedDMS_Core_DMS($db, $g_config['contentDir'], $g_config['contentOffsetDir']);
|
||||
|
||||
$path = '/Test 1/';
|
||||
echo "Searching for folder or document with path '".$path."'\n";
|
||||
|
||||
$root = $dms->getRootFolder();
|
||||
if($path[0] == '/') {
|
||||
$path = substr($path, 1);
|
||||
}
|
||||
$patharr = explode('/', $path);
|
||||
/* The last entry is always the document, though if the path ends in '/' the
|
||||
* document name will be empty.
|
||||
*/
|
||||
$docname = array_pop($patharr);
|
||||
$parentfolder = $root;
|
||||
|
||||
foreach($patharr as $pathseg) {
|
||||
if($folder = $dms->getFolderByName($pathseg, $parentfolder)) {
|
||||
$parentfolder = $folder;
|
||||
}
|
||||
}
|
||||
if($folder) {
|
||||
if($docname) {
|
||||
if($document = $dms->getDocumentByName($docname, $folder)) {
|
||||
echo "Given path is document '".$document->getName()."'\n";
|
||||
} else {
|
||||
echo "No object found\n";
|
||||
}
|
||||
} else {
|
||||
echo "Given path is a folder '".$folder->getName()."'\n";
|
||||
}
|
||||
} else {
|
||||
echo "No object found\n";
|
||||
}
|
||||
|
||||
?>
|
||||
|
44
SeedDMS_Lucene/Lucene.php
Normal file
44
SeedDMS_Lucene/Lucene.php
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
// SeedDMS. Document Management System
|
||||
// Copyright (C) 2011-2013 Uwe Steinmann
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
/**
|
||||
* @uses Zend_Search_Lucene
|
||||
*/
|
||||
require_once('Zend/Search/Lucene.php');
|
||||
|
||||
/**
|
||||
* @uses Zend_Search_Lucene_Analysis_TokenFilter_Stopwords
|
||||
*/
|
||||
require_once("Zend/Search/Lucene/Analysis/TokenFilter/StopWords.php");
|
||||
|
||||
/**
|
||||
* @uses SeedDMS_Lucene_Indexer
|
||||
*/
|
||||
require_once('Lucene/Indexer.php');
|
||||
|
||||
/**
|
||||
* @uses SeedDMS_Lucene_Search
|
||||
*/
|
||||
require_once('Lucene/Search.php');
|
||||
|
||||
/**
|
||||
* @uses SeedDMS_Lucene_IndexedDocument
|
||||
*/
|
||||
require_once('Lucene/IndexedDocument.php');
|
||||
|
||||
?>
|
146
SeedDMS_Lucene/Lucene/IndexedDocument.php
Normal file
146
SeedDMS_Lucene/Lucene/IndexedDocument.php
Normal file
|
@ -0,0 +1,146 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of an indexed document
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Lucene
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010, Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Class for managing an indexed document.
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Lucene
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2011, Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Lucene_IndexedDocument extends Zend_Search_Lucene_Document {
|
||||
|
||||
static function execWithTimeout($cmd, $timeout=2) { /* {{{ */
|
||||
$descriptorspec = array(
|
||||
0 => array("pipe", "r"),
|
||||
1 => array("pipe", "w"),
|
||||
2 => array("pipe", "w")
|
||||
);
|
||||
$pipes = array();
|
||||
|
||||
$timeout += time();
|
||||
$process = proc_open($cmd, $descriptorspec, $pipes);
|
||||
if (!is_resource($process)) {
|
||||
throw new Exception("proc_open failed on: " . $cmd);
|
||||
}
|
||||
|
||||
$output = '';
|
||||
do {
|
||||
$timeleft = $timeout - time();
|
||||
$read = array($pipes[1]);
|
||||
stream_select($read, $write = NULL, $exeptions = NULL, $timeleft, NULL);
|
||||
|
||||
if (!empty($read)) {
|
||||
$output .= fread($pipes[1], 8192);
|
||||
}
|
||||
} while (!feof($pipes[1]) && $timeleft > 0);
|
||||
|
||||
if ($timeleft <= 0) {
|
||||
proc_terminate($process);
|
||||
throw new Exception("command timeout on: " . $cmd);
|
||||
} else {
|
||||
return $output;
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Constructor. Creates our indexable document and adds all
|
||||
* necessary fields to it using the passed in document
|
||||
*/
|
||||
public function __construct($dms, $document, $convcmd=null, $nocontent=false, $timeout=5) {
|
||||
$_convcmd = array(
|
||||
'application/pdf' => 'pdftotext -enc UTF-8 -nopgbrk %s - |sed -e \'s/ [a-zA-Z0-9.]\{1\} / /g\' -e \'s/[0-9.]//g\'',
|
||||
'application/postscript' => 'ps2pdf14 %s - | pdftotext -enc UTF-8 -nopgbrk - - | sed -e \'s/ [a-zA-Z0-9.]\{1\} / /g\' -e \'s/[0-9.]//g\'',
|
||||
'application/msword' => 'catdoc %s',
|
||||
'application/vnd.ms-excel' => 'ssconvert -T Gnumeric_stf:stf_csv -S %s fd://1',
|
||||
'audio/mp3' => "id3 -l -R %s | egrep '(Title|Artist|Album)' | sed 's/^[^:]*: //g'",
|
||||
'audio/mpeg' => "id3 -l -R %s | egrep '(Title|Artist|Album)' | sed 's/^[^:]*: //g'",
|
||||
'text/plain' => 'cat %s',
|
||||
);
|
||||
if($convcmd) {
|
||||
$_convcmd = $convcmd;
|
||||
}
|
||||
|
||||
$version = $document->getLatestContent();
|
||||
$this->addField(Zend_Search_Lucene_Field::Keyword('document_id', $document->getID()));
|
||||
if($version) {
|
||||
$this->addField(Zend_Search_Lucene_Field::Keyword('mimetype', $version->getMimeType()));
|
||||
$this->addField(Zend_Search_Lucene_Field::Keyword('origfilename', $version->getOriginalFileName(), 'utf-8'));
|
||||
if(!$nocontent)
|
||||
$this->addField(Zend_Search_Lucene_Field::UnIndexed('created', $version->getDate()));
|
||||
if($attributes = $version->getAttributes()) {
|
||||
foreach($attributes as $attribute) {
|
||||
$attrdef = $attribute->getAttributeDefinition();
|
||||
if($attrdef->getValueSet() != '')
|
||||
$this->addField(Zend_Search_Lucene_Field::Keyword('attr_'.str_replace(' ', '_', $attrdef->getName()), $attribute->getValue(), 'utf-8'));
|
||||
else
|
||||
$this->addField(Zend_Search_Lucene_Field::Text('attr_'.str_replace(' ', '_', $attrdef->getName()), $attribute->getValue(), 'utf-8'));
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->addField(Zend_Search_Lucene_Field::Text('title', $document->getName(), 'utf-8'));
|
||||
if($categories = $document->getCategories()) {
|
||||
$names = array();
|
||||
foreach($categories as $cat) {
|
||||
$names[] = $cat->getName();
|
||||
}
|
||||
$this->addField(Zend_Search_Lucene_Field::Text('category', implode(' ', $names), 'utf-8'));
|
||||
}
|
||||
if($attributes = $document->getAttributes()) {
|
||||
foreach($attributes as $attribute) {
|
||||
$attrdef = $attribute->getAttributeDefinition();
|
||||
if($attrdef->getValueSet() != '')
|
||||
$this->addField(Zend_Search_Lucene_Field::Keyword('attr_'.str_replace(' ', '_', $attrdef->getName()), $attribute->getValue(), 'utf-8'));
|
||||
else
|
||||
$this->addField(Zend_Search_Lucene_Field::Text('attr_'.str_replace(' ', '_', $attrdef->getName()), $attribute->getValue(), 'utf-8'));
|
||||
}
|
||||
}
|
||||
|
||||
$owner = $document->getOwner();
|
||||
$this->addField(Zend_Search_Lucene_Field::Text('owner', $owner->getLogin(), 'utf-8'));
|
||||
if($keywords = $document->getKeywords()) {
|
||||
$this->addField(Zend_Search_Lucene_Field::Text('keywords', $keywords, 'utf-8'));
|
||||
}
|
||||
if($comment = $document->getComment()) {
|
||||
$this->addField(Zend_Search_Lucene_Field::Text('comment', $comment, 'utf-8'));
|
||||
}
|
||||
if($version && !$nocontent) {
|
||||
$path = $dms->contentDir . $version->getPath();
|
||||
$content = '';
|
||||
$fp = null;
|
||||
$mimetype = $version->getMimeType();
|
||||
if(isset($_convcmd[$mimetype])) {
|
||||
$cmd = sprintf($_convcmd[$mimetype], $path);
|
||||
$content = self::execWithTimeout($cmd, $timeout);
|
||||
/*
|
||||
$fp = popen($cmd, 'r');
|
||||
if($fp) {
|
||||
$content = '';
|
||||
while(!feof($fp)) {
|
||||
$content .= fread($fp, 2048);
|
||||
}
|
||||
pclose($fp);
|
||||
}
|
||||
*/
|
||||
if($content) {
|
||||
$this->addField(Zend_Search_Lucene_Field::UnStored('content', $content, 'utf-8'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
63
SeedDMS_Lucene/Lucene/Indexer.php
Normal file
63
SeedDMS_Lucene/Lucene/Indexer.php
Normal file
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of lucene index
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Lucene
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010, Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Class for managing a lucene index.
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Lucene
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2011, Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Lucene_Indexer {
|
||||
/**
|
||||
* @var string $indexname name of lucene index
|
||||
* @access protected
|
||||
*/
|
||||
protected $indexname;
|
||||
|
||||
static function open($luceneDir) { /* {{{ */
|
||||
try {
|
||||
$index = Zend_Search_Lucene::open($luceneDir);
|
||||
return($index);
|
||||
} catch (Exception $e) {
|
||||
return null;
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
function create($luceneDir) { /* {{{ */
|
||||
$index = Zend_Search_Lucene::create($luceneDir);
|
||||
return($index);
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Do some initialization
|
||||
*
|
||||
*/
|
||||
function init($stopWordsFile='') { /* {{{ */
|
||||
$analyzer = new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8_CaseInsensitive();
|
||||
if($stopWordsFile && file_exists($stopWordsFile)) {
|
||||
$stopWordsFilter = new Zend_Search_Lucene_Analysis_TokenFilter_StopWords();
|
||||
$stopWordsFilter->loadFromFile($stopWordsFile);
|
||||
$analyzer->addFilter($stopWordsFilter);
|
||||
}
|
||||
|
||||
Zend_Search_Lucene_Analysis_Analyzer::setDefault($analyzer);
|
||||
} /* }}} */
|
||||
|
||||
|
||||
}
|
||||
?>
|
98
SeedDMS_Lucene/Lucene/Search.php
Normal file
98
SeedDMS_Lucene/Lucene/Search.php
Normal file
|
@ -0,0 +1,98 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of search in lucene index
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Lucene
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010, Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Class for searching in a lucene index.
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Lucene
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2011, Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Lucene_Search {
|
||||
/**
|
||||
* @var object $index lucene index
|
||||
* @access protected
|
||||
*/
|
||||
protected $index;
|
||||
|
||||
/**
|
||||
* Create a new instance of the search
|
||||
*
|
||||
* @param object $index lucene index
|
||||
* @return object instance of SeedDMS_Lucene_Search
|
||||
*/
|
||||
function __construct($index) { /* {{{ */
|
||||
$this->index = $index;
|
||||
$this->version = '@package_version@';
|
||||
if($this->version[0] == '@')
|
||||
$this->version = '3.0.0';
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Get document from index
|
||||
*
|
||||
* @param object $index lucene index
|
||||
* @return object instance of SeedDMS_Lucene_Document of false
|
||||
*/
|
||||
function getDocument($id) { /* {{{ */
|
||||
$hits = $this->index->find('document_id:'.$id);
|
||||
return $hits ? $hits[0] : false;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Search in index
|
||||
*
|
||||
* @param object $index lucene index
|
||||
* @return object instance of SeedDMS_Lucene_Search
|
||||
*/
|
||||
function search($term, $owner, $status='', $categories=array(), $fields=array()) { /* {{{ */
|
||||
$querystr = '';
|
||||
if($fields) {
|
||||
} else {
|
||||
if($term)
|
||||
$querystr .= trim($term);
|
||||
}
|
||||
if($owner) {
|
||||
if($querystr)
|
||||
$querystr .= ' && ';
|
||||
$querystr .= 'owner:'.$owner;
|
||||
}
|
||||
if($categories) {
|
||||
if($querystr)
|
||||
$querystr .= ' && ';
|
||||
$querystr .= '(category:"';
|
||||
$querystr .= implode('" || category:"', $categories);
|
||||
$querystr .= '")';
|
||||
}
|
||||
try {
|
||||
$query = Zend_Search_Lucene_Search_QueryParser::parse($querystr);
|
||||
try {
|
||||
$hits = $this->index->find($query);
|
||||
$recs = array();
|
||||
foreach($hits as $hit) {
|
||||
$recs[] = array('id'=>$hit->id, 'document_id'=>$hit->document_id);
|
||||
}
|
||||
return $recs;
|
||||
} catch (Zend_Search_Lucene_Exception $e) {
|
||||
return false;
|
||||
}
|
||||
} catch (Zend_Search_Lucene_Search_QueryParserException $e) {
|
||||
return false;
|
||||
}
|
||||
} /* }}} */
|
||||
}
|
||||
?>
|
206
SeedDMS_Lucene/package.xml
Normal file
206
SeedDMS_Lucene/package.xml
Normal file
|
@ -0,0 +1,206 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<package packagerversion="1.8.1" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
|
||||
<name>SeedDMS_Lucene</name>
|
||||
<channel>pear.php.net</channel>
|
||||
<summary>Fulltext search for SeedDMS</summary>
|
||||
<description>SeedDMS is a web based document management system (DMS). This is
|
||||
the fulltext search engine for it, based on Lucene.</description>
|
||||
<lead>
|
||||
<name>Uwe Steinmann</name>
|
||||
<user>steinm</user>
|
||||
<email>uwe@steinmann.cx</email>
|
||||
<active>yes</active>
|
||||
</lead>
|
||||
<date>2016-02-01</date>
|
||||
<time>09:14:07</time>
|
||||
<version>
|
||||
<release>1.1.7</release>
|
||||
<api>1.1.7</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
add command for indexing postѕcript files
|
||||
</notes>
|
||||
<contents>
|
||||
<dir baseinstalldir="SeedDMS" name="/">
|
||||
<dir name="Lucene">
|
||||
<file name="Indexer.php" role="php">
|
||||
<tasks:replace from="@package_version@" to="version" type="package-info" />
|
||||
</file>
|
||||
<file name="Search.php" role="php">
|
||||
<tasks:replace from="@package_version@" to="version" type="package-info" />
|
||||
</file>
|
||||
<file name="IndexedDocument.php" role="php">
|
||||
<tasks:replace from="@package_version@" to="version" type="package-info" />
|
||||
</file>
|
||||
</dir> <!-- /Lucene -->
|
||||
<dir name="tests">
|
||||
</dir> <!-- /tests -->
|
||||
<file name="Lucene.php" role="php">
|
||||
<tasks:replace from="@package_version@" to="version" type="package-info" />
|
||||
</file>
|
||||
</dir> <!-- / -->
|
||||
</contents>
|
||||
<dependencies>
|
||||
<required>
|
||||
<php>
|
||||
<min>4.3.0</min>
|
||||
</php>
|
||||
<pearinstaller>
|
||||
<min>1.5.4</min>
|
||||
</pearinstaller>
|
||||
</required>
|
||||
</dependencies>
|
||||
<phprelease />
|
||||
<changelog>
|
||||
<release>
|
||||
<version>
|
||||
<release>0.0.1</release>
|
||||
<api>0.0.1</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>alpha</release>
|
||||
<api>alpha</api>
|
||||
</stability>
|
||||
<date>2009-04-27</date>
|
||||
<license uri="http://opensource.org/licenses/bsd-license">BSD License</license>
|
||||
<notes>
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2011-11-06</date>
|
||||
<time>08:05:38</time>
|
||||
<version>
|
||||
<release>1.0.1</release>
|
||||
<api>1.0.0</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>beta</release>
|
||||
<api>beta</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
- New Release
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2012-11-06</date>
|
||||
<time>08:05:38</time>
|
||||
<version>
|
||||
<release>1.1.0</release>
|
||||
<api>1.1.0</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>beta</release>
|
||||
<api>beta</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
use a configurable list of mime type converters, fixed indexing and searching
|
||||
of special chars like german umlaute.
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2012-12-03</date>
|
||||
<time>10:31:23</time>
|
||||
<version>
|
||||
<release>1.1.1</release>
|
||||
<api>1.1.1</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
catch exception if index is opened but not available
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2013-06-17</date>
|
||||
<time>10:31:23</time>
|
||||
<version>
|
||||
<release>1.1.2</release>
|
||||
<api>1.1.1</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
parse query term and catch errors before using it
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2013-06-27</date>
|
||||
<time>15:12:50</time>
|
||||
<version>
|
||||
<release>1.1.3</release>
|
||||
<api>1.1.1</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
explicitly set encoding to utf-8 when adding fields
|
||||
do not check if deleting document from index fails, update it in any case
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2013-08-13</date>
|
||||
<time>21:56:55</time>
|
||||
<version>
|
||||
<release>1.1.4</release>
|
||||
<api>1.1.4</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
class SeedDMS_Lucene_Search::search returns false if query is invalid instead of an empty result record
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2014-07-30</date>
|
||||
<time>09:00:34</time>
|
||||
<version>
|
||||
<release>1.1.5</release>
|
||||
<api>1.1.5</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
field for original filename is treated as utf-8
|
||||
declare SeeDMS_Lucene_Indexer::open() static
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2015-08-05</date>
|
||||
<time>21:13:13</time>
|
||||
<version>
|
||||
<release>1.1.6</release>
|
||||
<api>1.1.6</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
run external commands with a timeout
|
||||
</notes>
|
||||
</release>
|
||||
</changelog>
|
||||
</package>
|
24
SeedDMS_Preview/Preview.php
Normal file
24
SeedDMS_Preview/Preview.php
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
// SeedDMS. Document Management System
|
||||
// Copyright (C) 2011-2013 Uwe Steinmann
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
/**
|
||||
* @uses Preview/Previewer.php
|
||||
*/
|
||||
require_once('Preview/Previewer.php');
|
||||
|
||||
?>
|
327
SeedDMS_Preview/Preview/Previewer.php
Normal file
327
SeedDMS_Preview/Preview/Previewer.php
Normal file
|
@ -0,0 +1,327 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of preview documents
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Preview
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010, Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Class for managing creation of preview images for documents.
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Preview
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2011, Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Preview_Previewer {
|
||||
/**
|
||||
* @var string $cacheDir location in the file system where all the
|
||||
* cached data like thumbnails are located. This should be an
|
||||
* absolute path.
|
||||
* @access public
|
||||
*/
|
||||
public $previewDir;
|
||||
|
||||
/**
|
||||
* @var integer $width maximum width/height of resized image
|
||||
* @access protected
|
||||
*/
|
||||
protected $width;
|
||||
|
||||
/**
|
||||
* @var integer $timeout maximum time for execution of external commands
|
||||
* @access protected
|
||||
*/
|
||||
protected $timeout;
|
||||
|
||||
function __construct($previewDir, $width=40, $timeout=5) {
|
||||
if(!is_dir($previewDir)) {
|
||||
if (!SeedDMS_Core_File::makeDir($previewDir)) {
|
||||
$this->previewDir = '';
|
||||
} else {
|
||||
$this->previewDir = $previewDir;
|
||||
}
|
||||
} else {
|
||||
$this->previewDir = $previewDir;
|
||||
}
|
||||
$this->width = intval($width);
|
||||
$this->timeout = intval($timeout);
|
||||
}
|
||||
|
||||
static function execWithTimeout($cmd, $timeout=5) { /* {{{ */
|
||||
$descriptorspec = array(
|
||||
0 => array("pipe", "r"),
|
||||
1 => array("pipe", "w"),
|
||||
2 => array("pipe", "w")
|
||||
);
|
||||
$pipes = array();
|
||||
|
||||
$timeout += time();
|
||||
$process = proc_open($cmd, $descriptorspec, $pipes);
|
||||
if (!is_resource($process)) {
|
||||
throw new Exception("proc_open failed on: " . $cmd);
|
||||
}
|
||||
|
||||
$output = '';
|
||||
do {
|
||||
$timeleft = $timeout - time();
|
||||
$read = array($pipes[1]);
|
||||
stream_select($read, $write = NULL, $exeptions = NULL, $timeleft, NULL);
|
||||
|
||||
if (!empty($read)) {
|
||||
$output .= fread($pipes[1], 8192);
|
||||
}
|
||||
} while (!feof($pipes[1]) && $timeleft > 0);
|
||||
|
||||
if ($timeleft <= 0) {
|
||||
proc_terminate($process);
|
||||
throw new Exception("command timeout on: " . $cmd);
|
||||
} else {
|
||||
return $output;
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Retrieve the physical filename of the preview image on disk
|
||||
*
|
||||
* @param object $object document content or document file
|
||||
* @param integer $width width of preview image
|
||||
* @return string file name of preview image
|
||||
*/
|
||||
protected function getFileName($object, $width) { /* }}} */
|
||||
if(!$object)
|
||||
return false;
|
||||
|
||||
$document = $object->getDocument();
|
||||
$dir = $this->previewDir.'/'.$document->getDir();
|
||||
switch(get_class($object)) {
|
||||
case "SeedDMS_Core_DocumentContent":
|
||||
$target = $dir.'p'.$object->getVersion().'-'.$width;
|
||||
break;
|
||||
case "SeedDMS_Core_DocumentFile":
|
||||
$target = $dir.'f'.$object->getID().'-'.$width;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return $target;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Create a preview image for a given file
|
||||
*
|
||||
* @param string $infile name of input file including full path
|
||||
* @param string $dir directory relative to $this->previewDir
|
||||
* @param string $mimetype MimeType of input file
|
||||
* @param integer $width width of generated preview image
|
||||
* @return boolean true on success, false on failure
|
||||
*/
|
||||
public function createRawPreview($infile, $dir, $mimetype, $width=0, $target='') { /* {{{ */
|
||||
if($width == 0)
|
||||
$width = $this->width;
|
||||
else
|
||||
$width = intval($width);
|
||||
if(!$this->previewDir)
|
||||
return false;
|
||||
if(!is_dir($this->previewDir.'/'.$dir)) {
|
||||
if (!SeedDMS_Core_File::makeDir($this->previewDir.'/'.$dir)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(!file_exists($infile))
|
||||
return false;
|
||||
if(!$target)
|
||||
$target = $this->previewDir.$dir.md5($infile).'-'.$width;
|
||||
if($target != '' && (!file_exists($target.'.png') || filectime($target.'.png') < filectime($infile))) {
|
||||
$cmd = '';
|
||||
switch($mimetype) {
|
||||
case "image/png":
|
||||
case "image/gif":
|
||||
case "image/jpeg":
|
||||
case "image/jpg":
|
||||
case "image/svg+xml":
|
||||
$cmd = 'convert -resize '.$width.'x '.$infile.' '.$target.'.png';
|
||||
break;
|
||||
case "application/pdf":
|
||||
case "application/postscript":
|
||||
$cmd = 'convert -density 100 -resize '.$width.'x '.$infile.'[0] '.$target.'.png';
|
||||
break;
|
||||
case "text/plain":
|
||||
$cmd = 'convert -resize '.$width.'x '.$infile.'[0] '.$target.'.png';
|
||||
break;
|
||||
case "application/x-compressed-tar":
|
||||
$cmd = 'tar tzvf '.$infile.' | convert -density 100 -resize '.$width.'x text:-[0] '.$target.'.png';
|
||||
break;
|
||||
}
|
||||
if($cmd) {
|
||||
//exec($cmd);
|
||||
try {
|
||||
self::execWithTimeout($cmd, $this->timeout);
|
||||
} catch(Exception $e) {
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
|
||||
} /* }}} */
|
||||
|
||||
public function createPreview($object, $width=0) { /* {{{ */
|
||||
if(!$object)
|
||||
return false;
|
||||
|
||||
if($width == 0)
|
||||
$width = $this->width;
|
||||
else
|
||||
$width = intval($width);
|
||||
$document = $object->getDocument();
|
||||
$file = $document->_dms->contentDir.$object->getPath();
|
||||
$target = $this->getFileName($object, $width);
|
||||
return $this->createRawPreview($file, $document->getDir(), $object->getMimeType(), $width, $target);
|
||||
|
||||
if($width == 0)
|
||||
$width = $this->width;
|
||||
else
|
||||
$width = intval($width);
|
||||
if(!$this->previewDir)
|
||||
return false;
|
||||
$document = $object->getDocument();
|
||||
$dir = $this->previewDir.'/'.$document->getDir();
|
||||
if(!is_dir($dir)) {
|
||||
if (!SeedDMS_Core_File::makeDir($dir)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$file = $document->_dms->contentDir.$object->getPath();
|
||||
if(!file_exists($file))
|
||||
return false;
|
||||
$target = $this->getFileName($object, $width);
|
||||
if($target !== false && (!file_exists($target.'.png') || filectime($target.'.png') < $object->getDate())) {
|
||||
$cmd = '';
|
||||
switch($object->getMimeType()) {
|
||||
case "image/png":
|
||||
case "image/gif":
|
||||
case "image/jpeg":
|
||||
case "image/jpg":
|
||||
case "image/svg+xml":
|
||||
$cmd = 'convert -resize '.$width.'x '.$file.' '.$target.'.png';
|
||||
break;
|
||||
case "application/pdf":
|
||||
case "application/postscript":
|
||||
$cmd = 'convert -density 100 -resize '.$width.'x '.$file.'[0] '.$target.'.png';
|
||||
break;
|
||||
case "text/plain":
|
||||
$cmd = 'convert -resize '.$width.'x '.$file.'[0] '.$target.'.png';
|
||||
break;
|
||||
case "application/x-compressed-tar":
|
||||
$cmd = 'tar tzvf '.$file.' | convert -density 100 -resize '.$width.'x text:-[0] '.$target.'.png';
|
||||
break;
|
||||
}
|
||||
if($cmd) {
|
||||
//exec($cmd);
|
||||
try {
|
||||
self::execWithTimeout($cmd, $this->timeout);
|
||||
} catch(Exception $e) {
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
|
||||
} /* }}} */
|
||||
|
||||
public function hasRawPreview($infile, $dir, $width=0) { /* {{{ */
|
||||
if($width == 0)
|
||||
$width = $this->width;
|
||||
else
|
||||
$width = intval($width);
|
||||
if(!$this->previewDir)
|
||||
return false;
|
||||
$target = $this->previewDir.$dir.md5($infile).'-'.$width;
|
||||
if($target !== false && file_exists($target.'.png') && filectime($target.'.png') >= filectime($infile)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} /* }}} */
|
||||
|
||||
public function hasPreview($object, $width=0) { /* {{{ */
|
||||
if(!$object)
|
||||
return false;
|
||||
|
||||
if($width == 0)
|
||||
$width = $this->width;
|
||||
else
|
||||
$width = intval($width);
|
||||
if(!$this->previewDir)
|
||||
return false;
|
||||
$target = $this->getFileName($object, $width);
|
||||
if($target !== false && file_exists($target.'.png') && filectime($target.'.png') >= $object->getDate()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} /* }}} */
|
||||
|
||||
public function getRawPreview($infile, $dir, $width=0) { /* {{{ */
|
||||
if($width == 0)
|
||||
$width = $this->width;
|
||||
else
|
||||
$width = intval($width);
|
||||
if(!$this->previewDir)
|
||||
return false;
|
||||
|
||||
$target = $this->previewDir.$dir.md5($infile).'-'.$width;
|
||||
if($target && file_exists($target.'.png')) {
|
||||
readfile($target.'.png');
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
public function getPreview($object, $width=0) { /* {{{ */
|
||||
if($width == 0)
|
||||
$width = $this->width;
|
||||
else
|
||||
$width = intval($width);
|
||||
if(!$this->previewDir)
|
||||
return false;
|
||||
|
||||
$target = $this->getFileName($object, $width);
|
||||
if($target && file_exists($target.'.png')) {
|
||||
readfile($target.'.png');
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
public function getFilesize($object, $width=0) { /* {{{ */
|
||||
if($width == 0)
|
||||
$width = $this->width;
|
||||
else
|
||||
$width = intval($width);
|
||||
$target = $this->getFileName($object, $width);
|
||||
if($target && file_exists($target.'.png')) {
|
||||
return(filesize($target.'.png'));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
} /* }}} */
|
||||
|
||||
|
||||
public function deletePreview($document, $object, $width=0) { /* {{{ */
|
||||
if($width == 0)
|
||||
$width = $this->width;
|
||||
else
|
||||
$width = intval($width);
|
||||
if(!$this->previewDir)
|
||||
return false;
|
||||
|
||||
$target = $this->getFileName($object, $width);
|
||||
} /* }}} */
|
||||
}
|
||||
?>
|
168
SeedDMS_Preview/package.xml
Normal file
168
SeedDMS_Preview/package.xml
Normal file
|
@ -0,0 +1,168 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<package packagerversion="1.8.1" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
|
||||
<name>SeedDMS_Preview</name>
|
||||
<channel>pear.php.net</channel>
|
||||
<summary>Create thumbnails from document content for SeedDMS</summary>
|
||||
<description>SeedDMS is a web based document management system (DMS). These
|
||||
are the classes to create preview images from the document content.</description>
|
||||
<lead>
|
||||
<name>Uwe Steinmann</name>
|
||||
<user>steinm</user>
|
||||
<email>uwe@steinmann.cx</email>
|
||||
<active>yes</active>
|
||||
</lead>
|
||||
<date>2016-03-08</date>
|
||||
<time>09:36:57</time>
|
||||
<version>
|
||||
<release>1.1.6</release>
|
||||
<api>1.1.6</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
check if object passed to createPreview(), hasPreview() is not null
|
||||
</notes>
|
||||
<contents>
|
||||
<dir baseinstalldir="SeedDMS" name="/">
|
||||
<dir name="Preview">
|
||||
<file name="Previewer.php" role="php">
|
||||
<tasks:replace from="@package_version@" to="version" type="package-info" />
|
||||
</file>
|
||||
</dir> <!-- /Lucene -->
|
||||
<dir name="tests">
|
||||
</dir> <!-- /tests -->
|
||||
<file name="Preview.php" role="php">
|
||||
<tasks:replace from="@package_version@" to="version" type="package-info" />
|
||||
</file>
|
||||
</dir> <!-- / -->
|
||||
</contents>
|
||||
<dependencies>
|
||||
<required>
|
||||
<php>
|
||||
<min>4.3.0</min>
|
||||
</php>
|
||||
<pearinstaller>
|
||||
<min>1.5.4</min>
|
||||
</pearinstaller>
|
||||
</required>
|
||||
</dependencies>
|
||||
<phprelease />
|
||||
<changelog>
|
||||
<release>
|
||||
<date>2012-11-20</date>
|
||||
<time>08:05:38</time>
|
||||
<version>
|
||||
<release>1.0.0</release>
|
||||
<api>1.0.0</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
initial version
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2013-04-29</date>
|
||||
<time>19:34:07</time>
|
||||
<version>
|
||||
<release>1.1.0</release>
|
||||
<api>1.1.0</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
preview image can also be created from a document file (SeedDMS_Core_DocumentFile)
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2014-03-18</date>
|
||||
<time>16:34:59</time>
|
||||
<version>
|
||||
<release>1.1.1</release>
|
||||
<api>1.1.0</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
add converters for .tar.gz, .ps, .txt
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2014-04-10</date>
|
||||
<time>20:29:39</time>
|
||||
<version>
|
||||
<release>1.1.2</release>
|
||||
<api>1.1.0</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
create fixed width image with proportional height
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2015-02-13</date>
|
||||
<time>20:29:39</time>
|
||||
<version>
|
||||
<release>1.1.3</release>
|
||||
<api>1.1.0</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
preview images will also be recreated if the object this image belongs is of newer date than the image itself. This happens if versions are being deleted and than a new version is uploaded. Because the new version will get the version number of the old version, it will also take over the old preview image.Comparing the creation date of the image with the object detects this case.
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2015-08-08</date>
|
||||
<time>09:36:57</time>
|
||||
<version>
|
||||
<release>1.1.4</release>
|
||||
<api>1.1.0</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
command for creating the preview will be called with a given timeout
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2016-02-11</date>
|
||||
<time>09:36:57</time>
|
||||
<version>
|
||||
<release>1.1.5</release>
|
||||
<api>1.1.5</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
add method getFilesize()
|
||||
timeout for external commands can be passed to contructor of SeedDMS_Preview_Previewer
|
||||
</notes>
|
||||
</release>
|
||||
</changelog>
|
||||
</package>
|
0
SeedDMS_Preview/tests/Preview.php
Normal file
0
SeedDMS_Preview/tests/Preview.php
Normal file
44
SeedDMS_SQLiteFTS/SQLiteFTS.php
Normal file
44
SeedDMS_SQLiteFTS/SQLiteFTS.php
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
// SeedDMS. Document Management System
|
||||
// Copyright (C) 2011-2015 Uwe Steinmann
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
/**
|
||||
* @uses SeedDMS_SQLiteFTS_Indexer
|
||||
*/
|
||||
require_once('SQLiteFTS/Indexer.php');
|
||||
|
||||
/**
|
||||
* @uses SeedDMS_SQLiteFTS_Search
|
||||
*/
|
||||
require_once('SQLiteFTS/Search.php');
|
||||
|
||||
/**
|
||||
* @uses SeedDMS_SQLiteFTS_Term
|
||||
*/
|
||||
require_once('SQLiteFTS/Term.php');
|
||||
|
||||
/**
|
||||
* @uses SeedDMS_SQLiteFTS_QueryHit
|
||||
*/
|
||||
require_once('SQLiteFTS/QueryHit.php');
|
||||
|
||||
/**
|
||||
* @uses SeedDMS_SQLiteFTS_IndexedDocument
|
||||
*/
|
||||
require_once('SQLiteFTS/IndexedDocument.php');
|
||||
|
||||
?>
|
65
SeedDMS_SQLiteFTS/SQLiteFTS/Document.php
Normal file
65
SeedDMS_SQLiteFTS/SQLiteFTS/Document.php
Normal file
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of a document
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_SQLiteFTS
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010, Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Class for managing a document.
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_SQLiteFTS
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2011, Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_SQLiteFTS_Document {
|
||||
|
||||
/**
|
||||
* @var integer $id id of document
|
||||
* @access protected
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @var array $fields fields
|
||||
* @access protected
|
||||
*/
|
||||
protected $fields;
|
||||
|
||||
public function __get($key) { /* {{{ */
|
||||
if(isset($this->fields[$key]))
|
||||
return $this->fields[$key];
|
||||
else
|
||||
return false;
|
||||
} /* }}} */
|
||||
|
||||
public function addField($key, $value) { /* {{{ */
|
||||
if($key == 'document_id') {
|
||||
$this->id = $this->fields[$key] = (int) $value;
|
||||
} else {
|
||||
if(isset($this->fields[$key]))
|
||||
$this->fields[$key] .= ' '.$value;
|
||||
else
|
||||
$this->fields[$key] = $value;
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
public function getFieldValue($key) { /* {{{ */
|
||||
if(isset($this->fields[$key]))
|
||||
return $this->fields[$key];
|
||||
else
|
||||
return false;
|
||||
} /* }}} */
|
||||
|
||||
}
|
||||
?>
|
141
SeedDMS_SQLiteFTS/SQLiteFTS/IndexedDocument.php
Normal file
141
SeedDMS_SQLiteFTS/SQLiteFTS/IndexedDocument.php
Normal file
|
@ -0,0 +1,141 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of an indexed document
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_SQLiteFTS
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010, Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @uses SeedDMS_SQLiteFTS_Document
|
||||
*/
|
||||
require_once('Document.php');
|
||||
|
||||
|
||||
/**
|
||||
* Class for managing an indexed document.
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_SQLiteFTS
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2011, Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_SQLiteFTS_IndexedDocument extends SeedDMS_SQLiteFTS_Document {
|
||||
|
||||
static function execWithTimeout($cmd, $timeout=2) { /* {{{ */
|
||||
$descriptorspec = array(
|
||||
0 => array("pipe", "r"),
|
||||
1 => array("pipe", "w"),
|
||||
2 => array("pipe", "w")
|
||||
);
|
||||
$pipes = array();
|
||||
|
||||
$timeout += time();
|
||||
$process = proc_open($cmd, $descriptorspec, $pipes);
|
||||
if (!is_resource($process)) {
|
||||
throw new Exception("proc_open failed on: " . $cmd);
|
||||
}
|
||||
|
||||
$output = '';
|
||||
do {
|
||||
$timeleft = $timeout - time();
|
||||
$read = array($pipes[1]);
|
||||
stream_select($read, $write = NULL, $exeptions = NULL, $timeleft, NULL);
|
||||
|
||||
if (!empty($read)) {
|
||||
$output .= fread($pipes[1], 8192);
|
||||
}
|
||||
} while (!feof($pipes[1]) && $timeleft > 0);
|
||||
|
||||
if ($timeleft <= 0) {
|
||||
proc_terminate($process);
|
||||
throw new Exception("command timeout on: " . $cmd);
|
||||
} else {
|
||||
return $output;
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Constructor. Creates our indexable document and adds all
|
||||
* necessary fields to it using the passed in document
|
||||
*/
|
||||
public function __construct($dms, $document, $convcmd=null, $nocontent=false, $timeout=5) {
|
||||
$_convcmd = array(
|
||||
'application/pdf' => 'pdftotext -enc UTF-8 -nopgbrk %s - |sed -e \'s/ [a-zA-Z0-9.]\{1\} / /g\' -e \'s/[0-9.]//g\'',
|
||||
'application/postscript' => 'ps2pdf14 %s - | pdftotext -enc UTF-8 -nopgbrk - - | sed -e \'s/ [a-zA-Z0-9.]\{1\} / /g\' -e \'s/[0-9.]//g\'',
|
||||
'application/msword' => 'catdoc %s',
|
||||
'application/vnd.ms-excel' => 'ssconvert -T Gnumeric_stf:stf_csv -S %s fd://1',
|
||||
'audio/mp3' => "id3 -l -R %s | egrep '(Title|Artist|Album)' | sed 's/^[^:]*: //g'",
|
||||
'audio/mpeg' => "id3 -l -R %s | egrep '(Title|Artist|Album)' | sed 's/^[^:]*: //g'",
|
||||
'text/plain' => 'cat %s',
|
||||
);
|
||||
if($convcmd) {
|
||||
$_convcmd = $convcmd;
|
||||
}
|
||||
|
||||
$version = $document->getLatestContent();
|
||||
$this->addField('document_id', $document->getID());
|
||||
if($version) {
|
||||
$this->addField('mimetype', $version->getMimeType());
|
||||
$this->addField('origfilename', $version->getOriginalFileName());
|
||||
if(!$nocontent)
|
||||
$this->addField('created', $version->getDate(), 'unindexed');
|
||||
if($attributes = $version->getAttributes()) {
|
||||
foreach($attributes as $attribute) {
|
||||
$attrdef = $attribute->getAttributeDefinition();
|
||||
if($attrdef->getValueSet() != '')
|
||||
$this->addField('attr_'.str_replace(' ', '_', $attrdef->getName()), $attribute->getValue());
|
||||
else
|
||||
$this->addField('attr_'.str_replace(' ', '_', $attrdef->getName()), $attribute->getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->addField('title', $document->getName());
|
||||
if($categories = $document->getCategories()) {
|
||||
$names = array();
|
||||
foreach($categories as $cat) {
|
||||
$names[] = $cat->getName();
|
||||
}
|
||||
$this->addField('category', implode(' ', $names));
|
||||
}
|
||||
if($attributes = $document->getAttributes()) {
|
||||
foreach($attributes as $attribute) {
|
||||
$attrdef = $attribute->getAttributeDefinition();
|
||||
if($attrdef->getValueSet() != '')
|
||||
$this->addField('attr_'.str_replace(' ', '_', $attrdef->getName()), $attribute->getValue());
|
||||
else
|
||||
$this->addField('attr_'.str_replace(' ', '_', $attrdef->getName()), $attribute->getValue());
|
||||
}
|
||||
}
|
||||
|
||||
$owner = $document->getOwner();
|
||||
$this->addField('owner', $owner->getLogin());
|
||||
if($keywords = $document->getKeywords()) {
|
||||
$this->addField('keywords', $keywords);
|
||||
}
|
||||
if($comment = $document->getComment()) {
|
||||
$this->addField('comment', $comment);
|
||||
}
|
||||
if($version && !$nocontent) {
|
||||
$path = $dms->contentDir . $version->getPath();
|
||||
$content = '';
|
||||
$fp = null;
|
||||
$mimetype = $version->getMimeType();
|
||||
if(isset($_convcmd[$mimetype])) {
|
||||
$cmd = sprintf($_convcmd[$mimetype], $path);
|
||||
$content = self::execWithTimeout($cmd, $timeout);
|
||||
if($content) {
|
||||
$this->addField('content', $content, 'unstored');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
260
SeedDMS_SQLiteFTS/SQLiteFTS/Indexer.php
Normal file
260
SeedDMS_SQLiteFTS/SQLiteFTS/Indexer.php
Normal file
|
@ -0,0 +1,260 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of SQLiteFTS index
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Lucene
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010, Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Class for managing a SQLiteFTS index.
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Lucene
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2011, Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_SQLiteFTS_Indexer {
|
||||
/**
|
||||
* @var object $index sqlite index
|
||||
* @access protected
|
||||
*/
|
||||
protected $_conn;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
*/
|
||||
function __construct($indexerDir) { /* {{{ */
|
||||
$this->_conn = new PDO('sqlite:'.$indexerDir.'/index.db');
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Open an existing index
|
||||
*
|
||||
* @param string $indexerDir directory on disk containing the index
|
||||
*/
|
||||
static function open($indexerDir) { /* {{{ */
|
||||
if(file_exists($indexerDir.'/index.db')) {
|
||||
return new SeedDMS_SQLiteFTS_Indexer($indexerDir);
|
||||
} else
|
||||
return self::create($indexerDir);
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Create a new index
|
||||
*
|
||||
* @param string $indexerDir directory on disk containing the index
|
||||
*/
|
||||
static function create($indexerDir) { /* {{{ */
|
||||
if(file_exists($indexerDir.'/index.db'))
|
||||
unlink($indexerDir.'/index.db');
|
||||
$index = new SeedDMS_SQLiteFTS_Indexer($indexerDir);
|
||||
/* Make sure the sequence of fields is identical to the field list
|
||||
* in SeedDMS_SQLiteFTS_Term
|
||||
*/
|
||||
$version = SQLite3::version();
|
||||
if($version['versionNumber'] >= 3008000)
|
||||
$sql = 'CREATE VIRTUAL TABLE docs USING fts4(title, comment, keywords, category, mimetype, origfilename, owner, content, created, notindexed=created, matchinfo=fts3)';
|
||||
else
|
||||
$sql = 'CREATE VIRTUAL TABLE docs USING fts4(title, comment, keywords, category, mimetype, origfilename, owner, content, created, matchinfo=fts3)';
|
||||
$res = $index->_conn->exec($sql);
|
||||
if($res === false) {
|
||||
return null;
|
||||
}
|
||||
$sql = 'CREATE VIRTUAL TABLE docs_terms USING fts4aux(docs);';
|
||||
$res = $index->_conn->exec($sql);
|
||||
if($res === false) {
|
||||
return null;
|
||||
}
|
||||
return($index);
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Do some initialization
|
||||
*
|
||||
*/
|
||||
static function init($stopWordsFile='') { /* {{{ */
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Add document to index
|
||||
*
|
||||
* @param object $doc indexed document of class
|
||||
* SeedDMS_SQLiteFTS_IndexedDocument
|
||||
* @return boolean false in case of an error, otherwise true
|
||||
*/
|
||||
function addDocument($doc) { /* {{{ */
|
||||
if(!$this->_conn)
|
||||
return false;
|
||||
|
||||
$sql = "INSERT INTO docs (docid, title, comment, keywords, category, owner, content, mimetype, origfilename, created) VALUES(".$doc->getFieldValue('document_id').", ".$this->_conn->quote($doc->getFieldValue('title')).", ".$this->_conn->quote($doc->getFieldValue('comment')).", ".$this->_conn->quote($doc->getFieldValue('keywords')).", ".$this->_conn->quote($doc->getFieldValue('category')).", ".$this->_conn->quote($doc->getFieldValue('owner')).", ".$this->_conn->quote($doc->getFieldValue('content')).", ".$this->_conn->quote($doc->getFieldValue('mimetype')).", ".$this->_conn->quote($doc->getFieldValue('origfilename')).", ".time().")";
|
||||
$res = $this->_conn->exec($sql);
|
||||
if($res === false) {
|
||||
var_dump($this->_conn->errorInfo());
|
||||
}
|
||||
return $res;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Remove document from index
|
||||
*
|
||||
* @param object $doc indexed document of class
|
||||
* SeedDMS_SQLiteFTS_IndexedDocument
|
||||
* @return boolean false in case of an error, otherwise true
|
||||
*/
|
||||
public function delete($id) { /* {{{ */
|
||||
if(!$this->_conn)
|
||||
return false;
|
||||
|
||||
$sql = "DELETE FROM docs WHERE docid=".(int) $id;
|
||||
$res = $this->_conn->exec($sql);
|
||||
return $res;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Check if document was deleted
|
||||
*
|
||||
* Just for compatibility with lucene.
|
||||
*
|
||||
* @return boolean always false
|
||||
*/
|
||||
public function isDeleted($id) { /* {{{ */
|
||||
return false;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Find documents in index
|
||||
*
|
||||
* @param object $doc indexed document of class
|
||||
* SeedDMS_SQLiteFTS_IndexedDocument
|
||||
* @return boolean false in case of an error, otherwise true
|
||||
*/
|
||||
public function find($query) { /* {{{ */
|
||||
if(!$this->_conn)
|
||||
return false;
|
||||
|
||||
$sql = "SELECT docid FROM docs WHERE docs MATCH ".$this->_conn->quote($query);
|
||||
$res = $this->_conn->query($sql);
|
||||
$hits = array();
|
||||
if($res) {
|
||||
foreach($res as $rec) {
|
||||
$hit = new SeedDMS_SQLiteFTS_QueryHit($this);
|
||||
$hit->id = $rec['docid'];
|
||||
$hits[] = $hit;
|
||||
}
|
||||
}
|
||||
return $hits;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Get a single document from index
|
||||
*
|
||||
* @param integer $id id of document
|
||||
* @return boolean false in case of an error, otherwise true
|
||||
*/
|
||||
public function findById($id) { /* {{{ */
|
||||
if(!$this->_conn)
|
||||
return false;
|
||||
|
||||
$sql = "SELECT docid FROM docs WHERE docid=".(int) $id;
|
||||
$res = $this->_conn->query($sql);
|
||||
$hits = array();
|
||||
if($res) {
|
||||
while($rec = $res->fetch(PDO::FETCH_ASSOC)) {
|
||||
$hit = new SeedDMS_SQLiteFTS_QueryHit($this);
|
||||
$hit->id = $rec['docid'];
|
||||
$hits[] = $hit;
|
||||
}
|
||||
}
|
||||
return $hits;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Get a single document from index
|
||||
*
|
||||
* @param integer $id id of document
|
||||
* @return boolean false in case of an error, otherwise true
|
||||
*/
|
||||
public function getDocument($id) { /* {{{ */
|
||||
if(!$this->_conn)
|
||||
return false;
|
||||
|
||||
$sql = "SELECT title, comment, owner, keywords, category, mimetype, origfilename, created FROM docs WHERE docid=".(int) $id;
|
||||
$res = $this->_conn->query($sql);
|
||||
$doc = false;
|
||||
if($res) {
|
||||
$rec = $res->fetch(PDO::FETCH_ASSOC);
|
||||
$doc = new SeedDMS_SQLiteFTS_Document();
|
||||
$doc->addField('title', $rec['title']);
|
||||
$doc->addField('comment', $rec['comment']);
|
||||
$doc->addField('keywords', $rec['keywords']);
|
||||
$doc->addField('category', $rec['category']);
|
||||
$doc->addField('mimetype', $rec['mimetype']);
|
||||
$doc->addField('origfilename', $rec['origfilename']);
|
||||
$doc->addField('owner', $rec['owner']);
|
||||
$doc->addField('created', $rec['created']);
|
||||
}
|
||||
return $doc;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Return list of terms in index
|
||||
*
|
||||
* This function does nothing!
|
||||
*/
|
||||
public function terms() { /* {{{ */
|
||||
if(!$this->_conn)
|
||||
return false;
|
||||
|
||||
$sql = "SELECT term, col, occurrences FROM docs_terms WHERE col!='*' ORDER BY col";
|
||||
$res = $this->_conn->query($sql);
|
||||
$terms = array();
|
||||
if($res) {
|
||||
while($rec = $res->fetch(PDO::FETCH_ASSOC)) {
|
||||
$term = new SeedDMS_SQLiteFTS_Term($rec['term'], $rec['col'], $rec['occurrences']);
|
||||
$terms[] = $term;
|
||||
}
|
||||
}
|
||||
return $terms;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Return list of documents in index
|
||||
*
|
||||
*/
|
||||
public function count() { /* {{{ */
|
||||
$sql = "SELECT count(*) c FROM docs";
|
||||
$res = $this->_conn->query($sql);
|
||||
if($res) {
|
||||
$rec = $res->fetch(PDO::FETCH_ASSOC);
|
||||
return $rec['c'];
|
||||
}
|
||||
return 0;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Commit changes
|
||||
*
|
||||
* This function does nothing!
|
||||
*/
|
||||
function commit() { /* {{{ */
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Optimize index
|
||||
*
|
||||
* This function does nothing!
|
||||
*/
|
||||
function optimize() { /* {{{ */
|
||||
} /* }}} */
|
||||
}
|
||||
?>
|
65
SeedDMS_SQLiteFTS/SQLiteFTS/QueryHit.php
Normal file
65
SeedDMS_SQLiteFTS/SQLiteFTS/QueryHit.php
Normal file
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of a query hit
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_SQLiteFTS
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010, Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Class for managing a query hit.
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_SQLiteFTS
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2011, Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_SQLiteFTS_QueryHit {
|
||||
|
||||
/**
|
||||
* @var SeedDMS_SQliteFTS_Indexer $index
|
||||
* @access protected
|
||||
*/
|
||||
protected $_index;
|
||||
|
||||
/**
|
||||
* @var SeedDMS_SQliteFTS_Document $document
|
||||
* @access protected
|
||||
*/
|
||||
protected $_document;
|
||||
|
||||
/**
|
||||
* @var integer $id id of document
|
||||
* @access public
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct(SeedDMS_SQLiteFTS_Indexer $index) { /* {{{ */
|
||||
$this->_index = $index;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Return the document associated with this hit
|
||||
*
|
||||
* @return SeedDMS_SQLiteFTS_Document
|
||||
*/
|
||||
public function getDocument() { /* {{{ */
|
||||
if (!$this->_document instanceof SeedDMS_SQLiteFTS_Document) {
|
||||
$this->_document = $this->_index->getDocument($this->id);
|
||||
}
|
||||
|
||||
return $this->_document;
|
||||
} /* }}} */
|
||||
}
|
||||
?>
|
96
SeedDMS_SQLiteFTS/SQLiteFTS/Search.php
Normal file
96
SeedDMS_SQLiteFTS/SQLiteFTS/Search.php
Normal file
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of search in SQlite FTS index
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Lucene
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010, Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Class for searching in a SQlite FTS index.
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Lucene
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2011, Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_SQliteFTS_Search {
|
||||
/**
|
||||
* @var object $index SQlite FTS index
|
||||
* @access protected
|
||||
*/
|
||||
protected $index;
|
||||
|
||||
/**
|
||||
* Create a new instance of the search
|
||||
*
|
||||
* @param object $index SQlite FTS index
|
||||
* @return object instance of SeedDMS_SQliteFTS_Search
|
||||
*/
|
||||
function __construct($index) { /* {{{ */
|
||||
$this->index = $index;
|
||||
$this->version = '@package_version@';
|
||||
if($this->version[0] == '@')
|
||||
$this->version = '3.0.0';
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Get hit from index
|
||||
*
|
||||
* @param object $index lucene index
|
||||
* @return object instance of SeedDMS_Lucene_Document of false
|
||||
*/
|
||||
function getDocument($id) { /* {{{ */
|
||||
$hits = $this->index->findById((int) $id);
|
||||
return $hits ? $hits[0] : false;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Search in index
|
||||
*
|
||||
* @param object $index SQlite FTS index
|
||||
* @return object instance of SeedDMS_Lucene_Search
|
||||
*/
|
||||
function search($term, $owner, $status='', $categories=array(), $fields=array()) { /* {{{ */
|
||||
$querystr = '';
|
||||
if($fields) {
|
||||
} else {
|
||||
if($term)
|
||||
$querystr .= trim($term);
|
||||
}
|
||||
if($owner) {
|
||||
if($querystr)
|
||||
$querystr .= ' ';
|
||||
//$querystr .= ' AND ';
|
||||
$querystr .= 'owner:'.$owner;
|
||||
//$querystr .= $owner;
|
||||
}
|
||||
if($categories) {
|
||||
if($querystr)
|
||||
$querystr .= ' ';
|
||||
//$querystr .= ' AND ';
|
||||
$querystr .= 'category:';
|
||||
$querystr .= implode(' OR category:', $categories);
|
||||
$querystr .= '';
|
||||
}
|
||||
try {
|
||||
$hits = $this->index->find($querystr);
|
||||
$recs = array();
|
||||
foreach($hits as $hit) {
|
||||
$recs[] = array('id'=>$hit->id, 'document_id'=>$hit->id);
|
||||
}
|
||||
return $recs;
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
} /* }}} */
|
||||
}
|
||||
?>
|
66
SeedDMS_SQLiteFTS/SQLiteFTS/Term.php
Normal file
66
SeedDMS_SQLiteFTS/SQLiteFTS/Term.php
Normal file
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of a term
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_SQLiteFTS
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010, Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Class for managing a term.
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_SQLiteFTS
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2011, Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_SQLiteFTS_Term {
|
||||
|
||||
/**
|
||||
* @var string $text
|
||||
* @access public
|
||||
*/
|
||||
public $text;
|
||||
|
||||
/**
|
||||
* @var string $field
|
||||
* @access public
|
||||
*/
|
||||
public $field;
|
||||
|
||||
/**
|
||||
* @var integer $occurrence
|
||||
* @access public
|
||||
*/
|
||||
public $_occurrence;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct($term, $col, $occurrence) { /* {{{ */
|
||||
$this->text = $term;
|
||||
$fields = array(
|
||||
0 => 'title',
|
||||
1 => 'comment',
|
||||
2 => 'keywords',
|
||||
3 => 'category',
|
||||
4 => 'mimetype',
|
||||
5 => 'origfilename',
|
||||
6 => 'owner',
|
||||
7 => 'content',
|
||||
8 => 'created'
|
||||
);
|
||||
$this->field = $fields[$col];
|
||||
$this->_occurrence = $occurrence;
|
||||
} /* }}} */
|
||||
|
||||
}
|
||||
?>
|
134
SeedDMS_SQLiteFTS/package.xml
Normal file
134
SeedDMS_SQLiteFTS/package.xml
Normal file
|
@ -0,0 +1,134 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<package packagerversion="1.8.1" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
|
||||
<name>SeedDMS_SQLiteFTS</name>
|
||||
<channel>pear.php.net</channel>
|
||||
<summary>Fulltext search based on sqlite for SeedDMS</summary>
|
||||
<description>SeedDMS is a web based document management system (DMS). This is
|
||||
the fulltext search engine for it, based on SQLite FTS.</description>
|
||||
<lead>
|
||||
<name>Uwe Steinmann</name>
|
||||
<user>steinm</user>
|
||||
<email>uwe@steinmann.cx</email>
|
||||
<active>yes</active>
|
||||
</lead>
|
||||
<date>2016-03-15</date>
|
||||
<time>15:59:07</time>
|
||||
<version>
|
||||
<release>1.0.4</release>
|
||||
<api>1.0.1</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
make it work with sqlite3 < 3.8.0
|
||||
</notes>
|
||||
<contents>
|
||||
<dir baseinstalldir="SeedDMS" name="/">
|
||||
<dir name="SQLiteFTS">
|
||||
<file name="Indexer.php" role="php">
|
||||
<tasks:replace from="@package_version@" to="version" type="package-info" />
|
||||
</file>
|
||||
<file name="IndexedDocument.php" role="php">
|
||||
<tasks:replace from="@package_version@" to="version" type="package-info" />
|
||||
</file>
|
||||
<file name="Document.php" role="php">
|
||||
<tasks:replace from="@package_version@" to="version" type="package-info" />
|
||||
</file>
|
||||
<file name="QueryHit.php" role="php">
|
||||
<tasks:replace from="@package_version@" to="version" type="package-info" />
|
||||
</file>
|
||||
<file name="Search.php" role="php">
|
||||
<tasks:replace from="@package_version@" to="version" type="package-info" />
|
||||
</file>
|
||||
<file name="Term.php" role="php">
|
||||
<tasks:replace from="@package_version@" to="version" type="package-info" />
|
||||
</file>
|
||||
</dir> <!-- /SQLiteFTS -->
|
||||
<dir name="tests">
|
||||
</dir> <!-- /tests -->
|
||||
<file name="SQLiteFTS.php" role="php">
|
||||
<tasks:replace from="@package_version@" to="version" type="package-info" />
|
||||
</file>
|
||||
</dir> <!-- / -->
|
||||
</contents>
|
||||
<dependencies>
|
||||
<required>
|
||||
<php>
|
||||
<min>4.3.0</min>
|
||||
</php>
|
||||
<pearinstaller>
|
||||
<min>1.5.4</min>
|
||||
</pearinstaller>
|
||||
</required>
|
||||
</dependencies>
|
||||
<phprelease />
|
||||
<changelog>
|
||||
<release>
|
||||
<date>2015-08-10</date>
|
||||
<time>21:13:13</time>
|
||||
<version>
|
||||
<release>1.0.0</release>
|
||||
<api>1.0.0</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
initial release
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2015-11-16</date>
|
||||
<time>09:07:07</time>
|
||||
<version>
|
||||
<release>1.0.1</release>
|
||||
<api>1.0.1</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
add __get() to SQLiteFTS_Document because class.IndexInfo.php access class variable title which doesn't exists
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2016-01-10</date>
|
||||
<time>09:07:07</time>
|
||||
<version>
|
||||
<release>1.0.2</release>
|
||||
<api>1.0.1</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
check if index exists before removing it when creating a new one
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2016-02-01</date>
|
||||
<time>09:15:01</time>
|
||||
<version>
|
||||
<release>1.0.3</release>
|
||||
<api>1.0.1</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
add command for indexing postѕcript files
|
||||
</notes>
|
||||
</release>
|
||||
</changelog>
|
||||
</package>
|
0
SeedDMS_SQLiteFTS/tests/Index.php
Normal file
0
SeedDMS_SQLiteFTS/tests/Index.php
Normal file
28
TODO
28
TODO
|
@ -1,14 +1,22 @@
|
|||
This list is hopelessly outdated, but some of the issues are
|
||||
still worth to be implemented!
|
||||
Show workflow steps after document has been released (keep workflow tab)
|
||||
|
||||
Show documents in calendar when they where uploaded.
|
||||
|
||||
Add attribute type 'date'
|
||||
|
||||
Update comment and date of a review/approval, if the same status is set
|
||||
again. Currently setting the same status is turned of, because it didn't
|
||||
have any effect, which is quite confusing if the user can do an operation
|
||||
which has not the expected result.
|
||||
|
||||
Show number of documents that needs care (approval, review, any other action
|
||||
in a workflog) next to Login/Logout-Menu.
|
||||
|
||||
Show message on doc info page if documents expects an action like review,
|
||||
approval, etc.
|
||||
|
||||
Import and export of a workflow as xml.
|
||||
|
||||
Find a way to make the workflows adjustable when used for a document.
|
||||
e.g. a workflow shall be used for a number of document but the users of
|
||||
a transtion has to be altered for each document. This is basically reusing
|
||||
|
@ -23,13 +31,26 @@ the session data. See op.Login.php and op.Logout.php
|
|||
|
||||
Allow to specify fine grained notification (e.g. deleting a document, folder)
|
||||
|
||||
Have access rights depending on document status. This will allow to
|
||||
restrict access when a document is in a workflow or has been rejected.
|
||||
|
||||
There are still global variable in class SeedetoDMS_Bootstrap_Style
|
||||
|
||||
Settings::searchConfigFilePath() and Settings::getConfigDir() use different
|
||||
approaches to get the configuration directory.
|
||||
|
||||
Show expiration status of documents in document list
|
||||
|
||||
Export/Import content as xml (even for subfolders)
|
||||
|
||||
Copy folders recursivly
|
||||
|
||||
Allow operations like delete, move, approve, etc. on a list of documents
|
||||
|
||||
Upload of multiple documents without an applet
|
||||
|
||||
Do not show documents which are not reviewed or approved or rejected
|
||||
|
||||
installation script:
|
||||
- user simply unpack the tar.gz in a server folder and access that folder
|
||||
- on startup if there are installation problems php automatically run the configuration script
|
||||
|
@ -49,6 +70,9 @@ Sometimes in the DB are written messages strings in plain language whose
|
|||
language depends on the current user and will never be translated.
|
||||
This can be avoided using only coded messages
|
||||
|
||||
The mail language is translated using the current user language but should use
|
||||
the receiver language (not easy).
|
||||
|
||||
In my Documents->all documents there should be two lists: one (the current) with
|
||||
the user's document, and another with the user's updated document (that's because
|
||||
one user could have updated a document not owned by himself)
|
||||
|
|
216
build.xml
216
build.xml
|
@ -1,216 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="seeddms" basedir="." default="main">
|
||||
<property name="tmp" value="/tmp" />
|
||||
<property name="package" value="${phing.project.name}" override="true" />
|
||||
<property name="seeddmsurl" value="http://localhost/seeddms51x" />
|
||||
<property name="builddir" value="${tmp}/build/${phing.project.name}" override="true" />
|
||||
<property name="srcdir" value="${project.basedir}" override="true" />
|
||||
<property name="datadir" value="" override="true" />
|
||||
<property name="dbtype" value="sqlite" override="true" />
|
||||
<property name="dbhost" value="" override="true" />
|
||||
<property name="dbuser" value="" override="true" />
|
||||
<property name="dbpass" value="" override="true" />
|
||||
<property name="dbname" value="" override="true" />
|
||||
<property name="version" value="-" />
|
||||
<property name="shortversion" value="${version}" />
|
||||
<propertyregex property="shortversion" subject="${version} kk" pattern="([56])\.([0-9]).*" replace="seeddms$1$2x" override="true"/>
|
||||
<property name="majorversion" value="${version}" />
|
||||
<propertyregex property="majorversion" subject="${version}" pattern="([56])\..*" replace="$1" override="true"/>
|
||||
<property name="composer_version" value="2.8.5" />
|
||||
<property name="composer_extra_params" value="" />
|
||||
<property name="composer_env" value="" />
|
||||
<property name="mink_driver" value="chrome" />
|
||||
<property name="snooze_multiplier" value="1" />
|
||||
|
||||
<fileset id="distfiles" dir=".">
|
||||
<include name="languages/**" />
|
||||
<include name="op/**" />
|
||||
<include name="out/**" />
|
||||
<include name="inc/**" />
|
||||
<include name="controllers/**" />
|
||||
<include name="styles/**" />
|
||||
<include name="views/bootstrap*/**" />
|
||||
<include name="utils/**" />
|
||||
<include name="doc/**" />
|
||||
<include name="webdav/**" />
|
||||
<include name="install/**" />
|
||||
<include name="restapi/**" />
|
||||
<include name="pdfviewer/**" />
|
||||
<include name="index.php" />
|
||||
<include name="CHANGELOG" />
|
||||
<include name=".htaccess" />
|
||||
<include name="LICENSE" />
|
||||
</fileset>
|
||||
|
||||
<target name="main">
|
||||
<echo>Hello</echo>
|
||||
</target>
|
||||
|
||||
<!-- PHP CodeSniffer -->
|
||||
<target name="phpcbf">
|
||||
<exec command="${srcdir}/vendor/bin/phpcbf --standard=${srcdir}/phpcs.xml" escape="false" passthru="true" checkreturn="true" />
|
||||
</target>
|
||||
<target name="phpcs">
|
||||
<exec command="${srcdir}/vendor/bin/phpcs --standard=${srcdir}/phpcs.xml --report=checkstyle > ${builddir}/reports/checkstyle.xml" escape="false" />
|
||||
</target>
|
||||
<target name="phpcs-console">
|
||||
<exec command="${srcdir}/vendor/bin/phpcs --standard=${srcdir}/phpcs.xml" escape="false" passthru="true" checkreturn="true" />
|
||||
</target>
|
||||
|
||||
<target name="php-cs-fixer-dryrun">
|
||||
<exec command="${srcdir}/vendor/bin/php-cs-fixer fix --dry-run -vvv --diff ${srcdir}/inc" passthru="true" escape="false" checkreturn="true" />
|
||||
</target>
|
||||
|
||||
<!-- PHPUnit -->
|
||||
<target name="phpunitfast" description="Run tests">
|
||||
<exec dir="${srcdir}/SeedDMS_Core" command="XDEBUG_MODE=coverage SEEDDMS_CORE_SQL=../install/create_tables-sqlite3.sql ${srcdir}/vendor/bin/phpunit --bootstrap ${srcdir}/SeedDMS_Core/bootstrap-${majorversion}.php --coverage-html ${srcdir}/coverage/" passthru="true" checkreturn="true" />
|
||||
<!-- exec dir="${srcdir}/tests" command="SEEDDMS_URL=${seeddmsurl} SEEDDMS_MINK_DRIVER=${mink_driver} SEEDDMS_SNOOZE_MULTIPLIER=${snooze_multiplier} ${srcdir}/vendor/bin/phpunit" passthru="true" checkreturn="true" / -->
|
||||
</target>
|
||||
|
||||
<target name="composer" description="Install dependencies with Composer">
|
||||
<if>
|
||||
<equals arg1="${composer_version}" arg2="latest-2.x" />
|
||||
<then>
|
||||
<httpget url="https://getcomposer.org/composer-2.phar" sslVerifyPeer="false" dir="${srcdir}" filename="composer.phar" />
|
||||
</then>
|
||||
<else>
|
||||
<if>
|
||||
<not><available file="composer.phar" /></not>
|
||||
<then>
|
||||
<httpget url="https://getcomposer.org/download/${composer_version}/composer.phar" sslVerifyPeer="false" dir="${srcdir}" />
|
||||
</then>
|
||||
</if>
|
||||
</else>
|
||||
</if>
|
||||
<echo message="Installing dependencies..." />
|
||||
<exec command="${composer_env} php ${srcdir}/composer.phar install ${composer_extra_params}" passthru="true" checkreturn="true" />
|
||||
</target>
|
||||
|
||||
<target name="dist" description="build SeedDMS tar archive">
|
||||
<if>
|
||||
<equals arg1="-" arg2="${version}" />
|
||||
<then><fail msg="Pass version as property 'version'" /></then>
|
||||
</if>
|
||||
|
||||
<echo msg="This is ${shortversion}" />
|
||||
|
||||
<delete file="./seeddms-${version}.tar.gz" failonerror="false" />
|
||||
<tar destfile="./seeddms-${version}.tar.gz" prefix="seeddms-${version}" compression="gzip">
|
||||
<fileset refid="distfiles" />
|
||||
</tar>
|
||||
</target>
|
||||
|
||||
<target name="package" description="build SeedDMS quickstart packages for distribution">
|
||||
<if>
|
||||
<equals arg1="-" arg2="${version}" />
|
||||
<then><fail msg="Pass version as property 'version'" /></then>
|
||||
</if>
|
||||
|
||||
<echo msg="This is ${shortversion}" />
|
||||
|
||||
<if>
|
||||
<matches string="${version}" pattern="^6\.0\..*" />
|
||||
<then><echo msg="This is version 6" /></then>
|
||||
<else><echo msg="This is version 5" /></else>
|
||||
</if>
|
||||
<!-- make sure the work area is empty, then rebuild it -->
|
||||
<delete dir="${builddir}/packages" includeemptydirs="true" failonerror="false" />
|
||||
<mkdir dir="${builddir}/packages" />
|
||||
<delete dir="${builddir}/export" includeemptydirs="true" failonerror="false" />
|
||||
<mkdir dir="${builddir}/export/${shortversion}" />
|
||||
<mkdir dir="${builddir}/export/${shortversion}/conf" />
|
||||
<mkdir dir="${builddir}/export/${shortversion}/data" />
|
||||
<mkdir dir="${builddir}/export/${shortversion}/data/1048576" />
|
||||
<mkdir dir="${builddir}/export/${shortversion}/data/log" />
|
||||
<mkdir dir="${builddir}/export/${shortversion}/data/cache" />
|
||||
<exec command="echo 'Signature: 8a477f597d28d172789f06886806bc55' > ${builddir}/export/${shortversion}/data/cache/CACHEDIR.TAG" />
|
||||
<exec command="echo '# This file is a cache directory tag created by seeddms.' >> ${builddir}/export/${shortversion}/data/cache/CACHEDIR.TAG" />
|
||||
<exec command="echo '# For information about cache directory tags, see: http://www.brynosaurus.com/cachedir/' >> ${builddir}/export/${shortversion}/data/cache/CACHEDIR.TAG" />
|
||||
<mkdir dir="${builddir}/export/${shortversion}/data/backup" />
|
||||
<mkdir dir="${builddir}/export/${shortversion}/data/lucene" />
|
||||
<mkdir dir="${builddir}/export/${shortversion}/data/staging" />
|
||||
<mkdir dir="${builddir}/export/${shortversion}/pear" />
|
||||
<mkdir dir="${builddir}/export/${shortversion}/www" />
|
||||
<mkdir dir="${builddir}/export/${shortversion}/www/ext" />
|
||||
<mkdir dir="${builddir}/export/${shortversion}/seeddms-${version}" />
|
||||
|
||||
<copy file="${srcdir}/conf/settings.xml.template" tofile="${builddir}/export/${shortversion}/conf/settings.xml">
|
||||
<filterchain>
|
||||
<replaceregexp>
|
||||
<regexp pattern="_DBC_DBTYPE_" replace="${dbtype}"/>
|
||||
<regexp pattern="_DBC_DBSERVER_" replace="${dbhost}"/>
|
||||
<regexp pattern="_DBC_DBNAME_" replace="${dbname}"/>
|
||||
<regexp pattern="_DBC_DBUSER_" replace="${dbuser}"/>
|
||||
<regexp pattern="_DBC_DBPASS_" replace="${dbpass}"/>
|
||||
<regexp pattern="_SHORT_VERSION_" replace="${shortversion}"/>
|
||||
</replaceregexp>
|
||||
</filterchain>
|
||||
</copy>
|
||||
<copy file="${srcdir}/conf/.htaccess" tofile="${builddir}/export/${shortversion}/conf/.htaccess" />
|
||||
<copy todir="${builddir}/export/${shortversion}/seeddms-${version}">
|
||||
<fileset refid="distfiles" />
|
||||
</copy>
|
||||
<copy todir="${builddir}/export/${shortversion}/pear/vendor">
|
||||
<fileset dir="${srcdir}/vendor" defaultexcludes="false" />
|
||||
</copy>
|
||||
<copy todir="${builddir}/export/${shortversion}/www/ext/example">
|
||||
<fileset dir="${srcdir}/ext/example" defaultexcludes="false" />
|
||||
</copy>
|
||||
<!-- copy todir="${builddir}/export/${shortversion}/pear/SeedDMS">
|
||||
<fileset dir="SeedDMS_Core">
|
||||
<include name="Core/**" />
|
||||
<include name="Core.php" />
|
||||
</fileset>
|
||||
<fileset dir="SeedDMS_Preview">
|
||||
<include name="Preview/**" />
|
||||
<include name="Preview.php" />
|
||||
</fileset>
|
||||
<fileset dir="SeedDMS_Lucene">
|
||||
<include name="Lucene/**" />
|
||||
<include name="Lucene.php" />
|
||||
</fileset -->
|
||||
<!-- fileset dir="SeedDMS_SQLiteFTS">
|
||||
<include name="SQLiteFTS/**" />
|
||||
<include name="SQLiteFTS.php" />
|
||||
</fileset>
|
||||
</copy -->
|
||||
<!-- copy todir="${builddir}/export/${shortversion}/pear">
|
||||
<fileset dir="../seeddms-ext/http_webdav_server">
|
||||
<include name="HTTP/WebDAV/Server/**" />
|
||||
<include name="HTTP/WebDAV/Server.php" />
|
||||
</fileset>
|
||||
</copy>
|
||||
<copy todir="${builddir}/export/${shortversion}/pear/HTTP/WebDAV">
|
||||
<fileset dir="../seeddms-ext/http_webdav_server">
|
||||
<include name="Tools/**" />
|
||||
</fileset>
|
||||
</copy -->
|
||||
<copy tofile="${builddir}/export/${shortversion}/pear/composer.json" file="composer-dist.json">
|
||||
</copy>
|
||||
<phingcall target="composer">
|
||||
<property name="composer_extra_params" value="--working-dir=${builddir}/export/${shortversion}/pear/" />
|
||||
<property name="composer_envv" value="COMPOSER=${srcdir}/composer-dist.json" />
|
||||
</phingcall>
|
||||
<exec command="cd ${builddir}/export/${shortversion} && ln -s seeddms-${version} seeddms" />
|
||||
<exec command="cd ${builddir}/export/${shortversion}/www && ln -s ../seeddms/op" />
|
||||
<exec command="cd ${builddir}/export/${shortversion}/www && ln -s ../seeddms/out" />
|
||||
<exec command="cd ${builddir}/export/${shortversion}/www && ln -s ../seeddms/inc" />
|
||||
<exec command="cd ${builddir}/export/${shortversion}/www && ln -s ../seeddms/controllers" />
|
||||
<exec command="cd ${builddir}/export/${shortversion}/www && ln -s ../seeddms/languages" />
|
||||
<exec command="cd ${builddir}/export/${shortversion}/www && ln -s ../seeddms/views" />
|
||||
<exec command="cd ${builddir}/export/${shortversion}/www && ln -s ../seeddms/restapi" />
|
||||
<exec command="cd ${builddir}/export/${shortversion}/www && ln -s ../seeddms/styles" />
|
||||
<exec command="cd ${builddir}/export/${shortversion}/www && ln -s ../seeddms/pdfviewer" />
|
||||
<exec command="cd ${builddir}/export/${shortversion}/www && ln -s ../seeddms/install" />
|
||||
<exec command="cd ${builddir}/export/${shortversion}/www && ln -s ../seeddms/webdav" />
|
||||
<exec command="cd ${builddir}/export/${shortversion}/www && ln -s ../seeddms/index.php" />
|
||||
<exec command="cd ${builddir}/export/${shortversion}/www && ln -s ../seeddms/.htaccess" />
|
||||
|
||||
<exec command="cat ${srcdir}/install/create_tables-sqlite3.sql | sqlite3 ${builddir}/export/${shortversion}/data/content.db" />
|
||||
|
||||
<!-- build the standard tar.gz archive -->
|
||||
<echo message="Building .tar.gz...." />
|
||||
<exec command="cd ${builddir}/export ; tar czf ${builddir}/packages/seeddms-quickstart-${version}.tar.gz ${shortversion}" checkreturn="true" />
|
||||
<echo message="Built in ${builddir}/packages/seeddms-quickstart-${version}.tar.gz" />
|
||||
</target>
|
||||
</project>
|
|
@ -1,76 +0,0 @@
|
|||
{
|
||||
"config": {
|
||||
"platform": {
|
||||
"php": "8.2"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"robthree/twofactorauth": "^1.5",
|
||||
"slim/slim": "^4.0",
|
||||
"guzzlehttp/psr7": "*",
|
||||
"erusev/parsedown": "*",
|
||||
"erusev/parsedown-extra": "*",
|
||||
"mibe/feedwriter": "^1.1",
|
||||
"phpoffice/phpspreadsheet": "*",
|
||||
"sabre/xml": "*",
|
||||
"sabre/dav": "^4.",
|
||||
"pear/log": "*",
|
||||
"pear/mail": "*",
|
||||
"pear/mail_mime": "*",
|
||||
"pear/net_smtp": "*",
|
||||
"pear/auth_sasl": "*",
|
||||
"pear/db": "*",
|
||||
"dragonmantank/cron-expression": "^3.1",
|
||||
"alecrabbit/php-console-colour": "*",
|
||||
"dragonmantank/cron-expression": "^3",
|
||||
"zf1/zend-search-lucene": "*",
|
||||
"symfony/http-foundation": "^5.4",
|
||||
"php-di/php-di": "^6.4",
|
||||
"slim/psr7": "^1.7",
|
||||
"seeddms/core": "dev-master",
|
||||
"seeddms/lucene": "dev-master",
|
||||
"seeddms/preview": "dev-master",
|
||||
"seeddms/sqlitefts": "dev-master",
|
||||
"seeddms/http_webdav_server": "dev-master"
|
||||
},
|
||||
"require-dev": {
|
||||
"composer/composer": "dev-main"
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "path",
|
||||
"url": "/home/cvs/seeddms-ext/core",
|
||||
"options": {
|
||||
"symlink": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "path",
|
||||
"url": "/home/cvs/seeddms-ext/lucene",
|
||||
"options": {
|
||||
"symlink": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "path",
|
||||
"url": "/home/cvs/seeddms-ext/preview",
|
||||
"options": {
|
||||
"symlink": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "path",
|
||||
"url": "/home/cvs/seeddms-ext/sqlitefts",
|
||||
"options": {
|
||||
"symlink": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "path",
|
||||
"url": "/home/cvs/seeddms-ext/http_webdav_server",
|
||||
"options": {
|
||||
"symlink": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,10 +1,6 @@
|
|||
# Make sure settings.xml can not be opened from outside!
|
||||
# Deny all requests from Apache 2.4+.
|
||||
<IfModule mod_authz_core.c>
|
||||
Require all denied
|
||||
</IfModule>
|
||||
|
||||
# Deny all requests from Apache 2.0-2.2.
|
||||
<IfModule !mod_authz_core.c>
|
||||
Deny from all
|
||||
</IfModule>
|
||||
#Redirect /conf/settings.xml /index.php
|
||||
<Files ~ "^settings\.xml">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
|
|
|
@ -15,15 +15,14 @@
|
|||
footNote = "SeedDMS free document management system - www.seeddms.org"
|
||||
printDisclaimer = "true"
|
||||
language = "en_GB"
|
||||
theme = "bootstrap4"
|
||||
theme = "bootstrap"
|
||||
previewWidthList = "40"
|
||||
previewWidthDetail = "100"
|
||||
onePageMode="true"
|
||||
/>
|
||||
<!--
|
||||
- strictFormCheck: Strict form checking. If set to true, then all fields in the form will be checked for a value. If set to false, then (most) comments and keyword fields become optional. Comments are always required when submitting a review or overriding document status.
|
||||
- viewOnlineFileTypes: files with one of the following endings can be viewed online (USE ONLY LOWER CASE CHARACTERS)
|
||||
- enableConverting: enable/disable converting of files (deprecated)
|
||||
- enableConverting: enable/disable converting of files XXX
|
||||
- enableEmail: enable/disable automatic email notification
|
||||
- enableUsersView: enable/disable group and user view for all users
|
||||
- enableFullSearch: false to don't use fulltext search
|
||||
|
@ -35,14 +34,12 @@
|
|||
- 2 to start with tree shown fully expanded
|
||||
- stopWordsFile: path to stop word file for indexer
|
||||
- sortUsersInList: how to sort users in lists ('fullname' or '' (default))
|
||||
- enableDropUpload: enable/disable uploading files by drag&drop
|
||||
- enableRecursiveCount: enable/disable counting docs and folder recursively
|
||||
- maxRecursiveCount: after this number of docs/folders precise counting will stop
|
||||
- enableThemeSelector: enable/disable the theme selector on the login page
|
||||
- enableDropUpload: XXX
|
||||
- enableRecursiveCount: XXX
|
||||
- maxRecursiveCount: XXX
|
||||
- enableThemeSelector: XXX
|
||||
- fullSearchEngine: Either "lucene" or "sqlitefts"
|
||||
- sortFoldersDefault: how to sort forders by default. u=unsorted, s=sequence, n=name
|
||||
- defaultDocPosition: Default position for a new document. 'start', 'end', or ''
|
||||
- defaultFolderPosition: Default position for a new folder. 'start', 'end', or ''
|
||||
- sortFoldersDefault: XXX
|
||||
-->
|
||||
<edition
|
||||
strictFormCheck = "false"
|
||||
|
@ -57,14 +54,12 @@
|
|||
enableLanguageSelector = "true"
|
||||
stopWordsFile = ""
|
||||
sortUsersInList = ""
|
||||
enableDropUpload = "true"
|
||||
enableDropUpload = "false"
|
||||
enableRecursiveCount = "false"
|
||||
maxRecursiveCount = "0"
|
||||
enableThemeSelector = "true"
|
||||
fullSearchEngine = "sqlitefts"
|
||||
enableThemeSelector = "false"
|
||||
fullSearchEngine = "lucene"
|
||||
sortFoldersDefault = "u"
|
||||
defaultDocPosition = "end"
|
||||
defaultFolderPosition = "end"
|
||||
/>
|
||||
<!--
|
||||
- enableCalendar: enable/disable calendar
|
||||
|
@ -76,9 +71,6 @@
|
|||
calendarDefaultView = "y"
|
||||
firstDayOfWeek = "0"
|
||||
/>
|
||||
<webdav
|
||||
enableWebdavReplaceDoc="true"
|
||||
/>
|
||||
</site>
|
||||
<system>
|
||||
<!--
|
||||
|
@ -97,22 +89,19 @@
|
|||
- partitionSize: size of chunk uploaded by jumploader
|
||||
- dropFolderDir: where files for document upload are located
|
||||
- cacheDir: where the preview images are saved
|
||||
- backupDir: where the backups are saved
|
||||
-->
|
||||
<server
|
||||
rootDir = ""
|
||||
httpRoot = "/_SHORT_VERSION_/"
|
||||
httpRoot = "/seeddms/"
|
||||
contentDir = ""
|
||||
stagingDir = ""
|
||||
luceneDir = ""
|
||||
logFileEnable = "true"
|
||||
logFileRotation = "d"
|
||||
enableLargeFileUpload = "false"
|
||||
enableLargeFileUpload = "true"
|
||||
partitionSize = "2000000"
|
||||
dropFolderDir = ""
|
||||
cacheDir = ""
|
||||
backupDir = ""
|
||||
logFileMaxLevel="6"
|
||||
/>
|
||||
<!--
|
||||
- enableGuestLogin: If you want anybody to login as guest, set the following line to true
|
||||
|
@ -121,17 +110,16 @@
|
|||
- restricted: Restricted access: only allow users to log in if they have an entry in the local database (irrespective of successful authentication with LDAP).
|
||||
- enableUserImage: enable users images
|
||||
- disableSelfEdit: if true user cannot edit his own profile
|
||||
- disableChangePassword: if true user cannot change the password
|
||||
- passwordStrength: minimum strength of password, set to 0 to disable
|
||||
- passwordStrengthAlgorithm: algorithm used to calculate password strenght (simple or advanced)
|
||||
- passwordExpiration: number of days after password expires
|
||||
- passwordHistory: number of remembered passwords
|
||||
- loginFailure: maximum allowed login failures before an account is disabled
|
||||
- autoLoginUser: id of user used if auto login is turned on
|
||||
- quota: maximum allowed space on disc for each user
|
||||
- undelUserIds: ids of users which cannot be deleted
|
||||
- encryptionKey: arbitrary string used for creating form tokens
|
||||
- cookieLifetime: lifetime of cookie in seconds, set to 0 for session cookies
|
||||
- passwordStrength: XXX
|
||||
- passwordStrengthAlgorithm: XXX
|
||||
- passwordExpiration: XXX
|
||||
- passwordHistory: XXX
|
||||
- loginFailure: XXX
|
||||
- autoLoginUser: XXX
|
||||
- quota: XXX
|
||||
- undelUserIds: XXX
|
||||
- encryptionKey: XXX
|
||||
- cookieLifetime: XXX
|
||||
-->
|
||||
<authentication
|
||||
enableGuestLogin = "false"
|
||||
|
@ -139,7 +127,6 @@
|
|||
restricted = "true"
|
||||
enableUserImage = "false"
|
||||
disableSelfEdit = "false"
|
||||
disableChangePassword = "false"
|
||||
passwordStrength = "0"
|
||||
passwordStrengthAlgorithm = "simple"
|
||||
passwordExpiration = "0"
|
||||
|
@ -158,8 +145,8 @@
|
|||
- URIs are supported, e.g.: ldaps://ldap.host.com
|
||||
- port: port of the authentification server
|
||||
- baseDN: top level of the LDAP directory tree
|
||||
- bindDN: use this dn for a first step bind, leave empty for annonymous bind
|
||||
- bindPw: use this password for a first step bind
|
||||
- bindDN: XXX
|
||||
- bindPw: XXX
|
||||
- filter: Additional filters which are to be checked
|
||||
-->
|
||||
<connector
|
||||
|
@ -171,7 +158,6 @@
|
|||
bindDN = ""
|
||||
bindPw = ""
|
||||
filter = ""
|
||||
groupField = ""
|
||||
/>
|
||||
<!-- ***** CONNECTOR Microsoft Active Directory *****
|
||||
- enable: enable/disable connector
|
||||
|
@ -179,10 +165,9 @@
|
|||
- host: hostname of the authentification server
|
||||
- port: port of the authentification server
|
||||
- baseDN: top level of the LDAP directory tree
|
||||
- bindDN: use this dn for a first step bind, leave empty for annonymous bind
|
||||
- bindPw: use this password for a first step bind
|
||||
- filter: Additional filters which are to be checked
|
||||
- accountDomainName: sample: example.com
|
||||
- bindDN: XXX
|
||||
- bindPw: XXX
|
||||
-->
|
||||
<connector
|
||||
enable = "false"
|
||||
|
@ -193,12 +178,11 @@
|
|||
accountDomainName = "example.com"
|
||||
bindDN = ""
|
||||
bindPw = ""
|
||||
filter = ""
|
||||
groupField = ""
|
||||
/>
|
||||
</connectors>
|
||||
</authentication>
|
||||
<!--
|
||||
- ADOdbPath: Path to adodb. This is the directory containing the adodb directory
|
||||
- dbDriver: DB-Driver used by adodb (see adodb-readme)
|
||||
- dbHostname: DB-Server
|
||||
- dbDatabase: database where the tables for seeddms are stored (optional - see adodb-readme)
|
||||
|
@ -207,6 +191,7 @@
|
|||
- doNotCheckVersion: Whether or not to check the database schema for its correct version.
|
||||
-->
|
||||
<database
|
||||
ADOdbPath = ""
|
||||
dbDriver = "_DBC_DBTYPE_"
|
||||
dbHostname = "_DBC_DBSERVER_"
|
||||
dbDatabase = "_DBC_DBNAME_"
|
||||
|
@ -218,8 +203,8 @@
|
|||
- smtpServer: SMTP Server hostname
|
||||
- smtpPort: SMTP Server port
|
||||
- smtpSendFrom: Send from
|
||||
- smtpUser: user name used for authenticating against smtp server
|
||||
- smtpPassword: password used for authenticating against smtp server
|
||||
- smtpUser: XXX
|
||||
- smtpPassword: XXX
|
||||
-->
|
||||
<smtp
|
||||
smtpServer = "localhost"
|
||||
|
@ -233,11 +218,13 @@
|
|||
<!--
|
||||
-siteDefaultPage: Default page on login. Defaults to out/out.ViewFolder.php
|
||||
- rootFolderID: ID of root-folder (mostly no need to change)
|
||||
- showMissingTranslations: set true if missing translation shall be listed at end of page
|
||||
- titleDisplayHack: Workaround for page titles that go over more than 2 lines.
|
||||
- showMissingTranslations: XXX
|
||||
-->
|
||||
<display
|
||||
siteDefaultPage = ""
|
||||
rootFolderID = "1"
|
||||
titleDisplayHack = "true"
|
||||
showMissingTranslations = "false"
|
||||
/>
|
||||
<!--
|
||||
|
@ -255,20 +242,18 @@
|
|||
- enableVersionDeletion: allow to delete versions after approval
|
||||
- enableVersionModification: allow to modify versions after approval
|
||||
- enableDuplicateDocNames: allow duplicate names in a folder
|
||||
- enableDuplicateSubFolderNames: allow duplicate names in a folder
|
||||
- enableOwnerRevApp: allow owner of a document to review and approve
|
||||
- enableSelfRevApp: allow the user current logged in to add herself as a reviewer or approver
|
||||
- presetExpirationDate: set to time period if each document shall expire
|
||||
- overrideMimeType: set to true if the mimetype of a document version is determined by the server
|
||||
- enableOwnerRevApp: XXX
|
||||
- enableSelfRevApp: XXX
|
||||
- presetExpirationDate: XXX
|
||||
- overrideMimeType: XXX
|
||||
-->
|
||||
<edition
|
||||
enableAdminRevApp = "false"
|
||||
versioningFileName = "versioning_info.txt"
|
||||
workflowMode = "traditional"
|
||||
workflowMode = "advanced"
|
||||
enableVersionDeletion = "true"
|
||||
enableVersionModification = "true"
|
||||
enableDuplicateDocNames = "true"
|
||||
enableDuplicateSubFolderNames = "true"
|
||||
enableOwnerRevApp = "false"
|
||||
enableSelfRevApp = "false"
|
||||
presetExpirationDate = ""
|
||||
|
@ -282,11 +267,11 @@
|
|||
- directory ($_contentDir). This requires a base directory from which
|
||||
- to begin. Usually leave this to the default setting, 1048576, but can
|
||||
- be any number or string that does not already exist within $_contentDir.
|
||||
- maxDirID: Maximum number of sub-directories per parent directory. Default: 0.
|
||||
- maxDirID: Maximum number of sub-directories per parent directory. Default: 32700.
|
||||
- updateNotifyTime: users are notified about document-changes that took place within the last "updateNotifyTime" seconds
|
||||
- extraPath: additional path which is added to php's include path
|
||||
- maxExecutionTime: maximum script execution time, this cannot be larger than the value set in php.ini
|
||||
- cmdTimeout: timeout in sec. for external commands
|
||||
- extraPath: XXX
|
||||
- maxExecutionTime: XXX
|
||||
- cmdTimeout: XXX
|
||||
-->
|
||||
<server
|
||||
coreDir = ""
|
||||
|
@ -296,33 +281,18 @@
|
|||
updateNotifyTime = "86400"
|
||||
extraPath = ""
|
||||
maxExecutionTime = "30"
|
||||
cmdTimeout = "10"
|
||||
cmdTimeout = "1"
|
||||
/>
|
||||
<!--
|
||||
- enableNotificationAppRev: set to true if reviewers and approvers shall be informed about a pending review/approval
|
||||
- enableNotificationAppRev: XXX
|
||||
- enableOwnerNotification: XXX
|
||||
- enableNotificationWorkflow: set to true if the users in the workflow shall be informed
|
||||
- enableNotificationWorkflow: XXX
|
||||
-->
|
||||
<notification
|
||||
enableNotificationAppRev = "true"
|
||||
enableOwnerNotification = "false"
|
||||
enableNotificationWorkflow = "false"
|
||||
/>
|
||||
<converters target="fulltext">
|
||||
<converter mimeType="application/pdf">pdftotext -nopgbrk %s -</converter>
|
||||
<converter mimeType="application/msword">catdoc %s</converter>
|
||||
<converter mimeType="text/plain">cat %s</converter>
|
||||
<converter mimeType="application/vnd.openxmlformats-officedocument.wordprocessingml.document">docx2txt %s -</converter>
|
||||
</converters>
|
||||
<converters target="preview">
|
||||
<converter mimeType="image/png">convert -resize %wx '%f' '%o'</converter>
|
||||
<converter mimeType="image/jpg">convert -resize %wx '%f' '%o'</converter>
|
||||
<converter mimeType="image/gif">convert -resize %wx '%f' '%o'</converter>
|
||||
</converters>
|
||||
</advanced>
|
||||
<extensions>
|
||||
<extension name="example" disable="true">
|
||||
<parameter name="__disable__">1</parameter>
|
||||
</extension>
|
||||
</extensions>
|
||||
<extensions/>
|
||||
</configuration>
|
||||
|
|
|
@ -1,246 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of AddDocument controller
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class which does the busines logic for downloading a document
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Controller_AddDocument extends SeedDMS_Controller_Common {
|
||||
|
||||
public function run() { /* {{{ */
|
||||
$dms = $this->params['dms'];
|
||||
$user = $this->params['user'];
|
||||
$settings = $this->params['settings'];
|
||||
$fulltextservice = $this->params['fulltextservice'];
|
||||
$folder = $this->params['folder'];
|
||||
|
||||
/* Call preAddDocument early, because it might need to modify some
|
||||
* of the parameters.
|
||||
*/
|
||||
if(false === $this->callHook('preAddDocument')) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_preAddDocument_failed';
|
||||
return null;
|
||||
}
|
||||
|
||||
$name = $this->getParam('name');
|
||||
$comment = $this->getParam('comment');
|
||||
$documentsource = $this->params['documentsource'];
|
||||
$expires = $this->getParam('expires');
|
||||
$keywords = $this->getParam('keywords');
|
||||
$cats = $this->getParam('categories');
|
||||
$owner = $this->getParam('owner');
|
||||
$userfiletmp = $this->getParam('userfiletmp');
|
||||
$userfilename = $this->getParam('userfilename');
|
||||
$filetype = $this->getParam('filetype');
|
||||
$userfiletype = $this->getParam('userfiletype');
|
||||
$sequence = $this->getParam('sequence');
|
||||
$reviewers = $this->getParam('reviewers');
|
||||
$approvers = $this->getParam('approvers');
|
||||
$recipients = $this->getParam('recipients');
|
||||
$reqversion = $this->getParam('reqversion');
|
||||
$version_comment = $this->getParam('versioncomment');
|
||||
$attributes = $this->getParam('attributes');
|
||||
foreach($attributes as $attrdefid=>&$attribute) {
|
||||
if($attrdef = $dms->getAttributeDefinition($attrdefid)) {
|
||||
if(null === ($ret = $this->callHook('validateAttribute', $attrdef, $attribute))) {
|
||||
if($attribute) {
|
||||
switch($attrdef->getType()) {
|
||||
case SeedDMS_Core_AttributeDefinition::type_date:
|
||||
if(is_array($attribute))
|
||||
$attribute = array_map(fn($value): string => date('Y-m-d', makeTsFromDate($value)), $attribute);
|
||||
else
|
||||
$attribute = date('Y-m-d', makeTsFromDate($attribute));
|
||||
break;
|
||||
case SeedDMS_Core_AttributeDefinition::type_folder:
|
||||
if(is_array($attribute))
|
||||
$attribute = array_map(fn($value): object => $dms->getFolder((int) $value), $attribute);
|
||||
else
|
||||
$attribute = $dms->getFolder((int) $attribute);
|
||||
break;
|
||||
case SeedDMS_Core_AttributeDefinition::type_document:
|
||||
if(is_array($attribute))
|
||||
$attribute = array_map(fn($value): object => $dms->getDocument((int) $value), $attribute);
|
||||
else
|
||||
$attribute = $dms->getDocument((int) $attribute);
|
||||
break;
|
||||
case SeedDMS_Core_AttributeDefinition::type_user:
|
||||
if(is_array($attribute))
|
||||
$attribute = array_map(fn($value): object => $dms->getUser((int) $value), $attribute);
|
||||
else
|
||||
$attribute = $dms->getUser((int) $attribute);
|
||||
break;
|
||||
case SeedDMS_Core_AttributeDefinition::type_group:
|
||||
if(is_array($attribute))
|
||||
$attribute = array_map(fn($value): object => $dms->getGroup((int) $value), $attribute);
|
||||
else
|
||||
$attribute = $dms->getGroup((int) $attribute);
|
||||
break;
|
||||
}
|
||||
if(!$attrdef->validate($attribute, null, true)) {
|
||||
$this->errormsg = getAttributeValidationError($attrdef->getValidationError(), $attrdef->getName(), $attribute);
|
||||
return false;
|
||||
}
|
||||
} elseif($attrdef->getMinValues() > 0) {
|
||||
$this->errormsg = array("attr_min_values", array("attrname"=>$attrdef->getName()));
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if($ret === false)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if($attributes_version = $this->getParam('attributesversion')) {
|
||||
foreach($attributes_version as $attrdefid=>&$attribute) {
|
||||
if($attrdef = $dms->getAttributeDefinition($attrdefid)) {
|
||||
if(null === ($ret = $this->callHook('validateAttribute', $attrdef, $attribute))) {
|
||||
if($attribute) {
|
||||
switch($attrdef->getType()) {
|
||||
case SeedDMS_Core_AttributeDefinition::type_date:
|
||||
if(is_array($attribute))
|
||||
$attribute = array_map(fn($value): string => date('Y-m-d', makeTsFromDate($value)), $attribute);
|
||||
else
|
||||
$attribute = date('Y-m-d', makeTsFromDate($attribute));
|
||||
break;
|
||||
case SeedDMS_Core_AttributeDefinition::type_folder:
|
||||
if(is_array($attribute))
|
||||
$attribute = array_map(fn($value): object => $dms->getFolder((int) $value), $attribute);
|
||||
else
|
||||
$attribute = $dms->getFolder((int) $attribute);
|
||||
break;
|
||||
case SeedDMS_Core_AttributeDefinition::type_document:
|
||||
if(is_array($attribute))
|
||||
$attribute = array_map(fn($value): object => $dms->getDocument((int) $value), $attribute);
|
||||
else
|
||||
$attribute = $dms->getDocument((int) $attribute);
|
||||
break;
|
||||
case SeedDMS_Core_AttributeDefinition::type_user:
|
||||
if(is_array($attribute))
|
||||
$attribute = array_map(fn($value): object => $dms->getUser((int) $value), $attribute);
|
||||
else
|
||||
$attribute = $dms->getUser((int) $attribute);
|
||||
break;
|
||||
case SeedDMS_Core_AttributeDefinition::type_group:
|
||||
if(is_array($attribute))
|
||||
$attribute = array_map(fn($value): object => $dms->getGroup((int) $value), $attribute);
|
||||
else
|
||||
$attribute = $dms->getGroup((int) $attribute);
|
||||
break;
|
||||
}
|
||||
if(!$attrdef->validate($attribute, null, true)) {
|
||||
$this->errormsg = getAttributeValidationError($attrdef->getValidationError(), $attrdef->getName(), $attribute);
|
||||
return false;
|
||||
}
|
||||
} elseif($attrdef->getMinValues() > 0) {
|
||||
$this->errormsg = array("attr_min_values", array("attrname"=>$attrdef->getName()));
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if($ret === false)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$workflow = $this->getParam('workflow');
|
||||
$notificationgroups = $this->getParam('notificationgroups');
|
||||
$notificationusers = $this->getParam('notificationusers');
|
||||
$initialdocumentstatus = $this->getParam('initialdocumentstatus');
|
||||
$maxsizeforfulltext = $this->getParam('maxsizeforfulltext');
|
||||
$defaultaccessdocs = $this->getParam('defaultaccessdocs');
|
||||
|
||||
$document = $this->callHook('addDocument');
|
||||
if($document === null) {
|
||||
$filesize = SeedDMS_Core_File::fileSize($userfiletmp);
|
||||
$res = $folder->addDocument($name, $comment, $expires, $owner, $keywords,
|
||||
$cats, $userfiletmp, utf8_basename($userfilename),
|
||||
$filetype, $userfiletype, $sequence,
|
||||
$reviewers, $approvers, $reqversion,
|
||||
$version_comment, $attributes, $attributes_version, $workflow, $initialdocumentstatus);
|
||||
|
||||
if (is_bool($res) && !$res) {
|
||||
$this->errormsg = "error_occured";
|
||||
return false;
|
||||
}
|
||||
|
||||
$document = $res[0];
|
||||
|
||||
/* Set access as specified in settings. */
|
||||
if($defaultaccessdocs) {
|
||||
if($defaultaccessdocs > 0 && $defaultaccessdocs < 4) {
|
||||
$document->setInheritAccess(0, true);
|
||||
$document->setDefaultAccess($defaultaccessdocs, true);
|
||||
}
|
||||
}
|
||||
|
||||
$lc = $document->getLatestContent();
|
||||
if($recipients) {
|
||||
if($recipients['i']) {
|
||||
foreach($recipients['i'] as $uid) {
|
||||
if($u = $dms->getUser($uid)) {
|
||||
$res = $lc->addIndRecipient($u, $user);
|
||||
}
|
||||
}
|
||||
}
|
||||
if($recipients['g']) {
|
||||
foreach($recipients['g'] as $gid) {
|
||||
if($g = $dms->getGroup($gid)) {
|
||||
$res = $lc->addGrpRecipient($g, $user);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Add a default notification for the owner of the document */
|
||||
if($settings->_enableOwnerNotification) {
|
||||
$res = $document->addNotify($owner->getID(), true);
|
||||
}
|
||||
/* Check if additional notification shall be added */
|
||||
foreach($notificationusers as $notuser) {
|
||||
if($document->getAccessMode($notuser) >= M_READ)
|
||||
$res = $document->addNotify($notuser->getID(), true);
|
||||
}
|
||||
foreach($notificationgroups as $notgroup) {
|
||||
if($document->getGroupAccessMode($notgroup) >= M_READ)
|
||||
$res = $document->addNotify($notgroup->getID(), false);
|
||||
}
|
||||
} elseif($document === false) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_addDocument_failed';
|
||||
return false;
|
||||
}
|
||||
|
||||
if($fulltextservice && ($index = $fulltextservice->Indexer()) && $document) {
|
||||
$idoc = $fulltextservice->IndexedDocument($document);
|
||||
if(false !== $this->callHook('preIndexDocument', $document, $idoc)) {
|
||||
$index->addDocument($idoc);
|
||||
$index->commit();
|
||||
}
|
||||
}
|
||||
|
||||
if(false === $this->callHook('postAddDocument', $document)) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_postAddDocument_failed';
|
||||
return false;
|
||||
}
|
||||
|
||||
return $document;
|
||||
} /* }}} */
|
||||
}
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of AddSubFolder controller
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class which does the busines logic for downloading a document
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Controller_AddSubFolder extends SeedDMS_Controller_Common {
|
||||
|
||||
public function run() { /* {{{ */
|
||||
$dms = $this->params['dms'];
|
||||
$user = $this->params['user'];
|
||||
$fulltextservice = $this->params['fulltextservice'];
|
||||
$folder = $this->params['folder'];
|
||||
|
||||
/* Call preAddSubFolder early, because it might need to modify some
|
||||
* of the parameters.
|
||||
*/
|
||||
if(false === $this->callHook('preAddSubFolder')) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_preAddSubFolder_failed';
|
||||
return false;
|
||||
}
|
||||
|
||||
$name = $this->getParam('name');
|
||||
$comment = $this->getParam('comment');
|
||||
$sequence = $this->getParam('sequence');
|
||||
$attributes = $this->getParam('attributes');
|
||||
foreach($attributes as $attrdefid=>&$attribute) {
|
||||
if($attrdef = $dms->getAttributeDefinition($attrdefid)) {
|
||||
if(null === ($ret = $this->callHook('validateAttribute', $attrdef, $attribute))) {
|
||||
if($attribute) {
|
||||
switch($attrdef->getType()) {
|
||||
case SeedDMS_Core_AttributeDefinition::type_date:
|
||||
if(is_array($attribute))
|
||||
$attribute = array_map(fn($value): string => date('Y-m-d', makeTsFromDate($value)), $attribute);
|
||||
else
|
||||
$attribute = date('Y-m-d', makeTsFromDate($attribute));
|
||||
break;
|
||||
case SeedDMS_Core_AttributeDefinition::type_folder:
|
||||
if(is_array($attribute))
|
||||
$attribute = array_map(fn($value): object => $dms->getFolder((int) $value), $attribute);
|
||||
else
|
||||
$attribute = $dms->getFolder((int) $attribute);
|
||||
break;
|
||||
case SeedDMS_Core_AttributeDefinition::type_document:
|
||||
if(is_array($attribute))
|
||||
$attribute = array_map(fn($value): object => $dms->getDocument((int) $value), $attribute);
|
||||
else
|
||||
$attribute = $dms->getDocument((int) $attribute);
|
||||
break;
|
||||
case SeedDMS_Core_AttributeDefinition::type_user:
|
||||
if(is_array($attribute))
|
||||
$attribute = array_map(fn($value): object => $dms->getUser((int) $value), $attribute);
|
||||
else
|
||||
$attribute = $dms->getUser((int) $attribute);
|
||||
break;
|
||||
case SeedDMS_Core_AttributeDefinition::type_group:
|
||||
if(is_array($attribute))
|
||||
$attribute = array_map(fn($value): object => $dms->getGroup((int) $value), $attribute);
|
||||
else
|
||||
$attribute = $dms->getGroup((int) $attribute);
|
||||
break;
|
||||
}
|
||||
if(!$attrdef->validate($attribute, null, true)) {
|
||||
$this->errormsg = getAttributeValidationError($attrdef->getValidationError(), $attrdef->getName(), $attribute);
|
||||
return false;
|
||||
}
|
||||
} elseif($attrdef->getMinValues() > 0) {
|
||||
$this->errormsg = array("attr_min_values", array("attrname"=>$attrdef->getName()));
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if($ret === false)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
$notificationgroups = $this->getParam('notificationgroups');
|
||||
$notificationusers = $this->getParam('notificationusers');
|
||||
|
||||
$subFolder = $this->callHook('addSubFolder');
|
||||
if($subFolder === null) {
|
||||
$subFolder = $folder->addSubFolder($name, $comment, $user, $sequence, $attributes);
|
||||
if (!is_object($subFolder)) {
|
||||
$this->errormsg = "error_occured";
|
||||
return false;
|
||||
}
|
||||
/* Check if additional notification shall be added */
|
||||
foreach($notificationusers as $notuser) {
|
||||
if($subFolder->getAccessMode($user) >= M_READ)
|
||||
$res = $subFolder->addNotify($notuser->getID(), true);
|
||||
}
|
||||
foreach($notificationgroups as $notgroup) {
|
||||
if($subFolder->getGroupAccessMode($notgroup) >= M_READ)
|
||||
$res = $subFolder->addNotify($notgroup->getID(), false);
|
||||
}
|
||||
} elseif($subFolder === false) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_addFolder_failed';
|
||||
return false;
|
||||
}
|
||||
|
||||
if($fulltextservice && ($index = $fulltextservice->Indexer()) && $subFolder) {
|
||||
$idoc = $fulltextservice->IndexedDocument($subFolder);
|
||||
if(false !== $this->callHook('preIndexFolder', $subFolder, $idoc)) {
|
||||
$index->addDocument($idoc);
|
||||
$index->commit();
|
||||
}
|
||||
}
|
||||
|
||||
if(false === $this->callHook('postAddSubFolder', $subFolder)) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_postAddSubFoder_failed';
|
||||
return false;
|
||||
}
|
||||
|
||||
return $subFolder;
|
||||
} /* }}} */
|
||||
}
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of ApproveDocument controller
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2023 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class which does the busines logic for approving a document
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2023 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Controller_ApproveDocument extends SeedDMS_Controller_Common {
|
||||
|
||||
public $oldstatus;
|
||||
|
||||
public $newstatus;
|
||||
|
||||
public function run() { /* {{{ */
|
||||
$dms = $this->params['dms'];
|
||||
$user = $this->params['user'];
|
||||
$settings = $this->params['settings'];
|
||||
$content = $this->params['content'];
|
||||
$approvaltype = $this->params['type'];
|
||||
$approvalstatus = $this->params['status'];
|
||||
$approvalcomment = $this->params['comment'];
|
||||
$approvalfile = $this->params['file'];
|
||||
$approvalgroup = $this->params['group'];
|
||||
$overallStatus = $content->getStatus();
|
||||
$this->oldstatus = $overallStatus['status'];
|
||||
$this->newstatus = $this->oldstatus;
|
||||
|
||||
if(!$this->callHook('preApproveDocument', $content)) {
|
||||
}
|
||||
|
||||
$result = $this->callHook('approveDocument', $content);
|
||||
if($result === null) {
|
||||
if ($approvaltype == "ind") {
|
||||
$approvalLogID = $content->setApprovalByInd($user, $user, $approvalstatus, $approvalcomment, $approvalfile);
|
||||
} elseif ($approvaltype == "grp") {
|
||||
$approvalLogID = $content->setApprovalByGrp($approvalgroup, $user, $approvalstatus, $approvalcomment, $approvalfile);
|
||||
} else {
|
||||
$this->errormsg = "approval_wrong_type";
|
||||
return false;
|
||||
}
|
||||
if($approvalLogID === false || 0 > $approvalLogID) {
|
||||
$this->errormsg = "approval_update_failed";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$result = $this->callHook('approveUpdateDocumentStatus', $content);
|
||||
if($result === null) {
|
||||
if($approvalstatus == -1) {
|
||||
$this->newstatus = S_REJECTED;
|
||||
if($content->setStatus(S_REJECTED, $approvalcomment, $user)) {
|
||||
if(isset($GLOBALS['SEEDDMS_HOOKS']['approveDocument'])) {
|
||||
foreach($GLOBALS['SEEDDMS_HOOKS']['approveDocument'] as $hookObj) {
|
||||
if (method_exists($hookObj, 'postApproveDocument')) {
|
||||
$hookObj->postApproveDocument(null, $content, S_REJECTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$docApprovalStatus = $content->getApprovalStatus();
|
||||
if (is_bool($docApprovalStatus) && !$docApprovalStatus) {
|
||||
$this->errormsg = "cannot_retrieve_approval_snapshot";
|
||||
return false;
|
||||
}
|
||||
$approvalCT = 0;
|
||||
$approvalTotal = 0;
|
||||
foreach ($docApprovalStatus as $drstat) {
|
||||
if ($drstat["status"] == 1) {
|
||||
$approvalCT++;
|
||||
}
|
||||
if ($drstat["status"] != -2) {
|
||||
$approvalTotal++;
|
||||
}
|
||||
}
|
||||
// If all approvals have been received and there are no rejections, retrieve a
|
||||
// count of the approvals required for this document.
|
||||
if ($approvalCT == $approvalTotal) {
|
||||
// Change the status to released.
|
||||
$this->newstatus=S_RELEASED;
|
||||
if($content->setStatus($this->newstatus, getMLText("automatic_status_update"), $user)) {
|
||||
if(isset($GLOBALS['SEEDDMS_HOOKS']['approveDocument'])) {
|
||||
foreach($GLOBALS['SEEDDMS_HOOKS']['approveDocument'] as $hookObj) {
|
||||
if (method_exists($hookObj, 'postApproveDocument')) {
|
||||
$hookObj->postApproveDocument(null, $content, S_RELEASED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!$this->callHook('postApproveDocument', $content)) {
|
||||
}
|
||||
|
||||
return true;
|
||||
} /* }}} */
|
||||
}
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of Attribute Definition manager controller
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class which does the busines logic for attribute definition manager
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Controller_AttributeMgr extends SeedDMS_Controller_Common {
|
||||
|
||||
public function run() { /* {{{ */
|
||||
} /* }}} */
|
||||
|
||||
public function addattrdef() { /* {{{ */
|
||||
$dms = $this->params['dms'];
|
||||
$name = $this->params['name'];
|
||||
$type = $this->params['type'];
|
||||
$objtype = $this->params['objtype'];
|
||||
$multiple = $this->params['multiple'];
|
||||
$minvalues = $this->params['minvalues'];
|
||||
$maxvalues = $this->params['maxvalues'];
|
||||
$valueset = $this->params['valueset'];
|
||||
$regex = $this->params['regex'];
|
||||
|
||||
return($dms->addAttributeDefinition($name, $objtype, $type, $multiple, $minvalues, $maxvalues, $valueset, $regex));
|
||||
} /* }}} */
|
||||
|
||||
public function removeattrdef() { /* {{{ */
|
||||
$attrdef = $this->params['attrdef'];
|
||||
return $attrdef->remove();
|
||||
} /* }}} */
|
||||
|
||||
public function editattrdef() { /* {{{ */
|
||||
$dms = $this->params['dms'];
|
||||
$name = $this->params['name'];
|
||||
$attrdef = $this->params['attrdef'];
|
||||
$type = $this->params['type'];
|
||||
$objtype = $this->params['objtype'];
|
||||
$multiple = $this->params['multiple'];
|
||||
$minvalues = $this->params['minvalues'];
|
||||
$maxvalues = $this->params['maxvalues'];
|
||||
$valueset = $this->params['valueset'];
|
||||
$regex = $this->params['regex'];
|
||||
|
||||
if (!$attrdef->setName($name)) {
|
||||
return false;
|
||||
}
|
||||
if (!$attrdef->setType($type)) {
|
||||
return false;
|
||||
}
|
||||
if (!$attrdef->setObjType($objtype)) {
|
||||
return false;
|
||||
}
|
||||
if (!$attrdef->setMultipleValues($multiple)) {
|
||||
return false;
|
||||
}
|
||||
if (!$attrdef->setMinValues($minvalues)) {
|
||||
return false;
|
||||
}
|
||||
if (!$attrdef->setMaxValues($maxvalues)) {
|
||||
return false;
|
||||
}
|
||||
if (!$attrdef->setValueSet($valueset)) {
|
||||
return false;
|
||||
}
|
||||
if (!$attrdef->setRegex($regex)) {
|
||||
$this->errormsg = 'attrdef_invalid_regex';
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
public function removeattrvalue() { /* {{{ */
|
||||
$attrdef = $this->params['attrdef'];
|
||||
$attrval = $this->params['attrval'];
|
||||
//$attrdef->getObjects($attrval);
|
||||
return $attrdef->removeValue($attrval);
|
||||
} /* }}} */
|
||||
}
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of CheckInDocument controller
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2024 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class which does the busines logic for downloading a document
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2024 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Controller_CheckInDocument extends SeedDMS_Controller_Common {
|
||||
|
||||
public function run() { /* {{{ */
|
||||
$name = $this->getParam('name');
|
||||
$comment = $this->getParam('comment');
|
||||
|
||||
/* Call preCheckInDocument early, because it might need to modify some
|
||||
* of the parameters.
|
||||
*/
|
||||
if(false === $this->callHook('preCheckInDocument', $this->params['document'])) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_preCheckInDocument_failed';
|
||||
return null;
|
||||
}
|
||||
|
||||
$comment = $this->getParam('comment');
|
||||
$dms = $this->params['dms'];
|
||||
$user = $this->params['user'];
|
||||
$document = $this->params['document'];
|
||||
$settings = $this->params['settings'];
|
||||
$fulltextservice = $this->params['fulltextservice'];
|
||||
$folder = $this->params['folder'];
|
||||
$userfiletmp = $this->getParam('userfiletmp');
|
||||
$userfilename = $this->getParam('userfilename');
|
||||
$filetype = $this->getParam('filetype');
|
||||
$userfiletype = $this->getParam('userfiletype');
|
||||
$reviewers = $this->getParam('reviewers');
|
||||
$approvers = $this->getParam('approvers');
|
||||
$recipients = $this->getParam('recipients');
|
||||
$reqversion = $this->getParam('reqversion');
|
||||
$comment = $this->getParam('comment');
|
||||
$attributes = $this->getParam('attributes');
|
||||
$workflow = $this->getParam('workflow');
|
||||
$maxsizeforfulltext = $this->getParam('maxsizeforfulltext');
|
||||
$initialdocumentstatus = $this->getParam('initialdocumentstatus');
|
||||
|
||||
$content = $this->callHook('checkinDocument');
|
||||
if($content === null) {
|
||||
if($contentResult=$document->checkIn($comment, $user, $reviewers, $approvers, $version=0, $attributes, $workflow, $initialdocumentstatus)) {
|
||||
|
||||
if ($this->hasParam('expires')) {
|
||||
if($document->setExpires($this->getParam('expires'))) {
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
if(!empty($recipients['i'])) {
|
||||
foreach($recipients['i'] as $uid) {
|
||||
if($u = $dms->getUser($uid)) {
|
||||
$res = $contentResult->getContent()->addIndRecipient($u, $user);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!empty($recipients['g'])) {
|
||||
foreach($recipients['g'] as $gid) {
|
||||
if($g = $dms->getGroup($gid)) {
|
||||
$res = $contentResult->getContent()->addGrpRecipient($g, $user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$content = $contentResult->getContent();
|
||||
} else {
|
||||
$this->errormsg = 'error_checkin_document';
|
||||
$result = false;
|
||||
}
|
||||
} elseif($result === false) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_checkinDocument_failed';
|
||||
return false;
|
||||
}
|
||||
|
||||
if($fulltextservice && ($index = $fulltextservice->Indexer()) && $content) {
|
||||
$idoc = $fulltextservice->IndexedDocument($document);
|
||||
if(false !== $this->callHook('preIndexDocument', $document, $idoc)) {
|
||||
$lucenesearch = $fulltextservice->Search();
|
||||
if($hit = $lucenesearch->getDocument((int) $document->getId())) {
|
||||
$index->delete($hit->id);
|
||||
}
|
||||
$index->addDocument($idoc);
|
||||
$index->commit();
|
||||
}
|
||||
}
|
||||
|
||||
if(false === $this->callHook('postCheckInDocument', $document, $content)) {
|
||||
}
|
||||
|
||||
return $content;
|
||||
} /* }}} */
|
||||
}
|
||||
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of ClearCache controller
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class which does the busines logic for clearing the cache
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Controller_ClearCache extends SeedDMS_Controller_Common {
|
||||
|
||||
public function run() {
|
||||
$dms = $this->params['dms'];
|
||||
$user = $this->params['user'];
|
||||
$settings = $this->params['settings'];
|
||||
$post = $this->params['post'];
|
||||
|
||||
$ret = '';
|
||||
if(!empty($post['previewpng'])) {
|
||||
$cmd = 'rm -rf '.addDirSep($settings->_cacheDir).'png'.DIRECTORY_SEPARATOR.'[1-9]*';
|
||||
system($cmd, $ret);
|
||||
}
|
||||
|
||||
if(!empty($post['previewpdf'])) {
|
||||
$cmd = 'rm -rf '.addDirSep($settings->_cacheDir).'pdf'.DIRECTORY_SEPARATOR.'[1-9]*';
|
||||
system($cmd, $ret);
|
||||
}
|
||||
|
||||
if(!empty($post['previewtxt'])) {
|
||||
$cmd = 'rm -rf '.addDirSep($settings->_cacheDir).'txt'.DIRECTORY_SEPARATOR.'[1-9]*';
|
||||
system($cmd, $ret);
|
||||
}
|
||||
|
||||
if(!empty($post['js'])) {
|
||||
/* system('rm ...') does not work anymore if the number of files is too large */
|
||||
array_map('unlink', array_filter((array) glob(addDirSep($settings->_cacheDir).'js'.DIRECTORY_SEPARATOR.'*')));
|
||||
}
|
||||
|
||||
if(false === $this->callHook('clear', $post)) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_clear_failed';
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,108 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of Cron controller
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2020 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class which does the busines logic for the regular cron job
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2020 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Controller_Cron extends SeedDMS_Controller_Common {
|
||||
|
||||
public function run() { /* {{{ */
|
||||
$dms = $this->params['dms'];
|
||||
$user = $this->params['user'];
|
||||
$settings = $this->params['settings'];
|
||||
$logger = $this->params['logger'];
|
||||
$mode = $this->params['mode'];
|
||||
$seltask = $this->params['task'];
|
||||
$db = $dms->getDb();
|
||||
|
||||
$scheduler = new SeedDMS_Scheduler($db);
|
||||
$tasks = $scheduler->getTasks();
|
||||
|
||||
$jsonarr = [];
|
||||
foreach($tasks as $task) {
|
||||
if($seltask && $seltask != $task->getExtension()."::".$task->getTask())
|
||||
continue;
|
||||
if(isset($GLOBALS['SEEDDMS_SCHEDULER']['tasks'][$task->getExtension()]) && is_object($taskobj = resolveTask($GLOBALS['SEEDDMS_SCHEDULER']['tasks'][$task->getExtension()][$task->getTask()]))) {
|
||||
$arr = array(
|
||||
'extension'=>$task->getExtension(),
|
||||
'name'=>$task->getTask(),
|
||||
'mode'=>$mode,
|
||||
'disabled' => (bool) $task->getDisabled(),
|
||||
'isdue' => $task->isDue(),
|
||||
);
|
||||
switch($mode) {
|
||||
case "run":
|
||||
case "dryrun":
|
||||
if(method_exists($taskobj, 'execute')) {
|
||||
if(!$task->getDisabled() && $task->isDue()) {
|
||||
if($mode == 'run') {
|
||||
/* Schedule the next run right away to prevent a second execution
|
||||
* of the task when the cron job of the scheduler is called before
|
||||
* the last run was finished. The task itself can still be scheduled
|
||||
* to fast, but this is up to the admin of seeddms.
|
||||
*/
|
||||
$task->updateLastNextRun();
|
||||
if($taskobj->execute($task)) {
|
||||
add_log_line("Execution of task ".$task->getExtension()."::".$task->getTask()." successful.");
|
||||
$arr['success'] = true;
|
||||
} else {
|
||||
add_log_line("Execution of task ".$task->getExtension()."::".$task->getTask()." failed, task has been disabled.", PEAR_LOG_ERR);
|
||||
$arr['success'] = false;
|
||||
$task->setDisabled(1);
|
||||
}
|
||||
} elseif($mode == 'dryrun') {
|
||||
$arr['success'] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "check":
|
||||
$arr['error'] = false;
|
||||
if(!method_exists($taskobj, 'execute')) {
|
||||
$arr['error'] = true;
|
||||
$arr['messages'][] = 'Missing method execute()';
|
||||
}
|
||||
if(get_parent_class($taskobj) != 'SeedDMS_SchedulerTaskBase') {
|
||||
$arr['error'] = true;
|
||||
$arr['error'][] = "Wrong parent class";
|
||||
}
|
||||
break;
|
||||
case "list":
|
||||
default:
|
||||
header("Content-Type: application/json");
|
||||
$arr['nextrun']=$task->getNextRun();
|
||||
$arr['frequency']=$task->getFrequency();
|
||||
$arr['params']=array();
|
||||
if($params = $task->getParameter()) {
|
||||
foreach($params as $key=>$value) {
|
||||
$p = $taskobj->getAdditionalParamByName($key);
|
||||
$arr['params'][$key] = ($p['type'] == 'password') ? '*******' : $value;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
$jsonarr[] = $arr;
|
||||
}
|
||||
}
|
||||
echo json_encode($jsonarr);
|
||||
|
||||
return true;
|
||||
} /* }}} */
|
||||
}
|
||||
|
|
@ -1,209 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of DocumentAccess controller
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2017 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class which does the busines logic for editing a folder
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2017 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Controller_DocumentAccess extends SeedDMS_Controller_Common {
|
||||
|
||||
public function run() {
|
||||
$dms = $this->params['dms'];
|
||||
$user = $this->params['user'];
|
||||
$folder = $this->params['folder'];
|
||||
$document = $this->params['document'];
|
||||
$settings = $this->params['settings'];
|
||||
$action = $this->params['action'];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Change owner -----------------------------------------------------------
|
||||
public function setowner() {
|
||||
$dms = $this->params['dms'];
|
||||
$user = $this->params['user'];
|
||||
$folder = $this->params['folder'];
|
||||
$document = $this->params['document'];
|
||||
$settings = $this->params['settings'];
|
||||
|
||||
if(false === $this->callHook('preSetOwner', $document)) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_preSetOwner_failed';
|
||||
return null;
|
||||
}
|
||||
$newowner = $this->params['newowner'];
|
||||
$oldowner = $document->getOwner();
|
||||
if($document->setOwner($newowner)) {
|
||||
if(false === $this->callHook('postSetOwner', $document, $oldowner)) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_postSetOwner_failed';
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function notinherit() {
|
||||
$dms = $this->params['dms'];
|
||||
$user = $this->params['user'];
|
||||
$folder = $this->params['folder'];
|
||||
$document = $this->params['document'];
|
||||
$settings = $this->params['settings'];
|
||||
|
||||
if(false === $this->callHook('preSetNotInherit', $document)) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_preSetNotInherit_failed';
|
||||
return null;
|
||||
}
|
||||
|
||||
/* Get default access before access is not longer inherited. This
|
||||
* will return the default access from the parent folder.
|
||||
*/
|
||||
$defAccess = $document->getDefaultAccess();
|
||||
if(!$document->setInheritAccess(false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!$document->setDefaultAccess($defAccess)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//copy ACL of parent folder
|
||||
$mode = $this->params['mode'];
|
||||
if ($mode == "copy") {
|
||||
$accessList = $folder->getAccessList();
|
||||
foreach ($accessList["users"] as $userAccess)
|
||||
$document->addAccess($userAccess->getMode(), $userAccess->getUserID(), true);
|
||||
foreach ($accessList["groups"] as $groupAccess)
|
||||
$document->addAccess($groupAccess->getMode(), $groupAccess->getGroupID(), false);
|
||||
}
|
||||
|
||||
if(false === $this->callHook('postSetNotInherit', $document)) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_postSetNotInherit_failed';
|
||||
return null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function inherit() {
|
||||
$dms = $this->params['dms'];
|
||||
$user = $this->params['user'];
|
||||
$folder = $this->params['folder'];
|
||||
$document = $this->params['document'];
|
||||
$settings = $this->params['settings'];
|
||||
|
||||
if(false === $this->callHook('preSetInherit', $document)) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_preSetInherit_failed';
|
||||
return null;
|
||||
}
|
||||
if(!$document->clearAccessList() || !$document->setInheritAccess(true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(false === $this->callHook('postSetInherit', $document)) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_postSetInherit_failed';
|
||||
return null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function setdefault() {
|
||||
$dms = $this->params['dms'];
|
||||
$user = $this->params['user'];
|
||||
$folder = $this->params['folder'];
|
||||
$document = $this->params['document'];
|
||||
$settings = $this->params['settings'];
|
||||
|
||||
if(false === $this->callHook('preSetDefault', $document)) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_preSetDefault_failed';
|
||||
return null;
|
||||
}
|
||||
|
||||
$mode = $this->params['mode'];
|
||||
if(!$document->setDefaultAccess($mode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(false === $this->callHook('postSetDefault', $document)) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_postSetDefault_failed';
|
||||
return null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function editaccess() {
|
||||
$dms = $this->params['dms'];
|
||||
$user = $this->params['user'];
|
||||
$folder = $this->params['folder'];
|
||||
$document = $this->params['document'];
|
||||
$settings = $this->params['settings'];
|
||||
|
||||
$mode = $this->params['mode'];
|
||||
$userid = $this->params['userid'];
|
||||
$groupid = $this->params['groupid'];
|
||||
if ($userid) {
|
||||
$document->changeAccess($mode, $userid, true);
|
||||
}
|
||||
elseif ($groupid) {
|
||||
$document->changeAccess($mode, $groupid, false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function delaccess() {
|
||||
$dms = $this->params['dms'];
|
||||
$user = $this->params['user'];
|
||||
$folder = $this->params['folder'];
|
||||
$document = $this->params['document'];
|
||||
$settings = $this->params['settings'];
|
||||
|
||||
$userid = $this->params['userid'];
|
||||
$groupid = $this->params['groupid'];
|
||||
if ($userid) {
|
||||
$document->removeAccess($userid, true);
|
||||
}
|
||||
elseif ($groupid) {
|
||||
$document->removeAccess($groupid, false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function addaccess() {
|
||||
$dms = $this->params['dms'];
|
||||
$user = $this->params['user'];
|
||||
$folder = $this->params['folder'];
|
||||
$document = $this->params['document'];
|
||||
$settings = $this->params['settings'];
|
||||
|
||||
$mode = $this->params['mode'];
|
||||
$userid = $this->params['userid'];
|
||||
$groupid = $this->params['groupid'];
|
||||
if ($userid && $userid != -1) {
|
||||
$document->addAccess($mode, $userid, true);
|
||||
}
|
||||
elseif ($groupid && $groupid != -1) {
|
||||
$document->addAccess($mode, $groupid, false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -22,192 +22,27 @@
|
|||
*/
|
||||
class SeedDMS_Controller_Download extends SeedDMS_Controller_Common {
|
||||
|
||||
public function version() { /* {{{ */
|
||||
public function run() {
|
||||
$dms = $this->params['dms'];
|
||||
$version = $this->params['version'];
|
||||
$document = $this->params['document'];
|
||||
if($version < 1) {
|
||||
$content = $this->callHook('documentLatestContent', $document);
|
||||
if($content === null)
|
||||
$content = $document->getLatestContent();
|
||||
} else {
|
||||
$content = $this->callHook('documentContent', $document, $version);
|
||||
if($content === null)
|
||||
$content = $document->getContentByVersion($version);
|
||||
}
|
||||
if (!is_object($content)) {
|
||||
$this->errormsg = 'invalid_version';
|
||||
return false;
|
||||
}
|
||||
/* set params['content'] for compatiblity with older extensions which
|
||||
* expect the content in the controller
|
||||
*/
|
||||
$this->params['content'] = $content;
|
||||
if(null === $this->callHook('version')) {
|
||||
$type = $this->params['type'];
|
||||
$content = $this->params['content'];
|
||||
|
||||
switch($type) {
|
||||
case "version":
|
||||
|
||||
if(!$this->callHook('version')) {
|
||||
if(file_exists($dms->contentDir . $content->getPath())) {
|
||||
header("Content-Transfer-Encoding: binary");
|
||||
header("Content-Length: " . filesize($dms->contentDir . $content->getPath() ));
|
||||
$efilename = rawurlencode($content->getOriginalFileName());
|
||||
header("Content-Disposition: attachment; filename=\"" . $efilename . "\"; filename*=UTF-8''".$efilename);
|
||||
header("Content-Type: " . $content->getMimeType());
|
||||
header("Cache-Control: must-revalidate");
|
||||
header("ETag: ".$content->getChecksum());
|
||||
|
||||
sendFile($dms->contentDir . $content->getPath());
|
||||
readfile($dms->contentDir . $content->getPath());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
public function file() { /* {{{ */
|
||||
$dms = $this->params['dms'];
|
||||
$file = $this->params['file'];
|
||||
|
||||
if(null === $this->callHook('file')) {
|
||||
if(file_exists($dms->contentDir . $file->getPath())) {
|
||||
header("Content-Transfer-Encoding: binary");
|
||||
header("Content-Disposition: attachment; filename=\"" . $file->getOriginalFileName() . "\"");
|
||||
header("Content-Type: " . $file->getMimeType());
|
||||
header("Cache-Control: must-revalidate");
|
||||
|
||||
sendFile($dms->contentDir . $file->getPath());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
public function archive() { /* {{{ */
|
||||
$dms = $this->params['dms'];
|
||||
$filename = $this->params['file'];
|
||||
$basedir = $this->params['basedir'];
|
||||
|
||||
if(null === $this->callHook('archive')) {
|
||||
if(file_exists($basedir . $filename)) {
|
||||
header('Content-Description: File Transfer');
|
||||
header("Content-Type: application/zip");
|
||||
header("Content-Transfer-Encoding: binary");
|
||||
$efilename = rawurlencode($filename);
|
||||
header("Content-Disposition: attachment; filename=\"" .$efilename . "\"; filename*=UTF-8''".$efilename);
|
||||
header("Cache-Control: public");
|
||||
|
||||
sendFile($basedir .$filename );
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
public function log() { /* {{{ */
|
||||
$dms = $this->params['dms'];
|
||||
$filename = $this->params['file'];
|
||||
$basedir = $this->params['basedir'];
|
||||
|
||||
if(null === $this->callHook('log')) {
|
||||
if(file_exists($basedir . $filename)) {
|
||||
header("Content-Type: text/plain; name=\"" . $filename . "\"");
|
||||
header("Content-Transfer-Encoding: binary");
|
||||
$efilename = rawurlencode($filename);
|
||||
header("Content-Disposition: attachment; filename=\"" .$efilename . "\"; filename*=UTF-8''".$efilename);
|
||||
header("Cache-Control: must-revalidate");
|
||||
|
||||
sendFile($basedir.$filename);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
public function sqldump() { /* {{{ */
|
||||
$dms = $this->params['dms'];
|
||||
$filename = $this->params['file'];
|
||||
$basedir = $this->params['basedir'];
|
||||
|
||||
if(null === $this->callHook('sqldump')) {
|
||||
if(file_exists($basedir . $filename)) {
|
||||
header("Content-Type: application/zip");
|
||||
header("Content-Transfer-Encoding: binary");
|
||||
$efilename = rawurlencode($filename);
|
||||
header("Content-Disposition: attachment; filename=\"" .$efilename . "\"; filename*=UTF-8''".$efilename);
|
||||
header("Cache-Control: must-revalidate");
|
||||
|
||||
sendFile($basedir.$filename);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
public function approval() { /* {{{ */
|
||||
$dms = $this->params['dms'];
|
||||
$document = $this->params['document'];
|
||||
$logid = $this->params['approvelogid'];
|
||||
|
||||
$filename = $dms->contentDir . $document->getDir().'a'.$logid;
|
||||
if (!file_exists($filename) ) {
|
||||
$this->error = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(null === $this->callHook('approval')) {
|
||||
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
||||
$mimetype = finfo_file($finfo, $filename);
|
||||
|
||||
header("Content-Type: ".$mimetype);
|
||||
header("Content-Transfer-Encoding: binary");
|
||||
header("Content-Disposition: attachment; filename=\"approval-" . $document->getID()."-".(int) $_GET['approvelogid'] . get_extension($mimetype) . "\"");
|
||||
header("Cache-Control: must-revalidate");
|
||||
sendFile($filename);
|
||||
}
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
public function review() { /* {{{ */
|
||||
$dms = $this->params['dms'];
|
||||
$document = $this->params['document'];
|
||||
$logid = $this->params['reviewlogid'];
|
||||
|
||||
$filename = $dms->contentDir . $document->getDir().'r'.$logid;
|
||||
if (!file_exists($filename) ) {
|
||||
$this->error = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(null === $this->callHook('review')) {
|
||||
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
||||
$mimetype = finfo_file($finfo, $filename);
|
||||
|
||||
header("Content-Type: ".$mimetype);
|
||||
header("Content-Transfer-Encoding: binary");
|
||||
header("Content-Length: " . filesize($filename ));
|
||||
header("Content-Disposition: attachment; filename=\"review-" . $document->getID()."-".(int) $_GET['reviewlogid'] . get_extension($mimetype) . "\"");
|
||||
header("Cache-Control: must-revalidate");
|
||||
sendFile($filename);
|
||||
}
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
public function run() { /* {{{ */
|
||||
$dms = $this->params['dms'];
|
||||
$type = $this->params['type'];
|
||||
|
||||
switch($type) {
|
||||
case "version":
|
||||
return $this->version();
|
||||
break;
|
||||
case "file":
|
||||
return $this->file();
|
||||
break;
|
||||
case "archive":
|
||||
return $this->archive();
|
||||
break;
|
||||
case "log":
|
||||
return $this->log();
|
||||
break;
|
||||
case "sqldump":
|
||||
return $this->sqldump();
|
||||
break;
|
||||
case "approval":
|
||||
return $this->approval();
|
||||
break;
|
||||
case "review":
|
||||
return $this->review();
|
||||
break;
|
||||
}
|
||||
} /* }}} */
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,220 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of EditDocument controller
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class which does the busines logic for editing a document
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Controller_EditDocument extends SeedDMS_Controller_Common {
|
||||
|
||||
public function run() {
|
||||
$dms = $this->params['dms'];
|
||||
$user = $this->params['user'];
|
||||
$settings = $this->params['settings'];
|
||||
$fulltextservice = $this->params['fulltextservice'];
|
||||
$document = $this->params['document'];
|
||||
$name = $this->params['name'];
|
||||
|
||||
if(false === $this->callHook('preEditDocument')) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_preEditDocument_failed';
|
||||
return null;
|
||||
}
|
||||
|
||||
$result = $this->callHook('editDocument', $document);
|
||||
if($result === null) {
|
||||
$name = $this->params['name'];
|
||||
$oldname = $document->getName();
|
||||
if($oldname != $name)
|
||||
if(!$document->setName($name))
|
||||
return false;
|
||||
|
||||
$comment = $this->params['comment'];
|
||||
if(($oldcomment = $document->getComment()) != $comment)
|
||||
if(!$document->setComment($comment))
|
||||
return false;
|
||||
|
||||
$expires = $this->params['expires'];
|
||||
$oldexpires = $document->getExpires();
|
||||
if ($expires != $oldexpires) {
|
||||
if(false === $this->callHook('preSetExpires', $document, $expires)) {
|
||||
}
|
||||
|
||||
if(!$document->setExpires($expires)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$document->verifyLastestContentExpriry();
|
||||
|
||||
if(false === $this->callHook('postSetExpires', $document, $expires)) {
|
||||
}
|
||||
}
|
||||
|
||||
$keywords = $this->params['keywords'];
|
||||
$oldkeywords = $document->getKeywords();
|
||||
if ($oldkeywords != $keywords) {
|
||||
if(false === $this->callHook('preSetKeywords', $document, $keywords, $oldkeywords)) {
|
||||
}
|
||||
|
||||
if(!$document->setKeywords($keywords)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(false === $this->callHook('postSetKeywords', $document, $keywords, $oldkeywords)) {
|
||||
}
|
||||
}
|
||||
|
||||
$categories = $this->params['categories'];
|
||||
$oldcategories = $document->getCategories();
|
||||
if($categories) {
|
||||
$categoriesarr = array();
|
||||
foreach($categories as $catid) {
|
||||
if($cat = $dms->getDocumentCategory($catid)) {
|
||||
$categoriesarr[] = $cat;
|
||||
}
|
||||
|
||||
}
|
||||
$oldcatsids = array();
|
||||
foreach($oldcategories as $oldcategory)
|
||||
$oldcatsids[] = $oldcategory->getID();
|
||||
|
||||
if (count($categoriesarr) != count($oldcategories) ||
|
||||
array_diff($categories, $oldcatsids)) {
|
||||
if(false === $this->callHook('preSetCategories', $document, $categoriesarr, $oldcategories)) {
|
||||
}
|
||||
if(!$document->setCategories($categoriesarr)) {
|
||||
return false;
|
||||
}
|
||||
if(false === $this->callHook('postSetCategories', $document, $categoriesarr, $oldcategories)) {
|
||||
}
|
||||
}
|
||||
} elseif($oldcategories) {
|
||||
if(false === $this->callHook('preSetCategories', $document, array(), $oldcategories)) {
|
||||
}
|
||||
if(!$document->setCategories(array())) {
|
||||
return false;
|
||||
}
|
||||
if(false === $this->callHook('postSetCategories', $document, array(), $oldcategories)) {
|
||||
}
|
||||
}
|
||||
|
||||
$attributes = $this->params['attributes'];
|
||||
$oldattributes = $document->getAttributes();
|
||||
if($attributes) {
|
||||
foreach($attributes as $attrdefid=>$attribute) {
|
||||
if($attrdef = $dms->getAttributeDefinition($attrdefid)) {
|
||||
if(null === ($ret = $this->callHook('validateAttribute', $attrdef, $attribute))) {
|
||||
if($attribute) {
|
||||
switch($attrdef->getType()) {
|
||||
case SeedDMS_Core_AttributeDefinition::type_date:
|
||||
if(is_array($attribute))
|
||||
$attribute = array_map(fn($value): string => date('Y-m-d', makeTsFromDate($value)), $attribute);
|
||||
else
|
||||
$attribute = date('Y-m-d', makeTsFromDate($attribute));
|
||||
break;
|
||||
case SeedDMS_Core_AttributeDefinition::type_folder:
|
||||
if(is_array($attribute))
|
||||
$attribute = array_map(fn($value): object => $dms->getFolder((int) $value), $attribute);
|
||||
else
|
||||
$attribute = $dms->getFolder((int) $attribute);
|
||||
break;
|
||||
case SeedDMS_Core_AttributeDefinition::type_document:
|
||||
if(is_array($attribute))
|
||||
$attribute = array_map(fn($value): object => $dms->getDocument((int) $value), $attribute);
|
||||
else
|
||||
$attribute = $dms->getDocument((int) $attribute);
|
||||
break;
|
||||
case SeedDMS_Core_AttributeDefinition::type_user:
|
||||
if(is_array($attribute))
|
||||
$attribute = array_map(fn($value): object => $dms->getUser((int) $value), $attribute);
|
||||
else
|
||||
$attribute = $dms->getUser((int) $attribute);
|
||||
break;
|
||||
case SeedDMS_Core_AttributeDefinition::type_group:
|
||||
if(is_array($attribute))
|
||||
$attribute = array_map(fn($value): object => $dms->getGroup((int) $value), $attribute);
|
||||
else
|
||||
$attribute = $dms->getGroup((int) $attribute);
|
||||
break;
|
||||
}
|
||||
if(!$attrdef->validate($attribute, $document, false)) {
|
||||
$this->errormsg = getAttributeValidationError($attrdef->getValidationError(), $attrdef->getName(), $attribute);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!isset($oldattributes[$attrdefid]) || $attribute != $oldattributes[$attrdefid]->getValue()) {
|
||||
if(!$document->setAttributeValue($dms->getAttributeDefinition($attrdefid), $attribute))
|
||||
return false;
|
||||
}
|
||||
} elseif($attrdef->getMinValues() > 0) {
|
||||
$this->errormsg = array("attr_min_values", array("attrname"=>$attrdef->getName()));
|
||||
} elseif(isset($oldattributes[$attrdefid])) {
|
||||
if(!$document->removeAttribute($dms->getAttributeDefinition($attrdefid)))
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if($ret === false)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach($oldattributes as $attrdefid=>$oldattribute) {
|
||||
if(!isset($attributes[$attrdefid])) {
|
||||
if(!$document->removeAttribute($dms->getAttributeDefinition($attrdefid)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$sequence = $this->params['sequence'];
|
||||
if(strcasecmp($sequence, "keep")) {
|
||||
if($document->setSequence($sequence)) {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* There are various hooks in inc/inc.FulltextInit.php which will take
|
||||
* care of reindexing it. They just delete the indexing date which is
|
||||
* faster then indexing the folder completely
|
||||
*
|
||||
if($fulltextservice && ($index = $fulltextservice->Indexer()) && $document) {
|
||||
$idoc = $fulltextservice->IndexedDocument($document);
|
||||
if(false !== $this->callHook('preIndexDocument', $document, $idoc)) {
|
||||
$lucenesearch = $fulltextservice->Search();
|
||||
if($hit = $lucenesearch->getDocument((int) $document->getId())) {
|
||||
$index->delete($hit->id);
|
||||
}
|
||||
$index->addDocument($idoc);
|
||||
$index->commit();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
} elseif($result === false) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_editDocument_failed';
|
||||
return false;
|
||||
}
|
||||
|
||||
if(false === $this->callHook('postEditDocument')) {
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of EditDocumentFile controller
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class which does the busines logic for editing a document
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Controller_EditDocumentFile extends SeedDMS_Controller_Common {
|
||||
|
||||
public function run() {
|
||||
$dms = $this->params['dms'];
|
||||
$user = $this->params['user'];
|
||||
$settings = $this->params['settings'];
|
||||
$document = $this->params['document'];
|
||||
$file = $this->params['file'];
|
||||
|
||||
if(false === $this->callHook('preEditDocumentFile')) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_preEditDocumentFile_failed';
|
||||
return null;
|
||||
}
|
||||
|
||||
$result = $this->callHook('editDocumentFile', $document);
|
||||
if($result === null) {
|
||||
$name = $this->params['name'];
|
||||
$oldname = $file->getName();
|
||||
if($oldname != $name)
|
||||
if(!$file->setName($name))
|
||||
return false;
|
||||
|
||||
$comment = $this->params['comment'];
|
||||
if(($oldcomment = $file->getComment()) != $comment)
|
||||
if(!$file->setComment($comment))
|
||||
return false;
|
||||
|
||||
$version = $this->params["version"];
|
||||
$oldversion = $file->getVersion();
|
||||
if ($oldversion != $version)
|
||||
if(!$file->setVersion($version))
|
||||
return false;
|
||||
|
||||
$public = $this->params["public"];
|
||||
$file->setPublic($public == 'true' ? 1 : 0);
|
||||
|
||||
if(!$this->callHook('postEditDocumentFile')) {
|
||||
}
|
||||
|
||||
} else
|
||||
return $result;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -26,87 +26,83 @@ class SeedDMS_Controller_EditFolder extends SeedDMS_Controller_Common {
|
|||
$dms = $this->params['dms'];
|
||||
$user = $this->params['user'];
|
||||
$settings = $this->params['settings'];
|
||||
$fulltextservice = $this->params['fulltextservice'];
|
||||
$folder = $this->params['folder'];
|
||||
$name = $this->params['name'];
|
||||
$comment = $this->params['comment'];
|
||||
$sequence = $this->params['sequence'];
|
||||
$attributes = $this->params['attributes'];
|
||||
|
||||
if(false === $this->callHook('preEditFolder')) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_preEditFolder_failed';
|
||||
return null;
|
||||
/* Get the document id and name before removing the document */
|
||||
$foldername = $folder->getName();
|
||||
$folderid = $folder->getID();
|
||||
|
||||
if(!$this->callHook('preEditFolder')) {
|
||||
}
|
||||
|
||||
$result = $this->callHook('editFolder', $folder);
|
||||
if($result === null) {
|
||||
$name = $this->params['name'];
|
||||
if(($oldname = $folder->getName()) != $name)
|
||||
if(!$folder->setName($name))
|
||||
return false;
|
||||
|
||||
$comment = $this->params['comment'];
|
||||
if(($oldcomment = $folder->getComment()) != $comment)
|
||||
if(!$folder->setComment($comment))
|
||||
return false;
|
||||
|
||||
$attributes = $this->params['attributes'];
|
||||
$oldattributes = $folder->getAttributes();
|
||||
if($attributes) {
|
||||
foreach($attributes as $attrdefid=>$attribute) {
|
||||
if($attrdef = $dms->getAttributeDefinition($attrdefid)) {
|
||||
if(null === ($ret = $this->callHook('validateAttribute', $attrdef, $attribute))) {
|
||||
$attrdef = $dms->getAttributeDefinition($attrdefid);
|
||||
if($attribute) {
|
||||
switch($attrdef->getType()) {
|
||||
case SeedDMS_Core_AttributeDefinition::type_date:
|
||||
if(is_array($attribute))
|
||||
$attribute = array_map(fn($value): string => date('Y-m-d', makeTsFromDate($value)), $attribute);
|
||||
else
|
||||
$attribute = date('Y-m-d', makeTsFromDate($attribute));
|
||||
if(!$attrdef->validate($attribute)) {
|
||||
$this->error = $attrdef->getValidationError();
|
||||
switch($attrdef->getValidationError()) {
|
||||
case 5:
|
||||
$this->errormsg = getMLText("attr_malformed_email", array("attrname"=>$attrdef->getName(), "value"=>$attribute));
|
||||
break;
|
||||
case SeedDMS_Core_AttributeDefinition::type_folder:
|
||||
if(is_array($attribute))
|
||||
$attribute = array_map(fn($value): object => $dms->getFolder((int) $value), $attribute);
|
||||
else
|
||||
$attribute = $dms->getFolder((int) $attribute);
|
||||
case 4:
|
||||
$this->errormsg = getMLText("attr_malformed_url", array("attrname"=>$attrdef->getName(), "value"=>$attribute));
|
||||
break;
|
||||
case SeedDMS_Core_AttributeDefinition::type_document:
|
||||
if(is_array($attribute))
|
||||
$attribute = array_map(fn($value): object => $dms->getDocument((int) $value), $attribute);
|
||||
else
|
||||
$attribute = $dms->getDocument((int) $attribute);
|
||||
case 3:
|
||||
$this->errormsg = getMLText("attr_no_regex_match", array("attrname"=>$attrdef->getName(), "value"=>$attribute, "regex"=>$attrdef->getRegex()));
|
||||
break;
|
||||
case SeedDMS_Core_AttributeDefinition::type_user:
|
||||
if(is_array($attribute))
|
||||
$attribute = array_map(fn($value): object => $dms->getUser((int) $value), $attribute);
|
||||
else
|
||||
$attribute = $dms->getUser((int) $attribute);
|
||||
case 2:
|
||||
$this->errormsg = getMLText("attr_max_values", array("attrname"=>$attrdef->getName()));
|
||||
break;
|
||||
case SeedDMS_Core_AttributeDefinition::type_group:
|
||||
if(is_array($attribute))
|
||||
$attribute = array_map(fn($value): object => $dms->getGroup((int) $value), $attribute);
|
||||
else
|
||||
$attribute = $dms->getGroup((int) $attribute);
|
||||
case 1:
|
||||
$this->errormsg = getMLText("attr_min_values", array("attrname"=>$attrdef->getName()));
|
||||
break;
|
||||
default:
|
||||
$this->errormsg = getMLText("error_occured");
|
||||
}
|
||||
if(!$attrdef->validate($attribute, $folder, false)) {
|
||||
$this->errormsg = getAttributeValidationText($attrdef->getValidationError(), $attrdef->getName(), $attribute);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
if($attrdef->getRegex()) {
|
||||
if(!preg_match($attrdef->getRegex(), $attribute)) {
|
||||
$this->error = 1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(is_array($attribute)) {
|
||||
if($attrdef->getMinValues() > count($attribute)) {
|
||||
$this->error = 2;
|
||||
return false;
|
||||
}
|
||||
if($attrdef->getMaxValues() && $attrdef->getMaxValues() < count($attribute)) {
|
||||
$this->error = 3;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
*/
|
||||
if(!isset($oldattributes[$attrdefid]) || $attribute != $oldattributes[$attrdefid]->getValue()) {
|
||||
if(!$folder->setAttributeValue($dms->getAttributeDefinition($attrdefid), $attribute))
|
||||
return false;
|
||||
}
|
||||
} elseif($attrdef->getMinValues() > 0) {
|
||||
$this->errormsg = getMLText("attr_min_values", array("attrname"=>$attrdef->getName()));
|
||||
return false;
|
||||
} elseif(isset($oldattributes[$attrdefid])) {
|
||||
if(!$folder->removeAttribute($dms->getAttributeDefinition($attrdefid)))
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if($ret === false)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach($oldattributes as $attrdefid=>$oldattribute) {
|
||||
|
@ -116,7 +112,6 @@ class SeedDMS_Controller_EditFolder extends SeedDMS_Controller_Common {
|
|||
}
|
||||
}
|
||||
|
||||
$sequence = $this->params['sequence'];
|
||||
if(strcasecmp($sequence, "keep")) {
|
||||
if($folder->setSequence($sequence)) {
|
||||
} else {
|
||||
|
@ -124,31 +119,11 @@ class SeedDMS_Controller_EditFolder extends SeedDMS_Controller_Common {
|
|||
}
|
||||
}
|
||||
|
||||
/* There are various hooks in inc/inc.FulltextInit.php which will take
|
||||
* care of reindexing it. They just delete the indexing date which is
|
||||
* faster then indexing the folder completely
|
||||
*
|
||||
if($fulltextservice && ($index = $fulltextservice->Indexer()) && $folder) {
|
||||
$idoc = $fulltextservice->IndexedDocument($folder);
|
||||
if(false !== $this->callHook('preIndexFolder', $folder, $idoc)) {
|
||||
$lucenesearch = $fulltextservice->Search();
|
||||
if($hit = $lucenesearch->getFolder((int) $folder->getId())) {
|
||||
$index->delete($hit->id);
|
||||
}
|
||||
$index->addDocument($idoc);
|
||||
$index->commit();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
} elseif($result === false) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_editFolder_failed';
|
||||
return false;
|
||||
if(!$this->callHook('postEditFolder')) {
|
||||
}
|
||||
|
||||
if(false === $this->callHook('postEditFolder')) {
|
||||
}
|
||||
} else
|
||||
return $result;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,98 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of EmptyFolder controller
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class which does the busines logic for downloading a document
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Controller_EmptyFolder extends SeedDMS_Controller_Common {
|
||||
|
||||
/* Register a callback which removes each document/folder from the fulltext index
|
||||
* The callback must return null otherwise the removal will be canceled.
|
||||
*/
|
||||
static function removeFromIndex($arr, $object) { /* {{{ */
|
||||
$fulltextservice = $arr[0];
|
||||
$lucenesearch = $fulltextservice->Search();
|
||||
$hit = null;
|
||||
if($object->isType('document'))
|
||||
$hit = $lucenesearch->getDocument($object->getID());
|
||||
elseif($object->isType('folder'))
|
||||
$hit = $lucenesearch->getFolder($object->getID());
|
||||
if($hit) {
|
||||
$index = $fulltextservice->Indexer();
|
||||
$index->delete($hit->id);
|
||||
$index->commit();
|
||||
}
|
||||
return null;
|
||||
} /* }}} */
|
||||
|
||||
static function removePreviews($arr, $document) { /* {{{ */
|
||||
$previewer = $arr[0];
|
||||
|
||||
$previewer->deleteDocumentPreviews($document);
|
||||
return null;
|
||||
} /* }}} */
|
||||
|
||||
public function run() { /* {{{ */
|
||||
$dms = $this->params['dms'];
|
||||
$user = $this->params['user'];
|
||||
$settings = $this->params['settings'];
|
||||
$folder = $this->params['folder'];
|
||||
$fulltextservice = $this->params['fulltextservice'];
|
||||
|
||||
/* Get the folder id and name before removing the folder */
|
||||
$foldername = $folder->getName();
|
||||
$folderid = $folder->getID();
|
||||
|
||||
if(false === $this->callHook('preEmptyFolder')) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_preEmptyFolder_failed';
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = $this->callHook('emptyFolder', $folder);
|
||||
if($result === null) {
|
||||
if($fulltextservice && ($index = $fulltextservice->Indexer())) {
|
||||
/* Register a callback which is called by SeedDMS_Core when a folder
|
||||
* or document is removed. The second parameter passed to this callback
|
||||
* is the document or folder to be removed.
|
||||
*/
|
||||
$dms->addCallback('onPreRemoveDocument', 'SeedDMS_Controller_EmptyFolder::removeFromIndex', array($fulltextservice));
|
||||
$dms->addCallback('onPreRemoveFolder', 'SeedDMS_Controller_EmptyFolder::removeFromIndex', array($fulltextservice));
|
||||
}
|
||||
|
||||
/* Register another callback which removes the preview images of the document */
|
||||
$previewer = new SeedDMS_Preview_Previewer($settings->_cacheDir);
|
||||
$dms->addCallback('onPreRemoveDocument', 'SeedDMS_Controller_EmptyFolder::removePreviews', array($previewer));
|
||||
|
||||
if (!$folder->emptyFolder()) {
|
||||
$this->errormsg = 'error_occured';
|
||||
return false;
|
||||
}
|
||||
} elseif($result === false) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_emptyFolder_failed';
|
||||
return false;
|
||||
}
|
||||
|
||||
if(false === $this->callHook('postEmptyFolder')) {
|
||||
}
|
||||
|
||||
return true;
|
||||
} /* }}} */
|
||||
}
|
|
@ -1,97 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of ExtensionMgr controller
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2018 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class which does the busines logic for managing extensions
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2018 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Controller_ExtensionMgr extends SeedDMS_Controller_Common {
|
||||
|
||||
public function refresh() { /* {{{ */
|
||||
$dms = $this->params['dms'];
|
||||
$extmgr = $this->params['extmgr'];
|
||||
|
||||
$extmgr->createExtensionConf();
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
public function download() { /* {{{ */
|
||||
$dms = $this->params['dms'];
|
||||
$settings = $this->params['settings'];
|
||||
$extmgr = $this->params['extmgr'];
|
||||
$extname = $this->params['extname'];
|
||||
|
||||
$filename = $extmgr->createArchive($extname, $extmgr->getExtensionConfiguration()[$extname]['version']);
|
||||
|
||||
if(null === $this->callHook('download')) {
|
||||
if(file_exists($filename)) {
|
||||
header("Content-Transfer-Encoding: binary");
|
||||
header("Content-Disposition: attachment; filename=\"" . utf8_basename($filename) . "\"; filename*=UTF-8''".utf8_basename($filename));
|
||||
header("Content-Type: application/zip");
|
||||
header("Cache-Control: must-revalidate");
|
||||
|
||||
sendFile($filename);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
public function upload() { /* {{{ */
|
||||
$dms = $this->params['dms'];
|
||||
$extmgr = $this->params['extmgr'];
|
||||
$file = $this->params['file'];
|
||||
|
||||
if($extmgr->updateExtension($file)) {
|
||||
$extmgr->createExtensionConf();
|
||||
} else {
|
||||
$this->setErrorMsg($extmgr->getErrorMsg());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
public function getlist() { /* {{{ */
|
||||
$dms = $this->params['dms'];
|
||||
$extmgr = $this->params['extmgr'];
|
||||
$forceupdate = $this->params['forceupdate'];
|
||||
$version = $this->params['version'];
|
||||
|
||||
if(!$extmgr->updateExtensionList($version, $forceupdate)) {
|
||||
$this->errormsg = $extmgr->getErrorMsg();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
public function toggle() { /* {{{ */
|
||||
$dms = $this->params['dms'];
|
||||
$settings = $this->params['settings'];
|
||||
$extmgr = $this->params['extmgr'];
|
||||
$extname = $this->params['extname'];
|
||||
|
||||
if($settings->extensionIsDisabled($extname))
|
||||
$settings->enableExtension($extname);
|
||||
else
|
||||
$settings->disableExtension($extname);
|
||||
$settings->save();
|
||||
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
}
|
|
@ -21,256 +21,14 @@
|
|||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Controller_Login extends SeedDMS_Controller_Common {
|
||||
/**
|
||||
* @var array $user set if user could be logged in
|
||||
* @access protected
|
||||
*/
|
||||
static protected $user;
|
||||
|
||||
public function getUser() { /* {{{ */
|
||||
return self::$user;
|
||||
} /* }}} */
|
||||
|
||||
public function _finalize($user) { /* {{{ */
|
||||
$settings = $this->params['settings'];
|
||||
$session = $this->params['session'];
|
||||
$sesstheme = $this->params['sesstheme'];
|
||||
$source = isset($this->params['source']) ? $this->params['source'] : '';
|
||||
$lang = $this->params['lang'];
|
||||
|
||||
self::$user = $user;
|
||||
|
||||
/* Check for other restrictions which prevent the user from login, though
|
||||
* the authentication was successfull.
|
||||
* Checking for a guest login the second time, makes only sense if there are
|
||||
* more guest users and the login was done with a password and a user name
|
||||
* unequal to 'guest'.
|
||||
*/
|
||||
$userid = $user->getID();
|
||||
if (($userid == $settings->_guestID) && (!$settings->_enableGuestLogin)) {
|
||||
$this->setErrorMsg("guest_login_disabled");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if account is disabled
|
||||
if($user->isDisabled()) {
|
||||
$this->setErrorMsg("login_disabled_text");
|
||||
return false;
|
||||
}
|
||||
|
||||
// control admin IP address if required
|
||||
if ($user->isAdmin() && ($_SERVER['REMOTE_ADDR'] != $settings->_adminIP ) && ( $settings->_adminIP != "") ){
|
||||
$this->setErrorMsg("invalid_user_id");
|
||||
return false;
|
||||
}
|
||||
|
||||
if($settings->_enable2FactorAuthentication) {
|
||||
if($user->getSecret()) {
|
||||
$tfa = new \RobThree\Auth\TwoFactorAuth('SeedDMS');
|
||||
if($tfa->verifyCode($user->getSecret(), $_POST['twofactauth']) !== true) {
|
||||
$this->setErrorMsg("login_error_text");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Run any additional checks which may prevent login */
|
||||
if(false === $this->callHook('restrictLogin', $user)) {
|
||||
if(empty($this->errormsg))
|
||||
$this->setErrorMsg("login_restrictions_apply");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Clear login failures if login was successful */
|
||||
$user->clearLoginFailures();
|
||||
|
||||
/* Setting the theme and language and all the cookie handling is
|
||||
* only done when authentication was requested from a weg page.
|
||||
*/
|
||||
if($source == 'web') {
|
||||
// Capture the user's language and theme settings.
|
||||
if ($lang) {
|
||||
$user->setLanguage($lang);
|
||||
} else {
|
||||
$lang = $user->getLanguage();
|
||||
if (strlen($lang)==0) {
|
||||
$lang = $settings->_language;
|
||||
$user->setLanguage($lang);
|
||||
}
|
||||
}
|
||||
if ($sesstheme) {
|
||||
$user->setTheme($sesstheme);
|
||||
}
|
||||
else {
|
||||
$sesstheme = $user->getTheme();
|
||||
/* Override the theme if the user doesn't have one or the default theme
|
||||
* shall override it.
|
||||
*/
|
||||
if (strlen($sesstheme)==0 || !empty($settings->_overrideTheme)) {
|
||||
$sesstheme = $settings->_theme;
|
||||
// $user->setTheme($sesstheme);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete all sessions that are more than 1 week or the configured
|
||||
// cookie lifetime old. Probably not the most
|
||||
// reliable place to put this check -- move to inc.Authentication.php?
|
||||
if($settings->_cookieLifetime)
|
||||
$lifetime = intval($settings->_cookieLifetime);
|
||||
else
|
||||
$lifetime = 7*86400;
|
||||
if(!$session->deleteByTime($lifetime)) {
|
||||
$this->setErrorMsg("error_occured");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isset($_COOKIE["mydms_session"])) {
|
||||
/* This part will never be reached unless the session cookie is kept,
|
||||
* but op.Logout.php deletes it. Keeping a session could be a good idea
|
||||
* for retaining the clipboard data, but the user id in the session should
|
||||
* be set to 0 which is not possible due to foreign key constraints.
|
||||
* So for now op.Logout.php will delete the cookie as always
|
||||
*/
|
||||
/* Load session */
|
||||
$dms_session = $_COOKIE["mydms_session"];
|
||||
if(!$resArr = $session->load($dms_session)) {
|
||||
/* Turn off http only cookies if jumploader is enabled */
|
||||
setcookie("mydms_session", $dms_session, time()-3600, $settings->_httpRoot, null, false, true); //delete cookie
|
||||
header("Location: " . $settings->_httpRoot . "out/out.Login.php?referuri=".$referuri);
|
||||
exit;
|
||||
} else {
|
||||
$session->updateAccess($dms_session);
|
||||
$session->setUser($userid);
|
||||
}
|
||||
} else {
|
||||
// Create new session in database
|
||||
if(!$id = $session->create(array('userid'=>$userid, 'theme'=>$sesstheme, 'lang'=>$lang))) {
|
||||
$this->setErrorMsg("error_occured");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the session cookie.
|
||||
if($settings->_cookieLifetime)
|
||||
$lifetime = time() + intval($settings->_cookieLifetime);
|
||||
else
|
||||
$lifetime = 0;
|
||||
setcookie("mydms_session", $id, $lifetime, $settings->_httpRoot, null, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
if($this->callHook('postLogin', $user)) {
|
||||
}
|
||||
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
public function run() { /* {{{ */
|
||||
public function run() {
|
||||
$dms = $this->params['dms'];
|
||||
$user = $this->params['user'];
|
||||
$settings = $this->params['settings'];
|
||||
$session = $this->params['session'];
|
||||
$authenticator = $this->params['authenticator'];
|
||||
$source = isset($this->params['source']) ? $this->params['source'] : '';
|
||||
$sesstheme = $this->getParam('sesstheme');
|
||||
$referuri = $this->getParam('referuri');
|
||||
$lang = $this->getParam('lang');
|
||||
$login = $this->params['login'];
|
||||
$pwd = $this->params['pwd'];
|
||||
|
||||
self::$user = null;
|
||||
|
||||
/* The preLogin hook may set self::$user which will prevent any further
|
||||
* authentication process.
|
||||
*/
|
||||
if($this->callHook('preLogin')) {
|
||||
}
|
||||
|
||||
$user = self::$user;
|
||||
|
||||
/* The password may only be empty if the guest user tries to log in.
|
||||
* There is just one guest account with id $settings->_guestID which
|
||||
* is allowed to log in without a password. All other guest accounts
|
||||
* are treated like regular logins
|
||||
*/
|
||||
if(!$user && $settings->_enableGuestLogin && (int) $settings->_guestID) {
|
||||
$guestUser = $dms->getUser((int) $settings->_guestID);
|
||||
if($guestUser) {
|
||||
if(($login != $guestUser->getLogin())) {
|
||||
if ((!isset($pwd) || strlen($pwd)==0)) {
|
||||
$this->setErrorMsg("login_error_text");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$user = $guestUser;
|
||||
if($this->callHook('postLogin')) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Run any additional authentication method. The hook must return a
|
||||
* valid user, if the authentication succeeded. If it fails, it must
|
||||
* return false and if the hook doesn't care at all, if must return null.
|
||||
*/
|
||||
if(!$user) {
|
||||
$user = $this->callHook('authenticate', $source);
|
||||
if(false === $user) {
|
||||
if(empty($this->errormsg))
|
||||
$this->setErrorMsg("authentication_failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Deprecated: Run any additional authentication implemented in a hook */
|
||||
if(!is_object($user) && isset($GLOBALS['SEEDDMS_HOOKS']['authentication'])) {
|
||||
foreach($GLOBALS['SEEDDMS_HOOKS']['authentication'] as $authObj) {
|
||||
if(!$user && method_exists($authObj, 'authenticate')) {
|
||||
$user = $authObj->authenticate($dms, $settings, $login, $pwd);
|
||||
if(false === $user) {
|
||||
if(empty($this->errormsg))
|
||||
$this->setErrorMsg("authentication_failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!is_object($user))
|
||||
$user = $authenticator->authenticate($login, $pwd);
|
||||
|
||||
if(0) {
|
||||
/* Authenticate against LDAP server {{{ */
|
||||
if (!is_object($user) && isset($settings->_ldapHost) && strlen($settings->_ldapHost)>0) {
|
||||
require_once("../inc/inc.ClassLdapAuthentication.php");
|
||||
$authobj = new SeedDMS_LdapAuthentication($dms, $settings);
|
||||
$user = $authobj->authenticate($login, $pwd);
|
||||
if(!$user) {
|
||||
add_log_line('Authentication against LDAP failed for user '.$login);
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
/* Authenticate against SeedDMS database {{{ */
|
||||
if(!is_object($user)) {
|
||||
require_once("../inc/inc.ClassDbAuthentication.php");
|
||||
$authobj = new SeedDMS_DbAuthentication($dms, $settings);
|
||||
$user = $authobj->authenticate($login, $pwd);
|
||||
} /* }}} */
|
||||
}
|
||||
|
||||
/* If the user is still not authenticated, then exit with an error */
|
||||
if(!is_object($user)) {
|
||||
/* if counting of login failures is turned on, then increment its value */
|
||||
if($settings->_loginFailure) {
|
||||
$user = $dms->getUserByLogin($login);
|
||||
if($user) {
|
||||
$failures = $user->addLoginFailure();
|
||||
if($failures >= $settings->_loginFailure)
|
||||
$user->setDisabled(true);
|
||||
}
|
||||
}
|
||||
$this->callHook('loginFailed');
|
||||
$this->setErrorMsg("login_error_text");
|
||||
return false;
|
||||
}
|
||||
|
||||
return self::_finalize($user);
|
||||
|
||||
} /* }}} */
|
||||
}
|
||||
|
|
|
@ -1,78 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of PdfPreview controller
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class which does the busines logic for previewing a document
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Controller_PdfPreview extends SeedDMS_Controller_Common {
|
||||
|
||||
public function run() {
|
||||
global $theme;
|
||||
$dms = $this->params['dms'];
|
||||
$type = $this->params['type'];
|
||||
$settings = $this->params['settings'];
|
||||
$conversionmgr = $this->params['conversionmgr'];
|
||||
|
||||
switch($type) {
|
||||
case "version":
|
||||
$version = $this->params['version'];
|
||||
$document = $this->params['document'];
|
||||
if($version < 1) {
|
||||
$content = $this->callHook('documentLatestContent', $document);
|
||||
if($content === null)
|
||||
$content = $document->getLatestContent();
|
||||
} else {
|
||||
$content = $this->callHook('documentContent', $document, $version);
|
||||
if($content === null)
|
||||
$content = $document->getContentByVersion($version);
|
||||
}
|
||||
if (!is_object($content)) {
|
||||
$this->errormsg = 'invalid_version';
|
||||
return false;
|
||||
}
|
||||
/* set params['content'] for compatiblity with older extensions which
|
||||
* expect the content in the controller
|
||||
*/
|
||||
$this->params['content'] = $content;
|
||||
if(null === $this->callHook('version')) {
|
||||
$previewer = new SeedDMS_Preview_PdfPreviewer($settings->_cacheDir, $settings->_cmdTimeout);
|
||||
if($conversionmgr)
|
||||
$previewer->setConversionMgr($conversionmgr);
|
||||
else
|
||||
$previewer->setConverters(isset($settings->_converters['pdf']) ? $settings->_converters['pdf'] : array());
|
||||
$previewer->setXsendfile($settings->_enableXsendfile);
|
||||
if(!$previewer->hasPreview($content)) {
|
||||
add_log_line("");
|
||||
if(!$previewer->createPreview($content)) {
|
||||
add_log_line("", PEAR_LOG_ERR);
|
||||
}
|
||||
}
|
||||
if(!$previewer->hasPreview($content)) {
|
||||
header('Content-Type: application/pdf');
|
||||
readfile('../views/'.$theme.'/images/empty.pdf');
|
||||
exit;
|
||||
}
|
||||
header('Content-Type: application/pdf');
|
||||
$previewer->getPreview($content);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,114 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of Preview controller
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class which does the busines logic for previewing a document
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Controller_Preview extends SeedDMS_Controller_Common {
|
||||
|
||||
public function version() { /* {{{ */
|
||||
$dms = $this->params['dms'];
|
||||
$settings = $this->params['settings'];
|
||||
$conversionmgr = $this->params['conversionmgr'];
|
||||
|
||||
$version = $this->params['version'];
|
||||
$document = $this->params['document'];
|
||||
$width = $this->params['width'];
|
||||
if($version < 1) {
|
||||
$content = $this->callHook('documentLatestContent', $document);
|
||||
if($content === null)
|
||||
$content = $document->getLatestContent();
|
||||
} else {
|
||||
$content = $this->callHook('documentContent', $document, $version);
|
||||
if($content === null)
|
||||
$content = $document->getContentByVersion($version);
|
||||
}
|
||||
if (!is_object($content)) {
|
||||
$this->errormsg = 'invalid_version';
|
||||
return false;
|
||||
}
|
||||
/* set params['content'] for compatiblity with older extensions which
|
||||
* expect the content in the controller
|
||||
*/
|
||||
$this->params['content'] = $content;
|
||||
if(null === $this->callHook('version')) {
|
||||
if($width)
|
||||
$previewer = new SeedDMS_Preview_Previewer($settings->_cacheDir, $width, $settings->_cmdTimeout);
|
||||
else
|
||||
$previewer = new SeedDMS_Preview_Previewer($settings->_cacheDir);
|
||||
if($conversionmgr)
|
||||
$previewer->setConversionMgr($conversionmgr);
|
||||
else
|
||||
$previewer->setConverters($settings->_converters['preview']);
|
||||
$previewer->setXsendfile($settings->_enableXsendfile);
|
||||
if(!$previewer->hasPreview($content)) {
|
||||
add_log_line("");
|
||||
if(!$previewer->createPreview($content)) {
|
||||
add_log_line("", PEAR_LOG_ERR);
|
||||
}
|
||||
}
|
||||
if(!$previewer->hasPreview($content)) {
|
||||
return false;
|
||||
}
|
||||
header('Content-Type: image/png');
|
||||
$previewer->getPreview($content);
|
||||
return true;
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
public function file() { /* {{{ */
|
||||
$dms = $this->params['dms'];
|
||||
$settings = $this->params['settings'];
|
||||
$conversionmgr = $this->params['conversionmgr'];
|
||||
|
||||
$object = $this->params['object'];
|
||||
$document = $this->params['document'];
|
||||
$width = $this->params['width'];
|
||||
if (!is_object($object)) {
|
||||
$this->errormsg = 'invalid_version';
|
||||
return false;
|
||||
}
|
||||
|
||||
if(null === $this->callHook('file')) {
|
||||
if($width)
|
||||
$previewer = new SeedDMS_Preview_Previewer($settings->_cacheDir, $width, $settings->_cmdTimeout);
|
||||
else
|
||||
$previewer = new SeedDMS_Preview_Previewer($settings->_cacheDir);
|
||||
if($conversionmgr)
|
||||
$previewer->setConversionMgr($conversionmgr);
|
||||
else
|
||||
$previewer->setConverters($settings->_converters['preview']);
|
||||
$previewer->setXsendfile($settings->_enableXsendfile);
|
||||
|
||||
if(!$previewer->hasPreview($object)) {
|
||||
add_log_line("");
|
||||
if(!$previewer->createPreview($object)) {
|
||||
add_log_line("", PEAR_LOG_ERR);
|
||||
}
|
||||
}
|
||||
if(!$previewer->hasPreview($object)) {
|
||||
return false;
|
||||
}
|
||||
header('Content-Type: image/png');
|
||||
$previewer->getPreview($object);
|
||||
return true;
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of ReceiptDocument controller
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class which does the busines logic for downloading a document
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Controller_ReceiptDocument extends SeedDMS_Controller_Common {
|
||||
|
||||
public function run() {
|
||||
$dms = $this->params['dms'];
|
||||
$user = $this->params['user'];
|
||||
$settings = $this->params['settings'];
|
||||
$document = $this->params['document'];
|
||||
$content = $this->params['content'];
|
||||
$receiptstatus = $this->params['receiptstatus'];
|
||||
$receipttype = $this->params['receipttype'];
|
||||
$group = $this->params['group'];
|
||||
$comment = $this->params['comment'];
|
||||
|
||||
/* Get the document id and name before removing the document */
|
||||
$docname = $document->getName();
|
||||
$documentid = $document->getID();
|
||||
|
||||
if(!$this->callHook('preReceiptDocument', $content)) {
|
||||
}
|
||||
|
||||
$result = $this->callHook('receiptDocument', $content);
|
||||
if($result === null) {
|
||||
|
||||
if ($receipttype == "ind") {
|
||||
if(0 > $content->setReceiptByInd($user, $user, $receiptstatus, $comment)) {
|
||||
$this->error = 1;
|
||||
$this->errormsg = "receipt_update_failed";
|
||||
return false;
|
||||
}
|
||||
} elseif ($receipttype == "grp") {
|
||||
if(0 > $content->setReceiptByGrp($group, $user, $receiptstatus, $comment)) {
|
||||
$this->error = 1;
|
||||
$this->errormsg = "receipt_update_failed";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!$this->callHook('postReceiptDocument', $content)) {
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -27,7 +27,8 @@ class SeedDMS_Controller_RemoveDocument extends SeedDMS_Controller_Common {
|
|||
$user = $this->params['user'];
|
||||
$settings = $this->params['settings'];
|
||||
$document = $this->params['document'];
|
||||
$fulltextservice = $this->params['fulltextservice'];
|
||||
$index = $this->params['index'];
|
||||
$indexconf = $this->params['indexconf'];
|
||||
|
||||
$folder = $document->getFolder();
|
||||
|
||||
|
@ -35,39 +36,27 @@ class SeedDMS_Controller_RemoveDocument extends SeedDMS_Controller_Common {
|
|||
$docname = $document->getName();
|
||||
$documentid = $document->getID();
|
||||
|
||||
if(false === $this->callHook('preRemoveDocument')) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_preRemoveDocument_failed';
|
||||
return false;
|
||||
if(!$this->callHook('preRemoveDocument')) {
|
||||
}
|
||||
|
||||
$result = $this->callHook('removeDocument', $document);
|
||||
if($result === null) {
|
||||
$previewer = new SeedDMS_Preview_Previewer($settings->_cacheDir);
|
||||
$previewer->deleteDocumentPreviews($document);
|
||||
if (!$document->remove()) {
|
||||
if($dms->lasterror)
|
||||
$this->errormsg = $dms->lasterror;
|
||||
else
|
||||
$this->errormsg = "error_occured";
|
||||
return false;
|
||||
}
|
||||
} elseif($result === false) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_removeDocument_failed';
|
||||
return false;
|
||||
} else {
|
||||
|
||||
if(!$this->callHook('postRemoveDocument')) {
|
||||
}
|
||||
|
||||
/* Remove the document from the fulltext index */
|
||||
if($fulltextservice && ($index = $fulltextservice->Indexer())) {
|
||||
$lucenesearch = $fulltextservice->Search();
|
||||
if($index) {
|
||||
$lucenesearch = new $indexconf['Search']($index);
|
||||
if($hit = $lucenesearch->getDocument($documentid)) {
|
||||
$index->delete($hit->id);
|
||||
$index->commit();
|
||||
}
|
||||
}
|
||||
|
||||
if(false === $this->callHook('postRemoveDocument')) {
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -22,77 +22,50 @@
|
|||
*/
|
||||
class SeedDMS_Controller_RemoveFolder extends SeedDMS_Controller_Common {
|
||||
|
||||
/* Register a callback which removes each document/folder from the fulltext index
|
||||
* The callback must return null otherwise the removal will be canceled.
|
||||
*/
|
||||
static function removeFromIndex($arr, $object) { /* {{{ */
|
||||
$fulltextservice = $arr[0];
|
||||
$lucenesearch = $fulltextservice->Search();
|
||||
$hit = null;
|
||||
if($object->isType('document'))
|
||||
$hit = $lucenesearch->getDocument($object->getID());
|
||||
elseif($object->isType('folder'))
|
||||
$hit = $lucenesearch->getFolder($object->getID());
|
||||
if($hit) {
|
||||
$index = $fulltextservice->Indexer();
|
||||
$index->delete($hit->id);
|
||||
$index->commit();
|
||||
}
|
||||
return null;
|
||||
} /* }}} */
|
||||
|
||||
static function removePreviews($arr, $document) { /* {{{ */
|
||||
$previewer = $arr[0];
|
||||
|
||||
$previewer->deleteDocumentPreviews($document);
|
||||
return null;
|
||||
} /* }}} */
|
||||
|
||||
public function run() { /* {{{ */
|
||||
public function run() {
|
||||
$dms = $this->params['dms'];
|
||||
$user = $this->params['user'];
|
||||
$settings = $this->params['settings'];
|
||||
$folder = $this->params['folder'];
|
||||
$fulltextservice = $this->params['fulltextservice'];
|
||||
$index = $this->params['index'];
|
||||
$indexconf = $this->params['indexconf'];
|
||||
|
||||
/* Get the folder id and name before removing the folder */
|
||||
/* Get the document id and name before removing the document */
|
||||
$foldername = $folder->getName();
|
||||
$folderid = $folder->getID();
|
||||
|
||||
if(false === $this->callHook('preRemoveFolder')) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_preRemoveFolder_failed';
|
||||
return false;
|
||||
if(!$this->callHook('preRemoveFolder')) {
|
||||
}
|
||||
|
||||
$result = $this->callHook('removeFolder', $folder);
|
||||
if($result === null) {
|
||||
if($fulltextservice && ($index = $fulltextservice->Indexer())) {
|
||||
/* Register a callback which is called by SeedDMS_Core when a folder
|
||||
* or document is removed. The second parameter passed to this callback
|
||||
* is the document or folder to be removed.
|
||||
/* Register a callback which removes each document from the fulltext index
|
||||
* The callback must return true other the removal will be canceled.
|
||||
*/
|
||||
$dms->addCallback('onPreRemoveDocument', 'SeedDMS_Controller_RemoveFolder::removeFromIndex', array($fulltextservice));
|
||||
$dms->addCallback('onPreRemoveFolder', 'SeedDMS_Controller_RemoveFolder::removeFromIndex', array($fulltextservice));
|
||||
function removeFromIndex($arr, $document) {
|
||||
$index = $arr[0];
|
||||
$indexconf = $arr[1];
|
||||
$lucenesearch = new $indexconf['Search']($index);
|
||||
if($hit = $lucenesearch->getDocument($document->getID())) {
|
||||
$index->delete($hit->id);
|
||||
$index->commit();
|
||||
}
|
||||
|
||||
/* Register another callback which removes the preview images of the document */
|
||||
$previewer = new SeedDMS_Preview_Previewer($settings->_cacheDir);
|
||||
$dms->addCallback('onPreRemoveDocument', 'SeedDMS_Controller_RemoveFolder::removePreviews', array($previewer));
|
||||
return true;
|
||||
}
|
||||
if($index)
|
||||
$dms->setCallback('onPreRemoveDocument', 'removeFromIndex', array($index, $indexconf));
|
||||
|
||||
if (!$folder->remove()) {
|
||||
$this->errormsg = 'error_occured';
|
||||
return false;
|
||||
}
|
||||
} elseif($result === false) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_removeFolder_failed';
|
||||
return false;
|
||||
} else {
|
||||
|
||||
if(!$this->callHook('postRemoveFolder')) {
|
||||
}
|
||||
|
||||
if(false === $this->callHook('postRemoveFolder')) {
|
||||
}
|
||||
} else
|
||||
return $result;
|
||||
|
||||
return true;
|
||||
} /* }}} */
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,131 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of ReviewDocument controller
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2023 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class which does the busines logic for reviewing a document
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2023 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Controller_ReviewDocument extends SeedDMS_Controller_Common {
|
||||
|
||||
public function run() { /* {{{ */
|
||||
$dms = $this->params['dms'];
|
||||
$user = $this->params['user'];
|
||||
$settings = $this->params['settings'];
|
||||
$content = $this->params['content'];
|
||||
$reviewtype = $this->params['type'];
|
||||
$reviewstatus = $this->params['status'];
|
||||
$reviewcomment = $this->params['comment'];
|
||||
$reviewfile = $this->params['file'];
|
||||
$reviewgroup = $this->params['group'];
|
||||
$overallStatus = $content->getStatus();
|
||||
$this->oldstatus = $overallStatus['status'];
|
||||
$this->newstatus = $this->oldstatus;
|
||||
|
||||
if(!$this->callHook('preReviewDocument', $content)) {
|
||||
}
|
||||
|
||||
$result = $this->callHook('reviewDocument', $content);
|
||||
if($result === null) {
|
||||
if ($reviewtype == "ind") {
|
||||
$reviewLogID = $content->setReviewByInd($user, $user, $reviewstatus, $reviewcomment, $reviewfile);
|
||||
} elseif($reviewtype == "grp") {
|
||||
$reviewLogID = $content->setReviewByGrp($reviewgroup, $user, $reviewstatus, $reviewcomment, $reviewfile);
|
||||
} else {
|
||||
$this->errormsg = "review_wrong_type";
|
||||
return false;
|
||||
}
|
||||
if($reviewLogID === false || 0 > $reviewLogID) {
|
||||
$this->errormsg = "review_update_failed";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$result = $this->callHook('reviewUpdateDocumentStatus', $content);
|
||||
if($result === null) {
|
||||
if($reviewstatus == -1) {
|
||||
$this->newstatus = S_REJECTED;
|
||||
if($content->setStatus(S_REJECTED, $reviewcomment, $user)) {
|
||||
if(isset($GLOBALS['SEEDDMS_HOOKS']['reviewDocument'])) {
|
||||
foreach($GLOBALS['SEEDDMS_HOOKS']['reviewDocument'] as $hookObj) {
|
||||
if (method_exists($hookObj, 'postReviewDocument')) {
|
||||
$hookObj->postReviewDocument(null, $content, S_REJECTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$docReviewStatus = $content->getReviewStatus();
|
||||
if (is_bool($docReviewStatus) && !$docReviewStatus) {
|
||||
$this->errormsg = "cannot_retrieve_review_snapshot";
|
||||
return false;
|
||||
}
|
||||
$reviewCT = 0;
|
||||
$reviewTotal = 0;
|
||||
foreach ($docReviewStatus as $drstat) {
|
||||
if ($drstat["status"] == 1) {
|
||||
$reviewCT++;
|
||||
}
|
||||
if ($drstat["status"] != -2) {
|
||||
$reviewTotal++;
|
||||
}
|
||||
}
|
||||
// If all reviews have been received and there are no rejections, retrieve a
|
||||
// count of the approvals required for this document.
|
||||
if ($reviewCT == $reviewTotal) {
|
||||
$docApprovalStatus = $content->getApprovalStatus();
|
||||
if (is_bool($docApprovalStatus) && !$docApprovalStatus) {
|
||||
$this->errormsg = "cannot_retrieve_approval_snapshot";
|
||||
return false;
|
||||
}
|
||||
$approvalCT = 0;
|
||||
$approvalTotal = 0;
|
||||
foreach($docApprovalStatus as $dastat) {
|
||||
if($dastat["status"] == 1) {
|
||||
$approvalCT++;
|
||||
}
|
||||
if($dastat["status"] != -2) {
|
||||
$approvalTotal++;
|
||||
}
|
||||
}
|
||||
// If the approvals received is less than the approvals total, then
|
||||
// change status to pending approval.
|
||||
if($approvalCT < $approvalTotal) {
|
||||
$this->newstatus = S_DRAFT_APP;
|
||||
} else {
|
||||
// Otherwise, change the status to released.
|
||||
$this->newstatus = S_RELEASED;
|
||||
}
|
||||
if($content->setStatus($this->newstatus, getMLText("automatic_status_update"), $user)) {
|
||||
if(isset($GLOBALS['SEEDDMS_HOOKS']['reviewDocument'])) {
|
||||
foreach($GLOBALS['SEEDDMS_HOOKS']['reviewDocument'] as $hookObj) {
|
||||
if (method_exists($hookObj, 'postReviewDocument')) {
|
||||
$hookObj->postReviewDocument(null, $content, $this->newstatus);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!$this->callHook('postReviewDocument', $content)) {
|
||||
}
|
||||
|
||||
return true;
|
||||
} /* }}} */
|
||||
}
|
|
@ -1,143 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of ReviseDocument controller
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class which does the busines logic for downloading a document
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Controller_ReviseDocument extends SeedDMS_Controller_Common {
|
||||
|
||||
public $oldstatus;
|
||||
|
||||
public $newstatus;
|
||||
|
||||
public function run() {
|
||||
$dms = $this->params['dms'];
|
||||
$user = $this->params['user'];
|
||||
$settings = $this->params['settings'];
|
||||
$document = $this->params['document'];
|
||||
$content = $this->params['content'];
|
||||
$revisionstatus = $this->params['revisionstatus'];
|
||||
$revisiontype = $this->params['revisiontype'];
|
||||
$group = $this->params['group'];
|
||||
$comment = $this->params['comment'];
|
||||
$overallStatus = $content->getStatus();
|
||||
$this->oldstatus = $overallStatus['status'];
|
||||
$this->newstatus = $this->oldstatus;
|
||||
|
||||
/* if set to true, a single reject will reject the doc. If set to false
|
||||
* all revisions will be collected first and afterwards the doc is rejected
|
||||
* if one has rejected it. So in the very end the doc is rejected, but
|
||||
* doc remainѕ in S_IN_REVISION until all have revised the doc
|
||||
*/
|
||||
$onevotereject = $this->params['onevotereject'];
|
||||
|
||||
/* Get the document id and name before removing the document */
|
||||
$docname = $document->getName();
|
||||
$documentid = $document->getID();
|
||||
|
||||
if(!$this->callHook('preReviseDocument', $content)) {
|
||||
}
|
||||
|
||||
$result = $this->callHook('reviseDocument', $content);
|
||||
if($result === null) {
|
||||
|
||||
if ($revisiontype == "ind") {
|
||||
if(0 > $content->setRevision($user, $user, $revisionstatus, $comment)) {
|
||||
$this->error = 1;
|
||||
$this->errormsg = "revision_update_failed";
|
||||
return false;
|
||||
}
|
||||
} elseif ($revisiontype == "grp") {
|
||||
if(0 > $content->setRevision($group, $user, $revisionstatus, $comment)) {
|
||||
$this->error = 1;
|
||||
$this->errormsg = $ll."revision_update_failed";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check to see if the overall status for the document version needs to be
|
||||
* updated.
|
||||
*/
|
||||
$result = $this->callHook('reviseUpdateDocumentStatus', $content);
|
||||
if($result === null) {
|
||||
if ($onevotereject && $revisionstatus == -1){
|
||||
$this->newstatus = S_NEEDS_CORRECTION;
|
||||
if(!$content->setStatus(S_NEEDS_CORRECTION,$comment,$user)) {
|
||||
$this->error = 1;
|
||||
$this->errormsg = "revision_update_failed";
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$docRevisionStatus = $content->getRevisionStatus();
|
||||
if (is_bool($docRevisionStatus) && !$docRevisionStatus) {
|
||||
$this->error = 1;
|
||||
$this->errormsg = "cannot_retrieve_revision_snapshot";
|
||||
return false;
|
||||
}
|
||||
$revisionok = 0;
|
||||
$revisionnotok = 0;
|
||||
$revisionTotal = 0;
|
||||
foreach ($docRevisionStatus as $drstat) {
|
||||
if ($drstat["status"] == 1) {
|
||||
$revisionok++;
|
||||
}
|
||||
if ($drstat["status"] == -1) {
|
||||
$revisionnotok++;
|
||||
}
|
||||
if ($drstat["status"] != -2) {
|
||||
$revisionTotal++;
|
||||
}
|
||||
}
|
||||
// If all revisions have been done and there are no rejections,
|
||||
// then release the document. If all revisions have been done but some
|
||||
// of them were rejections then documents needs correction.
|
||||
// Otherwise put it back into revision workflow
|
||||
if ($revisionok == $revisionTotal) {
|
||||
$this->newstatus=S_RELEASED;
|
||||
if ($content->finishRevision($user, $this->newstatus, 'Finished revision workflow', getMLText("automatic_status_update"))) {
|
||||
if(!$this->callHook('finishReviseDocument', $content)) {
|
||||
}
|
||||
}
|
||||
} elseif (($revisionok + $revisionnotok) == $revisionTotal) {
|
||||
$this->newstatus=S_NEEDS_CORRECTION;
|
||||
// if ($content->finishRevision($user, $this->newstatus, 'Finished revision workflow', getMLText("automatic_status_update"))) {
|
||||
if(!$content->setStatus($this->newstatus,$comment,$user)) {
|
||||
$this->error = 1;
|
||||
$this->errormsg = "revision_update_failed";
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$this->newstatus=S_IN_REVISION;
|
||||
if(!$content->setStatus($this->newstatus,$comment,$user)) {
|
||||
$this->error = 1;
|
||||
$this->errormsg = "revision_update_failed";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!$this->callHook('postReviseDocument', $content)) {
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of Role manager controller
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class which does the busines logic for role manager
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Controller_RoleMgr extends SeedDMS_Controller_Common {
|
||||
|
||||
public function run() {
|
||||
}
|
||||
|
||||
public function addrole() {
|
||||
$dms = $this->params['dms'];
|
||||
$name = $this->params['name'];
|
||||
$role = $this->params['role'];
|
||||
|
||||
return($dms->addRole($name, $role));
|
||||
}
|
||||
|
||||
public function removerole() {
|
||||
$roleobj = $this->params['roleobj'];
|
||||
return $roleobj->remove();
|
||||
}
|
||||
|
||||
public function editrole() {
|
||||
$dms = $this->params['dms'];
|
||||
$name = $this->params['name'];
|
||||
$role = $this->params['role'];
|
||||
$roleobj = $this->params['roleobj'];
|
||||
$noaccess = $this->params['noaccess'];
|
||||
|
||||
if ($roleobj->getName() != $name)
|
||||
$roleobj->setName($name);
|
||||
if ($roleobj->getRole() != $role)
|
||||
$roleobj->setRole($role);
|
||||
$roleobj->setNoAccess($noaccess);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of TransferDocument controller
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2017 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class which does the busines logic for downloading a document
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2017 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Controller_TransferDocument extends SeedDMS_Controller_Common {
|
||||
|
||||
public function run() {
|
||||
$dms = $this->params['dms'];
|
||||
$user = $this->params['user'];
|
||||
$settings = $this->params['settings'];
|
||||
$document = $this->params['document'];
|
||||
$newuser = $this->params['newuser'];
|
||||
|
||||
$folder = $document->getFolder();
|
||||
|
||||
if(false === $this->callHook('preTransferDocument')) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_preTransferDocument_failed';
|
||||
return null;
|
||||
}
|
||||
|
||||
$result = $this->callHook('transferDocument', $document);
|
||||
if($result === null) {
|
||||
if (!$document->transferToUser($newuser)) {
|
||||
return false;
|
||||
} else {
|
||||
if(false === $this->callHook('postTransferDocument')) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of Transmittal Download controller
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class which does the busines logic for downloading a transmittal
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Controller_TransmittalDownload extends SeedDMS_Controller_Common {
|
||||
|
||||
public function run() {
|
||||
$dms = $this->params['dms'];
|
||||
$user = $this->params['user'];
|
||||
$transmittal = $this->params['transmittal'];
|
||||
|
||||
$items = $transmittal->getItems();
|
||||
if($items) {
|
||||
include("../inc/inc.ClassDownloadMgr.php");
|
||||
$downmgr = new SeedDMS_Download_Mgr();
|
||||
if($extraheader = $this->callHook('extraDownloadHeader'))
|
||||
$downmgr->addHeader($extraheader);
|
||||
|
||||
foreach($items as $item) {
|
||||
$content = $item->getContent();
|
||||
$document = $content->getDocument();
|
||||
if ($document->getAccessMode($user) >= M_READ) {
|
||||
$extracols = $this->callHook('extraDownloadColumns', $document);
|
||||
$filename = $this->callHook('filenameDownloadItem', $content);
|
||||
if($rawcontent = $this->callHook('rawcontent', $content)) {
|
||||
$downmgr->addItem($content, $extracols, $rawcontent, $filename);
|
||||
} else
|
||||
$downmgr->addItem($content, $extracols, null, $filename);
|
||||
}
|
||||
}
|
||||
|
||||
$filename = tempnam(sys_get_temp_dir(), 'transmittal-download-');
|
||||
if($filename) {
|
||||
if($downmgr->createArchive($filename)) {
|
||||
header("Content-Transfer-Encoding: binary");
|
||||
header("Content-Length: " . filesize($filename));
|
||||
header("Content-Disposition: attachment; filename=\"export-" .date('Y-m-d') . ".zip\"");
|
||||
header("Content-Type: application/zip");
|
||||
header("Cache-Control: must-revalidate");
|
||||
|
||||
readfile($filename);
|
||||
} else {
|
||||
}
|
||||
unlink($filename);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of UpdateDocument controller
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class which does the busines logic for downloading a document
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Controller_UpdateDocument extends SeedDMS_Controller_Common {
|
||||
|
||||
public function run() { /* {{{ */
|
||||
$name = $this->getParam('name');
|
||||
$comment = $this->getParam('comment');
|
||||
|
||||
/* Call preUpdateDocument early, because it might need to modify some
|
||||
* of the parameters.
|
||||
*/
|
||||
if(false === $this->callHook('preUpdateDocument', $this->params['document'])) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_preUpdateDocument_failed';
|
||||
return null;
|
||||
}
|
||||
|
||||
$comment = $this->getParam('comment');
|
||||
$dms = $this->params['dms'];
|
||||
$user = $this->params['user'];
|
||||
$document = $this->params['document'];
|
||||
$settings = $this->params['settings'];
|
||||
$fulltextservice = $this->params['fulltextservice'];
|
||||
$folder = $this->params['folder'];
|
||||
$userfiletmp = $this->getParam('userfiletmp');
|
||||
$userfilename = $this->getParam('userfilename');
|
||||
$filetype = $this->getParam('filetype');
|
||||
$userfiletype = $this->getParam('userfiletype');
|
||||
$reviewers = $this->getParam('reviewers');
|
||||
$approvers = $this->getParam('approvers');
|
||||
$recipients = $this->getParam('recipients');
|
||||
$reqversion = $this->getParam('reqversion');
|
||||
$comment = $this->getParam('comment');
|
||||
$attributes = $this->getParam('attributes');
|
||||
$workflow = $this->getParam('workflow');
|
||||
$maxsizeforfulltext = $this->getParam('maxsizeforfulltext');
|
||||
$initialdocumentstatus = $this->getParam('initialdocumentstatus');
|
||||
|
||||
$content = $this->callHook('updateDocument');
|
||||
if($content === null) {
|
||||
$filesize = SeedDMS_Core_File::fileSize($userfiletmp);
|
||||
if($contentResult=$document->addContent($comment, $user, $userfiletmp, utf8_basename($userfilename), $filetype, $userfiletype, $reviewers, $approvers, 0, $attributes, $workflow, $initialdocumentstatus)) {
|
||||
|
||||
if ($this->hasParam('expires')) {
|
||||
if($document->setExpires($this->getParam('expires'))) {
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
if(!empty($recipients['i'])) {
|
||||
foreach($recipients['i'] as $uid) {
|
||||
if($u = $dms->getUser($uid)) {
|
||||
$res = $contentResult->getContent()->addIndRecipient($u, $user);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!empty($recipients['g'])) {
|
||||
foreach($recipients['g'] as $gid) {
|
||||
if($g = $dms->getGroup($gid)) {
|
||||
$res = $contentResult->getContent()->addGrpRecipient($g, $user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$content = $contentResult->getContent();
|
||||
} else {
|
||||
$this->errormsg = 'error_update_document';
|
||||
$result = false;
|
||||
}
|
||||
} elseif($result === false) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_updateDocument_failed';
|
||||
return false;
|
||||
}
|
||||
|
||||
if($fulltextservice && ($index = $fulltextservice->Indexer()) && $content) {
|
||||
$idoc = $fulltextservice->IndexedDocument($document);
|
||||
if(false !== $this->callHook('preIndexDocument', $document, $idoc)) {
|
||||
$lucenesearch = $fulltextservice->Search();
|
||||
if($hit = $lucenesearch->getDocument((int) $document->getId())) {
|
||||
$index->delete($hit->id);
|
||||
}
|
||||
$index->addDocument($idoc);
|
||||
$index->commit();
|
||||
}
|
||||
}
|
||||
|
||||
if(false === $this->callHook('postUpdateDocument', $document, $content)) {
|
||||
}
|
||||
|
||||
return $content;
|
||||
} /* }}} */
|
||||
}
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of UserListCsv controller
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class which does the busines logic for export a list of all users as csv
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Controller_UserListCsv extends SeedDMS_Controller_Common {
|
||||
|
||||
public function run() { /* {{{ */
|
||||
$dms = $this->params['dms'];
|
||||
$user = $this->params['user'];
|
||||
$settings = $this->params['settings'];
|
||||
$group = $this->params['group'];
|
||||
|
||||
if($group) {
|
||||
$allUsers = $group->getUsers();
|
||||
} else {
|
||||
$allUsers = $dms->getAllUsers($settings->_sortUsersInList);
|
||||
}
|
||||
$m = 0;
|
||||
foreach($allUsers as $u) {
|
||||
$m = max($m, count($u->getGroups()));
|
||||
}
|
||||
$fp = fopen("php://temp/maxmemory", 'r+');
|
||||
$header = array('login', 'passenc', 'name', 'email', 'comment', 'role', 'quota', 'homefolder', 'hidden', 'disabled');
|
||||
for($i=1; $i<=$m; $i++)
|
||||
$header[] = 'group_'.$i;
|
||||
fputcsv($fp, $header, ';');
|
||||
foreach($allUsers as $u) {
|
||||
$data = array($u->getLogin(), $u->getPwd(), $u->getFullName(), $u->getEmail(), $u->getComment(), $u->isAdmin() ? 'admin' : ($u->isGuest() ? 'guest' : 'user'), $u->getQuota(), $u->getHomeFolder() ? $u->getHomeFolder() : '', $u->isHidden() ? '1' : 0, $u->isDisabled() ? '1' : '0');
|
||||
foreach($u->getGroups() as $g)
|
||||
$data[] = $g->getName();
|
||||
fputcsv($fp, $data, ';');
|
||||
}
|
||||
$efilename = 'userlist-'.date('Ymd-His').'.csv';
|
||||
header("Content-Type: text/csv");
|
||||
header("Content-Disposition: attachment; filename=\"" . $efilename . "\"; filename*=UTF-8''".$efilename);
|
||||
// header("Content-Length: " . filesize($name));
|
||||
fseek($fp, 0);
|
||||
fpassthru($fp);
|
||||
fclose($fp);
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
}
|
|
@ -26,46 +26,25 @@ class SeedDMS_Controller_ViewOnline extends SeedDMS_Controller_Common {
|
|||
$dms = $this->params['dms'];
|
||||
$settings = $this->params['settings'];
|
||||
$type = $this->params['type'];
|
||||
$content = $this->params['content'];
|
||||
$document = $content->getDocument();
|
||||
|
||||
switch($type) {
|
||||
case "version":
|
||||
$version = $this->params['version'];
|
||||
$document = $this->params['document'];
|
||||
if($version < 1) {
|
||||
$content = $this->callHook('documentLatestContent', $document);
|
||||
if($content === null)
|
||||
$content = $document->getLatestContent();
|
||||
} else {
|
||||
$content = $this->callHook('documentContent', $document, $version);
|
||||
if($content === null)
|
||||
$content = $document->getContentByVersion($version);
|
||||
}
|
||||
if (!is_object($content)) {
|
||||
$this->errormsg = 'invalid_version';
|
||||
return false;
|
||||
}
|
||||
/* set params['content'] for compatiblity with older extensions which
|
||||
* expect the content in the controller
|
||||
*/
|
||||
$this->params['content'] = $content;
|
||||
if(null === $this->callHook('version')) {
|
||||
if(file_exists($dms->contentDir . $content->getPath())) {
|
||||
if(!$this->callHook('version')) {
|
||||
header("Content-Type: " . $content->getMimeType());
|
||||
$efilename = rawurlencode($content->getOriginalFileName());
|
||||
if (!isset($settings->_viewOnlineFileTypes) || !is_array($settings->_viewOnlineFileTypes) || !in_array(strtolower($content->getFileType()), $settings->_viewOnlineFileTypes)) {
|
||||
header("Content-Disposition: attachment; filename=\"" . $efilename . "\"; filename*=UTF-8''".$efilename);
|
||||
} else {
|
||||
header("Content-Disposition: filename=\"" . $efilename . "\"; filename*=UTF-8''".$efilename);
|
||||
header("Content-Disposition: filename=\"" . $document->getName().$content->getFileType()) . "\"";
|
||||
}
|
||||
header("Cache-Control: must-revalidate");
|
||||
header("ETag: ".$content->getChecksum());
|
||||
header("Content-Length: " . filesize($dms->contentDir . $content->getPath()));
|
||||
header("Expires: 0");
|
||||
header("Cache-Control: no-cache, must-revalidate");
|
||||
header("Pragma: no-cache");
|
||||
|
||||
sendFile($dms->contentDir.$content->getPath());
|
||||
}
|
||||
ob_clean();
|
||||
readfile($dms->contentDir . $content->getPath());
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
#!/bin/sh
|
||||
# This command retrieves the strings that need to be translated
|
||||
sgrep -o "%r\n" '"getMLText(\"" __ "\""' */*.php views/bootstrap/*.php |sort|uniq -c
|
||||
sgrep -o "%r\n" '"getMLText(\"" __ "\""' */*.php|sort|uniq -c
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
/* Determine all languages keys used in the php files */
|
||||
$output = array();
|
||||
if(exec('sgrep -o "%r\n" \'"tMLText(\"" __ "\""\' */*.php views/bootstrap/*.php|sort|uniq -c', $output)) {
|
||||
if(exec('sgrep -o "%r\n" \'"tMLText(\"" __ "\""\' */*.php|sort|uniq -c', &$output)) {
|
||||
$allkeys = array();
|
||||
foreach($output as $line) {
|
||||
$data = explode(' ', trim($line));
|
||||
|
@ -9,9 +9,8 @@ if(exec('sgrep -o "%r\n" \'"tMLText(\"" __ "\""\' */*.php views/bootstrap/*.php|
|
|||
}
|
||||
}
|
||||
|
||||
$languages = array('ar_EG', 'bg_BG', 'ca_ES', 'cs_CZ', 'de_DE', 'en_GB', 'es_ES', 'fr_FR', 'hu_HU', 'it_IT', 'nl_NL', 'pl_PL', 'pt_BR', 'ro_RO', 'ru_RU', 'sk_SK', 'sv_SE', 'tr_TR', 'zh_CN', 'zh_TW');
|
||||
/* Reading languages */
|
||||
foreach($languages as $lang) {
|
||||
foreach(array('English', 'German', 'Italian', 'Slovak', 'Czech') as $lang) {
|
||||
include('languages/'.$lang.'/lang.inc');
|
||||
ksort($text);
|
||||
$langarr[$lang] = $text;
|
||||
|
@ -21,7 +20,7 @@ foreach($languages as $lang) {
|
|||
echo "List of missing keys\n";
|
||||
echo "-----------------------------\n";
|
||||
foreach(array_keys($allkeys) as $key) {
|
||||
foreach($languages as $lang) {
|
||||
foreach(array('English', 'German', 'Italian', 'Slovak', 'Czech') as $lang) {
|
||||
if(!isset($langarr[$lang][$key])) {
|
||||
echo "Missing key '".$key."' in language ".$lang."\n";
|
||||
}
|
||||
|
@ -32,7 +31,7 @@ echo "\n";
|
|||
/* Check for phrases not used anymore */
|
||||
echo "List of superflous keys\n";
|
||||
echo "-----------------------------\n";
|
||||
foreach($languages as $lang) {
|
||||
foreach(array('English', 'German', 'Italian', 'Slovak', 'Czech') as $lang) {
|
||||
$n = 0;
|
||||
foreach($langarr[$lang] as $key=>$value) {
|
||||
if(!isset($allkeys[$key])) {
|
||||
|
@ -46,8 +45,8 @@ foreach($languages as $lang) {
|
|||
exit;
|
||||
|
||||
$fpout = fopen('php://stdout', 'w');
|
||||
foreach(array_keys($langarr['en_GB']) as $key) {
|
||||
$data = array($key, $langarr['en_GB'][$key], $langarr['de_DE'][$key]);
|
||||
foreach(array_keys($langarr['English']) as $key) {
|
||||
$data = array($key, $langarr['English'][$key], $langarr['German'][$key]);
|
||||
fputcsv($fpout, $data);
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -1,206 +0,0 @@
|
|||
Commands for converting documents
|
||||
----------------------------------
|
||||
|
||||
This file contains commands for converting different document types
|
||||
into
|
||||
|
||||
* text (for fulltext search)
|
||||
* png (for preview images)
|
||||
* pdf (for pdf documents)
|
||||
|
||||
Such conversions may not necessarily output an excact equivalent of
|
||||
the input file, but outputs a suitable representation, e.g.
|
||||
converting an mp3 file into text may output the metadata or even the
|
||||
lyrics of the song. Converting it into a preview image may result
|
||||
in a picture of the album cover.
|
||||
|
||||
Please note, that when ever a command outputs anything to stderr,
|
||||
this will considered as a failure of the command. Most command line
|
||||
programs have a parameter (.e.g. `-q`) to suppress such an output.
|
||||
|
||||
If you run php-fpm you may encounter problems with charsets based on
|
||||
UTF-8. Programms like `catdoc` read LANG from the environment to
|
||||
set the correct encoding of the output. php-fpm often clears the
|
||||
environment and programms like `catdoc` will not longer output any
|
||||
UTF-8 chars. In such a case you may want to set `clear_env=no` in
|
||||
php-fpm's configuration. On Debian this is done in the file
|
||||
`/etc/php/<php version>/fpm/pool.d/www.conf`. Search for `clear_env`.
|
||||
|
||||
Conversion to text for fulltext search
|
||||
=======================================
|
||||
|
||||
text/plain
|
||||
text/csv
|
||||
application/csv
|
||||
cat '%s'
|
||||
|
||||
application/pdf
|
||||
pdftotext -q -nopgbrk %s - | sed -e 's/ [a-zA-Z0-9.]\{1\} / /g' -e 's/[0-9.]//g'
|
||||
|
||||
If pdftotext takes too long on large document you may want to pass parameter
|
||||
-l to specify the last page to be converted. -q is for suppressing error/warnings
|
||||
send to stderr
|
||||
|
||||
mutool draw -F txt -q -N -o - %s
|
||||
|
||||
application/vnd.openxmlformats-officedocument.wordprocessingml.document
|
||||
docx2txt '%s' -
|
||||
|
||||
application/msword
|
||||
catdoc %s
|
||||
|
||||
application/vnd.oasis.opendocument.text
|
||||
odt2txt %s
|
||||
|
||||
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
|
||||
xlsx2csv -d tab %s
|
||||
|
||||
application/vnd.ms-excel
|
||||
xls2csv -d tab %s
|
||||
|
||||
text/html
|
||||
html2text %s
|
||||
|
||||
Many office formats
|
||||
unoconv -d document -f txt --stdout '%s'
|
||||
|
||||
Apache Tika is another option for creating plain text from various document
|
||||
types. Just use curl to send the document to your tika server and get the
|
||||
plain text in return.
|
||||
|
||||
curl -s -T '%s' http://localhost:9998/tika --header 'Accept: text/plain'
|
||||
|
||||
Conversion to pdf for pdf preview
|
||||
==================================
|
||||
|
||||
text/plain
|
||||
text/csv
|
||||
application/csv
|
||||
application/vnd.oasis.opendocument.text
|
||||
application/msword
|
||||
application/vnd.wordperfect
|
||||
text/rtf
|
||||
unoconv -d document -f pdf --stdout -v '%f' > '%o'
|
||||
|
||||
image/png
|
||||
image/jpg
|
||||
image/jpeg
|
||||
convert -density 300 '%f' 'pdf:%o'
|
||||
|
||||
image/svg+xml
|
||||
cairosvg -f pdf -o '%o' '%f'
|
||||
|
||||
application/vnd.ms-powerpoint
|
||||
application/vnd.openxmlformats-officedocument.presentationml.presentation
|
||||
application/vnd.oasis.opendocument.presentation
|
||||
unoconv -d presentation -f pdf --stdout -v '%f' > '%o'
|
||||
|
||||
application/vnd.ms-excel
|
||||
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
|
||||
application/vnd.oasis.opendocument.spreadsheet
|
||||
unoconv -d spreadsheet -f pdf --stdout -v '%f' > '%o'
|
||||
|
||||
message/rfc822
|
||||
java -jar emailconverter-2.5.3-all.jar '%f' -o '%o'
|
||||
|
||||
The emailconverter can be obtained from https://github.com/nickrussler/email-to-pdf-converter
|
||||
It requires wkhtmltopdf which is part of debian.
|
||||
|
||||
text/plain
|
||||
iconv -c -f utf-8 -t latin1 '%f' | a2ps -1 -q -a1 -R -B -o - - | ps2pdf - -
|
||||
|
||||
The parameter `-q` is important because a2ps sends some statistical
|
||||
data to stderr, which makes SeedDMS believe the command has failed.
|
||||
|
||||
application/x-xopp
|
||||
|
||||
xournalpp -p "%o" "%f"
|
||||
|
||||
Converting from application/x-xopp to pdf only works if the xopp file
|
||||
does not use a pdf document as a background, because this pdf is not
|
||||
stored in the xopp fіle.
|
||||
|
||||
Conversion to png for preview images
|
||||
=====================================
|
||||
|
||||
If you have problems running convert on PDF documents then read this page
|
||||
https://askubuntu.com/questions/1081895/trouble-with-batch-conversion-of-png-to-pdf-using-convert
|
||||
It basically instructs you to comment out the line
|
||||
|
||||
<policy domain="coder" rights="none" pattern="PDF" />
|
||||
|
||||
in /etc/ImageMagick-6/policy.xml
|
||||
|
||||
convert determines the format of the converted image from the extension of
|
||||
the output filename. SeedDMS usually sets a propper extension when running
|
||||
the command, but nevertheless it is good practice to explicitly set the output
|
||||
format by prefixing the output filename with 'png:'. This is of course always
|
||||
needed if the output goes to stdout.
|
||||
|
||||
image/jpg
|
||||
image/jpeg
|
||||
image/png
|
||||
convert -resize %wx '%f' 'png:%o'
|
||||
|
||||
image/svg+xml
|
||||
cairosvg -f png --output-width %w -o '%o' '%f'
|
||||
|
||||
text/plain
|
||||
convert -density 100 -resize %wx 'text:%f[0]' 'png:%o'
|
||||
|
||||
application/pdf
|
||||
gs -dBATCH -dNOPAUSE -sDEVICE=png16m -dPDFFitPage -r72x72 -sOutputFile=- -dFirstPage=1 -dLastPage=1 -q '%f' | convert -resize %wx png:- '%o'
|
||||
|
||||
convert -density 100 -resize %wx '%f[0]' 'png:%o'
|
||||
|
||||
mutool draw -F png -w %w -q -N -o '%o' '%f' 1
|
||||
|
||||
pdftocairo '%f' -png -singlefile -scale-to-x %w -scale-to-y -1 - > '%o'
|
||||
|
||||
pdftocairo needs to output to stdout because the output file name passed
|
||||
to pdftocairo will be suffixed with png
|
||||
|
||||
application/postscript
|
||||
convert -density 100 -resize %wx '%f[0]' 'png:%o'
|
||||
|
||||
text/plain
|
||||
iconv -c -f utf-8 -t latin1 '%f' | a2ps -1 -q -a1 -R -B -o - - | gs -dBATCH -dNOPAUSE -sDEVICE=png16m -dFirstPage=1 -dLastPage=1 -dPDFFitPage -r72x72 -sOutputFile=- -q - | convert -resize %wx png:- 'png:%o'
|
||||
|
||||
On Linux systems you will have to set the desired value in /etc/papersize for a2ps
|
||||
e.g. a4, or letter. Unfortunately, a2ps cannot process utf-8 encoded files. That's
|
||||
why the input needs to be recoded with iconv or recode.
|
||||
|
||||
application/msword
|
||||
application/vnd.oasis.opendocument.spreadsheet
|
||||
application/vnd.oasis.opendocument.text
|
||||
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
|
||||
application/vnd.ms-excel
|
||||
application/vnd.openxmlformats-officedocument.wordprocessingml.document
|
||||
text/rtf
|
||||
application/vnd.ms-powerpoint
|
||||
text/csv
|
||||
application/csv
|
||||
application/vnd.wordperfect
|
||||
unoconv -d document -e PageRange=1 -f pdf --stdout -v '%f' | gs -dBATCH -dNOPAUSE -sDEVICE=pngalpha -dPDFFitPage -r72x72 -sOutputFile=- -dFirstPage=1 -dLastPage=1 -q - | convert -resize %wx png:- 'png:%o'
|
||||
|
||||
video/webm
|
||||
video/mp4
|
||||
This will take 12th frame of a video and converts into a png. It requires
|
||||
ffmpeg to be installed.
|
||||
|
||||
convert -resize %wx "%f[12]" "png:%o"
|
||||
|
||||
You may as well use ffmpeg right away
|
||||
|
||||
ffmpeg -i "%f" -ss 00:00:02 -frames:v 1 -loglevel quiet -vf scale=%w:-1 -f apng "%o"
|
||||
|
||||
audio/mpeg
|
||||
|
||||
sox "%f" -n spectrogram -x 600 -Y 550 -r -l -o - | convert -resize %wx png:- "png:%o"
|
||||
|
||||
application/x-xopp
|
||||
xournalpp -i "%o" --export-png-width=%w "%f"
|
||||
|
||||
Converting from application/x-xopp to png only works if the xopp file
|
||||
does not use a pdf document as a background, because this pdf is not
|
||||
stored in the xopp fіle.
|
|
@ -1,95 +0,0 @@
|
|||
Layout of installation
|
||||
=======================
|
||||
|
||||
SeedDMS allows various kinds of installations with very individual layouts
|
||||
on disc. The proposed layout till version 5.1.6 was as the following:
|
||||
|
||||
seeddms51x ---+--- data
|
||||
|
|
||||
+--- pear
|
||||
|
|
||||
+--- seeddms-5.1.x
|
||||
|
|
||||
+--- www -> seeddms-5.1.x
|
||||
|
||||
'data' contains all document files, the sqlite database (if used), the full text
|
||||
data, the log files, and the cached preview images.
|
||||
|
||||
'pear' contains all PEAR packages including the four SeedDMS packages SeedDMS_Core,
|
||||
SeedDMS_Lucene, SeedDMS_Preview, SeedDMS_SQLiteFTS.
|
||||
|
||||
'seeddms-5.1.x' are the sources of seeddms and 'www' being a link on it.
|
||||
|
||||
This layout has disadvantages when updating the source of seeddms, because
|
||||
the directories 'conf' and 'ext' had to be moved from 'seeddms-5.1.x' to
|
||||
'seeddms-5.1.(x+1)'. 'conf' was also visible over the web unless it was
|
||||
protected by an .htaccess file. The .htaccess file has been shipped, but it
|
||||
is far better to keep senѕitive data out of the document root in the first
|
||||
place.
|
||||
|
||||
The new layout mostly retains that structure but uses more soft links to place
|
||||
the local data outside of 'seeddms-5.1.x' which makes updating a lot easier
|
||||
and moves the configuration out of the document root.
|
||||
As MS Windows does not support soft links, this change will only apply to Linux/Unix
|
||||
systems. MS Windows users just skip all the soft links and set seeddms-5.1.x
|
||||
as the document root. The new layout is the following:
|
||||
|
||||
seeddms51x ---+--- data --+-- log
|
||||
| |
|
||||
| +-- cache
|
||||
| |
|
||||
| +-- 1048576
|
||||
| |
|
||||
| +-- ...
|
||||
|
|
||||
+--- pear
|
||||
|
|
||||
+--- conf
|
||||
|
|
||||
+--- seeddms-5.1.x
|
||||
|
|
||||
+--- seeddms -> seeddms-5.1.x
|
||||
|
|
||||
+--- www --+-- inc -> ../seeddms/inc
|
||||
|
|
||||
+-- op -> ../seeddms/op
|
||||
|
|
||||
+-- out -> ../seeddms/out
|
||||
|
|
||||
+-- views -> ../seeddms/views
|
||||
|
|
||||
+-- controllers -> ../seeddms/controllers
|
||||
|
|
||||
+-- styles -> ../seeddms/styles
|
||||
|
|
||||
+-- languages -> ../seeddms/languages
|
||||
|
|
||||
+-- webdav -> ../seeddms/webdav
|
||||
|
|
||||
+-- restapi -> ../seeddms/restapi
|
||||
|
|
||||
+-- pdfviewer -> ../seeddms/pdfviewer
|
||||
|
|
||||
+-- index.php -> ../seeddms/index.php
|
||||
|
|
||||
+-- ext
|
||||
|
||||
In order to convert to this layout you need to do the following in the seeddms51x
|
||||
directory (replace the 'x' in '5.1.x' with the correct number):
|
||||
|
||||
ln -s seeddms-5.1.x seeddms
|
||||
mv www/conf .
|
||||
mv seeddms-5.1.x/ext www
|
||||
cd www
|
||||
rm inc op out views controllers styles languages webdav restapi pdfviewer index.php
|
||||
ln -s ../seeddms/inc
|
||||
ln -s ../seeddms/op
|
||||
ln -s ../seeddms/out
|
||||
ln -s ../seeddms/views
|
||||
ln -s ../seeddms/controllers
|
||||
ln -s ../seeddms/styles
|
||||
ln -s ../seeddms/languages
|
||||
ln -s ../seeddms/webdav
|
||||
ln -s ../seeddms/restapi
|
||||
ln -s ../seeddms/pdfviewer
|
||||
ln -s ../seeddms/index.php
|
|
@ -1,18 +0,0 @@
|
|||
Adding authentication failure check for fail2ban
|
||||
=================================================
|
||||
|
||||
You will have to use 5.1.10 for this to work.
|
||||
|
||||
Add a filter /etc/fail2ban/filter.d/seeddms.conf with the content
|
||||
|
||||
[Definition]
|
||||
|
||||
failregex = \[error\] -- \(<HOST>\) op.Login login failed
|
||||
|
||||
then configure a new jail in /etc/fail2ban/jail.d/seeddms.conf
|
||||
|
||||
[seeddms]
|
||||
enabled = yes
|
||||
port = http,https
|
||||
filter = seeddms
|
||||
logpath = /home/www-data/seeddms-demo/data/log/*.log
|
216
doc/README.Hooks
216
doc/README.Hooks
|
@ -1,216 +0,0 @@
|
|||
Hooks
|
||||
======
|
||||
|
||||
Attention: the api for hooks isn't stable yet!
|
||||
|
||||
Hooks in SeedDMS are user definied methods which are being called by
|
||||
the application. The SeedDMS Core also has hooks which are being
|
||||
called from the core itself. They are not subject of this document.
|
||||
The SeedDMS application distinguishes between
|
||||
|
||||
* view hooks and
|
||||
* controller hooks
|
||||
|
||||
view hooks usually return some html output which is send to the browser
|
||||
and either replaces the default output or adds additional information.
|
||||
A view hooks which returns null will be considered as not being called
|
||||
at all. If the hook is expected to return something, it must be either
|
||||
a string or an array of strings.
|
||||
|
||||
controller hooks implement additional functions which either replace
|
||||
existing functions or add new ones. If such a hook returns null then
|
||||
this is treated as if the hook was not called. If the hook returns
|
||||
false it will prevent other hooks implementing the same function from
|
||||
being called. All other return values will not stop other hooks from
|
||||
being called. A controller hook may set the error msg of the calling
|
||||
controller.
|
||||
|
||||
Currently available controller hooks
|
||||
------------------------------------
|
||||
AddDocument::preAddDocument
|
||||
Called before a new document will be added
|
||||
|
||||
If the hook returns false the document will not be added and the error msg
|
||||
set by the hook will be issued. This hook is called before the parameters
|
||||
are fetch from the controller. Therefore it is possible to modify them
|
||||
in this hook.
|
||||
|
||||
AddDocument::addDocument
|
||||
Called when the new document is to be added
|
||||
|
||||
This hook can be used to replace the code for adding a document. In
|
||||
that case it must return a document or false. If
|
||||
the hook does not return null, the original code for adding the
|
||||
document will be skipped.
|
||||
|
||||
AddDocument::postAddDocument
|
||||
Called after a new document has been added
|
||||
|
||||
This hook will be called after a document was added, both by the
|
||||
original code and within the hook addDocument. The hook is not called
|
||||
if adding the document failed. The document will be passed to the hook.
|
||||
The return value of this hook should always be null.
|
||||
|
||||
AddDocument::preIndexDocument
|
||||
Called before a new document will be indexed
|
||||
|
||||
This hook will be called after the document was added and before
|
||||
the hook postAddDocument. The parameters passed
|
||||
are the document and the indexed document. Returning false will prevent
|
||||
the document from being indexed.
|
||||
|
||||
EditDocument::editDocumentAttribute
|
||||
Called for each custom document attribute
|
||||
|
||||
This hook will be called for each custom attribute to ouput the form entry.
|
||||
The parameters passed are the document and the attribute definition.
|
||||
Returning an empty array will prevent the attribute from being show.
|
||||
Returning an array with two elements will pass those element to the formField
|
||||
method. A returned string will be output as is.
|
||||
|
||||
EditDocument::addDocumentAttributes
|
||||
Called after all custom document attributes has been output
|
||||
|
||||
This hook will be called right after the document attributes have been shown.
|
||||
The return value is either an array with two elements or a string.
|
||||
The string will be output as is, the array will be passed to the method formField.
|
||||
|
||||
UpdateDocument::preUpdateDocument
|
||||
Called before a new document will be updated
|
||||
|
||||
If the hook returns false the document will not be updated and the error msg
|
||||
set by the hook will be issued. This hook is called before the parameters
|
||||
are fetch from the controller. Therefore it is possible to modify them
|
||||
in this hook.
|
||||
|
||||
UpdateDocument::updateDocument
|
||||
Called when the document is to be updated
|
||||
|
||||
This hook can be used to replace the code for updating a document. In
|
||||
that case it must return a document content or false. If
|
||||
the hook returns null, the original code for adding the
|
||||
document will be executed.
|
||||
|
||||
UpdateDocument::postUpdateDocument
|
||||
Called after a new document has been updated
|
||||
|
||||
This hook will be called after a document was updated, both by the
|
||||
original code and within the hook addDocument.
|
||||
The document and content will be passed to the hook.
|
||||
The return value of this hook should always be null.
|
||||
|
||||
UpdateDocument::preIndexDocument
|
||||
Called before an updated document will be indexed
|
||||
|
||||
This hook will be called after the document was updated and before
|
||||
the hook postUpdateDocument. The parameters passed
|
||||
are the document and the indexed document. Returning false will prevent
|
||||
the document from being indexed.
|
||||
|
||||
RemoveDocument::preRemoveDocument
|
||||
Called before a document will be removed
|
||||
|
||||
If the hook returns false the document will not be removed and the error msg
|
||||
set by the hook will be issued.
|
||||
|
||||
RemoveDocument::removeDocument
|
||||
Called when the document is to be removed
|
||||
|
||||
If the hook returns null the
|
||||
regular document removal will happen.
|
||||
|
||||
RemoveDocument::postRemoveDocument
|
||||
Called after a document was removed
|
||||
|
||||
This hook will be called after a document was removed, both by the
|
||||
original code and within the hook removeDocument. It will not be
|
||||
called if removing the document failed.
|
||||
The return value of this hook should always be null.
|
||||
|
||||
RemoveFolder::preRemoveFolder
|
||||
Called before a folder will be removed
|
||||
|
||||
If the hook returns false the folder will not be removed and the error msg
|
||||
set by the hook will be issued.
|
||||
|
||||
RemoveFolder::removeFolder
|
||||
Called for removing the folder.
|
||||
|
||||
If the hook returns null the regular folder removal will happen.
|
||||
Keep in mind, that the hook function must also update the
|
||||
full text index.
|
||||
|
||||
RemoveFolder::postRemoveFolder
|
||||
Called after a document was removed
|
||||
|
||||
This hook will be called after a folder was removed, both by the
|
||||
original code and within the hook removeFolder. It will not be
|
||||
called if removing the folder failed.
|
||||
The return value of this hook should always be null.
|
||||
|
||||
EditFolder::preEditFolder
|
||||
Called before a folder will be updated
|
||||
|
||||
If the hook returns false the folder will not be updated and the error msg
|
||||
set by the hook will be issued. This hook is called before the parameters
|
||||
are fetch from the controller. Therefore it is possible to modify them
|
||||
in this hook.
|
||||
|
||||
EditFolder::EditFolder
|
||||
Called when the folder is to be updated
|
||||
|
||||
This hook can be used to replace the code for updating a folder. If
|
||||
the hook returns null, the original code for adding the
|
||||
document will be executed.
|
||||
|
||||
EditFolder::postEditFolder
|
||||
Called after a folder was updated
|
||||
|
||||
This hook will be called after a folder was updated, both by the
|
||||
original code and within the hook removeFolder. It will not be
|
||||
called if updating the folder failed.
|
||||
The return value of this hook should always be null.
|
||||
|
||||
TransferDocument::preTransferDocument
|
||||
|
||||
TransferDocument::transferDocument
|
||||
|
||||
TransferDocument::postTransferDocument
|
||||
|
||||
ViewOnline::version
|
||||
Called when a document is downloaded for online view
|
||||
|
||||
Download::version
|
||||
Called when a document is downloaded for saving on disk
|
||||
|
||||
Login::preLogin
|
||||
Called before a user is logged in
|
||||
|
||||
Login::authenticate
|
||||
Called before any other authentication is done
|
||||
|
||||
If this hooks returns a user, no other authentication will be done.
|
||||
If it returns false, the login fails as well.
|
||||
|
||||
Login::restrictLogin
|
||||
Called right before the user is considered to be logged in
|
||||
|
||||
This hook can contain a last check which keeps the user from being
|
||||
logged in. Return false to stop login. The authenticated user is
|
||||
passed to the hook.
|
||||
|
||||
Login::postLogin
|
||||
Called after user in fully logged in
|
||||
|
||||
The logged in user is passed to the hook.
|
||||
|
||||
Login::loginFailed
|
||||
Called if authentication failed
|
||||
|
||||
Logout::postLogout
|
||||
Called after user is logged out
|
||||
|
||||
IndexDocument::preIndexDocument
|
||||
|
||||
Currently available view hooks
|
||||
------------------------------------
|
|
@ -1,271 +1,76 @@
|
|||
SeedDMS Installation Instructions
|
||||
==================================
|
||||
|
||||
NOTE FOR VERSION 4.0.0
|
||||
======================
|
||||
|
||||
Since version 4.0.0 of SeedDMS installation has been simplified.
|
||||
ADOdb is no longer needed because the database access is done by
|
||||
PDO.
|
||||
|
||||
IMPORTANT NOTE ABOUT TRANSLATIONS
|
||||
=================================
|
||||
|
||||
As you can see SeedDMS provides a lot of languages but we are not professional
|
||||
translators and therefore rely on user contributions.
|
||||
|
||||
If your language is not present in the login panel:
|
||||
- copy the language/English/ folder and rename it appropriately for your
|
||||
language
|
||||
- open the file `languages/your_lang/lang.inc` and translate it
|
||||
- open the help file `languages/your_lang/help.htm` and translate it too
|
||||
|
||||
If you see some wrong or not translated messages:
|
||||
- open the file `languages/your_lang/lang.inc`
|
||||
- search the wrong messages and translate them
|
||||
|
||||
if you have some "error getting text":
|
||||
- search the string in the english file `languages/english/lang.inc`
|
||||
- copy to your language file `languages/your_lang/lang.inc`
|
||||
- translate it
|
||||
|
||||
If there is no help in your language:
|
||||
- Copy the English help `english/help.htm` file to your language folder
|
||||
- translate it
|
||||
|
||||
If you apply any changes to the language files please send them to the
|
||||
SeedDMS developers <info@seeddms.org>.
|
||||
|
||||
http://www.iana.org/assignments/language-subtag-registry has a list of
|
||||
all language and country codes.
|
||||
|
||||
REQUIREMENTS
|
||||
============
|
||||
|
||||
SeedDMS is a web-based application written in PHP. It uses MySQL,
|
||||
SQLite3 or PostgreSQL to manage the documents that were uploaded into
|
||||
the application. Be aware that PostgreSQL is not very well tested.
|
||||
SeedDMS is a web-based application written in PHP. It uses the MySQL RDBMS
|
||||
or sqlite3 to manage the documents that were uploaded into the application.
|
||||
|
||||
Make sure you have PHP >= 8.2 and MySQL 5 or higher installed. SeedDMS
|
||||
will work with PHP running in CGI-mode as well as running as a module under
|
||||
apache.
|
||||
Make sure you have PHP 5.3 and MySQL 5 or higher installed. SeedDMS
|
||||
will work with PHP running in CGI-mode as well as running as module under
|
||||
apache. If you want to give your users the opportunity of uploading passport
|
||||
photos you have to enable the gd-library (but the rest of SeedDMS will
|
||||
work without gd, too).
|
||||
|
||||
Here is a detailed list of requirements:
|
||||
|
||||
1. A web server with at least php 8.2
|
||||
2. A mysql database, unless you use SQLite
|
||||
3. The php installation must have support for `pdo_mysql`, `pdo_pgsql` or `pdo_sqlite`,
|
||||
`php_gd2`, `php_mbstring`, `php_xml`
|
||||
4. Depending on the configuration the extensions `php_ldap`, `php_mycrypt`,
|
||||
`php_gmp`, `php_libsodium`, `php_imagick` must be installed
|
||||
5. Various command line programms to convert files into text for indexing
|
||||
pdftotext, catdoc, xls2csv or scconvert, cat, id3 (all optional, only needed
|
||||
1. A web server with at least php 5.3
|
||||
2. A mysql database, unless you use sqlite
|
||||
3. The php installation must have support for `pdo_mysql` or `pdo_sqlite`,
|
||||
`php_gd2`, `php_mbstring`
|
||||
4. Various command line programms to convert files into text for indexing
|
||||
pdftotext, catdoc, xls2csv or scconvert, cat, id3 (optional, only needed
|
||||
for fulltext search)
|
||||
6. ImageMagic (the convert program) is needed for creating preview images
|
||||
7. A bunch of packages from Packagist which all ship with the seeddms-quickstart
|
||||
archive
|
||||
|
||||
It is highly recommended to use the quickstart archive
|
||||
(seeddms-quickstart-x.y.z.tar.gz) because it includes all software packages
|
||||
(excluding those listed above in item 1. to 6.) for running SeedDMS. Hence,
|
||||
you still need a working web server with PHP and in addition a mysql or
|
||||
PostgreSQL database unless you intend to use SQLite.
|
||||
|
||||
QUICKSTART
|
||||
===========
|
||||
|
||||
The fastes way to get SeedDMS running is by unpacking the archive
|
||||
`seeddms-quickstart-x.y.z.tar.gz` on your webserver.
|
||||
Let's assume you use seeddms-quickstart-5.1.x.tar.gz.
|
||||
It will create a new directory `seeddms51x` containing everything you
|
||||
need to run SeedDMS with SQLite3. Even if you intend to use mysql in the
|
||||
long run it is advisable to first set up SeedDMS with SQLite3 and than
|
||||
just switch the database.
|
||||
|
||||
Setting up the web server
|
||||
--------------------------
|
||||
|
||||
First of all you will need to set up your web server. Here, we will only focus
|
||||
on apache running on Debian/GNU Linux.
|
||||
Either let the document root of your web server point to the directory `www`
|
||||
below `seeddms51x`
|
||||
|
||||
DocumentRoot /var/www/seeddms51x/www
|
||||
|
||||
or add an alias. For apache this could be like
|
||||
|
||||
Alias /seeddms51x /<some directory>/seeddms51x/www
|
||||
|
||||
or even
|
||||
|
||||
Alias /mydms /<some directory>/seeddms51x/www
|
||||
|
||||
Do not set the DocumentRoot or Alias to
|
||||
the `seeddms51x` directory, because this will allow anybody to access
|
||||
your `data` and `conf` directory if it is not secured by a .htaccess file.
|
||||
This is a major security risk.
|
||||
|
||||
Make sure that the subdirectory `seeddms51x/data` and the configuration file
|
||||
`seeddms51/conf/settings.xml` is writeable by your web server. All other
|
||||
directories can be just readable by your web server, though it is advisable
|
||||
to even protect them from writing.
|
||||
|
||||
Adjusting the configuration of SeedDMS
|
||||
---------------------------------------
|
||||
|
||||
In the next step you need to adjust the configuration file in
|
||||
`seeddms51x/conf/settings.xml`. Open the file in your favorite text editor
|
||||
and search for `/home/wwww-data`. Replace that part in any path found with your
|
||||
base directory where you placed seeddms51x (e.g. /var/www/html/seeddms51x).
|
||||
Alternatively, you can open the installer with a browser at
|
||||
http://your-domain/install (if the document root points to
|
||||
`seeddms51x/www`) or http://your-domain/seeddms51x/install/ (if you have
|
||||
set an alias like described above).
|
||||
|
||||
It will first ask to unlock the installer by creating a file
|
||||
`ENABLE_INSTALL_TOOL` in the diretory `seeddms51x/conf/`. Change all paths by
|
||||
replacing `/home/www-data` with your base directory where you put seeddms51x.
|
||||
Set httpRoot to `/` (if the document root points to `seeddms51x/www`) or
|
||||
`/seeddms51x` (if you have set an alias `seeddms51x` like described above).
|
||||
|
||||
Once your configuration is done,
|
||||
save it, remove the file `ENABLE_INSTALL_TOOL` and point your browser to
|
||||
http://your-domain/ or http://your-domain/seeddms51x.
|
||||
|
||||
SECURITY CONSIDERATIONS
|
||||
=======================
|
||||
|
||||
You should always access your SeedDMS installation through
|
||||
a secured https connection, unless you precisly know what you are doing.
|
||||
SeedDMS ships an `.htaccess` file which already has some common security
|
||||
http headers set. In order for them to apply you need to activate the
|
||||
headers module. On Debian/GNU Linux this can be done with
|
||||
|
||||
```
|
||||
a2enmod headers
|
||||
```
|
||||
|
||||
Protect directories with data or configuration
|
||||
---------------------------------------------
|
||||
|
||||
A crucial point when setting up SeedDMS is the propper placement of the
|
||||
data directory. Do not place it below your document root of your web server!
|
||||
If you do so, there is a potential way that
|
||||
attackers can easily access your documents with a regular web browser.
|
||||
If you cannot place the data directory outside of document root, then either
|
||||
restrict access to it with an appropriate `.htaccess` file like the following.
|
||||
The SeedDMS quickstart archive already includes this `.htaccess` file.
|
||||
|
||||
```
|
||||
# line below if for Apache 2.4
|
||||
<ifModule mod_authz_core.c>
|
||||
Require all denied
|
||||
</ifModule>
|
||||
|
||||
# line below if for Apache 2.2
|
||||
<ifModule !mod_authz_core.c>
|
||||
deny from all
|
||||
Satisfy All
|
||||
</ifModule>
|
||||
|
||||
# section for Apache 2.2 and 2.4
|
||||
<ifModule mod_autoindex.c>
|
||||
IndexIgnore *
|
||||
</ifModule>
|
||||
```
|
||||
|
||||
Alternatively or in addition you can change
|
||||
the `contentOffsetDir` in `settings.xml` to something random, but ensure it
|
||||
is still a valid directory name. If you change contentOffsetDir, then
|
||||
do not forget to move `data/1048576` to `data/<your random name>`.
|
||||
Also turn off directory listings in your apache configuration for the
|
||||
`data` directory.
|
||||
5. ImageMagic (the convert program) is needed for creating preview images
|
||||
6. The Zend Framework (version 1) (optional, only needed for fulltext search)
|
||||
7. The pear Log package
|
||||
8. The pear HTTP_WebDAV_Server package (optional, only need for webdav)
|
||||
9. SLIM RestApi
|
||||
10. FeedWriter from https://github.com/mibe/FeedWriter
|
||||
|
||||
|
||||
Securing the configuration file
|
||||
---------------------------------
|
||||
|
||||
The configuration can be fully controlled by any administrator of SeedDMS. This
|
||||
can be crucial for those configuration options where external commands are
|
||||
being configured, e.g. for the full text engine or creating preview images.
|
||||
As a hoster you may not want this configuration options being set by a SeedDMS
|
||||
administrator. For now you need to make the configuration file `settings.xml`
|
||||
unwritable for the web server. In that case the SeedDMS administrator can
|
||||
still see the configuration but will not be able to change it.
|
||||
|
||||
Since version 5.1.23 and 6.0.16 of SeedDMS there is some preliminary way to
|
||||
hide parts of the configuration which makes them unchangeable for the
|
||||
SeedDMS administrator.
|
||||
|
||||
Setting a new encryption key
|
||||
------------------------------
|
||||
|
||||
Though this is not related to setting up the web server environment, it is
|
||||
important to recreated the encryption key in SeedDMS once SeedDMS is running.
|
||||
Just open the settings in the admin tools and empty the currently set
|
||||
encryption key on the tab 'System'. Save the settings and check the key again.
|
||||
It should be a new one. Save the settings again. The encryption key is
|
||||
mainly used for creating tokens in HTML forms to prevent CSRF attacks.
|
||||
|
||||
UPGRADING FROM A PREVIOUS VERSION OF SEEDDMS
|
||||
=============================================
|
||||
|
||||
As SeedDMS is a smooth continuation of LetoDMS there is no difference
|
||||
in updating from LetoDMS or SeedDMS.
|
||||
|
||||
You have basically two choices to update SeedDMS:
|
||||
|
||||
- you install a fresh version of SeedDMS and copy over your data and configuration
|
||||
- you replace the software in your current installation with a new version
|
||||
|
||||
The first option is less interuptive but requires to be able to set up a second
|
||||
temporary SeedDMS installation, which may not be possible, e.g. because of storage
|
||||
limitations. It can be the only option if you change servers.
|
||||
|
||||
The first update procedure is only needed if the version changes on the minor
|
||||
or major version number. Changes in the subminor version number will never
|
||||
include database changes and consequently it is sufficient to use the existing
|
||||
data directory and database with the new version. Choose the second update
|
||||
option in this case.
|
||||
|
||||
In both cases make sure to have a backup of your data directory, configuration
|
||||
and database.
|
||||
|
||||
Fresh installation and take over of data
|
||||
-----------------------------------------
|
||||
|
||||
The first update option is to set up a new instance of SeedDMS and once
|
||||
that is running take over the data from your current (old) instance.
|
||||
|
||||
1. just do a fresh installation somewhere on your web server and make sure it
|
||||
works. It is fine to use
|
||||
SQLite for it, even if your final installation uses MySQL.
|
||||
2. replace the data directory in your new installation with the data directory
|
||||
from your current installation. Depending on the size of that directory (and
|
||||
whether the new installation is on a new server or the old server) you
|
||||
may either copy, move or place a symbolic link. The content of the data directory
|
||||
will not be changed during the update. Its even perfectly save to
|
||||
browse through your documents and download them after finishing the
|
||||
update. The data directory will not be modified until you actually modify
|
||||
documents.
|
||||
3. copy over the configuration `settings.xml` into your new installation. This will
|
||||
effectively make your new installation use the data from your old installation,
|
||||
because all paths are still pointing to the old installation.
|
||||
4. if you use mysql you could as well make a copy of the database to make sure
|
||||
your current database remains unchanged.
|
||||
5. modify the `settings.xml` to fit the environment of the new installation.
|
||||
This will mostly be the
|
||||
httpRoot, the paths to the installation directory and possibly the database
|
||||
connection.
|
||||
6. create a file `ENABLE_INSTALL_TOOL` in the `conf` directory and point
|
||||
your browser at http://hostname/seeddms/install
|
||||
The install tool will detect the version of your current SeedDMS installation
|
||||
and run the required database updates.
|
||||
If you update just within the last version number (e.g. from 5.1.6 to 5.1.9),
|
||||
this step
|
||||
will not be required because such a subminor version update will never
|
||||
contain database updates.
|
||||
|
||||
Upgrading your current installation
|
||||
-----------------------------------
|
||||
|
||||
Instead of setting up a new installation, you may as well replace the php files
|
||||
in your current installation with new versions from the quickstart archive.
|
||||
|
||||
1. get the SeedDMS quickstart archive `seeddms-quickstart-x.y.z.tar.gz` and
|
||||
unpack it somewhere on your disc.
|
||||
2. copy the directory `seeddms-x.y.z` from the unpacked archive into your
|
||||
current installation and make the link `seeddms` point to this new directory.
|
||||
3. copy the directory `pear` from the unpacked archive into your current
|
||||
installation, replacing the existing directory. Make a backup of `pear` before
|
||||
the replacement if you want to ensure to be able to go back to your old version.
|
||||
4. you may compare your `conf/settings.xml` file with the shipped version
|
||||
`conf/settings.xml.template` for new parameters. If you don't do it, the next
|
||||
time you save the configuration the default values will be used.
|
||||
5. create a file `ENABLE_INSTALL_TOOL` in the `conf` directory and point
|
||||
your browser at http://hostname/seeddms/install
|
||||
The install tool will detect the version of your current SeedDMS installation
|
||||
and run the required database updates.
|
||||
If you update just within the last version number (e.g. from 5.1.6 to 5.1.9),
|
||||
this step
|
||||
will not be required because such a subminor version update will never
|
||||
contain database updates.
|
||||
|
||||
|
||||
THE LONG STORY
|
||||
BEFORE YOU START
|
||||
================
|
||||
|
||||
This section is mostly outdated but may still contain some valueable
|
||||
information for those trying to understand the installation process.
|
||||
|
||||
If you intend to run a single instance of SeedDMS, you are most likely
|
||||
better off by using the quickstart archive as described above. This
|
||||
section is mostly for users who wants to know more about the internals
|
||||
of SeedDMS or do packaging for a software distribution, which already
|
||||
ships some of the additional software SeedDMS requires.
|
||||
|
||||
SeedDMS has changed its installation process with version 3.0.0. This gives
|
||||
you many more options in how to install SeedDMS. First of all, SeedDMS was
|
||||
split into a core package (`SeedDMS_Core-<version>.tar.gz`) and the web
|
||||
|
@ -299,7 +104,7 @@ on your web server.
|
|||
-------------------
|
||||
|
||||
A common source of problems in the past have been the additional software
|
||||
packages needed by SeedDMS. Those are the PEAR packages `Log`, `Mail` and
|
||||
packages needed by SeedDMS. Those are the PEAR packages `Log` and
|
||||
`HTTP_WebDAV_Server` as well as the `Zend_Framework`.
|
||||
If you have full access to the server running a Linux distribution it is
|
||||
recommended to install those with your package manager if they are provided
|
||||
|
@ -345,7 +150,7 @@ http://localhost/seeddms/
|
|||
* Point you web browser towards http://hostname/seeddms/install/
|
||||
|
||||
* Follow the instructions on the page and create a file `ENABLE_INSTALL_TOOL`
|
||||
in the `conf` directory.
|
||||
in the conf directory.
|
||||
|
||||
* Create a data directory with the thre sub directories staging, cache
|
||||
and lucene.
|
||||
|
@ -399,16 +204,13 @@ full text search engine support, you will also need to unpack
|
|||
> pear install SeedDMS_Lucene-<version>.tgz
|
||||
> pear install SeedDMS_Preview-<version>.tgz
|
||||
|
||||
* The PEAR packages Log and Mail are also needed. They can be downloaded from
|
||||
http://pear.php.net/package/Log and http://pear.php.net/package/Mail.
|
||||
Either install it as a pear package
|
||||
* The PEAR package Log is also needed. It can be downloaded from
|
||||
http://pear.php.net/package/Log. Either install it as a pear package
|
||||
or place it under your new directory 'pear'
|
||||
|
||||
> pear
|
||||
> Log
|
||||
> Log.php
|
||||
> Mail
|
||||
> Mail.php
|
||||
|
||||
* The package HTTP_WebDAV_Server is also needed. It can be downloaded from
|
||||
http://pear.php.net/package/HTTP_WebDAV_Server. Either install it as a
|
||||
|
@ -454,10 +256,29 @@ If you install SeedDMS for the first time continue with the database setup.
|
|||
e.g. for mysql:
|
||||
> cat create_tables-innodb.sql | mysql -useeddms -p seeddms
|
||||
This step can also be done by the install tool.
|
||||
* create a file `ENABLE_INSTALL_TOOL` in the `conf` directory and point
|
||||
* create a file `ENABLE_INSTALL_TOOL` in the conf directory and point
|
||||
your browser at http://hostname/seeddms/install
|
||||
|
||||
|
||||
NOTE: UPDATING FROM A PREVIOUS VERSION OR SEEDDMS
|
||||
|
||||
As SeedDMS is a smooth continuation of LetoDMS there is no difference
|
||||
in updating from LetoDMS or SeedDMS
|
||||
|
||||
- make a backup archive of your installation folder
|
||||
- make a backup archive of your data folder
|
||||
- dump your current database
|
||||
- extract the SeedDMS archive to your web server
|
||||
- edit the conf/settings.xml file to match your previuos settings
|
||||
(you can even replace the file with your own one eventualy adding by hand
|
||||
the missing new parameters)
|
||||
- create a file `ENABLE_INSTALL_TOOL` in the conf directory and point
|
||||
your browser at http://hostname/seeddms/install
|
||||
|
||||
The install tool will detect the version of your current SeedDMS installation
|
||||
and run the required database updates.
|
||||
|
||||
|
||||
3. Email Notification
|
||||
---------------------
|
||||
|
||||
|
@ -555,47 +376,21 @@ settings in conf/settings.xml or run the installation tool.
|
|||
|
||||
Point your web browser towards the index.php file in your new instance.
|
||||
|
||||
NOTE FOR VERSION 4.0.0
|
||||
======================
|
||||
|
||||
Since version 4.0.0 of SeedDMS installation has been simplified.
|
||||
ADOdb is no longer needed because the database access is done by
|
||||
PDO.
|
||||
|
||||
IMPORTANT NOTE ABOUT TRANSLATIONS
|
||||
=================================
|
||||
|
||||
As you can see SeedDMS provides a lot of languages but we are not professional
|
||||
translators and therefore rely on user contributions.
|
||||
|
||||
If your language is not present in the login panel:
|
||||
- copy the language/English/ folder and rename it appropriately for your
|
||||
language
|
||||
- open the file `languages/your_lang/lang.inc` and translate it
|
||||
- open the help file `languages/your_lang/help.htm` and translate it too
|
||||
|
||||
If you see some wrong or not translated messages:
|
||||
- open the file `languages/your_lang/lang.inc`
|
||||
- search the wrong messages and translate them
|
||||
|
||||
if you have some "error getting text":
|
||||
- search the string in the english file `languages/english/lang.inc`
|
||||
- copy to your language file `languages/your_lang/lang.inc`
|
||||
- translate it
|
||||
|
||||
If there is no help in your language:
|
||||
- Copy the English help `english/help.htm` file to your language folder
|
||||
- translate it
|
||||
|
||||
If you apply any changes to the language files please send them to the
|
||||
SeedDMS developers <info@seeddms.org>.
|
||||
|
||||
http://www.iana.org/assignments/language-subtag-registry has a list of
|
||||
all language and country codes.
|
||||
|
||||
LICENSING
|
||||
=========
|
||||
|
||||
SeedDMS is licensed unter GPLv2
|
||||
|
||||
Jumploader is licensed as stated by the author on th web site
|
||||
<http://jumploader.com/>
|
||||
|
||||
-- Taken from web site of jumploader ---
|
||||
You may use this software for free, however, you should not:
|
||||
|
||||
- Decompile binaries.
|
||||
- Alter or replace class and/or resource files.
|
||||
- Redistribute this software under different name or authority.
|
||||
|
||||
If you would like a customized version, I can do this for a fee. Don't hesitate to contact me with questions or comments.
|
||||
|
||||
Uwe Steinmann <info@seeddms.org>
|
||||
|
|
|
@ -1,66 +0,0 @@
|
|||
Ldap configuration
|
||||
===================
|
||||
|
||||
The configuration for authentication against an ldap server needs to be done
|
||||
in the `settings.xml` file using a text editor. It cannot be edited from within the
|
||||
web gui.
|
||||
|
||||
SeedDMS supports ldap authentication using an Active Directory (AD) or a
|
||||
regular ldap server, e.g. openldap
|
||||
|
||||
The location of the ldap server is specified in two parameters: `host` and
|
||||
`port`. `host` can be either a plain hostname or an ldap URI, including the
|
||||
protocol, the host and optionally the port, e.g. ldap://localhost:389. In case
|
||||
of an URI the port in the configuration must remain empty.
|
||||
|
||||
The authentication itself is a two step process which differs, depending on how
|
||||
to bind to the server. If the configuration sets 'bindDN' and 'bindPW', those
|
||||
values will be used for a initial non anonymous bind to the ldap server
|
||||
otherwise an anonymous bind is executed.
|
||||
|
||||
After the initial bind, a ldap search for either 'uid=<username>' (ldap) or
|
||||
'sAMAccountName=<username>' (AD) below basedn is done. The purpose of this
|
||||
search is to retrieve a working bindDN which is then used to actually
|
||||
authenticate the user. In case of an anonymous first bind the search will
|
||||
likely fail and the bindDN for the second bind will be either
|
||||
'uid=<username>,<basedn>' (ldap) or '<username>@<accountDomainName>' (AD). If
|
||||
the search succeeds the bindDN will be taken from the user's data in the ldap
|
||||
server. This bindDN will be used for a second bind using the users password.
|
||||
If the second bind succeeds the user could be successfully authenticated.
|
||||
|
||||
The data from the ldap server can be used to create an account in SeedDMS
|
||||
if the user trying to login does not exist yet, but was able to authenticate.
|
||||
This will only be done if 'authentication->restricted' in the configuration
|
||||
is set to false. In that case the common name (cn) and email address is taken
|
||||
from ldap. An already existing account in SeedDMS will be updated with data from
|
||||
ldap.
|
||||
|
||||
Since version 5.1.35 and 6.0.28 the field name of the email address in ldap
|
||||
can be set with the attribute `mailField`. If it is not set it defaults to `mail`.
|
||||
|
||||
Since version 5.1.34 and 6.0.27 the groups of a user stored in the ldap directory
|
||||
can be synchronised with the groups in SeedDMS. The ldap field storing
|
||||
the groups can be configured with the attribute `mailField`. This will add
|
||||
new groups in SeedDMS and aѕsign them to the user.
|
||||
|
||||
Examples
|
||||
---------
|
||||
|
||||
Anonymous bind to openldap on localhost, port 389
|
||||
- type = "ldap"
|
||||
- baseDN = "ou=users,dc=mycompany,dc=de"
|
||||
- host = "ldap://localhost"
|
||||
|
||||
During authentication as user 'admin' the following steps are executed
|
||||
|
||||
1. connect to ldap server at localhost:389
|
||||
2. do an anonymous bind
|
||||
3. search for 'uid=admin' below basedn
|
||||
4.1. if search succeeds use the dn from the user
|
||||
4.2. if search fails use 'uid=admin,<basedn>' as dn
|
||||
5. do a non anonymous bind with dn and password entered by user
|
||||
6. if step 5. succeeds the use is authenticated
|
||||
|
||||
If bindDN and bindPW are specified in the configuration, the second step
|
||||
will be a non anonymous bind.
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
Mail configuration
|
||||
===================
|
||||
|
||||
SeedDMS uses email to
|
||||
|
||||
* notify users about changes of documents and folders
|
||||
* send instructions during the password forgotten process
|
||||
|
||||
Configuring email in SeedDMS is simple on systems running a
|
||||
local mail server, because this is the default in SeedDMS and
|
||||
no additional configuration is needed. On Linux you should
|
||||
consider running a local mail server, which relais the mails
|
||||
to your outgoing mail server. If you cannot run a local mail
|
||||
server, you can still configure SeedDMS to use an outgoing
|
||||
SMTP server. Below are some examples on how to configure
|
||||
SeedDMS for different hosters.
|
||||
|
||||
1&1
|
||||
---------
|
||||
|
||||
smtp server: ssl://smtp.1und1.de
|
||||
smtp port: 465
|
||||
|
||||
Gmail
|
||||
---------
|
||||
smtp server: ssl://smtp.gmail.com
|
||||
smtp port: 465
|
||||
note: since June, 2022 you will no longer be able to turn on 'Less secure app access' in your google account. Instead you need to turn on 2-Step Verification first and than
|
||||
create an App Password (https://support.google.com/accounts/answer/185833)
|
|
@ -3,17 +3,7 @@ Notifications
|
|||
|
||||
Most changes made to documents or folders in SeedDMS can be monitored
|
||||
by the users. Notifications are send by email if a user or group
|
||||
has subscribed to it. Setting up email is often troublesome, if you
|
||||
are not running SeedDMS on a Linux server with a running mail server.
|
||||
In that case you do not have to fill out any of the email settings
|
||||
except for the From address ('Send from' on the 'System' tab of the
|
||||
configuration). Mail is send by PHP's mail() function. If the SMTP
|
||||
host in the configuration is filled out, SeedDMS will use the PEAR
|
||||
Mail package for delivering mail to the configured server. If you
|
||||
also fill out the SMTP user, authentication with the SMTP server
|
||||
will also be done. Some servers like smtp.gmail.com may still complain
|
||||
about an invalid authentification. You should then check in your
|
||||
google account if less secure apps are allowed.
|
||||
has subscribed it.
|
||||
|
||||
The following notifications are send to all users and groups having
|
||||
registered a notification for the event:
|
||||
|
@ -106,11 +96,6 @@ op/op.ReviewDocument.php
|
|||
* document was reviewed
|
||||
subscribers of the document
|
||||
|
||||
op/op.SetReviewersApprovers.php
|
||||
* Reviewers/approvers were added/deleted
|
||||
subscribers of the document
|
||||
uploader of version
|
||||
|
||||
op/op.RewindWorkflow.php
|
||||
* Workflow was rewind to beginning
|
||||
subscribers of the document
|
||||
|
@ -123,31 +108,7 @@ op/op.TriggerWorkflow.php
|
|||
* Workflow transition was triggered
|
||||
subscribers of the document
|
||||
|
||||
op/op.UpdateDocument2.php
|
||||
op/op.UpdateDocument.php
|
||||
* document was updated
|
||||
subscribers of the document
|
||||
|
||||
op/op.ReceiptDocument.php
|
||||
* document was received
|
||||
subscribers of the document
|
||||
|
||||
op/op.ReviseDocument.php
|
||||
* document was revised
|
||||
subscribers of the document
|
||||
|
||||
op/op.SetRevisors.php
|
||||
* Revisors were added/deleted
|
||||
subscribers of the document
|
||||
uploader of version
|
||||
revisor
|
||||
|
||||
op/op.ReceiptDocument.php
|
||||
* document was receipt
|
||||
subscribers of the document
|
||||
|
||||
op/op.SetRecipients.php
|
||||
* Recipients were added/deleted
|
||||
subscribers of the document
|
||||
uploader of version
|
||||
recipient
|
||||
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
# How to access the Rest API
|
||||
|
||||
Below are various examples on how to access the Rest API. Some of them
|
||||
start by calling the `login` endpoint which creates a cookie based
|
||||
session which is stored in a local file named `cookies.txt`.
|
||||
The authentication is done with the user `admin`. You may use any other
|
||||
user as well.
|
||||
|
||||
You may as well pass `-H Authorization: <api key>` instead of `-b cookies.txt`
|
||||
to `curl` after setting the api key in the configuration of your SeedDMS.
|
||||
Of course, in that case you will not need the initial call of the `login`
|
||||
endpoint.
|
||||
|
||||
The examples often use the `jq` programm for formating the returned
|
||||
json data.
|
||||
|
||||
## Initial test
|
||||
|
||||
The `echo` endpoint does not require any authentication.
|
||||
|
||||
```
|
||||
#!/bin/sh
|
||||
BASEURL="https://your-domain/"
|
||||
|
||||
curl --silent -X GET ${BASEURL}restapi/index.php/echo/test | jq '.'
|
||||
|
||||
```
|
||||
|
||||
## Getting list of users
|
||||
|
||||
```
|
||||
#!/bin/sh
|
||||
BASEURL="https://your-domain/"
|
||||
|
||||
curl --silent -F "user=admin" -F "pass=admin" -b cookies.txt -c cookies.txt ${BASEURL}restapi/index.php/login | jq
|
||||
|
||||
curl --silent -b cookies.txt -X GET "${BASEURL}restapi/index.php/users" | jq '.'
|
||||
```
|
||||
|
||||
## Getting meta data of a folder
|
||||
|
||||
```
|
||||
#!/bin/sh
|
||||
BASEURL="https://your-domain/"
|
||||
|
||||
curl --silent -H "Authorization: <api key>" -X GET "${BASEURL}restapi/index.php/folder/1" | jq '.'
|
||||
```
|
||||
## Notes
|
||||
|
||||
Make sure to encode the data properly when using restapi functions which uses
|
||||
put. If you use curl with PHP, then encode the data as the following
|
||||
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
Scheduler
|
||||
==========
|
||||
|
||||
The scheduler in SeedDMS manages frequently run tasks. It is very similar
|
||||
to regular unix cron jobs. A task in SeedDMS is an instanciation of a task
|
||||
class which itself is defined by an extension or SeedDMS itself.
|
||||
SeedDMS has some predefined classes e.g. core::expireddocs.
|
||||
|
||||
In order for tasks to be runnalbe, a user `cli_scheduler` must exists in
|
||||
SeedDMS.
|
||||
|
||||
All tasks are executed by a single cronjob in the directory `utils`
|
||||
|
||||
> */5 * * * * /home/www-data/seeddms60x/seeddms/utils/seeddms-schedulercli --mode=run
|
||||
|
||||
Please keep in mind, that the php interpreter used for the cronjob may be
|
||||
different from the php interpreter used für the web application. Hence, two
|
||||
different php.ini files might be used. php and the php extensions may differ as
|
||||
well. This can cause some extensions to be disabled and consequently some task
|
||||
classes are not defined.
|
||||
|
||||
`utils/seeddms-schedulercli` can also be run on the command line. If you
|
||||
do that, run it with the same system user used for the web server. On Debian
|
||||
this is www-data. Hence run it like
|
||||
|
||||
sudo -u www-data utils/seeddms-schedulercli --mode=list
|
|
@ -1,23 +0,0 @@
|
|||
Swagger
|
||||
========
|
||||
|
||||
Swagger is used to describe a rest api. SeedDMS ships a swagger.yaml file
|
||||
in the restapi directory. You can load this file into a swagger editor, e.g.
|
||||
http://petstore.swagger.io/ or http://editor.swagger.io/
|
||||
You may as well set up your own swagger-ui installation as described at
|
||||
https://medium.com/@tatianaensslin/how-to-add-swagger-ui-to-php-server-code-f1610c01dc03
|
||||
|
||||
Your apache needs to have the module `header` enabled, because some HTTP headers
|
||||
are set when the file `swagger.yaml` is accessed by the editor.
|
||||
|
||||
Currently, the swagger.yaml shipped with SeedDMS uses still swagger 2.0
|
||||
|
||||
If you are using php-fpm you will have to ensure that files with
|
||||
extension .yaml are allowed to be parsed. Extend the
|
||||
`security.limit_extensions` in the pool configuration by `.yaml`. Also
|
||||
check the contents of the file `.htaccess` in directory `restapi`. It
|
||||
by default sets the handler for php to `application/x-httpd-php` which
|
||||
uses the apache module of php. If you would like to use php-fpm
|
||||
instead, then set it to
|
||||
|
||||
SetHandler "proxy:unix:/var/run/php/php8.2-fpm.sock|fcgi://localhost/"
|
|
@ -1,16 +1,14 @@
|
|||
*********************************************
|
||||
How to set up a Synology NAS to run SeedDMS
|
||||
How to set up SeedDMS Preview on Synology NAS
|
||||
*********************************************
|
||||
|
||||
**This guide has been updated and tested to work on Synology DSM 6.0. It should as well work with older DMS versions, however some steps or paths may be different.**
|
||||
|
||||
Introduction
|
||||
############
|
||||
SeedDMS is a feature rich and lightweight document management system. Unfortunately, some of the tools which are part of many Linux distros, have not been made available by
|
||||
Synology and therefore require additional steps to bring them to your Synology.
|
||||
SeedDMS provides a function creating a preview of each document which is displayed on the document page.
|
||||
|
||||
This guide covers the installation of the required tools to have all features of SeedDMS available. It does not cover the installation of 3rd party programs (like OPKG). It
|
||||
does not cover the installation of SeedDMS as well, please refer to the separate README.Install.md file.
|
||||
Synology stations do not support the creation of the previews by default due to a missing Ghostscript implementation. Therefore
|
||||
loading of a document page can use a lot of time because SeedDMS tries to create the missing preview images each time the document
|
||||
page is being loaded.
|
||||
|
||||
Prerequisites
|
||||
#############
|
||||
|
@ -22,7 +20,7 @@ In order to complete the steps outlined below, you must be able to carry out the
|
|||
To complete the installation, the following prerequisites on your Synology must be met:
|
||||
|
||||
* IPKG or OPKG (OPKG preferred) installed
|
||||
* PEAR installed from the Synology Package Center
|
||||
* Pear Package SeedDMS_Preview already installed
|
||||
|
||||
Installation and configuration
|
||||
##############################
|
||||
|
@ -33,8 +31,8 @@ must be done on the terminal.
|
|||
Install Ghostscript
|
||||
***************************
|
||||
|
||||
The first step is to install Ghostscript to make ImageMagick capable of converting PDF files to images which are then used for previews.
|
||||
Use IPKG or OPKG to complete this step.
|
||||
The first step is to install Ghostscript to make ImageMagick capable of converting PDF files to images. Use IPKG or OPKG to complete this
|
||||
step.
|
||||
|
||||
Make Ghostscript available to PHP
|
||||
*****************************************
|
||||
|
@ -44,10 +42,21 @@ use phpinfo and find **_SERVER["PATH"]**. If you can't find /opt inside, PHP can
|
|||
update the paths or just make a symlink.
|
||||
To create the symlink, cd to /usr/bin and type *ln -s /opt/bin/gs gs*. Verify the created symlink.
|
||||
|
||||
Fix Ghostscript package bug
|
||||
****************************************
|
||||
|
||||
Unfortunately the version delivered by OPKG has a bug, making Ghostscript failing to work properly. The bug requries fixing at the time
|
||||
of the writing are the following:
|
||||
|
||||
* Resource path pointing to a wrong version (9.10 instead of 9.16)
|
||||
|
||||
First, fix the resource path. Go to /opt/bin and find **gs** in there. Open the file with VI. Change the GS_LIB path from */opt/share/ghostscript/9.10/Resource*
|
||||
to */opt/share/ghostscript/9.16/Resource*. This will now allow Ghostscript to find it's files in the proper path.
|
||||
|
||||
Fix ImageMagick
|
||||
********************
|
||||
|
||||
Not only Ghostscript is affected by bugs, the default configuration files for ImageMagick are missing. Unfortunately some work is required here as well.
|
||||
Not only Ghostscript is affected by bugs, the default configuration files are missing. Unfortunately some work is required here as well.
|
||||
|
||||
To check where ImageMagick looks for it's files, invoke the command *convert -debug configure logo: null:*. You will see some paths shown, these
|
||||
are the paths where ImageMagic tries to locate it's configuration files. The first path shown will point to */usr/share/ImageMagick-6* followed by the
|
||||
|
@ -90,74 +99,11 @@ If you want to test Ghostcript as well, invoke the follwing command:
|
|||
|
||||
This command should go through without any errors and as well output a png file.
|
||||
|
||||
If the tests above are successful, you are ready to use SeedDMS Preview.
|
||||
If the tests above are successful, you are ready to use SeedDMS Preview. Go to your SeedDMS Installation and open a folder. For the first test you
|
||||
may take a folder with less files in it. Be patient while the previews are generated. You may check the process using *top* on the terminal.
|
||||
|
||||
Install PEAR packages
|
||||
*********************
|
||||
At the end your document page should show the previews like shown below:
|
||||
|
||||
This step is similar to the installation on other Linux distros. Once you installed PEAR from the Package Center you can call it from the command line.
|
||||
|
||||
The following packages are required by SeedDMS:
|
||||
|
||||
* Auth_SASL
|
||||
* HTTP_WebDAV_Server
|
||||
* Log
|
||||
* Mail
|
||||
* Net_SMTP
|
||||
|
||||
Install these packages, then go to the next step.
|
||||
|
||||
Install additional packages
|
||||
***************************
|
||||
|
||||
SeedDMS uses other small tools (for example the Slim Framework) to add some additional functionality. At the moment (Version 5.0.x) the list contains the following
|
||||
tools:
|
||||
|
||||
* FeedWriter
|
||||
* Slim
|
||||
* parsedown
|
||||
|
||||
Copy the tools to a folder on your Synology. Using the console, copy the tools to **/volume1/@appstore/PEAR**.
|
||||
Copy the whole folders as they are and do not change the structure. As the PEAR directory is already within
|
||||
the PHP include path, no further configuration is required to get them working.
|
||||
|
||||
Fulltext Index
|
||||
***************
|
||||
|
||||
If you do not intend to use the fulltext index, please skip this section and continue with the readme file to
|
||||
install SeedDMS.
|
||||
|
||||
To create the fulltext index, SeedDMS needs to be able to convert the documents to text files to read the terms
|
||||
out. Pdftotext is already available by default, so we just need to take care of the Microsoft Office formats.
|
||||
|
||||
For this guide, the following two tools have been selected:
|
||||
|
||||
docx2txt available from http://docx2txt.sourceforge.net/
|
||||
|
||||
xlsx2csv available from http://github.com/dilshod/xlsx2csv
|
||||
|
||||
Copy both files to your Synology.
|
||||
|
||||
**docx2txt**
|
||||
|
||||
This program runs without any kind of installation. Create a folder on your Synology and extract the contents of the archive.
|
||||
|
||||
In SeedDMS you can now configure the setting for Word documents to the path where you extracted the files in the step before. Point
|
||||
to the docx2txt.sh file and you are done.
|
||||
|
||||
To make the configuration more simple you can add a symlink in **/usr/bin**. This will allow you to call docx2txt from any location of your Synology.
|
||||
The symlink must point to docx2txt.sh to get it working. In SeedDMS you can now just configure docx2txt followed by any additional commands.
|
||||
|
||||
**xlsx2csv**
|
||||
|
||||
This one must be installed to get it working. The installation script is written in Python, so you need to get Python installed on your Synology.
|
||||
As the version available from Synology does not properly work (you can't install PIP) it is strongly recommended to use OPKG or IPKG to install Python.
|
||||
|
||||
Install Python and PIP. Once completed, point to the directory where you copied xlsx2csv. Unpack the archive, then execute the installer (pip install xlsx2csv).
|
||||
|
||||
Once completed, xlsx2csv is available and can be configured within SeedDMS.
|
||||
|
||||
Complete the installation
|
||||
*************************
|
||||
|
||||
Now you are ready to install SeedDMS and configure the database. Follow the README file to install SeedDMS.
|
||||
.. figure:: preview.png
|
||||
:alt: Document previews
|
||||
:scale: 75%
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
Help translating SeedDMS
|
||||
===========================
|
||||
|
||||
SeedDMS has got many translations over the years and it is a major
|
||||
task to keep them all updated. If you would like to give a helping
|
||||
hand, then this will be much appreciated. There are various ways
|
||||
to contribute translations.
|
||||
|
||||
1. The demo version of SeedDMS at https://demo.seeddms.org will list
|
||||
all missing translations in a formular on the bottom of the page
|
||||
while using the software. You can easily provide a missing translation
|
||||
by filling out the form and submitting it. The translation will not
|
||||
instantly be used, but is taken over into the official version of
|
||||
SeedDMS once in a while. This method does not allow to submit corrected
|
||||
translations of existing phrases.
|
||||
|
||||
2. Fixing translations is only possible by modifying one of the language
|
||||
files in `lanuages/xx_XX/lang.inc`. These files are php files containing
|
||||
one large array named `$text`. Any modification will be visible right away
|
||||
in your SeedDMS installation. If you intend to pass your modifications to
|
||||
the developers of SeedDMS, than keep your changes seperate from the
|
||||
original translation. A good way is to put your changes into a new
|
||||
file, e.g. `lang-local.inc` containing an array named `$text_local` and
|
||||
merge that array with the original translation array. Just put at the
|
||||
end of `lanuages/xx_XX/lang.inc` the follwing code:
|
||||
|
||||
include('lang-local.inc');
|
||||
array_merge($text, $text_local);
|
||||
|
||||
Also create the file `lang-local.inc` with the content
|
||||
|
||||
<?php
|
||||
$text_local = array(
|
||||
'xxx' => 'yyy',
|
||||
);
|
||||
?>
|
||||
|
||||
Once you are ready with your local modifications and you think those are
|
||||
good enough for the public version of SeedDMS, then please mail them to
|
||||
info@seeddms.org
|
||||
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
WebDAV
|
||||
========
|
||||
-----------------------------------------------
|
||||
|
||||
SeedDMS has support for WebDAV which allows to easily add, delete,
|
||||
move, copy and modify documents. All operating systems have support
|
||||
|
@ -13,121 +13,41 @@ and its content, while a file system knows just files.
|
|||
In SeedDMS a document is uniquely identified
|
||||
by its document id and not neccessarily by its name. A filesystem
|
||||
requires a unique paths for each file. Two identical files in the
|
||||
same folder are not possible. SeedDMS can handle identically named
|
||||
same folder are not possible. SeedDMS can handle identifcally named
|
||||
documents in one folder. In order to prevent any problems arising from
|
||||
this, you should always disallow identical document names in the
|
||||
settings. By definition a file in WebDAV is mapped on the latest
|
||||
version of a document in SeedDMS. There is no way to access previous
|
||||
versions of a document via WebDAV. Whenever you modify a file and
|
||||
upload it with the web gui,
|
||||
versions of a document via WebDAV. Whenever you modify a file,
|
||||
a new version will be created. Unfortunately, this has some very
|
||||
nasty side effects when you edit a document version via WebDAV and
|
||||
often save it, because any save
|
||||
operation will create a new version. This is why the WebDAV
|
||||
server has a configuration option which allows to either replace
|
||||
the content of document or creating a new
|
||||
version if a document is saved.
|
||||
nasty side effects when you often save a file, because any save
|
||||
operation will create a new version. This is because the WebDAV
|
||||
server replaces the content of document instead of creating a new
|
||||
version if a document is saved again.
|
||||
|
||||
Configuring davfs2
|
||||
-------------------
|
||||
|
||||
On Linux it is quite simple to mount the SeedDMS WebDAV server with
|
||||
davfs2. Just place a line like the following in your /etc/fstab
|
||||
|
||||
http://seeddms.your-domain.com/webdav/index.php /media/webdav davfs noauto,user,rw,uid=1000,gid=1000
|
||||
|
||||
and mount it as root with
|
||||
|
||||
mount /media/webdav davfs
|
||||
|
||||
You may as well want to configure davfs2 in /etc/davfs2/davfs2.conf by setting
|
||||
|
||||
[/media/webdav]
|
||||
use_locks 0
|
||||
gui_optimize 1
|
||||
|
||||
and possibly add your login data to /etc/davfs2/secrets
|
||||
|
||||
/media/webdav admin secret
|
||||
|
||||
Making applications work with WebDAV
|
||||
-------------------------------------
|
||||
|
||||
Various programms have differnt strategies to save files to disc and
|
||||
Various programms have differnt strategies to save files to disk and
|
||||
prevent data lost under all circumstances. Those strategies often don't
|
||||
work very well an a WebDAV-Server. The following will list some of those
|
||||
strategies.
|
||||
|
||||
### VIM
|
||||
VIM
|
||||
=========================
|
||||
|
||||
vim does a lot more than just reading and writing the file you want
|
||||
to edit. It creates swap and backup files for data recovery if vim crashes
|
||||
or is being killed unexpectively. On a low bandwidth connection this can
|
||||
or is being kill unexpectivly. On a low bandwidth connection this can
|
||||
slow down the editing. For that reason you should either not create the
|
||||
swap file at all or create it outside the WebDAV server. A second problem
|
||||
arises from how vim modifіes the file you are editing. Before a file
|
||||
is saved a backup is created by renaming the file to the same name with a
|
||||
'~' at the end and writing the file content into a new
|
||||
file with the name of the original file. Afterwards vim deletes the backup
|
||||
file. On a regular file system you
|
||||
won't see a difference between the file before and after saving, though
|
||||
it is actually a new one. In SeedDMS you won't notice a difference either
|
||||
by just looking at the document name. It's still the same, but the
|
||||
is saved a backup is created and the new content is written into a new
|
||||
file with the name of the original file. On a file system you
|
||||
won't see a difference between the file before and after saveing, though
|
||||
is actually a new one. In SeedDMS you won't notice a difference either
|
||||
if just looking at the document name. It's still the same, but the
|
||||
document id has changed. So saving a document will delete the
|
||||
old document and create a new one instead of creating a new version of
|
||||
the old document. If you don't want this behaviour, then tell vim
|
||||
to not create the backup file. You can do that by either passing additional
|
||||
parameters to vim
|
||||
|
||||
vi "+set nobackup" "+set nowritebackup" -n test.txt
|
||||
|
||||
or by setting them in your .vimrc
|
||||
|
||||
set nobackup
|
||||
set nowritebackup
|
||||
set noswapfile
|
||||
|
||||
If you want to restrict the settings to the directory where the dms
|
||||
is mounted by webdav, e.g. /media/webdav, you can set an auto command
|
||||
in .vimrc
|
||||
|
||||
autocmd BufNewFile,BufRead /media/webdav/* set nobackup nowritebackup noswapfile
|
||||
|
||||
Creating the backup file in a directory outside of WebDAV doesn't help in
|
||||
this case, because it still does the file renaming which is turned off by
|
||||
'nowritebackup'.
|
||||
|
||||
### cdaver
|
||||
|
||||
cadaver is a webdav client similar to classical command line based ftp clients.
|
||||
It can be used to browse through the folders, downloads and uploads files, and
|
||||
also for removing and moving folders and documents (called resources in webdav terminilogy).
|
||||
It's also capable of setting and getting properties of folders and documents.
|
||||
If webdav access isn't working, this client is probably the best for testing.
|
||||
|
||||
Just run
|
||||
|
||||
cadaver https://<your-domain>/<your-basedir>/webdav/index.php
|
||||
|
||||
It will ask for the user name and password. Once you are logged in just
|
||||
type `help` for a list of commands.
|
||||
|
||||
SeedDMS stores a lot more properties not covered by the webdav standard.
|
||||
Those have its own namespace called 'SeedDMS:'. Just type
|
||||
|
||||
propget <resource>
|
||||
|
||||
with `resource` being either the name of a folder or document. You will
|
||||
get a list of all properties stored for this resource. Setting a property
|
||||
requires to set the namespace first
|
||||
|
||||
set namespace SeedDMS:
|
||||
|
||||
Afterwards, you may set a property, e.g. the comment, with
|
||||
|
||||
propset <resource> comment 'Just a comment'
|
||||
|
||||
or even delete a property
|
||||
|
||||
propdel <resource> comment
|
||||
to not create the backup. Creating the backup file in a directory
|
||||
outside of WebDAV doesn't help in this case.
|
||||
|
||||
vi "+set nobackup" "+set nobackuwrite" -n test.txt
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
Running the scheduler
|
||||
======================
|
||||
|
||||
Since version 6 of SeedDMS a scheduler is implemented which runs
|
||||
scheduled tasks. Such tasks must be implemented in an extension
|
||||
and can be scheduled by the administrator within the user interface.
|
||||
|
||||
In order to check frequently for tasks ready to run, a system cron job
|
||||
must be installed. On Linux this can be done by adding the following line
|
||||
to the crontab
|
||||
|
||||
*/5 * * * * /var/www/seeddms60x/seeddms/utils/seeddms-schedulercli --mode=run
|
||||
|
||||
(Of course you need to change the path to `seeddms-schedulercli`)
|
||||
|
||||
This will install a cronjob running every 5 minutes. `seeddms-schedulercli` will check
|
||||
for tasks ready to run and execute them in that case. You can decrease the time between
|
||||
two calls of the cronjob, but keep in mind that seeddms tasks may take longer and
|
||||
are being started again before the previous task has been ended.
|
||||
|
||||
If the configuration file of SeedDMS is not found, its path can be passed
|
||||
on the command, though this should not be needed in a regular installation
|
||||
obeying the directory structure of the quickstart archive.
|
||||
|
||||
*/5 * * * * /var/www/seeddms60x/seeddms/utils/seeddms-schedulercli --config /var/www/seeddms60x/seeddms/conf/settings.xml --mode=run
|
||||
|
||||
For testing purposes it may be usefull to run `seeddms-schedulercli` in list mode.
|
||||
|
||||
seeddms-schedulercli --mode=list
|
||||
|
||||
This will just list all tasks and its scheduled exection time. Tasks ready to run,
|
||||
because its scheduled execution time is already in the past will be marked with
|
||||
a `*`. Tasks which are disabled will be marked with a `-`.
|
||||
|
||||
Executing `seeddms-schedulercli` in `dryrun` mode will behave just like in `run` mode
|
||||
but instead of running the task it will just issue a line.
|
||||
|
||||
Instead of running utils/seeddms-schedulercli you may as well access
|
||||
op/op.Cron.php which also runs all scheduled tasks. On Linux you do this
|
||||
by setting up a cronjob like
|
||||
|
||||
*/5 * * * * wget -q -O - "http://<your domain>/op/op.Cron.php"
|
|
@ -1,16 +0,0 @@
|
|||
Installation of external js packages
|
||||
-------------------------------------
|
||||
|
||||
All javascript was located in styles/bootstrap until SeedDMS 5.1.18 and 6.0.11.
|
||||
Since 5.1.19 and 6.0.12 most of it has moved into the view at views/boostrap/vendors
|
||||
and is no longer placed in git but must be installed by npm and grunt.
|
||||
|
||||
Run
|
||||
|
||||
`npm install`
|
||||
|
||||
and afterwards
|
||||
|
||||
`grunt`
|
||||
|
||||
to download the js packages and copy them into the new location.
|
|
@ -1,59 +0,0 @@
|
|||
OCR
|
||||
====
|
||||
|
||||
SeedDMS itself has no support for optical character recognition (OCR)
|
||||
because it does not care about the content of file. Though, external
|
||||
OCR software can be used to convert an image into text and index it
|
||||
by the full text search engine.
|
||||
|
||||
The following script can be use to convert a scanned image into pdf
|
||||
with a text layer added. The script actually takes this file to
|
||||
ran it through pdftotext. It was published in the seeddms forum
|
||||
https://sourceforge.net/p/seeddms/discussion/general/thread/4ec5973d/
|
||||
|
||||
|
||||
#!/bin/bash
|
||||
inputpdf=$1
|
||||
temp_folder=/tmp/seedinput/$(date +"%Y_%m_%d_%H%M%S")/
|
||||
lockfile=/tmp/seed
|
||||
protokolldatei=./tesser_syslog
|
||||
cores=2
|
||||
|
||||
mkdir -p $lockfile
|
||||
|
||||
while [ -e "$lockfile"/"`basename $0`" ];
|
||||
do
|
||||
sleep 5
|
||||
done
|
||||
|
||||
if ( set -o noclobber; echo "locked" > "$lockfile"/"`basename $0`"); then
|
||||
|
||||
trap 'rm -f "$lockfile"/"`basename $0`"; echo $(date) " Lockdatei wird geloescht: " $lockfile"/"`basename $0` Aufrufparameter: $* >> $protokolldatei ;rm -r $temp_folder; exit $?' INT TERM KILL EXIT
|
||||
#das Datum mit dem Scriptnamen in die Protokolldatei schreiben
|
||||
echo $(date) " Lockdatei erstellt: " $lockfile"/"`basename $0` >> $protokolldatei
|
||||
|
||||
else
|
||||
#Script beenden falls Lockdatei nicht erstellt werden konnte
|
||||
echo $(date) " Programm wird beendet, Lockdatei konnte nicht erstellt werden: $lockfile"/"`basename $0` Aufrufparameter: $* " >> $protokolldatei
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p $temp_folder
|
||||
|
||||
$(pdftotext -raw $1 - 1> $temp_folder''tmp.txt )
|
||||
pdf_contents=`cat $temp_folder''tmp.txt`
|
||||
pdf_contents=`echo "$pdf_contents" | tr -dc '[:print:]'`
|
||||
if [ -z "$pdf_contents" ]; then
|
||||
convert -density 300 -quality 95 $inputpdf +adjoin $temp_folder''image%03d.jpg
|
||||
find $temp_folder -name '*.jpg'| parallel --gnu -j $cores tesseract -l deu --psm 6 {} {} pdf
|
||||
|
||||
num=`find $temp_folder -name '*.pdf'| wc -l`
|
||||
if [ "$num" -gt "1" ]; then
|
||||
pdfunite $temp_folder*.pdf $temp_folder''tmp.pdf
|
||||
else
|
||||
mv $temp_folder*.pdf $temp_folder''tmp.pdf
|
||||
fi
|
||||
pdftotext $temp_folder''tmp.pdf $temp_folder''tmp.txt
|
||||
mv $temp_folder''tmp.pdf $1
|
||||
fi
|
||||
cat $temp_folder''tmp.txt
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user