mirror of
https://git.code.sf.net/p/seeddms/code
synced 2025-07-12 15:43:10 +00:00
Compare commits
No commits in common. "master" and "6.0.18" have entirely different histories.
|
@ -3,6 +3,6 @@ root = true
|
|||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
trim_trailing_whitespace = true
|
||||
trim_trailing_whitespaces = true
|
||||
indent_style = tab
|
||||
indent_size = 2
|
||||
|
|
|
@ -6,10 +6,9 @@ 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]
|
||||
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
|
||||
|
@ -31,9 +30,9 @@ RewriteRule "^styles/.*$" "-" [L]
|
|||
# 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]
|
||||
RewriteRule !^ext/[^/]+/.*(?:op|out|res) - [F]
|
||||
RewriteCond %{REQUEST_URI} "ext/[^/]+/res/.*$" [NC]
|
||||
RewriteRule !^ext/[^/]+/res/.*\.(?:css|js|png|gif|svg|ico|html|woff|ttf) - [F]
|
||||
RewriteRule !^ext/[^/]+/res/.*\.(?:css|js|png|svg) - [F]
|
||||
RewriteCond %{REQUEST_FILENAME} -f
|
||||
RewriteRule ^ext/.*$ - [L]
|
||||
|
||||
|
|
357
CHANGELOG
357
CHANGELOG
|
@ -1,107 +1,3 @@
|
|||
--------------------------------------------------------------------------------
|
||||
Changes in version 6.0.33
|
||||
--------------------------------------------------------------------------------
|
||||
- merge changes up to 5.1.40
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 6.0.32
|
||||
--------------------------------------------------------------------------------
|
||||
- merge changes up to 5.1.39
|
||||
- fix setting attributes (user, group, document, folder) when checking in
|
||||
a new document version
|
||||
- validate setting revision date
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 6.0.31
|
||||
--------------------------------------------------------------------------------
|
||||
- merge changes up to 5.1.38
|
||||
- fix various restapi endpoints which hadn't been updated to slim4
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 6.0.30
|
||||
--------------------------------------------------------------------------------
|
||||
- merge changes up to 5.1.37
|
||||
- receipt comment can be disabled
|
||||
- send request receipt notification only when document is released
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 6.0.29
|
||||
--------------------------------------------------------------------------------
|
||||
- merge changes up to 5.1.36
|
||||
- fix regression in FolderNotify
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 6.0.28
|
||||
--------------------------------------------------------------------------------
|
||||
- merge changes up to 5.1.35
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 6.0.27
|
||||
--------------------------------------------------------------------------------
|
||||
- merge changes up to 5.1.34
|
||||
- Document/folder check distinguishes between documents which cannot be
|
||||
receiped/revised because of access rights or the recipient/revisor being
|
||||
disabled.
|
||||
- fix creating user via rest api
|
||||
- checkout info does not depend on whether the logged in user was substituted
|
||||
- add new endpoints for managing roles by rest api
|
||||
- add transmittals in menu
|
||||
- add legacy access check for controllers
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 6.0.26
|
||||
--------------------------------------------------------------------------------
|
||||
- merge changes up to 5.1.33
|
||||
- add task to import files from drop folder
|
||||
- add substitution of users in bootstrap4 theme
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 6.0.25
|
||||
--------------------------------------------------------------------------------
|
||||
- merge changes up to 5.1.32
|
||||
- status log can be turned on with advanced access control
|
||||
- scheduler has more condensed layout
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 6.0.24
|
||||
--------------------------------------------------------------------------------
|
||||
- add task to send list of recent changes by email
|
||||
- merge changes up to 5.1.31
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 6.0.23
|
||||
--------------------------------------------------------------------------------
|
||||
- fix setting recipients and revisors
|
||||
- check in of a document is allowed for the user having done the check out
|
||||
or those users with unlimited access rights on the document
|
||||
- merge changes up to 5.1.30
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 6.0.22
|
||||
--------------------------------------------------------------------------------
|
||||
- merge changes up to 5.1.29
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 6.0.21
|
||||
--------------------------------------------------------------------------------
|
||||
- merge changes up to 5.1.28
|
||||
- add new check for documents with identical sequence numbers in a folder
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 6.0.20
|
||||
--------------------------------------------------------------------------------
|
||||
- merge changes up to 5.1.27
|
||||
- fix triggering workflow (Closes: #542)
|
||||
- create original file name from new document name when uploading document
|
||||
from the library folder. Used to be the original file name
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 6.0.19
|
||||
--------------------------------------------------------------------------------
|
||||
- merge changes up to 5.1.26
|
||||
- fix deletion of tasks when using bootstrap4 theme
|
||||
- fix deletion of documents when clicking on icon in document list (my documents)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 6.0.18
|
||||
--------------------------------------------------------------------------------
|
||||
|
@ -110,7 +6,7 @@
|
|||
- fix sending trigger workflow notification (Closes: #522)
|
||||
- fix updating und deleting items in document lists
|
||||
- call hook 'filenameDownloadItem' in search export and transmittal download
|
||||
- fix possible xss attack in UsrMgr (CVE-2022-28479)
|
||||
- fix possible xss attack in UsrMgr
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 6.0.17
|
||||
|
@ -321,252 +217,6 @@
|
|||
- add document list which can be exported as an archive
|
||||
- search results can be exported
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 5.1.40
|
||||
--------------------------------------------------------------------------------
|
||||
- fix saving user data when language selection is turned of (Closes: #568)
|
||||
- add much better support for new storage drivers
|
||||
- fix possible xss attacks
|
||||
- saver way to collect plugin configuration
|
||||
- fix update of postgres database
|
||||
- add hook displayPreviewThumb
|
||||
- add searching for mimetype in database
|
||||
- list of expired documents can be filtered by user
|
||||
- use quoted printable encoding instead of base64 for email subjects
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 5.1.39
|
||||
--------------------------------------------------------------------------------
|
||||
- show quota on chart page when listing total document size per user
|
||||
- turn off legend for chart sizepermonth
|
||||
- do not add group manager as mandatory approver/reviewer if logged in
|
||||
user is the manager itself
|
||||
- fixed setting group approvers from previous document version
|
||||
- very experimental support of memcached for accelerating some database
|
||||
operations (do not use in production)
|
||||
- prevent malicious manipulation of referer when setting language
|
||||
- fix setting attributes of type user, group, document, folder when updating
|
||||
a document
|
||||
- objects can be removed from clipboard
|
||||
- call hooks for document/folder list in attribute manager
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 5.1.38
|
||||
--------------------------------------------------------------------------------
|
||||
- require php 8.2
|
||||
- fix php error in out/out.ReviewSummary.php
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 5.1.37
|
||||
--------------------------------------------------------------------------------
|
||||
- do not show chart by category if there are no categories
|
||||
- documents in certain folders can be excluded from dashboard, could be useful
|
||||
for folders containing archived documents
|
||||
- migrate from Slim 3 to Slim 4 (check for extension updates)
|
||||
- fix reloading more entries in list of folders/documents at end of page if
|
||||
maxItemsPerPage is set
|
||||
- prevent xss attack
|
||||
- log level for rest api can be set separately
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 5.1.36
|
||||
--------------------------------------------------------------------------------
|
||||
- add new page for send test notification
|
||||
- remove deprecated function formatted_size()
|
||||
- fix bugs when importing files from filesystem with metadata, better logging
|
||||
- fix potential xss attack when showing log file
|
||||
- support for different storage of documents (not yet used)
|
||||
- do not treat repository url like a directory name (will no longer add a
|
||||
directory seperator)
|
||||
- use rename() on windows when moving an extension to its final destination
|
||||
- fixed bug in AddDocument, approver group wasn't checked properly against
|
||||
mandatory approvers
|
||||
- email From-address in settings can be forced for all outgoing mail
|
||||
- checking of ssl certificate for smtp can be turned off
|
||||
- add chart for disk space per month
|
||||
- clearing cache of js files works for a large number of files
|
||||
- WebDAV returns `quota-used-bytes` and `quota-available-bytes`
|
||||
- fix settings SeedDMS attributes in WebDAV server
|
||||
- propperly check for duplicate folder names in op/op.Ajax.php
|
||||
- add searching for file size (fulltext search)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 5.1.35
|
||||
--------------------------------------------------------------------------------
|
||||
- check access rights on EditDocumentFile and RemoveDocumentFile
|
||||
- allow to set expiration dates in the past again
|
||||
- fix authentication with ldap if AD is used
|
||||
- fix progress bar in list of users if quota is active
|
||||
- field storing email in ldap can be configured
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 5.1.34
|
||||
--------------------------------------------------------------------------------
|
||||
- introduce global reviewer/approver
|
||||
- group managers can be used as mandatory reviewers/approvers for all
|
||||
users of that group
|
||||
- update sabre/dav to 4.*
|
||||
- show parent folder of document in lists of documents (calendar, dashboard)
|
||||
- documents can be updated by dragging a file on a document list item
|
||||
- dragging a folder on a folder list item oder the drag and drop area will
|
||||
recursively upload the folder hierarchy including all files
|
||||
- fix checking if user is owner when sending notifications
|
||||
- do not show fast upload area if access on folder is insufficient
|
||||
- do not send notification mail 'submitted review/approval' to owner of
|
||||
document, still send it to uploader of version
|
||||
- set default language in login form if language selector is turned off
|
||||
- do not show full list of notifiers to none admins
|
||||
- do not list document/folders in sequence selector if its number exceeds 50
|
||||
- typeahead menu works with arrow keys again, wait 1 sec. before searching
|
||||
- fix sending notification mails when document/folder was moved
|
||||
- tasks and clipboard can be shown in main menu, even if there are no tasks
|
||||
due or the clipboard is empty
|
||||
- add conversion service from text/html to text/plain
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 5.1.33
|
||||
--------------------------------------------------------------------------------
|
||||
- use SeedDMS_Core_File::mimetype() to determine mime type when uploading a
|
||||
file with drag&drop
|
||||
- user images may be 300px height, do not scale them up
|
||||
- do not show unreadable documents on Dashboard
|
||||
- fix creating preview image of file in drop folder if it contains
|
||||
special chars
|
||||
- show fileѕ and folders in dropfolder dir recursively
|
||||
- fix 'Add to clipboard' menu item in bootstrap theme
|
||||
- open confirm box when changing category in batch operation
|
||||
- hidden users can excluded when setting list of reviewers/approvers
|
||||
- extension can add a legacy access right
|
||||
- check if document version may be removed
|
||||
- set max file size for indexing when updating a document
|
||||
- nicer output on info page
|
||||
- do not show filter for categories in database search if they don't exist
|
||||
- show logs of finished worflows
|
||||
- show preview of documents on clipboard
|
||||
- minor improvements in restapi
|
||||
- update layout of tab for attachments
|
||||
- remove session when calling logout of restapi
|
||||
- fix some potential security issues
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 5.1.32
|
||||
--------------------------------------------------------------------------------
|
||||
- check error msg after calling AddDocument and UpdateDocument controller
|
||||
in webdav module
|
||||
- more verbose log messages
|
||||
- show errors of none activated extensions and do not allow to activate it,
|
||||
if there are errors (e.g. missing php extensions)
|
||||
- move Approve/ReviewDocument in a controller
|
||||
- setting password by user can be disabled
|
||||
- groups from ldap can be synced with seeddms groups
|
||||
- fix error when sending notification to group of reviewers
|
||||
- seperate some notification messages for folders and documents
|
||||
- fix various drag&drop operations
|
||||
- do not sent notifidation mail to uploader if owner has received on already
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 5.1.31
|
||||
--------------------------------------------------------------------------------
|
||||
- rest api returns error msg and not just http status
|
||||
- comment of document, documentcontent and folder can be rendered as
|
||||
markdown
|
||||
- fix preview for file in drop folder
|
||||
- fix export of search result
|
||||
- use openssl instead of mcrypt
|
||||
- search form shows 'from' and 'to' field for integers and floats
|
||||
- show preview of document in EditAttributes page
|
||||
- major overhaul of fulltext search, add new search tab for a more
|
||||
facetted based search
|
||||
- add initial version of Dashboard
|
||||
- default public status of attachments can be configured
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 5.1.30
|
||||
--------------------------------------------------------------------------------
|
||||
- conversion from pdf to png replaces alpha channel with white
|
||||
- add list of conversion services in debug menu of admin tool
|
||||
- use chosen select for custom attributes
|
||||
- color category (use first 6 chars of md5(category name) as hex color)
|
||||
- create missing preview images in category or attribute manager
|
||||
- support README of extension in different languages
|
||||
- do not force password change if in substitute user mode
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 5.1.29
|
||||
--------------------------------------------------------------------------------
|
||||
- fix php errors in restapi
|
||||
- fix 'maximum size' error when uploading a file with drag&drop
|
||||
- update jquery to 3.6.1 (only bootstrap4 theme)
|
||||
- introduce authentication service
|
||||
- new hook in restapi to add middleware
|
||||
- previews for png, txt, pdf in different directories. This will
|
||||
enforce a recreation of all cached preview images, pdf and text files!
|
||||
- various improvements of fulltext service
|
||||
- show number of documents per category in category manager
|
||||
- show number of keywords per category in keyword manager
|
||||
- improve drag&drop with clipboard
|
||||
- old pear packages SeedDMS/Core, SeedDMS/Lucene, SeedDMS/Preview
|
||||
are now based on composer and has moved into vendor dir
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 5.1.28
|
||||
--------------------------------------------------------------------------------
|
||||
- user information in user manager failed to load when a document content
|
||||
with 0 bytes was created by the user
|
||||
- fix repair of wrong file extension
|
||||
- fix regression in password forgotten function
|
||||
- fix security issue when creating hash in password forgotten operation
|
||||
- add initial support for logging and notifications in rest api
|
||||
- add rest api calls to get attributes of a document version and to set
|
||||
attributes of folders, documents, and document versions
|
||||
- fixed various errors in swagger.yaml
|
||||
- use methods in inc/inc.ClassNotificationService.php for webdav
|
||||
- clear login failures when login by webdav succeeds
|
||||
- output log of restapi in LogManagement
|
||||
- new hook to add more tabs for sections in LogManagement
|
||||
- rest api returns version attributes as 'version_attributes' (was
|
||||
'version-attributes'), each attribute also contains the name
|
||||
- new hook in rest api to add more routes in extensions
|
||||
- uploaded several documents at once by fast upload will assign random
|
||||
sequence number to allow manually sorting the documents afterwards
|
||||
- fix counting of login failures if both ldap and db authentication is done
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 5.1.27
|
||||
--------------------------------------------------------------------------------
|
||||
- fix adding new attribute definition if object type is 'all'
|
||||
- EmptyFolder runs callbacks to remove objects from index and remove preview images
|
||||
- skip internal conversion service for images if imagick extension is missing
|
||||
- running the controller will always call the hooks preRun and postRun
|
||||
- add tabs on ViewFolder page
|
||||
- link behind logo in header can be set in extension
|
||||
- move attributes for documents and folders on search page into own accordion
|
||||
- search page uses conversion mgr for preview images
|
||||
- backport export of search result from seeddms 6.0.x
|
||||
- ldap authentication used 'uid' instead 'cn' in distinguished name if
|
||||
the initial bind failed and a second bind with the user's credentials
|
||||
is done
|
||||
- fix sorting in search result
|
||||
- import of users can handle hidden and disabled flag
|
||||
- image conversion falls back to gd library if imagick extension is not loaded
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 5.1.26
|
||||
--------------------------------------------------------------------------------
|
||||
- add hook additionalDocumentContentInfo
|
||||
- add restapi function 'statstotal'
|
||||
- custom attributes of type 'date' regard the date format
|
||||
- check extension dependency on shell commands
|
||||
- log reason for notification
|
||||
- add list of notification services
|
||||
- clicking on the file selection button no longer submits the form in firefox
|
||||
- fix clear clipboard link in menu
|
||||
- add conversion service from tiff, gif to png
|
||||
- do not use logger in notification service if it was not initialized
|
||||
- fix editing of custom date fields
|
||||
- fix listing files/folders with umlauts when using webdav
|
||||
- fix upload with fine-uploader
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 5.1.25
|
||||
--------------------------------------------------------------------------------
|
||||
|
@ -578,8 +228,8 @@
|
|||
- various improvements for workflows
|
||||
- output splash message when removing, editing, adding a category or keyword
|
||||
- extensions cannot be disabled/enabled if configuration file is not writeable
|
||||
- prevent cross site scripting in views/bootstrap/class.DefaultKeywords.php (CVE-2022-28051)
|
||||
- fix possible DoS in op/op.RemoveLog.php (CVE-2022-28478)
|
||||
- prevent cross site scripting in views/bootstrap/class.DefaultKeywords.php
|
||||
- fix possible DoS in op/op.RemoveLog.php
|
||||
- show only calendar events of logged in user
|
||||
- show expired documents in calendar
|
||||
- call new hook 'cleanUpDocument' after uploading or updating a document
|
||||
|
@ -798,7 +448,6 @@
|
|||
- pass configuration to init() of extension (backport from 6.0.x)
|
||||
- place comment of version below version data (remove extra column, backport from 6.0.x)
|
||||
- fix creating folders via restapi (Closes: #469)
|
||||
- custom attributes of type date show up in the calendar
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Changes in version 5.1.15
|
||||
|
|
15
Gruntfile.js
15
Gruntfile.js
|
@ -74,13 +74,6 @@ module.exports = function (grunt) {
|
|||
],
|
||||
dest: bootstrapDir + '/select2/js',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
nodeDir + '/select2/dist/js/i18n/*'
|
||||
],
|
||||
dest: bootstrapDir + '/select2/js/i18n',
|
||||
flatten: true
|
||||
},{
|
||||
expand: true,
|
||||
src: [
|
||||
|
@ -213,14 +206,6 @@ module.exports = function (grunt) {
|
|||
],
|
||||
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: [
|
||||
|
|
36
Makefile
36
Makefile
|
@ -24,7 +24,7 @@ dist:
|
|||
rm -rf tmp
|
||||
|
||||
quickstart:
|
||||
php7.4 vendor/bin/phing -Dversion=$(VERSION) package
|
||||
vendor/bin/phing -Dversion=$(VERSION) package
|
||||
|
||||
unittest:
|
||||
vendor/bin/phing -Dversion=$(VERSION) phpunitfast
|
||||
|
@ -62,37 +62,7 @@ repository:
|
|||
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 -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: doc webdav webapp repository
|
||||
|
|
108
SeedDMS_Core/Core.php
Normal file
108
SeedDMS_Core/Core.php
Normal file
|
@ -0,0 +1,108 @@
|
|||
<?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_Decorator
|
||||
*/
|
||||
require_once('Core/inc.ClassDecorator.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');
|
||||
|
||||
/**
|
||||
* @uses SeedDMS_Transmittal
|
||||
*/
|
||||
require_once('Core/inc.ClassTransmittal.php');
|
||||
|
||||
/**
|
||||
* @uses SeedDMS_File
|
||||
*/
|
||||
require_once('Core/inc.ClassIterator.php');
|
||||
?>
|
94
SeedDMS_Core/Core/inc.AccessUtils.php
Normal file
94
SeedDMS_Core/Core/inc.AccessUtils.php
Normal file
|
@ -0,0 +1,94 @@
|
|||
<?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);
|
||||
|
||||
/*
|
||||
* Lowest and highest access right
|
||||
*/
|
||||
define("M_LOWEST_RIGHT", 1);
|
||||
define("M_HIGHEST_RIGHT", 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);
|
122
SeedDMS_Core/Core/inc.ClassAccess.php
Normal file
122
SeedDMS_Core/Core/inc.ClassAccess.php
Normal file
|
@ -0,0 +1,122 @@
|
|||
<?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 SeedDMS_Core_User
|
||||
*/
|
||||
var $_user;
|
||||
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
var $_mode;
|
||||
|
||||
/**
|
||||
* SeedDMS_Core_UserAccess constructor.
|
||||
* @param $user
|
||||
* @param $mode
|
||||
*/
|
||||
function __construct($user, $mode) {
|
||||
$this->_user = $user;
|
||||
$this->_mode = $mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
function getUserID() { return $this->_user->getID(); }
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
function getMode() { return $this->_mode; }
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function isAdmin() {
|
||||
return ($this->_mode == SeedDMS_Core_User::role_admin);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SeedDMS_Core_User
|
||||
*/
|
||||
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 SeedDMS_Core_Group
|
||||
*/
|
||||
var $_group;
|
||||
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
var $_mode;
|
||||
|
||||
/**
|
||||
* SeedDMS_Core_GroupAccess constructor.
|
||||
* @param $group
|
||||
* @param $mode
|
||||
*/
|
||||
function __construct($group, $mode) {
|
||||
$this->_group = $group;
|
||||
$this->_mode = $mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
function getGroupID() { return $this->_group->getID(); }
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
function getMode() { return $this->_mode; }
|
||||
|
||||
/**
|
||||
* @return SeedDMS_Core_Group
|
||||
*/
|
||||
function getGroup() {
|
||||
return $this->_group;
|
||||
}
|
||||
} /* }}} */
|
1375
SeedDMS_Core/Core/inc.ClassAttribute.php
Normal file
1375
SeedDMS_Core/Core/inc.ClassAttribute.php
Normal file
File diff suppressed because it is too large
Load Diff
4263
SeedDMS_Core/Core/inc.ClassDMS.php
Normal file
4263
SeedDMS_Core/Core/inc.ClassDMS.php
Normal file
File diff suppressed because it is too large
Load Diff
42
SeedDMS_Core/Core/inc.ClassDecorator.php
Normal file
42
SeedDMS_Core/Core/inc.ClassDecorator.php
Normal file
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of the decorator pattern
|
||||
*
|
||||
* @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 which implements a simple decorator pattern
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS_Core
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010, Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Core_Decorator {
|
||||
protected $o;
|
||||
|
||||
public function __construct($object) {
|
||||
$this->o = $object;
|
||||
}
|
||||
|
||||
public function __call($method, $args)
|
||||
{
|
||||
if (!method_exists($this->o, $method)) {
|
||||
throw new Exception("Undefined method $method attempt.");
|
||||
}
|
||||
/* In case the called method returns the object itself, then return this object */
|
||||
$result = call_user_func_array(array($this->o, $method), $args);
|
||||
return $result === $this->o ? $this : $result;
|
||||
}
|
||||
}
|
||||
|
7730
SeedDMS_Core/Core/inc.ClassDocument.php
Normal file
7730
SeedDMS_Core/Core/inc.ClassDocument.php
Normal file
File diff suppressed because it is too large
Load Diff
124
SeedDMS_Core/Core/inc.ClassDocumentCategory.php
Normal file
124
SeedDMS_Core/Core/inc.ClassDocumentCategory.php
Normal file
|
@ -0,0 +1,124 @@
|
|||
<?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) { /* {{{ */
|
||||
$newName = trim($newName);
|
||||
if(!$newName)
|
||||
return false;
|
||||
|
||||
$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 remove() { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "DELETE FROM `tblCategory` WHERE `id` = " . $this->_id;
|
||||
if (!$db->getResult($queryStr))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
function getDocumentsByCategory($limit=0, $offset=0) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "SELECT * FROM `tblDocumentCategory` where `categoryID`=".$this->_id;
|
||||
if($limit && is_numeric($limit))
|
||||
$queryStr .= " LIMIT ".(int) $limit;
|
||||
if($offset && is_numeric($offset))
|
||||
$queryStr .= " OFFSET ".(int) $offset;
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if (is_bool($resArr) && !$resArr)
|
||||
return false;
|
||||
|
||||
$documents = array();
|
||||
foreach ($resArr as $row) {
|
||||
if($doc = $this->_dms->getDocument($row["documentID"]))
|
||||
array_push($documents, $doc);
|
||||
}
|
||||
return $documents;
|
||||
} /* }}} */
|
||||
|
||||
function countDocumentsByCategory() { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "SELECT COUNT(*) as `c` FROM `tblDocumentCategory` where `categoryID`=".$this->_id;
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if (is_bool($resArr) && !$resArr)
|
||||
return false;
|
||||
|
||||
return $resArr[0]['c'];
|
||||
} /* }}} */
|
||||
|
||||
}
|
||||
|
||||
?>
|
2081
SeedDMS_Core/Core/inc.ClassFolder.php
Normal file
2081
SeedDMS_Core/Core/inc.ClassFolder.php
Normal file
File diff suppressed because it is too large
Load Diff
630
SeedDMS_Core/Core/inc.ClassGroup.php
Normal file
630
SeedDMS_Core/Core/inc.ClassGroup.php
Normal file
|
@ -0,0 +1,630 @@
|
|||
<?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;
|
||||
|
||||
/**
|
||||
* @var SeedDMS_Core_User[]
|
||||
*/
|
||||
protected $_users;
|
||||
|
||||
/**
|
||||
* The comment of the user group
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_comment;
|
||||
|
||||
/**
|
||||
* Back reference to DMS this user group belongs to
|
||||
*
|
||||
* @var SeedDMS_Core_DMS
|
||||
*/
|
||||
protected $_dms;
|
||||
|
||||
function __construct($id, $name, $comment) { /* {{{ */
|
||||
$this->_id = $id;
|
||||
$this->_name = $name;
|
||||
$this->_comment = $comment;
|
||||
$this->_dms = null;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Return an instance of a group object
|
||||
*
|
||||
* @param string|integer $id Id, name of group, depending
|
||||
* on the 3rd parameter.
|
||||
* @param SeedDMS_Core_DMS $dms instance of dms
|
||||
* @param string $by search by group name if set to 'name'.
|
||||
* Search by Id of group if left empty.
|
||||
* @return SeedDMS_Core_Group|bool instance of class SeedDMS_Core_Group if group was
|
||||
* found, null if group was not found, false in case of error
|
||||
*/
|
||||
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 null;
|
||||
|
||||
$resArr = $resArr[0];
|
||||
|
||||
$group = new self($resArr["id"], $resArr["name"], $resArr["comment"]);
|
||||
$group->setDMS($dms);
|
||||
return $group;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* @param $orderby
|
||||
* @param SeedDMS_Core_DMS $dms
|
||||
* @return array|bool
|
||||
*/
|
||||
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;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Check if this object is of type 'group'.
|
||||
*
|
||||
* @param string $type type of object
|
||||
*/
|
||||
public function isType($type) { /* {{{ */
|
||||
return $type == 'group';
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* @param SeedDMS_Core_DMS $dms
|
||||
*/
|
||||
function setDMS($dms) { /* {{{ */
|
||||
$this->_dms = $dms;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* @return SeedDMS_Core_DMS $dms
|
||||
*/
|
||||
function getDMS() {
|
||||
return $this->_dms;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
function getID() { return $this->_id; }
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
function getName() { return $this->_name; }
|
||||
|
||||
/**
|
||||
* @param $newName
|
||||
* @return bool
|
||||
*/
|
||||
function setName($newName) { /* {{{ */
|
||||
$newName = trim($newName);
|
||||
if(!$newName)
|
||||
return false;
|
||||
|
||||
$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;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
function getComment() { return $this->_comment; }
|
||||
|
||||
/**
|
||||
* @param $newComment
|
||||
* @return bool
|
||||
*/
|
||||
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;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* @return SeedDMS_Core_User[]|bool
|
||||
*/
|
||||
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();
|
||||
|
||||
$classnamerole = $this->_dms->getClassname('role');
|
||||
$classname = $this->_dms->getClassname('user');
|
||||
foreach ($resArr as $row) {
|
||||
/** @var SeedDMS_Core_User $user */
|
||||
$role = $classnamerole::getInstance($row['role'], $this->_dms);
|
||||
$user = new $classname($row["id"], $row["login"], $row["pwd"], $row["fullName"], $row["email"], $row["language"], $row["theme"], $row["comment"], $role, $row['hidden']);
|
||||
$user->setDMS($this->_dms);
|
||||
array_push($this->_users, $user);
|
||||
}
|
||||
}
|
||||
return $this->_users;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* @return SeedDMS_Core_User[]|bool
|
||||
*/
|
||||
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();
|
||||
|
||||
$classnamerole = $this->_dms->getClassname('role');
|
||||
$classname = $this->_dms->getClassname('user');
|
||||
foreach ($resArr as $row) {
|
||||
/** @var SeedDMS_Core_User $user */
|
||||
$role = $classnamerole::getInstance($row['role'], $this->_dms);
|
||||
$user = new $classname($row["id"], $row["login"], $row["pwd"], $row["fullName"], $row["email"], $row["language"], $row["theme"], $row["comment"], $role, $row['hidden']);
|
||||
$user->setDMS($this->_dms);
|
||||
array_push($managers, $user);
|
||||
}
|
||||
return $managers;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* @param SeedDMS_Core_User $user
|
||||
* @param bool $asManager
|
||||
* @return bool
|
||||
*/
|
||||
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;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* @param SeedDMS_Core_User $user
|
||||
* @return bool
|
||||
*/
|
||||
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;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Check if user is member of group
|
||||
*
|
||||
* @param SeedDMS_Core_User $user user to be checked
|
||||
* @param boolean $asManager also check whether user is manager of group if
|
||||
* set to true, otherwise does not care about manager status
|
||||
* @return boolean true if user is member, otherwise false
|
||||
*/
|
||||
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();
|
||||
$queryStr = "SELECT * FROM `tblGroupMembers` WHERE `groupID` = " . $this->_id . " AND `userID` = " . $user->getID();
|
||||
if ($asManager)
|
||||
$queryStr .= " AND `manager` = 1";
|
||||
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
|
||||
if (is_bool($resArr) && $resArr == false) return false;
|
||||
if (count($resArr) != 1) return false;
|
||||
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Toggle manager status of user
|
||||
*
|
||||
* @param SeedDMS_Core_User $user
|
||||
* @return boolean true if operation was successful, otherwise false
|
||||
*/
|
||||
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 SeedDMS_Core_User $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;
|
||||
}
|
||||
}
|
||||
|
||||
$receiptStatus = $this->getReceiptStatus();
|
||||
foreach ($receiptStatus as $r) {
|
||||
$queryStr = "INSERT INTO `tblDocumentReceiptLog` (`receiptID`, `status`, `comment`, `date`, `userID`) ".
|
||||
"VALUES ('". $r["receiptID"] ."', '-2', 'Recipients group removed from process', ".$db->getCurrentDatetime().", '". $user->getID() ."')";
|
||||
$res=$db->getResult($queryStr);
|
||||
if(!$res) {
|
||||
$db->rollbackTransaction();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$revisionStatus = $this->getRevisionStatus();
|
||||
foreach ($revisionStatus as $r) {
|
||||
$queryStr = "INSERT INTO `tblDocumentRevisionLog` (`revisionID`, `status`, `comment`, `date`, `userID`) ".
|
||||
"VALUES ('". $r["revisionID"] ."', '-2', 'Revisors 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 ."' ".
|
||||
"ORDER BY `tblDocumentReviewLog`.`reviewLogID` DESC";
|
||||
$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;
|
||||
} /* }}} */
|
||||
|
||||
function getReceiptStatus($documentID=null, $version=null) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$status = array();
|
||||
|
||||
// See if the group is assigned as a recipient.
|
||||
$queryStr = "SELECT `tblDocumentRecipients`.*, `tblDocumentReceiptLog`.`status`, ".
|
||||
"`tblDocumentReceiptLog`.`comment`, `tblDocumentReceiptLog`.`date`, ".
|
||||
"`tblDocumentReceiptLog`.`userID` ".
|
||||
"FROM `tblDocumentRecipients` ".
|
||||
"LEFT JOIN `tblDocumentReceiptLog` USING (`receiptID`) ".
|
||||
"WHERE `tblDocumentRecipients`.`type`='1' ".
|
||||
($documentID==null ? "" : "AND `tblDocumentRecipients`.`documentID` = '". (int) $documentID ."' ").
|
||||
($version==null ? "" : "AND `tblDocumentRecipients`.`version` = '". (int) $version ."' ").
|
||||
"AND `tblDocumentRecipients`.`required`='". $this->_id ."' ";
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if (is_bool($resArr) && $resArr == false)
|
||||
return false;
|
||||
if (count($resArr)>0) {
|
||||
foreach ($resArr as $res) {
|
||||
if(isset($status["status"][$res['documentID']])) {
|
||||
if($status["status"][$res['documentID']]['date'] < $res['date']) {
|
||||
$status["status"][$res['documentID']] = $res;
|
||||
}
|
||||
} else {
|
||||
$status["status"][$res['documentID']] = $res;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $status;
|
||||
} /* }}} */
|
||||
|
||||
function getRevisionStatus($documentID=null, $version=null) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$status = array();
|
||||
|
||||
if (!$db->createTemporaryTable("ttcontentid")) {
|
||||
return false;
|
||||
}
|
||||
// See if the group is assigned as a revisor.
|
||||
$queryStr = "SELECT `tblDocumentRevisors`.*, `tblDocumentRevisionLog`.`status`, ".
|
||||
"`tblDocumentRevisionLog`.`comment`, `tblDocumentRevisionLog`.`date`, ".
|
||||
"`tblDocumentRevisionLog`.`userID` ".
|
||||
"FROM `tblDocumentRevisors` ".
|
||||
"LEFT JOIN `tblDocumentRevisionLog` USING (`revisionID`) ".
|
||||
"LEFT JOIN `ttcontentid` ON `ttcontentid`.`maxVersion` = `tblDocumentRevisors`.`version` AND `ttcontentid`.`document` = `tblDocumentRevisors`.`documentID` ".
|
||||
"WHERE `tblDocumentRevisors`.`type`='1' ".
|
||||
($documentID==null ? "" : "AND `tblDocumentRevisors`.`documentID` = '". (int) $documentID ."' ").
|
||||
($version==null ? "" : "AND `tblDocumentRevisors`.`version` = '". (int) $version ."' ").
|
||||
($documentID==null && $version==null ? "AND `ttcontentid`.`maxVersion` = `tblDocumentRevisors`.`version` " : "").
|
||||
"AND `tblDocumentRevisors`.`required`='". $this->_id ."' ".
|
||||
"ORDER BY `tblDocumentRevisionLog`.`revisionLogID` DESC";
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if ($resArr === false)
|
||||
return false;
|
||||
if (count($resArr)>0) {
|
||||
$status['status'] = array();
|
||||
foreach ($resArr as $res) {
|
||||
if($res['date']) {
|
||||
if(isset($status["status"][$res['documentID']])) {
|
||||
if($status["status"][$res['documentID']]['date'] < $res['date']) {
|
||||
$status["status"][$res['documentID']] = $res;
|
||||
}
|
||||
} else {
|
||||
$status["status"][$res['documentID']] = $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 bool|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 SeedDMS_Core_Notification[]|bool 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->_dms);
|
||||
array_push($notifications, $not);
|
||||
}
|
||||
|
||||
return $notifications;
|
||||
} /* }}} */
|
||||
|
||||
} /* }}} */
|
231
SeedDMS_Core/Core/inc.ClassIterator.php
Normal file
231
SeedDMS_Core/Core/inc.ClassIterator.php
Normal file
|
@ -0,0 +1,231 @@
|
|||
<?php
|
||||
namespace SeedDMS;
|
||||
|
||||
/**
|
||||
* Implementation of the document iterartor
|
||||
*
|
||||
* @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 DocumentIterator implements \Iterator {
|
||||
/**
|
||||
* @var object folder
|
||||
*/
|
||||
protected $_folder;
|
||||
|
||||
/**
|
||||
* @var object dms
|
||||
*/
|
||||
protected $_dms;
|
||||
|
||||
/**
|
||||
* @var array documents
|
||||
*/
|
||||
protected $_documents;
|
||||
|
||||
public function __construct($folder) {
|
||||
$this->_folder = $folder;
|
||||
$this->_dms = $folder->getDMS();
|
||||
$this->_documents = array();
|
||||
$this->_pointer = 0;
|
||||
$this->_cache = array();
|
||||
$this->populate();
|
||||
}
|
||||
|
||||
public function rewind() {
|
||||
$this->_pointer = 0;
|
||||
}
|
||||
|
||||
public function valid() {
|
||||
return isset($this->_documents[$this->_pointer]);
|
||||
}
|
||||
|
||||
public function next() {
|
||||
$this->_pointer++;
|
||||
}
|
||||
|
||||
public function key() {
|
||||
return $this->_folders[$this->_pointer];
|
||||
}
|
||||
|
||||
public function current() {
|
||||
if($this->_documents[$this->_pointer]) {
|
||||
$documentid = $this->_documents[$this->_pointer]['id'];
|
||||
if(!isset($this->_cache[$documentid])) {
|
||||
// echo $documentid." not cached<br />";
|
||||
$this->_cache[$documentid] = $this->_dms->getdocument($documentid);
|
||||
}
|
||||
return $this->_cache[$documentid];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private function populate($orderby="", $dir="asc", $limit=0, $offset=0) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "SELECT `id` FROM `tblDocuments` WHERE `folder` = " . $this->_folder->getID();
|
||||
|
||||
if ($orderby && $orderby[0]=="n") $queryStr .= " ORDER BY `name`";
|
||||
elseif ($orderby && $orderby[0]=="s") $queryStr .= " ORDER BY `sequence`";
|
||||
elseif ($orderby && $orderby[0]=="d") $queryStr .= " ORDER BY `date`";
|
||||
if($dir == 'desc')
|
||||
$queryStr .= " DESC";
|
||||
if(is_int($limit) && $limit > 0) {
|
||||
$queryStr .= " LIMIT ".$limit;
|
||||
if(is_int($offset) && $offset > 0)
|
||||
$queryStr .= " OFFSET ".$offset;
|
||||
}
|
||||
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if (is_bool($resArr) && $resArr == false)
|
||||
return false;
|
||||
|
||||
$this->_documents = $resArr;
|
||||
} /* }}} */
|
||||
}
|
||||
|
||||
class FolderIterator implements \Iterator { /* {{{ */
|
||||
/**
|
||||
* @var object folder
|
||||
*/
|
||||
protected $_folder;
|
||||
|
||||
/**
|
||||
* @var object dms
|
||||
*/
|
||||
protected $_dms;
|
||||
|
||||
/**
|
||||
* @var array documents
|
||||
*/
|
||||
protected $_folders;
|
||||
|
||||
public function __construct($folder) { /* {{{ */
|
||||
$this->_folder = $folder;
|
||||
$this->_dms = $folder->getDMS();
|
||||
$this->_folders = array();
|
||||
$this->_pointer = 0;
|
||||
$this->_cache = array();
|
||||
$this->populate();
|
||||
} /* }}} */
|
||||
|
||||
public function rewind() { /* {{{ */
|
||||
$this->_pointer = 0;
|
||||
} /* }}} */
|
||||
|
||||
public function valid() { /* {{{ */
|
||||
return isset($this->_folders[$this->_pointer]);
|
||||
} /* }}} */
|
||||
|
||||
public function next() { /* {{{ */
|
||||
$this->_pointer++;
|
||||
} /* }}} */
|
||||
|
||||
public function key() { /* {{{ */
|
||||
return $this->_folders[$this->_pointer];
|
||||
} /* }}} */
|
||||
|
||||
public function current() { /* {{{ */
|
||||
if($this->_folders[$this->_pointer]) {
|
||||
$folderid = $this->_folders[$this->_pointer]['id'];
|
||||
if(!isset($this->_cache[$folderid])) {
|
||||
// echo $folderid." not cached<br />";
|
||||
$this->_cache[$folderid] = $this->_dms->getFolder($folderid);
|
||||
}
|
||||
return $this->_cache[$folderid];
|
||||
}
|
||||
return null;
|
||||
} /* }}} */
|
||||
|
||||
private function populate($orderby="", $dir="asc", $limit=0, $offset=0) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "SELECT `id` FROM `tblFolders` WHERE `parent` = " . $this->_folder->getID();
|
||||
|
||||
if ($orderby && $orderby[0]=="n") $queryStr .= " ORDER BY `name`";
|
||||
elseif ($orderby && $orderby[0]=="s") $queryStr .= " ORDER BY `sequence`";
|
||||
elseif ($orderby && $orderby[0]=="d") $queryStr .= " ORDER BY `date`";
|
||||
if($dir == 'desc')
|
||||
$queryStr .= " DESC";
|
||||
if(is_int($limit) && $limit > 0) {
|
||||
$queryStr .= " LIMIT ".$limit;
|
||||
if(is_int($offset) && $offset > 0)
|
||||
$queryStr .= " OFFSET ".$offset;
|
||||
}
|
||||
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if (is_bool($resArr) && $resArr == false)
|
||||
return false;
|
||||
|
||||
$this->_folders = $resArr;
|
||||
} /* }}} */
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* The FolderFilterIterator checks if the given user has access on
|
||||
* the current folder.
|
||||
* FilterIterator uses an inner iterator passed to the constructor
|
||||
* to iterate over the sub folders of a folder.
|
||||
*
|
||||
$iter = new FolderIterator($folder);
|
||||
$iter2 = new FolderFilterIterator($iter, $user);
|
||||
foreach($iter2 as $ff) {
|
||||
echo $ff->getName()."<br />";
|
||||
}
|
||||
*/
|
||||
class FolderFilterIterator extends \FilterIterator { /* {{{ */
|
||||
public function __construct(Iterator $iterator , $filter ) {
|
||||
parent::__construct($iterator);
|
||||
$this->userFilter = $filter;
|
||||
}
|
||||
public function accept() { /* {{{ */
|
||||
$folder = $this->getInnerIterator()->current();
|
||||
echo "accept() for ".$folder->getName()."<br />";
|
||||
return true;
|
||||
} /* }}} */
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
$iter = new RecursiveFolderIterator($folder);
|
||||
$iter2 = new RecursiveIteratorIterator($iter, RecursiveIteratorIterator::SELF_FIRST);
|
||||
foreach($iter2 as $ff) {
|
||||
echo $ff->getID().': '.$ff->getName()."<br />";
|
||||
}
|
||||
*/
|
||||
class RecursiveFolderIterator extends FolderIterator implements \RecursiveIterator { /* {{{ */
|
||||
|
||||
public function hasChildren() { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
$queryStr = "SELECT id FROM `tblFolders` WHERE `parent` = ".(int) $this->current()->getID();
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if (is_bool($resArr) && !$resArr)
|
||||
return false;
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
public function getChildren() { /* {{{ */
|
||||
return new RecursiveFolderIterator($this->current());
|
||||
} /* }}} */
|
||||
} /* }}} */
|
||||
|
||||
class RecursiveFolderFilterIterator extends FolderFilterIterator { /* {{{ */
|
||||
public function hasChildren() { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
$queryStr = "SELECT id FROM `tblFolders` WHERE `parent` = ".(int) $this->current()->getID();
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if (is_bool($resArr) && !$resArr)
|
||||
return false;
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
public function getChildren() { /* {{{ */
|
||||
return new RecursiveFolderIterator($this->current());
|
||||
} /* }}} */
|
||||
|
||||
} /* }}} */
|
193
SeedDMS_Core/Core/inc.ClassKeywords.php
Normal file
193
SeedDMS_Core/Core/inc.ClassKeywords.php
Normal file
|
@ -0,0 +1,193 @@
|
|||
<?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 SeedDMS_Core_DMS $_dms reference to dms this category belongs to
|
||||
* @access protected
|
||||
*/
|
||||
protected $_dms;
|
||||
|
||||
/**
|
||||
* SeedDMS_Core_KeywordCategory constructor.
|
||||
* @param $id
|
||||
* @param $ownerID
|
||||
* @param $name
|
||||
*/
|
||||
function __construct($id, $ownerID, $name) {
|
||||
$this->_id = $id;
|
||||
$this->_name = $name;
|
||||
$this->_ownerID = $ownerID;
|
||||
$this->_dms = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SeedDMS_Core_DMS $dms
|
||||
*/
|
||||
function setDMS($dms) {
|
||||
$this->_dms = $dms;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
function getID() { return $this->_id; }
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
function getName() { return $this->_name; }
|
||||
|
||||
/**
|
||||
* @return bool|SeedDMS_Core_User
|
||||
*/
|
||||
function getOwner() {
|
||||
if (!isset($this->_owner))
|
||||
$this->_owner = $this->_dms->getUser($this->_ownerID);
|
||||
return $this->_owner;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $newName
|
||||
* @return bool
|
||||
*/
|
||||
function setName($newName) {
|
||||
$newName = trim($newName);
|
||||
if(!$newName)
|
||||
return false;
|
||||
|
||||
$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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SeedDMS_Core_User $user
|
||||
* @return bool
|
||||
*/
|
||||
function setOwner($user) {
|
||||
if(!$user || !$user->isType('user'))
|
||||
return false;
|
||||
|
||||
$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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
function getKeywordLists() {
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "SELECT * FROM `tblKeywords` WHERE `category` = " . $this->_id . " order by `keywords`";
|
||||
return $db->getResultArray($queryStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $listID
|
||||
* @param $keywords
|
||||
* @return bool
|
||||
*/
|
||||
function editKeywordList($listID, $keywords) {
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "UPDATE `tblKeywords` SET `keywords` = ".$db->qstr($keywords)." WHERE `id` = $listID";
|
||||
return $db->getResult($queryStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $keywords
|
||||
* @return bool
|
||||
*/
|
||||
function addKeywordList($keywords) {
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "INSERT INTO `tblKeywords` (`category`, `keywords`) VALUES (" . $this->_id . ", ".$db->qstr($keywords).")";
|
||||
return $db->getResult($queryStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $listID
|
||||
* @return bool
|
||||
*/
|
||||
function removeKeywordList($listID) {
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "DELETE FROM `tblKeywords` WHERE `id` = $listID";
|
||||
return $db->getResult($queryStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
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); }
|
||||
} /* }}} */
|
||||
?>
|
331
SeedDMS_Core/Core/inc.ClassObject.php
Normal file
331
SeedDMS_Core/Core/inc.ClassObject.php
Normal file
|
@ -0,0 +1,331 @@
|
|||
<?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 SeedDMS_Core_DMS back reference to document management system
|
||||
*/
|
||||
public $_dms;
|
||||
|
||||
/**
|
||||
* SeedDMS_Core_Object constructor.
|
||||
* @param $id
|
||||
*/
|
||||
function __construct($id) { /* {{{ */
|
||||
$this->_id = $id;
|
||||
$this->_dms = null;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Check if this object is of a given type.
|
||||
*
|
||||
* This method must be implemened in the child class
|
||||
*
|
||||
* @param string $type type of object
|
||||
*/
|
||||
public function isType($type) {return false;}
|
||||
|
||||
/**
|
||||
* 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 SeedDMS_Core_DMS $dms reference to dms
|
||||
*/
|
||||
public function setDMS($dms) { /* {{{ */
|
||||
$this->_dms = $dms;
|
||||
} /* }}} */
|
||||
|
||||
public function getDMS() { /* {{{ */
|
||||
return $this->_dms;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Return the internal id of the document
|
||||
*
|
||||
* @return integer id of document
|
||||
*/
|
||||
public function getID() { return $this->_id; }
|
||||
|
||||
/**
|
||||
* Returns all attributes set for the object
|
||||
*
|
||||
* @return array|bool
|
||||
*/
|
||||
public function getAttributes() { /* {{{ */
|
||||
if (!$this->_attributes) {
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
switch(get_class($this)) {
|
||||
case $this->_dms->getClassname('document'):
|
||||
$queryStr = "SELECT a.* FROM `tblDocumentAttributes` a LEFT JOIN `tblAttributeDefinitions` b ON a.`attrdef`=b.`id` WHERE a.`document` = " . $this->_id." ORDER BY b.`name`";
|
||||
break;
|
||||
case $this->_dms->getClassname('documentcontent'):
|
||||
$queryStr = "SELECT a.* FROM `tblDocumentContentAttributes` a LEFT JOIN `tblAttributeDefinitions` b ON a.`attrdef`=b.`id` WHERE a.`content` = " . $this->_id." ORDER BY b.`name`";
|
||||
break;
|
||||
case $this->_dms->getClassname('folder'):
|
||||
$queryStr = "SELECT a.* FROM `tblFolderAttributes` a LEFT JOIN `tblAttributeDefinitions` b ON a.`attrdef`=b.`id` WHERE a.`folder` = " . $this->_id." ORDER BY b.`name`";
|
||||
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
|
||||
*
|
||||
* @param SeedDMS_Core_AttributeDefinition $attrdef
|
||||
* @return array|string value of attritbute or false. The value is an array
|
||||
* if the attribute is defined as multi value
|
||||
*/
|
||||
public 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
|
||||
*
|
||||
* @param SeedDMS_Core_AttributeDefinition $attrdef
|
||||
* @return array|string value of attritbute or false. The value is an array
|
||||
* if the attribute is defined as multi value
|
||||
*/
|
||||
public 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);
|
||||
$vsep = $attrdef->getValueSetSeparator();
|
||||
/* If the value doesn't start with the separator used in the value set,
|
||||
* then assume that the value was not saved with a leading separator.
|
||||
* This can happen, if the value was previously a single value from
|
||||
* the value set and later turned into a multi value attribute.
|
||||
*/
|
||||
if($sep == $vsep)
|
||||
return(explode($sep, substr($value, 1)));
|
||||
else
|
||||
return(array($value));
|
||||
} 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.
|
||||
*
|
||||
* @param SeedDMS_Core_AttributeDefinition $attrdef
|
||||
* @return array|bool
|
||||
* even if the attribute is not defined as multi value
|
||||
*/
|
||||
public 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.
|
||||
*
|
||||
* @param SeedDMS_Core_AttributeDefinition $attrdef
|
||||
* @return string value of attritbute or false. The value is always a string
|
||||
* even if the attribute is defined as multi value
|
||||
*/
|
||||
public 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 SeedDMS_Core_AttributeDefinition $attrdef definition of attribute
|
||||
* @param array|string $value value of attribute, for multiple values this
|
||||
* must be an array
|
||||
* @return boolean true if operation was successful, otherwise false
|
||||
*/
|
||||
public 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)) {
|
||||
if(in_array($attrdef->getType(), array(SeedDMS_Core_AttributeDefinition::type_user, SeedDMS_Core_AttributeDefinition::type_group)))
|
||||
$sep = ',';
|
||||
else
|
||||
$sep = substr($attrdef->getValueSet(), 0, 1);
|
||||
$value = $sep.implode($sep, $value);
|
||||
}
|
||||
/* Handle the case if an attribute is not set already */
|
||||
if(!isset($this->_attributes[$attrdef->getId()])) {
|
||||
switch(get_class($this)) {
|
||||
case $this->_dms->getClassname('document'):
|
||||
$tablename = 'tblDocumentAttributes';
|
||||
$queryStr = "INSERT INTO `tblDocumentAttributes` (`document`, `attrdef`, `value`) VALUES (".$this->_id.", ".$attrdef->getId().", ".$db->qstr($value).")";
|
||||
break;
|
||||
case $this->_dms->getClassname('documentcontent'):
|
||||
$tablename = 'tblDocumentContentAttributes';
|
||||
$queryStr = "INSERT INTO `tblDocumentContentAttributes` (`content`, `attrdef`, `value`) VALUES (".$this->_id.", ".$attrdef->getId().", ".$db->qstr($value).")";
|
||||
break;
|
||||
case $this->_dms->getClassname('folder'):
|
||||
$tablename = 'tblFolderAttributes';
|
||||
$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($tablename), $this, $attrdef, $value);
|
||||
$attr->setDMS($this->_dms);
|
||||
$this->_attributes[$attrdef->getId()] = $attr;
|
||||
|
||||
/* Check if 'onPostAddAttribute' callback is set */
|
||||
if(isset($this->_dms->callbacks['onPostAddAttribute'])) {
|
||||
foreach($this->_dms->callbacks['onPostAddAttribute'] as $callback) {
|
||||
if(!call_user_func($callback[0], $callback[1], $this, $attrdef, $value)) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* The attribute already exists. setValue() will either update or delete it. */
|
||||
$this->_attributes[$attrdef->getId()]->setValue($value);
|
||||
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Remove an attribute of the object for the given attribute definition
|
||||
* @param SeedDMS_Core_AttributeDefinition $attrdef
|
||||
* @return boolean true if operation was successful, otherwise false
|
||||
*/
|
||||
public function removeAttribute($attrdef) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
if (!$this->_attributes) {
|
||||
$this->getAttributes();
|
||||
}
|
||||
if(isset($this->_attributes[$attrdef->getId()])) {
|
||||
$oldvalue = $this->_attributes[$attrdef->getId()]->getValue();
|
||||
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;
|
||||
|
||||
/* Check if 'onPostRemoveAttribute' callback is set */
|
||||
if(isset($this->_dms->callbacks['onPostRemoveAttribute'])) {
|
||||
foreach($this->_dms->callbacks['onPostRemoveAttribute'] as $callback) {
|
||||
if(!call_user_func($callback[0], $callback[1], $this, $attrdef, $oldvalue)) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unset($this->_attributes[$attrdef->getId()]);
|
||||
}
|
||||
return true;
|
||||
} /* }}} */
|
||||
} /* }}} */
|
398
SeedDMS_Core/Core/inc.ClassTransmittal.php
Normal file
398
SeedDMS_Core/Core/inc.ClassTransmittal.php
Normal file
|
@ -0,0 +1,398 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of the transmittal 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 transmittal 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_Transmittal {
|
||||
/**
|
||||
* @var integer id of transmittal
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
var $_id;
|
||||
|
||||
/**
|
||||
* @var string name of transmittal
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
var $_name;
|
||||
|
||||
/**
|
||||
* @var string comment of transmittal
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
var $_comment;
|
||||
|
||||
/**
|
||||
* @var boolean true if transmittal is public
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
var $_isPublic;
|
||||
|
||||
/**
|
||||
* @var object user this transmittal belongs to
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
var $_user;
|
||||
|
||||
/**
|
||||
* @var object date of creation
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
var $_date;
|
||||
|
||||
/**
|
||||
* @var object items
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
var $_items;
|
||||
|
||||
/**
|
||||
* @var object reference to the dms instance this user belongs to
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
var $_dms;
|
||||
|
||||
function __construct($id, $user, $name, $comment, $isPublic=0, $date='') {
|
||||
$this->_id = $id;
|
||||
$this->_name = $name;
|
||||
$this->_comment = $comment;
|
||||
$this->_user = $user;
|
||||
$this->_isPublic = $isPublic;
|
||||
$this->_date = $date;
|
||||
$this->_items = array();
|
||||
$this->_dms = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an instance of a transmittal object
|
||||
*
|
||||
* @param string|integer $id id or name of transmittal, depending
|
||||
* on the 3rd parameter.
|
||||
* @param object $dms instance of dms
|
||||
* @param string $by search by [id|name]. If this
|
||||
* parameter is left empty, the user will be search by its Id.
|
||||
* @return object instance of class SeedDMS_Core_Transmittal
|
||||
*/
|
||||
public static function getInstance($id, $dms, $by='') { /* {{{ */
|
||||
if(!$dms || get_class($dms) != 'SeedDMS_Core_DMS')
|
||||
return false;
|
||||
|
||||
$db = $dms->getDB();
|
||||
|
||||
switch($by) {
|
||||
case 'name':
|
||||
$queryStr = "SELECT * FROM `tblTransmittals` WHERE `name` = ".$db->qstr($id);
|
||||
break;
|
||||
default:
|
||||
$queryStr = "SELECT * FROM `tblTransmittals` WHERE id = " . (int) $id;
|
||||
}
|
||||
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
|
||||
if (is_bool($resArr) && $resArr == false) return false;
|
||||
if (count($resArr) != 1) return false;
|
||||
|
||||
$resArr = $resArr[0];
|
||||
|
||||
$uclassname = $dms->getClassname('user');
|
||||
$user = $uclassname::getInstance($resArr['userID'], $dms);
|
||||
$transmittal = new self($resArr["id"], $user, $resArr["name"], $resArr["comment"], $resArr["public"], $resArr["date"]);
|
||||
$transmittal->setDMS($dms);
|
||||
return $transmittal;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Get all instances of a transmittal object
|
||||
*
|
||||
* @param string|integer $id id or name of transmittal, depending
|
||||
* on the 3rd parameter.
|
||||
* @param object $dms instance of dms
|
||||
* @param string $by search by [id|name]. If this
|
||||
* parameter is left empty, the user will be search by its Id.
|
||||
* @return object instance of class SeedDMS_Core_Transmittal
|
||||
*/
|
||||
public static function getAllInstances($user, $orderby, $dms) { /* {{{ */
|
||||
$db = $dms->getDB();
|
||||
|
||||
$queryStr = "SELECT * FROM `tblTransmittals`";
|
||||
if($user)
|
||||
$queryStr .= " WHERE `userID` = " . $user->getID();
|
||||
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
|
||||
if (is_bool($resArr) && $resArr == false) return false;
|
||||
|
||||
$uclassname = $dms->getClassname('user');
|
||||
$transmittals = array();
|
||||
foreach ($resArr as $res) {
|
||||
$user = $uclassname::getInstance($res['userID'], $dms);
|
||||
$transmittal = new self($res["id"], $user, $res["name"], $res["comment"], $res["public"], $res["date"]);
|
||||
$transmittal->setDMS($dms);
|
||||
$transmittals[] = $transmittal;
|
||||
}
|
||||
return $transmittals;
|
||||
} /* }}} */
|
||||
|
||||
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 `tblTransmittals` SET `name` =".$db->qstr($newName)." WHERE `id` = " . $this->_id;
|
||||
$res = $db->getResult($queryStr);
|
||||
if (!$res)
|
||||
return false;
|
||||
|
||||
$this->_name = $newName;
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
function getComment() { return $this->_comment; }
|
||||
|
||||
function setComment($newComment) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "UPDATE `tblTransmittals` SET `comment` =".$db->qstr($newComment)." WHERE `id` = " . $this->_id;
|
||||
$res = $db->getResult($queryStr);
|
||||
if (!$res)
|
||||
return false;
|
||||
|
||||
$this->_comment = $newComment;
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
function getUser() { return $this->_user; }
|
||||
|
||||
function getItems() { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
if (!$this->_items) {
|
||||
$queryStr = "SELECT `tblTransmittalItems`.* FROM `tblTransmittalItems` ".
|
||||
"LEFT JOIN `tblDocuments` ON `tblTransmittalItems`.`document`=`tblDocuments`.`id` ".
|
||||
"WHERE `tblTransmittalItems`.`transmittal` = '". $this->_id ."'";
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if (is_bool($resArr) && $resArr == false)
|
||||
return false;
|
||||
|
||||
$this->_users = array();
|
||||
|
||||
$classname = $this->_dms->getClassname('transmittalitem');
|
||||
foreach ($resArr as $row) {
|
||||
$document = $this->_dms->getDocument($row['document']);
|
||||
$content = $document->getContentByVersion($row['version']);
|
||||
$item = new $classname($row["id"], $this, $content, $row["date"]);
|
||||
array_push($this->_items, $item);
|
||||
}
|
||||
}
|
||||
return $this->_items;
|
||||
} /* }}} */
|
||||
|
||||
function getSize() { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
if (!$this->_items) {
|
||||
self::getItems();
|
||||
}
|
||||
|
||||
$size = 0;
|
||||
foreach ($this->_items as $item) {
|
||||
if($content = $item->getContent()) {
|
||||
$size += $content->getFileSize();
|
||||
}
|
||||
}
|
||||
return $size;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Add an item to the transmittal
|
||||
*
|
||||
* @param object $item instance of SeedDMS_Core_DocumentContent
|
||||
* @return boolean true if item could be added, otherwise false
|
||||
*/
|
||||
function addContent($item) { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
if(get_class($item) != $this->_dms->getClassname('documentcontent'))
|
||||
return false;
|
||||
|
||||
$document = $item->getDocument();
|
||||
$queryStr = "INSERT INTO `tblTransmittalItems` (`transmittal`, `document`, `version`, `date`) ".
|
||||
"VALUES ('". $this->_id ."', ".$document->getID().", ".$item->getVersion().", ".$db->getCurrentDatetime().")";
|
||||
$res=$db->getResult($queryStr);
|
||||
if(!$res) {
|
||||
return false;
|
||||
}
|
||||
$itemID = $db->getInsertID('tblTransmittalItems');
|
||||
|
||||
return SeedDMS_Core_TransmittalItem::getInstance($itemID, $this->_dms);
|
||||
} /* }}} */
|
||||
|
||||
function remove() { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
|
||||
$queryStr = "DELETE FROM `tblTransmittals` WHERE `id` = " . $this->_id;
|
||||
if (!$db->getResult($queryStr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Class to represent a transmittal 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_TransmittalItem {
|
||||
/**
|
||||
* @var integer id of transmittal item
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
var $_id;
|
||||
|
||||
/**
|
||||
* @var object document content
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
var $_content;
|
||||
|
||||
/**
|
||||
* @var object transmittal
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
var $_transmittal;
|
||||
|
||||
/**
|
||||
* @var object date of creation
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
var $_date;
|
||||
|
||||
function __construct($id, $transmittal, $content, $date='') {
|
||||
$this->_id = $id;
|
||||
$this->_transmittal = $transmittal;
|
||||
$this->_content = $content;
|
||||
$this->_date = $date;
|
||||
$this->_dms = null;
|
||||
}
|
||||
|
||||
public static function getInstance($id, $dms) { /* {{{ */
|
||||
if(!$dms || get_class($dms) != 'SeedDMS_Core_DMS')
|
||||
return false;
|
||||
|
||||
$db = $dms->getDB();
|
||||
|
||||
$queryStr = "SELECT * FROM `tblTransmittalItems` WHERE `id` = " . (int) $id;
|
||||
$resArr = $db->getResultArray($queryStr);
|
||||
if (is_bool($resArr) && $resArr == false)
|
||||
return false;
|
||||
if (count($resArr) != 1)
|
||||
return false;
|
||||
$resArr = $resArr[0];
|
||||
|
||||
$transmittal = SeedDMS_Core_Transmittal::getInstance($resArr['transmittal'], $dms);
|
||||
$dclassname = $dms->getClassname('document');
|
||||
$document = $dclassname::getInstance($resArr['document'], $dms);
|
||||
$content = $document->getContentByVersion((int) $resArr['version']);
|
||||
|
||||
$item = new self($resArr["id"], $transmittal, $content, $resArr["date"]);
|
||||
$item->setDMS($dms);
|
||||
return $item;
|
||||
} /* }}} */
|
||||
|
||||
function setDMS($dms) {
|
||||
$this->_dms = $dms;
|
||||
}
|
||||
|
||||
function getID() { return $this->_id; }
|
||||
|
||||
function getTransmittal() { return $this->_transmittal; }
|
||||
|
||||
function getContent() { return $this->_content; }
|
||||
|
||||
function getDate() { return $this->_date; }
|
||||
|
||||
function remove() { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
$transmittal = $this->_transmittal;
|
||||
|
||||
$queryStr = "DELETE FROM `tblTransmittalItems` WHERE `id` = " . $this->_id;
|
||||
if (!$db->getResult($queryStr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Check if the content referenzed by the transmittal item is unequal
|
||||
* to the latest content of the document.
|
||||
*
|
||||
* This function updateѕ always to the latest version of the document,
|
||||
* even if the version in the item is higher. This can happen if a
|
||||
* version has been removed.
|
||||
*
|
||||
* @return boolean/integer false in case of an error, otherwise the new
|
||||
* version.
|
||||
*/
|
||||
function updateContent() { /* {{{ */
|
||||
$db = $this->_dms->getDB();
|
||||
$transmittal = $this->_transmittal;
|
||||
|
||||
$document = $this->_content->getDocument();
|
||||
$latestcontent = $document->getLatestContent();
|
||||
if($latestcontent->getVersion() != $this->_content->getVersion()) {
|
||||
$queryStr = "UPDATE `tblTransmittalItems` set `version` = ".$latestcontent->getVersion()." WHERE `id` = " . $this->_id;
|
||||
if (!$db->getResult($queryStr)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return $latestcontent->getVersion();
|
||||
} /* }}} */
|
||||
}
|
||||
?>
|
2659
SeedDMS_Core/Core/inc.ClassUser.php
Normal file
2659
SeedDMS_Core/Core/inc.ClassUser.php
Normal file
File diff suppressed because it is too large
Load Diff
1429
SeedDMS_Core/Core/inc.ClassWorkflow.php
Normal file
1429
SeedDMS_Core/Core/inc.ClassWorkflow.php
Normal file
File diff suppressed because it is too large
Load Diff
1187
SeedDMS_Core/Core/inc.DBAccessPDO.php
Normal file
1187
SeedDMS_Core/Core/inc.DBAccessPDO.php
Normal file
File diff suppressed because it is too large
Load Diff
485
SeedDMS_Core/Core/inc.FileUtils.php
Normal file
485
SeedDMS_Core/Core/inc.FileUtils.php
Normal file
|
@ -0,0 +1,485 @@
|
|||
<?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 {
|
||||
/**
|
||||
* @param $old
|
||||
* @param $new
|
||||
* @return bool
|
||||
*/
|
||||
static function renameFile($old, $new) { /* {{{ */
|
||||
return @rename($old, $new);
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* @param $file
|
||||
* @return bool
|
||||
*/
|
||||
static function removeFile($file) { /* {{{ */
|
||||
return @unlink($file);
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* @param $source
|
||||
* @param $target
|
||||
* @return bool
|
||||
*/
|
||||
static function copyFile($source, $target) { /* {{{ */
|
||||
return @copy($source, $target);
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* @param $source
|
||||
* @param $target
|
||||
* @return bool
|
||||
*/
|
||||
static function moveFile($source, $target) { /* {{{ */
|
||||
/** @noinspection PhpUndefinedFunctionInspection */
|
||||
if (!self::copyFile($source, $target))
|
||||
return false;
|
||||
/** @noinspection PhpUndefinedFunctionInspection */
|
||||
return self::removeFile($source);
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* @param $file
|
||||
* @return bool|int
|
||||
*/
|
||||
static function fileSize($file) { /* {{{ */
|
||||
if(!$a = @fopen($file, 'r'))
|
||||
return false;
|
||||
fseek($a, 0, SEEK_END);
|
||||
$filesize = ftell($a);
|
||||
fclose($a);
|
||||
return $filesize;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* @param $size
|
||||
* @param array $sizes
|
||||
* @return string
|
||||
*/
|
||||
static function format_filesize($size, $sizes = array('Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB')) { /* {{{ */
|
||||
if ($size == 0) return('0 Bytes');
|
||||
if ($size == 1) return('1 Byte');
|
||||
/** @noinspection PhpIllegalArrayKeyTypeInspection */
|
||||
return (round($size/pow(1024, ($i = floor(log($size, 1024)))), 2) . ' ' . $sizes[$i]);
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* @param $str
|
||||
* @return bool|int
|
||||
*/
|
||||
static function parse_filesize($str) { /* {{{ */
|
||||
preg_replace('/\s\s+/', '', $str);
|
||||
if(in_array(strtoupper(substr($str, -1)), array('B','K','M','G'))) {
|
||||
$value = (int) substr($str, 0, -1);
|
||||
$unit = substr($str, -1, 1);
|
||||
} else {
|
||||
return (int) $str;
|
||||
}
|
||||
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;
|
||||
}
|
||||
/** @noinspection PhpUnreachableStatementInspection */
|
||||
return false;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* @param $file
|
||||
* @return string
|
||||
*/
|
||||
static function checksum($file) { /* {{{ */
|
||||
return md5_file($file);
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* @param $string mimetype
|
||||
* @return string
|
||||
*/
|
||||
static function fileExtension($mimetype) { /* {{{ */
|
||||
switch($mimetype) {
|
||||
case "application/pdf":
|
||||
case "image/png":
|
||||
case "image/gif":
|
||||
case "image/jpg":
|
||||
$expect = substr($this->_mimeType, -3, 3);
|
||||
break;
|
||||
default:
|
||||
$mime_map = [
|
||||
'video/3gpp2' => '3g2',
|
||||
'video/3gp' => '3gp',
|
||||
'video/3gpp' => '3gp',
|
||||
'application/x-compressed' => '7zip',
|
||||
'audio/x-acc' => 'aac',
|
||||
'audio/ac3' => 'ac3',
|
||||
'application/postscript' => 'ai',
|
||||
'audio/x-aiff' => 'aif',
|
||||
'audio/aiff' => 'aif',
|
||||
'audio/x-au' => 'au',
|
||||
'video/x-msvideo' => 'avi',
|
||||
'video/msvideo' => 'avi',
|
||||
'video/avi' => 'avi',
|
||||
'application/x-troff-msvideo' => 'avi',
|
||||
'application/macbinary' => 'bin',
|
||||
'application/mac-binary' => 'bin',
|
||||
'application/x-binary' => 'bin',
|
||||
'application/x-macbinary' => 'bin',
|
||||
'image/bmp' => 'bmp',
|
||||
'image/x-bmp' => 'bmp',
|
||||
'image/x-bitmap' => 'bmp',
|
||||
'image/x-xbitmap' => 'bmp',
|
||||
'image/x-win-bitmap' => 'bmp',
|
||||
'image/x-windows-bmp' => 'bmp',
|
||||
'image/ms-bmp' => 'bmp',
|
||||
'image/x-ms-bmp' => 'bmp',
|
||||
'application/bmp' => 'bmp',
|
||||
'application/x-bmp' => 'bmp',
|
||||
'application/x-win-bitmap' => 'bmp',
|
||||
'application/cdr' => 'cdr',
|
||||
'application/coreldraw' => 'cdr',
|
||||
'application/x-cdr' => 'cdr',
|
||||
'application/x-coreldraw' => 'cdr',
|
||||
'image/cdr' => 'cdr',
|
||||
'image/x-cdr' => 'cdr',
|
||||
'zz-application/zz-winassoc-cdr' => 'cdr',
|
||||
'application/mac-compactpro' => 'cpt',
|
||||
'application/pkix-crl' => 'crl',
|
||||
'application/pkcs-crl' => 'crl',
|
||||
'application/x-x509-ca-cert' => 'crt',
|
||||
'application/pkix-cert' => 'crt',
|
||||
'text/css' => 'css',
|
||||
'text/x-comma-separated-values' => 'csv',
|
||||
'text/comma-separated-values' => 'csv',
|
||||
'application/vnd.msexcel' => 'csv',
|
||||
'application/x-director' => 'dcr',
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'docx',
|
||||
'application/x-dvi' => 'dvi',
|
||||
'message/rfc822' => 'eml',
|
||||
'application/x-msdownload' => 'exe',
|
||||
'video/x-f4v' => 'f4v',
|
||||
'audio/x-flac' => 'flac',
|
||||
'video/x-flv' => 'flv',
|
||||
'image/gif' => 'gif',
|
||||
'application/gpg-keys' => 'gpg',
|
||||
'application/x-gtar' => 'gtar',
|
||||
'application/x-gzip' => 'gzip',
|
||||
'application/mac-binhex40' => 'hqx',
|
||||
'application/mac-binhex' => 'hqx',
|
||||
'application/x-binhex40' => 'hqx',
|
||||
'application/x-mac-binhex40' => 'hqx',
|
||||
'text/html' => 'html',
|
||||
'image/x-icon' => 'ico',
|
||||
'image/x-ico' => 'ico',
|
||||
'image/vnd.microsoft.icon' => 'ico',
|
||||
'text/calendar' => 'ics',
|
||||
'application/java-archive' => 'jar',
|
||||
'application/x-java-application' => 'jar',
|
||||
'application/x-jar' => 'jar',
|
||||
'image/jp2' => 'jp2',
|
||||
'video/mj2' => 'jp2',
|
||||
'image/jpx' => 'jp2',
|
||||
'image/jpm' => 'jp2',
|
||||
'image/jpeg' => 'jpeg',
|
||||
'image/pjpeg' => 'jpeg',
|
||||
'application/x-javascript' => 'js',
|
||||
'application/json' => 'json',
|
||||
'text/json' => 'json',
|
||||
'application/vnd.google-earth.kml+xml' => 'kml',
|
||||
'application/vnd.google-earth.kmz' => 'kmz',
|
||||
'text/x-log' => 'log',
|
||||
'audio/x-m4a' => 'm4a',
|
||||
'application/vnd.mpegurl' => 'm4u',
|
||||
'audio/midi' => 'mid',
|
||||
'application/vnd.mif' => 'mif',
|
||||
'video/quicktime' => 'mov',
|
||||
'video/x-sgi-movie' => 'movie',
|
||||
'audio/mpeg' => 'mp3',
|
||||
'audio/mpg' => 'mp3',
|
||||
'audio/mpeg3' => 'mp3',
|
||||
'audio/mp3' => 'mp3',
|
||||
'video/mp4' => 'mp4',
|
||||
'video/mpeg' => 'mpeg',
|
||||
'application/oda' => 'oda',
|
||||
'audio/ogg' => 'ogg',
|
||||
'video/ogg' => 'ogg',
|
||||
'application/ogg' => 'ogg',
|
||||
'application/x-pkcs10' => 'p10',
|
||||
'application/pkcs10' => 'p10',
|
||||
'application/x-pkcs12' => 'p12',
|
||||
'application/x-pkcs7-signature' => 'p7a',
|
||||
'application/pkcs7-mime' => 'p7c',
|
||||
'application/x-pkcs7-mime' => 'p7c',
|
||||
'application/x-pkcs7-certreqresp' => 'p7r',
|
||||
'application/pkcs7-signature' => 'p7s',
|
||||
'application/pdf' => 'pdf',
|
||||
'application/octet-stream' => 'pdf',
|
||||
'application/x-x509-user-cert' => 'pem',
|
||||
'application/x-pem-file' => 'pem',
|
||||
'application/pgp' => 'pgp',
|
||||
'application/x-httpd-php' => 'php',
|
||||
'application/php' => 'php',
|
||||
'application/x-php' => 'php',
|
||||
'text/php' => 'php',
|
||||
'text/x-php' => 'php',
|
||||
'application/x-httpd-php-source' => 'php',
|
||||
'image/png' => 'png',
|
||||
'image/x-png' => 'png',
|
||||
'application/powerpoint' => 'ppt',
|
||||
'application/vnd.ms-powerpoint' => 'ppt',
|
||||
'application/vnd.ms-office' => 'ppt',
|
||||
'application/msword' => 'doc',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'pptx',
|
||||
'application/x-photoshop' => 'psd',
|
||||
'image/vnd.adobe.photoshop' => 'psd',
|
||||
'audio/x-realaudio' => 'ra',
|
||||
'audio/x-pn-realaudio' => 'ram',
|
||||
'application/x-rar' => 'rar',
|
||||
'application/rar' => 'rar',
|
||||
'application/x-rar-compressed' => 'rar',
|
||||
'audio/x-pn-realaudio-plugin' => 'rpm',
|
||||
'application/x-pkcs7' => 'rsa',
|
||||
'text/rtf' => 'rtf',
|
||||
'text/richtext' => 'rtx',
|
||||
'video/vnd.rn-realvideo' => 'rv',
|
||||
'application/x-stuffit' => 'sit',
|
||||
'application/smil' => 'smil',
|
||||
'text/srt' => 'srt',
|
||||
'image/svg+xml' => 'svg',
|
||||
'application/x-shockwave-flash' => 'swf',
|
||||
'application/x-tar' => 'tar',
|
||||
'application/x-gzip-compressed' => 'tgz',
|
||||
'image/tiff' => 'tiff',
|
||||
'text/plain' => 'txt',
|
||||
'text/x-vcard' => 'vcf',
|
||||
'application/videolan' => 'vlc',
|
||||
'text/vtt' => 'vtt',
|
||||
'audio/x-wav' => 'wav',
|
||||
'audio/wave' => 'wav',
|
||||
'audio/wav' => 'wav',
|
||||
'application/wbxml' => 'wbxml',
|
||||
'video/webm' => 'webm',
|
||||
'audio/x-ms-wma' => 'wma',
|
||||
'application/wmlc' => 'wmlc',
|
||||
'video/x-ms-wmv' => 'wmv',
|
||||
'video/x-ms-asf' => 'wmv',
|
||||
'application/xhtml+xml' => 'xhtml',
|
||||
'application/excel' => 'xl',
|
||||
'application/msexcel' => 'xls',
|
||||
'application/x-msexcel' => 'xls',
|
||||
'application/x-ms-excel' => 'xls',
|
||||
'application/x-excel' => 'xls',
|
||||
'application/x-dos_ms_excel' => 'xls',
|
||||
'application/xls' => 'xls',
|
||||
'application/x-xls' => 'xls',
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xlsx',
|
||||
'application/vnd.ms-excel' => 'xlsx',
|
||||
'application/xml' => 'xml',
|
||||
'text/xml' => 'xml',
|
||||
'text/xsl' => 'xsl',
|
||||
'application/xspf+xml' => 'xspf',
|
||||
'application/x-compress' => 'z',
|
||||
'application/x-zip' => 'zip',
|
||||
'application/zip' => 'zip',
|
||||
'application/x-zip-compressed' => 'zip',
|
||||
'application/s-compressed' => 'zip',
|
||||
'multipart/x-zip' => 'zip',
|
||||
'text/x-scriptzsh' => 'zsh',
|
||||
];
|
||||
$expect = isset($mime_map[$mimetype]) === true ? $mime_map[$mimetype] : '';
|
||||
}
|
||||
return $expect;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* @param $old
|
||||
* @param $new
|
||||
* @return bool
|
||||
*/
|
||||
static function renameDir($old, $new) { /* {{{ */
|
||||
return @rename($old, $new);
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
* @return bool
|
||||
*/
|
||||
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;
|
||||
*/
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
* @return bool
|
||||
*/
|
||||
static function removeDir($path) { /* {{{ */
|
||||
$handle = @opendir($path);
|
||||
while ($entry = @readdir($handle) )
|
||||
{
|
||||
if ($entry == ".." || $entry == ".")
|
||||
continue;
|
||||
else if (is_dir($path . DIRECTORY_SEPARATOR . $entry))
|
||||
{
|
||||
if (!self::removeDir($path . DIRECTORY_SEPARATOR . $entry . "/"))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!@unlink($path . DIRECTORY_SEPARATOR . $entry))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@closedir($handle);
|
||||
return @rmdir($path);
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* @param $sourcePath
|
||||
* @param $targetPath
|
||||
* @return bool
|
||||
*/
|
||||
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 . DIRECTORY_SEPARATOR . $entry, $targetPath . DIRECTORY_SEPARATOR . $entry))
|
||||
return false;
|
||||
} else {
|
||||
if (!@copy($sourcePath . DIRECTORY_SEPARATOR . $entry, $targetPath . DIRECTORY_SEPARATOR . $entry))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@closedir($handle);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* @param $sourcePath
|
||||
* @param $targetPath
|
||||
* @return bool
|
||||
*/
|
||||
static function moveDir($sourcePath, $targetPath) { /* {{{ */
|
||||
/** @noinspection PhpUndefinedFunctionInspection */
|
||||
if (!copyDir($sourcePath, $targetPath))
|
||||
return false;
|
||||
/** @noinspection PhpUndefinedFunctionInspection */
|
||||
return removeDir($sourcePath);
|
||||
} /* }}} */
|
||||
|
||||
// code by Kioob (php.net manual)
|
||||
/**
|
||||
* @param $source
|
||||
* @param bool $level
|
||||
* @return bool|string
|
||||
*/
|
||||
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;
|
||||
} /* }}} */
|
||||
}
|
10
SeedDMS_Core/oldtests/config.php
Normal file
10
SeedDMS_Core/oldtests/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/oldtests/getfoldertree.php
Normal file
25
SeedDMS_Core/oldtests/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/oldtests/getusers.php
Normal file
14
SeedDMS_Core/oldtests/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/oldtests/reverselookup.php
Normal file
44
SeedDMS_Core/oldtests/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";
|
||||
}
|
||||
|
||||
?>
|
||||
|
2314
SeedDMS_Core/package.xml
Normal file
2314
SeedDMS_Core/package.xml
Normal file
File diff suppressed because it is too large
Load Diff
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');
|
||||
|
||||
?>
|
254
SeedDMS_Lucene/Lucene/IndexedDocument.php
Normal file
254
SeedDMS_Lucene/Lucene/IndexedDocument.php
Normal file
|
@ -0,0 +1,254 @@
|
|||
<?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 {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $errormsg;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $mimetype;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $cmd;
|
||||
|
||||
/**
|
||||
* Run a shell command
|
||||
*
|
||||
* @param $cmd
|
||||
* @param int $timeout
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
static function execWithTimeout($cmd, $timeout=2) { /* {{{ */
|
||||
$descriptorspec = array(
|
||||
0 => array("pipe", "r"),
|
||||
1 => array("pipe", "w"),
|
||||
2 => array("pipe", "w")
|
||||
);
|
||||
$pipes = array();
|
||||
|
||||
$timeout += time();
|
||||
// Putting an 'exec' before the command will not fork the command
|
||||
// and therefore not create any child process. proc_terminate will
|
||||
// then reliably terminate the cmd and not just shell. See notes of
|
||||
// https://www.php.net/manual/de/function.proc-terminate.php
|
||||
$process = proc_open('exec '.$cmd, $descriptorspec, $pipes);
|
||||
if (!is_resource($process)) {
|
||||
throw new Exception("proc_open failed on: " . $cmd);
|
||||
}
|
||||
stream_set_blocking($pipes[1], 0);
|
||||
stream_set_blocking($pipes[2], 0);
|
||||
|
||||
$output = $error = '';
|
||||
$timeleft = $timeout - time();
|
||||
$read = array($pipes[1], $pipes[2]);
|
||||
$write = NULL;
|
||||
$exeptions = NULL;
|
||||
do {
|
||||
$num_changed_streams = stream_select($read, $write, $exeptions, $timeleft, 200000);
|
||||
|
||||
if ($num_changed_streams === false) {
|
||||
proc_terminate($process);
|
||||
throw new Exception("stream select failed on: " . $cmd);
|
||||
} elseif ($num_changed_streams > 0) {
|
||||
$output .= fread($pipes[1], 8192);
|
||||
$error .= fread($pipes[2], 8192);
|
||||
}
|
||||
$timeleft = $timeout - time();
|
||||
} while (!feof($pipes[1]) && $timeleft > 0);
|
||||
|
||||
fclose($pipes[0]);
|
||||
fclose($pipes[1]);
|
||||
fclose($pipes[2]);
|
||||
if ($timeleft <= 0) {
|
||||
proc_terminate($process);
|
||||
throw new Exception("command timeout on: " . $cmd);
|
||||
} else {
|
||||
$return_value = proc_close($process);
|
||||
return array('stdout'=>$output, 'stderr'=>$error, 'return'=>$return_value);
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Constructor. Creates our indexable document and adds all
|
||||
* necessary fields to it using the passed in document
|
||||
* @param SeedDMS_Core_DMS $dms
|
||||
* @param SeedDMS_Core_Document|Folder $document
|
||||
* @param null $convcmd
|
||||
* @param bool $nocontent
|
||||
* @param int $timeout
|
||||
*/
|
||||
public function __construct($dms, $document, $convcmd=null, $nocontent=false, $timeout=5) { /* {{{ */
|
||||
$this->errormsg = '';
|
||||
$this->cmd = '';
|
||||
$this->mimetype = '';
|
||||
|
||||
$this->addField(Zend_Search_Lucene_Field::Text('title', $document->getName(), 'utf-8'));
|
||||
if($acllist = $document->getReadAccessList(1, 1, 1)) {
|
||||
$allu = [];
|
||||
foreach($acllist['users'] as $u)
|
||||
$allu[] = $u->getLogin();
|
||||
$this->addField(Zend_Search_Lucene_Field::Text('users', implode(' ', $allu), 'utf-8'));
|
||||
/*
|
||||
$allg = [];
|
||||
foreach($acllist['groups'] as $g)
|
||||
$allg[] = $g->getName();
|
||||
$this->addField(Zend_Search_Lucene_Field::Text('groups', implode(' ', $allg), '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($comment = $document->getComment()) {
|
||||
$this->addField(Zend_Search_Lucene_Field::Text('comment', $comment, 'utf-8'));
|
||||
}
|
||||
$tmp = explode(':', substr($document->getFolderList(), 1, -1));
|
||||
foreach($tmp as $t)
|
||||
$this->addField(Zend_Search_Lucene_Field::Keyword('path', $t));
|
||||
// $this->addField(Zend_Search_Lucene_Field::Keyword('path', str_replace(':', 'x', $document->getFolderList())));
|
||||
|
||||
if($document->isType('document')) {
|
||||
$this->addField(Zend_Search_Lucene_Field::Keyword('document_id', 'D'.$document->getID()));
|
||||
$version = $document->getLatestContent();
|
||||
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'));
|
||||
}
|
||||
}
|
||||
}
|
||||
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($keywords = $document->getKeywords()) {
|
||||
$this->addField(Zend_Search_Lucene_Field::Text('keywords', $keywords, 'utf-8'));
|
||||
}
|
||||
if($version) {
|
||||
$status = $version->getStatus();
|
||||
$this->addField(Zend_Search_Lucene_Field::Keyword('status', $status['status'], 'utf-8'));
|
||||
}
|
||||
if($version && !$nocontent) {
|
||||
$path = $dms->contentDir . $version->getPath();
|
||||
if(file_exists($path)) {
|
||||
$mimetype = $version->getMimeType();
|
||||
$this->mimetype = $mimetype;
|
||||
if(is_object($convcmd) && (get_class($convcmd) == 'SeedDMS_ConversionMgr')) {
|
||||
if($service = $convcmd->getService($mimetype, 'text/plain')) {
|
||||
$content = $convcmd->convert($path, $mimetype, 'text/plain');
|
||||
if($content) {
|
||||
self::setContent($content);
|
||||
} elseif($content === false) {
|
||||
$this->errormsg = 'Conversion failed';
|
||||
}
|
||||
$this->cmd = get_class($service);
|
||||
} else {
|
||||
$this->cmd = 'No service to convert '.$mimetype.' to text/plain';
|
||||
}
|
||||
} else {
|
||||
$content = '';
|
||||
$cmd = '';
|
||||
$mimeparts = explode('/', $mimetype, 2);
|
||||
if(isset($convcmd[$mimetype])) {
|
||||
$cmd = sprintf($convcmd[$mimetype], $path);
|
||||
} elseif(isset($convcmd[$mimeparts[0].'/*'])) {
|
||||
$cmd = sprintf($convcmd[$mimetype], $path);
|
||||
} elseif(isset($convcmd['*'])) {
|
||||
$cmd = sprintf($convcmd[$mimetype], $path);
|
||||
}
|
||||
if($cmd) {
|
||||
$this->cmd = $cmd;
|
||||
try {
|
||||
$content = self::execWithTimeout($cmd, $timeout);
|
||||
if($content['stdout']) {
|
||||
self::setContent($content['stdout']);
|
||||
// $this->addField(Zend_Search_Lucene_Field::UnStored('content', $content['stdout'], 'utf-8'));
|
||||
}
|
||||
if($content['stderr']) {
|
||||
$this->errormsg = $content['stderr'];
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} elseif($document->isType('folder')) {
|
||||
$this->addField(Zend_Search_Lucene_Field::Keyword('document_id', 'F'.$document->getID()));
|
||||
$this->addField(Zend_Search_Lucene_Field::UnIndexed('created', $document->getDate()));
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
public function getErrorMsg() { /* {{{ */
|
||||
return $this->errormsg;
|
||||
} /* }}} */
|
||||
|
||||
public function getMimeType() { /* {{{ */
|
||||
return $this->mimetype;
|
||||
} /* }}} */
|
||||
|
||||
public function setContent($data) { /* {{{ */
|
||||
$this->addField(Zend_Search_Lucene_Field::UnStored('content', $data, 'utf-8'));
|
||||
} /* }}} */
|
||||
|
||||
public function getCmd() { /* {{{ */
|
||||
return $this->cmd;
|
||||
} /* }}} */
|
||||
|
||||
/* Use only for setting the command if e.g. an extension takes over the
|
||||
* conversion to txt (like the office extension which uses the collabora
|
||||
* conversion service).
|
||||
*/
|
||||
public function setCmd($cmd) { /* {{{ */
|
||||
$this->cmd = $cmd;
|
||||
} /* }}} */
|
||||
}
|
||||
?>
|
67
SeedDMS_Lucene/Lucene/Indexer.php
Normal file
67
SeedDMS_Lucene/Lucene/Indexer.php
Normal file
|
@ -0,0 +1,67 @@
|
|||
<?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($conf) { /* {{{ */
|
||||
try {
|
||||
$index = Zend_Search_Lucene::open($conf['indexdir']);
|
||||
return($index);
|
||||
} catch (Exception $e) {
|
||||
return null;
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
static function create($conf) { /* {{{ */
|
||||
try {
|
||||
$index = Zend_Search_Lucene::create($conf['indexdir']);
|
||||
return($index);
|
||||
} catch (Exception $e) {
|
||||
return null;
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Do some initialization
|
||||
*
|
||||
*/
|
||||
static 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);
|
||||
} /* }}} */
|
||||
|
||||
|
||||
}
|
||||
?>
|
153
SeedDMS_Lucene/Lucene/Search.php
Normal file
153
SeedDMS_Lucene/Lucene/Search.php
Normal file
|
@ -0,0 +1,153 @@
|
|||
<?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:D'.$id);
|
||||
return $hits ? $hits[0] : false;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Get folder from index
|
||||
*
|
||||
* @param object $index lucene index
|
||||
* @return object instance of SeedDMS_Lucene_Document of false
|
||||
*/
|
||||
function getFolder($id) { /* {{{ */
|
||||
$hits = $this->index->find('document_id:F'.$id);
|
||||
return $hits ? $hits[0] : false;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Search in index
|
||||
*
|
||||
* @param object $index lucene index
|
||||
* @return object instance of SeedDMS_Lucene_Search
|
||||
*/
|
||||
function search($term, $fields=array(), $limit=array()) { /* {{{ */
|
||||
$querystr = '';
|
||||
$term = trim($term);
|
||||
if($term) {
|
||||
$querystr = substr($term, -1) != '*' ? $term.'*' : $term;
|
||||
}
|
||||
if(!empty($fields['owner'])) {
|
||||
if(is_string($owner)) {
|
||||
if($querystr)
|
||||
$querystr .= ' && ';
|
||||
$querystr .= 'owner:'.$owner;
|
||||
} elseif(is_array($fields['owner'])) {
|
||||
if($querystr)
|
||||
$querystr .= ' && ';
|
||||
$querystr .= '(owner:"';
|
||||
$querystr .= implode('" || owner:"', $fields['owner']);
|
||||
$querystr .= '")';
|
||||
}
|
||||
}
|
||||
if(!empty($fields['category'])) {
|
||||
if($querystr)
|
||||
$querystr .= ' && ';
|
||||
$querystr .= '(category:"';
|
||||
$querystr .= implode('" && category:"', $fields['category']);
|
||||
$querystr .= '")';
|
||||
}
|
||||
if(!empty($fields['status'])) {
|
||||
if($querystr)
|
||||
$querystr .= ' && ';
|
||||
$querystr .= '(status:"';
|
||||
$querystr .= implode('" || status:"', $fields['status']);
|
||||
$querystr .= '")';
|
||||
}
|
||||
if(!empty($fields['user'])) {
|
||||
if($querystr)
|
||||
$querystr .= ' && ';
|
||||
$querystr .= '(users:"';
|
||||
$querystr .= implode('" || users:"', $fields['user']);
|
||||
$querystr .= '")';
|
||||
}
|
||||
if(!empty($fields['rootFolder']) && $fields['rootFolder']->getFolderList()) {
|
||||
if($querystr)
|
||||
$querystr .= ' && ';
|
||||
$querystr .= '(path:"';
|
||||
$tmp[] = $fields['rootFolder']->getID();
|
||||
$querystr .= implode('" && path:"', $tmp);
|
||||
//$querystr .= $fields['rootFolder']->getFolderList().$fields['rootFolder']->getID().':';
|
||||
$querystr .= '")';
|
||||
}
|
||||
if(!empty($fields['startFolder']) && $fields['startFolder']->getFolderList()) {
|
||||
if($querystr)
|
||||
$querystr .= ' && ';
|
||||
$querystr .= '(path:"';
|
||||
// $querystr .= str_replace(':', 'x', $fields['startFolder']->getFolderList().$fields['startFolder']->getID().':');
|
||||
$tmp = array();//explode(':', substr($fields['startFolder']->getFolderList(), 1, -1));
|
||||
$tmp[] = $fields['startFolder']->getID();
|
||||
$querystr .= implode('" && path:"', $tmp);
|
||||
// $querystr .= str_replace(':', ' ', $fields['startFolder']->getFolderList().$fields['startFolder']->getID());
|
||||
$querystr .= '")';
|
||||
}
|
||||
try {
|
||||
$query = Zend_Search_Lucene_Search_QueryParser::parse($querystr);
|
||||
try {
|
||||
$hits = $this->index->find($query);
|
||||
$recs = array();
|
||||
$c = 0;
|
||||
foreach($hits as $hit) {
|
||||
if($c >= $limit['offset'] && ($c-$limit['offset'] < $limit))
|
||||
$recs[] = array('id'=>$hit->id, 'document_id'=>$hit->document_id);
|
||||
$c++;
|
||||
}
|
||||
return array('count'=>count($hits), 'hits'=>$recs, 'facets'=>array());
|
||||
} catch (Zend_Search_Lucene_Exception $e) {
|
||||
return false;
|
||||
}
|
||||
} catch (Zend_Search_Lucene_Search_QueryParserException $e) {
|
||||
return false;
|
||||
}
|
||||
} /* }}} */
|
||||
}
|
||||
?>
|
372
SeedDMS_Lucene/package.xml
Normal file
372
SeedDMS_Lucene/package.xml
Normal file
|
@ -0,0 +1,372 @@
|
|||
<?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>2021-05-10</date>
|
||||
<time>08:55:43</time>
|
||||
<version>
|
||||
<release>1.1.17</release>
|
||||
<api>1.1.17</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
- close pipes in execWithTimeout(), also return exit code of command
|
||||
</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>
|
||||
<release>
|
||||
<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>
|
||||
</release>
|
||||
<release>
|
||||
<date>2016-03-29</date>
|
||||
<time>08:11:19</time>
|
||||
<version>
|
||||
<release>1.1.8</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>
|
||||
set last parameter of stream_select() to 200000 micro sec. in case the timeout in sec. is set to 0
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2016-04-28</date>
|
||||
<time>08:11:19</time>
|
||||
<version>
|
||||
<release>1.1.9</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>
|
||||
pass variables to stream_select() to fullfill strict standards.
|
||||
make all functions in Indexer.php static
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2017-03-01</date>
|
||||
<time>15:55:32</time>
|
||||
<version>
|
||||
<release>1.1.10</release>
|
||||
<api>1.1.10</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
catch exception in execWithTimeout()
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2017-12-04</date>
|
||||
<time>10:58:13</time>
|
||||
<version>
|
||||
<release>1.1.11</release>
|
||||
<api>1.1.11</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
allow conversion commands for mimetypes with wildcards
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2018-01-30</date>
|
||||
<time>10:58:13</time>
|
||||
<version>
|
||||
<release>1.1.12</release>
|
||||
<api>1.1.12</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
execWithTimeout() reads data from stderr and saves it into error msg
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2018-04-11</date>
|
||||
<time>10:58:13</time>
|
||||
<version>
|
||||
<release>1.1.13</release>
|
||||
<api>1.1.13</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
IndexedDocument() remembers cmd and mimetype
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2020-09-02</date>
|
||||
<time>08:55:43</time>
|
||||
<version>
|
||||
<release>1.1.14</release>
|
||||
<api>1.1.14</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
Index users with at least read access on the document
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2020-09-10</date>
|
||||
<time>08:55:43</time>
|
||||
<version>
|
||||
<release>1.1.15</release>
|
||||
<api>1.1.15</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
- add searching for document status
|
||||
- better error handling if opening index fails
|
||||
- parameters for SeedDMS_Lucene_Search::search() has changed
|
||||
- SeedDMS_Lucene_Search::search() returns array of hits, count and facets
|
||||
- pass config array instead of index directory to SeedDMS_Lucene_Indexer::create()
|
||||
and SeedDMS_Lucene_Indexer::open()
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2020-12-12</date>
|
||||
<time>08:55:43</time>
|
||||
<version>
|
||||
<release>1.1.16</release>
|
||||
<api>1.1.16</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
- add indexing of folders
|
||||
</notes>
|
||||
</release>
|
||||
</changelog>
|
||||
</package>
|
34
SeedDMS_Preview/Preview.php
Normal file
34
SeedDMS_Preview/Preview.php
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?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/Base.php
|
||||
*/
|
||||
require_once('Preview/Base.php');
|
||||
|
||||
/**
|
||||
* @uses Preview/Previewer.php
|
||||
*/
|
||||
require_once('Preview/Previewer.php');
|
||||
|
||||
/**
|
||||
* @uses Preview/PdfPreviewer.php
|
||||
*/
|
||||
require_once('Preview/PdfPreviewer.php');
|
||||
|
||||
?>
|
238
SeedDMS_Preview/Preview/Base.php
Normal file
238
SeedDMS_Preview/Preview/Base.php
Normal file
|
@ -0,0 +1,238 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of preview base
|
||||
*
|
||||
* @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_Base {
|
||||
/**
|
||||
* @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 array $converters list of mimetypes and commands for converting
|
||||
* file into preview image
|
||||
* @access protected
|
||||
*/
|
||||
protected $converters;
|
||||
|
||||
/**
|
||||
* @var object $conversionmgr
|
||||
* @access protected
|
||||
*/
|
||||
protected $conversionmgr;
|
||||
|
||||
/**
|
||||
* @var integer $timeout maximum time for execution of external commands
|
||||
* @access protected
|
||||
*/
|
||||
protected $timeout;
|
||||
|
||||
/**
|
||||
* @var boolean $xsendfile set to true if mod_xѕendfile is to be used
|
||||
* @access protected
|
||||
*/
|
||||
protected $xsendfile;
|
||||
|
||||
/**
|
||||
* @var string $lastpreviewfile will be set to the file name of the last preview
|
||||
* @access protected
|
||||
*/
|
||||
protected $lastpreviewfile;
|
||||
|
||||
function __construct($previewDir, $timeout=5, $xsendfile=true) { /* {{{ */
|
||||
if(!is_dir($previewDir)) {
|
||||
if (!SeedDMS_Core_File::makeDir($previewDir)) {
|
||||
$this->previewDir = '';
|
||||
} else {
|
||||
$this->previewDir = $previewDir;
|
||||
}
|
||||
} else {
|
||||
$this->previewDir = $previewDir;
|
||||
}
|
||||
$this->timeout = intval($timeout);
|
||||
$this->converters = array();
|
||||
$this->xsendfile = $xsendfile;
|
||||
$this->conversionmgr = null;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Run a shell command
|
||||
*
|
||||
* @param $cmd
|
||||
* @param int $timeout
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
static function execWithTimeout($cmd, $timeout=5) { /* {{{ */
|
||||
$descriptorspec = array(
|
||||
0 => array("pipe", "r"),
|
||||
1 => array("pipe", "w"),
|
||||
2 => array("pipe", "w")
|
||||
);
|
||||
$pipes = array();
|
||||
|
||||
$timeout += time();
|
||||
// Putting an 'exec' before the command will not fork the command
|
||||
// and therefore not create any child process. proc_terminate will
|
||||
// then reliably terminate the cmd and not just shell. See notes of
|
||||
// https://www.php.net/manual/de/function.proc-terminate.php
|
||||
$process = proc_open('exec '.$cmd, $descriptorspec, $pipes);
|
||||
if (!is_resource($process)) {
|
||||
throw new Exception("proc_open failed on: " . $cmd);
|
||||
}
|
||||
stream_set_blocking($pipes[1], 0);
|
||||
stream_set_blocking($pipes[2], 0);
|
||||
|
||||
$output = $error = '';
|
||||
$timeleft = $timeout - time();
|
||||
$read = array($pipes[1], $pipes[2]);
|
||||
$write = NULL;
|
||||
$exeptions = NULL;
|
||||
do {
|
||||
$num_changed_streams = stream_select($read, $write, $exeptions, $timeleft, 200000);
|
||||
|
||||
if ($num_changed_streams === false) {
|
||||
proc_terminate($process);
|
||||
throw new Exception("stream select failed on: " . $cmd);
|
||||
} elseif ($num_changed_streams > 0) {
|
||||
$output .= fread($pipes[1], 8192);
|
||||
$error .= fread($pipes[2], 8192);
|
||||
}
|
||||
$timeleft = $timeout - time();
|
||||
} while (!feof($pipes[1]) && $timeleft > 0);
|
||||
|
||||
fclose($pipes[0]);
|
||||
fclose($pipes[1]);
|
||||
fclose($pipes[2]);
|
||||
if ($timeleft <= 0) {
|
||||
proc_terminate($process);
|
||||
throw new Exception("command timeout on: " . $cmd);
|
||||
} else {
|
||||
$return_value = proc_close($process);
|
||||
return array('stdout'=>$output, 'stderr'=>$error, 'return'=>$return_value);
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Set a list of converters
|
||||
*
|
||||
* Merges the list of passed converters with the already existing ones.
|
||||
* Existing converters will be overwritten.
|
||||
*
|
||||
* @param array list of converters. The key of the array contains the mimetype
|
||||
* and the value is the command to be called for creating the preview
|
||||
*/
|
||||
function setConverters($arr) { /* {{{ */
|
||||
if(is_array($arr))
|
||||
$this->converters = $arr;
|
||||
else
|
||||
$this->converters = array();
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Set conversion service manager
|
||||
*
|
||||
* A conversion manager is a service for converting files from one format
|
||||
* to another format.
|
||||
*
|
||||
* @param object $conversionmgr
|
||||
*/
|
||||
function setConversionMgr($conversionmgr) { /* {{{ */
|
||||
$this->conversionmgr = $conversionmgr;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Enable/Disable xsendfile extension
|
||||
*
|
||||
* Merges the list of passed converters with the already existing ones.
|
||||
* Existing converters will be overwritten.
|
||||
*
|
||||
* @param boolean $xsendfile turn on/off use of xsendfile module in apache
|
||||
*/
|
||||
function setXsendfile($xsendfile) { /* {{{ */
|
||||
$this->xsendfile = $xsendfile;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Add a list of converters
|
||||
*
|
||||
* Merges the list of passed converters with the already existing ones.
|
||||
* Existing converters will be overwritten.
|
||||
*
|
||||
* @param array list of converters. The key of the array contains the mimetype
|
||||
* and the value is the command to be called for creating the preview
|
||||
*/
|
||||
function addConverters($arr) { /* {{{ */
|
||||
$this->converters = array_merge($this->converters, $arr);
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Check if converter for a given mimetype is set
|
||||
*
|
||||
* @param string $from from mimetype
|
||||
* @param string $to to mimetype
|
||||
*
|
||||
* @return boolean true if converter exists, otherwise false
|
||||
*/
|
||||
function hasConverter($from, $to='') { /* {{{ */
|
||||
if($this->conversionmgr)
|
||||
return $this->conversionmgr->hasService($from, $to);
|
||||
else
|
||||
return array_key_exists($from, $this->converters) && $this->converters[$from];
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Send a file from disk to the browser
|
||||
*
|
||||
* This function uses either readfile() or the xѕendfile apache module if
|
||||
* it is installed.
|
||||
*
|
||||
* @param string $filename
|
||||
*/
|
||||
protected function sendFile($filename) { /* {{{ */
|
||||
if($this->xsendfile && function_exists('apache_get_modules') && in_array('mod_xsendfile',apache_get_modules())) {
|
||||
header("X-Sendfile: ".$filename);
|
||||
} else {
|
||||
$size = filesize($filename);
|
||||
header("Content-Length: " . $size);
|
||||
/* Make sure output buffering is off */
|
||||
if (ob_get_level()) {
|
||||
ob_end_clean();
|
||||
}
|
||||
readfile($filename);
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Return path of last created preview file
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPreviewFile() { /* {{{ */
|
||||
return $this->lastpreviewfile;
|
||||
} /* }}} */
|
||||
}
|
||||
|
317
SeedDMS_Preview/Preview/PdfPreviewer.php
Normal file
317
SeedDMS_Preview/Preview/PdfPreviewer.php
Normal file
|
@ -0,0 +1,317 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of pdf 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 pdf preview 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_PdfPreviewer extends SeedDMS_Preview_Base {
|
||||
|
||||
function __construct($previewDir, $timeout=5, $xsendfile=true) { /* {{{ */
|
||||
parent::__construct($previewDir, $timeout, $xsendfile);
|
||||
$this->converters = array(
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => "unoconv -d document -f pdf --stdout -v '%f' > '%o'",
|
||||
'application/vnd.oasis.opendocument.text' => "unoconv -d document -f pdf --stdout -v '%f' > '%o'",
|
||||
'text/rtf' => "unoconv -d document -f pdf --stdout -v '%f' > '%o'",
|
||||
'application/msword' => "unoconv -d document -f pdf --stdout -v '%f' > '%o'",
|
||||
'application/vnd.ms-excel' => "unoconv -d document -f pdf --stdout -v '%f' > '%o'",
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => "unoconv -d document -f pdf --stdout -v '%f' > '%o'",
|
||||
'text/plain' => "unoconv -d document -f pdf --stdout -v '%f' > '%o'",
|
||||
'application/postscript' => "ps2pdf '%f' - > '%o'",
|
||||
'image/jpeg' => "convert '%f' pdf:- > '%o'",
|
||||
'image/png' => "convert '%f' pdf:- > '%o'",
|
||||
'image/gif' => "convert '%f' pdf:- > '%o'",
|
||||
'video/mp4' => "convert '%f[1-20]' pdf:- > '%o'",
|
||||
);
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Return the physical filename of the preview image on disk
|
||||
*
|
||||
* @param object $object document content or document file
|
||||
* @return string file name of preview image
|
||||
*/
|
||||
protected function getFileName($object) { /* {{{ */
|
||||
if(!$object)
|
||||
return false;
|
||||
|
||||
$document = $object->getDocument();
|
||||
$dms = $document->_dms;
|
||||
$dir = $this->previewDir.'/'.$document->getDir();
|
||||
switch(get_class($object)) {
|
||||
case $dms->getClassname('documentcontent'):
|
||||
$target = $dir.'p'.$object->getVersion();
|
||||
break;
|
||||
case "SeedDMS_Core_DocumentFile":
|
||||
$target = $dir.'f'.$object->getID();
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return $target;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Check if converter for a given mimetype is set
|
||||
*
|
||||
* @param string $mimetype from mimetype
|
||||
*
|
||||
* @return boolean true if converter exists, otherwise false
|
||||
*/
|
||||
function hasConverter($from, $to='') { /* {{{ */
|
||||
return parent::hasConverter($from, 'application/pdf');
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Create a pdf preview for a given file
|
||||
*
|
||||
* This method creates a preview in pdf format for a regular file
|
||||
* in the file system and stores the result in the directory $dir relative
|
||||
* to the configured preview directory. The filename of the resulting preview
|
||||
* image is either $target.pdf (if set) or md5($infile).pdf.
|
||||
* The $mimetype is used to select the propper conversion programm.
|
||||
* An already existing pdf preview is replaced.
|
||||
*
|
||||
* @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 string $target optional name of preview image (without extension)
|
||||
* @return boolean true on success, false on failure
|
||||
*/
|
||||
public function createRawPreview($infile, $dir, $mimetype, $target='') { /* {{{ */
|
||||
if(!self::hasConverter($mimetype))
|
||||
return false;
|
||||
|
||||
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);
|
||||
$this->lastpreviewfile = $target.'.pdf';
|
||||
if($target != '' && (!file_exists($target.'.pdf') || filectime($target.'.pdf') < filectime($infile))) {
|
||||
if($this->conversionmgr) {
|
||||
if(!$this->conversionmgr->convert($infile, $mimetype, 'application/pdf', $target.'.pdf')) {
|
||||
$this->lastpreviewfile = '';
|
||||
return false;
|
||||
}
|
||||
$new = true;
|
||||
} else {
|
||||
$cmd = '';
|
||||
$mimeparts = explode('/', $mimetype, 2);
|
||||
if(isset($this->converters[$mimetype])) {
|
||||
$cmd = str_replace(array('%f', '%o', '%m'), array($infile, $target.'.pdf', $mimetype), $this->converters[$mimetype]);
|
||||
} elseif(isset($this->converters[$mimeparts[0].'/*'])) {
|
||||
$cmd = str_replace(array('%f', '%o', '%m'), array($infile, $target.'.pdf', $mimetype), $this->converters[$mimeparts[0].'/*']);
|
||||
} elseif(isset($this->converters['*'])) {
|
||||
$cmd = str_replace(array('%f', '%o', '%m'), array($infile, $target.'.pdf', $mimetype), $this->converters['*']);
|
||||
}
|
||||
if($cmd) {
|
||||
try {
|
||||
self::execWithTimeout($cmd, $this->timeout);
|
||||
} catch(Exception $e) {
|
||||
$this->lastpreviewfile = '';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Create preview image
|
||||
*
|
||||
* This function creates a preview image for the given document
|
||||
* content or document file. It internally uses
|
||||
* {@link SeedDMS_Preview::createRawPreview()}. The filename of the
|
||||
* preview image is created by {@link SeedDMS_Preview_Previewer::getFileName()}
|
||||
*
|
||||
* @param object $object instance of SeedDMS_Core_DocumentContent
|
||||
* or SeedDMS_Core_DocumentFile
|
||||
* @return boolean true on success, false on failure
|
||||
*/
|
||||
public function createPreview($object) { /* {{{ */
|
||||
if(!$object)
|
||||
return false;
|
||||
|
||||
$document = $object->getDocument();
|
||||
$file = $document->_dms->contentDir.$object->getPath();
|
||||
$target = $this->getFileName($object);
|
||||
return $this->createRawPreview($file, $document->getDir(), $object->getMimeType(), $target);
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Check if a preview image already exists.
|
||||
*
|
||||
* This function is a companion to {@link SeedDMS_Preview_Previewer::createRawPreview()}.
|
||||
*
|
||||
* @param string $infile name of input file including full path
|
||||
* @param string $dir directory relative to $this->previewDir
|
||||
* @return boolean true if preview exists, otherwise false
|
||||
*/
|
||||
public function hasRawPreview($infile, $dir, $target='') { /* {{{ */
|
||||
if(!$this->previewDir)
|
||||
return false;
|
||||
if(!$target)
|
||||
$target = $this->previewDir.$dir.md5($infile);
|
||||
if($target !== false && file_exists($target.'.pdf') && filectime($target.'.pdf') >= filectime($infile)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Check if a preview image already exists.
|
||||
*
|
||||
* This function is a companion to {@link SeedDMS_Preview_Previewer::createPreview()}.
|
||||
*
|
||||
* @param object $object instance of SeedDMS_Core_DocumentContent
|
||||
* or SeedDMS_Core_DocumentFile
|
||||
* @return boolean true if preview exists, otherwise false
|
||||
*/
|
||||
public function hasPreview($object) { /* {{{ */
|
||||
if(!$object)
|
||||
return false;
|
||||
|
||||
if(!$this->previewDir)
|
||||
return false;
|
||||
$target = $this->getFileName($object);
|
||||
if($target !== false && file_exists($target.'.pdf') && filectime($target.'.pdf') >= $object->getDate()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Return a preview image.
|
||||
*
|
||||
* This function returns the content of a preview image if it exists..
|
||||
*
|
||||
* @param string $infile name of input file including full path
|
||||
* @param string $dir directory relative to $this->previewDir
|
||||
* @return boolean/string image content if preview exists, otherwise false
|
||||
*/
|
||||
public function getRawPreview($infile, $dir, $target='') { /* {{{ */
|
||||
if(!$this->previewDir)
|
||||
return false;
|
||||
|
||||
if(!$target)
|
||||
$target = $this->previewDir.$dir.md5($infile);
|
||||
if($target && file_exists($target.'.pdf')) {
|
||||
$this->sendFile($target.'.pdf');
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Return a preview image.
|
||||
*
|
||||
* This function returns the content of a preview image if it exists..
|
||||
*
|
||||
* @param object $object instance of SeedDMS_Core_DocumentContent
|
||||
* or SeedDMS_Core_DocumentFile
|
||||
* @return boolean/string image content if preview exists, otherwise false
|
||||
*/
|
||||
public function getPreview($object) { /* {{{ */
|
||||
if(!$this->previewDir)
|
||||
return false;
|
||||
|
||||
$target = $this->getFileName($object);
|
||||
if($target && file_exists($target.'.pdf')) {
|
||||
$this->sendFile($target.'.pdf');
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Return file size preview image.
|
||||
*
|
||||
* @param object $object instance of SeedDMS_Core_DocumentContent
|
||||
* or SeedDMS_Core_DocumentFile
|
||||
* @return boolean/integer size of preview image or false if image
|
||||
* does not exist
|
||||
*/
|
||||
public function getFilesize($object) { /* {{{ */
|
||||
$target = $this->getFileName($object);
|
||||
if($target && file_exists($target.'.pdf')) {
|
||||
return(filesize($target.'.pdf'));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Delete preview image.
|
||||
*
|
||||
* @param object $object instance of SeedDMS_Core_DocumentContent
|
||||
* or SeedDMS_Core_DocumentFile
|
||||
* @return boolean true if deletion succeded or false if file does not exist
|
||||
*/
|
||||
public function deletePreview($object) { /* {{{ */
|
||||
if(!$this->previewDir)
|
||||
return false;
|
||||
|
||||
$target = $this->getFileName($object);
|
||||
if($target && file_exists($target.'.pdf')) {
|
||||
return(unlink($target.'.pdf'));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
static function recurseRmdir($dir) {
|
||||
$files = array_diff(scandir($dir), array('.','..'));
|
||||
foreach ($files as $file) {
|
||||
(is_dir("$dir/$file")) ? SeedDMS_Preview_Previewer::recurseRmdir("$dir/$file") : unlink("$dir/$file");
|
||||
}
|
||||
return rmdir($dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all preview images belonging to a document
|
||||
*
|
||||
* This function removes the preview images of all versions and
|
||||
* files of a document including the directory. It actually just
|
||||
* removes the directory for the document in the cache.
|
||||
*
|
||||
* @param object $document instance of SeedDMS_Core_Document
|
||||
* @return boolean true if deletion succeded or false if file does not exist
|
||||
*/
|
||||
public function deleteDocumentPreviews($document) { /* {{{ */
|
||||
if(!$this->previewDir)
|
||||
return false;
|
||||
|
||||
$dir = $this->previewDir.'/'.$document->getDir();
|
||||
if(file_exists($dir) && is_dir($dir)) {
|
||||
return SeedDMS_Preview_Previewer::recurseRmdir($dir);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
} /* }}} */
|
||||
}
|
||||
?>
|
362
SeedDMS_Preview/Preview/Previewer.php
Normal file
362
SeedDMS_Preview/Preview/Previewer.php
Normal file
|
@ -0,0 +1,362 @@
|
|||
<?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 extends SeedDMS_Preview_Base {
|
||||
/**
|
||||
* @var integer $width maximum width/height of resized image
|
||||
* @access protected
|
||||
*/
|
||||
protected $width;
|
||||
|
||||
function __construct($previewDir, $width=40, $timeout=5, $xsendfile=true) { /* {{{ */
|
||||
parent::__construct($previewDir, $timeout, $xsendfile);
|
||||
$this->converters = array(
|
||||
'image/png' => "convert -resize %wx '%f' '%o'",
|
||||
'image/gif' => "convert -resize %wx '%f' '%o'",
|
||||
'image/jpg' => "convert -resize %wx '%f' '%o'",
|
||||
'image/jpeg' => "convert -resize %wx '%f' '%o'",
|
||||
'image/svg+xml' => "convert -resize %wx '%f' '%o'",
|
||||
'text/plain' => "convert -resize %wx '%f' '%o'",
|
||||
'application/pdf' => "convert -density 100 -resize %wx '%f[0]' '%o'",
|
||||
'application/postscript' => "convert -density 100 -resize %wx '%f[0]' '%o'",
|
||||
'application/x-compressed-tar' => "tar tzvf '%f' | convert -density 100 -resize %wx text:-[0] '%o'",
|
||||
);
|
||||
$this->width = intval($width);
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Return 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
|
||||
*/
|
||||
public function getFileName($object, $width) { /* {{{ */
|
||||
if(!$object)
|
||||
return false;
|
||||
|
||||
$document = $object->getDocument();
|
||||
$dms = $document->_dms;
|
||||
$dir = $this->previewDir.'/'.$document->getDir();
|
||||
switch(get_class($object)) {
|
||||
case $dms->getClassname('documentcontent'):
|
||||
$target = $dir.'p'.$object->getVersion().'-'.$width;
|
||||
break;
|
||||
case "SeedDMS_Core_DocumentFile":
|
||||
$target = $dir.'f'.$object->getID().'-'.$width;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return $target;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Check if converter for a given mimetype is set
|
||||
*
|
||||
* @param string $mimetype from mimetype
|
||||
*
|
||||
* @return boolean true if converter exists, otherwise false
|
||||
*/
|
||||
function hasConverter($from, $to='') { /* {{{ */
|
||||
return parent::hasConverter($from, 'image/png');
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Create a preview image for a given file
|
||||
*
|
||||
* This method creates a preview image in png format for a regular file
|
||||
* in the file system and stores the result in the directory $dir relative
|
||||
* to the configured preview directory. The filename of the resulting preview
|
||||
* image is either $target.png (if set) or md5($infile)-$width.png.
|
||||
* The $mimetype is used to select the propper conversion programm.
|
||||
* An already existing preview image is replaced.
|
||||
*
|
||||
* @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
|
||||
* @param string $target optional name of preview image (without extension)
|
||||
* @return boolean true on success, false on failure
|
||||
*/
|
||||
public function createRawPreview($infile, $dir, $mimetype, $width=0, $target='', &$new=false) { /* {{{ */
|
||||
if(!self::hasConverter($mimetype))
|
||||
return false;
|
||||
|
||||
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;
|
||||
$this->lastpreviewfile = $target.'.png';
|
||||
if($target != '' && (!file_exists($target.'.png') || filectime($target.'.png') < filectime($infile))) {
|
||||
if($this->conversionmgr) {
|
||||
if(!$this->conversionmgr->convert($infile, $mimetype, 'image/png', $target.'.png', array('width'=>$width))) {
|
||||
$this->lastpreviewfile = '';
|
||||
return false;
|
||||
}
|
||||
$new = true;
|
||||
} else {
|
||||
$cmd = '';
|
||||
$mimeparts = explode('/', $mimetype, 2);
|
||||
if(isset($this->converters[$mimetype])) {
|
||||
$cmd = str_replace(array('%w', '%f', '%o', '%m'), array($width, $infile, $target.'.png', $mimetype), $this->converters[$mimetype]);
|
||||
} elseif(isset($this->converters[$mimeparts[0].'/*'])) {
|
||||
$cmd = str_replace(array('%w', '%f', '%o', '%m'), array($width, $infile, $target.'.png', $mimetype), $this->converters[$mimeparts[0].'/*']);
|
||||
} elseif(isset($this->converters['*'])) {
|
||||
$cmd = str_replace(array('%w', '%f', '%o', '%m'), array($width, $infile, $target.'.png', $mimetype), $this->converters['*']);
|
||||
}
|
||||
|
||||
if($cmd) {
|
||||
try {
|
||||
self::execWithTimeout($cmd, $this->timeout);
|
||||
$new = true;
|
||||
} catch(Exception $e) {
|
||||
$this->lastpreviewfile = '';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
$new = false;
|
||||
return true;
|
||||
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Create preview image
|
||||
*
|
||||
* This function creates a preview image for the given document
|
||||
* content or document file. It internally uses
|
||||
* {@link SeedDMS_Preview::createRawPreview()}. The filename of the
|
||||
* preview image is created by {@link SeedDMS_Preview_Previewer::getFileName()}
|
||||
*
|
||||
* @param object $object instance of SeedDMS_Core_DocumentContent
|
||||
* or SeedDMS_Core_DocumentFile
|
||||
* @param integer $width desired width of preview image
|
||||
* @return boolean true on success, false on failure
|
||||
*/
|
||||
public function createPreview($object, $width=0, &$new=false) { /* {{{ */
|
||||
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, $new);
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Check if a preview image already exists.
|
||||
*
|
||||
* This function is a companion to {@link SeedDMS_Preview_Previewer::createRawPreview()}.
|
||||
*
|
||||
* @param string $infile name of input file including full path
|
||||
* @param string $dir directory relative to $this->previewDir
|
||||
* @param integer $width desired width of preview image
|
||||
* @return boolean true if preview exists, otherwise false
|
||||
*/
|
||||
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;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Check if a preview image already exists.
|
||||
*
|
||||
* This function is a companion to {@link SeedDMS_Preview_Previewer::createPreview()}.
|
||||
*
|
||||
* @param object $object instance of SeedDMS_Core_DocumentContent
|
||||
* or SeedDMS_Core_DocumentFile
|
||||
* @param integer $width desired width of preview image
|
||||
* @return boolean true if preview exists, otherwise 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;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Return a preview image.
|
||||
*
|
||||
* This function returns the content of a preview image if it exists..
|
||||
*
|
||||
* @param string $infile name of input file including full path
|
||||
* @param string $dir directory relative to $this->previewDir
|
||||
* @param integer $width desired width of preview image
|
||||
* @return boolean/string image content if preview exists, otherwise 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')) {
|
||||
$this->sendFile($target.'.png');
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Return a preview image.
|
||||
*
|
||||
* This function returns the content of a preview image if it exists..
|
||||
*
|
||||
* @param object $object instance of SeedDMS_Core_DocumentContent
|
||||
* or SeedDMS_Core_DocumentFile
|
||||
* @param integer $width desired width of preview image
|
||||
* @return boolean/string image content if preview exists, otherwise false
|
||||
*/
|
||||
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')) {
|
||||
$this->sendFile($target.'.png');
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Return file size preview image.
|
||||
*
|
||||
* @param object $object instance of SeedDMS_Core_DocumentContent
|
||||
* or SeedDMS_Core_DocumentFile
|
||||
* @param integer $width desired width of preview image
|
||||
* @return boolean/integer size of preview image or false if image
|
||||
* does not exist
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Delete preview image.
|
||||
*
|
||||
* @param object $object instance of SeedDMS_Core_DocumentContent
|
||||
* or SeedDMS_Core_DocumentFile
|
||||
* @param integer $width desired width of preview image
|
||||
* @return boolean true if deletion succeded or false if file does not exist
|
||||
*/
|
||||
public function deletePreview($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')) {
|
||||
return(unlink($target.'.png'));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
static function recurseRmdir($dir) {
|
||||
$files = array_diff(scandir($dir), array('.','..'));
|
||||
foreach ($files as $file) {
|
||||
(is_dir("$dir/$file")) ? SeedDMS_Preview_Previewer::recurseRmdir("$dir/$file") : unlink("$dir/$file");
|
||||
}
|
||||
return rmdir($dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all preview images belonging to a document
|
||||
*
|
||||
* This function removes the preview images of all versions and
|
||||
* files of a document including the directory. It actually just
|
||||
* removes the directory for the document in the cache.
|
||||
*
|
||||
* @param object $document instance of SeedDMS_Core_Document
|
||||
* @return boolean true if deletion succeded or false if file does not exist
|
||||
*/
|
||||
public function deleteDocumentPreviews($document) { /* {{{ */
|
||||
if(!$this->previewDir)
|
||||
return false;
|
||||
|
||||
$dir = $this->previewDir.'/'.$document->getDir();
|
||||
if(file_exists($dir) && is_dir($dir)) {
|
||||
return SeedDMS_Preview_Previewer::recurseRmdir($dir);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
} /* }}} */
|
||||
}
|
||||
?>
|
492
SeedDMS_Preview/package.xml
Normal file
492
SeedDMS_Preview/package.xml
Normal file
|
@ -0,0 +1,492 @@
|
|||
<?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 and pdf file from the document content.</description>
|
||||
<lead>
|
||||
<name>Uwe Steinmann</name>
|
||||
<user>steinm</user>
|
||||
<email>uwe@steinmann.cx</email>
|
||||
<active>yes</active>
|
||||
</lead>
|
||||
<date>2021-10-16</date>
|
||||
<time>09:49:39</time>
|
||||
<version>
|
||||
<release>1.4.0</release>
|
||||
<api>1.4.0</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
- use new conversion service if available
|
||||
- createRawPreview() checks early if a converter exists
|
||||
</notes>
|
||||
<contents>
|
||||
<dir baseinstalldir="SeedDMS" name="/">
|
||||
<dir name="Preview">
|
||||
<file name="Base.php" role="php">
|
||||
<tasks:replace from="@package_version@" to="version" type="package-info" />
|
||||
</file>
|
||||
<file name="Previewer.php" role="php">
|
||||
<tasks:replace from="@package_version@" to="version" type="package-info" />
|
||||
</file>
|
||||
<file name="PdfPreviewer.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>
|
||||
<release>
|
||||
<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>
|
||||
</release>
|
||||
<release>
|
||||
<date>2016-03-29</date>
|
||||
<time>08:07:14</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>
|
||||
set last parameter of stream_select() to 200000 micro sec. in case the timeout in sec. is set to 0
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2016-04-05</date>
|
||||
<time>15:17:11</time>
|
||||
<version>
|
||||
<release>1.1.8</release>
|
||||
<api>1.1.8</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
pass variables to stream_select (required by php7)
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2016-04-26</date>
|
||||
<time>15:17:11</time>
|
||||
<version>
|
||||
<release>1.1.9</release>
|
||||
<api>1.1.9</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
add more documentation
|
||||
finish deletePreview()
|
||||
add new method deleteDocumentPreviews()
|
||||
fix calculation of timeout (Bug #269)
|
||||
check if cache dir exists before deleting it in deleteDocumentPreviews()
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2016-11-07</date>
|
||||
<time>15:17:11</time>
|
||||
<version>
|
||||
<release>1.2.0</release>
|
||||
<api>1.2.0</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
add new previewer which converts document to pdf instead of png
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2016-11-15</date>
|
||||
<time>21:00:26</time>
|
||||
<version>
|
||||
<release>1.2.1</release>
|
||||
<api>1.2.0</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
setConverters() overrides exiting converters
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2017-03-02</date>
|
||||
<time>07:14:59</time>
|
||||
<version>
|
||||
<release>1.2.2</release>
|
||||
<api>1.2.0</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
commands can be set for mimetypes 'xxxx/*' and '*'
|
||||
pass mimetype as parameter '%m' to converter
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2017-09-18</date>
|
||||
<time>07:14:32</time>
|
||||
<version>
|
||||
<release>1.2.3</release>
|
||||
<api>1.2.0</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
createPreview() returns false if running the converter command fails
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2017-10-11</date>
|
||||
<time>07:14:32</time>
|
||||
<version>
|
||||
<release>1.2.4</release>
|
||||
<api>1.2.0</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
fix typo in converter for tar.gz files
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2017-10-11</date>
|
||||
<time>07:14:32</time>
|
||||
<version>
|
||||
<release>1.2.5</release>
|
||||
<api>1.2.0</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
SeedDMS_Preview_Base::hasConverter() returns only try if command is set
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2017-12-04</date>
|
||||
<time>10:59:39</time>
|
||||
<version>
|
||||
<release>1.2.6</release>
|
||||
<api>1.2.0</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
SeedDMS_Preview_Base::setConverters() overrides existing converters.
|
||||
New method SeedDMS_Preview_Base::addConverters() merges new converters with old ones.
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2018-01-18</date>
|
||||
<time>10:59:39</time>
|
||||
<version>
|
||||
<release>1.2.7</release>
|
||||
<api>1.2.0</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
add SeedDMS_Preview_Base::sendFile() as a replacement for readfile() which uses
|
||||
mod_xsendfile if available
|
||||
execWithTimeout() reads data from stderr and returns it together with stdout in array
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2018-03-08</date>
|
||||
<time>10:59:39</time>
|
||||
<version>
|
||||
<release>1.2.8</release>
|
||||
<api>1.2.0</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
preview is also created if SeedDMS_Core_DocumentContent has a child class
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2018-07-13</date>
|
||||
<time>10:59:39</time>
|
||||
<version>
|
||||
<release>1.2.9</release>
|
||||
<api>1.2.9</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
make sure list of converters is always an array
|
||||
usage of mod_sendfile can be configured
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2019-02-11</date>
|
||||
<time>10:59:39</time>
|
||||
<version>
|
||||
<release>1.2.10</release>
|
||||
<api>1.2.10</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
new parameter for enabling/disabling xsendfile
|
||||
fix creation of pdf preview if document content class is not SeedDMS_Core_DocumentContent
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2020-02-17</date>
|
||||
<time>09:49:39</time>
|
||||
<version>
|
||||
<release>1.3.0</release>
|
||||
<api>1.3.0</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
add new methode getPreviewFile()
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2020-03-21</date>
|
||||
<time>09:49:39</time>
|
||||
<version>
|
||||
<release>1.3.1</release>
|
||||
<api>1.3.1</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
add parameter $target to SeedDMS_Preview_pdfPreviewer::hasRawPreview() and SeedDMS_Preview_pdfPreviewer::getRawPreview()
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2020-12-23</date>
|
||||
<time>09:49:39</time>
|
||||
<version>
|
||||
<release>1.3.2</release>
|
||||
<api>1.3.1</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
set header Content-Length
|
||||
update package description
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2020-12-23</date>
|
||||
<time>09:49:39</time>
|
||||
<version>
|
||||
<release>1.3.3</release>
|
||||
<api>1.3.3</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
- close pipes in execWithTimeout(), also return exit code of command
|
||||
- createPreview() has optional parameter by referenz to return true if a
|
||||
preview image was actually created
|
||||
</notes>
|
||||
</release>
|
||||
</changelog>
|
||||
</package>
|
0
SeedDMS_Preview/tests/Preview.php
Normal file
0
SeedDMS_Preview/tests/Preview.php
Normal file
49
SeedDMS_SQLiteFTS/SQLiteFTS.php
Normal file
49
SeedDMS_SQLiteFTS/SQLiteFTS.php
Normal file
|
@ -0,0 +1,49 @@
|
|||
<?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');
|
||||
|
||||
/**
|
||||
* @uses SeedDMS_SQLiteFTS_Exception
|
||||
*/
|
||||
require_once('SQLiteFTS/Exception.php');
|
||||
|
||||
?>
|
117
SeedDMS_SQLiteFTS/SQLiteFTS/Document.php
Normal file
117
SeedDMS_SQLiteFTS/SQLiteFTS/Document.php
Normal file
|
@ -0,0 +1,117 @@
|
|||
<?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') {
|
||||
if($key == 'docid') {
|
||||
$this->id = $this->fields[$key] = (int) $value;
|
||||
} else {
|
||||
if(isset($this->fields[$key]))
|
||||
$this->fields[$key] .= ' '.$value;
|
||||
else
|
||||
$this->fields[$key] = $value;
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
public function addField(SeedDMS_SQLiteFTS_Field $field) { /* {{{ */
|
||||
$this->fields[$field->name] = $field;
|
||||
if($field->name == 'docid') {
|
||||
$this->id = $field->value;
|
||||
}
|
||||
return $this;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Return an array with the names of the fields in this document.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFieldNames() {
|
||||
return array_keys($this->fields);
|
||||
}
|
||||
|
||||
public function _getFieldValue($key) { /* {{{ */
|
||||
if(isset($this->fields[$key]))
|
||||
return $this->fields[$key];
|
||||
else
|
||||
return false;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Proxy method for getFieldValue(), provides more convenient access to
|
||||
* the string value of a field.
|
||||
*
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
public function __get($name) {
|
||||
return $this->getFieldValue($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Zend_Search_Lucene_Field object for a named field in this document.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @return Zend_Search_Lucene_Field
|
||||
*/
|
||||
public function getField($fieldName) {
|
||||
if (!array_key_exists($fieldName, $this->fields)) {
|
||||
require_once 'SeedDMS/SQLiteFTS/Exception.php';
|
||||
throw new SeedDMS_SQLiteFTS_Exception("Field name \"$fieldName\" not found in document.");
|
||||
}
|
||||
return $this->fields[$fieldName];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the string value of a named field in this document.
|
||||
*
|
||||
* @see __get()
|
||||
* @return string
|
||||
*/
|
||||
public function getFieldValue($fieldName) {
|
||||
return $this->getField($fieldName)->value;
|
||||
}
|
||||
}
|
||||
?>
|
41
SeedDMS_SQLiteFTS/SQLiteFTS/Exception.php
Normal file
41
SeedDMS_SQLiteFTS/SQLiteFTS/Exception.php
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
/**
|
||||
* SeedDMS_SQLiteFTS
|
||||
*
|
||||
* @category SeedDMS
|
||||
* @package SeedDMS
|
||||
* @copyright Copyright (c) 2021 uwe@steinmann.cx
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* @category SeedDMS
|
||||
* @package SeedDMS
|
||||
* @copyright Copyright (c) 2021 uwe@steinmann.cx
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class SeedDMS_SQLiteFTS_Exception extends Exception
|
||||
{
|
||||
/**
|
||||
* Construct the exception
|
||||
*
|
||||
* @param string $msg
|
||||
* @param int $code
|
||||
* @param Exception $previous
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($msg = '', $code = 0, Exception $previous = null) {
|
||||
parent::__construct($msg, (int) $code, $previous);
|
||||
}
|
||||
|
||||
/**
|
||||
* String representation of the exception
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString() {
|
||||
return parent::__toString();
|
||||
}
|
||||
|
||||
}
|
88
SeedDMS_SQLiteFTS/SQLiteFTS/Field.php
Normal file
88
SeedDMS_SQLiteFTS/SQLiteFTS/Field.php
Normal file
|
@ -0,0 +1,88 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of a field
|
||||
*
|
||||
* @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 field.
|
||||
*
|
||||
* @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_Field {
|
||||
|
||||
/**
|
||||
* Field name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* Field value
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
public $value;
|
||||
|
||||
/**
|
||||
* Object constructor
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
*/
|
||||
public function __construct($name, $value) {
|
||||
$this->name = $name;
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a String-valued Field that is not tokenized, but is indexed
|
||||
* and stored. Useful for non-text fields, e.g. date or url.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
* @return SeedDMS_SQLiteFTS_Field
|
||||
*/
|
||||
public static function keyword($name, $value) {
|
||||
return new self($name, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a String-valued Field that is tokenized and indexed,
|
||||
* and is stored in the index, for return with hits. Useful for short text
|
||||
* fields, like "title" or "subject". Term vector will not be stored for this field.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
* @return SeedDMS_SQLiteFTS_Field
|
||||
*/
|
||||
public static function text($name, $value) {
|
||||
return new self($name, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a String-valued Field that is tokenized and indexed,
|
||||
* but that is not stored in the index.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
* @return SeedDMS_SQLiteFTS_Field
|
||||
*/
|
||||
public static function unStored($name, $value) {
|
||||
return new self($name, $value);
|
||||
}
|
||||
}
|
256
SeedDMS_SQLiteFTS/SQLiteFTS/IndexedDocument.php
Normal file
256
SeedDMS_SQLiteFTS/SQLiteFTS/IndexedDocument.php
Normal file
|
@ -0,0 +1,256 @@
|
|||
<?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');
|
||||
require_once('Field.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 {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $errormsg;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $mimetype;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $cmd;
|
||||
|
||||
/**
|
||||
* Run a shell command
|
||||
*
|
||||
* @param $cmd
|
||||
* @param int $timeout
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
static function execWithTimeout($cmd, $timeout=2) { /* {{{ */
|
||||
$descriptorspec = array(
|
||||
0 => array("pipe", "r"),
|
||||
1 => array("pipe", "w"),
|
||||
2 => array("pipe", "w")
|
||||
);
|
||||
$pipes = array();
|
||||
|
||||
$timeout += time();
|
||||
// Putting an 'exec' before the command will not fork the command
|
||||
// and therefore not create any child process. proc_terminate will
|
||||
// then reliably terminate the cmd and not just shell. See notes of
|
||||
// https://www.php.net/manual/de/function.proc-terminate.php
|
||||
$process = proc_open('exec '.$cmd, $descriptorspec, $pipes);
|
||||
if (!is_resource($process)) {
|
||||
throw new Exception("proc_open failed on: " . $cmd);
|
||||
}
|
||||
stream_set_blocking($pipes[1], 0);
|
||||
stream_set_blocking($pipes[2], 0);
|
||||
|
||||
$output = $error = '';
|
||||
$timeleft = $timeout - time();
|
||||
$read = array($pipes[1], $pipes[2]);
|
||||
$write = NULL;
|
||||
$exeptions = NULL;
|
||||
do {
|
||||
$num_changed_streams = stream_select($read, $write, $exeptions, $timeleft, 200000);
|
||||
|
||||
if ($num_changed_streams === false) {
|
||||
proc_terminate($process);
|
||||
throw new Exception("stream select failed on: " . $cmd);
|
||||
} elseif ($num_changed_streams > 0) {
|
||||
$output .= fread($pipes[1], 8192);
|
||||
$error .= fread($pipes[2], 8192);
|
||||
}
|
||||
$timeleft = $timeout - time();
|
||||
} while (!feof($pipes[1]) && $timeleft > 0);
|
||||
|
||||
fclose($pipes[0]);
|
||||
fclose($pipes[1]);
|
||||
fclose($pipes[2]);
|
||||
if ($timeleft <= 0) {
|
||||
proc_terminate($process);
|
||||
throw new Exception("command timeout on: " . $cmd);
|
||||
} else {
|
||||
$return_value = proc_close($process);
|
||||
return array('stdout'=>$output, 'stderr'=>$error, 'return'=>$return_value);
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Constructor. Creates our indexable document and adds all
|
||||
* necessary fields to it using the passed in document
|
||||
*
|
||||
* $convcmd can either be an array of conversion commands or
|
||||
* an object of class SeedDMS_ConversionMgr
|
||||
*/
|
||||
public function __construct($dms, $document, $convcmd=null, $nocontent=false, $timeout=5) { /* {{{ */
|
||||
$this->errormsg = '';
|
||||
$this->cmd = '';
|
||||
$this->mimetype = '';
|
||||
|
||||
$this->addField(SeedDMS_SQLiteFTS_Field::Text('title', $document->getName()));
|
||||
if($acllist = $document->getReadAccessList(1, 1, 1)) {
|
||||
$allu = [];
|
||||
foreach($acllist['users'] as $u)
|
||||
$allu[] = $u->getLogin();
|
||||
$this->addField(SeedDMS_SQLiteFTS_Field::Text('users', implode(' ', $allu)));
|
||||
/*
|
||||
$allg = [];
|
||||
foreach($acllist['groups'] as $g)
|
||||
$allg[] = $g->getName();
|
||||
$this->addField(SeedDMS_SQLiteFTS_Field::Text('groups', implode(' ', $allg)));
|
||||
*/
|
||||
}
|
||||
if($attributes = $document->getAttributes()) {
|
||||
foreach($attributes as $attribute) {
|
||||
$attrdef = $attribute->getAttributeDefinition();
|
||||
if($attrdef->getValueSet() != '')
|
||||
$this->addField(SeedDMS_SQLiteFTS_Field::Keyword('attr_'.str_replace(' ', '_', $attrdef->getName()), $attribute->getValue()));
|
||||
else
|
||||
$this->addField(SeedDMS_SQLiteFTS_Field::Text('attr_'.str_replace(' ', '_', $attrdef->getName()), $attribute->getValue()));
|
||||
}
|
||||
}
|
||||
$owner = $document->getOwner();
|
||||
$this->addField(SeedDMS_SQLiteFTS_Field::Text('owner', $owner->getLogin()));
|
||||
$this->addField(SeedDMS_SQLiteFTS_Field::Keyword('path', str_replace(':', 'x', $document->getFolderList())));
|
||||
if($comment = $document->getComment()) {
|
||||
$this->addField(SeedDMS_SQLiteFTS_Field::Text('comment', $comment));
|
||||
}
|
||||
|
||||
if($document->isType('document')) {
|
||||
$this->addField(SeedDMS_SQLiteFTS_Field::Keyword('document_id', 'D'.$document->getID()));
|
||||
$this->addField(SeedDMS_SQLiteFTS_Field::Keyword('record_type', 'document'));
|
||||
$version = $document->getLatestContent();
|
||||
if($version) {
|
||||
$this->addField(SeedDMS_SQLiteFTS_Field::Keyword('mimetype', $version->getMimeType()));
|
||||
$this->addField(SeedDMS_SQLiteFTS_Field::Keyword('origfilename', $version->getOriginalFileName()));
|
||||
if(!$nocontent)
|
||||
$this->addField(SeedDMS_SQLiteFTS_Field::Keyword('created', $version->getDate(), 'unindexed'));
|
||||
if($attributes = $version->getAttributes()) {
|
||||
foreach($attributes as $attribute) {
|
||||
$attrdef = $attribute->getAttributeDefinition();
|
||||
if($attrdef->getValueSet() != '')
|
||||
$this->addField(SeedDMS_SQLiteFTS_Field::Keyword('attr_'.str_replace(' ', '_', $attrdef->getName()), $attribute->getValue()));
|
||||
else
|
||||
$this->addField(SeedDMS_SQLiteFTS_Field::Text('attr_'.str_replace(' ', '_', $attrdef->getName()), $attribute->getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
if($categories = $document->getCategories()) {
|
||||
$names = array();
|
||||
foreach($categories as $cat) {
|
||||
$names[] = $cat->getName();
|
||||
}
|
||||
$this->addField(SeedDMS_SQLiteFTS_Field::Text('category', implode(' ', $names)));
|
||||
}
|
||||
if($keywords = $document->getKeywords()) {
|
||||
$this->addField(SeedDMS_SQLiteFTS_Field::Text('keywords', $keywords));
|
||||
}
|
||||
if($version) {
|
||||
$status = $version->getStatus();
|
||||
$this->addField(SeedDMS_SQLiteFTS_Field::Keyword('status', $status['status']+10));
|
||||
}
|
||||
if($version && !$nocontent) {
|
||||
$path = $dms->contentDir . $version->getPath();
|
||||
if(file_exists($path)) {
|
||||
$mimetype = $version->getMimeType();
|
||||
$this->mimetype = $mimetype;
|
||||
if(is_object($convcmd) && (get_class($convcmd) == 'SeedDMS_ConversionMgr')) {
|
||||
if($service = $convcmd->getService($mimetype, 'text/plain')) {
|
||||
$content = $convcmd->convert($path, $mimetype, 'text/plain');
|
||||
if($content) {
|
||||
self::setContent($content);
|
||||
} elseif($content === false) {
|
||||
$this->errormsg = 'Conversion failed';
|
||||
}
|
||||
$this->cmd = get_class($service);
|
||||
} else {
|
||||
$this->cmd = 'No service to convert '.$mimetype.' to text/plain';
|
||||
}
|
||||
} else {
|
||||
$content = '';
|
||||
$cmd = '';
|
||||
$mimeparts = explode('/', $mimetype, 2);
|
||||
if(isset($convcmd[$mimetype])) {
|
||||
$cmd = sprintf($convcmd[$mimetype], $path);
|
||||
} elseif(isset($convcmd[$mimeparts[0].'/*'])) {
|
||||
$cmd = sprintf($convcmd[$mimetype], $path);
|
||||
} elseif(isset($convcmd['*'])) {
|
||||
$cmd = sprintf($convcmd[$mimetype], $path);
|
||||
}
|
||||
if($cmd) {
|
||||
$this->cmd = $cmd;
|
||||
try {
|
||||
$content = self::execWithTimeout($cmd, $timeout);
|
||||
if($content['stdout']) {
|
||||
self::setContent($content['stdout']);
|
||||
// $this->addField(SeedDMS_SQLiteFTS_Field::UnStored('content', $content['stdout']));
|
||||
}
|
||||
if($content['stderr']) {
|
||||
$this->errormsg = $content['stderr'];
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} elseif($document->isType('folder')) {
|
||||
$this->addField(SeedDMS_SQLiteFTS_Field::Keyword('document_id', 'F'.$document->getID()));
|
||||
$this->addField(SeedDMS_SQLiteFTS_Field::Keyword('record_type', 'folder'));
|
||||
$this->addField(SeedDMS_SQLiteFTS_Field::Keyword('created', $document->getDate(), 'unindexed'));
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
public function getErrorMsg() { /* {{{ */
|
||||
return $this->errormsg;
|
||||
} /* }}} */
|
||||
|
||||
public function getMimeType() { /* {{{ */
|
||||
return $this->mimetype;
|
||||
} /* }}} */
|
||||
|
||||
public function setContent($data) { /* {{{ */
|
||||
$this->addField(SeedDMS_SQLiteFTS_Field::Text('content', $data));
|
||||
} /* }}} */
|
||||
|
||||
public function getCmd() { /* {{{ */
|
||||
return $this->cmd;
|
||||
} /* }}} */
|
||||
|
||||
/* Use only for setting the command if e.g. an extension takes over the
|
||||
* conversion to txt (like the office extension which uses the collabora
|
||||
* conversion service).
|
||||
*/
|
||||
public function setCmd($cmd) { /* {{{ */
|
||||
$this->cmd = $cmd;
|
||||
} /* }}} */
|
||||
}
|
||||
?>
|
372
SeedDMS_SQLiteFTS/SQLiteFTS/Indexer.php
Normal file
372
SeedDMS_SQLiteFTS/SQLiteFTS/Indexer.php
Normal file
|
@ -0,0 +1,372 @@
|
|||
<?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 string $ftstype
|
||||
* @access protected
|
||||
*/
|
||||
protected $_ftstype;
|
||||
|
||||
/**
|
||||
* @var object $index sqlite index
|
||||
* @access protected
|
||||
*/
|
||||
protected $_conn;
|
||||
|
||||
const ftstype = 'fts5';
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
*/
|
||||
function __construct($indexerDir) { /* {{{ */
|
||||
$this->_conn = new PDO('sqlite:'.$indexerDir.'/index.db');
|
||||
$this->_ftstype = self::ftstype;
|
||||
if($this->_ftstype == 'fts5')
|
||||
$this->_rawid = 'rowid';
|
||||
else
|
||||
$this->_rawid = 'docid';
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Open an existing index
|
||||
*
|
||||
* @param string $indexerDir directory on disk containing the index
|
||||
*/
|
||||
static function open($conf) { /* {{{ */
|
||||
if(file_exists($conf['indexdir'].'/index.db')) {
|
||||
return new SeedDMS_SQLiteFTS_Indexer($conf['indexdir']);
|
||||
} else
|
||||
return self::create($conf);
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Create a new index
|
||||
*
|
||||
* @param array $conf $conf['indexdir'] is the directory on disk containing the index
|
||||
*/
|
||||
static function create($conf) { /* {{{ */
|
||||
if(file_exists($conf['indexdir'].'/index.db'))
|
||||
unlink($conf['indexdir'].'/index.db');
|
||||
$index = new SeedDMS_SQLiteFTS_Indexer($conf['indexdir']);
|
||||
/* Make sure the sequence of fields is identical to the field list
|
||||
* in SeedDMS_SQLiteFTS_Term
|
||||
*/
|
||||
$version = SQLite3::version();
|
||||
if(self::ftstype == 'fts4') {
|
||||
if($version['versionNumber'] >= 3008000)
|
||||
$sql = 'CREATE VIRTUAL TABLE docs USING fts4(documentid, record_type, title, comment, keywords, category, mimetype, origfilename, owner, content, created, users, status, path, notindexed=created, matchinfo=fts3)';
|
||||
else
|
||||
$sql = 'CREATE VIRTUAL TABLE docs USING fts4(documentid, record_type, title, comment, keywords, category, mimetype, origfilename, owner, content, created, users, status, path, 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;
|
||||
}
|
||||
} elseif(self::ftstype == 'fts5') {
|
||||
$sql = 'CREATE VIRTUAL TABLE docs USING fts5(documentid, record_type, title, comment, keywords, category, mimetype, origfilename, owner, content, created unindexed, users, status, path)';
|
||||
$res = $index->_conn->exec($sql);
|
||||
if($res === false) {
|
||||
return null;
|
||||
}
|
||||
$sql = 'CREATE VIRTUAL TABLE docs_terms USING fts5vocab(docs, \'col\');';
|
||||
$res = $index->_conn->exec($sql);
|
||||
if($res === false) {
|
||||
return null;
|
||||
}
|
||||
} else
|
||||
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;
|
||||
|
||||
foreach(array('comment', 'keywords', 'category', 'content', 'mimetype', 'origfilename', 'status', 'created') as $kk) {
|
||||
try {
|
||||
${$kk} = $doc->getFieldValue($kk);
|
||||
} catch (Exception $e) {
|
||||
${$kk} = '';
|
||||
}
|
||||
}
|
||||
$sql = "DELETE FROM docs WHERE documentid=".$this->_conn->quote($doc->getFieldValue('document_id'));
|
||||
$res = $this->_conn->exec($sql);
|
||||
if($res === false) {
|
||||
return false;
|
||||
}
|
||||
$sql = "INSERT INTO docs (documentid, record_type, title, comment, keywords, category, owner, content, mimetype, origfilename, created, users, status, path) VALUES (".$this->_conn->quote($doc->getFieldValue('document_id')).", ".$this->_conn->quote($doc->getFieldValue('record_type')).", ".$this->_conn->quote($doc->getFieldValue('title')).", ".$this->_conn->quote($comment).", ".$this->_conn->quote($keywords).", ".$this->_conn->quote($category).", ".$this->_conn->quote($doc->getFieldValue('owner')).", ".$this->_conn->quote($content).", ".$this->_conn->quote($mimetype).", ".$this->_conn->quote($origfilename).", ".(int)$created.", ".$this->_conn->quote($doc->getFieldValue('users')).", ".$this->_conn->quote($status).", ".$this->_conn->quote($doc->getFieldValue('path'))/*time()*/.")";
|
||||
$res = $this->_conn->exec($sql);
|
||||
if($res === false) {
|
||||
return 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 ".$this->_rawid."=".(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 string $query
|
||||
* @param array $limit array with elements 'limit' and 'offset'
|
||||
* @return boolean false in case of an error, otherwise array with elements
|
||||
* 'count', 'hits', 'facets'. 'hits' is an array of SeedDMS_SQLiteFTS_QueryHit
|
||||
*/
|
||||
public function find($query, $limit=array()) { /* {{{ */
|
||||
if(!$this->_conn)
|
||||
return false;
|
||||
|
||||
/* First count some records for facets */
|
||||
foreach(array('owner', 'mimetype', 'category') as $facetname) {
|
||||
$sql = "SELECT `".$facetname."`, count(*) AS `c` FROM `docs`";
|
||||
if($query)
|
||||
$sql .= " WHERE docs MATCH ".$this->_conn->quote($query);
|
||||
$res = $this->_conn->query($sql." GROUP BY `".$facetname."`");
|
||||
if(!$res)
|
||||
throw new SeedDMS_SQLiteFTS_Exception("Counting records in facet \"$facetname\" failed.");
|
||||
// return false;
|
||||
$facets[$facetname] = array();
|
||||
foreach($res as $row) {
|
||||
if($row[$facetname] && $row['c']) {
|
||||
if($facetname == 'category') {
|
||||
$tmp = explode(' ', $row[$facetname]);
|
||||
if(count($tmp) > 1) {
|
||||
foreach($tmp as $t) {
|
||||
if(!isset($facets[$facetname][$t]))
|
||||
$facets[$facetname][$t] = $row['c'];
|
||||
else
|
||||
$facets[$facetname][$t] += $row['c'];
|
||||
}
|
||||
} else {
|
||||
if(!isset($facets[$facetname][$row[$facetname]]))
|
||||
$facets[$facetname][$row[$facetname]] = $row['c'];
|
||||
else
|
||||
$facets[$facetname][$row[$facetname]] += $row['c'];
|
||||
}
|
||||
} else
|
||||
$facets[$facetname][$row[$facetname]] = $row['c'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$sql = "SELECT `record_type`, count(*) AS `c` FROM `docs`";
|
||||
if($query)
|
||||
$sql .= " WHERE docs MATCH ".$this->_conn->quote($query);
|
||||
$res = $this->_conn->query($sql." GROUP BY `record_type`");
|
||||
if(!$res)
|
||||
throw new SeedDMS_SQLiteFTS_Exception("Counting records in facet \"record_type\" failed.");
|
||||
// return false;
|
||||
$facets['record_type'] = array('document'=>0, 'folder'=>0);
|
||||
foreach($res as $row) {
|
||||
$facets['record_type'][$row['record_type']] = $row['c'];
|
||||
}
|
||||
$total = $facets['record_type']['document'] + $facets['record_type']['folder'];
|
||||
|
||||
$sql = "SELECT ".$this->_rawid.", documentid FROM docs";
|
||||
if($query)
|
||||
$sql .= " WHERE docs MATCH ".$this->_conn->quote($query);
|
||||
if($this->_ftstype == 'fts5')
|
||||
//$sql .= " ORDER BY rank";
|
||||
// boost documentid, title and comment
|
||||
$sql .= " ORDER BY bm25(docs, 10.0, 10.0, 10.0)";
|
||||
if(!empty($limit['limit']))
|
||||
$sql .= " LIMIT ".(int) $limit['limit'];
|
||||
if(!empty($limit['offset']))
|
||||
$sql .= " OFFSET ".(int) $limit['offset'];
|
||||
$res = $this->_conn->query($sql);
|
||||
if(!$res)
|
||||
throw new SeedDMS_SQLiteFTS_Exception("Searching for documents failed.");
|
||||
$hits = array();
|
||||
if($res) {
|
||||
foreach($res as $rec) {
|
||||
$hit = new SeedDMS_SQLiteFTS_QueryHit($this);
|
||||
$hit->id = $rec[$this->_rawid];
|
||||
$hit->documentid = $rec['documentid'];
|
||||
$hits[] = $hit;
|
||||
}
|
||||
}
|
||||
return array('count'=>$total, 'hits'=>$hits, 'facets'=>$facets);
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Get a single document from index
|
||||
*
|
||||
* @param string $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 ".$this->_rawid.", documentid FROM docs WHERE documentid=".$this->_conn->quote($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[$this->_rawid];
|
||||
$hit->documentid = $rec['documentid'];
|
||||
$hits[] = $hit;
|
||||
}
|
||||
}
|
||||
return $hits;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Get a single document from index
|
||||
*
|
||||
* @param integer $id id of index record
|
||||
* @return boolean false in case of an error, otherwise true
|
||||
*/
|
||||
public function getDocument($id, $content=true) { /* {{{ */
|
||||
if(!$this->_conn)
|
||||
return false;
|
||||
|
||||
$sql = "SELECT ".$this->_rawid.", documentid, title, comment, owner, keywords, category, mimetype, origfilename, created, users, status, path".($content ? ", content" : "")." FROM docs WHERE ".$this->_rawid."='".$id."'";
|
||||
$res = $this->_conn->query($sql);
|
||||
$doc = false;
|
||||
if($res) {
|
||||
if(!($rec = $res->fetch(PDO::FETCH_ASSOC)))
|
||||
return false;
|
||||
$doc = new SeedDMS_SQLiteFTS_Document();
|
||||
$doc->addField(SeedDMS_SQLiteFTS_Field::Keyword('docid', $rec[$this->_rawid]));
|
||||
$doc->addField(SeedDMS_SQLiteFTS_Field::Keyword('document_id', $rec['documentid']));
|
||||
$doc->addField(SeedDMS_SQLiteFTS_Field::Text('title', $rec['title']));
|
||||
$doc->addField(SeedDMS_SQLiteFTS_Field::Text('comment', $rec['comment']));
|
||||
$doc->addField(SeedDMS_SQLiteFTS_Field::Text('keywords', $rec['keywords']));
|
||||
$doc->addField(SeedDMS_SQLiteFTS_Field::Text('category', $rec['category']));
|
||||
$doc->addField(SeedDMS_SQLiteFTS_Field::Keyword('mimetype', $rec['mimetype']));
|
||||
$doc->addField(SeedDMS_SQLiteFTS_Field::Keyword('origfilename', $rec['origfilename']));
|
||||
$doc->addField(SeedDMS_SQLiteFTS_Field::Text('owner', $rec['owner']));
|
||||
$doc->addField(SeedDMS_SQLiteFTS_Field::Keyword('created', $rec['created']));
|
||||
$doc->addField(SeedDMS_SQLiteFTS_Field::Text('users', $rec['users']));
|
||||
$doc->addField(SeedDMS_SQLiteFTS_Field::Keyword('status', $rec['status']));
|
||||
$doc->addField(SeedDMS_SQLiteFTS_Field::Keyword('path', $rec['path']));
|
||||
if($content)
|
||||
$doc->addField(SeedDMS_SQLiteFTS_Field::UnStored('content', $rec['content']));
|
||||
}
|
||||
return $doc;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Return list of terms in index
|
||||
*
|
||||
* This function does nothing!
|
||||
*/
|
||||
public function terms() { /* {{{ */
|
||||
if(!$this->_conn)
|
||||
return false;
|
||||
|
||||
if($this->_ftstype == 'fts5')
|
||||
$sql = "SELECT term, col, doc as occurrences FROM docs_terms WHERE col!='*' ORDER BY col";
|
||||
else
|
||||
$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() { /* {{{ */
|
||||
} /* }}} */
|
||||
}
|
||||
?>
|
71
SeedDMS_SQLiteFTS/SQLiteFTS/QueryHit.php
Normal file
71
SeedDMS_SQLiteFTS/SQLiteFTS/QueryHit.php
Normal file
|
@ -0,0 +1,71 @@
|
|||
<?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 index document
|
||||
* @access public
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @var integer $id id of real document
|
||||
* @access public
|
||||
*/
|
||||
public $documentid;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
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;
|
||||
} /* }}} */
|
||||
}
|
||||
?>
|
154
SeedDMS_SQLiteFTS/SQLiteFTS/Search.php
Normal file
154
SeedDMS_SQLiteFTS/SQLiteFTS/Search.php
Normal file
|
@ -0,0 +1,154 @@
|
|||
<?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 document from index
|
||||
*
|
||||
* @param int $id id of seeddms document
|
||||
* @return object instance of SeedDMS_SQliteFTS_QueryHit or false
|
||||
*/
|
||||
function getDocument($id) { /* {{{ */
|
||||
$hits = $this->index->findById('D'.$id);
|
||||
return $hits ? $hits[0] : false;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Get folder from index
|
||||
*
|
||||
* @param int $id id of seeddms folder
|
||||
* @return object instance of SeedDMS_SQliteFTS_QueryHit or false
|
||||
*/
|
||||
function getFolder($id) { /* {{{ */
|
||||
$hits = $this->index->findById('F'.$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, $fields=array(), $limit=array()) { /* {{{ */
|
||||
$querystr = '';
|
||||
$term = trim($term);
|
||||
if($term) {
|
||||
$querystr = substr($term, -1) != '*' ? $term.'*' : $term;
|
||||
}
|
||||
if(!empty($fields['owner'])) {
|
||||
if(is_string($fields['owner'])) {
|
||||
if($querystr)
|
||||
$querystr .= ' AND ';
|
||||
$querystr .= 'owner:'.$fields['owner'];
|
||||
} elseif(is_array($fields['owner'])) {
|
||||
if($querystr)
|
||||
$querystr .= ' AND ';
|
||||
$querystr .= '(owner:';
|
||||
$querystr .= implode(' OR owner:', $fields['owner']);
|
||||
$querystr .= ')';
|
||||
}
|
||||
}
|
||||
if(!empty($fields['record_type'])) {
|
||||
if($querystr)
|
||||
$querystr .= ' AND ';
|
||||
$querystr .= '(record_type:';
|
||||
$querystr .= implode(' OR record_type:', $fields['record_type']);
|
||||
$querystr .= ')';
|
||||
}
|
||||
if(!empty($fields['category'])) {
|
||||
if($querystr)
|
||||
$querystr .= ' AND ';
|
||||
$querystr .= '(category:"';
|
||||
$querystr .= implode('" AND category:"', $fields['category']);
|
||||
$querystr .= '")';
|
||||
}
|
||||
if(!empty($fields['mimetype'])) {
|
||||
if($querystr)
|
||||
$querystr .= ' AND ';
|
||||
$querystr .= '(mimetype:"';
|
||||
$querystr .= implode('" OR mimetype:"', $fields['mimetype']);
|
||||
$querystr .= '")';
|
||||
}
|
||||
if(!empty($fields['status'])) {
|
||||
if($querystr)
|
||||
$querystr .= ' AND ';
|
||||
$status = array_map(function($v){return (int)$v+10;}, $fields['status']);
|
||||
$querystr .= '(status:';
|
||||
$querystr .= implode(' OR status:', $status);
|
||||
$querystr .= ')';
|
||||
}
|
||||
if(!empty($fields['user'])) {
|
||||
if($querystr)
|
||||
$querystr .= ' AND ';
|
||||
$querystr .= '(users:';
|
||||
$querystr .= implode(' OR users:', $fields['user']);
|
||||
$querystr .= ')';
|
||||
}
|
||||
if(!empty($fields['rootFolder']) && $fields['rootFolder']->getFolderList()) {
|
||||
if($querystr)
|
||||
$querystr .= ' AND ';
|
||||
$querystr .= '(path:';
|
||||
$querystr .= str_replace(':', 'x', $fields['rootFolder']->getFolderList().$fields['rootFolder']->getID().':');
|
||||
$querystr .= ')';
|
||||
}
|
||||
if(!empty($fields['startFolder']) && $fields['startFolder']->getFolderList()) {
|
||||
if($querystr)
|
||||
$querystr .= ' AND ';
|
||||
$querystr .= '(path:';
|
||||
$querystr .= str_replace(':', 'x', $fields['startFolder']->getFolderList().$fields['startFolder']->getID().':');
|
||||
$querystr .= ')';
|
||||
}
|
||||
try {
|
||||
$result = $this->index->find($querystr, $limit);
|
||||
$recs = array();
|
||||
foreach($result["hits"] as $hit) {
|
||||
$recs[] = array('id'=>$hit->id, 'document_id'=>$hit->documentid);
|
||||
}
|
||||
return array('count'=>$result['count'], 'hits'=>$recs, 'facets'=>$result['facets']);
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
} /* }}} */
|
||||
}
|
||||
?>
|
74
SeedDMS_SQLiteFTS/SQLiteFTS/Term.php
Normal file
74
SeedDMS_SQLiteFTS/SQLiteFTS/Term.php
Normal file
|
@ -0,0 +1,74 @@
|
|||
<?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 => 'documentid',
|
||||
1 => 'title',
|
||||
2 => 'comment',
|
||||
3 => 'keywords',
|
||||
4 => 'category',
|
||||
5 => 'mimetype',
|
||||
6 => 'origfilename',
|
||||
7 => 'owner',
|
||||
8 => 'content',
|
||||
9 => 'created',
|
||||
10 => 'user',
|
||||
11 => 'status',
|
||||
12 => 'path'
|
||||
);
|
||||
/* fts5 pass the column name in $col, fts4 uses an integer */
|
||||
if(is_int($col))
|
||||
$this->field = $fields[$col];
|
||||
else
|
||||
$this->field = $col; //$fields[$col];
|
||||
$this->_occurrence = $occurrence;
|
||||
} /* }}} */
|
||||
|
||||
}
|
||||
?>
|
356
SeedDMS_SQLiteFTS/package.xml
Normal file
356
SeedDMS_SQLiteFTS/package.xml
Normal file
|
@ -0,0 +1,356 @@
|
|||
<?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>2022-03-04</date>
|
||||
<time>08:57:44</time>
|
||||
<version>
|
||||
<release>1.0.17</release>
|
||||
<api>1.0.17</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
- throw exeption in find() instead of returning false
|
||||
</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>
|
||||
<file name="Field.php" role="php">
|
||||
<tasks:replace from="@package_version@" to="version" type="package-info" />
|
||||
</file>
|
||||
<file name="Exception.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>
|
||||
<release>
|
||||
<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>
|
||||
</release>
|
||||
<release>
|
||||
<date>2016-03-29</date>
|
||||
<time>08:09:48</time>
|
||||
<version>
|
||||
<release>1.0.5</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>
|
||||
set last parameter of stream_select() to 200000 micro sec. in case the timeout in sec. is set to 0
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2016-03-29</date>
|
||||
<time>08:09:48</time>
|
||||
<version>
|
||||
<release>1.0.6</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>
|
||||
fix calculation of timeout (see bug #269)
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2017-03-01</date>
|
||||
<time>15:53:24</time>
|
||||
<version>
|
||||
<release>1.0.7</release>
|
||||
<api>1.0.7</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
catch exception in execWithTimeout()
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2017-12-04</date>
|
||||
<time>11:00:40</time>
|
||||
<version>
|
||||
<release>1.0.8</release>
|
||||
<api>1.0.8</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
allow conversion commands for mimetypes with wildcards
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2018-01-30</date>
|
||||
<time>11:00:40</time>
|
||||
<version>
|
||||
<release>1.0.9</release>
|
||||
<api>1.0.9</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
execWithTimeout() reads data from stderr and saves it into error msg
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2018-04-11</date>
|
||||
<time>11:00:40</time>
|
||||
<version>
|
||||
<release>1.0.10</release>
|
||||
<api>1.0.10</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
IndexedDocument() remembers cmd and mimetype
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2019-11-28</date>
|
||||
<time>11:00:40</time>
|
||||
<version>
|
||||
<release>1.0.11</release>
|
||||
<api>1.0.11</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
Set 'created' in index to creation date of indexed content (was set to current
|
||||
timestamp)
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2020-09-02</date>
|
||||
<time>08:57:44</time>
|
||||
<version>
|
||||
<release>1.0.12</release>
|
||||
<api>1.0.12</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
Index users with at least read access on a document
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2020-09-02</date>
|
||||
<time>08:57:44</time>
|
||||
<version>
|
||||
<release>1.0.13</release>
|
||||
<api>1.0.13</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
add user to list of terms
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2020-09-11</date>
|
||||
<time>08:57:44</time>
|
||||
<version>
|
||||
<release>1.0.14</release>
|
||||
<api>1.0.14</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
- add searching for document status
|
||||
- search even if query is empty (will find all documents)
|
||||
- parameters for SeedDMS_SQLiteFTS_Search::search() has changed
|
||||
- SeedDMS_Lucene_Search::search() returns array of hits, count and facets
|
||||
- pass config array instead of index directory to SeedDMS_Lucene_Indexer::create()
|
||||
and SeedDMS_Lucene_Indexer::open()
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2020-12-12</date>
|
||||
<time>08:57:44</time>
|
||||
<version>
|
||||
<release>1.0.15</release>
|
||||
<api>1.0.15</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
- add indexing folders
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<date>2021-05-10</date>
|
||||
<time>08:57:44</time>
|
||||
<version>
|
||||
<release>1.0.16</release>
|
||||
<api>1.0.16</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
|
||||
<notes>
|
||||
- close pipes in execWithTimeout(), also return exit code of command
|
||||
- add support for fts5 (make it the default)
|
||||
- add class SeedDMS_SQLiteFTS_Field
|
||||
</notes>
|
||||
</release>
|
||||
</changelog>
|
||||
</package>
|
0
SeedDMS_SQLiteFTS/tests/Index.php
Normal file
0
SeedDMS_SQLiteFTS/tests/Index.php
Normal file
5
TODO
5
TODO
|
@ -1,6 +1,3 @@
|
|||
This list is hopelessly outdated, but some of the issues are
|
||||
still worth to be implemented!
|
||||
|
||||
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
|
||||
|
@ -28,6 +25,8 @@ approaches to get the configuration directory.
|
|||
|
||||
Show expiration status of documents in document list
|
||||
|
||||
Copy folders recursivly
|
||||
|
||||
Allow operations like delete, move, approve, etc. on a list of documents
|
||||
|
||||
installation script:
|
||||
|
|
25
build.xml
25
build.xml
|
@ -16,7 +16,7 @@
|
|||
<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_version" value="2.1.6" />
|
||||
<property name="composer_extra_params" value="" />
|
||||
<property name="composer_env" value="" />
|
||||
<property name="mink_driver" value="chrome" />
|
||||
|
@ -63,7 +63,7 @@
|
|||
|
||||
<!-- 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}/SeedDMS_Core" command="XDEBUG_MODE=coverage ${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>
|
||||
|
||||
|
@ -73,13 +73,8 @@
|
|||
<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>
|
||||
<httpget url="https://getcomposer.org/download/${composer_version}/composer.phar" sslVerifyPeer="false" dir="${srcdir}" />
|
||||
</else>
|
||||
</if>
|
||||
<echo message="Installing dependencies..." />
|
||||
|
@ -156,7 +151,7 @@
|
|||
<copy todir="${builddir}/export/${shortversion}/www/ext/example">
|
||||
<fileset dir="${srcdir}/ext/example" defaultexcludes="false" />
|
||||
</copy>
|
||||
<!-- copy todir="${builddir}/export/${shortversion}/pear/SeedDMS">
|
||||
<copy todir="${builddir}/export/${shortversion}/pear/SeedDMS">
|
||||
<fileset dir="SeedDMS_Core">
|
||||
<include name="Core/**" />
|
||||
<include name="Core.php" />
|
||||
|
@ -168,13 +163,13 @@
|
|||
<fileset dir="SeedDMS_Lucene">
|
||||
<include name="Lucene/**" />
|
||||
<include name="Lucene.php" />
|
||||
</fileset -->
|
||||
<!-- fileset dir="SeedDMS_SQLiteFTS">
|
||||
</fileset>
|
||||
<fileset dir="SeedDMS_SQLiteFTS">
|
||||
<include name="SQLiteFTS/**" />
|
||||
<include name="SQLiteFTS.php" />
|
||||
</fileset>
|
||||
</copy -->
|
||||
<!-- copy todir="${builddir}/export/${shortversion}/pear">
|
||||
</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" />
|
||||
|
@ -184,7 +179,7 @@
|
|||
<fileset dir="../seeddms-ext/http_webdav_server">
|
||||
<include name="Tools/**" />
|
||||
</fileset>
|
||||
</copy -->
|
||||
</copy>
|
||||
<copy tofile="${builddir}/export/${shortversion}/pear/composer.json" file="composer-dist.json">
|
||||
</copy>
|
||||
<phingcall target="composer">
|
||||
|
|
|
@ -1,76 +1,22 @@
|
|||
{
|
||||
"config": {
|
||||
"platform": {
|
||||
"php": "8.2"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"robthree/twofactorauth": "^1.5",
|
||||
"slim/slim": "^4.0",
|
||||
"guzzlehttp/psr7": "*",
|
||||
"sabre/dav": "^3.",
|
||||
"sabre/xml": "^1.4.",
|
||||
"slim/slim": "^3.0",
|
||||
"erusev/parsedown": "*",
|
||||
"erusev/parsedown-extra": "*",
|
||||
"mibe/feedwriter": "^1.1",
|
||||
"phpoffice/phpexcel": "^1.8",
|
||||
"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
|
||||
}
|
||||
}
|
||||
]
|
||||
"dragonmantank/cron-expression": "^2.2",
|
||||
"zf1/zend-search-lucene": "*"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
footNote = "SeedDMS free document management system - www.seeddms.org"
|
||||
printDisclaimer = "true"
|
||||
language = "en_GB"
|
||||
theme = "bootstrap4"
|
||||
theme = "bootstrap"
|
||||
previewWidthList = "40"
|
||||
previewWidthDetail = "100"
|
||||
onePageMode="true"
|
||||
|
@ -57,11 +57,11 @@
|
|||
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"
|
||||
|
@ -112,7 +112,6 @@
|
|||
dropFolderDir = ""
|
||||
cacheDir = ""
|
||||
backupDir = ""
|
||||
logFileMaxLevel="6"
|
||||
/>
|
||||
<!--
|
||||
- enableGuestLogin: If you want anybody to login as guest, set the following line to true
|
||||
|
@ -121,7 +120,6 @@
|
|||
- 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
|
||||
|
@ -139,7 +137,6 @@
|
|||
restricted = "true"
|
||||
enableUserImage = "false"
|
||||
disableSelfEdit = "false"
|
||||
disableChangePassword = "false"
|
||||
passwordStrength = "0"
|
||||
passwordStrengthAlgorithm = "simple"
|
||||
passwordExpiration = "0"
|
||||
|
@ -171,7 +168,6 @@
|
|||
bindDN = ""
|
||||
bindPw = ""
|
||||
filter = ""
|
||||
groupField = ""
|
||||
/>
|
||||
<!-- ***** CONNECTOR Microsoft Active Directory *****
|
||||
- enable: enable/disable connector
|
||||
|
@ -193,8 +189,6 @@
|
|||
accountDomainName = "example.com"
|
||||
bindDN = ""
|
||||
bindPw = ""
|
||||
filter = ""
|
||||
groupField = ""
|
||||
/>
|
||||
</connectors>
|
||||
</authentication>
|
||||
|
@ -309,15 +303,21 @@
|
|||
enableNotificationWorkflow = "false"
|
||||
/>
|
||||
<converters target="fulltext">
|
||||
<converter mimeType="application/pdf">pdftotext -nopgbrk %s -</converter>
|
||||
<converter mimeType="application/pdf">pdftotext -nopgbrk %s - | sed -e 's/ [a-zA-Z0-9.]\{1\} / /g' -e 's/[0-9.]//g'</converter>
|
||||
<converter mimeType="application/msword">catdoc %s</converter>
|
||||
<converter mimeType="application/vnd.ms-excel">ssconvert -T Gnumeric_stf:stf_csv -S %s fd://1</converter>
|
||||
<converter mimeType="audio/mp3">id3 -l -R %s | egrep '(Title|Artist|Album)' | sed 's/^[^:]*: //g'</converter>
|
||||
<converter mimeType="audio/mpeg">id3 -l -R %s | egrep '(Title|Artist|Album)' | sed 's/^[^:]*: //g'</converter>
|
||||
<converter mimeType="text/plain">cat %s</converter>
|
||||
<converter mimeType="text/html">html2text %s</converter>
|
||||
<converter mimeType="application/vnd.openxmlformats-officedocument.wordprocessingml.document">docx2txt %s -</converter>
|
||||
</converters>
|
||||
<converters target="preview">
|
||||
<converter mimeType="application/msword">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:- '%o'</converter>
|
||||
<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>
|
||||
<converter mimeType="text/plain">a2ps -1 -a1 -R -B -o - '%f' | gs -dBATCH -dNOPAUSE -sDEVICE=pngalpha -dFirstPage=1 -dLastPage=1 -dPDFFitPage -r72x72 -sOutputFile=- -q - | convert -resize %wx png:- '%o'</converter>
|
||||
</converters>
|
||||
</advanced>
|
||||
<extensions>
|
||||
|
|
|
@ -56,43 +56,16 @@ class SeedDMS_Controller_AddDocument extends SeedDMS_Controller_Common {
|
|||
$reqversion = $this->getParam('reqversion');
|
||||
$version_comment = $this->getParam('versioncomment');
|
||||
$attributes = $this->getParam('attributes');
|
||||
foreach($attributes as $attrdefid=>&$attribute) {
|
||||
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);
|
||||
$attribute = date('Y-m-d', makeTsFromDate($attribute));
|
||||
break;
|
||||
}
|
||||
if(!$attrdef->validate($attribute, null, true)) {
|
||||
if(!$attrdef->validate($attribute)) {
|
||||
$this->errormsg = getAttributeValidationError($attrdef->getValidationError(), $attrdef->getName(), $attribute);
|
||||
return false;
|
||||
}
|
||||
|
@ -107,49 +80,19 @@ class SeedDMS_Controller_AddDocument extends SeedDMS_Controller_Common {
|
|||
}
|
||||
}
|
||||
if($attributes_version = $this->getParam('attributesversion')) {
|
||||
foreach($attributes_version as $attrdefid=>&$attribute) {
|
||||
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);
|
||||
$attribute = date('Y-m-d', makeTsFromDate($attribute));
|
||||
break;
|
||||
}
|
||||
if(!$attrdef->validate($attribute, null, true)) {
|
||||
if(!$attrdef->validate($attribute)) {
|
||||
$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)
|
||||
|
|
|
@ -41,43 +41,11 @@ class SeedDMS_Controller_AddSubFolder extends SeedDMS_Controller_Common {
|
|||
$comment = $this->getParam('comment');
|
||||
$sequence = $this->getParam('sequence');
|
||||
$attributes = $this->getParam('attributes');
|
||||
foreach($attributes as $attrdefid=>&$attribute) {
|
||||
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)) {
|
||||
if(!$attrdef->validate($attribute)) {
|
||||
$this->errormsg = getAttributeValidationError($attrdef->getValidationError(), $attrdef->getName(), $attribute);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -7,38 +7,36 @@
|
|||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2023 Uwe Steinmann
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class which does the busines logic for approving a document
|
||||
* Class which does the busines logic for downloading a document
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2023 Uwe Steinmann
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Controller_ApproveDocument extends SeedDMS_Controller_Common {
|
||||
|
||||
public $oldstatus;
|
||||
|
||||
public $newstatus;
|
||||
|
||||
public function run() { /* {{{ */
|
||||
public function run() {
|
||||
$dms = $this->params['dms'];
|
||||
$user = $this->params['user'];
|
||||
$settings = $this->params['settings'];
|
||||
$document = $this->params['document'];
|
||||
$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;
|
||||
$approvalstatus = $this->params['approvalstatus'];
|
||||
$approvaltype = $this->params['approvaltype'];
|
||||
$group = $this->params['group'];
|
||||
$comment = $this->params['comment'];
|
||||
$file = $this->params['file'];
|
||||
|
||||
/* Get the document id and name before removing the document */
|
||||
$docname = $document->getName();
|
||||
$documentid = $document->getID();
|
||||
|
||||
if(!$this->callHook('preApproveDocument', $content)) {
|
||||
}
|
||||
|
@ -46,35 +44,36 @@ class SeedDMS_Controller_ApproveDocument extends SeedDMS_Controller_Common {
|
|||
$result = $this->callHook('approveDocument', $content);
|
||||
if($result === null) {
|
||||
if ($approvaltype == "ind") {
|
||||
$approvalLogID = $content->setApprovalByInd($user, $user, $approvalstatus, $approvalcomment, $approvalfile);
|
||||
$approvalLogID = $content->setApprovalByInd($user, $user, $approvalstatus, $comment, $file);
|
||||
if($approvalLogID === false || 0 > $approvalLogID) {
|
||||
$this->error = 1;
|
||||
$this->errormsg = "approval_update_failed";
|
||||
return false;
|
||||
}
|
||||
} 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;
|
||||
$approvalLogID = $content->setApprovalByGrp($group, $user, $approvalstatus, $comment, $file);
|
||||
if($approvalLogID === false || 0 > $approvalLogID) {
|
||||
$this->error = 1;
|
||||
$this->errormsg = "approval_update_failed";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check to see if the overall status for the document version needs to be
|
||||
* updated.
|
||||
*/
|
||||
$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);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* If document was rejected, set the document status to S_REJECTED right away */
|
||||
if ($approvalstatus == -1){
|
||||
if($content->setStatus(S_REJECTED,$comment,$user)) {
|
||||
$this->callHook('postApproveDocument', $content, S_REJECTED);
|
||||
}
|
||||
} else {
|
||||
$docApprovalStatus = $content->getApprovalStatus();
|
||||
if (is_bool($docApprovalStatus) && !$docApprovalStatus) {
|
||||
$this->error = 1;
|
||||
$this->errormsg = "cannot_retrieve_approval_snapshot";
|
||||
return false;
|
||||
}
|
||||
|
@ -92,15 +91,8 @@ class SeedDMS_Controller_ApproveDocument extends SeedDMS_Controller_Common {
|
|||
// 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($content->setStatus(S_RELEASED, getMLText("automatic_status_update"), $user)) {
|
||||
$this->callHook('postApproveDocument', $content, S_RELEASED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -110,6 +102,6 @@ class SeedDMS_Controller_ApproveDocument extends SeedDMS_Controller_Common {
|
|||
}
|
||||
|
||||
return true;
|
||||
} /* }}} */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
} /* }}} */
|
||||
}
|
||||
|
||||
|
|
@ -29,24 +29,14 @@ class SeedDMS_Controller_ClearCache extends SeedDMS_Controller_Common {
|
|||
$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]*';
|
||||
if(!empty($post['preview'])) {
|
||||
$cmd = 'rm -rf '.$settings->_cacheDir.'/[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.'*')));
|
||||
$cmd = 'rm -rf '.$settings->_cacheDir.'/js/*';
|
||||
system($cmd, $ret);
|
||||
}
|
||||
|
||||
if(false === $this->callHook('clear', $post)) {
|
||||
|
|
|
@ -26,9 +26,7 @@ class SeedDMS_Controller_Cron extends SeedDMS_Controller_Common {
|
|||
$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);
|
||||
|
@ -36,8 +34,6 @@ class SeedDMS_Controller_Cron extends SeedDMS_Controller_Common {
|
|||
|
||||
$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(),
|
||||
|
|
|
@ -30,180 +30,119 @@ class SeedDMS_Controller_DocumentAccess extends SeedDMS_Controller_Common {
|
|||
$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)) {
|
||||
// Change owner -----------------------------------------------------------
|
||||
if ($action == "setowner") {
|
||||
if(false === $this->callHook('preSetOwner', $document)) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_postSetOwner_failed';
|
||||
$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;
|
||||
}
|
||||
}
|
||||
} elseif ($action == "notinherit") {
|
||||
if(false === $this->callHook('preSetNotInherit', $document)) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_preSetNotInherit_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'];
|
||||
/* 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(false === $this->callHook('preSetNotInherit', $document)) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_preSetNotInherit_failed';
|
||||
return null;
|
||||
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;
|
||||
}
|
||||
} elseif ($action == "inherit") {
|
||||
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;
|
||||
}
|
||||
} elseif ($action == "setdefault") {
|
||||
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;
|
||||
}
|
||||
} elseif ($action == "editaccess") {
|
||||
$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);
|
||||
}
|
||||
} elseif ($action == "delaccess") {
|
||||
$userid = $this->params['userid'];
|
||||
$groupid = $this->params['groupid'];
|
||||
if ($userid) {
|
||||
$document->removeAccess($userid, true);
|
||||
}
|
||||
elseif ($groupid) {
|
||||
$document->removeAccess($groupid, false);
|
||||
}
|
||||
} elseif ($action == "addaccess") {
|
||||
$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);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -122,37 +122,10 @@ class SeedDMS_Controller_EditDocument extends SeedDMS_Controller_Common {
|
|||
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);
|
||||
$attribute = date('Y-m-d', makeTsFromDate($attribute));
|
||||
break;
|
||||
}
|
||||
if(!$attrdef->validate($attribute, $document, false)) {
|
||||
if(!$attrdef->validate($attribute, $document, true)) {
|
||||
$this->errormsg = getAttributeValidationError($attrdef->getValidationError(), $attrdef->getName(), $attribute);
|
||||
return false;
|
||||
}
|
||||
|
@ -189,10 +162,6 @@ class SeedDMS_Controller_EditDocument 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()) && $document) {
|
||||
$idoc = $fulltextservice->IndexedDocument($document);
|
||||
if(false !== $this->callHook('preIndexDocument', $document, $idoc)) {
|
||||
|
@ -204,7 +173,6 @@ class SeedDMS_Controller_EditDocument extends SeedDMS_Controller_Common {
|
|||
$index->commit();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
} elseif($result === false) {
|
||||
if(empty($this->errormsg))
|
||||
|
|
|
@ -51,61 +51,27 @@ class SeedDMS_Controller_EditFolder extends SeedDMS_Controller_Common {
|
|||
$oldattributes = $folder->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, $folder, false)) {
|
||||
$this->errormsg = getAttributeValidationText($attrdef->getValidationError(), $attrdef->getName(), $attribute);
|
||||
return false;
|
||||
}
|
||||
$attrdef = $dms->getAttributeDefinition($attrdefid);
|
||||
if(null === ($ret = $this->callHook('validateAttribute', $attrdef, $attribute))) {
|
||||
if($attribute) {
|
||||
if(!$attrdef->validate($attribute, $folder, true)) {
|
||||
$this->errormsg = getAttributeValidationText($attrdef->getValidationError(), $attrdef->getName(), $attribute);
|
||||
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)
|
||||
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()));
|
||||
} elseif(isset($oldattributes[$attrdefid])) {
|
||||
if(!$folder->removeAttribute($dms->getAttributeDefinition($attrdefid)))
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if($ret === false)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -124,10 +90,6 @@ 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)) {
|
||||
|
@ -139,7 +101,6 @@ class SeedDMS_Controller_EditFolder extends SeedDMS_Controller_Common {
|
|||
$index->commit();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
} elseif($result === false) {
|
||||
if(empty($this->errormsg))
|
||||
|
|
|
@ -22,63 +22,41 @@
|
|||
*/
|
||||
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() { /* {{{ */
|
||||
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('preEmptyFolder')) {
|
||||
if(empty($this->errormsg))
|
||||
$this->errormsg = 'hook_preEmptyFolder_failed';
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
$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 a callback which removes each document from the fulltext index
|
||||
* The callback must return null other the removal will be canceled.
|
||||
*/
|
||||
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();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/* 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($index)
|
||||
$dms->setCallback('onPreEmptyDocument', 'removeFromIndex', array($index, $indexconf));
|
||||
|
||||
if (!$folder->emptyFolder()) {
|
||||
$this->errormsg = 'error_occured';
|
||||
|
@ -94,5 +72,5 @@ class SeedDMS_Controller_EmptyFolder extends SeedDMS_Controller_Common {
|
|||
}
|
||||
|
||||
return true;
|
||||
} /* }}} */
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,12 +31,95 @@ class SeedDMS_Controller_Login extends SeedDMS_Controller_Common {
|
|||
return self::$user;
|
||||
} /* }}} */
|
||||
|
||||
public function _finalize($user) { /* {{{ */
|
||||
public function run() { /* {{{ */
|
||||
$dms = $this->params['dms'];
|
||||
$settings = $this->params['settings'];
|
||||
$session = $this->params['session'];
|
||||
$sesstheme = $this->params['sesstheme'];
|
||||
$source = isset($this->params['source']) ? $this->params['source'] : '';
|
||||
$referuri = $this->params['referuri'];
|
||||
$lang = $this->params['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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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');
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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)) {
|
||||
$this->callHook('loginFailed');
|
||||
$this->setErrorMsg("login_error_text");
|
||||
return false;
|
||||
}
|
||||
|
||||
self::$user = $user;
|
||||
|
||||
|
@ -84,78 +167,73 @@ class SeedDMS_Controller_Login extends SeedDMS_Controller_Common {
|
|||
/* 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) {
|
||||
// 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);
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
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)) {
|
||||
// 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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
// 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)) {
|
||||
|
@ -163,114 +241,4 @@ class SeedDMS_Controller_Login extends SeedDMS_Controller_Common {
|
|||
|
||||
return true;
|
||||
} /* }}} */
|
||||
|
||||
public function run() { /* {{{ */
|
||||
$dms = $this->params['dms'];
|
||||
$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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
} /* }}} */
|
||||
}
|
||||
|
|
|
@ -22,93 +22,96 @@
|
|||
*/
|
||||
class SeedDMS_Controller_Preview extends SeedDMS_Controller_Common {
|
||||
|
||||
public function version() { /* {{{ */
|
||||
public function run() {
|
||||
global $theme;
|
||||
$dms = $this->params['dms'];
|
||||
$type = $this->params['type'];
|
||||
$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);
|
||||
switch($type) {
|
||||
case "version":
|
||||
$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(!$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 (!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)) {
|
||||
header('Content-Type: image/svg+xml');
|
||||
readfile('../views/'.$theme.'/images/empty.svg');
|
||||
exit;
|
||||
}
|
||||
header('Content-Type: image/png');
|
||||
$previewer->getPreview($content);
|
||||
}
|
||||
break;
|
||||
case "file":
|
||||
$object = $this->params['object'];
|
||||
$document = $this->params['document'];
|
||||
$width = $this->params['width'];
|
||||
if (!is_object($object)) {
|
||||
$this->errormsg = 'invalid_version';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(!$previewer->hasPreview($object)) {
|
||||
return false;
|
||||
}
|
||||
header('Content-Type: image/png');
|
||||
$previewer->getPreview($object);
|
||||
return true;
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
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)) {
|
||||
header('Content-Type: image/svg+xml');
|
||||
readfile('../views/'.$theme.'/images/empty.svg');
|
||||
exit;
|
||||
}
|
||||
header('Content-Type: image/png');
|
||||
$previewer->getPreview($object);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ class SeedDMS_Controller_RemoveDocument extends SeedDMS_Controller_Common {
|
|||
|
||||
$result = $this->callHook('removeDocument', $document);
|
||||
if($result === null) {
|
||||
require_once("SeedDMS/Preview.php");
|
||||
$previewer = new SeedDMS_Preview_Previewer($settings->_cacheDir);
|
||||
$previewer->deleteDocumentPreviews($document);
|
||||
if (!$document->remove()) {
|
||||
|
|
|
@ -22,17 +22,17 @@
|
|||
*/
|
||||
class SeedDMS_Controller_RemoveFolder extends SeedDMS_Controller_Common {
|
||||
|
||||
/* Register a callback which removes each document/folder from the fulltext index
|
||||
/* Register a callback which removes each document from the fulltext index
|
||||
* The callback must return null otherwise the removal will be canceled.
|
||||
*/
|
||||
static function removeFromIndex($arr, $object) { /* {{{ */
|
||||
static function removeFromIndex($arr, $document) { /* {{{ */
|
||||
$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($document->isType('document'))
|
||||
$hit = $lucenesearch->getDocument($document->getID());
|
||||
elseif($document->isType('folder'))
|
||||
$hit = $lucenesearch->getFolder($document->getID());
|
||||
if($hit) {
|
||||
$index = $fulltextservice->Indexer();
|
||||
$index->delete($hit->id);
|
||||
|
@ -55,7 +55,7 @@ class SeedDMS_Controller_RemoveFolder extends SeedDMS_Controller_Common {
|
|||
$folder = $this->params['folder'];
|
||||
$fulltextservice = $this->params['fulltextservice'];
|
||||
|
||||
/* 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();
|
||||
|
||||
|
@ -77,6 +77,7 @@ class SeedDMS_Controller_RemoveFolder extends SeedDMS_Controller_Common {
|
|||
}
|
||||
|
||||
/* Register another callback which removes the preview images of the document */
|
||||
require_once("SeedDMS/Preview.php");
|
||||
$previewer = new SeedDMS_Preview_Previewer($settings->_cacheDir);
|
||||
$dms->addCallback('onPreRemoveDocument', 'SeedDMS_Controller_RemoveFolder::removePreviews', array($previewer));
|
||||
|
||||
|
|
|
@ -7,70 +7,72 @@
|
|||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2023 Uwe Steinmann
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class which does the busines logic for reviewing a document
|
||||
* Class which does the busines logic for downloading a document
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2010-2023 Uwe Steinmann
|
||||
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_Controller_ReviewDocument extends SeedDMS_Controller_Common {
|
||||
|
||||
public function run() { /* {{{ */
|
||||
public function run() {
|
||||
$dms = $this->params['dms'];
|
||||
$user = $this->params['user'];
|
||||
$settings = $this->params['settings'];
|
||||
$document = $this->params['document'];
|
||||
$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;
|
||||
$reviewstatus = $this->params['reviewstatus'];
|
||||
$reviewtype = $this->params['reviewtype'];
|
||||
$group = $this->params['group'];
|
||||
$comment = $this->params['comment'];
|
||||
$file = $this->params['file'];
|
||||
|
||||
/* Get the document id and name before removing the document */
|
||||
$docname = $document->getName();
|
||||
$documentid = $document->getID();
|
||||
|
||||
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;
|
||||
$reviewLogID > $content->setReviewByInd($user, $user, $reviewstatus, $comment, $file);
|
||||
if($reviewLogID === false || 0 > $reviewLogID) {
|
||||
$this->error = 1;
|
||||
$this->errormsg = "review_update_failed";
|
||||
return false;
|
||||
}
|
||||
} elseif ($reviewtype == "grp") {
|
||||
$reviewLogID = $content->setReviewByGrp($group, $user, $reviewstatus, $comment, $file);
|
||||
if($reviewLogID === false || 0 > $reviewLogID) {
|
||||
$this->error = 1;
|
||||
$this->errormsg = "review_update_failed";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check to see if the overall status for the document version needs to be
|
||||
* updated.
|
||||
*/
|
||||
$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);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($reviewstatus == -1){
|
||||
if($content->setStatus(S_REJECTED,$comment,$user)) {
|
||||
}
|
||||
} else {
|
||||
$docReviewStatus = $content->getReviewStatus();
|
||||
if (is_bool($docReviewStatus) && !$docReviewStatus) {
|
||||
$this->error = 1;
|
||||
$this->errormsg = "cannot_retrieve_review_snapshot";
|
||||
return false;
|
||||
}
|
||||
|
@ -89,35 +91,32 @@ class SeedDMS_Controller_ReviewDocument extends SeedDMS_Controller_Common {
|
|||
if ($reviewCT == $reviewTotal) {
|
||||
$docApprovalStatus = $content->getApprovalStatus();
|
||||
if (is_bool($docApprovalStatus) && !$docApprovalStatus) {
|
||||
$this->error = 1;
|
||||
$this->errormsg = "cannot_retrieve_approval_snapshot";
|
||||
return false;
|
||||
}
|
||||
$approvalCT = 0;
|
||||
$approvalTotal = 0;
|
||||
foreach($docApprovalStatus as $dastat) {
|
||||
if($dastat["status"] == 1) {
|
||||
foreach ($docApprovalStatus as $dastat) {
|
||||
if ($dastat["status"] == 1) {
|
||||
$approvalCT++;
|
||||
}
|
||||
if($dastat["status"] != -2) {
|
||||
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 ($approvalCT<$approvalTotal) {
|
||||
$newStatus=S_DRAFT_APP;
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Otherwise, change the status to released.
|
||||
$newStatus=S_RELEASED;
|
||||
}
|
||||
if ($content->setStatus($newStatus, getMLText("automatic_status_update"), $user)) {
|
||||
// Send notification to subscribers.
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -127,5 +126,6 @@ class SeedDMS_Controller_ReviewDocument extends SeedDMS_Controller_Common {
|
|||
}
|
||||
|
||||
return true;
|
||||
} /* }}} */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,10 +22,6 @@
|
|||
*/
|
||||
class SeedDMS_Controller_ReviseDocument extends SeedDMS_Controller_Common {
|
||||
|
||||
public $oldstatus;
|
||||
|
||||
public $newstatus;
|
||||
|
||||
public function run() {
|
||||
$dms = $this->params['dms'];
|
||||
$user = $this->params['user'];
|
||||
|
@ -36,9 +32,6 @@ class SeedDMS_Controller_ReviseDocument extends SeedDMS_Controller_Common {
|
|||
$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
|
||||
|
@ -78,7 +71,6 @@ class SeedDMS_Controller_ReviseDocument extends SeedDMS_Controller_Common {
|
|||
$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";
|
||||
|
@ -110,22 +102,22 @@ class SeedDMS_Controller_ReviseDocument extends SeedDMS_Controller_Common {
|
|||
// 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"))) {
|
||||
$newStatus=S_RELEASED;
|
||||
if ($content->finishRevision($user, $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)) {
|
||||
$newStatus=S_NEEDS_CORRECTION;
|
||||
// if ($content->finishRevision($user, $newStatus, 'Finished revision workflow', getMLText("automatic_status_update"))) {
|
||||
if(!$content->setStatus($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)) {
|
||||
$newStatus=S_IN_REVISION;
|
||||
if(!$content->setStatus($newStatus,$comment,$user)) {
|
||||
$this->error = 1;
|
||||
$this->errormsg = "revision_update_failed";
|
||||
return false;
|
||||
|
|
|
@ -59,7 +59,7 @@ class SeedDMS_Controller_UpdateDocument extends SeedDMS_Controller_Common {
|
|||
$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($contentResult=$document->addContent($comment, $user, $userfiletmp, utf8_basename($userfilename), $filetype, $userfiletype, $reviewers, $approvers, $version=0, $attributes, $workflow, $initialdocumentstatus)) {
|
||||
|
||||
if ($this->hasParam('expires')) {
|
||||
if($document->setExpires($this->getParam('expires'))) {
|
||||
|
|
|
@ -49,19 +49,16 @@ class SeedDMS_Controller_ViewOnline extends SeedDMS_Controller_Common {
|
|||
*/
|
||||
$this->params['content'] = $content;
|
||||
if(null === $this->callHook('version')) {
|
||||
if(file_exists($dms->contentDir . $content->getPath())) {
|
||||
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("Cache-Control: must-revalidate");
|
||||
header("ETag: ".$content->getChecksum());
|
||||
|
||||
sendFile($dms->contentDir.$content->getPath());
|
||||
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("Cache-Control: must-revalidate");
|
||||
|
||||
sendFile($dms->contentDir.$content->getPath());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1,31 +1,3 @@
|
|||
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
|
||||
=======================================
|
||||
|
||||
|
@ -35,11 +7,7 @@ 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
|
||||
pdftotext -nopgbrk %s - | sed -e 's/ [a-zA-Z0-9.]\{1\} / /g' -e 's/[0-9.]//g'
|
||||
|
||||
mutool draw -F txt -q -N -o - %s
|
||||
|
||||
|
@ -49,9 +17,6 @@ application/vnd.openxmlformats-officedocument.wordprocessingml.document
|
|||
application/msword
|
||||
catdoc %s
|
||||
|
||||
application/vnd.oasis.opendocument.text
|
||||
odt2txt %s
|
||||
|
||||
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
|
||||
xlsx2csv -d tab %s
|
||||
|
||||
|
@ -87,9 +52,6 @@ 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
|
||||
|
@ -106,20 +68,6 @@ message/rfc822
|
|||
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
|
||||
=====================================
|
||||
|
||||
|
@ -142,33 +90,15 @@ 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'
|
||||
mutool draw -F png -w %w -q -N -o %o %f 1
|
||||
|
||||
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.
|
||||
a2ps -1 -a1 -R -B -o - '%f' | gs -dBATCH -dNOPAUSE -sDEVICE=png16m -dFirstPage=1 -dLastPage=1 -dPDFFitPage -r72x72 -sOutputFile=- -q - | convert -resize %wx png:- 'png:%o'
|
||||
|
||||
application/msword
|
||||
application/vnd.oasis.opendocument.spreadsheet
|
||||
|
@ -183,24 +113,3 @@ 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.
|
||||
|
|
|
@ -8,20 +8,20 @@ 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.
|
||||
|
||||
Make sure you have PHP >= 8.2 and MySQL 5 or higher installed. SeedDMS
|
||||
Make sure you have PHP >= 7.3 and MySQL 5 or higher installed. SeedDMS
|
||||
will work with PHP running in CGI-mode as well as running as a module under
|
||||
apache.
|
||||
|
||||
Here is a detailed list of requirements:
|
||||
|
||||
1. A web server with at least php 8.2
|
||||
1. A web server with at least php 7.3
|
||||
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
|
||||
`php_gmp`, `php_libsodium` 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
|
||||
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
|
||||
|
@ -29,7 +29,7 @@ Here is a detailed list of requirements:
|
|||
|
||||
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,
|
||||
(excluding those listing 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.
|
||||
|
||||
|
@ -99,7 +99,7 @@ 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
|
||||
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
|
||||
|
||||
|
@ -240,7 +240,7 @@ in your current installation with new versions from the quickstart archive.
|
|||
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.
|
||||
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.
|
||||
|
@ -350,7 +350,7 @@ http://localhost/seeddms/
|
|||
* Create a data directory with the thre sub directories staging, cache
|
||||
and lucene.
|
||||
Make sure the data directory is either *not* below your document root
|
||||
or is protected with a .htaccess file against web access. The data directory
|
||||
or is protected with a .htaccess file against web access. The data directory
|
||||
needs to be writable by the web server.
|
||||
|
||||
* Clicking on 'Start installation' will show a form with all necessary
|
||||
|
@ -371,9 +371,9 @@ full text search engine support, you will also need to unpack
|
|||
* Unpack all the files in a public web server folder. If you're working on
|
||||
a host machine your provider will tell you where to upload the files.
|
||||
If possible, do not unpack the pear packages `SeedDMS_Core-<version>.tgz`,
|
||||
`SeedDMS_Preview-<version>.tgz` and
|
||||
`SeedDMS_Preview-<version>.tgz` and
|
||||
`SeedDMS_Lucene-<version>.tgz` below the document root of your web server.
|
||||
Choose a temporary folder, as the files will be moved in a second.
|
||||
Choose a temporary folder, as the files will be moved in a second.
|
||||
|
||||
Create a directory e.g. `pear` in the same directory where you unpacked
|
||||
seeddms and create a sub directory SeedDMS. Move the content except for the
|
||||
|
@ -395,36 +395,36 @@ full text search engine support, you will also need to unpack
|
|||
|
||||
Since they are pear packages they can also be installed with
|
||||
|
||||
> pear install SeedDMS_Core-<version>.tgz
|
||||
> pear install SeedDMS_Lucene-<version>.tgz
|
||||
> pear install SeedDMS_Preview-<version>.tgz
|
||||
> pear install SeedDMS_Core-<version>.tgz
|
||||
> 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
|
||||
or place it under your new directory 'pear'
|
||||
Either install it as a pear package
|
||||
or place it under your new directory 'pear'
|
||||
|
||||
> pear
|
||||
> Log
|
||||
> Log.php
|
||||
> Mail
|
||||
> Mail.php
|
||||
> 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
|
||||
pear package or place it under your new directory 'pear'
|
||||
pear package or place it under your new directory 'pear'
|
||||
|
||||
> pear
|
||||
> HTTP
|
||||
> WebDAV
|
||||
> Server
|
||||
> Server.php
|
||||
> WebDAV
|
||||
> Server
|
||||
> Server.php
|
||||
|
||||
If you run PHP in CGI mode, you also need to place a .htaccess file
|
||||
in the webdav directory with the following content.
|
||||
in the webdav directory with the following content.
|
||||
|
||||
RewriteEngine on
|
||||
RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization},last]
|
||||
RewriteEngine on
|
||||
RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization},last]
|
||||
|
||||
* Create a data folder somewhere on your web server including the subdirectories
|
||||
staging, cache and lucene and make sure they are writable by your web server,
|
||||
|
@ -435,24 +435,24 @@ or should be protected by a .htaccess file. The folder containing the
|
|||
configuration (settings.xml) must be protected by an .htaccess file like the
|
||||
following.
|
||||
|
||||
> <Files ~ "^settings\.xml">
|
||||
> Order allow,deny
|
||||
> Deny from all
|
||||
> </Files>
|
||||
> <Files ~ "^settings\.xml">
|
||||
> Order allow,deny
|
||||
> Deny from all
|
||||
> </Files>
|
||||
|
||||
|
||||
If you install SeedDMS for the first time continue with the database setup.
|
||||
|
||||
* Create a new database on your web server
|
||||
e.g. for mysql:
|
||||
create database seeddms;
|
||||
create database seeddms;
|
||||
* Create a new user for the database with all permissions on the new database
|
||||
e.g. for mysql:
|
||||
grant all privileges on seeddms.* to seeddms@localhost identified by 'secret';
|
||||
(replace 'secret' with you own password)
|
||||
grant all privileges on seeddms.* to seeddms@localhost identified by 'secret';
|
||||
(replace 'secret' with you own password)
|
||||
* Optionally import `create_tables-innodb.sql` in the new database
|
||||
e.g. for mysql:
|
||||
> cat create_tables-innodb.sql | mysql -useeddms -p seeddms
|
||||
> 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
|
||||
your browser at http://hostname/seeddms/install
|
||||
|
|
|
@ -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)
|
|
@ -106,11 +106,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
|
||||
|
@ -126,28 +121,3 @@ op/op.TriggerWorkflow.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,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
|
||||
|
@ -29,7 +29,7 @@ the content of document or creating a new
|
|||
version if a document is saved.
|
||||
|
||||
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
|
||||
|
@ -51,14 +51,15 @@ 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
|
||||
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
|
||||
|
@ -68,7 +69,7 @@ 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 with the name of the original file. Afterwards vim deleteѕ 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
|
||||
|
@ -87,17 +88,12 @@ 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
|
||||
this case, because it still does the file renaming which is turned of by
|
||||
'nowritebackup'.
|
||||
|
||||
### cdaver
|
||||
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
|
||||
|
|
|
@ -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
|
|
@ -12,6 +12,9 @@
|
|||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
require_once("inc.Utils.php");
|
||||
require_once("inc.ClassNotificationService.php");
|
||||
require_once("inc.ClassEmailNotify.php");
|
||||
require_once("inc.ClassSession.php");
|
||||
require_once("inc.ClassAccessOperation.php");
|
||||
|
||||
|
@ -107,6 +110,8 @@ if($settings->_useHomeAsRootFolder && !$user->isAdmin() && $user->getHomeFolder(
|
|||
$role = $user->getRole();
|
||||
$dms->noReadForStatus = $role->getNoAccess();
|
||||
|
||||
require_once('inc/inc.Notification.php');
|
||||
|
||||
/* Include additional language file for view
|
||||
* This file must set $LANG[xx][]
|
||||
*/
|
||||
|
@ -122,7 +127,7 @@ if($isajax)
|
|||
* to be changed redirect to out/out.ForcePasswordChange.php. Do this
|
||||
* check only if password expiration is turned on, we are not on the
|
||||
* page to change the password or the page that changes the password, the
|
||||
* current user is not admin, and no user substitution has occured. */
|
||||
* current user is not admin, and no user substiation has occured. */
|
||||
|
||||
if (!$user->isAdmin() && $origuser == null) {
|
||||
if($settings->_passwordExpiration > 0) {
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Create authentication service
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @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-2022 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
require_once('inc.ClassAuthenticationService.php');
|
||||
require_once('inc.ClassDbAuthentication.php');
|
||||
require_once('inc.ClassLdapAuthentication.php');
|
||||
|
||||
global $logger;
|
||||
$authenticator = new SeedDMS_AuthenticationService($logger, $settings);
|
||||
|
||||
if(isset($GLOBALS['SEEDDMS_HOOKS']['authentication'])) {
|
||||
foreach($GLOBALS['SEEDDMS_HOOKS']['authentication'] as $authenticationObj) {
|
||||
if(method_exists($authenticationObj, 'preAddService')) {
|
||||
$authenticationObj->preAddService($dms, $authenticator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$authenticator->addService(new SeedDMS_DbAuthentication($dms, $settings), 'db');
|
||||
if(isset($settings->_ldapHost) && strlen($settings->_ldapHost)>0) {
|
||||
$authenticator->addService(new SeedDMS_LdapAuthentication($dms, $settings), 'ldap');
|
||||
}
|
||||
|
||||
if(isset($GLOBALS['SEEDDMS_HOOKS']['authentication'])) {
|
||||
foreach($GLOBALS['SEEDDMS_HOOKS']['authentication'] as $authenticationObj) {
|
||||
if(method_exists($authenticationObj, 'postAddService')) {
|
||||
$authenticationObj->postAddService($dms, $authenticator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,13 +18,53 @@ require_once("inc.ClassEmailNotify.php");
|
|||
require_once("inc.ClassSession.php");
|
||||
require_once("inc.ClassAccessOperation.php");
|
||||
|
||||
function __authenticate($username, $password) { /* {{{ */
|
||||
global $dms, $settings;
|
||||
|
||||
$user = false;
|
||||
|
||||
/* Authenticate against LDAP server {{{ */
|
||||
if (!$user && isset($settings->_ldapHost) && strlen($settings->_ldapHost)>0) {
|
||||
require_once("../inc/inc.ClassLdapAuthentication.php");
|
||||
$authobj = new SeedDMS_LdapAuthentication($dms, $settings);
|
||||
$user = $authobj->authenticate($username, $password);
|
||||
} /* }}} */
|
||||
|
||||
/* Authenticate against SeedDMS database {{{ */
|
||||
else {
|
||||
require_once("../inc/inc.ClassDbAuthentication.php");
|
||||
$authobj = new SeedDMS_DbAuthentication($dms, $settings);
|
||||
$user = $authobj->authenticate($username, $password);
|
||||
} /* }}} */
|
||||
|
||||
if (!$user) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (($user->getID() == $settings->_guestID) && (!$settings->_enableGuestLogin)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if account is disabled
|
||||
if($user->isDisabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// control admin IP address if required
|
||||
if ($user->isAdmin() && ($_SERVER['REMOTE_ADDR'] != $settings->_adminIP ) && ( $settings->_adminIP != "") ){
|
||||
return false;
|
||||
}
|
||||
|
||||
return $user;
|
||||
} /* }}} */
|
||||
|
||||
if (!isset($_SERVER['PHP_AUTH_USER'])) {
|
||||
header('WWW-Authenticate: Basic realm="'.$settings->_siteName.'"');
|
||||
header('HTTP/1.0 401 Unauthorized');
|
||||
echo getMLText('cancel_basic_authentication');
|
||||
exit;
|
||||
} else {
|
||||
if(!($user = $authenticator->authenticate($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']))) {
|
||||
if(!($user = __authenticate($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']))) {
|
||||
header('WWW-Authenticate: Basic realm="'.$settings->_siteName.'"');
|
||||
header('HTTP/1.0 401 Unauthorized');
|
||||
echo getMLText('cancel_basic_authentication');
|
||||
|
|
|
@ -47,113 +47,10 @@ class SeedDMS_AccessOperation {
|
|||
*/
|
||||
private $_aro;
|
||||
|
||||
/**
|
||||
* @var array $legacy_access list of objects with access use for view and controller
|
||||
* @access protected
|
||||
*/
|
||||
private $legacy_access;
|
||||
|
||||
function __construct($dms, $user, $settings) { /* {{{ */
|
||||
$this->dms = $dms;
|
||||
$this->user = $user;
|
||||
$this->settings = $settings;
|
||||
$this->legacy_access['guest'] = array(
|
||||
'Calendar',
|
||||
'Download',
|
||||
'ErrorDlg',
|
||||
'Help',
|
||||
'Login',
|
||||
'Search',
|
||||
'ViewDocument',
|
||||
'ViewFolder',
|
||||
'ViewOnline',
|
||||
);
|
||||
$this->legacy_access['user'] = array(
|
||||
'AddDocument',
|
||||
'AddDocumentLink',
|
||||
'AddEvent',
|
||||
'AddFile',
|
||||
'AddSubFolder',
|
||||
'AddToTransmittal',
|
||||
'ApprovalSummary',
|
||||
'ApproveDocument',
|
||||
'Calendar',
|
||||
'CategoryChooser',
|
||||
'ChangePassword',
|
||||
'CheckInDocument',
|
||||
'CheckOutDocument',
|
||||
'Clipboard',
|
||||
'Dashboard',
|
||||
'DocumentAccess',
|
||||
'DocumentChooser',
|
||||
'DocumentNotify',
|
||||
'DocumentVersionDetail',
|
||||
'Download',
|
||||
'DropFolderChooser',
|
||||
'EditAttributes',
|
||||
'EditComment',
|
||||
'EditDocumentFile',
|
||||
'EditDocument',
|
||||
'EditEvent',
|
||||
'EditFolder',
|
||||
'EditOnline',
|
||||
'EditUserData',
|
||||
'ErrorDlg',
|
||||
'FolderAccess',
|
||||
'FolderChooser',
|
||||
'FolderNotify',
|
||||
'ForcePasswordChange',
|
||||
'GroupView',
|
||||
'Help',
|
||||
'KeywordChooser',
|
||||
'Login',
|
||||
'ManageNotify',
|
||||
'MoveDocument',
|
||||
'MoveFolder',
|
||||
'MyAccount',
|
||||
'MyDocuments',
|
||||
'OpensearchDesc',
|
||||
'OverrideContentStatus',
|
||||
'PasswordForgotten',
|
||||
'PasswordSend',
|
||||
'ReceiptDocument',
|
||||
'ReceiptSummary',
|
||||
'RemoveDocumentFile',
|
||||
'RemoveDocument',
|
||||
'RemoveEvent',
|
||||
'RemoveFolderFiles',
|
||||
'RemoveFolder',
|
||||
'RemoveTransmittal',
|
||||
'RemoveVersion',
|
||||
'RemoveWorkflowFromDocument',
|
||||
'ReturnFromSubWorkflow',
|
||||
'ReviewDocument',
|
||||
'ReviewSummary',
|
||||
'ReviseDocument',
|
||||
'RevisionSummary',
|
||||
'RewindWorkflow',
|
||||
'RunSubWorkflow',
|
||||
'Search',
|
||||
'Session',
|
||||
'SetExpires',
|
||||
'SetRecipients',
|
||||
'SetReviewersApprovers',
|
||||
'SetRevisors',
|
||||
'SetWorkflow',
|
||||
'SubstituteUser',
|
||||
'Tasks',
|
||||
'TransmittalMgr',
|
||||
'TriggerWorkflow',
|
||||
'UpdateDocument',
|
||||
'UserDefaultKeywords',
|
||||
'UserImage',
|
||||
'UsrView',
|
||||
'ViewDocument',
|
||||
'ViewEvent',
|
||||
'ViewFolder',
|
||||
'ViewOnline',
|
||||
'WorkflowGraph',
|
||||
'WorkflowSummary');
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
|
@ -192,7 +89,7 @@ class SeedDMS_AccessOperation {
|
|||
function mayRemoveVersion($document) { /* {{{ */
|
||||
if($document->isType('document')) {
|
||||
$versions = $document->getContent();
|
||||
if ((($this->settings->_enableVersionDeletion && ($document->getAccessMode($this->user, 'removeVersion') == M_ALL)) || $this->user->isAdmin() ) && (count($versions) > 1)) {
|
||||
if ((($this->settings->_enableVersionDeletion && ($document->getAccessMode($this->user) == M_ALL)) || $this->user->isAdmin() ) && (count($versions) > 1)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -514,30 +411,6 @@ class SeedDMS_AccessOperation {
|
|||
return false;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Check if document content may be checked in
|
||||
*
|
||||
*
|
||||
*/
|
||||
function mayCheckIn($document) { /* {{{ */
|
||||
if($document->isType('document')) {
|
||||
$checkoutinfo = $document->getCheckOutInfo();
|
||||
if(!$checkoutinfo)
|
||||
return false;
|
||||
$info = $checkoutinfo[0];
|
||||
if($this->user->getID() == $info['userID'] || $document->getAccessMode($this->user) == M_ALL) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} /* }}} */
|
||||
|
||||
public function allowLegacyAccess($access, $role) { /* {{{ */
|
||||
if($role == 'user' || $role == 'guest') {
|
||||
$this->legacy_access[$role][] = $access;
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
protected function check_view_legacy_access($view, $get=array()) { /* {{{ */
|
||||
if($this->user->isAdmin())
|
||||
return true;
|
||||
|
@ -553,35 +426,98 @@ class SeedDMS_AccessOperation {
|
|||
}
|
||||
|
||||
if($this->user->isGuest()) {
|
||||
$user_allowed = $this->legacy_access['guest'];
|
||||
$user_allowed = array(
|
||||
'Calendar',
|
||||
'ErrorDlg',
|
||||
'Help',
|
||||
'Login',
|
||||
'Search',
|
||||
'ViewDocument',
|
||||
'ViewFolder',
|
||||
);
|
||||
} else {
|
||||
$user_allowed = $this->legacy_access['user'];
|
||||
}
|
||||
|
||||
if(array_intersect($scripts, $user_allowed))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
} /* }}} */
|
||||
|
||||
protected function check_controller_legacy_access($controller, $get=array()) { /* {{{ */
|
||||
if($this->user->isAdmin())
|
||||
return true;
|
||||
|
||||
if(is_string($controller)) {
|
||||
$scripts = array($controller);
|
||||
} elseif(is_array($controller)) {
|
||||
$scripts = $controller;
|
||||
} elseif(is_subclass_of($controller, 'SeedDMS_Controller_Common')) {
|
||||
$scripts = array($controller->getParam('class'));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
if($this->user->isGuest()) {
|
||||
$user_allowed = $this->legacy_access['guest'];
|
||||
} else {
|
||||
$user_allowed = $this->legacy_access['user'];
|
||||
$user_allowed = array(
|
||||
'AddDocument',
|
||||
'AddDocumentLink',
|
||||
'AddEvent',
|
||||
'AddFile',
|
||||
'AddSubFolder',
|
||||
'AddToTransmittal',
|
||||
'ApprovalSummary',
|
||||
'ApproveDocument',
|
||||
'Calendar',
|
||||
'CategoryChooser',
|
||||
'ChangePassword',
|
||||
'CheckInDocument',
|
||||
'Clipboard',
|
||||
'DocumentAccess',
|
||||
'DocumentChooser',
|
||||
'DocumentNotify',
|
||||
'DocumentVersionDetail',
|
||||
'DropFolderChooser',
|
||||
'EditAttributes',
|
||||
'EditComment',
|
||||
'EditDocumentFile',
|
||||
'EditDocument',
|
||||
'EditEvent',
|
||||
'EditFolder',
|
||||
'EditOnline',
|
||||
'EditUserData',
|
||||
'ErrorDlg',
|
||||
'FolderAccess',
|
||||
'FolderChooser',
|
||||
'FolderNotify',
|
||||
'ForcePasswordChange',
|
||||
'GroupView',
|
||||
'Help',
|
||||
'KeywordChooser',
|
||||
'Login',
|
||||
'ManageNotify',
|
||||
'MoveDocument',
|
||||
'MoveFolder',
|
||||
'MyAccount',
|
||||
'MyDocuments',
|
||||
'OpensearchDesc',
|
||||
'OverrideContentStatus',
|
||||
'PasswordForgotten',
|
||||
'PasswordSend',
|
||||
'ReceiptDocument',
|
||||
'ReceiptSummary',
|
||||
'RemoveDocumentFile',
|
||||
'RemoveDocument',
|
||||
'RemoveEvent',
|
||||
'RemoveFolderFiles',
|
||||
'RemoveFolder',
|
||||
'RemoveTransmittal',
|
||||
'RemoveVersion',
|
||||
'RemoveWorkflowFromDocument',
|
||||
'ReturnFromSubWorkflow',
|
||||
'ReviewDocument',
|
||||
'ReviewSummary',
|
||||
'ReviseDocument',
|
||||
'RevisionSummary',
|
||||
'RewindWorkflow',
|
||||
'RunSubWorkflow',
|
||||
'Search',
|
||||
'Session',
|
||||
'SetExpires',
|
||||
'SetRecipients',
|
||||
'SetReviewersApprovers',
|
||||
'SetRevisors',
|
||||
'SetWorkflow',
|
||||
'SubstituteUser',
|
||||
'Tasks',
|
||||
'TransmittalMgr',
|
||||
'TriggerWorkflow',
|
||||
'UpdateDocument',
|
||||
'UserDefaultKeywords',
|
||||
'UserImage',
|
||||
'UsrView',
|
||||
'ViewDocument',
|
||||
'ViewEvent',
|
||||
'ViewFolder',
|
||||
'WorkflowGraph',
|
||||
'WorkflowSummary');
|
||||
}
|
||||
|
||||
if(array_intersect($scripts, $user_allowed))
|
||||
|
@ -649,8 +585,6 @@ class SeedDMS_AccessOperation {
|
|||
*/
|
||||
function check_controller_access($controller, $get=array()) { /* {{{ */
|
||||
if(!$this->settings->_advancedAcl) {
|
||||
return $this->check_controller_legacy_access($controller, $get);
|
||||
/*
|
||||
if($this->user->isGuest())
|
||||
return false;
|
||||
elseif($this->user->isAdmin())
|
||||
|
@ -660,7 +594,6 @@ class SeedDMS_AccessOperation {
|
|||
return false;
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
}
|
||||
if(is_string($controller)) {
|
||||
$scripts = array($controller);
|
||||
|
|
|
@ -163,7 +163,7 @@ class SeedDMS_AroAco { /* {{{ */
|
|||
* @return object instance of SeedDMS_Aco
|
||||
*/
|
||||
function __construct($dms, $id, $parent, $object, $alias) { /* {{{ */
|
||||
$this->_dms = $dms;
|
||||
$this->_dmѕ = $dms;
|
||||
$this->_id = $id;
|
||||
$this->_parent = $parent;
|
||||
$this->_object = $object;
|
||||
|
|
|
@ -24,6 +24,34 @@
|
|||
*/
|
||||
abstract class SeedDMS_Authentication
|
||||
{
|
||||
/**
|
||||
* DMS object
|
||||
*
|
||||
* @var SeedDMS_Core_DMS
|
||||
* @access protected
|
||||
*/
|
||||
protected $dms;
|
||||
|
||||
/**
|
||||
* DMS settings
|
||||
*
|
||||
* @var Settings
|
||||
* @access protected
|
||||
*/
|
||||
protected $settings;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param SeedDMS_Core_DMS $dms DMS object
|
||||
* @param Settings $settings DMS settings
|
||||
*/
|
||||
function __construct($dms, $settings) /* {{{ */
|
||||
{
|
||||
$this->dms = $dms;
|
||||
$this->settings = $settings;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Do Authentication
|
||||
*
|
||||
|
|
|
@ -1,108 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* MyDMS. Document Management System
|
||||
* Copyright (C) 2002-2005 Markus Westphal
|
||||
* Copyright (C) 2006-2008 Malcolm Cowe
|
||||
* Copyright (C) 2010 Matteo Lucarelli
|
||||
* Copyright (C) 2010-2024 Uwe Steinmann
|
||||
*
|
||||
* PHP version 8
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @category SeedDMS
|
||||
* @package SeedDMS
|
||||
* @author Uwe Steinmann <info@seeddms.org>
|
||||
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
|
||||
* @link https://www.seeddms.org Main Site
|
||||
*/
|
||||
|
||||
/* Middleware for authentication based on session */
|
||||
class SeedDMS_Auth_Middleware_Session { /* {{{ */
|
||||
|
||||
private $container;
|
||||
|
||||
public function __construct($container) {
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Example middleware invokable class
|
||||
*
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request PSR7 request
|
||||
* @param \Psr\Http\Message\ResponseInterface $response PSR7 response
|
||||
* @param callable $next Next middleware
|
||||
*
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
public function __invoke($request, $handler) {
|
||||
// $this->container has the DI
|
||||
$dms = $this->container->get('dms');
|
||||
$settings = $this->container->get('config');
|
||||
$logger = $this->container->get('logger');
|
||||
$userobj = null;
|
||||
if ($this->container->has('userobj')) {
|
||||
$userobj = $this->container->get('userobj');
|
||||
}
|
||||
|
||||
if ($userobj) {
|
||||
$response = $handler->handle($request);
|
||||
return $response;
|
||||
}
|
||||
|
||||
$logger->log("Invoke middleware for method " . $request->getMethod() . " on '" . $request->getUri()->getPath() . "'", PEAR_LOG_INFO);
|
||||
require_once("inc/inc.ClassSession.php");
|
||||
$session = new SeedDMS_Session($dms->getDb());
|
||||
if (isset($_COOKIE["mydms_session"])) {
|
||||
$dms_session = $_COOKIE["mydms_session"];
|
||||
$logger->log("Session key: " . $dms_session, PEAR_LOG_DEBUG);
|
||||
if (!$resArr = $session->load($dms_session)) {
|
||||
/* Delete Cookie */
|
||||
setcookie("mydms_session", $dms_session, time() - 3600, $settings->_httpRoot);
|
||||
$logger->log("Session for id '" . $dms_session . "' has gone", PEAR_LOG_ERR);
|
||||
return $response->withStatus(403);
|
||||
}
|
||||
|
||||
/* Load user data */
|
||||
$userobj = $dms->getUser($resArr["userID"]);
|
||||
if (!is_object($userobj)) {
|
||||
/* Delete Cookie */
|
||||
setcookie("mydms_session", $dms_session, time() - 3600, $settings->_httpRoot);
|
||||
if ($settings->_enableGuestLogin) {
|
||||
if (!($userobj = $dms->getUser($settings->_guestID))) {
|
||||
return $response->withStatus(403);
|
||||
}
|
||||
} else {
|
||||
return $response->withStatus(403);
|
||||
}
|
||||
}
|
||||
if ($userobj->isAdmin()) {
|
||||
if ($resArr["su"]) {
|
||||
if (!($userobj = $dms->getUser($resArr["su"]))) {
|
||||
return $response->withStatus(403);
|
||||
}
|
||||
}
|
||||
}
|
||||
$dms->setUser($userobj);
|
||||
} else {
|
||||
return $response->withStatus(403);
|
||||
}
|
||||
$this->container->set('userobj', $userobj);
|
||||
|
||||
$response = $handler->handle($request);
|
||||
return $response;
|
||||
}
|
||||
} /* }}} */
|
|
@ -1,102 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of authentication service
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2016 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implementation of authentication service
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2016 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_AuthenticationService {
|
||||
/**
|
||||
* List of services for authenticating user
|
||||
*/
|
||||
protected $services;
|
||||
|
||||
/*
|
||||
* List of servives with errors
|
||||
*/
|
||||
protected $errors;
|
||||
|
||||
/*
|
||||
* Service for logging
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/*
|
||||
* Configuration
|
||||
*/
|
||||
protected $settings;
|
||||
|
||||
public function __construct($logger = null, $settings = null) { /* {{{ */
|
||||
$this->services = array();
|
||||
$this->errors = array();
|
||||
$this->logger = $logger;
|
||||
$this->settings = $settings;
|
||||
} /* }}} */
|
||||
|
||||
public function addService($service, $name='') { /* {{{ */
|
||||
if(!$name)
|
||||
$name = md5(uniqid());
|
||||
$this->services[$name] = $service;
|
||||
$this->errors[$name] = true;
|
||||
} /* }}} */
|
||||
|
||||
public function getServices() { /* {{{ */
|
||||
return $this->services;
|
||||
} /* }}} */
|
||||
|
||||
public function getErrors() { /* {{{ */
|
||||
return $this->errors;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Run each authentication service
|
||||
*
|
||||
* This method calls authenticate() of each authentication service and
|
||||
* evaluates the returned value.
|
||||
* If the authentication method returns false (some internal error which
|
||||
* prevented to check authentication at all), this method will return
|
||||
* false imediately, in case of null (no valid authentication) the next
|
||||
* service will be tried and in all other cases the value will be returned.
|
||||
*
|
||||
* @param string $username name of user
|
||||
* @param string $password password of user
|
||||
*/
|
||||
public function authenticate($username, $password) { /* {{{ */
|
||||
$user = null;
|
||||
foreach($this->services as $name => $service) {
|
||||
if($this->logger)
|
||||
$this->logger->log('Authentication service \''.$name.'\'', PEAR_LOG_INFO);
|
||||
$user = $service->authenticate($username, $password);
|
||||
if($user === false) {
|
||||
$this->errors[$name] = false;
|
||||
if($this->logger)
|
||||
$this->logger->log('Authentication service \''.$name.'\': Authentication of user \''.$username.'\' failed.', PEAR_LOG_ERR);
|
||||
return false;
|
||||
} elseif($user === null) {
|
||||
if($this->logger)
|
||||
$this->logger->log('Authentication service \''.$name.'\': Authentication of user \''.$username.'\' disregarded.', PEAR_LOG_ERR);
|
||||
} else {
|
||||
if($this->logger)
|
||||
$this->logger->log('Authentication service \''.$name.'\': Authentication of user \''.$username.'\' successful.', PEAR_LOG_INFO);
|
||||
$this->errors[$name] = true;
|
||||
return $user;
|
||||
}
|
||||
}
|
||||
return $user;
|
||||
} /* }}} */
|
||||
}
|
|
@ -33,11 +33,6 @@ class SeedDMS_Calendar {
|
|||
*/
|
||||
protected $db;
|
||||
|
||||
/**
|
||||
* Instanz of user
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
public function __construct($db, $user) { /* {{{ */
|
||||
$this->db = $db;
|
||||
$this->user = $user;
|
||||
|
|
|
@ -30,7 +30,7 @@ class Controller {
|
|||
* @return object an object of a class implementing the view
|
||||
*/
|
||||
static function factory($class, $params=array()) { /* {{{ */
|
||||
global $settings, $session, $extMgr, $request, $logger, $notifier;
|
||||
global $settings, $session, $extMgr;
|
||||
if(!$class) {
|
||||
return null;
|
||||
}
|
||||
|
@ -57,10 +57,7 @@ class Controller {
|
|||
$controller->setParam('getVars', $_GET);
|
||||
$controller->setParam('requestVars', $_REQUEST);
|
||||
$controller->setParam('session', $session);
|
||||
$controller->setParam('request', $request);
|
||||
$controller->setParam('settings', $settings);
|
||||
$controller->setParam('logger', $logger);
|
||||
$controller->setParam('notifier', $notifier);
|
||||
return $controller;
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -41,63 +41,37 @@ class SeedDMS_Controller_Common {
|
|||
*/
|
||||
protected $lasthookresult;
|
||||
|
||||
public function __construct($params) {
|
||||
function __construct($params) {
|
||||
$this->params = $params;
|
||||
$this->error = 0;
|
||||
$this->errormsg = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Call method with name in $get['action']
|
||||
* Call methods with name in $get['action']
|
||||
*
|
||||
* Until 5.1.26 (6.0.19) this method took the name of the
|
||||
* controller method to run from the element 'action' passed
|
||||
* in the array $get. Since 5.1.27 (6.0.20) a PSR7 Request
|
||||
* object is available in the controller and used to get the
|
||||
* action.
|
||||
*
|
||||
* @params array $get $_GET or $_POST variables (since 5.1.27 this is no longer used)
|
||||
* @params array $get $_GET or $_POST variables
|
||||
* @return mixed return value of called method
|
||||
*/
|
||||
public function __invoke($get=array()) {
|
||||
$action = null;
|
||||
if(!$action = $this->getParam('action')) {
|
||||
$request = $this->getParam('request');
|
||||
if($request) {
|
||||
if($request->isMethod('get'))
|
||||
$action = $request->query->get('action');
|
||||
elseif($request->isMethod('post'))
|
||||
$action = $request->request->get('action');
|
||||
function __invoke($get=array()) {
|
||||
$this->callHook('preRun', isset($get['action']) ? $get['action'] : 'run');
|
||||
if(isset($get['action']) && $get['action']) {
|
||||
if(method_exists($this, $get['action'])) {
|
||||
return $this->{$get['action']}();
|
||||
} else {
|
||||
echo "Missing action '".$get['action']."'";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(!$this->callHook('preRun', get_class($this), $action ? $action : 'run')) {
|
||||
if($action) {
|
||||
if(method_exists($this, $action)) {
|
||||
$refl = new ReflectionMethod($this, $action);
|
||||
if($refl->isPublic())
|
||||
$ret = $this->{$action}();
|
||||
else {
|
||||
echo "Action '".$action."' not public";
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
echo "Missing action '".$action."'";
|
||||
return false;
|
||||
}
|
||||
} else
|
||||
$ret = $this->run();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
$this->callHook('postRun', get_class($this), $action ? $action : 'run');
|
||||
return $ret;
|
||||
} else
|
||||
return $this->run();
|
||||
$this->callHook('postRun', isset($get['action']) ? $get['action'] : 'run');
|
||||
}
|
||||
|
||||
public function setParams($params) {
|
||||
function setParams($params) {
|
||||
$this->params = $params;
|
||||
}
|
||||
|
||||
public function setParam($name, $value) {
|
||||
function setParam($name, $value) {
|
||||
$this->params[$name] = $value;
|
||||
}
|
||||
|
||||
|
@ -111,7 +85,7 @@ class SeedDMS_Controller_Common {
|
|||
* @param string $name name of parameter
|
||||
* @return mixed value of parameter or null if parameter does not exist
|
||||
*/
|
||||
public function getParam($name) {
|
||||
function getParam($name) {
|
||||
return isset($this->params[$name]) ? $this->params[$name] : null;
|
||||
}
|
||||
|
||||
|
@ -121,7 +95,7 @@ class SeedDMS_Controller_Common {
|
|||
* @param string $name name of parameter
|
||||
* @return boolean true if parameter exists otherwise false
|
||||
*/
|
||||
public function hasParam($name) {
|
||||
function hasParam($name) {
|
||||
return isset($this->params[$name]) ? true : false;
|
||||
}
|
||||
|
||||
|
@ -130,12 +104,12 @@ class SeedDMS_Controller_Common {
|
|||
*
|
||||
* @param string $name name of parameter
|
||||
*/
|
||||
public function unsetParam($name) {
|
||||
function unsetParam($name) {
|
||||
if(isset($this->params[$name]))
|
||||
unset($this->params[$name]);
|
||||
}
|
||||
|
||||
public function run() {
|
||||
function run() {
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -13,11 +13,8 @@
|
|||
|
||||
require_once("inc/inc.ClassConversionServiceExec.php");
|
||||
require_once("inc/inc.ClassConversionServiceImageToImage.php");
|
||||
require_once("inc/inc.ClassConversionServiceImageToText.php");
|
||||
require_once("inc/inc.ClassConversionServicePdfToImage.php");
|
||||
require_once("inc/inc.ClassConversionServiceTextToText.php");
|
||||
require_once("inc/inc.ClassConversionServiceHtmlToText.php");
|
||||
require_once("inc/inc.ClassConversionServiceTextToImage.php");
|
||||
|
||||
/**
|
||||
* Implementation of conversion manager
|
||||
|
@ -30,102 +27,62 @@ require_once("inc/inc.ClassConversionServiceTextToImage.php");
|
|||
*/
|
||||
class SeedDMS_ConversionMgr {
|
||||
/**
|
||||
* List of services for converting documents
|
||||
* List of services for searching fulltext
|
||||
*/
|
||||
public $services;
|
||||
|
||||
/**
|
||||
* @var $success set to false if conversion failed
|
||||
*/
|
||||
protected $success;
|
||||
|
||||
public function __construct() { /* {{{ */
|
||||
public function __construct() {
|
||||
$this->services = array();
|
||||
$this->success = true;
|
||||
} /* }}} */
|
||||
}
|
||||
|
||||
public function addService($service) { /* {{{ */
|
||||
$service->setConversionMgr($this);
|
||||
public function addService($service) {
|
||||
$this->services[$service->from][$service->to][] = $service;
|
||||
return $service;
|
||||
} /* }}} */
|
||||
}
|
||||
|
||||
public function hasService($from, $to) { /* {{{ */
|
||||
public function hasService($from, $to) {
|
||||
if(!empty($this->services[$from][$to]))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Return the list of mimetypes which can be converted
|
||||
* into the given mimetype
|
||||
*
|
||||
* @param string $askto mimetype to be converted into
|
||||
* @return array list of from mimetypes
|
||||
*/
|
||||
public function getFromWithTo($askto) { /* {{{ */
|
||||
$fromret = [];
|
||||
foreach($this->services as $from=>$toservices)
|
||||
foreach($toservices as $to=>$service)
|
||||
if($to == $askto)
|
||||
$fromret[] = $from;
|
||||
return $fromret;
|
||||
} /* }}} */
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the service that would be tried first for converting
|
||||
* the document.
|
||||
*
|
||||
* The conversion manager may not use this service but choose a different
|
||||
* The conversion may not use this service but choose a different
|
||||
* one when it fails.
|
||||
*/
|
||||
public function getService($from, $to) { /* {{{ */
|
||||
public function getService($from, $to) {
|
||||
if(!empty($this->services[$from][$to]))
|
||||
return end($this->services[$from][$to]);
|
||||
else
|
||||
return null;
|
||||
} /* }}} */
|
||||
}
|
||||
|
||||
public function getServices() { /* {{{ */
|
||||
public function getServices() {
|
||||
return $this->services;
|
||||
} /* }}} */
|
||||
|
||||
public function wasSuccessful() { /* {{{ */
|
||||
return $this->success;
|
||||
} /* }}} */
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a file from one format into another format
|
||||
*
|
||||
* This method will try each conversion service until a service
|
||||
* fails or was successful. If a service succeeds it must not
|
||||
* return false, null, '' or 0
|
||||
* Convert a file
|
||||
*
|
||||
* @param string $file name of file to convert
|
||||
* @param string $from mimetype of input file
|
||||
* @param string $to mimetype of output file
|
||||
* @param string $target name of target file. If none is given the
|
||||
* content of the converted document will be returned.
|
||||
* @param array $params additional parameter needed for the conversion,
|
||||
* e.g. the width of an image
|
||||
*
|
||||
* @return boolean true on success, other false
|
||||
*/
|
||||
public function convert($file, $from, $to, $target=null, $params=array()) { /* {{{ */
|
||||
public function convert($file, $from, $to, $target=null, $params=array()) {
|
||||
if(isset($this->services[$from][$to])) {
|
||||
$services = $this->services[$from][$to];
|
||||
for(end($services); key($services)!==null; prev($services)) {
|
||||
$service = current($services);
|
||||
$text = $service->convert($file, $target, $params);
|
||||
if(!$service->wasSuccessful()) {
|
||||
$this->success = false;
|
||||
return false;
|
||||
}
|
||||
if($text)
|
||||
if($text !== false)
|
||||
return $text;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} /* }}} */
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,36 +36,15 @@ abstract class SeedDMS_ConversionServiceBase {
|
|||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* conversion manager
|
||||
*/
|
||||
protected $conversionmgr;
|
||||
|
||||
/**
|
||||
* @var $success set to false if conversion failed
|
||||
*/
|
||||
protected $success;
|
||||
|
||||
public function __construct() {
|
||||
$this->from = null;
|
||||
$this->to = null;
|
||||
$this->success = true;
|
||||
$this->logger = null;
|
||||
$this->conversionmgr = null;
|
||||
}
|
||||
|
||||
public function setLogger($logger) {
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
public function setConversionMgr($conversionmgr) {
|
||||
$this->conversionmgr = $conversionmgr;
|
||||
}
|
||||
|
||||
public function getConversionMgr() {
|
||||
return $this->conversionmgr;
|
||||
}
|
||||
|
||||
public function getInfo() {
|
||||
return 'Conversion service';
|
||||
}
|
||||
|
@ -74,10 +53,6 @@ abstract class SeedDMS_ConversionServiceBase {
|
|||
return [];
|
||||
} /* }}} */
|
||||
|
||||
public function wasSuccessful() { /* {{{ */
|
||||
return $this->success;
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* This method does the conversion
|
||||
*
|
||||
|
|
|
@ -49,7 +49,6 @@ class SeedDMS_ConversionServiceExec extends SeedDMS_ConversionServiceBase {
|
|||
);
|
||||
$pipes = array();
|
||||
|
||||
$orgtimeout = $timeout;
|
||||
$timeout += time();
|
||||
// Putting an 'exec' before the command will not fork the command
|
||||
// and therefore not create any child process. proc_terminate will
|
||||
|
@ -85,19 +84,18 @@ class SeedDMS_ConversionServiceExec extends SeedDMS_ConversionServiceBase {
|
|||
fclose($pipes[2]);
|
||||
if ($timeleft <= 0) {
|
||||
proc_terminate($process);
|
||||
throw new Exception("command timeout after ".$orgtimeout." secs on: " . $cmd);
|
||||
throw new Exception("command timeout on: " . $cmd);
|
||||
} else {
|
||||
$return_value = proc_close($process);
|
||||
return array('stdout'=>$output, 'stderr'=>$error, 'return'=>$return_value);
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
public function __construct($from, $to, $cmd, $timeout=5) {
|
||||
parent::__construct();
|
||||
public function __construct($from, $to, $cmd) {
|
||||
$this->from = $from;
|
||||
$this->to = $to;
|
||||
$this->cmd = $cmd;
|
||||
$this->timeout = ((int) $timeout) ? (int) $timeout : 5;
|
||||
$this->timeout = 5;
|
||||
}
|
||||
|
||||
public function getInfo() {
|
||||
|
@ -159,7 +157,6 @@ class SeedDMS_ConversionServiceExec extends SeedDMS_ConversionServiceBase {
|
|||
/* %s was just added because the commands to convert to text/plain used
|
||||
* it instead of %f for the input file
|
||||
* %f = input file
|
||||
* %if = format (jpg, png, pdf, gif)
|
||||
* %o = output file
|
||||
* %m = mime type
|
||||
* %w = width
|
||||
|
@ -170,16 +167,6 @@ class SeedDMS_ConversionServiceExec extends SeedDMS_ConversionServiceBase {
|
|||
} catch(Exception $e) {
|
||||
if($hastempfile)
|
||||
unlink($tmpfile);
|
||||
$this->success = false;
|
||||
if($this->logger) {
|
||||
$this->logger->log('Conversion from '.$this->from.' to '.$this->to.' with cmd "'.$this->cmd.'" failed: '.$e->getMessage(), PEAR_LOG_ERR);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if(!empty($ret['stderr'])) {
|
||||
if($this->logger) {
|
||||
$this->logger->log('Conversion from '.$this->from.' to '.$this->to.' with cmd "'.$this->cmd.'" failed: '.$ret['stderr'], PEAR_LOG_ERR);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
$end = microtime(true);
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of conversion service class
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2021 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
require_once("inc/inc.ClassConversionServiceBase.php");
|
||||
|
||||
/**
|
||||
* Implementation of conversion service class for text to text
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2021 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_ConversionServiceHtmlToText extends SeedDMS_ConversionServiceBase {
|
||||
public function __construct($from, $to) {
|
||||
parent::__construct();
|
||||
$this->from = $from;
|
||||
$this->to = $to;
|
||||
}
|
||||
|
||||
public function getInfo() {
|
||||
return "Strip tags from document contents";
|
||||
}
|
||||
|
||||
public function convert($infile, $target = null, $params = array()) {
|
||||
$d = new DOMDocument;
|
||||
libxml_use_internal_errors(true);
|
||||
$d->loadHTMLFile($infile);
|
||||
libxml_clear_errors();
|
||||
$body = $d->getElementsByTagName('body')->item(0);
|
||||
$str = '';
|
||||
foreach($body->childNodes as $childNode) {
|
||||
$str .= $d->saveHTML($childNode);
|
||||
}
|
||||
if($target) {
|
||||
file_put_contents($target, strip_tags($str));
|
||||
return true;
|
||||
} else
|
||||
return strip_tags($str);
|
||||
}
|
||||
}
|
||||
|
|
@ -28,16 +28,15 @@ class SeedDMS_ConversionServiceImageToImage extends SeedDMS_ConversionServiceBas
|
|||
*/
|
||||
public $timeout;
|
||||
|
||||
public function __construct($from, $to) { /* {{{ */
|
||||
parent::__construct();
|
||||
public function __construct($from, $to) {
|
||||
$this->from = $from;
|
||||
$this->to = $to;
|
||||
$this->timeout = 5;
|
||||
} /* }}} */
|
||||
}
|
||||
|
||||
public function getInfo() { /* {{{ */
|
||||
return "Convert with imagick or gd php functions";
|
||||
} /* }}} */
|
||||
public function getInfo() {
|
||||
return "Convert with imagick php functions";
|
||||
}
|
||||
|
||||
public function getAdditionalParams() { /* {{{ */
|
||||
return [
|
||||
|
@ -45,88 +44,28 @@ class SeedDMS_ConversionServiceImageToImage extends SeedDMS_ConversionServiceBas
|
|||
];
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Convert a pixel image into png and scale it
|
||||
*
|
||||
* This method uses imagick and if not available falls back to the gd library.
|
||||
*/
|
||||
public function convert($infile, $target = null, $params = array()) { /* {{{ */
|
||||
public function convert($infile, $target = null, $params = array()) {
|
||||
$start = microtime(true);
|
||||
if(extension_loaded('imagick')) {
|
||||
$imagick = new Imagick();
|
||||
try {
|
||||
if($imagick->readImage($infile)) {
|
||||
if(!empty($params['width']))
|
||||
$imagick->scaleImage(min((int) $params['width'], $imagick->getImageWidth()), 0);
|
||||
$end = microtime(true);
|
||||
if($this->logger) {
|
||||
$this->logger->log('Conversion from '.$this->from.' to '.$this->to.' with imagick service took '.($end-$start).' sec.', PEAR_LOG_INFO);
|
||||
}
|
||||
if($target) {
|
||||
return $imagick->writeImage($target);
|
||||
} else {
|
||||
return $imagick->getImageBlob();
|
||||
}
|
||||
} else {
|
||||
if($this->logger) {
|
||||
$this->logger->log('Conversion from '.$this->from.' to '.$this->to.' with image service failed: could not read input file.', PEAR_LOG_ERR);
|
||||
}
|
||||
$this->success = false;
|
||||
return false;
|
||||
}
|
||||
} catch (ImagickException $e) {
|
||||
if($this->logger) {
|
||||
$this->logger->log('Conversion from '.$this->from.' to '.$this->to.' with image service failed: '.$e->getMessage(), PEAR_LOG_ERR);
|
||||
}
|
||||
$this->success = false;
|
||||
return false;
|
||||
}
|
||||
} elseif(extension_loaded('gd')) {
|
||||
$im = null;
|
||||
switch($this->from) {
|
||||
case 'image/jpeg':
|
||||
case 'image/jpg':
|
||||
$im = @imagecreatefromjpeg($infile);
|
||||
break;
|
||||
case 'image/png':
|
||||
$im = @imagecreatefrompng($infile);
|
||||
break;
|
||||
case 'image/gif':
|
||||
$im = @imagecreatefromgif($infile);
|
||||
break;
|
||||
case 'image/webp':
|
||||
$im = @imagecreatefromwebp($infile);
|
||||
break;
|
||||
case 'image/avif':
|
||||
$im = @imagecreatefromavif($infile);
|
||||
break;
|
||||
}
|
||||
if($im) {
|
||||
$width = imagesx($im);
|
||||
$imagick = new Imagick();
|
||||
try {
|
||||
if($imagick->readImage($infile)) {
|
||||
if(!empty($params['width']))
|
||||
$im = imagescale($im, min((int) $params['width'], $width));
|
||||
$imagick->scaleImage(min((int) $params['width'], $imagick->getImageWidth()), 0);
|
||||
$end = microtime(true);
|
||||
if($this->logger) {
|
||||
$this->logger->log('Conversion from '.$this->from.' to '.$this->to.' with gd image service took '.($end-$start).' sec.', PEAR_LOG_INFO);
|
||||
$this->logger->log('Conversion from '.$this->from.' to '.$this->to.' with image service took '.($end-$start).' sec.', PEAR_LOG_INFO);
|
||||
}
|
||||
if($target) {
|
||||
return imagepng($im, $target);
|
||||
return $imagick->writeImage($target);
|
||||
} else {
|
||||
ob_start();
|
||||
echo imagepng($im);
|
||||
$image = ob_get_clean();
|
||||
return $image;
|
||||
return $imagick->getImageBlob();
|
||||
}
|
||||
} else {
|
||||
if($this->logger) {
|
||||
$this->logger->log('Conversion from '.$this->from.' to '.$this->to.' with image service failed: could not read input file.', PEAR_LOG_ERR);
|
||||
}
|
||||
$this->success = false;
|
||||
return false;
|
||||
}
|
||||
} catch (ImagickException $e) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
} /* }}} */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Implementation of conversion service image class
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @license GPL 2
|
||||
* @version @version@
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2021 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
|
||||
require_once("inc/inc.ClassConversionServiceBase.php");
|
||||
|
||||
/**
|
||||
* Implementation of conversion service image class
|
||||
*
|
||||
* @category DMS
|
||||
* @package SeedDMS
|
||||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||||
* @copyright Copyright (C) 2021 Uwe Steinmann
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class SeedDMS_ConversionServiceImageToText extends SeedDMS_ConversionServiceBase {
|
||||
/**
|
||||
* timeout
|
||||
*/
|
||||
public $timeout;
|
||||
|
||||
public function __construct($from, $to) { /* {{{ */
|
||||
parent::__construct();
|
||||
$this->from = $from;
|
||||
$this->to = $to;
|
||||
} /* }}} */
|
||||
|
||||
public function getInfo() { /* {{{ */
|
||||
return "Convert by extracting iptc data";
|
||||
} /* }}} */
|
||||
|
||||
public function getAdditionalParams() { /* {{{ */
|
||||
return [
|
||||
];
|
||||
} /* }}} */
|
||||
|
||||
/**
|
||||
* Convert a pixel image into text by reading the iptc data
|
||||
*
|
||||
* This method uses getimagesize() to extract the data.
|
||||
*/
|
||||
public function convert($infile, $target = null, $params = array()) { /* {{{ */
|
||||
$start = microtime(true);
|
||||
$imsize = getimagesize($infile, $moreinfo);
|
||||
$txt = '';
|
||||
if(!empty($moreinfo['APP13'])) {
|
||||
$iptcdata = iptcparse($moreinfo['APP13']);
|
||||
foreach(['2#005', '2#015', '2#025', '2#105', '2#080', '2#115', '2#120'] as $key) {
|
||||
if(isset($iptcdata[$key]))
|
||||
$txt .= implode(' ', $iptcdata[$key])."\n";
|
||||
}
|
||||
}
|
||||
$end = microtime(true);
|
||||
if($this->logger) {
|
||||
$this->logger->log('Conversion from '.$this->from.' to '.$this->to.' by extracting iptc took '.($end-$start).' sec.', PEAR_LOG_INFO);
|
||||
}
|
||||
if($target) {
|
||||
file_put_contents($target, $txt);
|
||||
return true;
|
||||
} else {
|
||||
return $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