From 825883a667f2ec895858e8c13edb366a055b10bb Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 16 Oct 2023 12:55:35 +0200 Subject: [PATCH] has been moved into extra git repoository --- SeedDMS_Core/CHANGELOG.md | 639 -- SeedDMS_Core/Core.php | 102 - SeedDMS_Core/Core/inc.AccessUtils.php | 94 - SeedDMS_Core/Core/inc.ClassAccess.php | 122 - SeedDMS_Core/Core/inc.ClassAttribute.php | 1401 ---- SeedDMS_Core/Core/inc.ClassDMS.php | 3507 ---------- SeedDMS_Core/Core/inc.ClassDecorator.php | 42 - SeedDMS_Core/Core/inc.ClassDocument.php | 6158 ----------------- .../Core/inc.ClassDocumentCategory.php | 124 - SeedDMS_Core/Core/inc.ClassFolder.php | 2115 ------ SeedDMS_Core/Core/inc.ClassGroup.php | 531 -- SeedDMS_Core/Core/inc.ClassIterator.php | 231 - SeedDMS_Core/Core/inc.ClassKeywords.php | 207 - SeedDMS_Core/Core/inc.ClassNotification.php | 116 - SeedDMS_Core/Core/inc.ClassObject.php | 331 - SeedDMS_Core/Core/inc.ClassUser.php | 1994 ------ SeedDMS_Core/Core/inc.ClassWorkflow.php | 1400 ---- SeedDMS_Core/Core/inc.DBAccessPDO.php | 1018 --- SeedDMS_Core/Core/inc.FileUtils.php | 529 -- SeedDMS_Core/bootstrap-5.php | 3 - SeedDMS_Core/bootstrap-6.php | 3 - SeedDMS_Core/composer.json | 23 - SeedDMS_Core/oldtests/config.php | 10 - SeedDMS_Core/oldtests/getfoldertree.php | 25 - SeedDMS_Core/oldtests/getusers.php | 14 - SeedDMS_Core/oldtests/reverselookup.php | 44 - SeedDMS_Core/package.xml | 2039 ------ SeedDMS_Core/phpunit.xml | 26 - SeedDMS_Core/tests/.phpunit.result.cache | 1 - .../tests/AttributeDefinitionTest.php | 574 -- SeedDMS_Core/tests/AttributeTest.php | 155 - SeedDMS_Core/tests/DatabaseTest.php | 324 - SeedDMS_Core/tests/DmsTest.php | 2956 -------- SeedDMS_Core/tests/DmsWithDataTest.php | 290 - SeedDMS_Core/tests/DocumentCategoryTest.php | 295 - SeedDMS_Core/tests/DocumentContentTest.php | 593 -- SeedDMS_Core/tests/DocumentFileTest.php | 290 - SeedDMS_Core/tests/DocumentLinkTest.php | 125 - SeedDMS_Core/tests/DocumentTest.php | 1323 ---- SeedDMS_Core/tests/FileUtilsTest.php | 219 - SeedDMS_Core/tests/FolderTest.php | 1221 ---- SeedDMS_Core/tests/GroupTest.php | 410 -- SeedDMS_Core/tests/KeywordCategoryTest.php | 147 - SeedDMS_Core/tests/ReviewApprovalTest.php | 477 -- SeedDMS_Core/tests/SeedDmsBase.php | 365 - SeedDMS_Core/tests/UserTest.php | 1679 ----- SeedDMS_Core/tests/WorkflowTest.php | 638 -- SeedDMS_Lucene/CHANGELOG.md | 94 - SeedDMS_Lucene/Lucene.php | 44 - SeedDMS_Lucene/Lucene/IndexedDocument.php | 266 - SeedDMS_Lucene/Lucene/Indexer.php | 208 - SeedDMS_Lucene/Lucene/Search.php | 160 - SeedDMS_Lucene/composer.json | 23 - SeedDMS_Lucene/package.xml | 389 -- SeedDMS_Preview/CHANGELOG.md | 128 - SeedDMS_Preview/Preview.php | 39 - SeedDMS_Preview/Preview/Base.php | 247 - SeedDMS_Preview/Preview/PdfPreviewer.php | 309 - SeedDMS_Preview/Preview/Previewer.php | 371 - SeedDMS_Preview/Preview/TxtPreviewer.php | 306 - SeedDMS_Preview/composer.json | 23 - SeedDMS_Preview/package.xml | 511 -- SeedDMS_Preview/tests/Preview.php | 0 SeedDMS_SQLiteFTS/CHANGELOG.md | 89 - SeedDMS_SQLiteFTS/SQLiteFTS.php | 49 - SeedDMS_SQLiteFTS/SQLiteFTS/Document.php | 117 - SeedDMS_SQLiteFTS/SQLiteFTS/Exception.php | 41 - SeedDMS_SQLiteFTS/SQLiteFTS/Field.php | 88 - .../SQLiteFTS/IndexedDocument.php | 266 - SeedDMS_SQLiteFTS/SQLiteFTS/Indexer.php | 463 -- SeedDMS_SQLiteFTS/SQLiteFTS/QueryHit.php | 72 - SeedDMS_SQLiteFTS/SQLiteFTS/Search.php | 166 - SeedDMS_SQLiteFTS/SQLiteFTS/Term.php | 75 - SeedDMS_SQLiteFTS/composer.json | 23 - SeedDMS_SQLiteFTS/package.xml | 376 - SeedDMS_SQLiteFTS/tests/Index.php | 0 76 files changed, 39873 deletions(-) delete mode 100644 SeedDMS_Core/CHANGELOG.md delete mode 100644 SeedDMS_Core/Core.php delete mode 100644 SeedDMS_Core/Core/inc.AccessUtils.php delete mode 100644 SeedDMS_Core/Core/inc.ClassAccess.php delete mode 100644 SeedDMS_Core/Core/inc.ClassAttribute.php delete mode 100644 SeedDMS_Core/Core/inc.ClassDMS.php delete mode 100644 SeedDMS_Core/Core/inc.ClassDecorator.php delete mode 100644 SeedDMS_Core/Core/inc.ClassDocument.php delete mode 100644 SeedDMS_Core/Core/inc.ClassDocumentCategory.php delete mode 100644 SeedDMS_Core/Core/inc.ClassFolder.php delete mode 100644 SeedDMS_Core/Core/inc.ClassGroup.php delete mode 100644 SeedDMS_Core/Core/inc.ClassIterator.php delete mode 100644 SeedDMS_Core/Core/inc.ClassKeywords.php delete mode 100644 SeedDMS_Core/Core/inc.ClassNotification.php delete mode 100644 SeedDMS_Core/Core/inc.ClassObject.php delete mode 100644 SeedDMS_Core/Core/inc.ClassUser.php delete mode 100644 SeedDMS_Core/Core/inc.ClassWorkflow.php delete mode 100644 SeedDMS_Core/Core/inc.DBAccessPDO.php delete mode 100644 SeedDMS_Core/Core/inc.FileUtils.php delete mode 100644 SeedDMS_Core/bootstrap-5.php delete mode 100644 SeedDMS_Core/bootstrap-6.php delete mode 100644 SeedDMS_Core/composer.json delete mode 100644 SeedDMS_Core/oldtests/config.php delete mode 100644 SeedDMS_Core/oldtests/getfoldertree.php delete mode 100644 SeedDMS_Core/oldtests/getusers.php delete mode 100644 SeedDMS_Core/oldtests/reverselookup.php delete mode 100644 SeedDMS_Core/package.xml delete mode 100644 SeedDMS_Core/phpunit.xml delete mode 100644 SeedDMS_Core/tests/.phpunit.result.cache delete mode 100644 SeedDMS_Core/tests/AttributeDefinitionTest.php delete mode 100644 SeedDMS_Core/tests/AttributeTest.php delete mode 100644 SeedDMS_Core/tests/DatabaseTest.php delete mode 100644 SeedDMS_Core/tests/DmsTest.php delete mode 100644 SeedDMS_Core/tests/DmsWithDataTest.php delete mode 100644 SeedDMS_Core/tests/DocumentCategoryTest.php delete mode 100644 SeedDMS_Core/tests/DocumentContentTest.php delete mode 100644 SeedDMS_Core/tests/DocumentFileTest.php delete mode 100644 SeedDMS_Core/tests/DocumentLinkTest.php delete mode 100644 SeedDMS_Core/tests/DocumentTest.php delete mode 100644 SeedDMS_Core/tests/FileUtilsTest.php delete mode 100644 SeedDMS_Core/tests/FolderTest.php delete mode 100644 SeedDMS_Core/tests/GroupTest.php delete mode 100644 SeedDMS_Core/tests/KeywordCategoryTest.php delete mode 100644 SeedDMS_Core/tests/ReviewApprovalTest.php delete mode 100644 SeedDMS_Core/tests/SeedDmsBase.php delete mode 100644 SeedDMS_Core/tests/UserTest.php delete mode 100644 SeedDMS_Core/tests/WorkflowTest.php delete mode 100644 SeedDMS_Lucene/CHANGELOG.md delete mode 100644 SeedDMS_Lucene/Lucene.php delete mode 100644 SeedDMS_Lucene/Lucene/IndexedDocument.php delete mode 100644 SeedDMS_Lucene/Lucene/Indexer.php delete mode 100644 SeedDMS_Lucene/Lucene/Search.php delete mode 100644 SeedDMS_Lucene/composer.json delete mode 100644 SeedDMS_Lucene/package.xml delete mode 100644 SeedDMS_Preview/CHANGELOG.md delete mode 100644 SeedDMS_Preview/Preview.php delete mode 100644 SeedDMS_Preview/Preview/Base.php delete mode 100644 SeedDMS_Preview/Preview/PdfPreviewer.php delete mode 100644 SeedDMS_Preview/Preview/Previewer.php delete mode 100644 SeedDMS_Preview/Preview/TxtPreviewer.php delete mode 100644 SeedDMS_Preview/composer.json delete mode 100644 SeedDMS_Preview/package.xml delete mode 100644 SeedDMS_Preview/tests/Preview.php delete mode 100644 SeedDMS_SQLiteFTS/CHANGELOG.md delete mode 100644 SeedDMS_SQLiteFTS/SQLiteFTS.php delete mode 100644 SeedDMS_SQLiteFTS/SQLiteFTS/Document.php delete mode 100644 SeedDMS_SQLiteFTS/SQLiteFTS/Exception.php delete mode 100644 SeedDMS_SQLiteFTS/SQLiteFTS/Field.php delete mode 100644 SeedDMS_SQLiteFTS/SQLiteFTS/IndexedDocument.php delete mode 100644 SeedDMS_SQLiteFTS/SQLiteFTS/Indexer.php delete mode 100644 SeedDMS_SQLiteFTS/SQLiteFTS/QueryHit.php delete mode 100644 SeedDMS_SQLiteFTS/SQLiteFTS/Search.php delete mode 100644 SeedDMS_SQLiteFTS/SQLiteFTS/Term.php delete mode 100644 SeedDMS_SQLiteFTS/composer.json delete mode 100644 SeedDMS_SQLiteFTS/package.xml delete mode 100644 SeedDMS_SQLiteFTS/tests/Index.php diff --git a/SeedDMS_Core/CHANGELOG.md b/SeedDMS_Core/CHANGELOG.md deleted file mode 100644 index 8ac741064..000000000 --- a/SeedDMS_Core/CHANGELOG.md +++ /dev/null @@ -1,639 +0,0 @@ -5.1.29 (2022-11-21) ---------------------- -- SeedDMS_Core_Folder::addDocument() does rollback transaction propperly when setting document categories fail -- add $skiproot and $sep parameter to SeedDMS_Core_Folder::getFolderPathPlain() -- add class name for 'documentfile' -- add method SeedDMS_Core_KeywordCategory::countKeywordLists() - -5.1.28 (2022-11-07) ---------------------- -- fix SeedDMS_Core_User::getDocumentContents() -- fix SeedDMS_Core_File::fileExtension() -- SeedDMS_Core_DMS::createPasswordRequest() creates a cryptographically secure hash -- fix sql error when deleting a folder attribute -- add SeedDMS_Core_Attribute::getParsedValue() and use it in SeedDMS_Core_Object::getAttributeValue() -- add SeedDMS_Core_DMS::getDuplicateSequenceNo() and SeedDMS_Core_Folder::reorderDocuments() -- add SeedDMS_Core_File::mimetype(), fix SeedDMS_Core_File::moveDir() -- all file operations use methods of SeedDMS_Core_File -- change namespace of iterators from SeedDMS to SeedDMS\Core - - -5.1.27 (2022-08-31) ---------------------- -- fix SeedDMS_Core_DMS::addAttributeDefinition() when objtype is 0 -- sort search result even if sortorder is 'i' or 'n' -- pass an array as an attribute to search() will OR each element - -5.1.26 (2022-05-20) ---------------------- -- fix validating multi value attributes -- SeedDMS_Core_User::removeFromProcesses() can be limited to a list of documents. In that case only the last version will be modified. -- add more types to getStatisticalData() -- add optional parameter $op to SeedDMS_Core_AttributeDefinition::getObjects() -- SeedDMS_Core_AttributeDefinition::getObjects() will not filter by value if null is passed -- SeedDMS_Core_DMS::getAllAttributeDefinitions() has second parameter to filter attributes by type - -5.1.25 (2022-04-22) ---------------------- -- rename getLastWorkflowTransition() to getLastWorkflowLog() -- getLastWorkflowLog() returns a workflow entry even if the workflow has ended -- backport setFileType() from 6.0.x -- add SeedDMS_Core_File::fileExtension() -- add callbacks on onPostUpdateAttribute, onPostRemoveAttribute, onPostAddAttribute -- fix searching for document content with a custom attribute having a value set - -5.1.24 (2021-12-11) ---------------------- -- in SeedDMS_Core_DocumentContent::removeWorkflow() remove records from tblWorklflowLog before tblDWorkflowDocumentContent -- make all class variables of SeedDMS_Core_User protected -- fix various errors in SeedDMS_Core_AttributeDefinition::validate() -- add lots of unit tests -- replace incorrect use of array_search() by in_array() -- move method SeedDMS_Core_DMS::createDump() into SeedDMS_Core_DatabaseAccess -- lots of parameter checking when calling methods() -- make sure callbacks are callable -- SeedDMS_Core_Folder::getParent() returns null if there is no parent (used to be false) -- SeedDMS_Core_DMS::search() will not find document without an expiration date anymore, if the search is limited by an expiration end date but no start date -- add method SeedDMS_Core_Folder::getFoldersMinMax() -- init internal cache variables of SeedDMS_Core_Folder/SeedDMS_Core_Document and add method clearCache() -- SeedDMS_Core_Folder::hasDocuments() does not use the interal document cache anymore -- SeedDMS_Core_Document::addDocumentLink() returns an object of type SeedDMS_Core_DocumentLink in case of success -- trim email, comment, language, theme when setting data of user -- more checks whether an id > 0 when getting a database record - -5.1.23 (2021-08-19) ---------------------- -- SeedDMS_Core_DMS::getTimeline() uses status log instead of document content -- add methods SeedDMS_Core_DocumentContent::getReviewers() and SeedDMS_Core_DocumentContent::getApprovers() -- add methods SeedDMS_Core_DocumentContent::getApproveLog() and SeedDMS_Core_DocumentContent::getReviewLog() -- better handling of document with an empty workflow state -- fix checking of email addresses by using filter_var instead of regex -- add new method SeedDMS_Core_Document::hasCategory() -- add new method SeedDMS_Core_DocumentContent::removeReview() -- add new method SeedDMS_Core_DocumentContent::removeApproval() -- add new method SeedDMS_Core_User::getFolders() -- add new method SeedDMS_Core_User::getDocumentContents() -- add new method SeedDMS_Core_User::getDocumentFiles() -- add new method SeedDMS_Core_User::getDocumentLinks() -- add new type 'foldersperuser' to method SeedDMS_Core_DMS::getStatisticalData() - -5.1.22 (2021-03-15) ---------------------- -- add SeedDMS_Core_DatabaseAccess::hasTable() -- add SeedDMS_Core_User->isType() and SeedDMS_Core_Group->isType() -- add SeedDMS_Core_User->getDMS() and SeedDMS_Core_Group->getDMS() -- add new parameter to SeedDMS_Core_DMS->getDocumentList() for skipping expired documents -- add parameter $incdisabled to SeedDMS_Core_Folder::getNotifyList() -- do not validate value in SeedDMS_Core_Attribute::setValue(), it should have been done before -- SeedDMS_Core_DMS::search() can search for last date of document status change -- smarter caching in SeedDMS_Core_Document::getDocumentFiles() which fixes a potential - problem when removing a document - -5.1.21 (2020-09-29) ---------------------- -- SeedDMS_Folder_DMS::getAccessList() and getDefaultAccess() do not return fals anymore if the parent does not exists. They just stop inheritance. -- pass attribute value to callback 'onAttributeValidate' -- new paramter 'new' of methode SeedDMЅ_Core_AttributeDefinition::validate() -- check if folder/document is below rootDir can be turned on (default off) -- SeedDMS_Core_User::setHomeFolder() can be used to unset the home folder -- check if attribute definition exists when setting attributes of folders and documents - -5.1.20 (2020-09-29) ---------------------- -- SeedDMS_Core_DMS::getDocumentList() returns false, if an unknown list is passed -- SeedDMS_Core_Document::getDocumentFiles() has new parameter to select only those files attached to a specific version of the document -- removing a document version will not remove attachments of the document anymore -- set dms of new user instances in SeedDMS_Core_Group - -5.1.19 (2020-07-30) ---------------------- -- add method SeedDMS_Core_Document::setParent() as an alias for setFolder() -- clear the save content list and latest content in SeedDMS_Core_Document after - a version has been deleted. -- new method SeedDMS_Core_Document::isLatestVersion() -- add new attribute types 'document', 'folder', 'user', 'group' - -5.1.18 (2020-05-28) ---------------------- -- fixed remaining todos -- fixed parsing of file size in SeedDMS_Core_File::parse_filesize() -- fix SeedDMS_Core_DMS::getDocumentByOriginalFilename() - -5.1.17 (2020-05-22) ---------------------- -- add new callback onSetStatus -- fix SeedDMS_Core_DMS::getExpiredDocuments(), sql statement failed because temp. tables were not created -- add parameters $orderdir, $orderby, $update to SeedDMS_Core::getExpiredDocuments() - -5.1.16 (2020-04-14) ---------------------- -- fix call of hooks in SeedDMS_Core -- add variable lasterror in SeedDMS_Core_DMS which can be set by hooks to pass an - error msg to the calling application -- better error checking in SeedDMS_Core_Document::addDocumentFile() - -5.1.15 (2020-03-02) ---------------------- -- no changes, just keep same version as seeddms application - -5.1.14 (2020-02-17) ---------------------- -- speed up SeedDMS_Core_Folder::getSubFolders() SeedDMS_Core_Folder::getDocuments() by minimizing the number of sql queries. - -5.1.13 (2019-09-06) ---------------------- -- add decorators -- add new methods SeedDMS_Core_Document::isType(), SeedDMS_Core_Folder::isType(), SeedDMS_Core_DocumentContent::isType(). Use them instead of checking the class name. -- skip a fileType with just a '.' - -5.1.12 (2019-07-01) ---------------------- -- parameter $orderby passed to SeedDMS_Core_Folder::getDocuments() and SeedDMS_Core_Folder::getSubFolders() can be a string, but only the first char is evaluated -- SeedDMS_Core_DMS::search() excepts parameters as array, added orderby -- add SeedDMS_Core_Folder::hasSubFolderByName() -- fix SeedDMS_Core_Folder::hasDocumentByName() which returned an int > 0 if documents - has been loaded before and even if the document searching for was not among them. -- add new method SeedDMS_Core_Folder::empty() - -5.1.11 (2019-05-03) ---------------------- -- ??? - -5.1.10 (2019-04-04) ---------------------- -- fix php warning if workflow state doesn' have next transition -- add method SeedDMS_Core_DatabaseAccess::setLogFp() - -5.1.9 (2018-11-13) ---------------------- -- context can be passed to getAccessMode() -- call hook in SeedDMS_Core_Folder::getAccessMode() -- new optional parameter $listguest for SeedDMS_Core_Document::getReadAccessList() -- remove deprecated methods SeedDMS_Core_Document::convert(), SeedDMS_Core_Document::wasConverted(), SeedDMS_Core_Document::viewOnline(), SeedDMS_Core_Document::getUrl() - -5.1.8 (2018-07-02) ---------------------- -- SeedDMS_Core_DMS::search() returns false in case of an error -- do not use views in DBAccessPDO by default anymore, use temp. tables -- SeedDMS_Core_Document::getNotifyList() has new parameter to include disabled user in list -- fix possible sql injection in SeedDMS_Core_User - -5.1.7 (2018-04-05) ---------------------- -- just bump version - -5.1.6 (2018-02-14) ---------------------- -- add SeedDMS_Core_Folder::getDocumentsMinMax() -- add lots of DocBlocks from merge request #8 -- add SeedDMS_Core_AttributeDefinition::removeValue() - -5.1.5 (2017-11-07) ---------------------- -- use views instead of temp. tables -- add list of expired documents in SeedDMS_Core_DMS::getDocumentList() -- add methods to set comment, name, public, version of document files -- add method SeedDMS_Core_Document::transferToUser() -- SeedDMS_Core_Document::addDocumentFile() returns object of file -- add SeedDMS_Core_DocumentFile::setDate() -- remove SeedDMS_Core_DocumentCategory::addCategory() and getCategories() -- add optional parameters $limit and $offset to SeedDMS_Core_Folder::getDocuments() - and SeedDMS_Core_Folder::getSubFolders() -- getInstance() returns now null instead of false if the object was not found in the db -- add new methods SeedDMS_Core_Document::addCategories() and - SeedDMS_Core_Document::removeCategories() - -5.1.4 (2017-09-05) ---------------------- -- add virtual access mode for document links and attachments plus callbacks to - check access mode in a hook -- add new method SeedDMS_Core_DMS::getDocumentsExpired() -- all changes from 5.0.14 merged - -5.1.3 (2017-08-23) ---------------------- -- SeedDMS_Core_Document::getNotifyList() and SeedDMS_Core_Folder::getNotifyList() -returns just users which are not disabled -- add new methods removeFromProcesses(), getWorkflowsInvolved(), getKeywordCategories() to SeedDMS_Core_User -- add methods isMandatoryReviewerOf() and isMandatoryApproverOf() -- add methods transferDocumentsFolders() and transferEvents() -- add method SeedDMS_Core_DMS::getDocumentByOriginalFilename() - -5.1.2 (2017-03-23) ---------------------- -- SeedDMS_Core_DMS::filterDocumentFiles() returns also documents which are not public - if the owner tries to access them -- Check return value of onPreRemove[Document -Folder], return from calling method if bool -- Add SeedDMS_Core_DMS::getDocumentList() -- Limit number of duplicate files to 1000 -- Add hook on(Pre -Post)RemoveContent -- Add hook onAttributeValidate - -5.1.1 (2017-02-20) ---------------------- -- all changes from 5.0.11 merged - -5.1.0 (2017-02-20) ---------------------- -- added postgres support - -5.0.13 (2017-07-13) ---------------------- -- all changes from 4.3.36 merged - -5.0.12 (2017-03-23) ---------------------- -all sql statements can be logged to a file -do not sort some temporary tables anymore, because it causes an error in mysql if sql_mode=only_full_group_by is set - -5.0.11 (2017-02-28) ---------------------- -- all changes from 4.3.34 merged - -5.0.10 (2017-02-20) ---------------------- -- all changes from 4.3.33 merged - -5.0.9 (2016-11-02) ---------------------- -- all changes from 4.3.32 merged - -5.0.8 (2016-11-02) ---------------------- -- all changes from 4.3.31 merged - -5.0.7 (2016-11-02) ---------------------- -- all changes from 4.3.30 merged -- better attribute value checking - -5.0.6 (2016-09-06) ---------------------- -- all changes from 4.3.29 merged - -5.0.5 (2016-08-09) ---------------------- -- all changes from 4.3.28 merged - -5.0.4 (2016-05-03) ---------------------- -- all changes from 4.3.27 merged - -5.0.3 (2016-04-04) ---------------------- -- use classname from SeedDMS_Core_DMS::_classnames for SeedDMS_Core_DocumentContent -- all changes from 4.3.26 merged - -5.0.2 (2016-04-26) ---------------------- -- all changes from 4.3.25 merged - -5.0.1 (2016-01-22) ---------------------- -- all changes from 4.3.24 merged - -5.0.0 (2016-01-22) ---------------------- -- classes can be overloaded -- clean workflow log when a document version was deleted - -4.3.37 (2018-02-14) ---------------------- -- SeedDMS_Core_DMS::search() finds documents without a status log - -4.3.36 (2017-03-22) ---------------------- -- fix sql statement for creating temp. tables (sqlite) - -4.3.35 (2017-07-11) ---------------------- -do not sort some temporary tables anymore, because it causes an error in mysql if sql_mode=only_full_group_by is set - -4.3.34 (2017-02-28) ---------------------- -SeedDMS_Core_DMS::getDuplicateDocumentContent() returns complete document - -4.3.33 (2017-02-22) ---------------------- -- SeedDMЅ_Core_DMS::getTimeline() no longer returns duplicate documents -- SeedDMЅ_Core_Document::addContent() sets workflow after status was set -- SeedDMЅ_Core_Keyword::setOwner() fix sql statement -- SeedDMЅ_Core_User::setFullname() minor fix in sql statement - -4.3.32 (2017-01-12) ---------------------- -- order groups by name returned by getReadAccessList() -- add optional parameter to SeedDMS_Core_DMS::filterDocumentLinks() -- SeedDMS_Core_DMS::search() can search for document/folder id - -4.3.31 (2016-11-02) ---------------------- -- new method SeedDMЅ_Core_WorkflowAction::getTransitions() -- new method SeedDMЅ_Core_WorkflowState::getTransitions() -- new method SeedDMЅ_Core_AttributeDefinition::parseValue() -- add check for cycles in workflow SeedDMS_Core_Workflow::checkForCycles() - -4.3.30 (2016-10-07) ---------------------- -- new method SeedDMЅ_Core_AttributeDefinition::getValueSetSeparator() -- trim each value of a value set before saving the complete value set as a string - -4.3.29 (2016-09-06) ---------------------- -- SeedDMЅ_Core_Object::getAttributes() orders attributes by name of attribute definition -- SeedDMЅ_Core_Workflow::addTransition() force reload of transition list after adding a -- SeedDMЅ_Core_Document::rewrite[Review -Approval]Log() will also copy file if it exists -- add method SeedDMЅ_Core_Document::rewriteWorkflowLog() - -4.3.28 (2016-08-24) ---------------------- -- SeedDMЅ_Core_DMS::search() searches also comment of document version - -4.3.27 (2016-04-26) ---------------------- -- callbacks can have more then one user function -- fix some sql statements, because they didn't work with mysql 5.7.5 anymore - -4.3.26 (2016-04-04) ---------------------- -- add more callbacks - -4.3.25 (2016-03-08) ---------------------- -- rename SeedDMS_Core_Group::getNotificationsByGroup() to getNotifications() -- use __construct() for all constructors -- fix setting multi value attributes for versions - -4.3.24 (2016-01-22) ---------------------- -- make sure boolean attribute is saved as 0/1 -- add SeedDMS_Core_User::[g -s]etMandatoryWorkflows() -- add SeedDMS_Core_User::getNotifications() -- add SeedDMS_Core_Group::getNotifications() -- SeedDMS_Core_DMS::getNotificationsByGroup() and -SeedDMS_Core_DMS::getNotificationsByUser() are deprecated -- SeedDMS_Core_DocumentCategory::getDocumentsByCategory() now returns the documents -- add SeedDMS_Core_Group::getWorkflowStatus() -- SeedDMS_Core_User::getDocumentsLocked() sets locking user propperly - -4.3.24 (2016-01-21) ---------------------- -- make sure boolean attribute is saved as 0/1 -- add SeedDMS_Core_User::[g -s]etMandatoryWorkflows() -- add SeedDMS_Core_User::getNotifications() -- add SeedDMS_Core_Group::getNotifications() -- SeedDMS_Core_DMS::getNotificationsByGroup() and -SeedDMS_Core_DMS::getNotificationsByUser() are deprecated -- SeedDMS_Core_DocumentCategory::getDocumentsByCategory() now returns the documents -- add SeedDMS_Core_Group::getWorkflowStatus() -- SeedDMS_Core_User::getDocumentsLocked() sets locking user propperly - -4.3.23 (2016-01-21) ---------------------- -- new method SeedDMS_Core_DMS::createDump() -- minor improvements int SeedDMS_Core_Document::getReadAccessList() - -4.3.22 (2015-11-09) ---------------------- -- fix sql statement to reset password -- pass some more information for timeline - -4.3.21 (2015-09-28) ---------------------- -- add method SeedDMS_Core_Database::getCurrentTimestamp() -- add method SeedDMS_Core_Database::getCurrentDatetime() -- user getCurrentTimestamp() and getCurrentDatetime() whenever possible - -4.3.20 (2015-06-26) ---------------------- -- add method SeedDMS_Core_DMS::checkDate() -- add method SeedDMS_Core_Document::setDate() -- add method SeedDMS_Core_Folder::setDate() -- date can be passed to SeedDMS_Core_DocumentContent::setStatus() -- add method SeedDMS_Core_DocumentContent::rewriteStatusLog() -- add method SeedDMS_Core_DocumentContent::rewriteReviewLog() -- add method SeedDMS_Core_DocumentContent::rewriteApprovalLog() -- access rights for guest are also taken into account if set in an acl. Previously guest could gain read rights even if the access was probibited -by a group or user right - -4.3.19 (2015-06-26) ---------------------- -- add optional paramter $noclean to clearAccessList(), setDefaultAccess(), setInheritAccess() -- clearAccessList() will clean up the notifier list -- new method cleanNotifyList() - -4.3.18 (2015-06-09) ---------------------- -- add optional paramter $msg to SeedDMS_Core_DocumentContent::verifyStatus() -- add method SeedDMS_Core_DMS::getDuplicateDocumentContent() - -4.3.17 (2015-03-27) ---------------------- -clean workflow log when a document version was deleted - -4.3.16 (2015-03-20) ---------------------- -no changes - -4.3.15 (2015-02-12) ---------------------- -users returned by SeedDMS_Core_DMS::getAllUsers() have language and theme set again - -4.3.13 (2014-11-27) ---------------------- -- fix searching for attributes -- add some more documentation -- SeedDMS_Core_DMS::getDocumentCategories() returns categories sorted by name (Bug #181) -- new methode SeedDMS_Core_Document::replaceContent() which replaces the content of a version. - 4.3.14 -- add missing start transaction in SeedDMD_Core_Folder::remove() -- SeedDMD_Core_Folder::isSubFolder() doesn't compare object instances anymore (Bug #194) - -4.3.12 (2014-11-17) ---------------------- -- fix searching folders with multivalue attributes - -4.3.11 (2014-11-13) ---------------------- -- fixed saving multivalue attributes -- add method SeedDMS_Core_Attribute::getValueAsArray() - -4.3.10 (2014-10-22) ---------------------- -new release - -4.3.9 (2014-07-30) ---------------------- -- SeedDMS_Core_KeywordCategory::getKeywordLists() sorts keywords aphabetically -- SeedDMS_Core_DMS::addUser() doesn't throw an error if sql_mode is set to STRICT_TRANS_TABLES and pwdexpiration is not set to a valid date. - -4.3.8 (2014-04-09) ---------------------- -- new method SeedDMS_Core_DMS::getStatisticalData() - -4.3.7 (2014-03-21) ---------------------- -no changes - -4.3.6 (2014-03-18) ---------------------- -- add optional parameters $publiconly=false and $user=null to SeedDMS_Core_Document::getDocumentLinks() -- add new method SeedDMS_Core_Document::getReverseDocumentLinks() - -4.3.5 (2014-03-04) ---------------------- -no changes - -4.3.4 (2014-02-01) ---------------------- -- fix handling of multivalue attributes - -4.3.3 (2014-02-01) ---------------------- -- SeedDMS_Folder::getDocuments() and SeedDMS_Folder::getSubFolders() do not - do any sorting if $orderby is not set. -- database hostname can have port seperated by ':' -- make all functions in SeedDMS_Core_File static (fixes problem with php 5.5.x) - -4.3.2 (2013-11-27) ---------------------- -- new method SeedDMS_Core_Folder::isSubFolder() -- check for subFolder in SeedDMS_Core_Folder::setParent() -- new methods SeedDMS_Core_DMS::checkFolders() and SeedDMS_Core_DMS::checkDocuments() - -4.3.0 (2013-09-05) ---------------------- -- various small corrections -- comment of version is no longer taken from document if version comment is empty -- passing an array of users to SeedDMЅ_Core_DMS::search() instead of a single user ist now allowed -- turn on foreign key constraints for sqlite3 -- SeedDMЅ_Core_Folder::getPath() can handle a subfolder treated as a root folder - -4.2.2 (2013-05-17) ---------------------- -- admins can be added as reviewer/approver again - -4.2.1 (2013-04-30) ---------------------- -- fixed bug in SeedDMS_Core_DocumentContent::addIndApp() - -4.2.0 (2013-04-22) ---------------------- -- fixed bug in SeedDMS_Core_DocumentContent::addIndApp() - -4.1.3 (2013-04-08) ---------------------- -- stay in sync with seeddms application - -4.1.2 (2013-04-05) ---------------------- -- set propper folderList of sub folders after moving a folder - -4.1.1 (2013-04-05) ---------------------- -- stay in sync with seeddms application - -4.1.0 (2013-03-28) ---------------------- -- minor bugfixes - -4.0.0 (2013-02-26) ---------------------- -- minor bugfixes - -4.0.0pre5 (2013-02-14) ---------------------- -- changed name from letodms to seeddms -- fixed SeedDMS_Database::TableList() - -4.0.0pre4 (2013-02-11) ---------------------- -- calculate checksum for document versions -- some bug fixes -- some more documentation -- added new methods SeedDMS_Core_Document::getReadUserList() and - SeedDMS_Core_Folder::getReadUserList() which replaces getApproversList() -- fixed sql statement in getReadUserList() for sqlite3 - -4.0.0pre3 (2013-02-08) ---------------------- -- minor bug fixes - -4.0.0pre2 (2013-02-06) ---------------------- -- lots of bug fixes -- replaced more of old var declaration -- more code documentation - -4.0.0pre1 (2013-01-24) ---------------------- -- added database transactions -- new workflow -- replaced old var declaration - -4.0.0RC1 (2013-02-20) ---------------------- -- minor bugfixes - -3.4.0 (2012-12-13) ---------------------- -- added PDO database driver, several sql changes for better compatiblity -- fixed bug when adding a new document category -- make sure the database remains consistent even in case of errors - -3.3.9 (2012-09-19) ---------------------- -- version update to be in sync with letodms application - -3.3.8 (2012-09-16) ---------------------- -- more sql injection protection in LetoDMS_Core_User - -3.3.7 (2012-08-25) ---------------------- -- no changes, just keep same version as letodms application - -3.3.6 (2012-07-16) ---------------------- -- no changes, just keep same version as letodms application - -3.3.5 (2012-04-30) ---------------------- -- minor corrections - -3.3.4 (2012-04-11) ---------------------- -- fixed bug in LetoDMS_Core_DocumentFile::getPath() - -3.3.3 (2012-03-28) ---------------------- -- fixed bug in LetoDMS_Core_Document::getPath() - -3.3.2 (2012-03-22) ---------------------- -- fixed bug in LetoDMS_Core_Document::getDir() - -3.3.1 (2012-03-21) ---------------------- -- new release - -3.3.0 (2012-02-08) ---------------------- -- added methods to find and repair errors in document and folder records -- removed sendmail parameter from some methods in LetoDMS_Core_Document -- do not use some of the temporay tables anymore -- SetFetchMode(ADODB_FETCH_ASSOC) in LetoDMS_Core_DatabaseAccess::connect() - -3.2.0 (2011-07-23) ---------------------- -New release - -3.0.0 (2010-04-27) ---------------------- -Initial release - diff --git a/SeedDMS_Core/Core.php b/SeedDMS_Core/Core.php deleted file mode 100644 index 13cf1d142..000000000 --- a/SeedDMS_Core/Core.php +++ /dev/null @@ -1,102 +0,0 @@ - - * @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_File - */ -require_once('Core/inc.ClassIterator.php'); diff --git a/SeedDMS_Core/Core/inc.AccessUtils.php b/SeedDMS_Core/Core/inc.AccessUtils.php deleted file mode 100644 index 1edbce647..000000000 --- a/SeedDMS_Core/Core/inc.AccessUtils.php +++ /dev/null @@ -1,94 +0,0 @@ - - * @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); diff --git a/SeedDMS_Core/Core/inc.ClassAccess.php b/SeedDMS_Core/Core/inc.ClassAccess.php deleted file mode 100644 index c9ef9ffcd..000000000 --- a/SeedDMS_Core/Core/inc.ClassAccess.php +++ /dev/null @@ -1,122 +0,0 @@ - - * @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 - * @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 - * @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; - } -} /* }}} */ diff --git a/SeedDMS_Core/Core/inc.ClassAttribute.php b/SeedDMS_Core/Core/inc.ClassAttribute.php deleted file mode 100644 index 945b1b0c2..000000000 --- a/SeedDMS_Core/Core/inc.ClassAttribute.php +++ /dev/null @@ -1,1401 +0,0 @@ - - * @copyright Copyright (C) 2012 Uwe Steinmann - * @version Release: @package_version@ - */ - -/** - * Class to represent an attribute in the document management system - * - * Attributes are key/value pairs which can be attachted to documents, - * folders and document content. The number of attributes is unlimited. - * Each attribute has a value and is related to an attribute definition, - * which holds the name and other information about the attribute. - * - * @see SeedDMS_Core_AttributeDefinition - * - * @category DMS - * @package SeedDMS_Core - * @author Uwe Steinmann - * @copyright Copyright (C) 2012-2013 Uwe Steinmann - * @version Release: @package_version@ - */ -class SeedDMS_Core_Attribute { /* {{{ */ - /** - * @var integer id of attribute - * - * @access protected - */ - protected $_id; - - /** - * @var SeedDMS_Core_Folder|SeedDMS_Core_Document|SeedDMS_Core_DocumentContent SeedDMS_Core_Object folder, document or document content - * this attribute belongs to - * - * @access protected - */ - protected $_obj; - - /** - * @var SeedDMS_Core_AttributeDefinition definition of this attribute - * - * @access protected - */ - protected $_attrdef; - - /** - * @var mixed value of this attribute - * - * @access protected - */ - protected $_value; - - /** - * @var integer validation error - * - * @access protected - */ - protected $_validation_error; - - /** - * @var SeedDMS_Core_DMS reference to the dms instance this attribute belongs to - * - * @access protected - */ - protected $_dms; - - /** - * SeedDMS_Core_Attribute constructor. - * @param $id - * @param $obj - * @param $attrdef - * @param $value - */ - function __construct($id, $obj, $attrdef, $value) { /* {{{ */ - $this->_id = $id; - $this->_obj = $obj; - $this->_attrdef = $attrdef; - $this->_value = $value; - $this->_validation_error = 0; - $this->_dms = null; - } /* }}} */ - - /** - * Set reference to dms - * - * @param SeedDMS_Core_DMS $dms - */ - function setDMS($dms) { /* {{{ */ - $this->_dms = $dms; - } /* }}} */ - - /** - * Get dms of attribute - * - * @return object $dms - */ - function getDMS() { return $this->_dms; } - - /** - * Get internal id of attribute - * - * @return integer id - */ - function getID() { return $this->_id; } - - /** - * Return attribute value as stored in database - * - * This function will return the value of multi value attributes - * including the separator char. - * - * @return string the attribute value as it is stored in the database. - */ - function getValue() { return $this->_value; } - - /** - * Return attribute value parsed into a php type or object - * - * This function will return the value of multi value attributes - * including the separator char. - * - * @return string the attribute value as it is stored in the database. - */ - function getParsedValue() { /* {{{ */ - switch($this->_attrdef->getType()) { - case SeedDMS_Core_AttributeDefinition::type_float: - return (float) $this->_value; - case SeedDMS_Core_AttributeDefinition::type_boolean: - return (bool) $this->_value; - case SeedDMS_Core_AttributeDefinition::type_int: - return (int) $this->_value; - default: - return $this->_value; - } - } /* }}} */ - - /** - * Return attribute values as an array - * - * This function returns the attribute value as an array. The array - * has one element for non multi value attributes and n elements for - * multi value attributes. - * - * @return array the attribute values - */ - function getValueAsArray() { /* {{{ */ - if($this->_attrdef->getMultipleValues()) { - /* 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. - */ - $sep = substr($this->_value, 0, 1); - if(!($vsep = $this->_attrdef->getValueSetSeparator())) - $vsep = $sep; - if($sep == $vsep) - return(explode($sep, substr($this->_value, 1))); - else - return(array($this->_value)); - } else { - return array($this->_value); - } - } /* }}} */ - - /** - * Set a value of an attribute - * - * The attribute is completely deleted if the value is an empty string - * or empty array. An array of values is only allowed if the attribute may - * have multiple values. If an array is passed and the attribute may - * have only a single value, then the first element of the array will - * be taken. - * - * @param string $values value as string or array to be set - * @return boolean true if operation was successfull, otherwise false - */ - function setValue($values) { /* {{{*/ - $db = $this->_dms->getDB(); - - if($this->_attrdef->getMultipleValues()) { - $valuesetstr = $this->_attrdef->getValueSet(); - /* Multiple values without a value set is not allowed */ - /* No need to have valueset anymore. If none is given, the values are - * expected to be separated by ',' - if(!$valuesetstr) - return false; - */ - $valueset = $this->_attrdef->getValueSetAsArray(); - - if(is_array($values)) { - if($values) { - $vsep = $this->_attrdef->getValueSetSeparator(); - if($valueset) { - /* Validation should have been done before - $error = false; - foreach($values as $v) { - if(!in_array($v, $valueset)) { $error = true; break; } - } - if($error) - return false; - */ - $valuesetstr = $this->_attrdef->getValueSet(); - $value = $vsep.implode($vsep, $values); - } else { - $value = $vsep.implode($vsep, $values); - } - } else { - $value = ''; - } - } else { - if($values) { - if($valuesetstr) { - if($valuesetstr[0] != $values[0]) - $values = explode($valuesetstr[0], $values); - else - $values = explode($valuesetstr[0], substr($values, 1)); - } else { - $values = explode(',', substr($values, 1)); - } - - if($valueset) { - /* Validation should have been done before - $error = false; - foreach($values as $v) { - if(!in_array($v, $valueset)) { $error = true; break; } - } - if($error) - return false; - */ - $value = $valuesetstr[0].implode($valuesetstr[0], $values); - } else { - $value = ','.implode(',', $values); - } - } else { - $value = $values; - } - } - } else { - if(is_array($values)) { - if($values) - $value = $values[0]; - else - $value = ''; - } else { - $value = $values; - } - } - - switch(get_class($this->_obj)) { - case $this->_dms->getClassname('document'): - if(trim($value) === '') - $queryStr = "DELETE FROM `tblDocumentAttributes` WHERE `document` = " . $this->_obj->getID() . " AND `attrdef` = " . $this->_attrdef->getId(); - else - $queryStr = "UPDATE `tblDocumentAttributes` SET `value` = ".$db->qstr($value)." WHERE `document` = " . $this->_obj->getID() . " AND `attrdef` = " . $this->_attrdef->getId(); - break; - case $this->_dms->getClassname('documentcontent'): - if(trim($value) === '') - $queryStr = "DELETE FROM `tblDocumentContentAttributes` WHERE `content` = " . $this->_obj->getID() . " AND `attrdef` = " . $this->_attrdef->getId(); - else - $queryStr = "UPDATE `tblDocumentContentAttributes` SET `value` = ".$db->qstr($value)." WHERE `content` = " . $this->_obj->getID() . " AND `attrdef` = " . $this->_attrdef->getId(); - break; - case $this->_dms->getClassname('folder'): - if(trim($value) === '') - $queryStr = "DELETE FROM `tblFolderAttributes` WHERE `folder` = " . $this->_obj->getID() . " AND `attrdef` = " . $this->_attrdef->getId(); - else - $queryStr = "UPDATE `tblFolderAttributes` SET `value` = ".$db->qstr($value)." WHERE `folder` = " . $this->_obj->getID() . " AND `attrdef` = " . $this->_attrdef->getId(); - break; - default: - return false; - } - if (!$db->getResult($queryStr)) - return false; - - $oldvalue = $this->_value; - $this->_value = $value; - - /* Check if 'onPostUpdateAttribute' callback is set */ - if(isset($this->_dms->callbacks['onPostUpdateAttribute'])) { - foreach($this->_dms->callbacks['onPostUpdateAttribute'] as $callback) { - if(!call_user_func($callback[0], $callback[1], $this->_obj, $this->_attrdef, $value, $oldvalue)) { - } - } - } - - return true; - } /* }}} */ - - /** - * Validate attribute value - * - * This function checks if the attribute values fits the attribute - * definition. - * If the validation fails the validation error will be set which - * can be requested by SeedDMS_Core_Attribute::getValidationError() - * - * @return boolean true if validation succeeds, otherwise false - */ - function validate() { /* {{{ */ - /** @var SeedDMS_Core_AttributeDefinition $attrdef */ - $attrdef = $this->_attrdef; - $result = $attrdef->validate($this->_value); - $this->_validation_error = $attrdef->getValidationError(); - return $result; - } /* }}} */ - - /** - * Get validation error from last validation - * - * @return integer error code - */ - function getValidationError() { return $this->_validation_error; } - - /** - * Set validation error - * - * @param integer error code - */ - function setValidationError($error) { $this->_validation_error = $error; } - - /** - * Get definition of attribute - * - * @return object attribute definition - */ - function getAttributeDefinition() { return $this->_attrdef; } - -} /* }}} */ - -/** - * Class to represent an attribute definition in the document management system - * - * Attribute definitions specify the name, type, object type, minimum and - * maximum values and a value set. The object type determines the object - * an attribute may be attached to. If the object type is set to object_all - * the attribute can be used for documents, document content and folders. - * - * The type of an attribute specifies the skalar data type. - * - * Attributes for which multiple values are allowed must have the - * multiple flag set to true and specify a value set. A value set - * is a string consisting of n separated values. The separator is the - * first char of the value set. A possible value could be '|REV-A|REV-B' - * If multiple values are allowed, then minvalues and maxvalues may - * restrict the allowed number of values. - * - * @see SeedDMS_Core_Attribute - * - * @category DMS - * @package SeedDMS_Core - * @author Markus Westphal, Malcolm Cowe, Uwe Steinmann - * @copyright Copyright (C) 2012 Uwe Steinmann - * @version Release: @package_version@ - */ -class SeedDMS_Core_AttributeDefinition { /* {{{ */ - /** - * @var integer id of attribute definition - * - * @access protected - */ - protected $_id; - - /** - * @var string name of attribute definition - * - * @access protected - */ - protected $_name; - - /** - * @var string object type of attribute definition. This can be one of - * type_int, type_float, type_string, type_boolean, type_url, or type_email. - * - * @access protected - */ - protected $_type; - - /** - * @var string type of attribute definition. This can be one of objtype_all, - * objtype_folder, objtype_document, or objtype_documentcontent. - * - * @access protected - */ - protected $_objtype; - - /** - * @var boolean whether an attribute can have multiple values - * - * @access protected - */ - protected $_multiple; - - /** - * @var integer minimum values of an attribute - * - * @access protected - */ - protected $_minvalues; - - /** - * @var integer maximum values of an attribute - * - * @access protected - */ - protected $_maxvalues; - - /** - * @var string list of possible values of an attribute - * - * @access protected - */ - protected $_valueset; - - /** - * @var string regular expression the value must match - * - * @access protected - */ - protected $_regex; - - /** - * @var integer validation error - * - * @access protected - */ - protected $_validation_error; - - /** - * @var SeedDMS_Core_DMS reference to the dms instance this attribute definition belongs to - * - * @access protected - */ - protected $_dms; - - /** - * @var string just the separator of a value set (not used) - * - * @access protected - */ - protected $_separator; - - /* - * Possible skalar data types of an attribute - */ - const type_int = '1'; - const type_float = '2'; - const type_string = '3'; - const type_boolean = '4'; - const type_url = '5'; - const type_email = '6'; - const type_date = '7'; - - /* - * Addtional data types of an attribute representing objects in seeddms - */ - const type_folder = '101'; - const type_document = '102'; - //const type_documentcontent = '103'; - const type_user = '104'; - const type_group = '105'; - - /* - * The object type for which a attribute may be used - */ - const objtype_all = '0'; - const objtype_folder = '1'; - const objtype_document = '2'; - const objtype_documentcontent = '3'; - - /* - * The validation error codes - */ - const val_error_none = 0; - const val_error_min_values = 1; - const val_error_max_values = 2; - const val_error_boolean = 8; - const val_error_int = 6; - const val_error_date = 9; - const val_error_float = 7; - const val_error_regex = 3; - const val_error_email = 5; - const val_error_url = 4; - const val_error_document = 10; - const val_error_folder = 11; - const val_error_user = 12; - const val_error_group = 13; - const val_error_valueset = 14; - - /** - * Constructor - * - * @param integer $id internal id of attribute definition - * @param string $name name of attribute - * @param integer $objtype type of object for which this attribute definition - * may be used. - * @param integer $type skalar type of attribute - * @param boolean $multiple set to true if multiple values are allowed - * @param integer $minvalues minimum number of values - * @param integer $maxvalues maximum number of values - * @param string $valueset separated list of allowed values, the first char - * is taken as the separator - * @param $regex - */ - function __construct($id, $name, $objtype, $type, $multiple, $minvalues, $maxvalues, $valueset, $regex) { /* {{{ */ - $this->_id = $id; - $this->_name = $name; - $this->_type = $type; - $this->_objtype = $objtype; - $this->_multiple = $multiple; - $this->_minvalues = $minvalues; - $this->_maxvalues = $maxvalues; - $this->_valueset = $valueset; - $this->_separator = substr($valueset, 0, 1); - $this->_regex = $regex; - $this->_dms = null; - $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_none; - } /* }}} */ - - /** - * Set reference to dms - * - * @param SeedDMS_Core_DMS $dms - */ - function setDMS($dms) { /* {{{ */ - $this->_dms = $dms; - } /* }}} */ - - /** - * Get dms of attribute definition - * - * @return object $dms - */ - function getDMS() { return $this->_dms; } - - /** - * Get internal id of attribute definition - * - * @return integer id - */ - function getID() { return $this->_id; } - - /** - * Get name of attribute definition - * - * @return string name - */ - function getName() { return $this->_name; } - - function setName($name) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblAttributeDefinitions` SET `name` =".$db->qstr($name)." WHERE `id` = " . $this->_id; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - $this->_name = $name; - return true; - } /* }}} */ - - /** - * Get object type of attribute definition - * - * This can be one of objtype_all, - * objtype_folder, objtype_document, or objtype_documentcontent. - * - * @return integer type - */ - function getObjType() { return $this->_objtype; } - - /** - * Set object type of attribute definition - * - * This can be one of objtype_all, - * objtype_folder, objtype_document, or objtype_documentcontent. - * - * @param integer $objtype type - * @return bool - */ - function setObjType($objtype) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblAttributeDefinitions` SET `objtype` =".intval($objtype)." WHERE `id` = " . $this->_id; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - $this->_objtype = $objtype; - return true; - } /* }}} */ - - /** - * Get type of attribute definition - * - * This can be one of type_int, type_float, type_string, type_boolean, - * type_url, type_email. - * - * @return integer type - */ - function getType() { return $this->_type; } - - /** - * Set type of attribute definition - * - * This can be one of type_int, type_float, type_string, type_boolean, - * type_url, type_email. - * - * @param integer $type type - * @return bool - */ - function setType($type) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblAttributeDefinitions` SET `type` =".intval($type)." WHERE `id` = " . $this->_id; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - $this->_type = $type; - return true; - } /* }}} */ - - /** - * Check if attribute definition allows multi values for attribute - * - * @return boolean true if attribute may have multiple values - */ - function getMultipleValues() { return $this->_multiple; } - - /** - * Set if attribute definition allows multi values for attribute - * - * @param boolean $mv true if attribute may have multiple values, otherwise - * false - * @return bool - */ - function setMultipleValues($mv) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblAttributeDefinitions` SET `multiple` =".intval($mv)." WHERE `id` = " . $this->_id; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - $this->_multiple = $mv; - return true; - } /* }}} */ - - /** - * Return minimum number of values for attributes - * - * Attributes with multiple values may be limited to a range - * of values. This functions returns the minimum number of values. - * - * @return integer minimum number of values - */ - function getMinValues() { return $this->_minvalues; } - - function setMinValues($minvalues) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblAttributeDefinitions` SET `minvalues` =".intval($minvalues)." WHERE `id` = " . $this->_id; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - $this->_minvalues = $minvalues; - return true; - } /* }}} */ - - /** - * Return maximum number of values for attributes - * - * Attributes with multiple values may be limited to a range - * of values. This functions returns the maximum number of values. - * - * @return integer maximum number of values - */ - function getMaxValues() { return $this->_maxvalues; } - - function setMaxValues($maxvalues) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblAttributeDefinitions` SET `maxvalues` =".intval($maxvalues)." WHERE `id` = " . $this->_id; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - $this->_maxvalues = $maxvalues; - return true; - } /* }}} */ - - /** - * Get the value set as saved in the database - * - * This is a string containing the list of valueѕ separated by a - * delimiter which also precedes the whole string, e.g. '|Yes|No' - * - * Use {@link SeedDMS_Core_AttributeDefinition::getValueSetAsArray()} - * for a list of values returned as an array. - * - * @return string value set - */ - function getValueSet() { /* {{{ */ - return $this->_valueset; - } /* }}} */ - - /** - * Get the separator used for the value set - * - * This is the first char of the value set string. - * - * @return string separator or an empty string if a value set is not set - */ - function getValueSetSeparator() { /* {{{ */ - if(strlen($this->_valueset) > 1) { - return $this->_valueset[0]; - } elseif($this->_multiple) { - if($this->_type == SeedDMS_Core_AttributeDefinition::type_boolean) - return ''; - else - return ','; - } else { - return ''; - } - } /* }}} */ - - /** - * Get the whole value set as an array - * - * Each element is trimmed. - * - * @return array values of value set or false if the value set has - * less than 2 chars - */ - function getValueSetAsArray() { /* {{{ */ - if(strlen($this->_valueset) > 1) - return array_map('trim', explode($this->_valueset[0], substr($this->_valueset, 1))); - else - return array(); - } /* }}} */ - - /** - * Get the n'th trimmed value of a value set - * - * @param $ind starting from 0 for the first element in the value set - * @return string n'th value of value set or false if the index is - * out of range or the value set has less than 2 chars - * @internal param int $index - */ - function getValueSetValue($ind) { /* {{{ */ - if(strlen($this->_valueset) > 1) { - $tmp = explode($this->_valueset[0], substr($this->_valueset, 1)); - if(isset($tmp[$ind])) - return trim($tmp[$ind]); - else - return false; - } else - return false; - } /* }}} */ - - /** - * Set the value set - * - * A value set is a list of values allowed for an attribute. The values - * are separated by a char which must also be the first char of the - * value set string. The method decomposes the value set, removes all - * leading and trailing white space from the elements and recombines them - * into a string. - * - * @param string $valueset - * @return boolean true if value set could be set, otherwise false - */ - function setValueSet($valueset) { /* {{{ */ - /* - $tmp = array(); - foreach($valueset as $value) { - $tmp[] = str_replace('"', '""', $value); - } - $valuesetstr = implode(",", $tmp); - */ - $valueset = trim($valueset); - if($valueset) { - $valuesetarr = array_map('trim', explode($valueset[0], substr($valueset, 1))); - $valuesetstr = $valueset[0].implode($valueset[0], $valuesetarr); - } else { - $valuesetstr = ''; - } - - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblAttributeDefinitions` SET `valueset` =".$db->qstr($valuesetstr)." WHERE `id` = " . $this->_id; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - $this->_valueset = $valuesetstr; - $this->_separator = substr($valuesetstr, 0, 1); - return true; - } /* }}} */ - - /** - * Get the regular expression as saved in the database - * - * @return string regular expression - */ - function getRegex() { /* {{{ */ - return $this->_regex; - } /* }}} */ - - /** - * Set the regular expression - * - * A value of the attribute must match this regular expression. - * - * The methods checks if the regular expression is valid by running - * preg_match() on an empty string and see if it fails. Trying to set - * an invalid regular expression will not overwrite the current - * regular expression. - * - * All leading and trailing spaces of $regex will be removed. - * - * @param string $regex - * @return boolean true if regex could be set or is invalid, otherwise false - */ - function setRegex($regex) { /* {{{ */ - $db = $this->_dms->getDB(); - - $regex = trim($regex); - if($regex && @preg_match($regex, '') === false) - return false; - - $queryStr = "UPDATE `tblAttributeDefinitions` SET `regex` =".$db->qstr($regex)." WHERE `id` = " . $this->_id; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - $this->_regex = $regex; - return true; - } /* }}} */ - - /** - * Check if the attribute definition is used - * - * Checks all documents, folders and document content whether at least - * one of them referenceѕ this attribute definition - * - * @return boolean true if attribute definition is used, otherwise false - */ - function isUsed() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT * FROM `tblDocumentAttributes` WHERE `attrdef`=".$this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_array($resArr) && count($resArr) == 0) { - $queryStr = "SELECT * FROM `tblFolderAttributes` WHERE `attrdef`=".$this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_array($resArr) && count($resArr) == 0) { - $queryStr = "SELECT * FROM `tblDocumentContentAttributes` WHERE `attrdef`=".$this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_array($resArr) && count($resArr) == 0) { - - return false; - } - } - } - return true; - } /* }}} */ - - /** - * Parse a given value according to attribute definition - * - * The return value is always an array, even if the attribute is a single - * value attribute. If the type of attribute is any of document, folder, user, - * or group then this method will fetch each object from the database and - * return an array of SeedDMS_Core_Document, SeedDMS_Core_Folder, etc. - * - * @param $value string - * @return array|bool - */ - function parseValue(string $value) { /* {{{ */ - if($this->getMultipleValues()) { - /* 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. - */ - $sep = substr($value, 0, 1); - $vsep = $this->getValueSetSeparator(); - if($sep == $vsep) - $values = explode($sep, substr($value, 1)); - else - $values = array($value); - } else { - $values = array($value); - } - - switch((string) $this->getType()) { - case self::type_document: - foreach($values as $value) { - if($u = $this->_dms->getDocument((int) $value)) - $tmp[] = $u->getName(); - else - $tmp[] = '???'; - } - $values = $tmp; - break; - case self::type_folder: - foreach($values as $value) { - if($u = $this->_dms->getFolder((int) $value)) - $tmp[] = $u->getName(); - else - $tmp[] = '???'; - } - $values = $tmp; - break; - case self::type_user: - foreach($values as $value) { - if($u = $this->_dms->getUser((int) $value)) - $tmp[] = $u->getLogin(); - else - $tmp[] = '???'; - } - $values = $tmp; - break; - case self::type_group: - foreach($values as $value) { - if($u = $this->_dms->getGroup((int) $value)) - $tmp[] = $u->getName(); - else - $tmp[] = '???'; - } - $values = $tmp; - break; - } - return $values; - } /* }}} */ - - /** - * Return a list of documents, folders, document contents where this - * attribute definition is used - * - * @param integer $limit return not more the n objects of each type - * @return array|bool - */ - function getStatistics($limit=0) { /* {{{ */ - $db = $this->_dms->getDB(); - - $result = array('docs'=>array(), 'folders'=>array(), 'contents'=>array()); - if($this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_all || - $this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_document) { - $queryStr = "SELECT * FROM `tblDocumentAttributes` WHERE `attrdef`=".$this->_id; - if($limit) - $queryStr .= " limit ".(int) $limit; - $resArr = $db->getResultArray($queryStr); - if($resArr) { - foreach($resArr as $rec) { - if($doc = $this->_dms->getDocument($rec['document'])) { - $result['docs'][] = $doc; - } - } - } - $valueset = $this->getValueSetAsArray(); - $possiblevalues = array(); - foreach($valueset as $value) { - $possiblevalues[md5($value)] = array('value'=>$value, 'c'=>0); - } - $queryStr = "SELECT count(*) c, `value` FROM `tblDocumentAttributes` WHERE `attrdef`=".$this->_id." GROUP BY `value` ORDER BY c DESC"; - $resArr = $db->getResultArray($queryStr); - if($resArr) { - foreach($resArr as $row) { - $tmpattr = new SeedDMS_Core_Attribute(0, null, $this, $row['value']); - foreach($tmpattr->getValueAsArray() as $value) { - if(isset($possiblevalues[md5($value)])) { - $possiblevalues[md5($value)]['c'] += $row['c']; - } else { - $possiblevalues[md5($value)] = array('value'=>$value, 'c'=>$row['c']); - } - } - } - $result['frequencies']['document'] = $possiblevalues; - } - } - - if($this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_all || - $this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_folder) { - $queryStr = "SELECT * FROM `tblFolderAttributes` WHERE `attrdef`=".$this->_id; - if($limit) - $queryStr .= " limit ".(int) $limit; - $resArr = $db->getResultArray($queryStr); - if($resArr) { - foreach($resArr as $rec) { - if($folder = $this->_dms->getFolder($rec['folder'])) { - $result['folders'][] = $folder; - } - } - } - $valueset = $this->getValueSetAsArray(); - $possiblevalues = array(); - foreach($valueset as $value) { - $possiblevalues[md5($value)] = array('value'=>$value, 'c'=>0); - } - $queryStr = "SELECT count(*) c, `value` FROM `tblFolderAttributes` WHERE `attrdef`=".$this->_id." GROUP BY `value` ORDER BY c DESC"; - $resArr = $db->getResultArray($queryStr); - if($resArr) { - foreach($resArr as $row) { - $tmpattr = new SeedDMS_Core_Attribute(0, null, $this, $row['value']); - foreach($tmpattr->getValueAsArray() as $value) { - if(isset($possiblevalues[md5($value)])) { - $possiblevalues[md5($value)]['c'] += $row['c']; - } else { - $possiblevalues[md5($value)] = array('value'=>$value, 'c'=>$row['c']); - } - } - } - $result['frequencies']['folder'] = $possiblevalues; - } - } - - if($this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_all || - $this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_documentcontent) { - $queryStr = "SELECT * FROM `tblDocumentContentAttributes` WHERE `attrdef`=".$this->_id; - if($limit) - $queryStr .= " limit ".(int) $limit; - $resArr = $db->getResultArray($queryStr); - if($resArr) { - foreach($resArr as $rec) { - if($content = $this->_dms->getDocumentContent($rec['content'])) { - $result['contents'][] = $content; - } - } - } - $valueset = $this->getValueSetAsArray(); - $possiblevalues = array(); - foreach($valueset as $value) { - $possiblevalues[md5($value)] = array('value'=>$value, 'c'=>0); - } - $queryStr = "SELECT count(*) c, `value` FROM `tblDocumentContentAttributes` WHERE `attrdef`=".$this->_id." GROUP BY `value` ORDER BY c DESC"; - $resArr = $db->getResultArray($queryStr); - if($resArr) { - foreach($resArr as $row) { - $tmpattr = new SeedDMS_Core_Attribute(0, null, $this, $row['value']); - foreach($tmpattr->getValueAsArray() as $value) { - if(isset($possiblevalues[md5($value)])) { - $possiblevalues[md5($value)]['c'] += $row['c']; - } else { - $possiblevalues[md5($value)] = array('value'=>$value, 'c'=>$row['c']); - } - } - } - $result['frequencies']['content'] = $possiblevalues; - } - } - - return $result; - } /* }}} */ - - /** - * Remove the attribute definition - * Removal is only executed when the definition is not used anymore. - * - * @return boolean true on success or false in case of an error - */ - function remove() { /* {{{ */ - $db = $this->_dms->getDB(); - - if($this->isUsed()) - return false; - - // Delete user itself - $queryStr = "DELETE FROM `tblAttributeDefinitions` WHERE `id` = " . $this->_id; - if (!$db->getResult($queryStr)) return false; - - return true; - } /* }}} */ - - /** - * Get all documents and folders by a given attribute value - * - * @param string $attrvalue value of attribute - * @param integer $limit limit number of documents/folders - * @return array array containing list of documents and folders - */ - public function getObjects($attrvalue, $limit=0, $op=O_EQ) { /* {{{ */ - $db = $this->_dms->getDB(); - - $result = array('docs'=>array(), 'folders'=>array(), 'contents'=>array()); - if($this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_all || - $this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_document) { - $queryStr = "SELECT * FROM `tblDocumentAttributes` WHERE `attrdef`=".$this->_id; - if($attrvalue != null) { - $queryStr .= " AND "; - if($this->getMultipleValues()) { - $sep = $this->getValueSetSeparator(); - $queryStr .= "(`value` like ".$db->qstr($sep.$attrvalue.'%')." OR `value` like ".$db->qstr('%'.$sep.$attrvalue.$sep.'%')." OR `value` like ".$db->qstr('%'.$sep.$attrvalue).")"; - } else { - $queryStr .= "`value`".$op.$db->qstr($attrvalue); - } - } - if($limit) - $queryStr .= " limit ".(int) $limit; - $resArr = $db->getResultArray($queryStr); - if($resArr) { - foreach($resArr as $rec) { - if($doc = $this->_dms->getDocument($rec['document'])) { - $result['docs'][] = $doc; - } - } - } - } - - if($this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_all || - $this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_folder) { - $queryStr = "SELECT * FROM `tblFolderAttributes` WHERE `attrdef`=".$this->_id." AND "; - if($this->getMultipleValues()) { - $sep = $this->getValueSetSeparator(); - $queryStr .= "(`value` like ".$db->qstr($sep.$attrvalue.'%')." OR `value` like ".$db->qstr('%'.$sep.$attrvalue.$sep.'%')." OR `value` like ".$db->qstr('%'.$sep.$attrvalue).")"; - } else { - $queryStr .= "`value`=".$db->qstr($attrvalue); - } - if($limit) - $queryStr .= " limit ".(int) $limit; - $resArr = $db->getResultArray($queryStr); - if($resArr) { - foreach($resArr as $rec) { - if($folder = $this->_dms->getFolder($rec['folder'])) { - $result['folders'][] = $folder; - } - } - } - } - - return $result; - } /* }}} */ - - /** - * Remove a given attribute value from all documents, versions and folders - * - * @param string $attrvalue value of attribute - * @return array array containing list of documents and folders - */ - public function removeValue($attrvalue) { /* {{{ */ - $db = $this->_dms->getDB(); - - foreach(array('document', 'documentcontent', 'folder') as $type) { - if($type == 'document') { - $tablename = "tblDocumentAttributes"; - $objtype = SeedDMS_Core_AttributeDefinition::objtype_document; - } elseif($type == 'documentcontent') { - $tablename = "tblDocumentContentAttributes"; - $objtype = SeedDMS_Core_AttributeDefinition::objtype_documentcontent; - } elseif($type == 'folder') { - $tablename = "tblFolderAttributes"; - $objtype = SeedDMS_Core_AttributeDefinition::objtype_folder; - } - if($this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_all || $objtype) { - $queryStr = "SELECT * FROM `".$tablename."` WHERE `attrdef`=".$this->_id." AND "; - if($this->getMultipleValues()) { - $sep = $this->getValueSetSeparator(); - $queryStr .= "(`value` like ".$db->qstr($sep.$attrvalue.'%')." OR `value` like ".$db->qstr('%'.$sep.$attrvalue.$sep.'%')." OR `value` like ".$db->qstr('%'.$sep.$attrvalue).")"; - } else { - $queryStr .= "`value`=".$db->qstr($attrvalue); - } - - $resArr = $db->getResultArray($queryStr); - if($resArr) { - $db->startTransaction(); - foreach($resArr as $rec) { - if($rec['value'] == $attrvalue) { - $queryStr = "DELETE FROM `".$tablename."` WHERE `id`=".$rec['id']; - } else { - if($this->getMultipleValues()) { - $sep = substr($rec['value'], 0, 1); - $vsep = $this->getValueSetSeparator(); - if($sep == $vsep) - $values = explode($sep, substr($rec['value'], 1)); - else - $values = array($rec['value']); - if (($key = array_search($attrvalue, $values)) !== false) { - unset($values[$key]); - } - if($values) { - $queryStr = "UPDATE `".$tablename."` SET `value`=".$db->qstr($sep.implode($sep, $values))." WHERE `id`=".$rec['id']; - } else { - $queryStr = "DELETE FROM `".$tablename."` WHERE `id`=".$rec['id']; - } - } else { - } - } - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - } - $db->commitTransaction(); - } - } - } - return true; - } /* }}} */ - - /** - * Validate value against attribute definition - * - * This function checks if the given value fits the attribute - * definition. - * If the validation fails the validation error will be set which - * can be requested by SeedDMS_Core_Attribute::getValidationError() - * Set $new to true if the value to be checked isn't saved to the database - * already. It will just be passed to the callback onAttributeValidate where - * it could be used to, e.g. check if a value is unique once it is saved to - * the database. $object is set to a folder, document or documentcontent - * if the attribute belongs to such an object. This will be null, if a - * new object is created. - * - * @param string|array $attrvalue attribute value - * @param object $object set if the current attribute is saved for this object - * (this will only be passed to the onAttributeValidate callback) - * @param boolean $new set to true if the value is new value and not taken from - * an existing attribute - * (this will only be passed to the onAttributeValidate callback) - * @return boolean true if validation succeeds, otherwise false - */ - function validate($attrvalue, $object=null, $new=false) { /* {{{ */ - /* Check if 'onAttributeValidate' callback is set */ - if(isset($this->_dms->callbacks['onAttributeValidate'])) { - foreach($this->_dms->callbacks['onAttributeValidate'] as $callback) { - $ret = call_user_func($callback[0], $callback[1], $this, $attrvalue, $object, $new); - if(is_bool($ret)) - return $ret; - } - } - - /* Turn $attrvalue into an array of values. Checks if $attrvalue starts - * with a separator char as set in the value set and use it to explode - * the $attrvalue. If the separator doesn't match or this attribute - * definition doesn't have a value set, then just create a one element - * array. if $attrvalue is empty, then create an empty array. - */ - if($this->getMultipleValues()) { - if(is_string($attrvalue) && $attrvalue) { - $sep = $attrvalue[0]; - $vsep = $this->getValueSetSeparator(); - if($sep == $vsep) - $values = explode($attrvalue[0], substr($attrvalue, 1)); - else - $values = array($attrvalue); - } elseif(is_array($attrvalue)) { - $values = $attrvalue; - } elseif(is_string($attrvalue) && !$attrvalue) { - $values = array(); - } else - $values = array($attrvalue); - } elseif($attrvalue !== null) { - $values = array($attrvalue); - } else { - $values = array(); - } - - /* Check if attribute value has at least the minimum number of values */ - $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_none; - if($this->getMinValues() > count($values)) { - $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_min_values; - return false; - } - /* Check if attribute value has not more than maximum number of values */ - if($this->getMaxValues() && $this->getMaxValues() < count($values)) { - $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_max_values; - return false; - } - - $success = true; - switch((string) $this->getType()) { - case self::type_boolean: - foreach($values as $value) { - $success = $success && (preg_match('/^[01]$/', $value) ? true : false); - } - if(!$success) - $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_boolean; - break; - case self::type_int: - foreach($values as $value) { - $success = $success && (preg_match('/^[0-9]*$/', $value) ? true : false); - } - if(!$success) - $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_int; - break; - case self::type_date: - foreach($values as $value) { - $d = explode('-', $value, 3); - $success = $success && (count($d) == 3)&& checkdate((int) $d[1], (int) $d[2], (int) $d[0]); - } - if(!$success) - $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_date; - break; - case self::type_float: - foreach($values as $value) { - $success = $success && is_numeric($value); - } - if(!$success) - $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_float; - break; - case self::type_string: - if(trim($this->getRegex()) != '') { - foreach($values as $value) { - $success = $success && (preg_match($this->getRegex(), $value) ? true : false); - } - } - if(!$success) - $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_regex; - break; - case self::type_email: - foreach($values as $value) { - //$success &= filter_var($value, FILTER_VALIDATE_EMAIL) ? true : false; - $success = $success && (preg_match('/^[a-z0-9._-]+@[a-z0-9-]{2,63}(\.[a-z0-9-]{2,63})*\.[a-z]{2,63}$/i', $value) ? true : false); - } - if(!$success) - $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_email; - break; - case self::type_url: - foreach($values as $value) { - $success = $success && (preg_match('/^http(s)?:\/\/[a-z0-9_-]+(\.[a-z0-9-]{2,63})*(:[0-9]+)?(\/.*)?$/i', $value) ? true : false); - } - if(!$success) - $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_url; - break; - case self::type_document: - foreach($values as $value) { - $success = true; - if(!$this->_dms->getDocument((int) $value)) - $success = false; - } - if(!$success) - $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_document; - break; - case self::type_folder: - foreach($values as $value) { - $success = true; - if(!$this->_dms->getFolder((int) $value)) - $success = false; - } - if(!$success) - $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_folder; - break; - case self::type_user: - foreach($values as $value) { - $success = true; - if(!$this->_dms->getUser((int) $value)) - $success = false; - } - if(!$success) - $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_user; - break; - case self::type_group: - foreach($values as $value) { - $success = true; - if(!$this->_dms->getGroup((int) $value)) - $success = false; - } - if(!$success) - $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_group; - break; - } - - if(!$success) - return $success; - - /* Check if value is in value set */ - if($valueset = $this->getValueSetAsArray()) { - /* An empty value cannot be the value set */ - if(!$values) { - $success = false; - $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_valueset; - } else { - foreach($values as $value) { - if(!in_array($value, $valueset)) { - $success = false; - $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_valueset; - } - } - } - } - - return $success; - - } /* }}} */ - - /** - * Get validation error from last validation - * - * @return integer error code - */ - function getValidationError() { return $this->_validation_error; } - -} /* }}} */ diff --git a/SeedDMS_Core/Core/inc.ClassDMS.php b/SeedDMS_Core/Core/inc.ClassDMS.php deleted file mode 100644 index 99c150c0a..000000000 --- a/SeedDMS_Core/Core/inc.ClassDMS.php +++ /dev/null @@ -1,3507 +0,0 @@ - - * @copyright 2010 Uwe Steinmann - * @version Release: @package_version@ - */ - -/** - * Include some files - */ -require_once("inc.AccessUtils.php"); -require_once("inc.FileUtils.php"); -require_once("inc.ClassAccess.php"); -require_once("inc.ClassObject.php"); -require_once("inc.ClassFolder.php"); -require_once("inc.ClassDocument.php"); -require_once("inc.ClassGroup.php"); -require_once("inc.ClassUser.php"); -require_once("inc.ClassKeywords.php"); -require_once("inc.ClassNotification.php"); -require_once("inc.ClassAttribute.php"); - -/** - * Class to represent the complete document management system. - * This class is needed to do most of the dms operations. It needs - * an instance of {@link SeedDMS_Core_DatabaseAccess} to access the - * underlying database. Many methods are factory functions which create - * objects representing the entities in the dms, like folders, documents, - * users, or groups. - * - * Each dms has its own database for meta data and a data store for document - * content. Both must be specified when creating a new instance of this class. - * All folders and documents are organized in a hierachy like - * a regular file system starting with a {@link $rootFolderID} - * - * This class does not enforce any access rights on documents and folders - * by design. It is up to the calling application to use the methods - * {@link SeedDMS_Core_Folder::getAccessMode()} and - * {@link SeedDMS_Core_Document::getAccessMode()} and interpret them as desired. - * Though, there are two convenient functions to filter a list of - * documents/folders for which users have access rights for. See - * {@link filterAccess()} - * and {@link filterUsersByAccess()} - * - * Though, this class has a method to set the currently logged in user - * ({@link setUser}), it does not have to be called, because - * there is currently no class within the SeedDMS core which needs the logged - * in user. {@link SeedDMS_Core_DMS} itself does not do any user authentication. - * It is up to the application using this class. - * - * - * connect() or die ("Could not connect to db-server"); - * $dms = new SeedDMS_Core_DMS($db, $contentDir); - * $dms->setRootFolderID(1); - * ... - * ?> - * - * - * @category DMS - * @package SeedDMS_Core - * @version @version@ - * @author Uwe Steinmann - * @copyright Copyright (C) 2010, Uwe Steinmann - * @version Release: @package_version@ - */ -class SeedDMS_Core_DMS { - /** - * @var SeedDMS_Core_DatabaseAccess $db reference to database object. This must be an instance - * of {@link SeedDMS_Core_DatabaseAccess}. - * @access protected - */ - protected $db; - - /** - * @var array $classnames list of classnames for objects being instanciate - * by the dms - * @access protected - */ - protected $classnames; - - /** - * @var array $decorators list of decorators for objects being instanciate - * by the dms - * @access protected - */ - protected $decorators; - - /** - * @var SeedDMS_Core_User $user reference to currently logged in user. This must be - * an instance of {@link SeedDMS_Core_User}. This variable is currently not - * used. It is set by {@link setUser}. - * @access private - */ - private $user; - - /** - * @var string $contentDir location in the file system where all the - * document data is located. This should be an absolute path. - * @access public - */ - public $contentDir; - - /** - * @var integer $rootFolderID ID of root folder - * @access public - */ - public $rootFolderID; - - /** - * @var integer $maxDirID maximum number of documents per folder on the - * filesystem. If this variable is set to a value != 0, the content - * directory will have a two level hierarchy for document storage. - * @access public - */ - public $maxDirID; - - /** - * @var boolean $forceRename use renameFile() instead of copyFile() when - * copying the document content into the data store. The default is - * to copy the file. This parameter only affects the methods - * SeedDMS_Core_Document::addDocument() and - * SeedDMS_Core_Document::addDocumentFile(). Setting this to true - * may save resources especially for large files. - * @access public - */ - public $forceRename; - - /** - * @var array $noReadForStatus list of status without read right - * online. - * @access public - */ - public $noReadForStatus; - - /** - * @var boolean $checkWithinRootDir check if folder/document being accessed - * is within the rootdir - * @access public - */ - public $checkWithinRootDir; - - /** - * @var string $version version of pear package - * @access public - */ - public $version; - - /** - * @var array $callbacks list of methods called when certain operations, - * like removing a document, are executed. Set a callback with - * {@link SeedDMS_Core_DMS::setCallback()}. - * The key of the array is the internal callback function name. Each - * array element is an array with two elements: the function name - * and the parameter passed to the function. - * - * Currently implemented callbacks are: - * - * onPreRemoveDocument($user_param, $document); - * called before deleting a document. If this function returns false - * the document will not be deleted. - * - * onPostRemoveDocument($user_param, $document_id); - * called after the successful deletion of a document. - * - * @access public - */ - public $callbacks; - - /** - * @var string last error message. This can be set by hooks to pass an - * error message from the hook to the application which has called the - * method containing the hook. For example SeedDMS_Core_Document::remove() - * calls the hook 'onPreRemoveDocument'. The hook function can set $dms->lasterror - * which can than be read when SeedDMS_Core_Document::remove() fails. - * This variable could be set in any SeedDMS_Core class, but is currently - * only set by hooks. - * @access public - */ - public $lasterror; - - /** - * @var SeedDMS_Core_DMS - */ -// public $_dms; - - - /** - * Checks if two objects are equal by comparing their IDs - * - * The regular php check done by '==' compares all attributes of - * two objects, which is often not required. This method will first check - * if the objects are instances of the same class and than if they - * have the same id. - * - * @param object $object1 first object to be compared - * @param object $object2 second object to be compared - * @return boolean true if objects are equal, otherwise false - */ - static function checkIfEqual($object1, $object2) { /* {{{ */ - if(get_class($object1) != get_class($object2)) - return false; - if($object1->getID() != $object2->getID()) - return false; - return true; - } /* }}} */ - - /** - * Checks if a list of objects contains a single object by comparing their IDs - * - * This function is only applicable on list containing objects which have - * a method getID() because it is used to check if two objects are equal. - * The regular php check on objects done by '==' compares all attributes of - * two objects, which isn't required. The method will first check - * if the objects are instances of the same class. - * - * The result of the function can be 0 which happens if the first element - * of an indexed array matches. - * - * @param object $object object to look for (needle) - * @param array $list list of objects (haystack) - * @return boolean/integer index in array if object was found, otherwise false - */ - static function inList($object, $list) { /* {{{ */ - foreach($list as $i=>$item) { - if(get_class($item) == get_class($object) && $item->getID() == $object->getID()) - return $i; - } - return false; - } /* }}} */ - - /** - * Checks if date conforms to a given format - * - * @param string $date date to be checked - * @param string $format format of date. Will default to 'Y-m-d H:i:s' if - * format is not given. - * @return boolean true if date is in propper format, otherwise false - */ - static function checkDate($date, $format='Y-m-d H:i:s') { /* {{{ */ - $d = DateTime::createFromFormat($format, $date); - return $d && $d->format($format) == $date; - } /* }}} */ - - /** - * Filter out objects which are not accessible in a given mode by a user. - * - * The list of objects to be checked can be of any class, but has to have - * a method getAccessMode($user) which checks if the given user has at - * least the access right on the object as passed in $minMode. - * Hence, passing a group instead of user is possible. - * - * @param array $objArr list of objects (either documents or folders) - * @param object $user user for which access is checked - * @param integer $minMode minimum access mode required (M_ANY, M_NONE, - * M_READ, M_READWRITE, M_ALL) - * @return array filtered list of objects - */ - static function filterAccess($objArr, $user, $minMode) { /* {{{ */ - if (!is_array($objArr)) { - return array(); - } - $newArr = array(); - foreach ($objArr as $obj) { - if ($obj->getAccessMode($user) >= $minMode) - array_push($newArr, $obj); - } - return $newArr; - } /* }}} */ - - /** - * Filter out users which cannot access an object in a given mode. - * - * The list of users to be checked can be of any class, but has to have - * a method getAccessMode($user) which checks if a user has at least the - * access right as passed in $minMode. Hence, passing a list of groups - * instead of users is possible. - * - * @param object $obj object that shall be accessed - * @param array $users list of users/groups which are to check for sufficient - * access rights - * @param integer $minMode minimum access right on the object for each user - * (M_ANY, M_NONE, M_READ, M_READWRITE, M_ALL) - * @return array filtered list of users - */ - static function filterUsersByAccess($obj, $users, $minMode) { /* {{{ */ - $newArr = array(); - foreach ($users as $currUser) { - if ($obj->getAccessMode($currUser) >= $minMode) - array_push($newArr, $currUser); - } - return $newArr; - } /* }}} */ - - /** - * Filter out document links which can not be accessed by a given user - * - * Returns a filtered list of links which are accessible by the - * given user. A link is only accessible, if it is publically visible, - * owned by the user, or the accessing user is an administrator. - * - * @param SeedDMS_Core_DocumentLink[] $links list of objects of type SeedDMS_Core_DocumentLink - * @param object $user user for which access is being checked - * @param string $access set if source or target of link shall be checked - * for sufficient access rights. Set to 'source' if the source document - * of a link is to be checked, set to 'target' for the target document. - * If not set, then access right aren't checked at all. - * @return array filtered list of links - */ - static function filterDocumentLinks($user, $links, $access='') { /* {{{ */ - $tmp = array(); - foreach ($links as $link) { - if ($link->isPublic() || ($link->getUser()->getID() == $user->getID()) || $user->isAdmin()){ - if($access == 'source') { - $obj = $link->getDocument(); - if ($obj->getAccessMode($user) >= M_READ) - array_push($tmp, $link); - } elseif($access == 'target') { - $obj = $link->getTarget(); - if ($obj->getAccessMode($user) >= M_READ) - array_push($tmp, $link); - } else { - array_push($tmp, $link); - } - } - } - return $tmp; - } /* }}} */ - - /** - * Filter out document attachments which can not be accessed by a given user - * - * Returns a filtered list of files which are accessible by the - * given user. A file is only accessible, if it is publically visible, - * owned by the user, or the accessing user is an administrator. - * - * @param array $files list of objects of type SeedDMS_Core_DocumentFile - * @param object $user user for which access is being checked - * @return array filtered list of files - */ - static function filterDocumentFiles($user, $files) { /* {{{ */ - $tmp = array(); - if($files) { - foreach ($files as $file) - if ($file->isPublic() || ($file->getUser()->getID() == $user->getID()) || $user->isAdmin() || ($file->getDocument()->getOwner()->getID() == $user->getID())) - array_push($tmp, $file); - } - return $tmp; - } /* }}} */ - - /** @noinspection PhpUndefinedClassInspection */ - /** - * Create a new instance of the dms - * - * @param SeedDMS_Core_DatabaseAccess $db object of class {@link SeedDMS_Core_DatabaseAccess} - * to access the underlying database - * @param string $contentDir path in filesystem containing the data store - * all document contents is stored - */ - function __construct($db, $contentDir) { /* {{{ */ - $this->db = $db; - if(substr($contentDir, -1) == '/') - $this->contentDir = $contentDir; - else - $this->contentDir = $contentDir.'/'; - $this->rootFolderID = 1; - $this->user = null; - $this->maxDirID = 0; //31998; - $this->forceRename = false; - $this->checkWithinRootDir = false; - $this->noReadForStatus = array(); - $this->user = null; - $this->classnames = array(); - $this->classnames['folder'] = 'SeedDMS_Core_Folder'; - $this->classnames['document'] = 'SeedDMS_Core_Document'; - $this->classnames['documentcontent'] = 'SeedDMS_Core_DocumentContent'; - $this->classnames['documentfile'] = 'SeedDMS_Core_DocumentFile'; - $this->classnames['user'] = 'SeedDMS_Core_User'; - $this->classnames['group'] = 'SeedDMS_Core_Group'; - $this->callbacks = array(); - $this->lasterror = ''; - $this->version = '@package_version@'; - if($this->version[0] == '@') - $this->version = '5.1.27'; - } /* }}} */ - - /** - * Return class name of classes instanciated by SeedDMS_Core - * - * This method returns the class name of those objects being instantiated - * by the dms. Each class has an internal place holder, which must be - * passed to function. - * - * @param string $objectname placeholder (can be one of 'folder', 'document', - * 'documentcontent', 'user', 'group') - * - * @return string/boolean name of class or false if object name is invalid - */ - function getClassname($objectname) { /* {{{ */ - if(isset($this->classnames[$objectname])) - return $this->classnames[$objectname]; - else - return false; - } /* }}} */ - - /** - * Set class name of instantiated objects - * - * This method sets the class name of those objects being instatiated - * by the dms. It is mainly used to create a new class (possible - * inherited from one of the available classes) implementing new - * features. The method should be called in the postInitDMS hook. - * - * @param string $objectname placeholder (can be one of 'folder', 'document', - * 'documentcontent', 'user', 'group' - * @param string $classname name of class - * - * @return string/boolean name of old class or false if not set - */ - function setClassname($objectname, $classname) { /* {{{ */ - if(isset($this->classnames[$objectname])) - $oldclass = $this->classnames[$objectname]; - else - $oldclass = false; - $this->classnames[$objectname] = $classname; - return $oldclass; - } /* }}} */ - - /** - * Return list of decorators - * - * This method returns the list of decorator class names of those objects - * being instantiated - * by the dms. Each class has an internal place holder, which must be - * passed to function. - * - * @param string $objectname placeholder (can be one of 'folder', 'document', - * 'documentcontent', 'user', 'group') - * - * @return array/boolean list of class names or false if object name is invalid - */ - function getDecorators($objectname) { /* {{{ */ - if(isset($this->decorators[$objectname])) - return $this->decorators[$objectname]; - else - return false; - } /* }}} */ - - /** - * Add a decorator - * - * This method adds a single decorator class name to the list of decorators - * of those objects being instantiated - * by the dms. Each class has an internal place holder, which must be - * passed to function. - * - * @param string $objectname placeholder (can be one of 'folder', 'document', - * 'documentcontent', 'user', 'group') - * - * @return boolean true if decorator could be added, otherwise false - */ - function addDecorator($objectname, $decorator) { /* {{{ */ - $this->decorators[$objectname][] = $decorator; - return true; - } /* }}} */ - - /** - * Return database where meta data is stored - * - * This method returns the database object as it was set by the first - * parameter of the constructor. - * - * @return SeedDMS_Core_DatabaseAccess database - */ - function getDB() { /* {{{ */ - return $this->db; - } /* }}} */ - - /** - * Return the database version - * - * @return array|bool - */ - function getDBVersion() { /* {{{ */ - $tbllist = $this->db->TableList(); - $tbllist = explode(',',strtolower(join(',',$tbllist))); - if(!in_array('tblversion', $tbllist)) - return false; - $queryStr = "SELECT * FROM `tblVersion` ORDER BY `major`,`minor`,`subminor` LIMIT 1"; - $resArr = $this->db->getResultArray($queryStr); - if (is_bool($resArr) && $resArr == false) - return false; - if (count($resArr) != 1) - return false; - $resArr = $resArr[0]; - return $resArr; - } /* }}} */ - - /** - * Check if the version in the database is the same as of this package - * Only the major and minor version number will be checked. - * - * @return boolean returns false if versions do not match, but returns - * true if version matches or table tblVersion does not exists. - */ - function checkVersion() { /* {{{ */ - $tbllist = $this->db->TableList(); - $tbllist = explode(',',strtolower(join(',',$tbllist))); - if(!in_array('tblversion', $tbllist)) - return true; - $queryStr = "SELECT * FROM `tblVersion` ORDER BY `major`,`minor`,`subminor` LIMIT 1"; - $resArr = $this->db->getResultArray($queryStr); - if (is_bool($resArr) && $resArr == false) - return false; - if (count($resArr) != 1) - return false; - $resArr = $resArr[0]; - $ver = explode('.', $this->version); - if(($resArr['major'] != $ver[0]) || ($resArr['minor'] != $ver[1])) - return false; - return true; - } /* }}} */ - - /** - * Set id of root folder - * - * This function must be called right after creating an instance of - * {@link SeedDMS_Core_DMS} - * - * The new root folder id will only be set if the folder actually - * exists. In that case the old root folder id will be returned. - * If it does not exists, the method will return false; - * @param integer $id id of root folder - * @return boolean/int old root folder id if new root folder exists, otherwise false - */ - function setRootFolderID($id) { /* {{{ */ - if($this->getFolder($id)) { - $oldid = $this->rootFolderID; - $this->rootFolderID = $id; - return $oldid; - } - return false; - } /* }}} */ - - /** - * Set maximum number of subdirectories per directory - * - * The value of maxDirID is quite crucial, because each document is - * stored within a directory in the filesystem. Consequently, there can be - * a maximum number of documents, because depending on the file system - * the maximum number of subdirectories is limited. Since version 3.3.0 of - * SeedDMS an additional directory level has been introduced, which - * will be created when maxDirID is not 0. All documents - * from 1 to maxDirID-1 will be saved in 1/, documents from maxDirID - * to 2*maxDirID-1 are stored in 2/ and so on. - * - * Modern file systems like ext4 do not have any restrictions on the number - * of subdirectories anymore. Therefore it is best if this parameter is - * set to 0. Never change this parameter if documents has already been - * created. - * - * This function must be called right after creating an instance of - * {@link SeedDMS_Core_DMS} - * - * @param integer $id id of root folder - */ - function setMaxDirID($id) { /* {{{ */ - $this->maxDirID = $id; - } /* }}} */ - - /** - * Get root folder - * - * @return SeedDMS_Core_Folder|boolean return the object of the root folder or false if - * the root folder id was not set before with {@link setRootFolderID}. - */ - function getRootFolder() { /* {{{ */ - if(!$this->rootFolderID) return false; - return $this->getFolder($this->rootFolderID); - } /* }}} */ - - function setForceRename($enable) { /* {{{ */ - $this->forceRename = $enable; - } /* }}} */ - - /** - * Set the logged in user - * - * This method tells SeeDMS_Core_DMS the currently logged in user. It must be - * called right after instanciating the class, because some methods in - * SeedDMS_Core_Document() require the currently logged in user. - * - * @param object $user this muss not be empty and an instance of SeedDMS_Core_User - * @return bool|object returns the old user object or null on success, otherwise false - * - */ - function setUser($user) { /* {{{ */ - if(!$user) { - $olduser = $this->user; - $this->user = null; - return $olduser; - } - if(is_object($user) && (get_class($user) == $this->getClassname('user'))) { - $olduser = $this->user; - $this->user = $user; - return $olduser; - } - return false; - } /* }}} */ - - /** - * Get the logged in user - * - * Returns the currently logged in user, as set by setUser() - * - * @return SeedDMS_Core_User $user - * - */ - function getLoggedInUser() { /* {{{ */ - return $this->user; - } /* }}} */ - - /** - * Return a document by its id - * - * This function retrieves a document from the database by its id. - * - * @param integer $id internal id of document - * @return SeedDMS_Core_Document instance of {@link SeedDMS_Core_Document}, null or false - */ - function getDocument($id) { /* {{{ */ - $classname = $this->classnames['document']; - return $classname::getInstance($id, $this); - } /* }}} */ - - /** - * Returns all documents of a given user - * - * @param object $user - * @return array list of documents - */ - function getDocumentsByUser($user) { /* {{{ */ - return $user->getDocuments(); - } /* }}} */ - - /** - * Returns all documents locked by a given user - * - * @param object $user - * @return array list of documents - */ - function getDocumentsLockedByUser($user) { /* {{{ */ - return $user->getDocumentsLocked(); - } /* }}} */ - - /** - * Returns all documents which already expired or will expire in the future - * - * The parameter $date will be relative to the start of the day. It can - * be either a number of days (if an integer is passed) or a date string - * in the format 'YYYY-MM-DD'. - * If the parameter $date is a negative number or a date in the past, then - * all documents from the start of that date till the end of the current - * day will be returned. If $date is a positive integer or $date is a - * date in the future, then all documents from the start of the current - * day till the end of the day of the given date will be returned. - * Passing 0 or the - * current date in $date, will return all documents expiring the current - * day. - * @param string $date date in format YYYY-MM-DD or an integer with the number - * of days. A negative value will cover the days in the past. - * @param SeedDMS_Core_User $user limits the documents on those owned - * by this user - * @param string $orderby n=name, e=expired - * @param string $orderdir d=desc or a=asc - * @param bool $update update status of document if set to true - * @return bool|SeedDMS_Core_Document[] - */ - function getDocumentsExpired($date, $user=null, $orderby='e', $orderdir='desc', $update=true) { /* {{{ */ - $db = $this->getDB(); - - if (!$db->createTemporaryTable("ttstatid") || !$db->createTemporaryTable("ttcontentid")) { - return false; - } - - $tsnow = mktime(0, 0, 0); /* Start of today */ - if(is_int($date)) { - $ts = $tsnow + $date * 86400; - } elseif(is_string($date)) { - $tmp = explode('-', $date, 3); - if(count($tmp) != 3) - return false; - if(!self::checkDate($date, 'Y-m-d')) - return false; - $ts = mktime(0, 0, 0, $tmp[1], $tmp[2], $tmp[0]); - } else - return false; - - if($ts < $tsnow) { /* Check for docs expired in the past */ - $startts = $ts; - $endts = $tsnow+86400; /* Use end of day */ - $updatestatus = $update; - } else { /* Check for docs which will expire in the future */ - $startts = $tsnow; - $endts = $ts+86400; /* Use end of day */ - $updatestatus = false; - } - - /* Get all documents which have an expiration date. It doesn't check for - * the latest status which should be S_EXPIRED, but doesn't have to, because - * status may have not been updated after the expiration date has been reached. - **/ - $queryStr = "SELECT `tblDocuments`.`id`, `tblDocumentStatusLog`.`status` FROM `tblDocuments` ". - "LEFT JOIN `ttcontentid` ON `ttcontentid`.`document` = `tblDocuments`.`id` ". - "LEFT JOIN `tblDocumentContent` ON `tblDocuments`.`id` = `tblDocumentContent`.`document` AND `tblDocumentContent`.`version` = `ttcontentid`.`maxVersion` ". - "LEFT JOIN `tblDocumentStatus` ON `tblDocumentStatus`.`documentID` = `tblDocumentContent`.`document` AND `tblDocumentContent`.`version` = `tblDocumentStatus`.`version` ". - "LEFT JOIN `ttstatid` ON `ttstatid`.`statusID` = `tblDocumentStatus`.`statusID` ". - "LEFT JOIN `tblDocumentStatusLog` ON `tblDocumentStatusLog`.`statusLogID` = `ttstatid`.`maxLogID`"; - $queryStr .= - " WHERE `tblDocuments`.`expires` >= ".$startts." AND `tblDocuments`.`expires` < ".$endts; - if($user) - $queryStr .= - " AND `tblDocuments`.`owner` = '".$user->getID()."' "; - $queryStr .= - " ORDER BY ".($orderby == 'e' ? "`expires`" : "`name`")." ".($orderdir == 'd' ? "DESC" : "ASC"); - - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - /** @var SeedDMS_Core_Document[] $documents */ - $documents = array(); - foreach ($resArr as $row) { - $document = $this->getDocument($row["id"]); - if($updatestatus) { - $document->verifyLastestContentExpriry(); - } - $documents[] = $document; - } - return $documents; - } /* }}} */ - - /** - * Returns a document by its name - * - * This function searches a document by its name and restricts the search - * to the given folder if passed as the second parameter. - * If there are more than one document with that name, then only the - * one with the highest id will be returned. - * - * @param string $name Name of the document - * @param object $folder parent folder of document - * @return SeedDMS_Core_Document|null|boolean found document or null if not document was found or false in case of an error - */ - function getDocumentByName($name, $folder=null) { /* {{{ */ - $name = trim($name); - if (!$name) return false; - - $queryStr = "SELECT `tblDocuments`.*, `tblDocumentLocks`.`userID` as `lockUser` ". - "FROM `tblDocuments` ". - "LEFT JOIN `tblDocumentLocks` ON `tblDocuments`.`id`=`tblDocumentLocks`.`document` ". - "WHERE `tblDocuments`.`name` = " . $this->db->qstr($name); - if($folder) - $queryStr .= " AND `tblDocuments`.`folder` = ". $folder->getID(); - if($this->checkWithinRootDir) - $queryStr .= " AND `tblDocuments`.`folderList` LIKE '%:".$this->rootFolderID.":%'"; - $queryStr .= " ORDER BY `tblDocuments`.`id` DESC LIMIT 1"; - - $resArr = $this->db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - if(!$resArr) - return null; - - $row = $resArr[0]; - /** @var SeedDMS_Core_Document $document */ - $document = new $this->classnames['document']($row["id"], $row["name"], $row["comment"], $row["date"], $row["expires"], $row["owner"], $row["folder"], $row["inheritAccess"], $row["defaultAccess"], $row["lockUser"], $row["keywords"], $row["sequence"]); - $document->setDMS($this); - return $document; - } /* }}} */ - - /** - * Returns a document by the original file name of the last version - * - * This function searches a document by the name of the last document - * version and restricts the search - * to given folder if passed as the second parameter. - * If there are more than one document with that name, then only the - * one with the highest id will be returned. - * - * @param string $name Name of the original file - * @param object $folder parent folder of document - * @return SeedDMS_Core_Document|null|boolean found document or null if not document was found or false in case of an error - */ - function getDocumentByOriginalFilename($name, $folder=null) { /* {{{ */ - $name = trim($name); - if (!$name) return false; - - if (!$this->db->createTemporaryTable("ttcontentid")) { - return false; - } - $queryStr = "SELECT `tblDocuments`.*, `tblDocumentLocks`.`userID` as `lockUser` ". - "FROM `tblDocuments` ". - "LEFT JOIN `ttcontentid` ON `ttcontentid`.`document` = `tblDocuments`.`id` ". - "LEFT JOIN `tblDocumentContent` ON `tblDocumentContent`.`document` = `tblDocuments`.`id` AND `tblDocumentContent`.`version` = `ttcontentid`.`maxVersion` ". - "LEFT JOIN `tblDocumentLocks` ON `tblDocuments`.`id`=`tblDocumentLocks`.`document` ". - "WHERE `tblDocumentContent`.`orgFileName` = " . $this->db->qstr($name); - if($folder) - $queryStr .= " AND `tblDocuments`.`folder` = ". $folder->getID(); - $queryStr .= " ORDER BY `tblDocuments`.`id` DESC LIMIT 1"; - - $resArr = $this->db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - if(!$resArr) - return null; - - $row = $resArr[0]; - /** @var SeedDMS_Core_Document $document */ - $document = new $this->classnames['document']($row["id"], $row["name"], $row["comment"], $row["date"], $row["expires"], $row["owner"], $row["folder"], $row["inheritAccess"], $row["defaultAccess"], $row["lockUser"], $row["keywords"], $row["sequence"]); - $document->setDMS($this); - return $document; - } /* }}} */ - - /** - * Return a document content by its id - * - * This function retrieves a document content from the database by its id. - * - * @param integer $id internal id of document content - * @return bool|null|SeedDMS_Core_DocumentContent found document content or null if not document content was found or false in case of an error - - */ - function getDocumentContent($id) { /* {{{ */ - if (!is_numeric($id)) return false; - if ($id < 1) return false; - - $queryStr = "SELECT * FROM `tblDocumentContent` WHERE `id` = ".(int) $id; - $resArr = $this->db->getResultArray($queryStr); - if (is_bool($resArr) && $resArr == false) - return false; - if (count($resArr) != 1) - return null; - $row = $resArr[0]; - - $document = $this->getDocument($row['document']); - $version = new $this->classnames['documentcontent']($row['id'], $document, $row['version'], $row['comment'], $row['date'], $row['createdBy'], $row['dir'], $row['orgFileName'], $row['fileType'], $row['mimeType'], $row['fileSize'], $row['checksum']); - return $version; - } /* }}} */ - - /** - * Returns all documents with a predefined search criteria - * - * The records return have the following elements - * - * From Table tblDocuments - * [id] => id of document - * [name] => name of document - * [comment] => comment of document - * [date] => timestamp of creation date of document - * [expires] => timestamp of expiration date of document - * [owner] => user id of owner - * [folder] => id of parent folder - * [folderList] => column separated list of folder ids, e.g. :1:41: - * [inheritAccess] => 1 if access is inherited - * [defaultAccess] => default access mode - * [locked] => always -1 (TODO: is this field still used?) - * [keywords] => keywords of document - * [sequence] => sequence of document - * - * From Table tblDocumentLocks - * [lockUser] => id of user locking the document - * - * From Table tblDocumentStatusLog - * [version] => latest version of document - * [statusID] => id of latest status log - * [documentID] => id of document - * [status] => current status of document - * [statusComment] => comment of current status - * [statusDate] => datetime when the status was entered, e.g. 2014-04-17 21:35:51 - * [userID] => id of user who has initiated the status change - * - * From Table tblUsers - * [ownerName] => name of owner of document - * [statusName] => name of user who has initiated the status change - * - * @param string $listtype type of document list, can be 'AppRevByMe', - * 'AppRevOwner', 'ReceiptByMe', 'ReviseByMe', 'LockedByMe', 'MyDocs' - * @param SeedDMS_Core_User $param1 user - * @param bool|integer|string $param2 if set to true - * 'ReviewByMe', 'ApproveByMe', 'AppRevByMe', 'ReviseByMe', 'ReceiptByMe' - * will also return documents which the reviewer, approver, etc. - * has already taken care of. If set to false only - * untouched documents will be returned. In case of 'ExpiredOwner' this - * parameter contains the number of days (a negative number is allowed) - * relativ to the current date or a date in format 'yyyy-mm-dd' - * (even in the past). - * @param string $param3 sort list by this field - * @param string $param4 order direction - * @param bool $param5 set to false if expired documents shall not be considered - * @return array|bool - */ - function getDocumentList($listtype, $param1=null, $param2=false, $param3='', $param4='', $param5=true) { /* {{{ */ - /* The following query will get all documents and lots of additional - * information. It requires the two temporary tables ttcontentid and - * ttstatid. - */ - if (!$this->db->createTemporaryTable("ttstatid") || !$this->db->createTemporaryTable("ttcontentid")) { - return false; - } - /* The following statement retrieves the status of the last version of all - * documents. It must be restricted by further where clauses. - */ -/* - $queryStr = "SELECT `tblDocuments`.*, `tblDocumentLocks`.`userID` as `lockUser`, ". - "`tblDocumentContent`.`version`, `tblDocumentStatus`.*, `tblDocumentStatusLog`.`status`, ". - "`tblDocumentStatusLog`.`comment` AS `statusComment`, `tblDocumentStatusLog`.`date` as `statusDate`, ". - "`tblDocumentStatusLog`.`userID`, `oTbl`.`fullName` AS `ownerName`, `sTbl`.`fullName` AS `statusName` ". - "FROM `tblDocumentContent` ". - "LEFT JOIN `tblDocuments` ON `tblDocuments`.`id` = `tblDocumentContent`.`document` ". - "LEFT JOIN `tblDocumentStatus` ON `tblDocumentStatus`.`documentID` = `tblDocumentContent`.`document` ". - "LEFT JOIN `tblDocumentStatusLog` ON `tblDocumentStatusLog`.`statusID` = `tblDocumentStatus`.`statusID` ". - "LEFT JOIN `ttstatid` ON `ttstatid`.`maxLogID` = `tblDocumentStatusLog`.`statusLogID` ". - "LEFT JOIN `ttcontentid` ON `ttcontentid`.`maxVersion` = `tblDocumentStatus`.`version` AND `ttcontentid`.`document` = `tblDocumentStatus`.`documentID` ". - "LEFT JOIN `tblDocumentLocks` ON `tblDocuments`.`id`=`tblDocumentLocks`.`document` ". - "LEFT JOIN `tblUsers` AS `oTbl` on `oTbl`.`id` = `tblDocuments`.`owner` ". - "LEFT JOIN `tblUsers` AS `sTbl` on `sTbl`.`id` = `tblDocumentStatusLog`.`userID` ". - "WHERE `ttstatid`.`maxLogID`=`tblDocumentStatusLog`.`statusLogID` ". - "AND `ttcontentid`.`maxVersion` = `tblDocumentContent`.`version` "; - */ - /* New sql statement which retrieves all documents, its latest version and - * status, the owner and user initiating the latest status. - * It doesn't need the where clause anymore. Hence the statement could be - * extended with further left joins. - */ - $selectStr = "`tblDocuments`.*, `tblDocumentLocks`.`userID` as `lockUser`, ". - "`tblDocumentContent`.`version`, `tblDocumentStatus`.*, `tblDocumentStatusLog`.`status`, ". - "`tblDocumentStatusLog`.`comment` AS `statusComment`, `tblDocumentStatusLog`.`date` as `statusDate`, ". - "`tblDocumentStatusLog`.`userID`, `oTbl`.`fullName` AS `ownerName`, `sTbl`.`fullName` AS `statusName` "; - $queryStr = - "FROM `ttcontentid` ". - "LEFT JOIN `tblDocuments` ON `tblDocuments`.`id` = `ttcontentid`.`document` ". - "LEFT JOIN `tblDocumentContent` ON `tblDocumentContent`.`document` = `ttcontentid`.`document` AND `tblDocumentContent`.`version` = `ttcontentid`.`maxVersion` ". - "LEFT JOIN `tblDocumentStatus` ON `tblDocumentStatus`.`documentID`=`ttcontentid`.`document` AND `tblDocumentStatus`.`version`=`ttcontentid`.`maxVersion` ". - "LEFT JOIN `ttstatid` ON `ttstatid`.`statusID` = `tblDocumentStatus`.`statusID` ". - "LEFT JOIN `tblDocumentStatusLog` ON `ttstatid`.`statusID` = `tblDocumentStatusLog`.`statusID` AND `ttstatid`.`maxLogID` = `tblDocumentStatusLog`.`statusLogID` ". - "LEFT JOIN `tblDocumentLocks` ON `ttcontentid`.`document`=`tblDocumentLocks`.`document` ". - "LEFT JOIN `tblUsers` `oTbl` ON `oTbl`.`id` = `tblDocuments`.`owner` ". - "LEFT JOIN `tblUsers` `sTbl` ON `sTbl`.`id` = `tblDocumentStatusLog`.`userID` "; - -// echo $queryStr; - - switch($listtype) { - case 'AppRevByMe': // Documents I have to review/approve {{{ - $queryStr .= "WHERE 1=1 "; - - $user = $param1; - // Get document list for the current user. - $reviewStatus = $user->getReviewStatus(); - $approvalStatus = $user->getApprovalStatus(); - - // Create a comma separated list of all the documentIDs whose information is - // required. - // Take only those documents into account which hasn't be touched by the user - $dList = array(); - foreach ($reviewStatus["indstatus"] as $st) { - if (($st["status"]==0 || $param2) && !in_array($st["documentID"], $dList)) { - $dList[] = $st["documentID"]; - } - } - foreach ($reviewStatus["grpstatus"] as $st) { - if (($st["status"]==0 || $param2) && !in_array($st["documentID"], $dList)) { - $dList[] = $st["documentID"]; - } - } - foreach ($approvalStatus["indstatus"] as $st) { - if (($st["status"]==0 || $param2) && !in_array($st["documentID"], $dList)) { - $dList[] = $st["documentID"]; - } - } - foreach ($approvalStatus["grpstatus"] as $st) { - if (($st["status"]==0 || $param2) && !in_array($st["documentID"], $dList)) { - $dList[] = $st["documentID"]; - } - } - $docCSV = ""; - foreach ($dList as $d) { - $docCSV .= (strlen($docCSV)==0 ? "" : ", ")."'".$d."'"; - } - - if (strlen($docCSV)>0) { - $docstatarr = array(S_DRAFT_REV, S_DRAFT_APP); - if($param5) - $docstatarr[] = S_EXPIRED; - $queryStr .= "AND `tblDocumentStatusLog`.`status` IN (".implode(',', $docstatarr).") ". - "AND `tblDocuments`.`id` IN (" . $docCSV . ") ". - "ORDER BY `statusDate` DESC"; - } else { - $queryStr = ''; - } - break; // }}} - case 'ReviewByMe': // Documents I have to review {{{ - if (!$this->db->createTemporaryTable("ttreviewid")) { - return false; - } - $user = $param1; - $orderby = $param3; - if($param4 == 'desc') - $orderdir = 'DESC'; - else - $orderdir = 'ASC'; - - $groups = array(); - if($user) { - $tmp = $user->getGroups(); - foreach($tmp as $group) - $groups[] = $group->getID(); - } - - $selectStr .= ", `tblDocumentReviewLog`.`date` as `duedate` "; - $queryStr .= - "LEFT JOIN `tblDocumentReviewers` ON `ttcontentid`.`document`=`tblDocumentReviewers`.`documentID` AND `ttcontentid`.`maxVersion`=`tblDocumentReviewers`.`version` ". - "LEFT JOIN `ttreviewid` ON `ttreviewid`.`reviewID` = `tblDocumentReviewers`.`reviewID` ". - "LEFT JOIN `tblDocumentReviewLog` ON `tblDocumentReviewLog`.`reviewLogID`=`ttreviewid`.`maxLogID` "; - - if(1) { - if($user) { - $queryStr .= "WHERE (`tblDocumentReviewers`.`type` = 0 AND `tblDocumentReviewers`.`required` = ".$user->getID()." "; - if($groups) - $queryStr .= "OR `tblDocumentReviewers`.`type` = 1 AND `tblDocumentReviewers`.`required` IN (".implode(',', $groups).") "; - $queryStr .= ") "; - } - $docstatarr = array(S_DRAFT_REV); - if($param5) - $docstatarr[] = S_EXPIRED; - $queryStr .= "AND `tblDocumentStatusLog`.`status` IN (".implode(',', $docstatarr).") "; - if(!$param2) - $queryStr .= " AND `tblDocumentReviewLog`.`status` = 0 "; - if ($orderby=='e') $queryStr .= "ORDER BY `expires`"; - else if ($orderby=='u') $queryStr .= "ORDER BY `statusDate`"; - else if ($orderby=='s') $queryStr .= "ORDER BY `tblDocumentStatusLog`.`status`"; - else $queryStr .= "ORDER BY `name`"; - $queryStr .= " ".$orderdir; - } else { - $queryStr .= "WHERE 1=1 "; - - // Get document list for the current user. - $reviewStatus = $user->getReviewStatus(); - - // Create a comma separated list of all the documentIDs whose information is - // required. - // Take only those documents into account which hasn't be touched by the user - // ($st["status"]==0) - $dList = array(); - foreach ($reviewStatus["indstatus"] as $st) { - if (($st["status"]==0 || $param2) && !in_array($st["documentID"], $dList)) { - $dList[] = $st["documentID"]; - } - } - foreach ($reviewStatus["grpstatus"] as $st) { - if (($st["status"]==0 || $param2) && !in_array($st["documentID"], $dList)) { - $dList[] = $st["documentID"]; - } - } - $docCSV = ""; - foreach ($dList as $d) { - $docCSV .= (strlen($docCSV)==0 ? "" : ", ")."'".$d."'"; - } - - if (strlen($docCSV)>0) { - $queryStr .= "AND `tblDocumentStatusLog`.`status` IN (".S_DRAFT_REV.", ".S_EXPIRED.") ". - "AND `tblDocuments`.`id` IN (" . $docCSV . ") "; - //$queryStr .= "ORDER BY `statusDate` DESC"; - if ($orderby=='e') $queryStr .= "ORDER BY `expires`"; - else if ($orderby=='u') $queryStr .= "ORDER BY `statusDate`"; - else if ($orderby=='s') $queryStr .= "ORDER BY `status`"; - else $queryStr .= "ORDER BY `name`"; - $queryStr .= " ".$orderdir; - } else { - $queryStr = ''; - } - } - break; // }}} - case 'ApproveByMe': // Documents I have to approve {{{ - if (!$this->db->createTemporaryTable("ttapproveid")) { - return false; - } - $user = $param1; - $orderby = $param3; - if($param4 == 'desc') - $orderdir = 'DESC'; - else - $orderdir = 'ASC'; - - $groups = array(); - if($user) { - $tmp = $user->getGroups(); - foreach($tmp as $group) - $groups[] = $group->getID(); - } - - $selectStr .= ", `tblDocumentApproveLog`.`date` as `duedate` "; - $queryStr .= - "LEFT JOIN `tblDocumentApprovers` ON `ttcontentid`.`document`=`tblDocumentApprovers`.`documentID` AND `ttcontentid`.`maxVersion`=`tblDocumentApprovers`.`version` ". - "LEFT JOIN `ttapproveid` ON `ttapproveid`.`approveID` = `tblDocumentApprovers`.`approveID` ". - "LEFT JOIN `tblDocumentApproveLog` ON `tblDocumentApproveLog`.`approveLogID`=`ttapproveid`.`maxLogID` "; - - if(1) { - if($user) { - $queryStr .= "WHERE (`tblDocumentApprovers`.`type` = 0 AND `tblDocumentApprovers`.`required` = ".$user->getID()." "; - if($groups) - $queryStr .= "OR `tblDocumentApprovers`.`type` = 1 AND `tblDocumentApprovers`.`required` IN (".implode(',', $groups).")"; - $queryStr .= ") "; - } - $docstatarr = array(S_DRAFT_APP); - if($param5) - $docstatarr[] = S_EXPIRED; - $queryStr .= "AND `tblDocumentStatusLog`.`status` IN (".implode(',', $docstatarr).") "; - if(!$param2) - $queryStr .= " AND `tblDocumentApproveLog`.`status` = 0 "; - if ($orderby=='e') $queryStr .= "ORDER BY `expires`"; - else if ($orderby=='u') $queryStr .= "ORDER BY `statusDate`"; - else if ($orderby=='s') $queryStr .= "ORDER BY `tblDocumentStatusLog`.`status`"; - else $queryStr .= "ORDER BY `name`"; - $queryStr .= " ".$orderdir; - } else { - $queryStr .= "WHERE 1=1 "; - - // Get document list for the current user. - $approvalStatus = $user->getApprovalStatus(); - - // Create a comma separated list of all the documentIDs whose information is - // required. - // Take only those documents into account which hasn't be touched by the user - // ($st["status"]==0) - $dList = array(); - foreach ($approvalStatus["indstatus"] as $st) { - if (($st["status"]==0 || $param2) && !in_array($st["documentID"], $dList)) { - $dList[] = $st["documentID"]; - } - } - foreach ($approvalStatus["grpstatus"] as $st) { - if (($st["status"]==0 || $param2) && !in_array($st["documentID"], $dList)) { - $dList[] = $st["documentID"]; - } - } - $docCSV = ""; - foreach ($dList as $d) { - $docCSV .= (strlen($docCSV)==0 ? "" : ", ")."'".$d."'"; - } - - if (strlen($docCSV)>0) { - $docstatarr = array(S_DRAFT_APP); - if($param5) - $docstatarr[] = S_EXPIRED; - $queryStr .= "AND `tblDocumentStatusLog`.`status` IN (".implode(',', $docstatarr).") ". - "AND `tblDocuments`.`id` IN (" . $docCSV . ") "; - //$queryStr .= "ORDER BY `statusDate` DESC"; - if ($orderby=='e') $queryStr .= "ORDER BY `expires`"; - else if ($orderby=='u') $queryStr .= "ORDER BY `statusDate`"; - else if ($orderby=='s') $queryStr .= "ORDER BY `status`"; - else $queryStr .= "ORDER BY `name`"; - $queryStr .= " ".$orderdir; - } else { - $queryStr = ''; - } - } - break; // }}} - case 'WorkflowByMe': // Documents I to trigger in Worklflow {{{ - $user = $param1; - $orderby = $param3; - if($param4 == 'desc') - $orderdir = 'DESC'; - else - $orderdir = 'ASC'; - - if(1) { - $groups = array(); - if($user) { - $tmp = $user->getGroups(); - foreach($tmp as $group) - $groups[] = $group->getID(); - } - $selectStr = 'distinct '.$selectStr; - $queryStr .= - "LEFT JOIN `tblWorkflowDocumentContent` ON `ttcontentid`.`document`=`tblWorkflowDocumentContent`.`document` AND `ttcontentid`.`maxVersion`=`tblWorkflowDocumentContent`.`version` ". - "LEFT JOIN `tblWorkflowTransitions` ON `tblWorkflowDocumentContent`.`workflow`=`tblWorkflowTransitions`.`workflow` AND `tblWorkflowDocumentContent`.`state`=`tblWorkflowTransitions`.`state` ". - "LEFT JOIN `tblWorkflowTransitionUsers` ON `tblWorkflowTransitionUsers`.`transition` = `tblWorkflowTransitions`.`id` ". - "LEFT JOIN `tblWorkflowTransitionGroups` ON `tblWorkflowTransitionGroups`.`transition` = `tblWorkflowTransitions`.`id` "; - - if($user) { - $queryStr .= "WHERE (`tblWorkflowTransitionUsers`.`userid` = ".$user->getID()." "; - if($groups) - $queryStr .= "OR `tblWorkflowTransitionGroups`.`groupid` IN (".implode(',', $groups).")"; - $queryStr .= ") "; - } - $queryStr .= "AND `tblDocumentStatusLog`.`status` = ".S_IN_WORKFLOW." "; -// echo 'SELECT '.$selectStr." ".$queryStr; - if ($orderby=='e') $queryStr .= "ORDER BY `expires`"; - else if ($orderby=='u') $queryStr .= "ORDER BY `statusDate`"; - else $queryStr .= "ORDER BY `name`"; - } else { - $queryStr .= "WHERE 1=1 "; - // Get document list for the current user. - $workflowStatus = $user->getWorkflowStatus(); - - // Create a comma separated list of all the documentIDs whose information is - // required. - $dList = array(); - foreach ($workflowStatus["u"] as $st) { - if (!in_array($st["document"], $dList)) { - $dList[] = $st["document"]; - } - } - foreach ($workflowStatus["g"] as $st) { - if (!in_array($st["document"], $dList)) { - $dList[] = $st["document"]; - } - } - $docCSV = ""; - foreach ($dList as $d) { - $docCSV .= (strlen($docCSV)==0 ? "" : ", ")."'".$d."'"; - } - - if (strlen($docCSV)>0) { - $queryStr .= - //"AND `tblDocumentStatusLog`.`status` IN (".S_IN_WORKFLOW.", ".S_EXPIRED.") ". - "AND `tblDocuments`.`id` IN (" . $docCSV . ") ". - "ORDER BY `statusDate` DESC"; - } else { - $queryStr = ''; - } - } - break; // }}} - case 'AppRevOwner': // Documents waiting for review/approval/revision I'm owning {{{ - $queryStr .= "WHERE 1=1 "; - - $user = $param1; - $orderby = $param3; - if($param4 == 'desc') - $orderdir = 'DESC'; - else - $orderdir = 'ASC'; - /** @noinspection PhpUndefinedConstantInspection */ - $queryStr .= "AND `tblDocuments`.`owner` = '".$user->getID()."' ". - "AND `tblDocumentStatusLog`.`status` IN (".S_DRAFT_REV.", ".S_DRAFT_APP.") "; - if ($orderby=='e') $queryStr .= "ORDER BY `expires`"; - else if ($orderby=='u') $queryStr .= "ORDER BY `statusDate`"; - else if ($orderby=='s') $queryStr .= "ORDER BY `status`"; - else $queryStr .= "ORDER BY `name`"; - $queryStr .= " ".$orderdir; -// $queryStr .= "AND `tblDocuments`.`owner` = '".$user->getID()."' ". -// "AND `tblDocumentStatusLog`.`status` IN (".S_DRAFT_REV.", ".S_DRAFT_APP.") ". -// "ORDER BY `statusDate` DESC"; - break; // }}} - case 'RejectOwner': // Documents that has been rejected and I'm owning {{{ - $queryStr .= "WHERE 1=1 "; - - $user = $param1; - $orderby = $param3; - if($param4 == 'desc') - $orderdir = 'DESC'; - else - $orderdir = 'ASC'; - $queryStr .= "AND `tblDocuments`.`owner` = '".$user->getID()."' "; - $queryStr .= "AND `tblDocumentStatusLog`.`status` IN (".S_REJECTED.") "; - //$queryStr .= "ORDER BY `statusDate` DESC"; - if ($orderby=='e') $queryStr .= "ORDER BY `expires`"; - else if ($orderby=='u') $queryStr .= "ORDER BY `statusDate`"; - else if ($orderby=='s') $queryStr .= "ORDER BY `status`"; - else $queryStr .= "ORDER BY `name`"; - $queryStr .= " ".$orderdir; - break; // }}} - case 'LockedByMe': // Documents locked by me {{{ - $queryStr .= "WHERE 1=1 "; - - $user = $param1; - $orderby = $param3; - if($param4 == 'desc') - $orderdir = 'DESC'; - else - $orderdir = 'ASC'; - - $qs = 'SELECT `document` FROM `tblDocumentLocks` WHERE `userID`='.$user->getID(); - $ra = $this->db->getResultArray($qs); - if (is_bool($ra) && !$ra) { - return false; - } - $docs = array(); - foreach($ra as $d) { - $docs[] = $d['document']; - } - - if ($docs) { - $queryStr .= "AND `tblDocuments`.`id` IN (" . implode(',', $docs) . ") "; - if ($orderby=='e') $queryStr .= "ORDER BY `expires`"; - else if ($orderby=='u') $queryStr .= "ORDER BY `statusDate`"; - else if ($orderby=='s') $queryStr .= "ORDER BY `status`"; - else $queryStr .= "ORDER BY `name`"; - $queryStr .= " ".$orderdir; - } else { - $queryStr = ''; - } - break; // }}} - case 'ExpiredOwner': // Documents expired and owned by me {{{ - if(is_int($param2)) { - $ts = mktime(0, 0, 0) + $param2 * 86400; - } elseif(is_string($param2)) { - $tmp = explode('-', $param2, 3); - if(count($tmp) != 3) - return false; - if(!self::checkDate($param2, 'Y-m-d')) - return false; - $ts = mktime(0, 0, 0, $tmp[1], $tmp[2], $tmp[0]); - } else - $ts = mktime(0, 0, 0)-365*86400; /* Start of today - 1 year */ - - $tsnow = mktime(0, 0, 0); /* Start of today */ - if($ts < $tsnow) { /* Check for docs expired in the past */ - $startts = $ts; - $endts = $tsnow+86400; /* Use end of day */ - } else { /* Check for docs which will expire in the future */ - $startts = $tsnow; - $endts = $ts+86400; /* Use end of day */ - } - - $queryStr .= - "WHERE `tblDocuments`.`expires` >= ".$startts." AND `tblDocuments`.`expires` <= ".$endts." "; - - $user = $param1; - $orderby = $param3; - if($param4 == 'desc') - $orderdir = 'DESC'; - else - $orderdir = 'ASC'; - $queryStr .= "AND `tblDocuments`.`owner` = '".$user->getID()."' "; - if ($orderby=='e') $queryStr .= "ORDER BY `expires`"; - else if ($orderby=='u') $queryStr .= "ORDER BY `statusDate`"; - else if ($orderby=='s') $queryStr .= "ORDER BY `status`"; - else $queryStr .= "ORDER BY `name`"; - $queryStr .= " ".$orderdir; - break; // }}} - case 'WorkflowOwner': // Documents waiting for workflow trigger I'm owning {{{ - $queryStr .= "WHERE 1=1 "; - - $user = $param1; - $queryStr .= "AND `tblDocuments`.`owner` = '".$user->getID()."' ". - "AND `tblDocumentStatusLog`.`status` IN (".S_IN_WORKFLOW.") ". - "ORDER BY `statusDate` DESC"; - break; // }}} - case 'MyDocs': // Documents owned by me {{{ - $queryStr .= "WHERE 1=1 "; - - $user = $param1; - $orderby = $param3; - if($param4 == 'desc') - $orderdir = 'DESC'; - else - $orderdir = 'ASC'; - $queryStr .= "AND `tblDocuments`.`owner` = '".$user->getID()."' "; - if ($orderby=='e') $queryStr .= "ORDER BY `expires`"; - else if ($orderby=='u') $queryStr .= "ORDER BY `statusDate`"; - else if ($orderby=='s') $queryStr .= "ORDER BY `status`"; - else $queryStr .= "ORDER BY `name`"; - $queryStr .= " ".$orderdir; - break; // }}} - default: // {{{ - return false; - break; // }}} - } - - if($queryStr) { - $resArr = $this->db->getResultArray('SELECT '.$selectStr.$queryStr); - if (is_bool($resArr) && !$resArr) { - return false; - } - /* - $documents = array(); - foreach($resArr as $row) - $documents[] = $this->getDocument($row["id"]); - */ - } else { - return array(); - } - - return $resArr; - } /* }}} */ - - function makeTimeStamp($hour, $min, $sec, $year, $month, $day) { /* {{{ */ - $thirtyone = array (1, 3, 5, 7, 8, 10, 12); - $thirty = array (4, 6, 9, 11); - - // Very basic check that the terms are valid. Does not fail for illegal - // dates such as 31 Feb. - if (!is_numeric($hour) || !is_numeric($min) || !is_numeric($sec) || !is_numeric($year) || !is_numeric($month) || !is_numeric($day) || $month<1 || $month>12 || $day<1 || $day>31 || $hour<0 || $hour>23 || $min<0 || $min>59 || $sec<0 || $sec>59) { - return false; - } - $year = (int) $year; - $month = (int) $month; - $day = (int) $day; - - if(in_array($month, $thirtyone)) { - $max=31; - } elseif(in_array($month, $thirty)) { - $max=30; - } else { - $max=(($year % 4 == 0) && ($year % 100 != 0 || $year % 400 == 0)) ? 29 : 28; - } - - // Check again if day of month is valid in the given month - if ($day>$max) { - return false; - } - - return mktime($hour, $min, $sec, $month, $day, $year); - } /* }}} */ - - /** - * Search the database for documents - * - * Note: the creation date will be used to check againts the - * date saved with the document - * or folder. The modification date will only be used for documents. It - * is checked against the creation date of the document content. This - * meanѕ that updateѕ of a document will only result in a searchable - * modification if a new version is uploaded. - * - * If the search is filtered by an expiration date, only documents with - * an expiration date will be found. Even if just an end date is given. - * - * @param string $query seach query with space separated words - * @param integer $limit number of items in result set - * @param integer $offset index of first item in result set - * @param string $logicalmode either AND or OR - * @param array $searchin list of fields to search in - * 1 = keywords, 2=name, 3=comment, 4=attributes, 5=id - * @param SeedDMS_Core_Folder|null $startFolder search in the folder only (null for root folder) - * @param SeedDMS_Core_User $owner search for documents owned by this user - * @param array $status list of status - * @param array $creationstartdate search for documents created after this date - * @param array $creationenddate search for documents created before this date - * @param array $modificationstartdate search for documents modified after this date - * @param array $modificationenddate search for documents modified before this date - * @param array $categories list of categories the documents must have assigned - * @param array $attributes list of attributes. The key of this array is the - * attribute definition id. The value of the array is the value of the - * attribute. If the attribute may have multiple values it must be an array. - * @param integer $mode decide whether to search for documents/folders - * 0x1 = documents only - * 0x2 = folders only - * 0x3 = both - * @param array $expirationstartdate search for documents expiring after and on this date - * @param array $expirationenddate search for documents expiring before and on this date - * @return array|bool - */ - function search($query, $limit=0, $offset=0, $logicalmode='AND', $searchin=array(), $startFolder=null, $owner=null, $status = array(), $creationstartdate=array(), $creationenddate=array(), $modificationstartdate=array(), $modificationenddate=array(), $categories=array(), $attributes=array(), $mode=0x3, $expirationstartdate=array(), $expirationenddate=array()) { /* {{{ */ - $orderby = ''; - $statusstartdate = array(); - $statusenddate = array(); - if(is_array($query)) { - foreach(array('limit', 'offset', 'logicalmode', 'searchin', 'startFolder', 'owner', 'status', 'creationstartdate', 'creationenddate', 'modificationstartdate', 'modificationenddate', 'categories', 'attributes', 'mode', 'expirationstartdate', 'expirationenddate') as $paramname) - ${$paramname} = isset($query[$paramname]) ? $query[$paramname] : ${$paramname}; - foreach(array('orderby', 'statusstartdate', 'statusenddate') as $paramname) - ${$paramname} = isset($query[$paramname]) ? $query[$paramname] : ''; - $query = isset($query['query']) ? $query['query'] : ''; - } - /* Ensure $logicalmode has a valid value */ - if($logicalmode != 'OR') - $logicalmode = 'AND'; - - // Split the search string into constituent keywords. - $tkeys=array(); - if (strlen($query)>0) { - $tkeys = preg_split("/[\t\r\n ,]+/", $query); - } - - // if none is checkd search all - if (count($searchin)==0) - $searchin=array(1, 2, 3, 4, 5); - - /*--------- Do it all over again for folders -------------*/ - $totalFolders = 0; - if($mode & 0x2) { - $searchKey = ""; - - $classname = $this->classnames['folder']; - $searchFields = $classname::getSearchFields($this, $searchin); - - if (count($searchFields)>0) { - foreach ($tkeys as $key) { - $key = trim($key); - if (strlen($key)>0) { - $searchKey = (strlen($searchKey)==0 ? "" : $searchKey." ".$logicalmode." ")."(".implode(" like ".$this->db->qstr("%".$key."%")." OR ", $searchFields)." like ".$this->db->qstr("%".$key."%").")"; - } - } - } - - // Check to see if the search has been restricted to a particular sub-tree in - // the folder hierarchy. - $searchFolder = ""; - if ($startFolder) { - $searchFolder = "`tblFolders`.`folderList` LIKE '%:".$startFolder->getID().":%'"; - if($this->checkWithinRootDir) - $searchFolder = '('.$searchFolder." AND `tblFolders`.`folderList` LIKE '%:".$this->rootFolderID.":%')"; - } elseif($this->checkWithinRootDir) { - $searchFolder = "`tblFolders`.`folderList` LIKE '%:".$this->rootFolderID.":%'"; - } - - // Check to see if the search has been restricted to a particular - // document owner. - $searchOwner = ""; - if ($owner) { - if(is_array($owner)) { - $ownerids = array(); - foreach($owner as $o) - $ownerids[] = $o->getID(); - if($ownerids) - $searchOwner = "`tblFolders`.`owner` IN (".implode(',', $ownerids).")"; - } else { - $searchOwner = "`tblFolders`.`owner` = '".$owner->getId()."'"; - } - } - - // Check to see if the search has been restricted to a particular - // attribute. - $searchAttributes = array(); - if ($attributes) { - foreach($attributes as $attrdefid=>$attribute) { - if($attribute) { - $attrdef = $this->getAttributeDefinition($attrdefid); - if($attrdef->getObjType() == SeedDMS_Core_AttributeDefinition::objtype_folder || $attrdef->getObjType() == SeedDMS_Core_AttributeDefinition::objtype_all) { - if($valueset = $attrdef->getValueSet()) { - if($attrdef->getMultipleValues()) { - if(is_string($attribute)) - $attribute = array($attribute); - $searchAttributes[] = "EXISTS (SELECT NULL FROM `tblFolderAttributes` WHERE `tblFolderAttributes`.`attrdef`=".$attrdefid." AND (`tblFolderAttributes`.`value` like '%".$valueset[0].implode("%' OR `tblFolderAttributes`.`value` like '%".$valueset[0], $attribute)."%') AND `tblFolderAttributes`.`folder`=`tblFolders`.`id`)"; - } else { - $searchAttributes[] = "EXISTS (SELECT NULL FROM `tblFolderAttributes` WHERE `tblFolderAttributes`.`attrdef`=".$attrdefid." AND (`tblFolderAttributes`.`value`='".(is_array($attribute) ? implode("' OR `tblFolderAttributes`.`value` = '", $attribute) : $attribute)."') AND `tblFolderAttributes`.`folder`=`tblFolders`.`id`)"; - } - } else { - if($attrdef->getType() == SeedDMS_Core_AttributeDefinition::type_date && is_array($attribute)) { - $kkll = []; - if(!empty($attribute['from'])) - $kkll[] = "`tblFolderAttributes`.`value`>='".$attribute['from']."'"; - if(!empty($attribute['to'])) - $kkll[] = "`tblFolderAttributes`.`value`<='".$attribute['to']."'"; - if($kkll) - $searchAttributes[] = "EXISTS (SELECT NULL FROM `tblFolderAttributes` WHERE `tblFolderAttributes`.`attrdef`=".$attrdefid." AND ".implode(' AND ', $kkll)." AND `tblFolderAttributes`.`folder`=`tblFolders`.`id`)"; - } elseif(is_string($attribute)) { - $searchAttributes[] = "EXISTS (SELECT NULL FROM `tblFolderAttributes` WHERE `tblFolderAttributes`.`attrdef`=".$attrdefid." AND `tblFolderAttributes`.`value` like '%".$attribute."%' AND `tblFolderAttributes`.`folder`=`tblFolders`.`id`)"; - } - } - } - } - } - } - - // Is the search restricted to documents created between two specific dates? - $searchCreateDate = ""; - if ($creationstartdate) { - $startdate = SeedDMS_Core_DMS::makeTimeStamp($creationstartdate['hour'], $creationstartdate['minute'], $creationstartdate['second'], $creationstartdate['year'], $creationstartdate["month"], $creationstartdate["day"]); - if ($startdate) { - $searchCreateDate .= "`tblFolders`.`date` >= ".$this->db->qstr($startdate); - } - } - if ($creationenddate) { - $stopdate = SeedDMS_Core_DMS::makeTimeStamp($creationenddate['hour'], $creationstartdate['minute'], $creationstartdate['second'], $creationenddate["year"], $creationenddate["month"], $creationenddate["day"]); - if ($stopdate) { - /** @noinspection PhpUndefinedVariableInspection */ - if($startdate) - $searchCreateDate .= " AND "; - $searchCreateDate .= "`tblFolders`.`date` <= ".$this->db->qstr($stopdate); - } - } - - $searchQuery = "FROM ".$classname::getSearchTables()." WHERE 1=1"; - - if (strlen($searchKey)>0) { - $searchQuery .= " AND (".$searchKey.")"; - } - if (strlen($searchFolder)>0) { - $searchQuery .= " AND ".$searchFolder; - } - if (strlen($searchOwner)>0) { - $searchQuery .= " AND (".$searchOwner.")"; - } - if (strlen($searchCreateDate)>0) { - $searchQuery .= " AND (".$searchCreateDate.")"; - } - if ($searchAttributes) { - $searchQuery .= " AND (".implode(" AND ", $searchAttributes).")"; - } - - /* Do not search for folders if not at least a search for a key, - * an owner, or creation date is requested. - */ - if($searchKey || $searchOwner || $searchCreateDate || $searchAttributes) { - // Count the number of rows that the search will produce. - $resArr = $this->db->getResultArray("SELECT COUNT(*) AS num FROM (SELECT DISTINCT `tblFolders`.id ".$searchQuery.") a"); - if ($resArr && isset($resArr[0]) && is_numeric($resArr[0]["num"]) && $resArr[0]["num"]>0) { - $totalFolders = (integer)$resArr[0]["num"]; - } - - // If there are no results from the count query, then there is no real need - // to run the full query. TODO: re-structure code to by-pass additional - // queries when no initial results are found. - - // Only search if the offset is not beyond the number of folders - if($totalFolders > $offset) { - // Prepare the complete search query, including the LIMIT clause. - $searchQuery = "SELECT DISTINCT `tblFolders`.`id` ".$searchQuery." GROUP BY `tblFolders`.`id`"; - - switch($orderby) { - case 'dd': - $searchQuery .= " ORDER BY `tblFolders`.`date` DESC"; - break; - case 'da': - case 'd': - $searchQuery .= " ORDER BY `tblFolders`.`date`"; - break; - case 'nd': - $searchQuery .= " ORDER BY `tblFolders`.`name` DESC"; - break; - case 'na': - case 'n': - $searchQuery .= " ORDER BY `tblFolders`.`name`"; - break; - case 'id': - $searchQuery .= " ORDER BY `tblFolders`.`id` DESC"; - break; - case 'ia': - case 'i': - $searchQuery .= " ORDER BY `tblFolders`.`id`"; - break; - default: - break; - } - - if($limit) { - $searchQuery .= " LIMIT ".$limit." OFFSET ".$offset; - } - - // Send the complete search query to the database. - $resArr = $this->db->getResultArray($searchQuery); - } else { - $resArr = array(); - } - - // ------------------- Ausgabe der Ergebnisse ---------------------------- - $numResults = count($resArr); - if ($numResults == 0) { - $folderresult = array('totalFolders'=>$totalFolders, 'folders'=>array()); - } else { - foreach ($resArr as $folderArr) { - $folders[] = $this->getFolder($folderArr['id']); - } - /** @noinspection PhpUndefinedVariableInspection */ - $folderresult = array('totalFolders'=>$totalFolders, 'folders'=>$folders); - } - } else { - $folderresult = array('totalFolders'=>0, 'folders'=>array()); - } - } else { - $folderresult = array('totalFolders'=>0, 'folders'=>array()); - } - - /*--------- Do it all over again for documents -------------*/ - - $totalDocs = 0; - if($mode & 0x1) { - $searchKey = ""; - - $classname = $this->classnames['document']; - $searchFields = $classname::getSearchFields($this, $searchin); - - if (count($searchFields)>0) { - foreach ($tkeys as $key) { - $key = trim($key); - if (strlen($key)>0) { - $searchKey = (strlen($searchKey)==0 ? "" : $searchKey." ".$logicalmode." ")."(".implode(" like ".$this->db->qstr("%".$key."%")." OR ", $searchFields)." like ".$this->db->qstr("%".$key."%").")"; - } - } - } - - // Check to see if the search has been restricted to a particular sub-tree in - // the folder hierarchy. - $searchFolder = ""; - if ($startFolder) { - $searchFolder = "`tblDocuments`.`folderList` LIKE '%:".$startFolder->getID().":%'"; - if($this->checkWithinRootDir) - $searchFolder = '('.$searchFolder." AND `tblDocuments`.`folderList` LIKE '%:".$this->rootFolderID.":%')"; - } elseif($this->checkWithinRootDir) { - $searchFolder = "`tblDocuments`.`folderList` LIKE '%:".$this->rootFolderID.":%'"; - } - - // Check to see if the search has been restricted to a particular - // document owner. - $searchOwner = ""; - if ($owner) { - if(is_array($owner)) { - $ownerids = array(); - foreach($owner as $o) - $ownerids[] = $o->getID(); - if($ownerids) - $searchOwner = "`tblDocuments`.`owner` IN (".implode(',', $ownerids).")"; - } else { - $searchOwner = "`tblDocuments`.`owner` = '".$owner->getId()."'"; - } - } - - // Check to see if the search has been restricted to a particular - // document category. - $searchCategories = ""; - if ($categories) { - $catids = array(); - foreach($categories as $category) - $catids[] = $category->getId(); - $searchCategories = "`tblDocumentCategory`.`categoryID` in (".implode(',', $catids).")"; - } - - // Check to see if the search has been restricted to a particular - // attribute. - $searchAttributes = array(); - if ($attributes) { - foreach($attributes as $attrdefid=>$attribute) { - if($attribute) { - $lsearchAttributes = []; - $attrdef = $this->getAttributeDefinition($attrdefid); - if($attrdef->getObjType() == SeedDMS_Core_AttributeDefinition::objtype_document || $attrdef->getObjType() == SeedDMS_Core_AttributeDefinition::objtype_all) { - if($valueset = $attrdef->getValueSet()) { - if($attrdef->getMultipleValues()) { - if(is_string($attribute)) - $attribute = array($attribute); - $lsearchAttributes[] = "EXISTS (SELECT NULL FROM `tblDocumentAttributes` WHERE `tblDocumentAttributes`.`attrdef`=".$attrdefid." AND (`tblDocumentAttributes`.`value` like '%".$valueset[0].implode("%' OR `tblDocumentAttributes`.`value` like '%".$valueset[0], $attribute)."%') AND `tblDocumentAttributes`.`document` = `tblDocuments`.`id`)"; - } else - $lsearchAttributes[] = "EXISTS (SELECT NULL FROM `tblDocumentAttributes` WHERE `tblDocumentAttributes`.`attrdef`=".$attrdefid." AND (`tblDocumentAttributes`.`value`='".(is_array($attribute) ? implode("' OR `tblDocumentAttributes`.`value` = '", $attribute) : $attribute)."') AND `tblDocumentAttributes`.`document` = `tblDocuments`.`id`)"; - } else { - if($attrdef->getType() == SeedDMS_Core_AttributeDefinition::type_date && is_array($attribute)) { - $kkll = []; - if(!empty($attribute['from'])) - $kkll[] = "`tblDocumentAttributes`.`value`>='".$attribute['from']."'"; - if(!empty($attribute['to'])) - $kkll[] = "`tblDocumentAttributes`.`value`<='".$attribute['to']."'"; - if($kkll) - $lsearchAttributes[] = "EXISTS (SELECT NULL FROM `tblDocumentAttributes` WHERE `tblDocumentAttributes`.`attrdef`=".$attrdefid." AND ".implode(' AND ', $kkll)." AND `tblDocumentAttributes`.`document`=`tblDocuments`.`id`)"; - } else { - $lsearchAttributes[] = "EXISTS (SELECT NULL FROM `tblDocumentAttributes` WHERE `tblDocumentAttributes`.`attrdef`=".$attrdefid." AND `tblDocumentAttributes`.`value` like '%".$attribute."%' AND `tblDocumentAttributes`.`document` = `tblDocuments`.`id`)"; - } - } - } - if($attrdef->getObjType() == SeedDMS_Core_AttributeDefinition::objtype_documentcontent || $attrdef->getObjType() == SeedDMS_Core_AttributeDefinition::objtype_all) { - if($valueset = $attrdef->getValueSet()) { - if($attrdef->getMultipleValues()) { - /** @noinspection PhpUndefinedVariableInspection */ - if(is_string($attribute)) - $attribute = array($attribute); - $lsearchAttributes[] = "EXISTS (SELECT NULL FROM `tblDocumentContentAttributes` WHERE `tblDocumentContentAttributes`.`attrdef`=".$attrdefid." AND (`tblDocumentContentAttributes`.`value` like '%".$valueset[0].implode("%' OR `tblDocumentContentAttributes`.`value` like '%".$valueset[0], $attribute)."%') AND `tblDocumentContentAttributes`.`content` = `tblDocumentContent`.`id`)"; - } else { - $lsearchAttributes[] = "EXISTS (SELECT NULL FROM `tblDocumentContentAttributes` WHERE `tblDocumentContentAttributes`.`attrdef`=".$attrdefid." AND (`tblDocumentContentAttributes`.`value`='".(is_array($attribute) ? implode("' OR `tblDocumentContentAttributes`.`value` = '", $attribute) : $attribute)."') AND `tblDocumentContentAttributes`.content = `tblDocumentContent`.id)"; - } - } else { - if($attrdef->getType() == SeedDMS_Core_AttributeDefinition::type_date && is_array($attribute)) { - $kkll = []; - if(!empty($attribute['from'])) - $kkll[] = "`tblDocumentContentAttributes`.`value`>='".$attribute['from']."'"; - if(!empty($attribute['to'])) - $kkll[] = "`tblDocumentContentAttributes`.`value`<='".$attribute['to']."'"; - if($kkll) - $lsearchAttributes[] = "EXISTS (SELECT NULL FROM `tblDocumentContentAttributes` WHERE `tblDocumentContentAttributes`.`attrdef`=".$attrdefid." AND ".implode(' AND ', $kkll)." AND `tblDocumentContentAttributes`.`content`=`tblDocumentContent`.`id`)"; - } else { - $lsearchAttributes[] = "EXISTS (SELECT NULL FROM `tblDocumentContentAttributes` WHERE `tblDocumentContentAttributes`.`attrdef`=".$attrdefid." AND `tblDocumentContentAttributes`.`value` like '%".$attribute."%' AND `tblDocumentContentAttributes`.content = `tblDocumentContent`.id)"; - } - } - } - if($lsearchAttributes) - $searchAttributes[] = "(".implode(" OR ", $lsearchAttributes).")"; - } - } - } - - // Is the search restricted to documents created between two specific dates? - $searchCreateDate = ""; - if ($creationstartdate) { - $startdate = SeedDMS_Core_DMS::makeTimeStamp($creationstartdate['hour'], $creationstartdate['minute'], $creationstartdate['second'], $creationstartdate['year'], $creationstartdate["month"], $creationstartdate["day"]); - if ($startdate) { - $searchCreateDate .= "`tblDocuments`.`date` >= ".$this->db->qstr($startdate); - } - } - if ($creationenddate) { - $stopdate = SeedDMS_Core_DMS::makeTimeStamp($creationenddate['hour'], $creationenddate['minute'], $creationenddate['second'], $creationenddate["year"], $creationenddate["month"], $creationenddate["day"]); - if ($stopdate) { - if($searchCreateDate) - $searchCreateDate .= " AND "; - $searchCreateDate .= "`tblDocuments`.`date` <= ".$this->db->qstr($stopdate); - } - } - if ($modificationstartdate) { - $startdate = SeedDMS_Core_DMS::makeTimeStamp($modificationstartdate['hour'], $modificationstartdate['minute'], $modificationstartdate['second'], $modificationstartdate['year'], $modificationstartdate["month"], $modificationstartdate["day"]); - if ($startdate) { - if($searchCreateDate) - $searchCreateDate .= " AND "; - $searchCreateDate .= "`tblDocumentContent`.`date` >= ".$startdate; - } - } - if ($modificationenddate) { - $stopdate = SeedDMS_Core_DMS::makeTimeStamp($modificationenddate['hour'], $modificationenddate['minute'], $modificationenddate['second'], $modificationenddate["year"], $modificationenddate["month"], $modificationenddate["day"]); - if ($stopdate) { - if($searchCreateDate) - $searchCreateDate .= " AND "; - $searchCreateDate .= "`tblDocumentContent`.`date` <= ".$this->db->qstr($stopdate); - } - } - $searchExpirationDate = ''; - if ($expirationstartdate) { - $startdate = SeedDMS_Core_DMS::makeTimeStamp($expirationstartdate['hour'], $expirationstartdate['minute'], $expirationstartdate['second'], $expirationstartdate['year'], $expirationstartdate["month"], $expirationstartdate["day"]); - if ($startdate) { - $searchExpirationDate .= "`tblDocuments`.`expires` >= ".$this->db->qstr($startdate); - } - } - if ($expirationenddate) { - $stopdate = SeedDMS_Core_DMS::makeTimeStamp($expirationenddate['hour'], $expirationenddate['minute'], $expirationenddate['second'], $expirationenddate["year"], $expirationenddate["month"], $expirationenddate["day"]); - if ($stopdate) { - if($searchExpirationDate) - $searchExpirationDate .= " AND "; - else // do not find documents without an expiration date - $searchExpirationDate .= "`tblDocuments`.`expires` != 0 AND "; - $searchExpirationDate .= "`tblDocuments`.`expires` <= ".$this->db->qstr($stopdate); - } - } - $searchStatusDate = ''; - if ($statusstartdate) { - $startdate = $statusstartdate['year'].'-'.$statusstartdate["month"].'-'.$statusstartdate["day"].' '.$statusstartdate['hour'].':'.$statusstartdate['minute'].':'.$statusstartdate['second']; - if ($startdate) { - if($searchStatusDate) - $searchStatusDate .= " AND "; - $searchStatusDate .= "`tblDocumentStatusLog`.`date` >= ".$this->db->qstr($startdate); - } - } - if ($statusenddate) { - $stopdate = $statusenddate['year'].'-'.$statusenddate["month"].'-'.$statusenddate["day"].' '.$statusenddate['hour'].':'.$statusenddate['minute'].':'.$statusenddate['second']; - if ($stopdate) { - if($searchStatusDate) - $searchStatusDate .= " AND "; - $searchStatusDate .= "`tblDocumentStatusLog`.`date` <= ".$this->db->qstr($stopdate); - } - } - - // ---------------------- Suche starten ---------------------------------- - - // - // Construct the SQL query that will be used to search the database. - // - - if (!$this->db->createTemporaryTable("ttcontentid") || !$this->db->createTemporaryTable("ttstatid")) { - return false; - } - - $searchQuery = "FROM `tblDocuments` ". - "LEFT JOIN `tblDocumentContent` ON `tblDocuments`.`id` = `tblDocumentContent`.`document` ". - "LEFT JOIN `tblDocumentAttributes` ON `tblDocuments`.`id` = `tblDocumentAttributes`.`document` ". - "LEFT JOIN `tblDocumentContentAttributes` ON `tblDocumentContent`.`id` = `tblDocumentContentAttributes`.`content` ". - "LEFT JOIN `tblDocumentStatus` ON `tblDocumentStatus`.`documentID` = `tblDocumentContent`.`document` ". - "LEFT JOIN `ttstatid` ON `ttstatid`.`statusID` = `tblDocumentStatus`.`statusID` ". - "LEFT JOIN `tblDocumentStatusLog` ON `tblDocumentStatusLog`.`statusLogID` = `ttstatid`.`maxLogID` ". - "LEFT JOIN `ttcontentid` ON `ttcontentid`.`maxVersion` = `tblDocumentStatus`.`version` AND `ttcontentid`.`document` = `tblDocumentStatus`.`documentID` ". - "LEFT JOIN `tblDocumentLocks` ON `tblDocuments`.`id`=`tblDocumentLocks`.`document` ". - "LEFT JOIN `tblDocumentCategory` ON `tblDocuments`.`id`=`tblDocumentCategory`.`documentID` ". - "WHERE ". - // "`ttstatid`.`maxLogID`=`tblDocumentStatusLog`.`statusLogID` AND ". - "`ttcontentid`.`maxVersion` = `tblDocumentContent`.`version`"; - - if (strlen($searchKey)>0) { - $searchQuery .= " AND (".$searchKey.")"; - } - if (strlen($searchFolder)>0) { - $searchQuery .= " AND ".$searchFolder; - } - if (strlen($searchOwner)>0) { - $searchQuery .= " AND (".$searchOwner.")"; - } - if (strlen($searchCategories)>0) { - $searchQuery .= " AND (".$searchCategories.")"; - } - if (strlen($searchCreateDate)>0) { - $searchQuery .= " AND (".$searchCreateDate.")"; - } - if (strlen($searchExpirationDate)>0) { - $searchQuery .= " AND (".$searchExpirationDate.")"; - } - if (strlen($searchStatusDate)>0) { - $searchQuery .= " AND (".$searchStatusDate.")"; - } - if ($searchAttributes) { - $searchQuery .= " AND (".implode(" AND ", $searchAttributes).")"; - } - - // status - if ($status) { - $searchQuery .= " AND `tblDocumentStatusLog`.`status` IN (".implode(',', $status).")"; - } - - if($searchKey || $searchOwner || $searchCategories || $searchCreateDate || $searchExpirationDate || $searchStatusDate || $searchAttributes || $status) { - // Count the number of rows that the search will produce. - $resArr = $this->db->getResultArray("SELECT COUNT(*) AS num FROM (SELECT DISTINCT `tblDocuments`.`id` ".$searchQuery.") a"); - $totalDocs = 0; - if (is_numeric($resArr[0]["num"]) && $resArr[0]["num"]>0) { - $totalDocs = (integer)$resArr[0]["num"]; - } - - // If there are no results from the count query, then there is no real need - // to run the full query. TODO: re-structure code to by-pass additional - // queries when no initial results are found. - - // Prepare the complete search query, including the LIMIT clause. - $searchQuery = "SELECT DISTINCT `tblDocuments`.*, ". - "`tblDocumentContent`.`version`, ". - "`tblDocumentStatusLog`.`status`, `tblDocumentLocks`.`userID` as `lockUser` ".$searchQuery; - - switch($orderby) { - case 'dd': - $orderbyQuery = " ORDER BY `tblDocuments`.`date` DESC"; - break; - case 'da': - case 'd': - $orderbyQuery = " ORDER BY `tblDocuments`.`date`"; - break; - case 'nd': - $orderbyQuery = " ORDER BY `tblDocuments`.`name` DESC"; - break; - case 'na': - case 'n': - $orderbyQuery = " ORDER BY `tblDocuments`.`name`"; - break; - case 'id': - $orderbyQuery = " ORDER BY `tblDocuments`.`id` DESC"; - break; - case 'ia': - case 'i': - $orderbyQuery = " ORDER BY `tblDocuments`.`id`"; - break; - default: - $orderbyQuery = ""; - break; - } - - // calculate the remaining entrїes of the current page - // If page is not full yet, get remaining entries - if($limit) { - $remain = $limit - count($folderresult['folders']); - if($remain) { - if($remain == $limit) - $offset -= $totalFolders; - else - $offset = 0; - - $searchQuery .= $orderbyQuery; - - if($limit) - $searchQuery .= " LIMIT ".$limit." OFFSET ".$offset; - - // Send the complete search query to the database. - $resArr = $this->db->getResultArray($searchQuery); - if($resArr === false) - return false; - } else { - $resArr = array(); - } - } else { - $searchQuery .= $orderbyQuery; - - // Send the complete search query to the database. - $resArr = $this->db->getResultArray($searchQuery); - if($resArr === false) - return false; - } - - // ------------------- Ausgabe der Ergebnisse ---------------------------- - $numResults = count($resArr); - if ($numResults == 0) { - $docresult = array('totalDocs'=>$totalDocs, 'docs'=>array()); - } else { - foreach ($resArr as $docArr) { - $docs[] = $this->getDocument($docArr['id']); - } - /** @noinspection PhpUndefinedVariableInspection */ - $docresult = array('totalDocs'=>$totalDocs, 'docs'=>$docs); - } - } else { - $docresult = array('totalDocs'=>0, 'docs'=>array()); - } - } else { - $docresult = array('totalDocs'=>0, 'docs'=>array()); - } - - if($limit) { - $totalPages = (integer)(($totalDocs+$totalFolders)/$limit); - if ((($totalDocs+$totalFolders)%$limit) > 0) { - $totalPages++; - } - } else { - $totalPages = 1; - } - - return array_merge($docresult, $folderresult, array('totalPages'=>$totalPages)); - } /* }}} */ - - /** - * Return a folder by its id - * - * This function retrieves a folder from the database by its id. - * - * @param integer $id internal id of folder - * @return SeedDMS_Core_Folder instance of SeedDMS_Core_Folder or false - */ - function getFolder($id) { /* {{{ */ - $classname = $this->classnames['folder']; - return $classname::getInstance($id, $this); - } /* }}} */ - - /** - * Return a folder by its name - * - * This function retrieves a folder from the database by its name. The - * search covers the whole database. If - * the parameter $folder is not null, it will search for the name - * only within this parent folder. It will not be done recursively. - * - * @param string $name name of the folder - * @param SeedDMS_Core_Folder $folder parent folder - * @return SeedDMS_Core_Folder|boolean found folder or false - */ - function getFolderByName($name, $folder=null) { /* {{{ */ - $name = trim($name); - $classname = $this->classnames['folder']; - return $classname::getInstanceByName($name, $folder, $this); - } /* }}} */ - - /** - * Returns a list of folders and error message not linked in the tree - * - * This function checks all folders in the database. - * - * @return array|bool - */ - function checkFolders() { /* {{{ */ - $queryStr = "SELECT * FROM `tblFolders`"; - $resArr = $this->db->getResultArray($queryStr); - - if (is_bool($resArr) && $resArr === false) - return false; - - $cache = array(); - foreach($resArr as $rec) { - $cache[$rec['id']] = array('name'=>$rec['name'], 'parent'=>$rec['parent'], 'folderList'=>$rec['folderList']); - } - $errors = array(); - foreach($cache as $id=>$rec) { - if(!array_key_exists($rec['parent'], $cache) && $rec['parent'] != 0) { - $errors[$id] = array('id'=>$id, 'name'=>$rec['name'], 'parent'=>$rec['parent'], 'msg'=>'Missing parent'); - } - if(!isset($errors[$id])) { - /* Create the real folderList and compare it with the stored folderList */ - $parent = $rec['parent']; - $fl = []; - while($parent) { - array_unshift($fl, $parent); - $parent = $cache[$parent]['parent']; - } - if($fl) - $flstr = ':'.implode(':', $fl).':'; - else - $flstr = ''; - if($flstr != $rec['folderList']) - $errors[$id] = array('id'=>$id, 'name'=>$rec['name'], 'parent'=>$rec['parent'], 'msg'=>'Wrong folder list '.$flstr.'!='.$rec['folderList']); - } - if(!isset($errors[$id])) { - /* This is the old insufficient test which will most likely not be called - * anymore, because the check for a wrong folder list will cache a folder - * list problem anyway. - */ - $tmparr = explode(':', $rec['folderList']); - array_shift($tmparr); - if(count($tmparr) != count(array_unique($tmparr))) { - $errors[$id] = array('id'=>$id, 'name'=>$rec['name'], 'parent'=>$rec['parent'], 'msg'=>'Duplicate entry in folder list ('.$rec['folderList'].')'); - } - } - } - - return $errors; - } /* }}} */ - - /** - * Returns a list of documents and error message not linked in the tree - * - * This function checks all documents in the database. - * - * @return array|bool - */ - function checkDocuments() { /* {{{ */ - $queryStr = "SELECT * FROM `tblFolders`"; - $resArr = $this->db->getResultArray($queryStr); - - if (is_bool($resArr) && $resArr === false) - return false; - - $fcache = array(); - foreach($resArr as $rec) { - $fcache[$rec['id']] = array('name'=>$rec['name'], 'parent'=>$rec['parent'], 'folderList'=>$rec['folderList']); - } - - $queryStr = "SELECT * FROM `tblDocuments`"; - $resArr = $this->db->getResultArray($queryStr); - - if (is_bool($resArr) && $resArr === false) - return false; - - $dcache = array(); - foreach($resArr as $rec) { - $dcache[$rec['id']] = array('name'=>$rec['name'], 'parent'=>$rec['folder'], 'folderList'=>$rec['folderList']); - } - $errors = array(); - foreach($dcache as $id=>$rec) { - if(!array_key_exists($rec['parent'], $fcache) && $rec['parent'] != 0) { - $errors[$id] = array('id'=>$id, 'name'=>$rec['name'], 'parent'=>$rec['parent'], 'msg'=>'Missing parent'); - } - if(!isset($errors[$id])) { - /* Create the real folderList and compare it with the stored folderList */ - $parent = $rec['parent']; - $fl = []; - while($parent) { - array_unshift($fl, $parent); - $parent = $fcache[$parent]['parent']; - } - if($fl) - $flstr = ':'.implode(':', $fl).':'; - if($flstr != $rec['folderList']) - $errors[$id] = array('id'=>$id, 'name'=>$rec['name'], 'parent'=>$rec['parent'], 'msg'=>'Wrong folder list '.$flstr.'!='.$rec['folderList']); - } - if(!isset($errors[$id])) { - $tmparr = explode(':', $rec['folderList']); - array_shift($tmparr); - if(count($tmparr) != count(array_unique($tmparr))) { - $errors[$id] = array('id'=>$id, 'name'=>$rec['name'], 'parent'=>$rec['parent'], 'msg'=>'Duplicate entry in folder list ('.$rec['folderList'].''); - } - } - } - - return $errors; - } /* }}} */ - - /** - * Return a user by its id - * - * This function retrieves a user from the database by its id. - * - * @param integer $id internal id of user - * @return SeedDMS_Core_User|boolean instance of {@link SeedDMS_Core_User} or false - */ - function getUser($id) { /* {{{ */ - $classname = $this->classnames['user']; - return $classname::getInstance($id, $this); - } /* }}} */ - - /** - * Return a user by its login - * - * This function retrieves a user from the database by its login. - * If the second optional parameter $email is not empty, the user must - * also have the given email. - * - * @param string $login internal login of user - * @param string $email email of user - * @return object instance of {@link SeedDMS_Core_User} or false - */ - function getUserByLogin($login, $email='') { /* {{{ */ - $classname = $this->classnames['user']; - return $classname::getInstance($login, $this, 'name', $email); - } /* }}} */ - - /** - * Return a user by its email - * - * This function retrieves a user from the database by its email. - * It is needed when the user requests a new password. - * - * @param integer $email email address of user - * @return object instance of {@link SeedDMS_Core_User} or false - */ - function getUserByEmail($email) { /* {{{ */ - $classname = $this->classnames['user']; - return $classname::getInstance($email, $this, 'email'); - } /* }}} */ - - /** - * Return list of all users - * - * @param string $orderby - * @return array of instances of SeedDMS_Core_User or false - * or false - */ - function getAllUsers($orderby = '') { /* {{{ */ - $classname = $this->classnames['user']; - return $classname::getAllInstances($orderby, $this); - } /* }}} */ - - /** - * Add a new user - * - * @param string $login login name - * @param string $pwd password of new user - * @param $fullName - * @param string $email Email of new user - * @param string $language language of new user - * @param $theme - * @param string $comment comment of new user - * @param int|string $role role of new user (can be 0=normal, 1=admin, 2=guest) - * @param integer $isHidden hide user in all lists, if this is set login - * is still allowed - * @param integer $isDisabled disable user and prevent login - * @param string $pwdexpiration - * @param int $quota - * @param null $homefolder - * @return bool|SeedDMS_Core_User - */ - function addUser($login, $pwd, $fullName, $email, $language, $theme, $comment, $role='0', $isHidden=0, $isDisabled=0, $pwdexpiration='', $quota=0, $homefolder=null) { /* {{{ */ - $db = $this->db; - if (is_object($this->getUserByLogin($login))) { - return false; - } - if($role == '') - $role = '0'; - if(trim($pwdexpiration) == '' || trim($pwdexpiration) == 'never') { - $pwdexpiration = 'NULL'; - } elseif(trim($pwdexpiration) == 'now') { - $pwdexpiration = $db->qstr(date('Y-m-d H:i:s')); - } else { - $pwdexpiration = $db->qstr($pwdexpiration); - } - $queryStr = "INSERT INTO `tblUsers` (`login`, `pwd`, `fullName`, `email`, `language`, `theme`, `comment`, `role`, `hidden`, `disabled`, `pwdExpiration`, `quota`, `homefolder`) VALUES (".$db->qstr($login).", ".$db->qstr($pwd).", ".$db->qstr($fullName).", ".$db->qstr($email).", '".$language."', '".$theme."', ".$db->qstr($comment).", '".intval($role)."', '".intval($isHidden)."', '".intval($isDisabled)."', ".$pwdexpiration.", '".intval($quota)."', ".($homefolder ? intval($homefolder) : "NULL").")"; - $res = $this->db->getResult($queryStr); - if (!$res) - return false; - - $user = $this->getUser($this->db->getInsertID('tblUsers')); - - /* Check if 'onPostAddUser' callback is set */ - if(isset($this->callbacks['onPostAddUser'])) { - foreach($this->callbacks['onPostAddUser'] as $callback) { - /** @noinspection PhpStatementHasEmptyBodyInspection */ - if(!call_user_func($callback[0], $callback[1], $user)) { - } - } - } - - return $user; - } /* }}} */ - - /** - * Get a group by its id - * - * @param integer $id id of group - * @return SeedDMS_Core_Group|boolean group or false if no group was found - */ - function getGroup($id) { /* {{{ */ - $classname = $this->classnames['group']; - return $classname::getInstance($id, $this, ''); - } /* }}} */ - - /** - * Get a group by its name - * - * @param string $name name of group - * @return SeedDMS_Core_Group|boolean group or false if no group was found - */ - function getGroupByName($name) { /* {{{ */ - $name = trim($name); - $classname = $this->classnames['group']; - return $classname::getInstance($name, $this, 'name'); - } /* }}} */ - - /** - * Get a list of all groups - * - * @return SeedDMS_Core_Group[] array of instances of {@link SeedDMS_Core_Group} - */ - function getAllGroups() { /* {{{ */ - $classname = $this->classnames['group']; - return $classname::getAllInstances('name', $this); - } /* }}} */ - - /** - * Create a new user group - * - * @param string $name name of group - * @param string $comment comment of group - * @return SeedDMS_Core_Group|boolean instance of {@link SeedDMS_Core_Group} or false in - * case of an error. - */ - function addGroup($name, $comment) { /* {{{ */ - $name = trim($name); - if (is_object($this->getGroupByName($name))) { - return false; - } - - $queryStr = "INSERT INTO `tblGroups` (`name`, `comment`) VALUES (".$this->db->qstr($name).", ".$this->db->qstr($comment).")"; - if (!$this->db->getResult($queryStr)) - return false; - - $group = $this->getGroup($this->db->getInsertID('tblGroups')); - - /* Check if 'onPostAddGroup' callback is set */ - if(isset($this->callbacks['onPostAddGroup'])) { - foreach($this->callbacks['onPostAddGroup'] as $callback) { - /** @noinspection PhpStatementHasEmptyBodyInspection */ - if(!call_user_func($callback[0], $callback[1], $group)) { - } - } - } - - return $group; - } /* }}} */ - - function getKeywordCategory($id) { /* {{{ */ - if (!is_numeric($id) || $id < 1) - return false; - - $queryStr = "SELECT * FROM `tblKeywordCategories` WHERE `id` = " . (int) $id; - $resArr = $this->db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - if (count($resArr) != 1) - return null; - - $resArr = $resArr[0]; - $cat = new SeedDMS_Core_Keywordcategory($resArr["id"], $resArr["owner"], $resArr["name"]); - $cat->setDMS($this); - return $cat; - } /* }}} */ - - function getKeywordCategoryByName($name, $userID) { /* {{{ */ - if (!is_numeric($userID) || $userID < 1) - return false; - $name = trim($name); - $queryStr = "SELECT * FROM `tblKeywordCategories` WHERE `name` = " . $this->db->qstr($name) . " AND `owner` = " . (int) $userID; - $resArr = $this->db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - if (count($resArr) != 1) - return null; - - $resArr = $resArr[0]; - $cat = new SeedDMS_Core_Keywordcategory($resArr["id"], $resArr["owner"], $resArr["name"]); - $cat->setDMS($this); - return $cat; - } /* }}} */ - - function getAllKeywordCategories($userIDs = array()) { /* {{{ */ - $queryStr = "SELECT * FROM `tblKeywordCategories`"; - /* Ensure $userIDs() will only contain integers > 0 */ - $userIDs = array_filter(array_unique(array_map('intval', $userIDs)), function($a) {return $a > 0;}); - if ($userIDs) { - $queryStr .= " WHERE `owner` IN (".implode(',', $userIDs).")"; - } - - $resArr = $this->db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - $categories = array(); - foreach ($resArr as $row) { - $cat = new SeedDMS_Core_KeywordCategory($row["id"], $row["owner"], $row["name"]); - $cat->setDMS($this); - array_push($categories, $cat); - } - - return $categories; - } /* }}} */ - - /** - * This function should be replaced by getAllKeywordCategories() - * - * @param $userID - * @return SeedDMS_Core_KeywordCategory[]|bool - */ - function getAllUserKeywordCategories($userID) { /* {{{ */ - if (!is_numeric($userID) || $userID < 1) - return false; - return self::getAllKeywordCategories([$userID]); - } /* }}} */ - - function addKeywordCategory($userID, $name) { /* {{{ */ - if (!is_numeric($userID) || $userID < 1) - return false; - $name = trim($name); - if(!$name) - return false; - if (is_object($this->getKeywordCategoryByName($name, $userID))) { - return false; - } - $queryStr = "INSERT INTO `tblKeywordCategories` (`owner`, `name`) VALUES (".(int) $userID.", ".$this->db->qstr($name).")"; - if (!$this->db->getResult($queryStr)) - return false; - - $category = $this->getKeywordCategory($this->db->getInsertID('tblKeywordCategories')); - - /* Check if 'onPostAddKeywordCategory' callback is set */ - if(isset($this->callbacks['onPostAddKeywordCategory'])) { - foreach($this->callbacks['onPostAddKeywordCategory'] as $callback) { - /** @noinspection PhpStatementHasEmptyBodyInspection */ - if(!call_user_func($callback[0], $callback[1], $category)) { - } - } - } - - return $category; - } /* }}} */ - - function getDocumentCategory($id) { /* {{{ */ - if (!is_numeric($id) || $id < 1) - return false; - - $queryStr = "SELECT * FROM `tblCategory` WHERE `id` = " . (int) $id; - $resArr = $this->db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - if (count($resArr) != 1) - return null; - - $resArr = $resArr[0]; - $cat = new SeedDMS_Core_DocumentCategory($resArr["id"], $resArr["name"]); - $cat->setDMS($this); - return $cat; - } /* }}} */ - - function getDocumentCategories() { /* {{{ */ - $queryStr = "SELECT * FROM `tblCategory` order by `name`"; - - $resArr = $this->db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - $categories = array(); - foreach ($resArr as $row) { - $cat = new SeedDMS_Core_DocumentCategory($row["id"], $row["name"]); - $cat->setDMS($this); - array_push($categories, $cat); - } - - return $categories; - } /* }}} */ - - /** - * Get a category by its name - * - * The name of a category is by default unique. - * - * @param string $name human readable name of category - * @return SeedDMS_Core_DocumentCategory|boolean instance of {@link SeedDMS_Core_DocumentCategory} - */ - function getDocumentCategoryByName($name) { /* {{{ */ - $name = trim($name); - if (!$name) return false; - - $queryStr = "SELECT * FROM `tblCategory` WHERE `name`=".$this->db->qstr($name); - $resArr = $this->db->getResultArray($queryStr); - if (!$resArr) - return false; - - $row = $resArr[0]; - $cat = new SeedDMS_Core_DocumentCategory($row["id"], $row["name"]); - $cat->setDMS($this); - - return $cat; - } /* }}} */ - - function addDocumentCategory($name) { /* {{{ */ - $name = trim($name); - if(!$name) - return false; - if (is_object($this->getDocumentCategoryByName($name))) { - return false; - } - $queryStr = "INSERT INTO `tblCategory` (`name`) VALUES (".$this->db->qstr($name).")"; - if (!$this->db->getResult($queryStr)) - return false; - - $category = $this->getDocumentCategory($this->db->getInsertID('tblCategory')); - - /* Check if 'onPostAddDocumentCategory' callback is set */ - if(isset($this->callbacks['onPostAddDocumentCategory'])) { - foreach($this->callbacks['onPostAddDocumentCategory'] as $callback) { - /** @noinspection PhpStatementHasEmptyBodyInspection */ - if(!call_user_func($callback[0], $callback[1], $category)) { - } - } - } - - return $category; - } /* }}} */ - - /** - * Get all notifications for a group - * - * deprecated: User {@link SeedDMS_Core_Group::getNotifications()} - * - * @param object $group group for which notifications are to be retrieved - * @param integer $type type of item (T_DOCUMENT or T_FOLDER) - * @return array array of notifications - */ - function getNotificationsByGroup($group, $type=0) { /* {{{ */ - return $group->getNotifications($type); - } /* }}} */ - - /** - * Get all notifications for a user - * - * deprecated: User {@link SeedDMS_Core_User::getNotifications()} - * - * @param object $user user for which notifications are to be retrieved - * @param integer $type type of item (T_DOCUMENT or T_FOLDER) - * @return array array of notifications - */ - function getNotificationsByUser($user, $type=0) { /* {{{ */ - return $user->getNotifications($type); - } /* }}} */ - - /** - * Create a token to request a new password. - * This function will not delete the password but just creates an entry - * in tblUserRequestPassword indicating a password request. - * - * @param SeedDMS_Core_User $user - * @return string|boolean hash value of false in case of an error - */ - function createPasswordRequest($user) { /* {{{ */ - $lenght = 32; - if (function_exists("random_bytes")) { - $bytes = random_bytes(ceil($lenght / 2)); - } elseif (function_exists("openssl_random_pseudo_bytes")) { - $bytes = openssl_random_pseudo_bytes(ceil($lenght / 2)); - } else { - return false; - } - $hash = bin2hex($bytes); - $queryStr = "INSERT INTO `tblUserPasswordRequest` (`userID`, `hash`, `date`) VALUES (" . $user->getId() . ", " . $this->db->qstr($hash) .", ".$this->db->getCurrentDatetime().")"; - $resArr = $this->db->getResult($queryStr); - if (is_bool($resArr) && !$resArr) return false; - return $hash; - - } /* }}} */ - - /** - * Check if hash for a password request is valid. - * This function searches a previously create password request and - * returns the user. - * - * @param string $hash - * @return bool|SeedDMS_Core_User - */ - function checkPasswordRequest($hash) { /* {{{ */ - /* Get the password request from the database */ - $queryStr = "SELECT * FROM `tblUserPasswordRequest` WHERE `hash`=".$this->db->qstr($hash); - $resArr = $this->db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - if (count($resArr) != 1) - return false; - $resArr = $resArr[0]; - - return $this->getUser($resArr['userID']); - - } /* }}} */ - - /** - * Delete a password request - * - * @param string $hash - * @return bool - */ - function deletePasswordRequest($hash) { /* {{{ */ - /* Delete the request, so nobody can use it a second time */ - $queryStr = "DELETE FROM `tblUserPasswordRequest` WHERE `hash`=".$this->db->qstr($hash); - if (!$this->db->getResult($queryStr)) - return false; - return true; - } /* }}} */ - - /** - * Return a attribute definition by its id - * - * This function retrieves a attribute definitionr from the database by - * its id. - * - * @param integer $id internal id of attribute defintion - * @return bool|SeedDMS_Core_AttributeDefinition or false - */ - function getAttributeDefinition($id) { /* {{{ */ - if (!is_numeric($id) || $id < 1) - return false; - - $queryStr = "SELECT * FROM `tblAttributeDefinitions` WHERE `id` = " . (int) $id; - $resArr = $this->db->getResultArray($queryStr); - - if (is_bool($resArr) && $resArr == false) - return false; - if (count($resArr) != 1) - return null; - - $resArr = $resArr[0]; - - $attrdef = new SeedDMS_Core_AttributeDefinition($resArr["id"], $resArr["name"], $resArr["objtype"], $resArr["type"], $resArr["multiple"], $resArr["minvalues"], $resArr["maxvalues"], $resArr["valueset"], $resArr["regex"]); - $attrdef->setDMS($this); - return $attrdef; - } /* }}} */ - - /** - * Return a attribute definition by its name - * - * This function retrieves an attribute def. from the database by its name. - * - * @param string $name internal name of attribute def. - * @return SeedDMS_Core_AttributeDefinition|boolean instance of {@link SeedDMS_Core_AttributeDefinition} or false - */ - function getAttributeDefinitionByName($name) { /* {{{ */ - $name = trim($name); - if (!$name) return false; - - $queryStr = "SELECT * FROM `tblAttributeDefinitions` WHERE `name` = " . $this->db->qstr($name); - $resArr = $this->db->getResultArray($queryStr); - - if (is_bool($resArr) && $resArr == false) - return false; - if (count($resArr) != 1) - return null; - - $resArr = $resArr[0]; - - $attrdef = new SeedDMS_Core_AttributeDefinition($resArr["id"], $resArr["name"], $resArr["objtype"], $resArr["type"], $resArr["multiple"], $resArr["minvalues"], $resArr["maxvalues"], $resArr["valueset"], $resArr["regex"]); - $attrdef->setDMS($this); - return $attrdef; - } /* }}} */ - - /** - * Return list of all attributes definitions - * - * @param integer|array $objtype select those attributes defined for an object type - * @param integer|array $type select those attributes defined for a type - * @return bool|SeedDMS_Core_AttributeDefinition[] of instances of SeedDMS_Core_AttributeDefinition or false - * or false - */ - function getAllAttributeDefinitions($objtype=0, $type=0) { /* {{{ */ - $queryStr = "SELECT * FROM `tblAttributeDefinitions`"; - if($objtype || $type) { - $queryStr .= ' WHERE '; - if($objtype) { - if(is_array($objtype)) - $queryStr .= '`objtype` in (\''.implode("','", $objtype).'\')'; - else - $queryStr .= '`objtype`='.intval($objtype); - } - if($objtype && $type) { - $queryStr .= ' AND '; - } - if($type) { - if(is_array($type)) - $queryStr .= '`type` in (\''.implode("','", $type).'\')'; - else - $queryStr .= '`type`='.intval($type); - } - } - $queryStr .= ' ORDER BY `name`'; - $resArr = $this->db->getResultArray($queryStr); - - if (is_bool($resArr) && $resArr == false) - return false; - - /** @var SeedDMS_Core_AttributeDefinition[] $attrdefs */ - $attrdefs = array(); - - for ($i = 0; $i < count($resArr); $i++) { - $attrdef = new SeedDMS_Core_AttributeDefinition($resArr[$i]["id"], $resArr[$i]["name"], $resArr[$i]["objtype"], $resArr[$i]["type"], $resArr[$i]["multiple"], $resArr[$i]["minvalues"], $resArr[$i]["maxvalues"], $resArr[$i]["valueset"], $resArr[$i]["regex"]); - $attrdef->setDMS($this); - $attrdefs[$i] = $attrdef; - } - - return $attrdefs; - } /* }}} */ - - /** - * Add a new attribute definition - * - * @param string $name name of attribute - * @param $objtype - * @param string $type type of attribute - * @param bool|int $multiple set to 1 if attribute has multiple attributes - * @param integer $minvalues minimum number of values - * @param integer $maxvalues maximum number of values if multiple is set - * @param string $valueset list of allowed values (csv format) - * @param string $regex - * @return bool|SeedDMS_Core_User - */ - function addAttributeDefinition($name, $objtype, $type, $multiple=0, $minvalues=0, $maxvalues=1, $valueset='', $regex='') { /* {{{ */ - $name = trim($name); - if(!$name) - return false; - if (is_object($this->getAttributeDefinitionByName($name))) { - return false; - } - if($objtype < SeedDMS_Core_AttributeDefinition::objtype_all || $objtype > SeedDMS_Core_AttributeDefinition::objtype_documentcontent) - return false; - if(!$type) - return false; - if(trim($valueset)) { - $valuesetarr = array_map('trim', explode($valueset[0], substr($valueset, 1))); - $valueset = $valueset[0].implode($valueset[0], $valuesetarr); - } else { - $valueset = ''; - } - $queryStr = "INSERT INTO `tblAttributeDefinitions` (`name`, `objtype`, `type`, `multiple`, `minvalues`, `maxvalues`, `valueset`, `regex`) VALUES (".$this->db->qstr($name).", ".intval($objtype).", ".intval($type).", ".intval($multiple).", ".intval($minvalues).", ".intval($maxvalues).", ".$this->db->qstr($valueset).", ".$this->db->qstr($regex).")"; - $res = $this->db->getResult($queryStr); - if (!$res) - return false; - - return $this->getAttributeDefinition($this->db->getInsertID('tblAttributeDefinitions')); - } /* }}} */ - - /** - * Return list of all workflows - * - * @return SeedDMS_Core_Workflow[]|bool of instances of {@link SeedDMS_Core_Workflow} or false - */ - function getAllWorkflows() { /* {{{ */ - $queryStr = "SELECT * FROM `tblWorkflows` ORDER BY `name`"; - $resArr = $this->db->getResultArray($queryStr); - - if (is_bool($resArr) && $resArr == false) - return false; - - $queryStr = "SELECT * FROM `tblWorkflowStates` ORDER BY `name`"; - $ressArr = $this->db->getResultArray($queryStr); - - if (is_bool($ressArr) && $ressArr == false) - return false; - - for ($i = 0; $i < count($ressArr); $i++) { - $wkfstates[$ressArr[$i]["id"]] = new SeedDMS_Core_Workflow_State($ressArr[$i]["id"], $ressArr[$i]["name"], $ressArr[$i]["maxtime"], $ressArr[$i]["precondfunc"], $ressArr[$i]["documentstatus"]); - } - - /** @var SeedDMS_Core_Workflow[] $workflows */ - $workflows = array(); - for ($i = 0; $i < count($resArr); $i++) { - /** @noinspection PhpUndefinedVariableInspection */ - $workflow = new SeedDMS_Core_Workflow($resArr[$i]["id"], $resArr[$i]["name"], $wkfstates[$resArr[$i]["initstate"]]); - $workflow->setDMS($this); - $workflows[$i] = $workflow; - } - - return $workflows; - } /* }}} */ - - /** - * Return workflow by its Id - * - * @param integer $id internal id of workflow - * @return SeedDMS_Core_Workflow|bool of instances of {@link SeedDMS_Core_Workflow}, null if no workflow was found or false - */ - function getWorkflow($id) { /* {{{ */ - if (!is_numeric($id) || $id < 1) - return false; - - $queryStr = "SELECT * FROM `tblWorkflows` WHERE `id`=".intval($id); - $resArr = $this->db->getResultArray($queryStr); - - if (is_bool($resArr) && $resArr == false) - return false; - - if(!$resArr) - return null; - - $initstate = $this->getWorkflowState($resArr[0]['initstate']); - - $workflow = new SeedDMS_Core_Workflow($resArr[0]["id"], $resArr[0]["name"], $initstate); - $workflow->setDMS($this); - - return $workflow; - } /* }}} */ - - /** - * Return workflow by its name - * - * @param string $name name of workflow - * @return SeedDMS_Core_Workflow|bool of instances of {@link SeedDMS_Core_Workflow} or null if no workflow was found or false - */ - function getWorkflowByName($name) { /* {{{ */ - $name = trim($name); - if (!$name) return false; - - $queryStr = "SELECT * FROM `tblWorkflows` WHERE `name`=".$this->db->qstr($name); - $resArr = $this->db->getResultArray($queryStr); - - if (is_bool($resArr) && $resArr == false) - return false; - - if(!$resArr) - return null; - - $initstate = $this->getWorkflowState($resArr[0]['initstate']); - - $workflow = new SeedDMS_Core_Workflow($resArr[0]["id"], $resArr[0]["name"], $initstate); - $workflow->setDMS($this); - - return $workflow; - } /* }}} */ - - /** - * Add a new workflow - * - * @param string $name name of workflow - * @param SeedDMS_Core_Workflow_State $initstate initial state of workflow - * @return bool|SeedDMS_Core_Workflow - */ - function addWorkflow($name, $initstate) { /* {{{ */ - $db = $this->db; - $name = trim($name); - if(!$name) - return false; - if (is_object($this->getWorkflowByName($name))) { - return false; - } - $queryStr = "INSERT INTO `tblWorkflows` (`name`, `initstate`) VALUES (".$db->qstr($name).", ".$initstate->getID().")"; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - return $this->getWorkflow($db->getInsertID('tblWorkflows')); - } /* }}} */ - - /** - * Return a workflow state by its id - * - * This function retrieves a workflow state from the database by its id. - * - * @param integer $id internal id of workflow state - * @return bool|SeedDMS_Core_Workflow_State or false - */ - function getWorkflowState($id) { /* {{{ */ - if (!is_numeric($id) || $id < 1) - return false; - - $queryStr = "SELECT * FROM `tblWorkflowStates` WHERE `id` = " . (int) $id; - $resArr = $this->db->getResultArray($queryStr); - - if (is_bool($resArr) && $resArr == false) - return false; - - if (count($resArr) != 1) - return null; - - $resArr = $resArr[0]; - - $state = new SeedDMS_Core_Workflow_State($resArr["id"], $resArr["name"], $resArr["maxtime"], $resArr["precondfunc"], $resArr["documentstatus"]); - $state->setDMS($this); - return $state; - } /* }}} */ - - /** - * Return workflow state by its name - * - * @param string $name name of workflow state - * @return bool|SeedDMS_Core_Workflow_State or false - */ - function getWorkflowStateByName($name) { /* {{{ */ - $name = trim($name); - if (!$name) return false; - - $queryStr = "SELECT * FROM `tblWorkflowStates` WHERE `name`=".$this->db->qstr($name); - $resArr = $this->db->getResultArray($queryStr); - - if (is_bool($resArr) && $resArr == false) - return false; - - if(!$resArr) - return null; - - $resArr = $resArr[0]; - - $state = new SeedDMS_Core_Workflow_State($resArr["id"], $resArr["name"], $resArr["maxtime"], $resArr["precondfunc"], $resArr["documentstatus"]); - $state->setDMS($this); - - return $state; - } /* }}} */ - - /** - * Return list of all workflow states - * - * @return SeedDMS_Core_Workflow_State[]|bool of instances of {@link SeedDMS_Core_Workflow_State} or false - */ - function getAllWorkflowStates() { /* {{{ */ - $queryStr = "SELECT * FROM `tblWorkflowStates` ORDER BY `name`"; - $ressArr = $this->db->getResultArray($queryStr); - - if (is_bool($ressArr) && $ressArr == false) - return false; - - $wkfstates = array(); - for ($i = 0; $i < count($ressArr); $i++) { - $wkfstate = new SeedDMS_Core_Workflow_State($ressArr[$i]["id"], $ressArr[$i]["name"], $ressArr[$i]["maxtime"], $ressArr[$i]["precondfunc"], $ressArr[$i]["documentstatus"]); - $wkfstate->setDMS($this); - $wkfstates[$i] = $wkfstate; - } - - return $wkfstates; - } /* }}} */ - - /** - * Add new workflow state - * - * @param string $name name of workflow state - * @param integer $docstatus document status when this state is reached - * @return bool|SeedDMS_Core_Workflow_State - */ - function addWorkflowState($name, $docstatus) { /* {{{ */ - $db = $this->db; - $name = trim($name); - if(!$name) - return false; - if (is_object($this->getWorkflowStateByName($name))) { - return false; - } - $queryStr = "INSERT INTO `tblWorkflowStates` (`name`, `documentstatus`) VALUES (".$db->qstr($name).", ".(int) $docstatus.")"; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - return $this->getWorkflowState($db->getInsertID('tblWorkflowStates')); - } /* }}} */ - - /** - * Return a workflow action by its id - * - * This function retrieves a workflow action from the database by its id. - * - * @param integer $id internal id of workflow action - * @return SeedDMS_Core_Workflow_Action|bool instance of {@link SeedDMS_Core_Workflow_Action} or false - */ - function getWorkflowAction($id) { /* {{{ */ - if (!is_numeric($id) || $id < 1) - return false; - - $queryStr = "SELECT * FROM `tblWorkflowActions` WHERE `id` = " . (int) $id; - $resArr = $this->db->getResultArray($queryStr); - - if (is_bool($resArr) && $resArr == false) - return false; - - if (count($resArr) != 1) - return null; - - $resArr = $resArr[0]; - - $action = new SeedDMS_Core_Workflow_Action($resArr["id"], $resArr["name"]); - $action->setDMS($this); - return $action; - } /* }}} */ - - /** - * Return a workflow action by its name - * - * This function retrieves a workflow action from the database by its name. - * - * @param string $name name of workflow action - * @return SeedDMS_Core_Workflow_Action|bool instance of {@link SeedDMS_Core_Workflow_Action} or false - */ - function getWorkflowActionByName($name) { /* {{{ */ - $name = trim($name); - if (!$name) return false; - - $queryStr = "SELECT * FROM `tblWorkflowActions` WHERE `name` = " . $this->db->qstr($name); - $resArr = $this->db->getResultArray($queryStr); - - if (is_bool($resArr) && $resArr == false) - return false; - - if (count($resArr) != 1) - return null; - - $resArr = $resArr[0]; - - $action = new SeedDMS_Core_Workflow_Action($resArr["id"], $resArr["name"]); - $action->setDMS($this); - return $action; - } /* }}} */ - - /** - * Return list of workflow action - * - * @return SeedDMS_Core_Workflow_Action[]|bool list of instances of {@link SeedDMS_Core_Workflow_Action} or false - */ - function getAllWorkflowActions() { /* {{{ */ - $queryStr = "SELECT * FROM `tblWorkflowActions`"; - $resArr = $this->db->getResultArray($queryStr); - - if (is_bool($resArr) && $resArr == false) - return false; - - /** @var SeedDMS_Core_Workflow_Action[] $wkfactions */ - $wkfactions = array(); - for ($i = 0; $i < count($resArr); $i++) { - $action = new SeedDMS_Core_Workflow_Action($resArr[$i]["id"], $resArr[$i]["name"]); - $action->setDMS($this); - $wkfactions[$i] = $action; - } - - return $wkfactions; - } /* }}} */ - - /** - * Add new workflow action - * - * @param string $name name of workflow action - * @return SeedDMS_Core_Workflow_Action|bool - */ - function addWorkflowAction($name) { /* {{{ */ - $db = $this->db; - $name = trim($name); - if(!$name) - return false; - if (is_object($this->getWorkflowActionByName($name))) { - return false; - } - $queryStr = "INSERT INTO `tblWorkflowActions` (`name`) VALUES (".$db->qstr($name).")"; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - return $this->getWorkflowAction($db->getInsertID('tblWorkflowActions')); - } /* }}} */ - - /** - * Return a workflow transition by its id - * - * This function retrieves a workflow transition from the database by its id. - * - * @param integer $id internal id of workflow transition - * @return SeedDMS_Core_Workflow_Transition|bool instance of {@link SeedDMS_Core_Workflow_Transition} or false - */ - function getWorkflowTransition($id) { /* {{{ */ - if (!is_numeric($id)) - return false; - - $queryStr = "SELECT * FROM `tblWorkflowTransitions` WHERE `id` = " . (int) $id; - $resArr = $this->db->getResultArray($queryStr); - - if (is_bool($resArr) && $resArr == false) return false; - if (count($resArr) != 1) return false; - - $resArr = $resArr[0]; - - $transition = new SeedDMS_Core_Workflow_Transition($resArr["id"], $this->getWorkflow($resArr["workflow"]), $this->getWorkflowState($resArr["state"]), $this->getWorkflowAction($resArr["action"]), $this->getWorkflowState($resArr["nextstate"]), $resArr["maxtime"]); - $transition->setDMS($this); - return $transition; - } /* }}} */ - - /** - * Returns document content which is not linked to a document - * - * This method is for finding straying document content without - * a parent document. In normal operation this should not happen - * but little checks for database consistency and possible errors - * in the application may have left over document content though - * the document is gone already. - * - * @return array|bool - */ - function getUnlinkedDocumentContent() { /* {{{ */ - $queryStr = "SELECT * FROM `tblDocumentContent` WHERE `document` NOT IN (SELECT id FROM `tblDocuments`)"; - $resArr = $this->db->getResultArray($queryStr); - if ($resArr === false) - return false; - - $versions = array(); - foreach($resArr as $row) { - /** @var SeedDMS_Core_Document $document */ - $document = new $this->classnames['document']($row['document'], '', '', '', '', '', '', '', '', '', '', ''); - $document->setDMS($this); - $version = new $this->classnames['documentcontent']($row['id'], $document, $row['version'], $row['comment'], $row['date'], $row['createdBy'], $row['dir'], $row['orgFileName'], $row['fileType'], $row['mimeType'], $row['fileSize'], $row['checksum']); - $versions[] = $version; - } - return $versions; - - } /* }}} */ - - /** - * Returns document content which has no file size set - * - * This method is for finding document content without a file size - * set in the database. The file size of a document content was introduced - * in version 4.0.0 of SeedDMS for implementation of user quotas. - * - * @return SeedDMS_Core_Document[]|bool - */ - function getNoFileSizeDocumentContent() { /* {{{ */ - $queryStr = "SELECT * FROM `tblDocumentContent` WHERE `fileSize` = 0 OR `fileSize` is null"; - $resArr = $this->db->getResultArray($queryStr); - if ($resArr === false) - return false; - - /** @var SeedDMS_Core_Document[] $versions */ - $versions = array(); - foreach($resArr as $row) { - $document = $this->getDocument($row['document']); - /* getting the document can fail if it is outside the root folder - * and checkWithinRootDir is enabled. - */ - if($document) { - $version = new $this->classnames['documentcontent']($row['id'], $document, $row['version'], $row['comment'], $row['date'], $row['createdBy'], $row['dir'], $row['orgFileName'], $row['fileType'], $row['mimeType'], $row['fileSize'], $row['checksum'], $row['fileSize'], $row['checksum']); - $versions[] = $version; - } - } - return $versions; - - } /* }}} */ - - /** - * Returns document content which has no checksum set - * - * This method is for finding document content without a checksum - * set in the database. The checksum of a document content was introduced - * in version 4.0.0 of SeedDMS for finding duplicates. - * @return bool|SeedDMS_Core_Document[] - */ - function getNoChecksumDocumentContent() { /* {{{ */ - $queryStr = "SELECT * FROM `tblDocumentContent` WHERE `checksum` = '' OR `checksum` is null"; - $resArr = $this->db->getResultArray($queryStr); - if ($resArr === false) - return false; - - /** @var SeedDMS_Core_Document[] $versions */ - $versions = array(); - foreach($resArr as $row) { - $document = $this->getDocument($row['document']); - /* getting the document can fail if it is outside the root folder - * and checkWithinRootDir is enabled. - */ - if($document) { - $version = new $this->classnames['documentcontent']($row['id'], $document, $row['version'], $row['comment'], $row['date'], $row['createdBy'], $row['dir'], $row['orgFileName'], $row['fileType'], $row['mimeType'], $row['fileSize'], $row['checksum']); - $versions[] = $version; - } - } - return $versions; - - } /* }}} */ - - /** - * Returns document content which is duplicated - * - * This method is for finding document content which is available twice - * in the database. The checksum of a document content was introduced - * in version 4.0.0 of SeedDMS for finding duplicates. - * @return array|bool - */ - function getDuplicateDocumentContent() { /* {{{ */ - $queryStr = "SELECT a.*, b.`id` as dupid FROM `tblDocumentContent` a LEFT JOIN `tblDocumentContent` b ON a.`checksum`=b.`checksum` WHERE a.`id`!=b.`id` ORDER by a.`id` LIMIT 1000"; - $resArr = $this->db->getResultArray($queryStr); - if ($resArr === false) - return false; - - /** @var SeedDMS_Core_Document[] $versions */ - $versions = array(); - foreach($resArr as $row) { - $document = $this->getDocument($row['document']); - /* getting the document can fail if it is outside the root folder - * and checkWithinRootDir is enabled. - */ - if($document) { - $version = new $this->classnames['documentcontent']($row['id'], $document, $row['version'], $row['comment'], $row['date'], $row['createdBy'], $row['dir'], $row['orgFileName'], $row['fileType'], $row['mimeType'], $row['fileSize'], $row['checksum']); - if(!isset($versions[$row['dupid']])) { - $versions[$row['id']]['content'] = $version; - $versions[$row['id']]['duplicates'] = array(); - } else - $versions[$row['dupid']]['duplicates'][] = $version; - } - } - return $versions; - - } /* }}} */ - - /** - * Returns folders which contain documents with none unique sequence number - * - * This method is for finding folders with documents not having a - * unique sequence number. Those documents cannot propperly be sorted - * by sequence and changing their position is impossible if more than - * two documents with the same sequence number exists, e.g. - * doc 1: 3 - * doc 2: 5 - * doc 3: 5 - * doc 4: 5 - * doc 5: 7 - * If document 4 was to be moved between doc 1 and 2 it get sequence - * number 4 ((5+3)/2). - * But if document 4 was to be moved between doc 2 and 3 it will again - * have sequence number 5. - * - * @return array|bool - */ - function getDuplicateSequenceNo() { /* {{{ */ - $queryStr = "SELECT DISTINCT `folder` FROM (SELECT `folder`, `sequence`, count(*) c FROM `tblDocuments` GROUP BY `folder`, `sequence` HAVING c > 1) a"; - $resArr = $this->db->getResultArray($queryStr); - if ($resArr === false) - return false; - - $folders = array(); - foreach($resArr as $row) { - $folder = $this->getFolder($row['folder']); - if($folder) - $folders[] = $folder; - } - return $folders; - - } /* }}} */ - - /** - * Returns a list of reviews, approvals which are not linked - * to a user, group anymore - * - * This method is for finding reviews or approvals whose user - * or group was deleted and not just removed from the process. - * - * @param string $process - * @param string $usergroup - * @return array - */ - function getProcessWithoutUserGroup($process, $usergroup) { /* {{{ */ - switch($process) { - case 'review': - $queryStr = "SELECT a.*, b.`name` FROM `tblDocumentReviewers`"; - break; - case 'approval': - $queryStr = "SELECT a.*, b.`name` FROM `tblDocumentApprovers`"; - break; - } - /** @noinspection PhpUndefinedVariableInspection */ - $queryStr .= " a LEFT JOIN `tblDocuments` b ON a.`documentID`=b.`id` WHERE"; - switch($usergroup) { - case 'user': - $queryStr .= " a.`type`=0 and a.`required` not in (SELECT `id` FROM `tblUsers`) ORDER by b.`id`"; - break; - case 'group': - $queryStr .= " a.`type`=1 and a.`required` not in (SELECT `id` FROM `tblGroups`) ORDER by b.`id`"; - break; - } - return $this->db->getResultArray($queryStr); - } /* }}} */ - - /** - * Removes all reviews, approvals which are not linked - * to a user, group anymore - * - * This method is for removing all reviews or approvals whose user - * or group was deleted and not just removed from the process. - * If the optional parameter $id is set, only this user/group id is removed. - * @param string $process - * @param string $usergroup - * @param int $id - * @return array - */ - function removeProcessWithoutUserGroup($process, $usergroup, $id=0) { /* {{{ */ - /* Entries of tblDocumentReviewLog or tblDocumentApproveLog are deleted - * because of CASCADE ON - */ - switch($process) { - case 'review': - $queryStr = "DELETE FROM tblDocumentReviewers"; - break; - case 'approval': - $queryStr = "DELETE FROM tblDocumentApprovers"; - break; - } - /** @noinspection PhpUndefinedVariableInspection */ - $queryStr .= " WHERE"; - switch($usergroup) { - case 'user': - $queryStr .= " type=0 AND"; - if($id) - $queryStr .= " required=".((int) $id)." AND"; - $queryStr .= " required NOT IN (SELECT id FROM tblUsers)"; - break; - case 'group': - $queryStr .= " type=1 AND"; - if($id) - $queryStr .= " required=".((int) $id)." AND"; - $queryStr .= " required NOT IN (SELECT id FROM tblGroups)"; - break; - } - return $this->db->getResultArray($queryStr); - } /* }}} */ - - /** - * Returns statitical information - * - * This method returns all kind of statistical information like - * documents or used space per user, recent activity, etc. - * - * @param string $type type of statistic - * @return array|bool returns false if the sql statement fails, returns an empty - * array if no documents or folder where found, otherwise returns a non empty - * array with statistical data - */ - function getStatisticalData($type='') { /* {{{ */ - switch($type) { - case 'docsperuser': - $queryStr = "SELECT ".$this->db->concat(array('b.`fullName`', "' ('", 'b.`login`', "')'"))." AS `key`, count(`owner`) AS total FROM `tblDocuments` a LEFT JOIN `tblUsers` b ON a.`owner`=b.`id` GROUP BY `owner`, b.`fullName`"; - $resArr = $this->db->getResultArray($queryStr); - if(is_bool($resArr) && $resArr == false) - return false; - - return $resArr; - case 'foldersperuser': - $queryStr = "SELECT ".$this->db->concat(array('b.`fullName`', "' ('", 'b.`login`', "')'"))." AS `key`, count(`owner`) AS total FROM `tblFolders` a LEFT JOIN `tblUsers` b ON a.`owner`=b.`id` GROUP BY `owner`, b.`fullName`"; - $resArr = $this->db->getResultArray($queryStr); - if(is_bool($resArr) && $resArr == false) - return false; - - return $resArr; - case 'docspermimetype': - $queryStr = "SELECT b.`mimeType` AS `key`, count(`mimeType`) AS total FROM `tblDocuments` a LEFT JOIN `tblDocumentContent` b ON a.`id`=b.`document` GROUP BY b.`mimeType`"; - $resArr = $this->db->getResultArray($queryStr); - if(is_bool($resArr) && $resArr == false) - return false; - - return $resArr; - case 'docspercategory': - $queryStr = "SELECT b.`name` AS `key`, count(a.`categoryID`) AS total FROM `tblDocumentCategory` a LEFT JOIN `tblCategory` b ON a.`categoryID`=b.id GROUP BY a.`categoryID`, b.`name`"; - $resArr = $this->db->getResultArray($queryStr); - if(is_bool($resArr) && $resArr == false) - return false; - - return $resArr; - case 'docsperstatus': - /** @noinspection PhpUnusedLocalVariableInspection */ - $queryStr = "SELECT b.`status` AS `key`, count(b.`status`) AS total FROM (SELECT a.id, max(b.version), max(c.`statusLogID`) AS maxlog FROM `tblDocuments` a LEFT JOIN `tblDocumentStatus` b ON a.id=b.`documentID` LEFT JOIN `tblDocumentStatusLog` c ON b.`statusID`=c.`statusID` GROUP BY a.`id`, b.`version` ORDER BY a.`id`, b.`statusID`) a LEFT JOIN `tblDocumentStatusLog` b ON a.`maxlog`=b.`statusLogID` GROUP BY b.`status`"; - $queryStr = "SELECT b.`status` AS `key`, count(b.`status`) AS total FROM (SELECT a.`id`, max(c.`statusLogID`) AS maxlog FROM `tblDocuments` a LEFT JOIN `tblDocumentStatus` b ON a.id=b.`documentID` LEFT JOIN `tblDocumentStatusLog` c ON b.`statusID`=c.`statusID` GROUP BY a.`id` ORDER BY a.id) a LEFT JOIN `tblDocumentStatusLog` b ON a.maxlog=b.`statusLogID` GROUP BY b.`status`"; - $resArr = $this->db->getResultArray($queryStr); - if(is_bool($resArr) && $resArr == false) - return false; - - return $resArr; - case 'docspermonth': - $queryStr = "SELECT *, count(`key`) AS total FROM (SELECT ".$this->db->getDateExtract("date", '%Y-%m')." AS `key` FROM `tblDocuments`) a GROUP BY `key` ORDER BY `key`"; - $resArr = $this->db->getResultArray($queryStr); - if(is_bool($resArr) && $resArr == false) - return false; - - return $resArr; - case 'docsaccumulated': - $queryStr = "SELECT *, count(`key`) AS total FROM (SELECT ".$this->db->getDateExtract("date")." AS `key` FROM `tblDocuments`) a GROUP BY `key` ORDER BY `key`"; - $resArr = $this->db->getResultArray($queryStr); - if(is_bool($resArr) && $resArr == false) - return false; - - $sum = 0; - foreach($resArr as &$res) { - $sum += $res['total']; - /* auxially variable $key is need because sqlite returns - * a key '`key`' - */ - $res['key'] = mktime(12, 0, 0, substr($res['key'], 5, 2), substr($res['key'], 8, 2), substr($res['key'], 0, 4)) * 1000; - $res['total'] = $sum; - } - return $resArr; - case 'docstotal': - $queryStr = "SELECT count(*) AS total FROM `tblDocuments`"; - $resArr = $this->db->getResultArray($queryStr); - if(is_bool($resArr) && $resArr == false) - return false; - return (int) $resArr[0]['total']; - case 'folderstotal': - $queryStr = "SELECT count(*) AS total FROM `tblFolders`"; - $resArr = $this->db->getResultArray($queryStr); - if(is_bool($resArr) && $resArr == false) - return false; - return (int) $resArr[0]['total']; - case 'userstotal': - $queryStr = "SELECT count(*) AS total FROM `tblUsers`"; - $resArr = $this->db->getResultArray($queryStr); - if(is_bool($resArr) && $resArr == false) - return false; - return (int) $resArr[0]['total']; - case 'sizeperuser': - $queryStr = "SELECT ".$this->db->concat(array('c.`fullName`', "' ('", 'c.`login`', "')'"))." AS `key`, sum(`fileSize`) AS total FROM `tblDocuments` a LEFT JOIN `tblDocumentContent` b ON a.id=b.`document` LEFT JOIN `tblUsers` c ON a.`owner`=c.`id` GROUP BY a.`owner`, c.`fullName`"; - $resArr = $this->db->getResultArray($queryStr); - if(is_bool($resArr) && $resArr == false) - return false; - - return $resArr; - default: - return array(); - } - } /* }}} */ - - /** - * Returns changes with a period of time - * - * This method returns a list of all changes happened in the database - * within a given period of time. It currently just checks for - * entries in the database tables tblDocumentContent, tblDocumentFiles, - * and tblDocumentStatusLog - * - * @param string $startts - * @param string $endts - * @return array|bool - * @internal param string $start start date, defaults to start of current day - * @internal param string $end end date, defaults to end of start day - */ - function getTimeline($startts='', $endts='') { /* {{{ */ - if(!$startts) - $startts = mktime(0, 0, 0); - if(!$endts) - $endts = $startts+86400; - - /** @var SeedDMS_Core_Document[] $timeline */ - $timeline = array(); - - if(0) { - $queryStr = "SELECT DISTINCT `document` FROM `tblDocumentContent` WHERE `date` > ".$startts." AND `date` < ".$endts." UNION SELECT DISTINCT `document` FROM `tblDocumentFiles` WHERE `date` > ".$startts." AND `date` < ".$endts; - } else { - $startdate = date('Y-m-d H:i:s', $startts); - $enddate = date('Y-m-d H:i:s', $endts); - $queryStr = "SELECT DISTINCT `documentID` AS `document` FROM `tblDocumentStatus` LEFT JOIN `tblDocumentStatusLog` ON `tblDocumentStatus`.`statusId`=`tblDocumentStatusLog`.`statusID` WHERE `date` > ".$this->db->qstr($startdate)." AND `date` < ".$this->db->qstr($enddate)." UNION SELECT DISTINCT document FROM `tblDocumentFiles` WHERE `date` > ".$this->db->qstr($startdate)." AND `date` < ".$this->db->qstr($enddate)." UNION SELECT DISTINCT `document` FROM `tblDocumentFiles` WHERE `date` > ".$startts." AND `date` < ".$endts; - } - $resArr = $this->db->getResultArray($queryStr); - if ($resArr === false) - return false; - foreach($resArr as $rec) { - $document = $this->getDocument($rec['document']); - $timeline = array_merge($timeline, $document->getTimeline()); - } - return $timeline; - - } /* }}} */ - - /** - * Set a callback function - * - * The function passed in $func must be a callable and $name may not be empty. - * - * Setting a callback with the method will remove all priorly set callbacks. - * - * @param string $name internal name of callback - * @param mixed $func function name as expected by {call_user_method} - * @param mixed $params parameter passed as the first argument to the - * callback - * @return bool true if adding the callback succeeds otherwise false - */ - function setCallback($name, $func, $params=null) { /* {{{ */ - if($name && $func && is_callable($func)) { - $this->callbacks[$name] = array(array($func, $params)); - return true; - } else { - return false; - } - } /* }}} */ - - /** - * Add a callback function - * - * The function passed in $func must be a callable and $name may not be empty. - * - * @param string $name internal name of callback - * @param mixed $func function name as expected by {call_user_method} - * @param mixed $params parameter passed as the first argument to the - * callback - * @return bool true if adding the callback succeeds otherwise false - */ - function addCallback($name, $func, $params=null) { /* {{{ */ - if($name && $func && is_callable($func)) { - $this->callbacks[$name][] = array($func, $params); - return true; - } else { - return false; - } - } /* }}} */ - - /** - * Check if a callback with the given has been set - * - * @param string $name internal name of callback - * @return bool true a callback exists otherwise false - */ - function hasCallback($name) { /* {{{ */ - if($name && !empty($this->callbacks[$name])) - return true; - return false; - } /* }}} */ - -} diff --git a/SeedDMS_Core/Core/inc.ClassDecorator.php b/SeedDMS_Core/Core/inc.ClassDecorator.php deleted file mode 100644 index 9450d5fef..000000000 --- a/SeedDMS_Core/Core/inc.ClassDecorator.php +++ /dev/null @@ -1,42 +0,0 @@ - - * @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 - * @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; - } -} - diff --git a/SeedDMS_Core/Core/inc.ClassDocument.php b/SeedDMS_Core/Core/inc.ClassDocument.php deleted file mode 100644 index d9f11610d..000000000 --- a/SeedDMS_Core/Core/inc.ClassDocument.php +++ /dev/null @@ -1,6158 +0,0 @@ - - * @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe, - * 2010 Matteo Lucarelli, 2010 Uwe Steinmann - * @version Release: @package_version@ - */ - -/** - * The different states a document can be in - */ -/* - * Document is in review state. A document is in review state when - * it needs to be reviewed by a user or group. - */ -define("S_DRAFT_REV", 0); - -/* - * Document is in approval state. A document is in approval state when - * it needs to be approved by a user or group. - */ -define("S_DRAFT_APP", 1); - -/* - * Document is released. A document is in release state either when - * it needs no review or approval after uploaded or has been reviewed - * and/or approved. - */ -define("S_RELEASED", 2); - -/* - * Document is in workflow. A document is in workflow if a workflow - * has been started and has not reached a final state. - */ -define("S_IN_WORKFLOW", 3); - -/* - * Document was rejected. A document is in rejected state when - * the review failed or approval was not given. - */ -define("S_REJECTED", -1); - -/* - * Document is obsolete. A document can be obsoleted once it was - * released. - */ -define("S_OBSOLETE", -2); - -/* - * Document is expired. A document expires when the expiration date - * is reached - */ -define("S_EXPIRED", -3); - -/* - * Lowest and highest status that may be set - */ -define("S_LOWEST_STATUS", -3); -define("S_HIGHEST_STATUS", 3); - -/** - * The different states a workflow log can be in. This is used in - * all tables tblDocumentXXXLog - */ -/* - * workflow is in a neutral status waiting for action of user - */ -define("S_LOG_WAITING", 0); - -/* - * workflow has been successful ended. The document content has been - * approved, reviewed, aknowledged or revised - */ -define("S_LOG_ACCEPTED", 1); - -/* - * workflow has been unsuccessful ended. The document content has been - * rejected - */ -define("S_LOG_REJECTED", -1); - -/* - * user has been removed from workflow. This can be for different reasons - * 1. the user has been actively removed from the workflow, 2. the user has - * been deleted. - */ -define("S_LOG_USER_REMOVED", -2); - -/* - * workflow is sleeping until reactivation. The workflow has been set up - * but not started. This is only valid for the revision workflow, which - * may run over and over again. - */ -define("S_LOG_SLEEPING", -3); - -/** - * Class to represent a document in the document management system - * - * A document in SeedDMS is similar to a file in a regular file system. - * Documents may have any number of content elements - * ({@link SeedDMS_Core_DocumentContent}). These content elements are often - * called versions ordered in a timely manner. The most recent content element - * is the current version. - * - * Documents can be linked to other documents and can have attached files. - * The document content can be anything that can be stored in a regular - * file. - * - * @category DMS - * @package SeedDMS_Core - * @author Markus Westphal, Malcolm Cowe, Matteo Lucarelli, - * Uwe Steinmann - * @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe, - * 2010 Matteo Lucarelli, 2010-2022 Uwe Steinmann - * @version Release: @package_version@ - */ -class SeedDMS_Core_Document extends SeedDMS_Core_Object { /* {{{ */ - /** - * @var string name of document - */ - protected $_name; - - /** - * @var string comment of document - */ - protected $_comment; - - /** - * @var integer unix timestamp of creation date - */ - protected $_date; - - /** - * @var integer id of user who is the owner - */ - protected $_ownerID; - - /** - * @var integer id of folder this document belongs to - */ - protected $_folderID; - - /** - * @var integer timestamp of expiration date - */ - protected $_expires; - - /** - * @var boolean true if access is inherited, otherwise false - */ - protected $_inheritAccess; - - /** - * @var integer default access if access rights are not inherited - */ - protected $_defaultAccess; - - /** - * @var array list of notifications for users and groups - */ - protected $_readAccessList; - - /** - * @var array list of notifications for users and groups - */ - public $_notifyList; - - /** - * @var boolean true if document is locked, otherwise false - */ - protected $_locked; - - /** - * @var string list of keywords - */ - protected $_keywords; - - /** - * @var SeedDMS_Core_DocumentCategory[] list of categories - */ - protected $_categories; - - /** - * @var integer position of document within the parent folder - */ - protected $_sequence; - - /** - * @var SeedDMS_Core_DocumentContent temp. storage for latestcontent - */ - protected $_latestContent; - - /** - * @var array temp. storage for content - */ - protected $_content; - - /** - * @var SeedDMS_Core_Folder - */ - protected $_folder; - - /** @var array of SeedDMS_Core_UserAccess and SeedDMS_Core_GroupAccess */ - protected $_accessList; - - function __construct($id, $name, $comment, $date, $expires, $ownerID, $folderID, $inheritAccess, $defaultAccess, $locked, $keywords, $sequence) { /* {{{ */ - parent::__construct($id); - $this->_name = $name; - $this->_comment = $comment; - $this->_date = $date; - $this->_expires = $expires; - $this->_ownerID = $ownerID; - $this->_folderID = $folderID; - $this->_inheritAccess = $inheritAccess ? true : false; - $this->_defaultAccess = $defaultAccess; - $this->_locked = ($locked == null || $locked == '' ? -1 : $locked); - $this->_keywords = $keywords; - $this->_sequence = $sequence; - $this->_categories = array(); - $this->_notifyList = array(); - $this->_latestContent = null; - $this->_content = null; - /* Cache */ - $this->clearCache(); - } /* }}} */ - - /** - * Clear cache of this instance. - * - * The result of some expensive database actions (e.g. get all subfolders - * or documents) will be saved in a class variable to speed up consecutive - * calls of the same method. If a second call of the same method shall not - * use the cache, then it must be cleared. - * - */ - public function clearCache() { /* {{{ */ - $this->_parent = null; - $this->_owner = null; - $this->_documentLinks = null; - $this->_documentFiles = null; - $this->_content = null; - $this->_accessList = null; - $this->_notifyList = null; - } /* }}} */ - - /** - * Check if this object is of type 'document'. - * - * @param string $type type of object - */ - public function isType($type) { /* {{{ */ - return $type == 'document'; - } /* }}} */ - - /** - * Return an array of database fields which used for searching - * a term entered in the database search form - * - * @param SeedDMS_Core_DMS $dms - * @param array $searchin integer list of search scopes (2=name, 3=comment, - * 4=attributes) - * @return array list of database fields - */ - public static function getSearchFields($dms, $searchin) { /* {{{ */ - $db = $dms->getDB(); - - $searchFields = array(); - if (in_array(1, $searchin)) { - $searchFields[] = "`tblDocuments`.`keywords`"; - } - if (in_array(2, $searchin)) { - $searchFields[] = "`tblDocuments`.`name`"; - } - if (in_array(3, $searchin)) { - $searchFields[] = "`tblDocuments`.`comment`"; - $searchFields[] = "`tblDocumentContent`.`comment`"; - } - if (in_array(4, $searchin)) { - $searchFields[] = "`tblDocumentAttributes`.`value`"; - $searchFields[] = "`tblDocumentContentAttributes`.`value`"; - } - if (in_array(5, $searchin)) { - $searchFields[] = $db->castToText("`tblDocuments`.`id`"); - } - - return $searchFields; - } /* }}} */ - - /** - * Return a folder by its database record - * - * @param array $resArr array of folder data as returned by database - * @param SeedDMS_Core_DMS $dms - * @return SeedDMS_Core_Folder|bool instance of SeedDMS_Core_Folder if document exists - */ - public static function getInstanceByData($resArr, $dms) { /* {{{ */ - $classname = $dms->getClassname('document'); - /** @var SeedDMS_Core_Document $document */ - $document = new $classname($resArr["id"], $resArr["name"], $resArr["comment"], $resArr["date"], $resArr["expires"], $resArr["owner"], $resArr["folder"], $resArr["inheritAccess"], $resArr["defaultAccess"], $resArr['lock'], $resArr["keywords"], $resArr["sequence"]); - $document->setDMS($dms); - $document = $document->applyDecorators(); - return $document; - } /* }}} */ - - /** - * Return an document by its id - * - * @param integer $id id of document - * @param SeedDMS_Core_DMS $dms - * @return bool|SeedDMS_Core_Document instance of SeedDMS_Core_Document if document exists, null - * if document does not exist, false in case of error - */ - public static function getInstance($id, $dms) { /* {{{ */ - $db = $dms->getDB(); - -// $queryStr = "SELECT * FROM `tblDocuments` WHERE `id` = " . (int) $id; - $queryStr = "SELECT `tblDocuments`.*, `tblDocumentLocks`.`userID` as `lock` FROM `tblDocuments` LEFT JOIN `tblDocumentLocks` ON `tblDocuments`.`id` = `tblDocumentLocks`.`document` WHERE `id` = " . (int) $id; - if($dms->checkWithinRootDir) - $queryStr .= " AND `folderList` LIKE '%:".$dms->rootFolderID.":%'"; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && $resArr == false) - return false; - if (count($resArr) != 1) - return null; - $resArr = $resArr[0]; - - $resArr['lock'] = !$resArr['lock'] ? -1 : $resArr['lock']; - - return self::getInstanceByData($resArr, $dms); - } /* }}} */ - - /** - * Apply decorators - * - * @return object final object after all decorators has been applied - */ - function applyDecorators() { /* {{{ */ - if($decorators = $this->_dms->getDecorators('document')) { - $s = $this; - foreach($decorators as $decorator) { - $s = new $decorator($s); - } - return $s; - } else { - return $this; - } - } /* }}} */ - - /** - * Return the directory of the document in the file system relativ - * to the contentDir - * - * @return string directory of document - */ - function getDir() { /* {{{ */ - if($this->_dms->maxDirID) { - $dirid = (int) (($this->_id-1) / $this->_dms->maxDirID) + 1; - return $dirid."/".$this->_id."/"; - } else { - return $this->_id."/"; - } - } /* }}} */ - - /** - * Return the name of the document - * - * @return string name of document - */ - function getName() { return $this->_name; } - - /** - * Set the name of the document - * - * @param $newName string new name of document - * @return bool - */ - function setName($newName) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblDocuments` SET `name` = ".$db->qstr($newName)." WHERE `id` = ". $this->_id; - if (!$db->getResult($queryStr)) - return false; - - $this->_name = $newName; - return true; - } /* }}} */ - - /** - * Return the comment of the document - * - * @return string comment of document - */ - function getComment() { return $this->_comment; } - - /** - * Set the comment of the document - * - * @param $newComment string new comment of document - * @return bool - */ - function setComment($newComment) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblDocuments` SET `comment` = ".$db->qstr($newComment)." WHERE `id` = ". $this->_id; - if (!$db->getResult($queryStr)) - return false; - - $this->_comment = $newComment; - return true; - } /* }}} */ - - /** - * @return string - */ - function getKeywords() { return $this->_keywords; } - - /** - * @param string $newKeywords - * @return bool - */ - function setKeywords($newKeywords) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblDocuments` SET `keywords` = ".$db->qstr($newKeywords)." WHERE `id` = ". $this->_id; - if (!$db->getResult($queryStr)) - return false; - - $this->_keywords = $newKeywords; - return true; - } /* }}} */ - - /** - * Check if document has a given category - * - * @param SeedDMS_Core_DocumentCategory $cat - * @return bool true if document has category, otherwise false - */ - function hasCategory($cat) { /* {{{ */ - $db = $this->_dms->getDB(); - - if(!$cat) - return false; - - $queryStr = "SELECT * FROM `tblDocumentCategory` WHERE `documentID` = ".$this->_id." AND `categoryID`=".$cat->getId(); - $resArr = $db->getResultArray($queryStr); - if (!$resArr) - return false; - - return true; - } /* }}} */ - - /** - * Retrieve a list of all categories this document belongs to - * - * @return bool|SeedDMS_Core_DocumentCategory[] - */ - function getCategories() { /* {{{ */ - $db = $this->_dms->getDB(); - - if(!$this->_categories) { - $queryStr = "SELECT * FROM `tblCategory` WHERE `id` IN (SELECT `categoryID` FROM `tblDocumentCategory` WHERE `documentID` = ".$this->_id.")"; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - $this->_categories = []; - foreach ($resArr as $row) { - $cat = new SeedDMS_Core_DocumentCategory($row['id'], $row['name']); - $cat->setDMS($this->_dms); - $this->_categories[] = $cat; - } - } - return $this->_categories; - } /* }}} */ - - /** - * Set a list of categories for the document - * This function will delete currently assigned categories and sets new - * categories. - * - * @param SeedDMS_Core_DocumentCategory[] $newCategories list of category objects - * @return bool - */ - function setCategories($newCategories) { /* {{{ */ - $db = $this->_dms->getDB(); - - $db->startTransaction(); - $queryStr = "DELETE FROM `tblDocumentCategory` WHERE `documentID` = ". $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - foreach($newCategories as $cat) { - $queryStr = "INSERT INTO `tblDocumentCategory` (`categoryID`, `documentID`) VALUES (". $cat->getId() .", ". $this->_id .")"; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - } - - $db->commitTransaction(); - $this->_categories = $newCategories; - return true; - } /* }}} */ - - /** - * Add a list of categories to the document - * This function will add a list of new categories to the document. - * - * @param array $newCategories list of category objects - */ - function addCategories($newCategories) { /* {{{ */ - $db = $this->_dms->getDB(); - - if(!$this->_categories) - $this->getCategories(); - - $catids = array(); - foreach($this->_categories as $cat) - $catids[] = $cat->getID(); - - $db->startTransaction(); - $ncat = array(); // Array containing actually added new categories - foreach($newCategories as $cat) { - if(!in_array($cat->getID(), $catids)) { - $queryStr = "INSERT INTO `tblDocumentCategory` (`categoryID`, `documentID`) VALUES (". $cat->getId() .", ". $this->_id .")"; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - $ncat[] = $cat; - } - } - $db->commitTransaction(); - $this->_categories = array_merge($this->_categories, $ncat); - return true; - } /* }}} */ - - /** - * Remove a list of categories from the document - * This function will remove a list of assigned categories to the document. - * - * @param array $newCategories list of category objects - */ - function removeCategories($categories) { /* {{{ */ - $db = $this->_dms->getDB(); - - $catids = array(); - foreach($categories as $cat) - $catids[] = $cat->getID(); - - $queryStr = "DELETE FROM `tblDocumentCategory` WHERE `documentID` = ". $this->_id ." AND `categoryID` IN (".implode(',', $catids).")"; - if (!$db->getResult($queryStr)) { - return false; - } - - $this->_categories = null; - return true; - } /* }}} */ - - /** - * Return creation date of the document - * - * @return integer unix timestamp of creation date - */ - function getDate() { /* {{{ */ - return $this->_date; - } /* }}} */ - - /** - * Set creation date of the document - * - * @param integer $date timestamp of creation date. If false then set it - * to the current timestamp - * @return boolean true on success - */ - function setDate($date) { /* {{{ */ - $db = $this->_dms->getDB(); - - if(!$date) - $date = time(); - else { - if(!is_numeric($date)) - return false; - } - - $queryStr = "UPDATE `tblDocuments` SET `date` = " . (int) $date . " WHERE `id` = ". $this->_id; - if (!$db->getResult($queryStr)) - return false; - $this->_date = $date; - return true; - } /* }}} */ - - /** - * Check, if this document is below of a given folder - * - * @param object $folder parent folder - * @return boolean true if folder is a subfolder - */ - function isDescendant($folder) { /* {{{ */ - /* First check if the parent folder is folder looking for */ - if ($this->getFolder()->getID() == $folder->getID()) - return true; - /* Second, check for the parent folder of this document to be - * below the given folder - */ - if($this->getFolder()->isDescendant($folder)) - return true; - return false; - } /* }}} */ - - /** - * Return the parent folder of the document - * - * @return SeedDMS_Core_Folder parent folder - */ - function getParent() { /* {{{ */ - return $this->getFolder(); - } /* }}} */ - - function getFolder() { /* {{{ */ - if (!isset($this->_folder)) - $this->_folder = $this->_dms->getFolder($this->_folderID); - return $this->_folder; - } /* }}} */ - - /** - * Set folder of a document - * - * This function basically moves a document from a folder to another - * folder. - * - * @param SeedDMS_Core_Folder $newFolder - * @return boolean false in case of an error, otherwise true - */ - function setParent($newFolder) { /* {{{ */ - return $this->setFolder($newFolder); - } /* }}} */ - - /** - * Set folder of a document - * - * This function basically moves a document from a folder to another - * folder. - * - * @param SeedDMS_Core_Folder $newFolder - * @return boolean false in case of an error, otherwise true - */ - function setFolder($newFolder) { /* {{{ */ - $db = $this->_dms->getDB(); - - if(!$newFolder) - return false; - - if(!$newFolder->isType('folder')) - return false; - - $queryStr = "UPDATE `tblDocuments` SET `folder` = " . $newFolder->getID() . " WHERE `id` = ". $this->_id; - if (!$db->getResult($queryStr)) - return false; - $this->_folderID = $newFolder->getID(); - /** @noinspection PhpUndefinedFieldInspection */ - $this->_folder = $newFolder; - - // Make sure that the folder search path is also updated. - $path = $newFolder->getPath(); - $flist = ""; - /** @var SeedDMS_Core_Folder[] $path */ - foreach ($path as $f) { - $flist .= ":".$f->getID(); - } - if (strlen($flist)>1) { - $flist .= ":"; - } - $queryStr = "UPDATE `tblDocuments` SET `folderList` = '" . $flist . "' WHERE `id` = ". $this->_id; - if (!$db->getResult($queryStr)) - return false; - - return true; - } /* }}} */ - - /** - * Return owner of document - * - * @return SeedDMS_Core_User owner of document as an instance of {@link SeedDMS_Core_User} - */ - function getOwner() { /* {{{ */ - if (!isset($this->_owner)) - $this->_owner = $this->_dms->getUser($this->_ownerID); - return $this->_owner; - } /* }}} */ - - /** - * Set owner of a document - * - * @param SeedDMS_Core_User $newOwner new owner - * @return boolean true if successful otherwise false - */ - function setOwner($newOwner) { /* {{{ */ - $db = $this->_dms->getDB(); - - if(!$newOwner) - return false; - - if(!$newOwner->isType('user')) - return false; - - $queryStr = "UPDATE `tblDocuments` set `owner` = " . $newOwner->getID() . " WHERE `id` = " . $this->_id; - if (!$db->getResult($queryStr)) - return false; - - $this->_ownerID = $newOwner->getID(); - /** @noinspection PhpUndefinedFieldInspection */ - $this->_owner = $newOwner; - return true; - } /* }}} */ - - /** - * @return bool|int - */ - function getDefaultAccess() { /* {{{ */ - if ($this->inheritsAccess()) { - $res = $this->getFolder(); - if (!$res) return false; - return $this->_folder->getDefaultAccess(); - } - return $this->_defaultAccess; - } /* }}} */ - - /** - * Set default access mode - * - * This method sets the default access mode and also removes all notifiers which - * will not have read access anymore. Setting a default access mode will only - * have an immediate effect if the access rights are not inherited, otherwise - * it just updates the database record of the document and once the - * inheritance is turn off the default access mode will take effect. - * - * @param integer $mode access mode - * @param bool|string $noclean set to true if notifier list shall not be clean up - * - * @return bool - */ - function setDefaultAccess($mode, $noclean=false) { /* {{{ */ - $db = $this->_dms->getDB(); - - if($mode < M_LOWEST_RIGHT || $mode > M_HIGHEST_RIGHT) - return false; - - $queryStr = "UPDATE `tblDocuments` set `defaultAccess` = " . (int) $mode . " WHERE `id` = " . $this->_id; - if (!$db->getResult($queryStr)) - return false; - - $this->_defaultAccess = $mode; - - /* Setting the default access mode does not have any effect if access - * is still inherited. In that case there is no need to clean the - * notification list. - */ - if(!$noclean && !$this->_inheritAccess) - $this->cleanNotifyList(); - - return true; - } /* }}} */ - - /** - * @return bool - */ - function inheritsAccess() { return $this->_inheritAccess; } - - /** - * This is supposed to be a replacement for inheritsAccess() - * - * @return bool - */ - function getInheritAccess() { return $this->_inheritAccess; } - - /** - * Set inherited access mode - * Setting inherited access mode will set or unset the internal flag which - * controls if the access mode is inherited from the parent folder or not. - * It will not modify the - * access control list for the current object. It will remove all - * notifications of users which do not even have read access anymore - * after setting or unsetting inherited access. - * - * @param boolean $inheritAccess set to true for setting and false for - * unsetting inherited access mode - * @param boolean $noclean set to true if notifier list shall not be clean up - * @return boolean true if operation was successful otherwise false - */ - function setInheritAccess($inheritAccess, $noclean=false) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblDocuments` SET `inheritAccess` = " . ($inheritAccess ? "1" : "0") . " WHERE `id` = " . $this->_id; - if (!$db->getResult($queryStr)) - return false; - - $this->_inheritAccess = ($inheritAccess ? true : false); - - if(!$noclean) - $this->cleanNotifyList(); - - return true; - } /* }}} */ - - /** - * Check if document expires - * - * @return boolean true if document has expiration date set, otherwise false - */ - function expires() { /* {{{ */ - if (intval($this->_expires) == 0) - return false; - else - return true; - } /* }}} */ - - /** - * Get expiration time of document - * - * @return integer/boolean expiration date as unix timestamp or false - */ - function getExpires() { /* {{{ */ - if (intval($this->_expires) == 0) - return false; - else - return $this->_expires; - } /* }}} */ - - /** - * Set expiration date as unix timestamp - * - * @param integer $expires unix timestamp of expiration date - * @return bool - */ - function setExpires($expires) { /* {{{ */ - $db = $this->_dms->getDB(); - - $expires = (!$expires) ? 0 : $expires; - - if ($expires == $this->_expires) { - // No change is necessary. - return true; - } - - $queryStr = "UPDATE `tblDocuments` SET `expires` = " . (int) $expires . " WHERE `id` = " . $this->_id; - if (!$db->getResult($queryStr)) - return false; - - $this->_expires = $expires; - return true; - } /* }}} */ - - /** - * Check if the document has expired - * - * The method expects to database field 'expired' to hold the timestamp - * of the start of day at which end the document expires. The document will - * expire if that day is over. Hence, a document will *not* - * be expired during the day of expiration but at the end of that day - * - * @return boolean true if document has expired otherwise false - */ - function hasExpired() { /* {{{ */ - if (intval($this->_expires) == 0) return false; - if (time()>=$this->_expires+24*60*60) return true; - return false; - } /* }}} */ - - /** - * Check if the document has expired and set the status accordingly - * It will also recalculate the status if the current status is - * set to S_EXPIRED but the document isn't actually expired. - * The method will update the document status log database table - * if needed. - * FIXME: some left over reviewers/approvers are in the way if - * no workflow is set and traditional workflow mode is on. In that - * case the status is set to S_DRAFT_REV or S_DRAFT_APP - * - * @return boolean true if status has changed - */ - function verifyLastestContentExpriry(){ /* {{{ */ - $lc=$this->getLatestContent(); - if($lc) { - $st=$lc->getStatus(); - - if (($st["status"]==S_DRAFT_REV || $st["status"]==S_DRAFT_APP || $st["status"]==S_IN_WORKFLOW || $st["status"]==S_RELEASED) && $this->hasExpired()){ - return $lc->setStatus(S_EXPIRED,"", $this->getOwner()); - } - elseif ($st["status"]==S_EXPIRED && !$this->hasExpired() ){ - $lc->verifyStatus(true, $this->getOwner()); - return true; - } - } - return false; - } /* }}} */ - - /** - * Check if document is locked - * - * @return boolean true if locked otherwise false - */ - function isLocked() { return $this->_locked != -1; } - - /** - * Lock or unlock document - * - * @param SeedDMS_Core_User|bool $falseOrUser user object for locking or false for unlocking - * @return boolean true if operation was successful otherwise false - */ - function setLocked($falseOrUser) { /* {{{ */ - $db = $this->_dms->getDB(); - - $lockUserID = -1; - if (is_bool($falseOrUser) && !$falseOrUser) { - $queryStr = "DELETE FROM `tblDocumentLocks` WHERE `document` = ".$this->_id; - } - else if (is_object($falseOrUser)) { - $queryStr = "INSERT INTO `tblDocumentLocks` (`document`, `userID`) VALUES (".$this->_id.", ".$falseOrUser->getID().")"; - $lockUserID = $falseOrUser->getID(); - } - else { - return false; - } - if (!$db->getResult($queryStr)) { - return false; - } - unset($this->_lockingUser); - $this->_locked = $lockUserID; - return true; - } /* }}} */ - - /** - * Get the user currently locking the document - * - * @return SeedDMS_Core_User|bool user have a lock - */ - function getLockingUser() { /* {{{ */ - if (!$this->isLocked()) - return false; - - if (!isset($this->_lockingUser)) - $this->_lockingUser = $this->_dms->getUser($this->_locked); - return $this->_lockingUser; - } /* }}} */ - - /** - * @return float - */ - function getSequence() { return $this->_sequence; } - - /** - * @param float $seq - * @return bool - */ - function setSequence($seq) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblDocuments` SET `sequence` = " . $seq . " WHERE `id` = " . $this->_id; - if (!$db->getResult($queryStr)) - return false; - - $this->_sequence = $seq; - return true; - } /* }}} */ - - /** - * Delete all entries for this document from the access control list - * - * @param boolean $noclean set to true if notifier list shall not be clean up - * @return boolean true if operation was successful otherwise false - */ - function clearAccessList($noclean=false) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "DELETE FROM `tblACLs` WHERE `targetType` = " . T_DOCUMENT . " AND `target` = " . $this->_id; - if (!$db->getResult($queryStr)) - return false; - - unset($this->_accessList); - - if(!$noclean) - $this->cleanNotifyList(); - - return true; - } /* }}} */ - - /** - * Returns a list of access privileges - * - * If the document inherits the access privileges from the parent folder - * those will be returned. - * $mode and $op can be set to restrict the list of returned access - * privileges. If $mode is set to M_ANY no restriction will apply - * regardless of the value of $op. The returned array contains a list - * of {@link SeedDMS_Core_UserAccess} and - * {@link SeedDMS_Core_GroupAccess} objects. Even if the document - * has no access list the returned array contains the two elements - * 'users' and 'groups' which are than empty. The methode returns false - * if the function fails. - * - * @param int $mode access mode (defaults to M_ANY) - * @param int|string $op operation (defaults to O_EQ) - * @return bool|array - */ - function getAccessList($mode = M_ANY, $op = O_EQ) { /* {{{ */ - $db = $this->_dms->getDB(); - - if ($this->inheritsAccess()) { - $res = $this->getFolder(); - if (!$res) return false; - return $this->_folder->getAccessList($mode, $op); - } - - if (!isset($this->_accessList[$mode])) { - if ($op!=O_GTEQ && $op!=O_LTEQ && $op!=O_EQ) { - return false; - } - $modeStr = ""; - if ($mode!=M_ANY) { - $modeStr = " AND `mode`".$op.(int)$mode; - } - $queryStr = "SELECT * FROM `tblACLs` WHERE `targetType` = ".T_DOCUMENT. - " AND `target` = " . $this->_id . $modeStr . " ORDER BY `targetType`"; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - $this->_accessList[$mode] = array("groups" => array(), "users" => array()); - foreach ($resArr as $row) { - if ($row["userID"] != -1) - array_push($this->_accessList[$mode]["users"], new SeedDMS_Core_UserAccess($this->_dms->getUser($row["userID"]), (int) $row["mode"])); - else //if ($row["groupID"] != -1) - array_push($this->_accessList[$mode]["groups"], new SeedDMS_Core_GroupAccess($this->_dms->getGroup($row["groupID"]), (int) $row["mode"])); - } - } - - return $this->_accessList[$mode]; - } /* }}} */ - - /** - * Add access right to folder - * This function may change in the future. Instead of passing a flag - * and a user/group id a user or group object will be expected. - * Starting with version 5.1.25 this method will first check if there - * is already an access right for the user/group. - * - * @param integer $mode access mode - * @param integer $userOrGroupID id of user or group - * @param integer $isUser set to 1 if $userOrGroupID is the id of a - * user - * @return bool - */ - function addAccess($mode, $userOrGroupID, $isUser) { /* {{{ */ - $db = $this->_dms->getDB(); - - if($mode < M_NONE || $mode > M_ALL) - return false; - - $userOrGroup = ($isUser) ? "`userID`" : "`groupID`"; - - /* Adding a second access right will return false */ - $queryStr = "SELECT * FROM `tblACLs` WHERE `targetType` = ".T_DOCUMENT. - " AND `target` = " . $this->_id . " AND ". $userOrGroup . " = ".$userOrGroupID; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) || $resArr) - return false; - - $queryStr = "INSERT INTO `tblACLs` (`target`, `targetType`, ".$userOrGroup.", `mode`) VALUES - (".$this->_id.", ".T_DOCUMENT.", " . (int) $userOrGroupID . ", " .(int) $mode. ")"; - if (!$db->getResult($queryStr)) - return false; - - unset($this->_accessList); - - // Update the notify list, if necessary. - if ($mode == M_NONE) { - $this->removeNotify($userOrGroupID, $isUser); - } - - return true; - } /* }}} */ - - /** - * Change access right of document - * This function may change in the future. Instead of passing the a flag - * and a user/group id a user or group object will be expected. - * - * @param integer $newMode access mode - * @param integer $userOrGroupID id of user or group - * @param integer $isUser set to 1 if $userOrGroupID is the id of a - * user - * @return bool - */ - function changeAccess($newMode, $userOrGroupID, $isUser) { /* {{{ */ - $db = $this->_dms->getDB(); - - $userOrGroup = ($isUser) ? "`userID`" : "`groupID`"; - - $queryStr = "UPDATE `tblACLs` SET `mode` = " . (int) $newMode . " WHERE `targetType` = ".T_DOCUMENT." AND `target` = " . $this->_id . " AND " . $userOrGroup . " = " . (int) $userOrGroupID; - if (!$db->getResult($queryStr)) - return false; - - unset($this->_accessList); - - // Update the notify list, if necessary. - if ($newMode == M_NONE) { - $this->removeNotify($userOrGroupID, $isUser); - } - - return true; - } /* }}} */ - - /** - * Remove access rights for a user or group - * - * @param integer $userOrGroupID ID of user or group - * @param boolean $isUser true if $userOrGroupID is a user id, false if it - * is a group id. - * @return boolean true on success, otherwise false - */ - function removeAccess($userOrGroupID, $isUser) { /* {{{ */ - $db = $this->_dms->getDB(); - - $userOrGroup = ($isUser) ? "`userID`" : "`groupID`"; - - $queryStr = "DELETE FROM `tblACLs` WHERE `targetType` = ".T_DOCUMENT." AND `target` = ".$this->_id." AND ".$userOrGroup." = " . (int) $userOrGroupID; - if (!$db->getResult($queryStr)) - return false; - - unset($this->_accessList); - - // Update the notify list, if the user looses access rights. - $mode = ($isUser ? $this->getAccessMode($this->_dms->getUser($userOrGroupID)) : $this->getGroupAccessMode($this->_dms->getGroup($userOrGroupID))); - if ($mode == M_NONE) { - $this->removeNotify($userOrGroupID, $isUser); - } - - return true; - } /* }}} */ - - /** - * Returns the greatest access privilege for a given user - * - * This function returns the access mode for a given user. An administrator - * and the owner of the folder has unrestricted access. A guest user has - * read only access or no access if access rights are further limited - * by access control lists. All other users have access rights according - * to the access control lists or the default access. This function will - * recursive check for access rights of parent folders if access rights - * are inherited. - * - * The function searches the access control list for entries of - * user $user. If it finds more than one entry it will return the - * one allowing the greatest privileges, but user rights will always - * precede group rights. If there is no entry in the - * access control list, it will return the default access mode. - * The function takes inherited access rights into account. - * For a list of possible access rights see @file inc.AccessUtils.php - * - * Having access on a document does not necessarily mean the document - * content is accessible too. Accessing the content is checked by - * {@link SeedDMS_Core_DocumentContent::getAccessMode()} which calls - * a callback function defined by the application. If the callback - * function is not set, access on the content is always granted. - * - * Before checking the access in the method itself a callback 'onCheckAccessDocument' - * is called. If it returns a value > 0, then this will be returned by this - * method without any further checks. The optional paramater $context - * will be passed as a third parameter to the callback. It contains - * the operation for which the access mode is retrieved. It is for example - * set to 'removeDocument' if the access mode is used to check for sufficient - * permission on deleting a document. - * - * @param $user object instance of class SeedDMS_Core_User - * @param string $context context in which the access mode is requested - * @return integer access mode - */ - function getAccessMode($user, $context='') { /* {{{ */ - if(!$user) - return M_NONE; - - /* Check if 'onCheckAccessDocument' callback is set */ - if(isset($this->_dms->callbacks['onCheckAccessDocument'])) { - foreach($this->_dms->callbacks['onCheckAccessDocument'] as $callback) { - if(($ret = call_user_func($callback[0], $callback[1], $this, $user, $context)) > 0) { - return $ret; - } - } - } - - /* Administrators have unrestricted access */ - if ($user->isAdmin()) return M_ALL; - - /* The owner of the document has unrestricted access */ - if ($user->getID() == $this->_ownerID) return M_ALL; - - /* Check ACLs */ - $accessList = $this->getAccessList(); - if (!$accessList) return false; - - /** @var SeedDMS_Core_UserAccess $userAccess */ - foreach ($accessList["users"] as $userAccess) { - if ($userAccess->getUserID() == $user->getID()) { - $mode = $userAccess->getMode(); - if ($user->isGuest()) { - if ($mode >= M_READ) $mode = M_READ; - } - return $mode; - } - } - - /* Get the highest right defined by a group */ - if($accessList['groups']) { - $mode = 0; - /** @var SeedDMS_Core_GroupAccess $groupAccess */ - foreach ($accessList["groups"] as $groupAccess) { - if ($user->isMemberOfGroup($groupAccess->getGroup())) { - if ($groupAccess->getMode() > $mode) - $mode = $groupAccess->getMode(); - } - } - if($mode) { - if ($user->isGuest()) { - if ($mode >= M_READ) $mode = M_READ; - } - return $mode; - } - } - - $mode = $this->getDefaultAccess(); - if ($user->isGuest()) { - if ($mode >= M_READ) $mode = M_READ; - } - return $mode; - } /* }}} */ - - /** - * Returns the greatest access privilege for a given group - * - * This function searches the access control list for entries of - * group $group. If it finds more than one entry it will return the - * one allowing the greatest privileges. If there is no entry in the - * access control list, it will return the default access mode. - * The function takes inherited access rights into account. - * For a list of possible access rights see @file inc.AccessUtils.php - * - * @param SeedDMS_Core_Group $group object instance of class SeedDMS_Core_Group - * @return integer access mode - */ - function getGroupAccessMode($group) { /* {{{ */ - $highestPrivileged = M_NONE; - - //ACLs durchforsten - $foundInACL = false; - $accessList = $this->getAccessList(); - if (!$accessList) - return false; - - /** @var SeedDMS_Core_GroupAccess $groupAccess */ - foreach ($accessList["groups"] as $groupAccess) { - if ($groupAccess->getGroupID() == $group->getID()) { - $foundInACL = true; - if ($groupAccess->getMode() > $highestPrivileged) - $highestPrivileged = $groupAccess->getMode(); - if ($highestPrivileged == M_ALL) // max access right -> skip the rest - return $highestPrivileged; - } - } - - if ($foundInACL) - return $highestPrivileged; - - //Standard-Berechtigung verwenden - return $this->getDefaultAccess(); - } /* }}} */ - - /** - * Returns a list of all notifications - * - * The returned list has two elements called 'users' and 'groups'. Each one - * is an array itself countaining objects of class SeedDMS_Core_User and - * SeedDMS_Core_Group. - * - * @param integer $type type of notification (not yet used) - * @param bool $incdisabled set to true if disabled user shall be included - * @return array|bool - */ - function getNotifyList($type=0, $incdisabled=false) { /* {{{ */ - if (empty($this->_notifyList)) { - $db = $this->_dms->getDB(); - - $queryStr ="SELECT * FROM `tblNotify` WHERE `targetType` = " . T_DOCUMENT . " AND `target` = " . $this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && $resArr == false) - return false; - - $this->_notifyList = array("groups" => array(), "users" => array()); - foreach ($resArr as $row) - { - if ($row["userID"] != -1) { - $u = $this->_dms->getUser($row["userID"]); - if($u && (!$u->isDisabled() || $incdisabled)) - array_push($this->_notifyList["users"], $u); - } else { //if ($row["groupID"] != -1) - $g = $this->_dms->getGroup($row["groupID"]); - if($g) - array_push($this->_notifyList["groups"], $g); - } - } - } - return $this->_notifyList; - } /* }}} */ - - /** - * Make sure only users/groups with read access are in the notify list - * - */ - function cleanNotifyList() { /* {{{ */ - // If any of the notification subscribers no longer have read access, - // remove their subscription. - if (empty($this->_notifyList)) - $this->getNotifyList(); - - /* Make a copy of both notifier lists because removeNotify will empty - * $this->_notifyList and the second foreach will not work anymore. - */ - /** @var SeedDMS_Core_User[] $nusers */ - $nusers = $this->_notifyList["users"]; - /** @var SeedDMS_Core_Group[] $ngroups */ - $ngroups = $this->_notifyList["groups"]; - foreach ($nusers as $u) { - if ($this->getAccessMode($u) < M_READ) { - $this->removeNotify($u->getID(), true); - } - } - foreach ($ngroups as $g) { - if ($this->getGroupAccessMode($g) < M_READ) { - $this->removeNotify($g->getID(), false); - } - } - } /* }}} */ - - /** - * Add a user/group to the notification list - * This function does not check if the currently logged in user - * is allowed to add a notification. This must be checked by the calling - * application. - * - * @param $userOrGroupID integer id of user or group to add - * @param $isUser integer 1 if $userOrGroupID is a user, - * 0 if $userOrGroupID is a group - * @return integer 0: Update successful. - * -1: Invalid User/Group ID. - * -2: Target User / Group does not have read access. - * -3: User is already subscribed. - * -4: Database / internal error. - */ - function addNotify($userOrGroupID, $isUser) { /* {{{ */ - $db = $this->_dms->getDB(); - - $userOrGroup = ($isUser ? "`userID`" : "`groupID`"); - - /* Verify that user / group exists. */ - $obj = ($isUser ? $this->_dms->getUser($userOrGroupID) : $this->_dms->getGroup($userOrGroupID)); - if (!is_object($obj)) { - return -1; - } - - /* Verify that the requesting user has permission to add the target to - * the notification system. - */ - /* - * The calling application should enforce the policy on who is allowed - * to add someone to the notification system. If is shall remain here - * the currently logged in user should be passed to this function - * - GLOBAL $user; - if ($user->isGuest()) { - return -2; - } - if (!$user->isAdmin()) { - if ($isUser) { - if ($user->getID() != $obj->getID()) { - return -2; - } - } - else { - if (!$obj->isMember($user)) { - return -2; - } - } - } - */ - - /* Verify that target user / group has read access to the document. */ - if ($isUser) { - // Users are straightforward to check. - if ($this->getAccessMode($obj) < M_READ) { - return -2; - } - } - else { - // Groups are a little more complex. - if ($this->getDefaultAccess() >= M_READ) { - // If the default access is at least READ-ONLY, then just make sure - // that the current group has not been explicitly excluded. - $acl = $this->getAccessList(M_NONE, O_EQ); - $found = false; - /** @var SeedDMS_Core_GroupAccess $group */ - foreach ($acl["groups"] as $group) { - if ($group->getGroupID() == $userOrGroupID) { - $found = true; - break; - } - } - if ($found) { - return -2; - } - } - else { - // The default access is restricted. Make sure that the group has - // been explicitly allocated access to the document. - $acl = $this->getAccessList(M_READ, O_GTEQ); - if (is_bool($acl)) { - return -4; - } - $found = false; - /** @var SeedDMS_Core_GroupAccess $group */ - foreach ($acl["groups"] as $group) { - if ($group->getGroupID() == $userOrGroupID) { - $found = true; - break; - } - } - if (!$found) { - return -2; - } - } - } - /* Check to see if user/group is already on the list. */ - $queryStr = "SELECT * FROM `tblNotify` WHERE `tblNotify`.`target` = '".$this->_id."' ". - "AND `tblNotify`.`targetType` = '".T_DOCUMENT."' ". - "AND `tblNotify`.".$userOrGroup." = '".(int) $userOrGroupID."'"; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr)) { - return -4; - } - if (count($resArr)>0) { - return -3; - } - - $queryStr = "INSERT INTO `tblNotify` (`target`, `targetType`, " . $userOrGroup . ") VALUES (" . $this->_id . ", " . T_DOCUMENT . ", " . (int) $userOrGroupID . ")"; - if (!$db->getResult($queryStr)) - return -4; - - unset($this->_notifyList); - return 0; - } /* }}} */ - - /** - * Remove a user or group from the notification list - * This function does not check if the currently logged in user - * is allowed to remove a notification. This must be checked by the calling - * application. - * - * @param integer $userOrGroupID id of user or group - * @param boolean $isUser boolean true if a user is passed in $userOrGroupID, false - * if a group is passed in $userOrGroupID - * @param integer $type type of notification (0 will delete all) Not used yet! - * @return integer 0 if operation was succesful - * -1 if the userid/groupid is invalid - * -3 if the user/group is already subscribed - * -4 in case of an internal database error - */ - function removeNotify($userOrGroupID, $isUser, $type=0) { /* {{{ */ - $db = $this->_dms->getDB(); - - /* Verify that user / group exists. */ - /** @var SeedDMS_Core_Group|SeedDMS_Core_User $obj */ - $obj = ($isUser ? $this->_dms->getUser($userOrGroupID) : $this->_dms->getGroup($userOrGroupID)); - if (!is_object($obj)) { - return -1; - } - - $userOrGroup = ($isUser) ? "`userID`" : "`groupID`"; - - /* Verify that the requesting user has permission to add the target to - * the notification system. - */ - /* - * The calling application should enforce the policy on who is allowed - * to add someone to the notification system. If is shall remain here - * the currently logged in user should be passed to this function - * - GLOBAL $user; - if ($user->isGuest()) { - return -2; - } - if (!$user->isAdmin()) { - if ($isUser) { - if ($user->getID() != $obj->getID()) { - return -2; - } - } - else { - if (!$obj->isMember($user)) { - return -2; - } - } - } - */ - - /* Check to see if the target is in the database. */ - $queryStr = "SELECT * FROM `tblNotify` WHERE `tblNotify`.`target` = '".$this->_id."' ". - "AND `tblNotify`.`targetType` = '".T_DOCUMENT."' ". - "AND `tblNotify`.".$userOrGroup." = '".(int) $userOrGroupID."'"; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr)) { - return -4; - } - if (count($resArr)==0) { - return -3; - } - - $queryStr = "DELETE FROM `tblNotify` WHERE `target` = " . $this->_id . " AND `targetType` = " . T_DOCUMENT . " AND " . $userOrGroup . " = " . (int) $userOrGroupID; - /* If type is given then delete only those notifications */ - if($type) - $queryStr .= " AND `type` = ".(int) $type; - if (!$db->getResult($queryStr)) - return -4; - - unset($this->_notifyList); - return 0; - } /* }}} */ - - /** - * Add content to a document - * - * Each document may have any number of content elements attached to it. - * Each content element has a version number. Newer versions (greater - * version number) replace older versions. - * - * @param string $comment comment - * @param object $user user who shall be the owner of this content - * @param string $tmpFile file containing the actuall content - * @param string $orgFileName original file name - * @param string $fileType - * @param string $mimeType MimeType of the content - * @param array $reviewers list of reviewers - * @param array $approvers list of approvers - * @param integer $version version number of content or 0 if next higher version shall be used. - * @param array $attributes list of version attributes. The element key - * must be the id of the attribute definition. - * @param object $workflow - * @return bool|SeedDMS_Core_AddContentResultSet - */ - function addContent($comment, $user, $tmpFile, $orgFileName, $fileType, $mimeType, $reviewers=array(), $approvers=array(), $version=0, $attributes=array(), $workflow=null) { /* {{{ */ - $db = $this->_dms->getDB(); - - // the doc path is id/version.filetype - $dir = $this->getDir(); - - /* The version field in table tblDocumentContent used to be auto - * increment but that requires the field to be primary as well if - * innodb is used. That's why the version is now determined here. - */ - if ((int)$version<1) { - $queryStr = "SELECT MAX(`version`) AS m FROM `tblDocumentContent` WHERE `document` = ".$this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - $version = $resArr[0]['m']+1; - } - - if($fileType == '.') - $fileType = ''; - $filesize = SeedDMS_Core_File::fileSize($tmpFile); - $checksum = SeedDMS_Core_File::checksum($tmpFile); - - $db->startTransaction(); - $queryStr = "INSERT INTO `tblDocumentContent` (`document`, `version`, `comment`, `date`, `createdBy`, `dir`, `orgFileName`, `fileType`, `mimeType`, `fileSize`, `checksum`) VALUES ". - "(".$this->_id.", ".(int)$version.",".$db->qstr($comment).", ".$db->getCurrentTimestamp().", ".$user->getID().", ".$db->qstr($dir).", ".$db->qstr($orgFileName).", ".$db->qstr($fileType).", ".$db->qstr($mimeType).", ".$filesize.", ".$db->qstr($checksum).")"; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - $contentID = $db->getInsertID('tblDocumentContent'); - - // copy file - if (!SeedDMS_Core_File::makeDir($this->_dms->contentDir . $dir)) { - $db->rollbackTransaction(); - return false; - } - if($this->_dms->forceRename) - $err = SeedDMS_Core_File::renameFile($tmpFile, $this->_dms->contentDir . $dir . $version . $fileType); - else - $err = SeedDMS_Core_File::copyFile($tmpFile, $this->_dms->contentDir . $dir . $version . $fileType); - if (!$err) { - $db->rollbackTransaction(); - return false; - } - - $this->_content = null; - $this->_latestContent = null; - $content = $this->getLatestContent($contentID); /** @todo: Parameter not defined in Funktion */ - $docResultSet = new SeedDMS_Core_AddContentResultSet($content); - $docResultSet->setDMS($this->_dms); - - if($attributes) { - foreach($attributes as $attrdefid=>$attribute) { - /* $attribute can be a string or an array */ - if($attribute) { - if($attrdef = $this->_dms->getAttributeDefinition($attrdefid)) { - if(!$content->setAttributeValue($attrdef, $attribute)) { - $this->_removeContent($content); - $db->rollbackTransaction(); - return false; - } - } else { - $this->_removeContent($content); - $db->rollbackTransaction(); - return false; - } - } - } - } - - $queryStr = "INSERT INTO `tblDocumentStatus` (`documentID`, `version`) ". - "VALUES (". $this->_id .", ". (int) $version .")"; - if (!$db->getResult($queryStr)) { - $this->_removeContent($content); - $db->rollbackTransaction(); - return false; - } - - $statusID = $db->getInsertID('tblDocumentStatus', 'statusID'); - - if($workflow) - $content->setWorkflow($workflow, $user); - - // Add reviewers into the database. Reviewers must review the document - // and submit comments, if appropriate. Reviewers can also recommend that - // a document be rejected. - $pendingReview=false; - /** @noinspection PhpUnusedLocalVariableInspection */ - foreach (array("i", "g") as $i){ - if (isset($reviewers[$i])) { - foreach ($reviewers[$i] as $reviewerID) { - $reviewer=($i=="i" ?$this->_dms->getUser($reviewerID) : $this->_dms->getGroup($reviewerID)); - $res = ($i=="i" ? $docResultSet->getContent()->addIndReviewer($reviewer, $user, true) : $docResultSet->getContent()->addGrpReviewer($reviewer, $user, true)); - $docResultSet->addReviewer($reviewer, $i, $res); - // If no error is returned, or if the error is just due to email - // failure, mark the state as "pending review". - // FIXME: There seems to be no error code -4 anymore - if ($res==0 || $res=-3 || $res=-4) { - $pendingReview=true; - } - } - } - } - // Add approvers to the database. Approvers must also review the document - // and make a recommendation on its release as an approved version. - $pendingApproval=false; - /** @noinspection PhpUnusedLocalVariableInspection */ - foreach (array("i", "g") as $i){ - if (isset($approvers[$i])) { - foreach ($approvers[$i] as $approverID) { - $approver=($i=="i" ? $this->_dms->getUser($approverID) : $this->_dms->getGroup($approverID)); - $res=($i=="i" ? $docResultSet->getContent()->addIndApprover($approver, $user, true) : $docResultSet->getContent()->addGrpApprover($approver, $user, !$pendingReview)); - $docResultSet->addApprover($approver, $i, $res); - // FIXME: There seems to be no error code -4 anymore - if ($res==0 || $res=-3 || $res=-4) { - $pendingApproval=true; - } - } - } - } - - // If there are no reviewers or approvers, the document is automatically - // promoted to the released state. - if ($pendingReview) { - $status = S_DRAFT_REV; - $comment = ""; - } - elseif ($pendingApproval) { - $status = S_DRAFT_APP; - $comment = ""; - } - elseif($workflow) { - $status = S_IN_WORKFLOW; - $comment = ", workflow: ".$workflow->getName(); - } else { - $status = S_RELEASED; - $comment = ""; - } - $queryStr = "INSERT INTO `tblDocumentStatusLog` (`statusID`, `status`, `comment`, `date`, `userID`) ". - "VALUES ('". $statusID ."', '". $status."', 'New document content submitted". $comment ."', ".$db->getCurrentDatetime().", '". $user->getID() ."')"; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - /** @noinspection PhpMethodParametersCountMismatchInspection */ - $docResultSet->setStatus($status); - - $db->commitTransaction(); - return $docResultSet; - } /* }}} */ - - /** - * Replace a version of a document - * - * Each document may have any number of content elements attached to it. - * This function replaces the file content of a given version. - * Using this function is highly discourage, because it undermines the - * idea of keeping all versions of a document as originally saved. - * Content will only be replaced if the mimetype, filetype, user and - * original filename are identical to the version being updated. - * - * This function was introduced for the webdav server because any saving - * of a document created a new version. - * - * @param object $user user who shall be the owner of this content - * @param string $tmpFile file containing the actuall content - * @param string $orgFileName original file name - * @param string $fileType - * @param string $mimeType MimeType of the content - * @param integer $version version number of content or 0 if latest version shall be replaced. - * @return bool/array false in case of an error or a result set - */ - function replaceContent($version, $user, $tmpFile, $orgFileName, $fileType, $mimeType) { /* {{{ */ - $db = $this->_dms->getDB(); - - // the doc path is id/version.filetype - $dir = $this->getDir(); - - /* If $version < 1 than replace the content of the latest version. - */ - if ((int) $version<1) { - $queryStr = "SELECT MAX(`version`) AS m FROM `tblDocumentContent` WHERE `document` = ".$this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - $version = $resArr[0]['m']; - } - - $content = $this->getContentByVersion($version); - if(!$content) - return false; - - if($fileType == '.') - $fileType = ''; - - /* Check if $user, $orgFileName, $fileType and $mimeType are the same */ - if($user->getID() != $content->getUser()->getID()) { - return false; - } - if($orgFileName != $content->getOriginalFileName()) { - return false; - } - if($fileType != $content->getFileType()) { - return false; - } - if($mimeType != $content->getMimeType()) { - return false; - } - - $filesize = SeedDMS_Core_File::fileSize($tmpFile); - $checksum = SeedDMS_Core_File::checksum($tmpFile); - - $db->startTransaction(); - $queryStr = "UPDATE `tblDocumentContent` set `date`=".$db->getCurrentTimestamp().", `fileSize`=".$filesize.", `checksum`=".$db->qstr($checksum)." WHERE `id`=".$content->getID(); - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - // copy file - if (!SeedDMS_Core_File::copyFile($tmpFile, $this->_dms->contentDir . $dir . $version . $fileType)) { - $db->rollbackTransaction(); - return false; - } - - $this->_content = null; - $this->_latestContent = null; - $db->commitTransaction(); - - return true; - } /* }}} */ - - /** - * Return all content elements of a document - * - * This functions returns an array of content elements ordered by version. - * Version which are not accessible because of its status, will be filtered - * out. Access rights based on the document status are calculated for the - * currently logged in user. - * - * @return bool|SeedDMS_Core_DocumentContent[] - */ - function getContent() { /* {{{ */ - $db = $this->_dms->getDB(); - - if (!isset($this->_content)) { - $queryStr = "SELECT * FROM `tblDocumentContent` WHERE `document` = ".$this->_id." ORDER BY `version`"; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - $this->_content = array(); - $classname = $this->_dms->getClassname('documentcontent'); - $user = $this->_dms->getLoggedInUser(); - foreach ($resArr as $row) { - /** @var SeedDMS_Core_DocumentContent $content */ - $content = new $classname($row["id"], $this, $row["version"], $row["comment"], $row["date"], $row["createdBy"], $row["dir"], $row["orgFileName"], $row["fileType"], $row["mimeType"], $row['fileSize'], $row['checksum']); - /* TODO: Better use content id as key in $this->_content. This - * would allow to remove a single content object in removeContent(). - * Currently removeContent() must clear $this->_content completely - */ - if($user) { - if($content->getAccessMode($user) >= M_READ) - array_push($this->_content, $content); - } else { - array_push($this->_content, $content); - } - } - } - - return $this->_content; - } /* }}} */ - - /** - * Return the content element of a document with a given version number - * - * This function will check if the version is accessible and return false - * if not. Access rights based on the document status are calculated for the - * currently logged in user. - * - * @param integer $version version number of content element - * @return SeedDMS_Core_DocumentContent|null|boolean object of class - * {@link SeedDMS_Core_DocumentContent}, null if not content was found, - * false in case of an error - */ - function getContentByVersion($version) { /* {{{ */ - if (!is_numeric($version)) return false; - - if (isset($this->_content)) { - foreach ($this->_content as $revision) { - if ($revision->getVersion() == $version) - return $revision; - } - return null; - } - - $db = $this->_dms->getDB(); - $queryStr = "SELECT * FROM `tblDocumentContent` WHERE `document` = ".$this->_id." AND `version` = " . (int) $version; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - if (count($resArr) != 1) - return null; - - $resArr = $resArr[0]; - $classname = $this->_dms->getClassname('documentcontent'); - /** @var SeedDMS_Core_DocumentContent $content */ - if($content = new $classname($resArr["id"], $this, $resArr["version"], $resArr["comment"], $resArr["date"], $resArr["createdBy"], $resArr["dir"], $resArr["orgFileName"], $resArr["fileType"], $resArr["mimeType"], $resArr['fileSize'], $resArr['checksum'])) { - $user = $this->_dms->getLoggedInUser(); - /* A user with write access on the document may always see the version */ - if($user && $content->getAccessMode($user) == M_NONE) - return null; - else - return $content; - } else { - return false; - } - } /* }}} */ - - /** - * Check if a given version is the latest version of the document - * - * @param integer $version version number of content element - * @return SeedDMS_Core_DocumentContent|boolean object of class {@link SeedDMS_Core_DocumentContent} - * or false - */ - function isLatestContent($version) { /* {{{ */ - return $this->getLatestContent()->getVersion() == $version; - } /* }}} */ - - /** - * @return bool|null|SeedDMS_Core_DocumentContent - */ - function __getLatestContent() { /* {{{ */ - if (!$this->_latestContent) { - $db = $this->_dms->getDB(); - $queryStr = "SELECT * FROM `tblDocumentContent` WHERE `document` = ".$this->_id." ORDER BY `version` DESC LIMIT 1"; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - if (count($resArr) != 1) - return false; - - $resArr = $resArr[0]; - $classname = $this->_dms->getClassname('documentcontent'); - $this->_latestContent = new $classname($resArr["id"], $this, $resArr["version"], $resArr["comment"], $resArr["date"], $resArr["createdBy"], $resArr["dir"], $resArr["orgFileName"], $resArr["fileType"], $resArr["mimeType"], $resArr['fileSize'], $resArr['checksum']); - } - return $this->_latestContent; - } /* }}} */ - - /** - * Get the latest version of document - * - * This function returns the latest accessible version of a document. - * If content access has been restricted by setting - * {@link SeedDMS_Core_DMS::noReadForStatus} the function will go - * backwards in history until an accessible version is found. If none - * is found null will be returned. - * Access rights based on the document status are calculated for the - * currently logged in user. - * - * @return bool|SeedDMS_Core_DocumentContent object of class {@link SeedDMS_Core_DocumentContent} - */ - function getLatestContent() { /* {{{ */ - if (!$this->_latestContent) { - $db = $this->_dms->getDB(); - $queryStr = "SELECT * FROM `tblDocumentContent` WHERE `document` = ".$this->_id." ORDER BY `version` DESC"; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - $classname = $this->_dms->getClassname('documentcontent'); - $user = $this->_dms->getLoggedInUser(); - foreach ($resArr as $row) { - if (!$this->_latestContent) { - /** @var SeedDMS_Core_DocumentContent $content */ - $content = new $classname($row["id"], $this, $row["version"], $row["comment"], $row["date"], $row["createdBy"], $row["dir"], $row["orgFileName"], $row["fileType"], $row["mimeType"], $row['fileSize'], $row['checksum']); - if($user) { - /* If the user may even write the document, then also allow to see all content. - * This is needed because the user could upload a new version - */ - if($content->getAccessMode($user) >= M_READ) { - $this->_latestContent = $content; - } - } else { - $this->_latestContent = $content; - } - } - } - } - - return $this->_latestContent; - } /* }}} */ - - /** - * Remove version of document - * - * @param SeedDMS_Core_DocumentContent $version version number of content - * @return boolean true if successful, otherwise false - */ - private function _removeContent($version) { /* {{{ */ - $db = $this->_dms->getDB(); - - $db->startTransaction(); - - $status = $version->getStatus(); - $stID = $status["statusID"]; - - $queryStr = "DELETE FROM `tblDocumentContent` WHERE `document` = " . $this->getID() . " AND `version` = " . $version->getVersion(); - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - $queryStr = "DELETE FROM `tblDocumentContentAttributes` WHERE `content` = " . $version->getId(); - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - $queryStr = "DELETE FROM `tblDocumentStatusLog` WHERE `statusID` = '".$stID."'"; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - $queryStr = "DELETE FROM `tblDocumentStatus` WHERE `documentID` = '". $this->getID() ."' AND `version` = '" . $version->getVersion()."'"; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - $status = $version->getReviewStatus(); - $stList = ""; - foreach ($status as $st) { - $stList .= (strlen($stList)==0 ? "" : ", "). "'".$st["reviewID"]."'"; - $queryStr = "SELECT * FROM `tblDocumentReviewLog` WHERE `reviewID` = " . $st['reviewID']; - $resArr = $db->getResultArray($queryStr); - if ((is_bool($resArr) && !$resArr)) { - $db->rollbackTransaction(); - return false; - } - foreach($resArr as $res) { - $file = $this->_dms->contentDir . $this->getDir().'r'.$res['reviewLogID']; - if(SeedDMS_Core_File::file_exists($file)) - SeedDMS_Core_File::removeFile($file); - } - } - - if (strlen($stList)>0) { - $queryStr = "DELETE FROM `tblDocumentReviewLog` WHERE `tblDocumentReviewLog`.`reviewID` IN (".$stList.")"; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - } - $queryStr = "DELETE FROM `tblDocumentReviewers` WHERE `documentID` = '". $this->getID() ."' AND `version` = '" . $version->getVersion()."'"; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - $status = $version->getApprovalStatus(); - $stList = ""; - foreach ($status as $st) { - $stList .= (strlen($stList)==0 ? "" : ", "). "'".$st["approveID"]."'"; - $queryStr = "SELECT * FROM `tblDocumentApproveLog` WHERE `approveID` = " . $st['approveID']; - $resArr = $db->getResultArray($queryStr); - if ((is_bool($resArr) && !$resArr)) { - $db->rollbackTransaction(); - return false; - } - foreach($resArr as $res) { - $file = $this->_dms->contentDir . $this->getDir().'a'.$res['approveLogID']; - if(SeedDMS_Core_File::file_exists($file)) - SeedDMS_Core_File::removeFile($file); - } - } - - if (strlen($stList)>0) { - $queryStr = "DELETE FROM `tblDocumentApproveLog` WHERE `tblDocumentApproveLog`.`approveID` IN (".$stList.")"; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - } - $queryStr = "DELETE FROM `tblDocumentApprovers` WHERE `documentID` = '". $this->getID() ."' AND `version` = '" . $version->getVersion()."'"; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - $queryStr = "DELETE FROM `tblWorkflowDocumentContent` WHERE `document` = '". $this->getID() ."' AND `version` = '" . $version->getVersion()."'"; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - $queryStr = "DELETE FROM `tblWorkflowLog` WHERE `document` = '". $this->getID() ."' AND `version` = '" . $version->getVersion()."'"; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - // remove only those document files attached to version - $res = $this->getDocumentFiles($version->getVersion(), false); - if (is_bool($res) && !$res) { - $db->rollbackTransaction(); - return false; - } - - foreach ($res as $documentfile) - if(!$this->removeDocumentFile($documentfile->getId())) { - $db->rollbackTransaction(); - return false; - } - - if (SeedDMS_Core_File::file_exists( $this->_dms->contentDir.$version->getPath() )) - if (!SeedDMS_Core_File::removeFile( $this->_dms->contentDir.$version->getPath() )) { - $db->rollbackTransaction(); - return false; - } - - $db->commitTransaction(); - return true; - } /* }}} */ - - /** - * Call callback onPreRemoveDocument before deleting content - * - * @param SeedDMS_Core_DocumentContent $version version number of content - * @return bool|mixed - */ - function removeContent($version) { /* {{{ */ - $this->_dms->lasterror = ''; - $db = $this->_dms->getDB(); - - /* Make sure the version exists */ - $queryStr = "SELECT * FROM `tblDocumentContent` WHERE `document` = " . $this->getID() . " AND `version` = " . $version->getVersion(); - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - if (count($resArr)==0) - return false; - - /* Make sure this is not the last version */ - $queryStr = "SELECT * FROM `tblDocumentContent` WHERE `document` = " . $this->getID(); - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - if (count($resArr)==1) - return false; - - /* Check if 'onPreRemoveDocument' callback is set */ - if(isset($this->_dms->callbacks['onPreRemoveContent'])) { - foreach($this->_dms->callbacks['onPreRemoveContent'] as $callback) { - $ret = call_user_func($callback[0], $callback[1], $this, $version); - if(is_bool($ret)) - return $ret; - } - } - - if(false === ($ret = self::_removeContent($version))) { - return false; - } - - /* Invalidate the content list and the latest content of this document, - * otherwise getContent() and getLatestContent() - * will still return the content just deleted. - */ - $this->_latestContent = null; - $this->_content = null; - - /* Check if 'onPostRemoveDocument' callback is set */ - if(isset($this->_dms->callbacks['onPostRemoveContent'])) { - foreach($this->_dms->callbacks['onPostRemoveContent'] as $callback) { - if(!call_user_func($callback[0], $callback[1], $version)) { - } - } - } - - return $ret; - } /* }}} */ - - /** - * Return a certain document link - * - * @param integer $linkID id of link - * @return SeedDMS_Core_DocumentLink|bool of SeedDMS_Core_DocumentLink or false in case of - * an error. - */ - function getDocumentLink($linkID) { /* {{{ */ - $db = $this->_dms->getDB(); - - if (!is_numeric($linkID)) return false; - - $queryStr = "SELECT * FROM `tblDocumentLinks` WHERE `document` = " . $this->_id ." AND `id` = " . (int) $linkID; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - if (count($resArr)==0) - return null; - - $resArr = $resArr[0]; - $document = $this->_dms->getDocument($resArr["document"]); - $target = $this->_dms->getDocument($resArr["target"]); - $link = new SeedDMS_Core_DocumentLink($resArr["id"], $document, $target, $resArr["userID"], $resArr["public"]); - $user = $this->_dms->getLoggedInUser(); - if($link->getAccessMode($user, $document, $target) >= M_READ) - return $link; - return null; - } /* }}} */ - - /** - * Return all document links - * - * The list may contain all links to other documents, even those which - * may not be visible by certain users, unless you pass appropriate - * parameters to filter out public links and those created by - * the given user. The two parameters are or'ed. If $publiconly - * is set the method will return all public links disregarding the - * user. If $publiconly is not set but a user is set, the method - * will return all links of that user (public and none public). - * Setting a user and $publiconly to true will *not* return the - * public links of that user but all links which are public or - * owned by that user. - * - * The application must call - * SeedDMS_Core_DMS::filterDocumentLinks() afterwards to filter out - * those links pointing to a document not accessible by a given user. - * - * @param boolean $publiconly return all publically visible links - * @param SeedDMS_Core_User $user return also private links of this user - * - * @return array list of objects of class {@see SeedDMS_Core_DocumentLink} - */ - function getDocumentLinks($publiconly=false, $user=null) { /* {{{ */ - if (!isset($this->_documentLinks)) { - $db = $this->_dms->getDB(); - - $queryStr = "SELECT * FROM `tblDocumentLinks` WHERE `document` = " . $this->_id; - $tmp = array(); - if($publiconly) - $tmp[] = "`public`=1"; - if($user) - $tmp[] = "`userID`=".$user->getID(); - if($tmp) { - $queryStr .= " AND (".implode(" OR ", $tmp).")"; - } - - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - $this->_documentLinks = array(); - - $user = $this->_dms->getLoggedInUser(); - foreach ($resArr as $row) { - $target = $this->_dms->getDocument($row["target"]); - $link = new SeedDMS_Core_DocumentLink($row["id"], $this, $target, $row["userID"], $row["public"]); - if($link->getAccessMode($user, $this, $target) >= M_READ) - array_push($this->_documentLinks, $link); - } - } - return $this->_documentLinks; - } /* }}} */ - - /** - * Return all document having a link on this document - * - * The list contains all documents which have a link to the current - * document. The list contains even those documents which - * may not be accessible by the user, unless you pass appropriate - * parameters to filter out public links and those created by - * the given user. - * This functions is basically the reverse of - * {@see SeedDMS_Core_Document::getDocumentLinks()} - * - * The application must call - * SeedDMS_Core_DMS::filterDocumentLinks() afterwards to filter out - * those links pointing to a document not accessible by a given user. - * - * @param boolean $publiconly return all publically visible links - * @param SeedDMS_Core_User $user return also private links of this user - * - * @return array list of objects of class SeedDMS_Core_DocumentLink - */ - function getReverseDocumentLinks($publiconly=false, $user=null) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT * FROM `tblDocumentLinks` WHERE `target` = " . $this->_id; - $tmp = array(); - if($publiconly) - $tmp[] = "`public`=1"; - if($user) - $tmp[] = "`userID`=".$user->getID(); - if($tmp) { - $queryStr .= " AND (".implode(" OR ", $tmp).")"; - } - - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - $links = array(); - foreach ($resArr as $row) { - $document = $this->_dms->getDocument($row["document"]); - $link = new SeedDMS_Core_DocumentLink($row["id"], $document, $this, $row["userID"], $row["public"]); - if($link->getAccessMode($user, $document, $this) >= M_READ) - array_push($links, $link); - } - - return $links; - } /* }}} */ - - function addDocumentLink($targetID, $userID, $public) { /* {{{ */ - $db = $this->_dms->getDB(); - - $public = ($public) ? 1 : 0; - - if (!is_numeric($targetID) || $targetID < 1) - return false; - - if ($targetID == $this->_id) - return false; - - if (!is_numeric($userID) || $userID < 1) - return false; - - if(!($target = $this->_dms->getDocument($targetID))) - return false; - - if(!($user = $this->_dms->getUser($userID))) - return false; - - $queryStr = "INSERT INTO `tblDocumentLinks` (`document`, `target`, `userID`, `public`) VALUES (".$this->_id.", ".(int)$targetID.", ".(int)$userID.", ".$public.")"; - if (!$db->getResult($queryStr)) - return false; - - unset($this->_documentLinks); - - $id = $db->getInsertID('tblDocumentLinks'); - $link = new SeedDMS_Core_DocumentLink($id, $this, $target, $user->getId(), $public); - return $link; - } /* }}} */ - - function removeDocumentLink($linkID) { /* {{{ */ - $db = $this->_dms->getDB(); - - if (!is_numeric($linkID) || $linkID < 1) - return false; - - $queryStr = "DELETE FROM `tblDocumentLinks` WHERE `document` = " . $this->_id ." AND `id` = " . (int) $linkID; - if (!$db->getResult($queryStr)) return false; - unset ($this->_documentLinks); - return true; - } /* }}} */ - - /** - * Get attached file by its id - * - * @return object instance of SeedDMS_Core_DocumentFile, null if file is not - * accessible, false in case of an sql error - */ - function getDocumentFile($ID) { /* {{{ */ - $db = $this->_dms->getDB(); - - if (!is_numeric($ID)) return false; - - $queryStr = "SELECT * FROM `tblDocumentFiles` WHERE `document` = " . $this->_id ." AND `id` = " . (int) $ID; - $resArr = $db->getResultArray($queryStr); - if ((is_bool($resArr) && !$resArr) || count($resArr)==0) return false; - - $resArr = $resArr[0]; - $classname = $this->_dms->getClassname('documentfile'); - $file = new $classname($resArr["id"], $this, $resArr["userID"], $resArr["comment"], $resArr["date"], $resArr["dir"], $resArr["fileType"], $resArr["mimeType"], $resArr["orgFileName"], $resArr["name"],$resArr["version"],$resArr["public"]); - $user = $this->_dms->getLoggedInUser(); - if($file->getAccessMode($user) >= M_READ) - return $file; - return null; - } /* }}} */ - - /** - * Get list of files attached to document - * - * @param integer $version get only attachments for this version - * @param boolean $incnoversion include attachments without a version - * - * @return array list of files, false in case of an sql error - */ - function getDocumentFiles($version=0, $incnoversion=true) { /* {{{ */ - /* use a smarter caching because removing a document will call this function - * for each version and the document itself. - */ - $hash = substr(md5($version.$incnoversion), 0, 4); - if (!isset($this->_documentFiles[$hash])) { - $db = $this->_dms->getDB(); - - $queryStr = "SELECT * FROM `tblDocumentFiles` WHERE `document` = " . $this->_id; - if($version) { - if($incnoversion) - $queryStr .= " AND (`version`=0 OR `version`=".(int) $version.")"; - else - $queryStr .= " AND (`version`=".(int) $version.")"; - } - $queryStr .= " ORDER BY "; - if($version) { - $queryStr .= "`version` DESC,"; - } - $queryStr .= "`date` DESC"; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) return false; - - $this->_documentFiles = array($hash=>array()); - - $user = $this->_dms->getLoggedInUser(); - $classname = $this->_dms->getClassname('documentfile'); - foreach ($resArr as $row) { - $file = new $classname($row["id"], $this, $row["userID"], $row["comment"], $row["date"], $row["dir"], $row["fileType"], $row["mimeType"], $row["orgFileName"], $row["name"], $row["version"], $row["public"]); - if($file->getAccessMode($user) >= M_READ) - array_push($this->_documentFiles[$hash], $file); - } - } - return $this->_documentFiles[$hash]; - } /* }}} */ - - function addDocumentFile($name, $comment, $user, $tmpFile, $orgFileName, $fileType, $mimeType, $version=0, $public=1) { /* {{{ */ - $db = $this->_dms->getDB(); - - $dir = $this->getDir(); - - $db->startTransaction(); - $queryStr = "INSERT INTO `tblDocumentFiles` (`comment`, `date`, `dir`, `document`, `fileType`, `mimeType`, `orgFileName`, `userID`, `name`, `version`, `public`) VALUES ". - "(".$db->qstr($comment).", ".$db->getCurrentTimestamp().", ".$db->qstr($dir).", ".$this->_id.", ".$db->qstr($fileType).", ".$db->qstr($mimeType).", ".$db->qstr($orgFileName).",".$user->getID().",".$db->qstr($name).", ".((int) $version).", ".($public ? 1 : 0).")"; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - $id = $db->getInsertID('tblDocumentFiles'); - - $file = $this->getDocumentFile($id); - if (is_bool($file) && !$file) { - $db->rollbackTransaction(); - return false; - } - - // copy file - if (!SeedDMS_Core_File::makeDir($this->_dms->contentDir . $dir)) return false; - if($this->_dms->forceRename) - $err = SeedDMS_Core_File::renameFile($tmpFile, $this->_dms->contentDir . $file->getPath()); - else - $err = SeedDMS_Core_File::copyFile($tmpFile, $this->_dms->contentDir . $file->getPath()); - if (!$err) { - $db->rollbackTransaction(); - return false; - } - - $db->commitTransaction(); - unset ($this->_documentFiles); - return $file; - } /* }}} */ - - function removeDocumentFile($ID) { /* {{{ */ - $db = $this->_dms->getDB(); - - if (!is_numeric($ID) || $ID < 1) - return false; - - $file = $this->getDocumentFile($ID); - if (is_bool($file) && !$file) return false; - - $db->startTransaction(); - /* First delete the database record, because that can be undone - * if deletion of the file fails. - */ - $queryStr = "DELETE FROM `tblDocumentFiles` WHERE `document` = " . $this->getID() . " AND `id` = " . (int) $ID; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - if (SeedDMS_Core_File::file_exists( $this->_dms->contentDir . $file->getPath() )){ - if (!SeedDMS_Core_File::removeFile( $this->_dms->contentDir . $file->getPath() )) { - $db->rollbackTransaction(); - return false; - } - } - - $db->commitTransaction(); - unset ($this->_documentFiles); - - return true; - } /* }}} */ - - /** - * Remove a document completly - * - * This methods calls the callback 'onPreRemoveDocument' before removing - * the document. The current document will be passed as the second - * parameter to the callback function. After successful deletion the - * 'onPostRemoveDocument' callback will be used. The current document id - * will be passed as the second parameter. If onPreRemoveDocument fails - * the whole function will fail and the document will not be deleted. - * The return value of 'onPostRemoveDocument' will be disregarded. - * - * @return boolean true on success, otherwise false - */ - function remove() { /* {{{ */ - $db = $this->_dms->getDB(); - $this->_dms->lasterror = ''; - - /* Check if 'onPreRemoveDocument' callback is set */ - if(isset($this->_dms->callbacks['onPreRemoveDocument'])) { - foreach($this->_dms->callbacks['onPreRemoveDocument'] as $callback) { - $ret = call_user_func($callback[0], $callback[1], $this); - if(is_bool($ret)) - return $ret; - } - } - - $res = $this->getContent(); - if (is_bool($res) && !$res) return false; - - $db->startTransaction(); - - // remove content of document - foreach ($this->_content as $version) { - if (!$this->_removeContent($version)) { - $db->rollbackTransaction(); - return false; - } - } - - // remove all document files - $res = $this->getDocumentFiles(); - if (is_bool($res) && !$res) { - $db->rollbackTransaction(); - return false; - } - - foreach ($res as $documentfile) - if(!$this->removeDocumentFile($documentfile->getId())) { - $db->rollbackTransaction(); - return false; - } - - // TODO: versioning file? - - if (SeedDMS_Core_File::file_exists( $this->_dms->contentDir . $this->getDir() )) - if (!SeedDMS_Core_File::removeDir( $this->_dms->contentDir . $this->getDir() )) { - $db->rollbackTransaction(); - return false; - } - - $queryStr = "DELETE FROM `tblDocuments` WHERE `id` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - $queryStr = "DELETE FROM `tblDocumentAttributes` WHERE `document` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - $queryStr = "DELETE FROM `tblACLs` WHERE `target` = " . $this->_id . " AND `targetType` = " . T_DOCUMENT; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - $queryStr = "DELETE FROM `tblDocumentLinks` WHERE `document` = " . $this->_id . " OR `target` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - $queryStr = "DELETE FROM `tblDocumentLocks` WHERE `document` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - $queryStr = "DELETE FROM `tblDocumentFiles` WHERE `document` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - $queryStr = "DELETE FROM `tblDocumentCategory` WHERE `documentID` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - // Delete the notification list. - $queryStr = "DELETE FROM `tblNotify` WHERE `target` = " . $this->_id . " AND `targetType` = " . T_DOCUMENT; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - $db->commitTransaction(); - - /* Check if 'onPostRemoveDocument' callback is set */ - if(isset($this->_dms->callbacks['onPostRemoveDocument'])) { - foreach($this->_dms->callbacks['onPostRemoveDocument'] as $callback) { - if(!call_user_func($callback[0], $callback[1], $this)) { - } - } - } - - return true; - } /* }}} */ - - /** - * Get List of users and groups which have read access on the document - * The list will not include any guest users, - * administrators and the owner of the folder unless $listadmin resp. - * $listowner is set to true. - * - * This function is deprecated. Use - * {@see SeedDMS_Core_Document::getReadAccessList()} instead. - */ - protected function __getApproversList() { /* {{{ */ - return $this->getReadAccessList(0, 0, 0); - } /* }}} */ - - /** - * Returns a list of groups and users with read access on the document - * - * @param boolean $listadmin if set to true any admin will be listed too - * @param boolean $listowner if set to true the owner will be listed too - * @param boolean $listguest if set to true any guest will be listed too - * - * @return array list of users and groups - */ - function getReadAccessList($listadmin=0, $listowner=0, $listguest=0) { /* {{{ */ - $db = $this->_dms->getDB(); - - if (!isset($this->_readAccessList)) { - $this->_readAccessList = array("groups" => array(), "users" => array()); - $userIDs = ""; - $groupIDs = ""; - $defAccess = $this->getDefaultAccess(); - - /* Check if the default access is < read access or >= read access. - * If default access is less than read access, then create a list - * of users and groups with read access. - * If default access is equal or greater then read access, then - * create a list of users and groups without read access. - */ - if ($defAccessgetAccessList(M_READ, O_GTEQ); - } - else { - // Get the list of all users and groups that DO NOT have read access - // to the document. - $tmpList = $this->getAccessList(M_NONE, O_LTEQ); - } - /** @var SeedDMS_Core_GroupAccess $groupAccess */ - foreach ($tmpList["groups"] as $groupAccess) { - $groupIDs .= (strlen($groupIDs)==0 ? "" : ", ") . $groupAccess->getGroupID(); - } - - /** @var SeedDMS_Core_UserAccess $userAccess */ - foreach ($tmpList["users"] as $userAccess) { - $user = $userAccess->getUser(); - if (!$listadmin && $user->isAdmin()) continue; - if (!$listowner && $user->getID() == $this->_ownerID) continue; - if (!$listguest && $user->isGuest()) continue; - $userIDs .= (strlen($userIDs)==0 ? "" : ", ") . $userAccess->getUserID(); - } - - // Construct a query against the users table to identify those users - // that have read access to this document, either directly through an - // ACL entry, by virtue of ownership or by having administrative rights - // on the database. - $queryStr=""; - /* If default access is less then read, $userIDs and $groupIDs contains - * a list of user with read access - */ - if ($defAccess < M_READ) { - if (strlen($groupIDs)>0) { - $queryStr = "SELECT `tblUsers`.* FROM `tblUsers` ". - "LEFT JOIN `tblGroupMembers` ON `tblGroupMembers`.`userID`=`tblUsers`.`id` ". - "WHERE `tblGroupMembers`.`groupID` IN (". $groupIDs .") ". - "AND `tblUsers`.`role` != ".SeedDMS_Core_User::role_guest." UNION "; - } - $queryStr .= - "SELECT `tblUsers`.* FROM `tblUsers` ". - "WHERE (`tblUsers`.`role` != ".SeedDMS_Core_User::role_guest.") ". - "AND ((`tblUsers`.`id` = ". $this->_ownerID . ") ". - "OR (`tblUsers`.`role` = ".SeedDMS_Core_User::role_admin.")". - (strlen($userIDs) == 0 ? "" : " OR (`tblUsers`.`id` IN (". $userIDs ."))"). - ") ORDER BY `login`"; - } - /* If default access is equal or greater than M_READ, $userIDs and - * $groupIDs contains a list of user without read access - */ - else { - if (strlen($groupIDs)>0) { - $queryStr = "SELECT `tblUsers`.* FROM `tblUsers` ". - "LEFT JOIN `tblGroupMembers` ON `tblGroupMembers`.`userID`=`tblUsers`.`id` ". - "WHERE `tblGroupMembers`.`groupID` NOT IN (". $groupIDs .")". - "AND `tblUsers`.`role` != ".SeedDMS_Core_User::role_guest." ". - (strlen($userIDs) == 0 ? "" : " AND (`tblUsers`.`id` NOT IN (". $userIDs ."))")." UNION "; - } else { - $queryStr .= - "SELECT `tblUsers`.* FROM `tblUsers` ". - "WHERE `tblUsers`.`role` != ".SeedDMS_Core_User::role_guest." ". - (strlen($userIDs) == 0 ? "" : " AND (`tblUsers`.`id` NOT IN (". $userIDs ."))")." UNION "; - } - $queryStr .= - "SELECT `tblUsers`.* FROM `tblUsers` ". - "WHERE (`tblUsers`.`id` = ". $this->_ownerID . ") ". - "OR (`tblUsers`.`role` = ".SeedDMS_Core_User::role_admin.") ". -// "UNION ". -// "SELECT `tblUsers`.* FROM `tblUsers` ". -// "WHERE `tblUsers`.`role` != ".SeedDMS_Core_User::role_guest." ". -// (strlen($userIDs) == 0 ? "" : " AND (`tblUsers`.`id` NOT IN (". $userIDs ."))"). - " ORDER BY `login`"; - } - $resArr = $db->getResultArray($queryStr); - if (!is_bool($resArr)) { - foreach ($resArr as $row) { - $user = $this->_dms->getUser($row['id']); - if (!$listadmin && $user->isAdmin()) continue; - if (!$listowner && $user->getID() == $this->_ownerID) continue; - $this->_readAccessList["users"][] = $user; - } - } - - // Assemble the list of groups that have read access to the document. - $queryStr=""; - if ($defAccess < M_READ) { - if (strlen($groupIDs)>0) { - $queryStr = "SELECT `tblGroups`.* FROM `tblGroups` ". - "WHERE `tblGroups`.`id` IN (". $groupIDs .") ORDER BY `name`"; - } - } - else { - if (strlen($groupIDs)>0) { - $queryStr = "SELECT `tblGroups`.* FROM `tblGroups` ". - "WHERE `tblGroups`.`id` NOT IN (". $groupIDs .") ORDER BY `name`"; - } - else { - $queryStr = "SELECT `tblGroups`.* FROM `tblGroups` ORDER BY `name`"; - } - } - if (strlen($queryStr)>0) { - $resArr = $db->getResultArray($queryStr); - if (!is_bool($resArr)) { - foreach ($resArr as $row) { - $group = $this->_dms->getGroup($row["id"]); - $this->_readAccessList["groups"][] = $group; - } - } - } - } - return $this->_readAccessList; - } /* }}} */ - - /** - * Get the internally used folderList which stores the ids of folders from - * the root folder to the parent folder. - * - * @return string column separated list of folder ids - */ - function getFolderList() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT `folderList` FROM `tblDocuments` WHERE id = ".$this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - return $resArr[0]['folderList']; - } /* }}} */ - - /** - * Checks the internal data of the document and repairs it. - * Currently, this function only repairs an incorrect folderList - * - * @return boolean true on success, otherwise false - */ - function repair() { /* {{{ */ - $db = $this->_dms->getDB(); - - $curfolderlist = $this->getFolderList(); - - // calculate the folderList of the folder - $parent = $this->getFolder(); - $pathPrefix=""; - $path = $parent->getPath(); - foreach ($path as $f) { - $pathPrefix .= ":".$f->getID(); - } - if (strlen($pathPrefix)>1) { - $pathPrefix .= ":"; - } - if($curfolderlist != $pathPrefix) { - $queryStr = "UPDATE `tblDocuments` SET `folderList`='".$pathPrefix."' WHERE `id` = ". $this->_id; - $res = $db->getResult($queryStr); - if (!$res) - return false; - } - return true; - } /* }}} */ - - /** - * Calculate the disk space including all versions of the document - * - * This is done by using the internal database field storing the - * filesize of a document version. - * - * @return integer total disk space in Bytes - */ - function getUsedDiskSpace() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT SUM(`fileSize`) sum FROM `tblDocumentContent` WHERE `document` = " . $this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && $resArr == false) - return false; - - return $resArr[0]['sum']; - } /* }}} */ - - /** - * Returns a list of events happend during the life of the document - * - * This includes the creation of new versions, approval and reviews, etc. - * - * @return array list of events - */ - function getTimeline() { /* {{{ */ - $db = $this->_dms->getDB(); - - $timeline = array(); - - /* No need to add entries for new version because the status log - * will generate an entry as well. - $queryStr = "SELECT * FROM `tblDocumentContent` WHERE `document` = " . $this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && $resArr == false) - return false; - - foreach ($resArr as $row) { - $date = date('Y-m-d H:i:s', $row['date']); - $timeline[] = array('date'=>$date, 'msg'=>'Added version '.$row['version'], 'type'=>'add_version', 'version'=>$row['version'], 'document'=>$this, 'params'=>array($row['version'])); - } - */ - - $queryStr = "SELECT * FROM `tblDocumentFiles` WHERE `document` = " . $this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && $resArr == false) - return false; - - foreach ($resArr as $row) { - $date = date('Y-m-d H:i:s', (int) $row['date']); - $timeline[] = array('date'=>$date, 'msg'=>'Added attachment "'.$row['name'].'"', 'document'=>$this, 'type'=>'add_file', 'fileid'=>$row['id']); - } - - $queryStr= - "SELECT `tblDocumentStatus`.*, `tblDocumentStatusLog`.`statusLogID`,`tblDocumentStatusLog`.`status`, ". - "`tblDocumentStatusLog`.`comment`, `tblDocumentStatusLog`.`date`, ". - "`tblDocumentStatusLog`.`userID` ". - "FROM `tblDocumentStatus` ". - "LEFT JOIN `tblDocumentStatusLog` USING (`statusID`) ". - "WHERE `tblDocumentStatus`.`documentID` = '". $this->_id ."' ". - "ORDER BY `tblDocumentStatusLog`.`statusLogID` DESC"; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - /* The above query will also contain entries where a document status exists - * but no status log entry. Those records will have no date and must be - * skipped. - */ - foreach ($resArr as $row) { - if($row['date']) { - $date = $row['date']; - $timeline[] = array('date'=>$date, 'msg'=>'Version '.$row['version'].': Status change to '.$row['status'], 'type'=>'status_change', 'version'=>$row['version'], 'document'=>$this, 'status'=>$row['status'], 'statusid'=>$row['statusID'], 'statuslogid'=>$row['statusLogID']); - } - } - return $timeline; - } /* }}} */ - - /** - * Transfers the document to a new user - * - * This method not just sets a new owner of the document but also - * transfers the document links, attachments and locks to the new user. - * - * @return boolean true if successful, otherwise false - */ - function transferToUser($newuser) { /* {{{ */ - $db = $this->_dms->getDB(); - - if($newuser->getId() == $this->_ownerID) - return true; - - $db->startTransaction(); - $queryStr = "UPDATE `tblDocuments` SET `owner` = ".$newuser->getId()." WHERE `id` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - $queryStr = "UPDATE `tblDocumentLocks` SET `userID` = ".$newuser->getId()." WHERE `document` = " . $this->_id . " AND `userID` = ".$this->_ownerID; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - $queryStr = "UPDATE `tblDocumentLinks` SET `userID` = ".$newuser->getId()." WHERE `document` = " . $this->_id . " AND `userID` = ".$this->_ownerID; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - $queryStr = "UPDATE `tblDocumentFiles` SET `userID` = ".$newuser->getId()." WHERE `document` = " . $this->_id . " AND `userID` = ".$this->_ownerID; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - $this->_ownerID = $newuser->getID(); - $this->_owner = $newuser; - - $db->commitTransaction(); - return true; - } /* }}} */ - -} /* }}} */ - - -/** - * Class to represent content of a document - * - * Each document has content attached to it, often called a 'version' of the - * document. The document content represents a file on the disk with some - * meta data stored in the database. A document content has a version number - * which is incremented with each replacement of the old content. Old versions - * are kept unless they are explicitly deleted by - * {@link SeedDMS_Core_Document::removeContent()}. - * - * @category DMS - * @package SeedDMS_Core - * @author Markus Westphal, Malcolm Cowe, Matteo Lucarelli, - * Uwe Steinmann - * @copyright Copyright (C) 2002-2005 Markus Westphal, - * 2006-2008 Malcolm Cowe, 2010 Matteo Lucarelli, - * 2010-2022 Uwe Steinmann - * @version Release: @package_version@ - */ -class SeedDMS_Core_DocumentContent extends SeedDMS_Core_Object { /* {{{ */ - /** - * @var object document - */ - protected $_document; - - /** - * @var integer version - */ - protected $_version; - - /** - * @var string comment - */ - protected $_comment; - - /** - * @var string date - */ - protected $_date; - - /** - * @var integer userID - */ - protected $_userID; - - /** - * @var string dir on disk (deprecated) - */ - protected $_dir; - - /** - * @var string original file name - */ - protected $_orgFileName; - - /** - * @var string file type (actually the extension without the leading dot) - */ - protected $_fileType; - - /** - * @var string mime type - */ - protected $_mimeType; - - /** - * @var string checksum of content - */ - protected $_checksum; - - /** - * @var object workflow - */ - protected $_workflow; - - /** - * @var object workflow state - */ - protected $_workflowState; - - /** - * @var object dms - */ - public $_dms; - - /** - * Recalculate the status of a document - * - * The methods checks the review and approval status and sets the - * status of the document accordingly. - * - * If status is S_RELEASED and the version has a workflow, then set - * the status to S_IN_WORKFLOW - * If status is S_RELEASED and there are reviewers => set status S_DRAFT_REV - * If status is S_RELEASED or S_DRAFT_REV and there are approvers => set - * status S_DRAFT_APP - * If status is draft and there are no approver and no reviewers => set - * status to S_RELEASED - * The status of a document with the current status S_OBSOLETE, S_REJECTED, - * or S_EXPIRED will not be changed unless the parameter - * $ignorecurrentstatus is set to true. - * - * This method may not be called after a negative approval or review to - * recalculated the status, because - * it doesn't take a defeating approval or review into account. This method - * does not set the status to S_REJECTED! It will - * just check for a pending workflow, approval or review and set the status - * accordingly, e.g. after the list of reviewers or appovers has been - * modified. If there is not pending workflow, approval or review the - * status will be set to S_RELEASED. - * - * This method will call {@see SeedDMS_Core_DocumentContent::setStatus()} - * which checks if the status has actually changed. This is, why this - * function can be called at any time without harm to the status log. - * - * @param boolean $ignorecurrentstatus ignore the current status and - * recalculate a new status in any case - * @param object $user the user initiating this method - * @param string $msg message stored in status log when status is set - */ - function verifyStatus($ignorecurrentstatus=false, $user=null, $msg='') { /* {{{ */ - - unset($this->_status); - $st=$this->getStatus(); - - if (!$ignorecurrentstatus && ($st["status"]==S_OBSOLETE || $st["status"]==S_REJECTED || $st["status"]==S_EXPIRED )) return $st['status']; - - $this->_workflow = null; // force to be reloaded from DB - $hasworkflow = $this->getWorkflow() ? true : false; - - /* $pendingReview will be set when there are still open reviews */ - $pendingReview=false; - /* $hasReview will be set if there is at least one positiv review */ - $hasReview=false; - unset($this->_reviewStatus); // force to be reloaded from DB - $reviewStatus=$this->getReviewStatus(); - if (is_array($reviewStatus) && count($reviewStatus)>0) { - foreach ($reviewStatus as $r){ - if ($r["status"]==0){ - $pendingReview=true; - break; - } elseif($r["status"]==1){ - $hasReview=true; - } - } - } - - /* $pendingApproval will be set when there are still open approvals */ - $pendingApproval=false; - /* $hasApproval will be set if there is at least one positiv review */ - $hasApproval=false; - unset($this->_approvalStatus); // force to be reloaded from DB - $approvalStatus=$this->getApprovalStatus(); - if (is_array($approvalStatus) && count($approvalStatus)>0) { - foreach ($approvalStatus as $a){ - if ($a["status"]==0){ - $pendingApproval=true; - break; - } elseif($a["status"]==1){ - $hasApproval=true; - } - } - } - - /* First check for a running workflow or open reviews or approvals. */ - if ($hasworkflow) { $newstatus = S_IN_WORKFLOW; $ret = $this->setStatus(S_IN_WORKFLOW,$msg,$user); } - elseif ($pendingReview) { $newstatus = S_DRAFT_REV; $ret = $this->setStatus(S_DRAFT_REV,$msg,$user); } - elseif ($pendingApproval) { $newstatus = S_DRAFT_APP; $ret = $this->setStatus(S_DRAFT_APP,$msg,$user); } - else { $newstatus = S_RELEASED; $ret = $this->setStatus(S_RELEASED,$msg,$user); } - return $ret ? $newstatus : $ret; - } /* }}} */ - - function __construct($id, $document, $version, $comment, $date, $userID, $dir, $orgFileName, $fileType, $mimeType, $fileSize=0, $checksum='') { /* {{{ */ - parent::__construct($id); - $this->_document = $document; - $this->_version = (int) $version; - $this->_comment = $comment; - $this->_date = (int) $date; - $this->_userID = (int) $userID; - $this->_dir = $dir; - $this->_orgFileName = $orgFileName; - $this->_fileType = $fileType; - $this->_mimeType = $mimeType; - $this->_dms = $document->getDMS(); - if(!$fileSize) { - $this->_fileSize = SeedDMS_Core_File::fileSize($this->_dms->contentDir . $this->getPath()); - } else { - $this->_fileSize = $fileSize; - } - $this->_checksum = $checksum; - $this->_workflow = null; - $this->_workflowState = null; - } /* }}} */ - - /** - * Check if this object is of type 'documentcontent'. - * - * @param string $type type of object - */ - public function isType($type) { /* {{{ */ - return $type == 'documentcontent'; - } /* }}} */ - - function getVersion() { return $this->_version; } - function getComment() { return $this->_comment; } - function getDate() { return $this->_date; } - function getOriginalFileName() { return $this->_orgFileName; } - function getFileType() { return $this->_fileType; } - function getFileName(){ return $this->_version . $this->_fileType; } - /** - * getDir and the corresponding database table field are deprecated - */ - function __getDir() { return $this->_dir; } - function getMimeType() { return $this->_mimeType; } - function getDocument() { return $this->_document; } - - function getUser() { /* {{{ */ - if (!isset($this->_user)) - $this->_user = $this->_document->getDMS()->getUser($this->_userID); - return $this->_user; - } /* }}} */ - - /** - * Return path of file on disk relative to the content directory - * - * Since version 5.1.13 a single '.' in the fileType will be skipped. - * On Windows a file named 'name.' will be saved as 'name' but the fileType - * will contain the a single '.'. - * - * @return string path of file on disc - */ - function getPath() { return $this->_document->getDir() . $this->_version . $this->_fileType; } - - /** - * Set upload date of document content - * - * @param string $date date must be a timestamp or in the format 'Y-m-d H:i:s' - * - * @return boolean true on success, otherwise false - */ - function setDate($date = false) { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - if(!$date) - $date = time(); - else { - if(is_string($date) && SeedDMS_Core_DMS::checkDate($date, 'Y-m-d H:i:s')) { - $date = strtotime($date); - } elseif(is_numeric($date)) - $date = (int) $date; - else - return false; - } - - $queryStr = "UPDATE `tblDocumentContent` SET `date` = ". $date." WHERE `document` = " . $this->_document->getID() . " AND `version` = " . $this->_version; - if (!$db->getResult($queryStr)) - return false; - - $this->_date = $date; - - return true; - } /* }}} */ - - function getFileSize() { /* {{{ */ - return $this->_fileSize; - } /* }}} */ - - /** - * Set file size by reading the file - */ - function setFileSize() { /* {{{ */ - $filesize = SeedDMS_Core_File::fileSize($this->_dms->contentDir . $this->_document->getDir() . $this->getFileName()); - if($filesize === false) - return false; - - $db = $this->_document->getDMS()->getDB(); - $queryStr = "UPDATE `tblDocumentContent` SET `fileSize` = ".$filesize." WHERE `document` = " . $this->_document->getID() . " AND `version` = " . $this->_version; - if (!$db->getResult($queryStr)) - return false; - $this->_fileSize = $filesize; - - return true; - } /* }}} */ - - function getChecksum() { /* {{{ */ - return $this->_checksum; - } /* }}} */ - - /** - * Set checksum by reading the file - */ - function setChecksum() { /* {{{ */ - $checksum = SeedDMS_Core_File::checksum($this->_dms->contentDir . $this->_document->getDir() . $this->getFileName()); - if($checksum === false) - return false; - - $db = $this->_document->getDMS()->getDB(); - $queryStr = "UPDATE `tblDocumentContent` SET `checksum` = ".$db->qstr($checksum)." WHERE `document` = " . $this->_document->getID() . " AND `version` = " . $this->_version; - if (!$db->getResult($queryStr)) - return false; - $this->_checksum = $checksum; - - return true; - } /* }}} */ - - /** - * Set file type by evaluating the mime type - */ - function setFileType() { /* {{{ */ - $mimetype = $this->getMimeType(); - - $expect = SeedDMS_Core_File::fileExtension($mimetype); - if($expect && '.'.$expect != $this->_fileType) { - $db = $this->_document->getDMS()->getDB(); - $db->startTransaction(); - $queryStr = "UPDATE `tblDocumentContent` SET `fileType`='.".$expect."' WHERE `id` = ". $this->_id; - $res = $db->getResult($queryStr); - if ($res) { - if(!SeedDMS_Core_File::renameFile($this->_dms->contentDir.$this->_document->getDir() . $this->_version . $this->_fileType, $this->_dms->contentDir.$this->_document->getDir() . $this->_version . '.' . $expect)) { - $db->rollbackTransaction(); - } else { - $this->_fileType = '.'.$expect; - $db->commitTransaction(); - return true; - } - } else { - $db->rollbackTransaction(); - } - } - - return false; - } /* }}} */ - - function setMimeType($newMimetype) { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - if(!$newMimetype) - return false; - - $newMimetype = trim($newMimetype); - - if(!$newMimetype) - return false; - - $queryStr = "UPDATE `tblDocumentContent` SET `mimeType` = ".$db->qstr($newMimetype)." WHERE `document` = " . $this->_document->getID() . " AND `version` = " . $this->_version; - if (!$db->getResult($queryStr)) - return false; - - $this->_mimeType = $newMimetype; - - return true; - } /* }}} */ - - function setComment($newComment) { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - $queryStr = "UPDATE `tblDocumentContent` SET `comment` = ".$db->qstr($newComment)." WHERE `document` = " . $this->_document->getID() . " AND `version` = " . $this->_version; - if (!$db->getResult($queryStr)) - return false; - - $this->_comment = $newComment; - - return true; - } /* }}} */ - - /** - * Get the latest status of the content - * - * The status of the content reflects its current review, approval or workflow - * state. A status can be a negative or positive number or 0. A negative - * numbers indicate a missing approval, review or an obsolete content. - * Positive numbers indicate some kind of approval or workflow being - * active, but not necessarily a release. - * S_DRAFT_REV, 0 - * S_DRAFT_APP, 1 - * S_RELEASED, 2 - * S_IN_WORKFLOW, 3 - * S_REJECTED, -1 - * S_OBSOLETE, -2 - * S_EXPIRED, -3 - * When a content is inserted and does not need approval nor review, - * then its status is set to S_RELEASED immediately. Any change of - * the status is monitored in the table tblDocumentStatusLog. This - * function will always return the latest entry for the content. - * - * @return array latest record from tblDocumentStatusLog - */ - function getStatus($limit=1) { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - if (!is_numeric($limit)) return false; - - // Retrieve the current overall status of the content represented by - // this object. - if (!isset($this->_status)) { - $queryStr= - "SELECT `tblDocumentStatus`.*, `tblDocumentStatusLog`.`status`, ". - "`tblDocumentStatusLog`.`comment`, `tblDocumentStatusLog`.`date`, ". - "`tblDocumentStatusLog`.`userID` ". - "FROM `tblDocumentStatus` ". - "LEFT JOIN `tblDocumentStatusLog` USING (`statusID`) ". - "WHERE `tblDocumentStatus`.`documentID` = '". $this->_document->getID() ."' ". - "AND `tblDocumentStatus`.`version` = '". $this->_version ."' ". - "ORDER BY `tblDocumentStatusLog`.`statusLogID` DESC LIMIT ".(int) $limit; - - $res = $db->getResultArray($queryStr); - if (is_bool($res) && !$res) - return false; - if (count($res)!=1) - return false; - $this->_status = $res[0]; - } - return $this->_status; - } /* }}} */ - - /** - * Get current and former states of the document content - * - * @param integer $limit if not set all log entries will be returned - * @return array list of status changes - */ - function getStatusLog($limit=0) { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - if (!is_numeric($limit)) return false; - - $queryStr= - "SELECT `tblDocumentStatus`.*, `tblDocumentStatusLog`.`status`, ". - "`tblDocumentStatusLog`.`comment`, `tblDocumentStatusLog`.`date`, ". - "`tblDocumentStatusLog`.`userID` ". - "FROM `tblDocumentStatus` ". - "LEFT JOIN `tblDocumentStatusLog` USING (`statusID`) ". - "WHERE `tblDocumentStatus`.`documentID` = '". $this->_document->getID() ."' ". - "AND `tblDocumentStatus`.`version` = '". $this->_version ."' ". - "ORDER BY `tblDocumentStatusLog`.`statusLogID` DESC "; - if($limit) - $queryStr .= "LIMIT ".(int) $limit; - - $res = $db->getResultArray($queryStr); - if (is_bool($res) && !$res) - return false; - - return $res; - } /* }}} */ - - /** - * Set the status of the content - * Setting the status means to add another entry into the table - * tblDocumentStatusLog. The method returns also false if the status - * is already set on the value passed to the method. - * - * @param integer $status new status of content - * @param string $comment comment for this status change - * @param object $updateUser user initiating the status change - * @param string $date date in the format 'Y-m-d H:i:s' - * - * @return boolean true on success, otherwise false - */ - function setStatus($status, $comment, $updateUser, $date='') { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - if (!is_numeric($status)) return false; - - /* return an error if $updateuser is not set */ - if(!$updateUser || !$updateUser->isType('user')) - return false; - - // If the supplied value lies outside of the accepted range, return an - // error. - if ($status < S_LOWEST_STATUS || $status > S_HIGHEST_STATUS) { - return false; - } - - // Retrieve the current overall status of the content represented by - // this object, if it hasn't been done already. - if (!isset($this->_status)) { - $this->getStatus(); - } - if ($this->_status["status"]==$status) { - return true; - } - if($date) { - if(!SeedDMS_Core_DMS::checkDate($date, 'Y-m-d H:i:s')) - return false; - $ddate = $db->qstr($date); - } else - $ddate = $db->getCurrentDatetime(); - $db->startTransaction(); - $queryStr = "INSERT INTO `tblDocumentStatusLog` (`statusID`, `status`, `comment`, `date`, `userID`) ". - "VALUES ('". $this->_status["statusID"] ."', '". (int) $status ."', ".$db->qstr($comment).", ".$ddate.", '". $updateUser->getID() ."')"; - $res = $db->getResult($queryStr); - if (is_bool($res) && !$res) { - $db->rollbackTransaction(); - return false; - } - - /* Check if 'onSetStatus' callback is set */ - if(isset($this->_dms->callbacks['onSetStatus'])) { - foreach($this->_dms->callbacks['onSetStatus'] as $callback) { - $ret = call_user_func($callback[0], $callback[1], $this, $updateUser, $this->_status["status"], $status); - if(is_bool($ret)) { - unset($this->_status); - if($ret) - $db->commitTransaction(); - else - $db->rollbackTransaction(); - return $ret; - } - } - } - - $db->commitTransaction(); - unset($this->_status); - return true; - } /* }}} */ - - /** - * Rewrites the complete status log - * - * Attention: this function is highly dangerous. - * It removes an existing status log and rewrites it. - * This method was added for importing an xml dump. - * - * @param array $statuslog new status log with the newest log entry first. - * @return boolean true on success, otherwise false - */ - function rewriteStatusLog($statuslog) { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - $queryStr= "SELECT `tblDocumentStatus`.* FROM `tblDocumentStatus` WHERE `tblDocumentStatus`.`documentID` = '". $this->_document->getID() ."' AND `tblDocumentStatus`.`version` = '". $this->_version ."' "; - $res = $db->getResultArray($queryStr); - if (is_bool($res) && !$res) - return false; - - $statusID = $res[0]['statusID']; - - $db->startTransaction(); - - /* First, remove the old entries */ - $queryStr = "DELETE FROM `tblDocumentStatusLog` WHERE `statusID`=".$statusID; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - /* Second, insert the new entries */ - $statuslog = array_reverse($statuslog); - foreach($statuslog as $log) { - if(!SeedDMS_Core_DMS::checkDate($log['date'], 'Y-m-d H:i:s')) { - $db->rollbackTransaction(); - return false; - } - $queryStr = "INSERT INTO `tblDocumentStatusLog` (`statusID`, `status`, `comment`, `date`, `userID`) ". - "VALUES ('".$statusID ."', '".(int) $log['status']."', ".$db->qstr($log['comment']) .", ".$db->qstr($log['date']).", ".$log['user']->getID().")"; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - } - - $db->commitTransaction(); - return true; - } /* }}} */ - - - /** - * Returns the access mode similar to a document - * - * There is no real access mode for document content, so this is more - * like a virtual access mode, derived from the status of the document - * content. The function checks if {@link SeedDMS_Core_DMS::noReadForStatus} - * contains the status of the version and returns M_NONE if it exists and - * the user is not involved in a workflow or review/approval/revision. - * This method is called by all functions that returns the content e.g. - * {@link SeedDMS_Core_Document::getLatestContent()} - * It is also used by {@link SeedDMS_Core_Document::getAccessMode()} to - * prevent access on the whole document if there is no accessible version. - * - * FIXME: This function only works propperly if $u is the currently logged in - * user, because noReadForStatus will be set for this user. - * FIXED: instead of using $dms->noReadForStatus it is take from the user's role - * - * @param object $u user - * @return integer either M_NONE or M_READ - */ - function getAccessMode($u) { /* {{{ */ - $dms = $this->_document->getDMS(); - - /* Check if 'onCheckAccessDocumentContent' callback is set */ - if(isset($this->_dms->callbacks['onCheckAccessDocumentContent'])) { - foreach($this->_dms->callbacks['onCheckAccessDocumentContent'] as $callback) { - if(($ret = call_user_func($callback[0], $callback[1], $this, $u)) > 0) { - return $ret; - } - } - } - - return M_READ; - - if(!$u) - return M_NONE; - - /* If read access isn't further restricted by status, than grant read access */ - if(!$dms->noReadForStatus) - return M_READ; - $noReadForStatus = $dms->noReadForStatus; - - /* If the current status is not in list of status without read access, then grant read access */ - if(!in_array($this->getStatus()['status'], $noReadForStatus)) - return M_READ; - - /* Administrators have unrestricted access */ - if ($u->isAdmin()) return M_READ; - - /* The owner of the document has unrestricted access */ - $owner = $this->_document->getOwner(); - if ($u->getID() == $owner->getID()) return M_READ; - - /* Read/Write access on the document will also grant access on the version */ - if($this->_document->getAccessMode($u) >= M_READWRITE) return M_READ; - - /* At this point the current status is in the list of status without read access. - * The only way to still gain read access is, if the user is involved in the - * process, e.g. is a reviewer, approver or an active person in the workflow. - */ - $s = $this->getStatus(); - switch($s['status']) { - case S_DRAFT_REV: - $status = $this->getReviewStatus(); - foreach ($status as $r) { - if($r['status'] != -2) // Check if reviewer was removed - switch ($r["type"]) { - case 0: // Reviewer is an individual. - if($u->getId() == $r["required"]) - return M_READ; - break; - case 1: // Reviewer is a group. - $required = $dms->getGroup($r["required"]); - if (is_object($required) && $required->isMember($u)) - return M_READ; - break; - } - } - break; - case S_DRAFT_APP: - $status = $this->getApprovalStatus(); - foreach ($status as $r) { - if($r['status'] != -2) // Check if approver was removed - switch ($r["type"]) { - case 0: // Reviewer is an individual. - if($u->getId() == $r["required"]) - return M_READ; - break; - case 1: // Reviewer is a group. - $required = $dms->getGroup($r["required"]); - if (is_object($required) && $required->isMember($u)) - return M_READ; - break; - } - } - break; - case S_RELEASED: - break; - case S_IN_WORKFLOW: - if(!$this->_workflow) - $this->getWorkflow(); - - if($this->_workflow) { - if (!$this->_workflowState) - $this->getWorkflowState(); - $transitions = $this->_workflow->getNextTransitions($this->_workflowState); - foreach($transitions as $transition) { - if($this->triggerWorkflowTransitionIsAllowed($u, $transition)) - return M_READ; - } - } - break; - case S_REJECTED: - break; - case S_OBSOLETE: - break; - case S_EXPIRED: - break; - } - - return M_NONE; - } /* }}} */ - - /** - * Return a list of all reviewers separated by individuals and groups - * This list will not take the review log into account. Therefore it - * can contain which has actually been deleted as a reviewer. - * - * @return array|bool|null - */ - function getReviewers() { /* {{{ */ - $dms = $this->_document->getDMS(); - $db = $dms->getDB(); - - $queryStr= - "SELECT * FROM `tblDocumentReviewers` WHERE `version`='".$this->_version - ."' AND `documentID` = '". $this->_document->getID() ."' "; - - $recs = $db->getResultArray($queryStr); - if (is_bool($recs)) - return false; - $reviewers = array('i'=>array(), 'g'=>array()); - foreach($recs as $rec) { - if($rec['type'] == 0) { - if($u = $dms->getUser($rec['required'])) - $reviewers['i'][] = $u; - } elseif($rec['type'] == 1) { - if($g = $dms->getGroup($rec['required'])) - $reviewers['g'][] = $g; - } - } - return $reviewers; - } /* }}} */ - - /** - * Get the current review status of the document content - * The review status is a list of reviewers and its current status - * - * @param integer $limit the number of recent status changes per reviewer - * @return array list of review status - */ - function getReviewStatus($limit=1) { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - if (!is_numeric($limit)) return false; - - // Retrieve the current status of each assigned reviewer for the content - // represented by this object. - // FIXME: caching was turned off to make list of review log in ViewDocument - // possible - if (1 || !isset($this->_reviewStatus)) { - /* First get a list of all reviews for this document content */ - $queryStr= - "SELECT `reviewID` FROM `tblDocumentReviewers` WHERE `version`='".$this->_version - ."' AND `documentID` = '". $this->_document->getID() ."' "; - $recs = $db->getResultArray($queryStr); - if (is_bool($recs) && !$recs) - return false; - $this->_reviewStatus = array(); - if($recs) { - foreach($recs as $rec) { - $queryStr= - "SELECT `tblDocumentReviewers`.*, `tblDocumentReviewLog`.`reviewLogID`, `tblDocumentReviewLog`.`status`, ". - "`tblDocumentReviewLog`.`comment`, `tblDocumentReviewLog`.`date`, ". - "`tblDocumentReviewLog`.`userID`, `tblUsers`.`fullName`, `tblGroups`.`name` AS `groupName` ". - "FROM `tblDocumentReviewers` ". - "LEFT JOIN `tblDocumentReviewLog` USING (`reviewID`) ". - "LEFT JOIN `tblUsers` on `tblUsers`.`id` = `tblDocumentReviewers`.`required`". - "LEFT JOIN `tblGroups` on `tblGroups`.`id` = `tblDocumentReviewers`.`required`". - "WHERE `tblDocumentReviewers`.`reviewID` = '". $rec['reviewID'] ."' ". - "ORDER BY `tblDocumentReviewLog`.`reviewLogID` DESC LIMIT ".(int) $limit; - - $res = $db->getResultArray($queryStr); - if (is_bool($res) && !$res) { - unset($this->_reviewStatus); - return false; - } - foreach($res as &$t) { - $filename = $this->_dms->contentDir . $this->_document->getDir().'r'.$t['reviewLogID']; - if(SeedDMS_Core_File::file_exists($filename)) - $t['file'] = $filename; - else - $t['file'] = ''; - } - $this->_reviewStatus = array_merge($this->_reviewStatus, $res); - } - } - } - return $this->_reviewStatus; - } /* }}} */ - - /** - * Get the latest entries from the review log of the document content - * - * @param integer $limit the number of log entries returned, defaults to 1 - * @return array list of review log entries - */ - function getReviewLog($limit=1) { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - if (!is_numeric($limit)) return false; - - $queryStr= - "SELECT * FROM `tblDocumentReviewLog` LEFT JOIN `tblDocumentReviewers` ON `tblDocumentReviewLog`.`reviewID` = `tblDocumentReviewers`.`reviewID` WHERE `version`='".$this->_version - ."' AND `documentID` = '". $this->_document->getID() ."' " - ."ORDER BY `tblDocumentReviewLog`.`reviewLogID` DESC LIMIT ".(int) $limit; - $recs = $db->getResultArray($queryStr); - if (is_bool($recs) && !$recs) - return false; - return($recs); - } /* }}} */ - - /** - * Rewrites the complete review log - * - * Attention: this function is highly dangerous. - * It removes an existing review log and rewrites it. - * This method was added for importing an xml dump. - * - * @param array $reviewlog new status log with the newest log entry first. - * @return boolean true on success, otherwise false - */ - function rewriteReviewLog($reviewers) { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - $queryStr= "SELECT `tblDocumentReviewers`.* FROM `tblDocumentReviewers` WHERE `tblDocumentReviewers`.`documentID` = '". $this->_document->getID() ."' AND `tblDocumentReviewers`.`version` = '". $this->_version ."' "; - $res = $db->getResultArray($queryStr); - if (is_bool($res) && !$res) - return false; - - $db->startTransaction(); - - if($res) { - foreach($res as $review) { - $reviewID = $review['reviewID']; - - /* First, remove the old entries */ - $queryStr = "DELETE FROM `tblDocumentReviewLog` WHERE `reviewID`=".$reviewID; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - $queryStr = "DELETE FROM `tblDocumentReviewers` WHERE `reviewID`=".$reviewID; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - } - } - - /* Second, insert the new entries */ - foreach($reviewers as $review) { - $queryStr = "INSERT INTO `tblDocumentReviewers` (`documentID`, `version`, `type`, `required`) ". - "VALUES ('".$this->_document->getID()."', '".$this->_version."', ".$review['type'] .", ".(is_object($review['required']) ? $review['required']->getID() : (int) $review['required']).")"; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - $reviewID = $db->getInsertID('tblDocumentReviewers', 'reviewID'); - $reviewlog = array_reverse($review['logs']); - foreach($reviewlog as $log) { - if(!SeedDMS_Core_DMS::checkDate($log['date'], 'Y-m-d H:i:s')) { - $db->rollbackTransaction(); - return false; - } - $queryStr = "INSERT INTO `tblDocumentReviewLog` (`reviewID`, `status`, `comment`, `date`, `userID`) ". - "VALUES ('".$reviewID ."', '".(int) $log['status']."', ".$db->qstr($log['comment']) .", ".$db->qstr($log['date']).", ".(is_object($log['user']) ? $log['user']->getID() : (int) $log['user']).")"; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - $reviewLogID = $db->getInsertID('tblDocumentReviewLog', 'reviewLogID'); - if(!empty($log['file'])) { - SeedDMS_Core_File::copyFile($log['file'], $this->_dms->contentDir . $this->_document->getDir() . 'r' . $reviewLogID); - } - } - } - - $db->commitTransaction(); - return true; - } /* }}} */ - - /** - * Return a list of all approvers separated by individuals and groups - * This list will not take the approval log into account. Therefore it - * can contain which has actually been deleted as an approver. - * - * @return array|bool|null - */ - function getApprovers() { /* {{{ */ - $dms = $this->_document->getDMS(); - $db = $dms->getDB(); - - $queryStr= - "SELECT * FROM `tblDocumentApprovers` WHERE `version`='".$this->_version - ."' AND `documentID` = '". $this->_document->getID() ."' "; - - $recs = $db->getResultArray($queryStr); - if (is_bool($recs)) - return false; - $approvers = array('i'=>array(), 'g'=>array()); - foreach($recs as $rec) { - if($rec['type'] == 0) { - if($u = $dms->getUser($rec['required'])) - $approvers['i'][] = $u; - } elseif($rec['type'] == 1) { - if($g = $dms->getGroup($rec['required'])) - $approvers['g'][] = $g; - } - } - return $approvers; - } /* }}} */ - - /** - * Get the current approval status of the document content - * The approval status is a list of approvers and its current status - * - * @param integer $limit the number of recent status changes per approver - * @return array list of approval status - */ - function getApprovalStatus($limit=1) { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - if (!is_numeric($limit)) return false; - - // Retrieve the current status of each assigned approver for the content - // represented by this object. - // FIXME: caching was turned off to make list of approval log in ViewDocument - // possible - if (1 || !isset($this->_approvalStatus)) { - /* First get a list of all approvals for this document content */ - $queryStr= - "SELECT `approveID` FROM `tblDocumentApprovers` WHERE `version`='".$this->_version - ."' AND `documentID` = '". $this->_document->getID() ."' "; - $recs = $db->getResultArray($queryStr); - if (is_bool($recs) && !$recs) - return false; - $this->_approvalStatus = array(); - if($recs) { - foreach($recs as $rec) { - $queryStr= - "SELECT `tblDocumentApprovers`.*, `tblDocumentApproveLog`.`approveLogID`, `tblDocumentApproveLog`.`status`, ". - "`tblDocumentApproveLog`.`comment`, `tblDocumentApproveLog`.`date`, ". - "`tblDocumentApproveLog`.`userID`, `tblUsers`.`fullName`, `tblGroups`.`name` AS `groupName` ". - "FROM `tblDocumentApprovers` ". - "LEFT JOIN `tblDocumentApproveLog` USING (`approveID`) ". - "LEFT JOIN `tblUsers` on `tblUsers`.`id` = `tblDocumentApprovers`.`required` ". - "LEFT JOIN `tblGroups` on `tblGroups`.`id` = `tblDocumentApprovers`.`required`". - "WHERE `tblDocumentApprovers`.`approveID` = '". $rec['approveID'] ."' ". - "ORDER BY `tblDocumentApproveLog`.`approveLogID` DESC LIMIT ".(int) $limit; - - $res = $db->getResultArray($queryStr); - if (is_bool($res) && !$res) { - unset($this->_approvalStatus); - return false; - } - foreach($res as &$t) { - $filename = $this->_dms->contentDir . $this->_document->getDir().'a'.$t['approveLogID']; - if(SeedDMS_Core_File::file_exists($filename)) - $t['file'] = $filename; - else - $t['file'] = ''; - } - $this->_approvalStatus = array_merge($this->_approvalStatus, $res); - } - } - } - return $this->_approvalStatus; - } /* }}} */ - - /** - * Get the latest entries from the approval log of the document content - * - * @param integer $limit the number of log entries returned, defaults to 1 - * @return array list of approval log entries - */ - function getApproveLog($limit=1) { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - if (!is_numeric($limit)) return false; - - $queryStr= - "SELECT * FROM `tblDocumentApproveLog` LEFT JOIN `tblDocumentApprovers` ON `tblDocumentApproveLog`.`approveID` = `tblDocumentApprovers`.`approveID` WHERE `version`='".$this->_version - ."' AND `documentID` = '". $this->_document->getID() ."' " - ."ORDER BY `tblDocumentApproveLog`.`approveLogID` DESC LIMIT ".(int) $limit; - $recs = $db->getResultArray($queryStr); - if (is_bool($recs) && !$recs) - return false; - return($recs); - } /* }}} */ - - /** - * Rewrites the complete approval log - * - * Attention: this function is highly dangerous. - * It removes an existing review log and rewrites it. - * This method was added for importing an xml dump. - * - * @param array $reviewlog new status log with the newest log entry first. - * @return boolean true on success, otherwise false - */ - function rewriteApprovalLog($reviewers) { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - $queryStr= "SELECT `tblDocumentApprovers`.* FROM `tblDocumentApprovers` WHERE `tblDocumentApprovers`.`documentID` = '". $this->_document->getID() ."' AND `tblDocumentApprovers`.`version` = '". $this->_version ."' "; - $res = $db->getResultArray($queryStr); - if (is_bool($res) && !$res) - return false; - - $db->startTransaction(); - - if($res) { - foreach($res as $review) { - $reviewID = $review['reviewID']; - - /* First, remove the old entries */ - $queryStr = "DELETE FROM `tblDocumentApproveLog` WHERE `approveID`=".$reviewID; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - $queryStr = "DELETE FROM `tblDocumentApprovers` WHERE `approveID`=".$reviewID; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - } - } - - /* Second, insert the new entries */ - foreach($reviewers as $review) { - $queryStr = "INSERT INTO `tblDocumentApprovers` (`documentID`, `version`, `type`, `required`) ". - "VALUES ('".$this->_document->getID()."', '".$this->_version."', ".$review['type'] .", ".(is_object($review['required']) ? $review['required']->getID() : (int) $review['required']).")"; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - $reviewID = $db->getInsertID('tblDocumentApprovers', 'approveID'); - $reviewlog = array_reverse($review['logs']); - foreach($reviewlog as $log) { - if(!SeedDMS_Core_DMS::checkDate($log['date'], 'Y-m-d H:i:s')) { - $db->rollbackTransaction(); - return false; - } - $queryStr = "INSERT INTO `tblDocumentApproveLog` (`approveID`, `status`, `comment`, `date`, `userID`) ". - "VALUES ('".$reviewID ."', '".(int) $log['status']."', ".$db->qstr($log['comment']) .", ".$db->qstr($log['date']).", ".(is_object($log['user']) ? $log['user']->getID() : (int) $log['user']).")"; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - $approveLogID = $db->getInsertID('tblDocumentApproveLog', 'approveLogID'); - if(!empty($log['file'])) { - SeedDMS_Core_File::copyFile($log['file'], $this->_dms->contentDir . $this->_document->getDir() . 'a' . $approveLogID); - } - } - } - - $db->commitTransaction(); - return true; - } /* }}} */ - - /** - * Add user as new reviewer - * - * @param object $user user in charge for the review - * @param object $requestUser user requesting the operation (usually the - * currently logged in user) - * - * @return integer|false if > 0 the id of the review log, if < 0 the error - * code, false in case of an sql error - */ - function addIndReviewer($user, $requestUser) { /* {{{ */ - if(!$user || !$requestUser) - return -1; - - $db = $this->_document->getDMS()->getDB(); - - if(!$user->isType('user')) - return -1; - - $userID = $user->getID(); - - // Get the list of users and groups with read access to this document. - if($this->_document->getAccessMode($user) < M_READ) { - return -2; - } - - // Check to see if the user has already been added to the review list. - $reviewStatus = $user->getReviewStatus($this->_document->getID(), $this->_version); - if (is_bool($reviewStatus) && !$reviewStatus) { - return false; - } - $indstatus = false; - if (count($reviewStatus["indstatus"]) > 0) { - $indstatus = array_pop($reviewStatus["indstatus"]); - if($indstatus["status"]!=-2) { - // User is already on the list of reviewers; return an error. - return -3; - } - } - - // Add the user into the review database. - if (!$indstatus || ($indstatus && $indstatus["status"]!=-2)) { - $queryStr = "INSERT INTO `tblDocumentReviewers` (`documentID`, `version`, `type`, `required`) ". - "VALUES ('". $this->_document->getID() ."', '". $this->_version ."', '0', '". $userID ."')"; - $res = $db->getResult($queryStr); - if (is_bool($res) && !$res) { - return false; - } - $reviewID = $db->getInsertID('tblDocumentReviewers', 'reviewID'); - } - else { - $reviewID = isset($indstatus["reviewID"]) ? $indstatus["reviewID"] : NULL; - } - - $queryStr = "INSERT INTO `tblDocumentReviewLog` (`reviewID`, `status`, `comment`, `date`, `userID`) ". - "VALUES ('". $reviewID ."', '0', '', ".$db->getCurrentDatetime().", '". $requestUser->getID() ."')"; - $res = $db->getResult($queryStr); - if (is_bool($res) && !$res) { - return false; - } - - $reviewLogID = $db->getInsertID('tblDocumentReviewLog', 'reviewLogID'); - $db->dropTemporaryTable('ttreviewid'); - return $reviewLogID; - } /* }}} */ - - /** - * Add group as new reviewer - * - * @param object $group group in charge for the review - * @param object $requestUser user requesting the operation (usually the - * currently logged in user) - * - * @return integer|false if > 0 the id of the review log, if < 0 the error - * code, false in case of an sql error - */ - function addGrpReviewer($group, $requestUser) { /* {{{ */ - if(!$group || !$requestUser) - return -1; - - $db = $this->_document->getDMS()->getDB(); - - if(!$group->isType('group')) - return -1; - - $groupID = $group->getID(); - - // Get the list of users and groups with read access to this document. - if (!isset($this->_readAccessList)) { - // TODO: error checking. - $this->_readAccessList = $this->_document->getReadAccessList(); - } - $approved = false; - foreach ($this->_readAccessList["groups"] as $appGroup) { - if ($groupID == $appGroup->getID()) { - $approved = true; - break; - } - } - if (!$approved) { - return -2; - } - - // Check to see if the group has already been added to the review list. - $reviewStatus = $group->getReviewStatus($this->_document->getID(), $this->_version); - if (is_bool($reviewStatus) && !$reviewStatus) { - return false; - } - if (count($reviewStatus) > 0 && $reviewStatus[0]["status"]!=-2) { - // Group is already on the list of reviewers; return an error. - return -3; - } - - // Add the group into the review database. - if (!isset($reviewStatus[0]["status"]) || (isset($reviewStatus[0]["status"]) && $reviewStatus[0]["status"]!=-2)) { - $queryStr = "INSERT INTO `tblDocumentReviewers` (`documentID`, `version`, `type`, `required`) ". - "VALUES ('". $this->_document->getID() ."', '". $this->_version ."', '1', '". $groupID ."')"; - $res = $db->getResult($queryStr); - if (is_bool($res) && !$res) { - return false; - } - $reviewID = $db->getInsertID('tblDocumentReviewers', 'reviewID'); - } - else { - $reviewID = isset($reviewStatus[0]["reviewID"])?$reviewStatus[0]["reviewID"]:NULL; - } - - $queryStr = "INSERT INTO `tblDocumentReviewLog` (`reviewID`, `status`, `comment`, `date`, `userID`) ". - "VALUES ('". $reviewID ."', '0', '', ".$db->getCurrentDatetime().", '". $requestUser->getID() ."')"; - $res = $db->getResult($queryStr); - if (is_bool($res) && !$res) { - return false; - } - - $reviewLogID = $db->getInsertID('tblDocumentReviewLog', 'reviewLogID'); - $db->dropTemporaryTable('ttreviewid'); - return $reviewLogID; - } /* }}} */ - - /** - * Add a review to the document content - * - * This method will add an entry to the table tblDocumentReviewLog. - * It will first check if the user is ment to review the document version. - * It not the return value is -3. - * Next it will check if the users has been removed from the list of - * reviewers. In that case -4 will be returned. - * If the given review status has been set by the user before, it cannot - * be set again and 0 will be returned. Іf the review could be succesfully - * added, the review log id will be returned. - * - * @see SeedDMS_Core_DocumentContent::setApprovalByInd() - * - * @param object $user user doing the review - * @param object $requestUser user asking for the review, this is mostly - * the user currently logged in. - * @param integer $status status of review - * @param string $comment comment for review - * - * @return integer|bool new review log id, error code 0 till -4, - * false in case of an sql error - */ - function setReviewByInd($user, $requestUser, $status, $comment, $file='') { /* {{{ */ - if(!$user || !$requestUser) - return -1; - - $db = $this->_document->getDMS()->getDB(); - - if(!$user->isType('user')) - return -1; - - // Check if the user is on the review list at all. - $reviewStatus = $user->getReviewStatus($this->_document->getID(), $this->_version); - if (is_bool($reviewStatus) && !$reviewStatus) { - return false; - } - if (count($reviewStatus["indstatus"])==0) { - // User is not assigned to review this document. No action required. - // Return an error. - return -3; - } - $indstatus = array_pop($reviewStatus["indstatus"]); - if ($indstatus["status"]==-2) { - // User has been deleted from reviewers - return -4; - } - // Check if the status is really different from the current status - if ($indstatus["status"] == $status) - return 0; - - $queryStr = "INSERT INTO `tblDocumentReviewLog` (`reviewID`, `status`, - `comment`, `date`, `userID`) ". - "VALUES ('". $indstatus["reviewID"] ."', '". - (int) $status ."', ".$db->qstr($comment).", ".$db->getCurrentDatetime().", '". - $requestUser->getID() ."')"; - $res=$db->getResult($queryStr); - if (is_bool($res) && !$res) - return false; - - $reviewLogID = $db->getInsertID('tblDocumentReviewLog', 'reviewLogID'); - if($file) { - SeedDMS_Core_File::copyFile($file, $this->_dms->contentDir . $this->_document->getDir() . 'r' . $reviewLogID); - } - return $reviewLogID; - } /* }}} */ - - /** - * Add another entry to review log which resets the status - * - * This method will not delete anything from the database, but will add - * a new review log entry which sets the status to 0. This is only allowed - * if the current status is either 1 (reviewed) or -1 (rejected). - * - * After calling this method SeedDMS_Core_DocumentCategory::verifyStatus() - * should be called to recalculate the document status. - * - * @param integer $reviewid id of review - * @param SeedDMS_Core_User $requestUser user requesting the removal - * @param string $comment comment - * - * @return integer|bool true if successful, error code < 0, - * false in case of an sql error - */ - public function removeReview($reviewid, $requestUser, $comment='') { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - // Check to see if the user can be removed from the review list. - $reviews = $this->getReviewStatus(); - if (is_bool($reviews) && !$reviews) { - return false; - } - $reviewStatus = null; - foreach($reviews as $review) { - if($review['reviewID'] == $reviewid) { - $reviewStatus = $review; - break; - } - } - if(!$reviewStatus) - return -2; - - // The review log entry may only be removed if the status is 1 or -1 - if ($reviewStatus["status"] != 1 && $reviewStatus["status"] != -1) - return -3; - - $queryStr = "INSERT INTO `tblDocumentReviewLog` (`reviewID`, `status`, - `comment`, `date`, `userID`) ". - "VALUES ('". $reviewStatus["reviewID"] ."', '0', ".$db->qstr($comment).", ".$db->getCurrentDatetime().", '". - $requestUser->getID() ."')"; - $res=$db->getResult($queryStr); - if (is_bool($res) && !$res) - return false; - - return true; - } /* }}} */ - - /** - * Add a review to the document content - * - * This method is similar to - * {@see SeedDMS_Core_DocumentContent::setReviewByInd()} but adds a review - * for a group instead of a user. - * - * @param object $group group doing the review - * @param object $requestUser user asking for the review, this is mostly - * the user currently logged in. - * @param integer $status status of review - * @param string $comment comment for review - * - * @return integer|bool new review log id, error code 0 till -4, - * false in case of an sql error - */ - function setReviewByGrp($group, $requestUser, $status, $comment, $file='') { /* {{{ */ - if(!$group || !$requestUser) - return -1; - - $db = $this->_document->getDMS()->getDB(); - - if(!$group->isType('group')) - return -1; - - // Check if the group is on the review list at all. - $reviewStatus = $group->getReviewStatus($this->_document->getID(), $this->_version); - if (is_bool($reviewStatus) && !$reviewStatus) { - return false; - } - if (count($reviewStatus)==0) { - // User is not assigned to review this document. No action required. - // Return an error. - return -3; - } - if ((int) $reviewStatus[0]["status"]==-2) { - // Group has been deleted from reviewers - return -4; - } - - // Check if the status is really different from the current status - if ($reviewStatus[0]["status"] == $status) - return 0; - - $queryStr = "INSERT INTO `tblDocumentReviewLog` (`reviewID`, `status`, - `comment`, `date`, `userID`) ". - "VALUES ('". $reviewStatus[0]["reviewID"] ."', '". - (int) $status ."', ".$db->qstr($comment).", ".$db->getCurrentDatetime().", '". - $requestUser->getID() ."')"; - $res=$db->getResult($queryStr); - if (is_bool($res) && !$res) - return false; - - $reviewLogID = $db->getInsertID('tblDocumentReviewLog', 'reviewLogID'); - if($file) { - SeedDMS_Core_File::copyFile($file, $this->_dms->contentDir . $this->_document->getDir() . 'r' . $reviewLogID); - } - return $reviewLogID; - } /* }}} */ - - /** - * Add user as new approver - * - * @param object $user user in charge for the approval - * @param object $requestUser user requesting the operation (usually the - * currently logged in user) - * - * @return integer|false if > 0 the id of the approval log, if < 0 the error - * code, false in case of an sql error - */ - function addIndApprover($user, $requestUser) { /* {{{ */ - if(!$user || !$requestUser) - return -1; - - $db = $this->_document->getDMS()->getDB(); - - if(!$user->isType('user')) - return -1; - - $userID = $user->getID(); - - // Get the list of users and groups with read access to this document. - if($this->_document->getAccessMode($user) < M_READ) { - return -2; - } - - // Check if the user has already been added to the approvers list. - $approvalStatus = $user->getApprovalStatus($this->_document->getID(), $this->_version); - if (is_bool($approvalStatus) && !$approvalStatus) { - return false; - } - $indstatus = false; - if (count($approvalStatus["indstatus"]) > 0) { - $indstatus = array_pop($approvalStatus["indstatus"]); - if($indstatus["status"]!=-2) { - // User is already on the list of approverss; return an error. - return -3; - } - } - - if ( !$indstatus || (isset($indstatus["status"]) && $indstatus["status"]!=-2)) { - // Add the user into the approvers database. - $queryStr = "INSERT INTO `tblDocumentApprovers` (`documentID`, `version`, `type`, `required`) ". - "VALUES ('". $this->_document->getID() ."', '". $this->_version ."', '0', '". $userID ."')"; - $res = $db->getResult($queryStr); - if (is_bool($res) && !$res) { - return false; - } - $approveID = $db->getInsertID('tblDocumentApprovers', 'approveID'); - } - else { - $approveID = isset($indstatus["approveID"]) ? $indstatus["approveID"] : NULL; - } - - $queryStr = "INSERT INTO `tblDocumentApproveLog` (`approveID`, `status`, `comment`, `date`, `userID`) ". - "VALUES ('". $approveID ."', '0', '', ".$db->getCurrentDatetime().", '". $requestUser->getID() ."')"; - $res = $db->getResult($queryStr); - if (is_bool($res) && !$res) { - return false; - } - - $approveLogID = $db->getInsertID('tblDocumentApproveLog', 'approveLogID'); - $db->dropTemporaryTable('ttapproveid'); - return $approveLogID; - } /* }}} */ - - /** - * Add group as new approver - * - * @param object $group group in charge for the approval - * @param object $requestUser user requesting the operation (usually the - * currently logged in user) - * - * @return integer|false if > 0 the id of the approval log, if < 0 the error - * code, false in case of an sql error - */ - function addGrpApprover($group, $requestUser) { /* {{{ */ - if(!$group || !$requestUser) - return -1; - - $db = $this->_document->getDMS()->getDB(); - - if(!$group->isType('group')) - return -1; - - $groupID = $group->getID(); - - // Get the list of users and groups with read access to this document. - if (!isset($this->_readAccessList)) { - // TODO: error checking. - $this->_readAccessList = $this->_document->getReadAccessList(); - } - $approved = false; - foreach ($this->_readAccessList["groups"] as $appGroup) { - if ($groupID == $appGroup->getID()) { - $approved = true; - break; - } - } - if (!$approved) { - return -2; - } - - // Check if the group has already been added to the approver list. - $approvalStatus = $group->getApprovalStatus($this->_document->getID(), $this->_version); - if (is_bool($approvalStatus) && !$approvalStatus) { - return false; - } - if (count($approvalStatus) > 0 && $approvalStatus[0]["status"]!=-2) { - // Group is already on the list of approvers; return an error. - return -3; - } - - // Add the group into the approver database. - if (!isset($approvalStatus[0]["status"]) || (isset($approvalStatus[0]["status"]) && $approvalStatus[0]["status"]!=-2)) { - $queryStr = "INSERT INTO `tblDocumentApprovers` (`documentID`, `version`, `type`, `required`) ". - "VALUES ('". $this->_document->getID() ."', '". $this->_version ."', '1', '". $groupID ."')"; - $res = $db->getResult($queryStr); - if (is_bool($res) && !$res) { - return false; - } - $approveID = $db->getInsertID('tblDocumentApprovers', 'approveID'); - } - else { - $approveID = isset($approvalStatus[0]["approveID"])?$approvalStatus[0]["approveID"]:NULL; - } - - $queryStr = "INSERT INTO `tblDocumentApproveLog` (`approveID`, `status`, `comment`, `date`, `userID`) ". - "VALUES ('". $approveID ."', '0', '', ".$db->getCurrentDatetime().", '". $requestUser->getID() ."')"; - $res = $db->getResult($queryStr); - if (is_bool($res) && !$res) { - return false; - } - - $approveLogID = $db->getInsertID('tblDocumentApproveLog', 'approveLogID'); - $db->dropTemporaryTable('ttapproveid'); - return $approveLogID; - } /* }}} */ - - /** - * Sets approval status of a document content for a user - * - * This function can be used to approve or reject a document content, or - * to reset its approval state. In most cases this function will be - * called by an user, but an admin may set the approval for - * somebody else. - * It is first checked if the user is in the list of approvers at all. - * Then it is check if the approval status is already -2. In both cases - * the function returns with an error. - * - * @see SeedDMS_Core_DocumentContent::setReviewByInd() - * - * @param object $user user in charge for doing the approval - * @param object $requestUser user actually calling this function - * @param integer $status the status of the approval, possible values are - * 0=unprocessed (maybe used to reset a status) - * 1=approved, - * -1=rejected, - * -2=user is deleted (use {link - * SeedDMS_Core_DocumentContent::delIndApprover} instead) - * @param string $comment approval comment - * - * @return integer|bool new review log id, error code 0 till -4, - * false in case of an sql error - */ - function setApprovalByInd($user, $requestUser, $status, $comment, $file='') { /* {{{ */ - if(!$user || !$requestUser) - return -1; - - $db = $this->_document->getDMS()->getDB(); - - if(!$user->isType('user')) - return -1; - - // Check if the user is on the approval list at all. - $approvalStatus = $user->getApprovalStatus($this->_document->getID(), $this->_version); - if (is_bool($approvalStatus) && !$approvalStatus) { - return false; - } - if (count($approvalStatus["indstatus"])==0) { - // User is not assigned to approve this document. No action required. - // Return an error. - return -3; - } - $indstatus = array_pop($approvalStatus["indstatus"]); - if ($indstatus["status"]==-2) { - // User has been deleted from approvers - return -4; - } - // Check if the status is really different from the current status - if ($indstatus["status"] == $status) - return 0; - - $queryStr = "INSERT INTO `tblDocumentApproveLog` (`approveID`, `status`, - `comment`, `date`, `userID`) ". - "VALUES ('". $indstatus["approveID"] ."', '". - (int) $status ."', ".$db->qstr($comment).", ".$db->getCurrentDatetime().", '". - $requestUser->getID() ."')"; - $res=$db->getResult($queryStr); - if (is_bool($res) && !$res) - return false; - - $approveLogID = $db->getInsertID('tblDocumentApproveLog', 'approveLogID'); - if($file) { - SeedDMS_Core_File::copyFile($file, $this->_dms->contentDir . $this->_document->getDir() . 'a' . $approveLogID); - } - return $approveLogID; - } /* }}} */ - - /** - * Add another entry to approval log which resets the status - * - * This method will not delete anything from the database, but will add - * a new approval log entry which sets the status to 0. This is only allowed - * if the current status is either 1 (approved) or -1 (rejected). - * - * After calling this method SeedDMS_Core_DocumentCategory::verifyStatus() - * should be called to recalculate the document status. - * - * @param integer $approveid id of approval - * @param SeedDMS_Core_User $requestUser user requesting the removal - * @param string $comment comment - * - * @return integer|bool true if successful, error code < 0, - * false in case of an sql error - */ - public function removeApproval($approveid, $requestUser, $comment='') { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - // Check to see if the user can be removed from the approval list. - $approvals = $this->getApprovalStatus(); - if (is_bool($approvals) && !$approvals) { - return false; - } - $approvalStatus = null; - foreach($approvals as $approval) { - if($approval['approveID'] == $approveid) { - $approvalStatus = $approval; - break; - } - } - if(!$approvalStatus) - return -2; - - // The approval log entry may only be removed if the status is 1 or -1 - if ($approvalStatus["status"] != 1 && $approvalStatus["status"] != -1) - return -3; - - $queryStr = "INSERT INTO `tblDocumentApproveLog` (`approveID`, `status`, - `comment`, `date`, `userID`) ". - "VALUES ('". $approvalStatus["approveID"] ."', '0', ".$db->qstr($comment).", ".$db->getCurrentDatetime().", '". - $requestUser->getID() ."')"; - $res=$db->getResult($queryStr); - if (is_bool($res) && !$res) - return false; - - return true; - } /* }}} */ - - /** - * Sets approval status of a document content for a group - * - * The functions behaves like - * {link SeedDMS_Core_DocumentContent::setApprovalByInd} but does it for - * a group instead of a user - */ - function setApprovalByGrp($group, $requestUser, $status, $comment, $file='') { /* {{{ */ - if(!$group || !$requestUser) - return -1; - - $db = $this->_document->getDMS()->getDB(); - - if(!$group->isType('group')) - return -1; - - // Check if the group is on the approval list at all. - $approvalStatus = $group->getApprovalStatus($this->_document->getID(), $this->_version); - if (is_bool($approvalStatus) && !$approvalStatus) { - return false; - } - if (count($approvalStatus)==0) { - // User is not assigned to approve this document. No action required. - // Return an error. - return -3; - } - if ($approvalStatus[0]["status"]==-2) { - // Group has been deleted from approvers - return -4; - } - - // Check if the status is really different from the current status - if ($approvalStatus[0]["status"] == $status) - return 0; - - $queryStr = "INSERT INTO `tblDocumentApproveLog` (`approveID`, `status`, - `comment`, `date`, `userID`) ". - "VALUES ('". $approvalStatus[0]["approveID"] ."', '". - (int) $status ."', ".$db->qstr($comment).", ".$db->getCurrentDatetime().", '". - $requestUser->getID() ."')"; - $res=$db->getResult($queryStr); - if (is_bool($res) && !$res) - return false; - - $approveLogID = $db->getInsertID('tblDocumentApproveLog', 'approveLogID'); - if($file) { - SeedDMS_Core_File::copyFile($file, $this->_dms->contentDir . $this->_document->getDir() . 'a' . $approveLogID); - } - return $approveLogID; - } /* }}} */ - - function delIndReviewer($user, $requestUser, $msg='') { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - if(!$user->isType('user')) - return -1; - - // Check to see if the user can be removed from the review list. - $reviewStatus = $user->getReviewStatus($this->_document->getID(), $this->_version); - if (is_bool($reviewStatus) && !$reviewStatus) { - return false; - } - if (count($reviewStatus["indstatus"])==0) { - // User is not assigned to review this document. No action required. - // Return an error. - return -2; - } - $indstatus = array_pop($reviewStatus["indstatus"]); - if ($indstatus["status"]!=0) { - // User has already submitted a review or has already been deleted; - // return an error. - return -3; - } - - $queryStr = "INSERT INTO `tblDocumentReviewLog` (`reviewID`, `status`, `comment`, `date`, `userID`) ". - "VALUES ('". $indstatus["reviewID"] ."', '".S_LOG_USER_REMOVED."', ".$db->qstr($msg).", ".$db->getCurrentDatetime().", '". $requestUser->getID() ."')"; - $res = $db->getResult($queryStr); - if (is_bool($res) && !$res) { - return false; - } - - return 0; - } /* }}} */ - - function delGrpReviewer($group, $requestUser, $msg='') { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - if(!$group->isType('group')) - return -1; - - $groupID = $group->getID(); - - // Check to see if the user can be removed from the review list. - $reviewStatus = $group->getReviewStatus($this->_document->getID(), $this->_version); - if (is_bool($reviewStatus) && !$reviewStatus) { - return false; - } - if (count($reviewStatus)==0) { - // User is not assigned to review this document. No action required. - // Return an error. - return -2; - } - if ($reviewStatus[0]["status"]!=0) { - // User has already submitted a review or has already been deleted; - // return an error. - return -3; - } - - $queryStr = "INSERT INTO `tblDocumentReviewLog` (`reviewID`, `status`, `comment`, `date`, `userID`) ". - "VALUES ('". $reviewStatus[0]["reviewID"] ."', '".S_LOG_USER_REMOVED."', ".$db->qstr($msg).", ".$db->getCurrentDatetime().", '". $requestUser->getID() ."')"; - $res = $db->getResult($queryStr); - if (is_bool($res) && !$res) { - return false; - } - - return 0; - } /* }}} */ - - function delIndApprover($user, $requestUser, $msg='') { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - if(!$user->isType('user')) - return -1; - - $userID = $user->getID(); - - // Check if the user is on the approval list at all. - $approvalStatus = $user->getApprovalStatus($this->_document->getID(), $this->_version); - if (is_bool($approvalStatus) && !$approvalStatus) { - return false; - } - if (count($approvalStatus["indstatus"])==0) { - // User is not assigned to approve this document. No action required. - // Return an error. - return -2; - } - $indstatus = array_pop($approvalStatus["indstatus"]); - if ($indstatus["status"]!=0) { - // User has already submitted an approval or has already been deleted; - // return an error. - return -3; - } - - $queryStr = "INSERT INTO `tblDocumentApproveLog` (`approveID`, `status`, `comment`, `date`, `userID`) ". - "VALUES ('". $indstatus["approveID"] ."', '".S_LOG_USER_REMOVED."', ".$db->qstr($msg).", ".$db->getCurrentDatetime().", '". $requestUser->getID() ."')"; - $res = $db->getResult($queryStr); - if (is_bool($res) && !$res) { - return false; - } - - return 0; - } /* }}} */ - - function delGrpApprover($group, $requestUser, $msg='') { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - if(!$group->isType('group')) - return -1; - - $groupID = $group->getID(); - - // Check if the group is on the approval list at all. - $approvalStatus = $group->getApprovalStatus($this->_document->getID(), $this->_version); - if (is_bool($approvalStatus) && !$approvalStatus) { - return false; - } - if (count($approvalStatus)==0) { - // User is not assigned to approve this document. No action required. - // Return an error. - return -2; - } - if ($approvalStatus[0]["status"]!=0) { - // User has already submitted an approval or has already been deleted; - // return an error. - return -3; - } - - $queryStr = "INSERT INTO `tblDocumentApproveLog` (`approveID`, `status`, `comment`, `date`, `userID`) ". - "VALUES ('". $approvalStatus[0]["approveID"] ."', '".S_LOG_USER_REMOVED."', ".$db->qstr($msg).", ".$db->getCurrentDatetime().", '". $requestUser->getID() ."')"; - $res = $db->getResult($queryStr); - if (is_bool($res) && !$res) { - return false; - } - - return 0; - } /* }}} */ - - /** - * Set state of workflow assigned to the document content - * - * @param object $state - */ - function setWorkflowState($state) { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - if($this->_workflow) { - $queryStr = "UPDATE `tblWorkflowDocumentContent` set `state`=". $state->getID() ." WHERE `workflow`=". intval($this->_workflow->getID()). " AND `document`=". intval($this->_document->getID()) ." AND version=". intval($this->_version) .""; - if (!$db->getResult($queryStr)) { - return false; - } - $this->_workflowState = $state; - return true; - } - return false; - } /* }}} */ - - /** - * Get state of workflow assigned to the document content - * - * @return object/boolean an object of class SeedDMS_Core_Workflow_State - * or false in case of error, e.g. the version has not a workflow - */ - function getWorkflowState() { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - if(!$this->_workflow) - $this->getWorkflow(); - - if(!$this->_workflow) - return false; - - if (!$this->_workflowState) { - $queryStr= - "SELECT b.* FROM `tblWorkflowDocumentContent` a LEFT JOIN `tblWorkflowStates` b ON a.`state` = b.`id` WHERE a.`state` IS NOT NULL AND `workflow`=". intval($this->_workflow->getID()) - ." AND a.`version`='".$this->_version - ."' AND a.`document` = '". $this->_document->getID() ."' "; - $recs = $db->getResultArray($queryStr); - if (!$recs) - return false; - $this->_workflowState = new SeedDMS_Core_Workflow_State($recs[0]['id'], $recs[0]['name'], $recs[0]['maxtime'], $recs[0]['precondfunc'], $recs[0]['documentstatus']); - $this->_workflowState->setDMS($this->_document->getDMS()); - } - return $this->_workflowState; - } /* }}} */ - - /** - * Assign a workflow to a document content - * - * @param object $workflow - */ - function setWorkflow($workflow, $user) { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - $this->getWorkflow(); - if($this->_workflow) - return false; - - if($workflow && is_object($workflow)) { - $db->startTransaction(); - $initstate = $workflow->getInitState(); - $queryStr = "INSERT INTO `tblWorkflowDocumentContent` (`workflow`, `document`, `version`, `state`, `date`) VALUES (". $workflow->getID(). ", ". $this->_document->getID() .", ". $this->_version .", ".$initstate->getID().", ".$db->getCurrentDatetime().")"; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - $this->_workflow = $workflow; - if(!$this->setStatus(S_IN_WORKFLOW, "Added workflow '".$workflow->getName()."'", $user)) { - $db->rollbackTransaction(); - return false; - } - $db->commitTransaction(); - return true; - } - return false; - } /* }}} */ - - /** - * Get workflow assigned to the document content - * - * The method returns the last workflow if one was assigned. - * If the document version is in a sub workflow, it will have - * a never date and therefore will be found first. - * - * @return object/boolean an object of class SeedDMS_Core_Workflow - * or false in case of error, e.g. the version has not a workflow - */ - function getWorkflow() { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - if (!$this->_workflow) { - $queryStr= - "SELECT b.* FROM `tblWorkflowDocumentContent` a LEFT JOIN `tblWorkflows` b ON a.`workflow` = b.`id` WHERE a.`version`='".$this->_version - ."' AND a.`document` = '". $this->_document->getID() ."' " - ." ORDER BY `date` DESC LIMIT 1"; - $recs = $db->getResultArray($queryStr); - if (is_bool($recs) && !$recs) - return false; - if(!$recs) - return false; - $this->_workflow = new SeedDMS_Core_Workflow($recs[0]['id'], $recs[0]['name'], $this->_document->getDMS()->getWorkflowState($recs[0]['initstate'])); - $this->_workflow->setDMS($this->_document->getDMS()); - } - return $this->_workflow; - } /* }}} */ - - /** - * Rewrites the complete workflow log - * - * Attention: this function is highly dangerous. - * It removes an existing workflow log and rewrites it. - * This method was added for importing an xml dump. - * - * @param array $workflowlog new workflow log with the newest log entry first. - * @return boolean true on success, otherwise false - */ - function rewriteWorkflowLog($workflowlog) { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - $db->startTransaction(); - - /* First, remove the old entries */ - $queryStr = "DELETE FROM `tblWorkflowLog` WHERE `tblWorkflowLog`.`document` = '". $this->_document->getID() ."' AND `tblWorkflowLog`.`version` = '". $this->_version ."'"; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - /* Second, insert the new entries */ - $workflowlog = array_reverse($workflowlog); - foreach($workflowlog as $log) { - if(!SeedDMS_Core_DMS::checkDate($log['date'], 'Y-m-d H:i:s')) { - $db->rollbackTransaction(); - return false; - } - $queryStr = "INSERT INTO `tblWorkflowLog` (`document`, `version`, `workflow`, `transition`, `comment`, `date`, `userid`) ". - "VALUES ('".$this->_document->getID() ."', '".(int) $this->_version."', '".(int) $log['workflow']->getID()."', '".(int) $log['transition']->getID()."', ".$db->qstr($log['comment']) .", ".$db->qstr($log['date']).", ".$log['user']->getID().")"; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - } - - $db->commitTransaction(); - return true; - } /* }}} */ - - /** - * Restart workflow from its initial state - * - * @return boolean true if workflow could be restarted - * or false in case of error - */ - function rewindWorkflow() { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - $this->getWorkflow(); - - if (!$this->_workflow) { - return true; - } - - $db->startTransaction(); - $queryStr = "DELETE from `tblWorkflowLog` WHERE `document` = ". $this->_document->getID() ." AND `version` = ".$this->_version." AND `workflow` = ".$this->_workflow->getID(); - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - $this->setWorkflowState($this->_workflow->getInitState()); - $db->commitTransaction(); - - return true; - } /* }}} */ - - /** - * Remove workflow - * - * Fully removing a workflow including entries in the workflow log is - * only allowed if the workflow is still its initial state. - * At a later point of time only unlinking the document from the - * workflow is allowed. It will keep any log entries. - * A workflow is unlinked from a document when enterNextState() - * succeeds. - * - * @param object $user user doing initiating the removal - * @param boolean $unlink if true, just unlink the workflow from the - * document but do not remove the workflow log. The $unlink - * flag has been added to detach the workflow from the document - * when it has reached a valid end state - (see SeedDMS_Core_DocumentContent::enterNextState()) - * @return boolean true if workflow could be removed - * or false in case of error - */ - function removeWorkflow($user, $unlink=false) { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - $this->getWorkflow(); - - if (!$this->_workflow) { - return true; - } - - /* A workflow should always be in a state, but in case it isn't, the - * at least allow to remove the workflow. - */ - $currentstate = $this->getWorkflowState(); - if(!$currentstate || SeedDMS_Core_DMS::checkIfEqual($this->_workflow->getInitState(), $currentstate) || $unlink == true) { - $db->startTransaction(); - if(!$unlink) { - $queryStr= - "DELETE FROM `tblWorkflowLog` WHERE " - ."`version`='".$this->_version."' " - ." AND `document` = '". $this->_document->getID() ."' " - ." AND `workflow` = '". $this->_workflow->getID() ."' "; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - } - $queryStr= - "DELETE FROM `tblWorkflowDocumentContent` WHERE " - ."`version`='".$this->_version."' " - ." AND `document` = '". $this->_document->getID() ."' " - ." AND `workflow` = '". $this->_workflow->getID() ."' "; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - $this->_workflow = null; - $this->_workflowState = null; - $this->verifyStatus(false, $user, 'Workflow removed'); - $db->commitTransaction(); - } - - return true; - } /* }}} */ - - /** - * Run a sub workflow - * - * @param object $subworkflow - */ - function getParentWorkflow() { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - /* document content must be in a workflow */ - $this->getWorkflow(); - if(!$this->_workflow) - return false; - - $queryStr= - "SELECT * FROM `tblWorkflowDocumentContent` WHERE " - ."`version`='".$this->_version."' " - ." AND `document` = '". $this->_document->getID() ."' " - ." AND `workflow` = '". $this->_workflow->getID() ."' "; - $recs = $db->getResultArray($queryStr); - if (is_bool($recs) && !$recs) - return false; - if(!$recs) - return false; - - if($recs[0]['parentworkflow']) - return $this->_document->getDMS()->getWorkflow($recs[0]['parentworkflow']); - - return false; - } /* }}} */ - - /** - * Run a sub workflow - * - * @param object $subworkflow - */ - function runSubWorkflow($subworkflow) { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - /* document content must be in a workflow */ - $this->getWorkflow(); - if(!$this->_workflow) - return false; - - /* The current workflow state must match the sub workflows initial state */ - if($subworkflow->getInitState()->getID() != $this->_workflowState->getID()) - return false; - - if($subworkflow) { - $initstate = $subworkflow->getInitState(); - $queryStr = "INSERT INTO `tblWorkflowDocumentContent` (`parentworkflow`, `workflow`, `document`, `version`, `state`, `date`) VALUES (". $this->_workflow->getID(). ", ". $subworkflow->getID(). ", ". $this->_document->getID() .", ". $this->_version .", ".$initstate->getID().", ".$db->getCurrentDatetime().")"; - if (!$db->getResult($queryStr)) { - return false; - } - $this->_workflow = $subworkflow; - return true; - } - return true; - } /* }}} */ - - /** - * Return from sub workflow to parent workflow. - * The method will trigger the given transition - * - * FIXME: Needs much better checking if this is allowed - * - * @param object $user intiating the return - * @param object $transtion to trigger - * @param string comment for the transition trigger - */ - function returnFromSubWorkflow($user, $transition=null, $comment='') { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - /* document content must be in a workflow */ - $this->getWorkflow(); - if(!$this->_workflow) - return false; - - if ($this->_workflow) { - $db->startTransaction(); - - $queryStr= - "SELECT * FROM `tblWorkflowDocumentContent` WHERE `workflow`=". intval($this->_workflow->getID()) - . " AND `version`='".$this->_version - ."' AND `document` = '". $this->_document->getID() ."' "; - $recs = $db->getResultArray($queryStr); - if (is_bool($recs) && !$recs) { - $db->rollbackTransaction(); - return false; - } - if(!$recs) { - $db->rollbackTransaction(); - return false; - } - - $queryStr = "DELETE FROM `tblWorkflowDocumentContent` WHERE `workflow` =". intval($this->_workflow->getID())." AND `document` = '". $this->_document->getID() ."' AND `version` = '" . $this->_version."'"; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - $this->_workflow = $this->_document->getDMS()->getWorkflow($recs[0]['parentworkflow']); - $this->_workflow->setDMS($this->_document->getDMS()); - - if($transition) { - if(false === $this->triggerWorkflowTransition($user, $transition, $comment)) { - $db->rollbackTransaction(); - return false; - } - } - - $db->commitTransaction(); - } - return $this->_workflow; - } /* }}} */ - - /** - * Check if the user is allowed to trigger the transition - * A user is allowed if either the user itself or - * a group of which the user is a member of is registered for - * triggering a transition. This method does not change the workflow - * state of the document content. - * - * @param object $user - * @return boolean true if user may trigger transaction - */ - function triggerWorkflowTransitionIsAllowed($user, $transition) { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - if(!$this->_workflow) - $this->getWorkflow(); - - if(!$this->_workflow) - return false; - - if(!$this->_workflowState) - $this->getWorkflowState(); - - /* Check if the user has already triggered the transition */ - $queryStr= - "SELECT * FROM `tblWorkflowLog` WHERE `version`='".$this->_version ."' AND `document` = '". $this->_document->getID() ."' AND `workflow` = ". $this->_workflow->getID(). " AND userid = ".$user->getID(); - $queryStr .= " AND `transition` = ".$transition->getID(); - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - if(count($resArr)) - return false; - - /* Get all transition users allowed to trigger the transition */ - $transusers = $transition->getUsers(); - if($transusers) { - foreach($transusers as $transuser) { - if($user->getID() == $transuser->getUser()->getID()) - return true; - } - } - - /* Get all transition groups whose members are allowed to trigger - * the transition */ - $transgroups = $transition->getGroups(); - if($transgroups) { - foreach($transgroups as $transgroup) { - $group = $transgroup->getGroup(); - if($group->isMember($user)) - return true; - } - } - - return false; - } /* }}} */ - - /** - * Check if all conditions are met to change the workflow state - * of a document content (run the transition). - * The conditions are met if all explicitly set users and a sufficient - * number of users of the groups have acknowledged the content. - * - * @return boolean true if transaction maybe executed - */ - function executeWorkflowTransitionIsAllowed($transition) { /* {{{ */ - if(!$this->_workflow) - $this->getWorkflow(); - - if(!$this->_workflow) - return false; - - if(!$this->_workflowState) - $this->getWorkflowState(); - - /* Get the Log of transition triggers */ - $entries = $this->getWorkflowLog($transition); - if(!$entries) - return false; - - /* Get all transition users allowed to trigger the transition - * $allowedusers is a list of all users allowed to trigger the - * transition - */ - $transusers = $transition->getUsers(); - $allowedusers = array(); - foreach($transusers as $transuser) { - $a = $transuser->getUser(); - $allowedusers[$a->getID()] = $a; - } - - /* Get all transition groups whose members are allowed to trigger - * the transition */ - $transgroups = $transition->getGroups(); - foreach($entries as $entry) { - $loguser = $entry->getUser(); - /* Unset each allowed user if it was found in the log */ - if(isset($allowedusers[$loguser->getID()])) - unset($allowedusers[$loguser->getID()]); - /* Also check groups if required. Count the group membership of - * each user in the log in the array $gg - */ - if($transgroups) { - $loggroups = $loguser->getGroups(); - foreach($loggroups as $loggroup) { - if(!isset($gg[$loggroup->getID()])) - $gg[$loggroup->getID()] = 1; - else - $gg[$loggroup->getID()]++; - } - } - } - /* If there are allowed users left, then there some users still - * need to trigger the transition. - */ - if($allowedusers) - return false; - - if($transgroups) { - foreach($transgroups as $transgroup) { - $group = $transgroup->getGroup(); - $minusers = $transgroup->getNumOfUsers(); - if(!isset($gg[$group->getID()])) - return false; - if($gg[$group->getID()] < $minusers) - return false; - } - } - return true; - } /* }}} */ - - /** - * Trigger transition - * - * This method will be deprecated - * - * The method will first check if the user is allowed to trigger the - * transition. If the user is allowed, an entry in the workflow log - * will be added, which is later used to check if the transition - * can actually be processed. The method will finally call - * executeWorkflowTransitionIsAllowed() which checks all log entries - * and does the transitions post function if all users and groups have - * triggered the transition. Finally enterNextState() is called which - * will try to enter the next state. - * - * @param object $user - * @param object $transition - * @param string $comment user comment - * @return boolean/object next state if transition could be triggered and - * then next state could be entered, - * true if the transition could just be triggered or - * false in case of an error - */ - function triggerWorkflowTransition($user, $transition, $comment='') { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - if(!$this->_workflow) - $this->getWorkflow(); - - if(!$this->_workflow) - return false; - - if(!$this->_workflowState) - $this->getWorkflowState(); - - if(!$this->_workflowState) - return false; - - /* Check if the user is allowed to trigger the transition. - */ - if(!$this->triggerWorkflowTransitionIsAllowed($user, $transition)) - return false; - - $state = $this->_workflowState; - $queryStr = "INSERT INTO `tblWorkflowLog` (`document`, `version`, `workflow`, `userid`, `transition`, `date`, `comment`) VALUES (".$this->_document->getID().", ".$this->_version.", " . (int) $this->_workflow->getID() . ", " .(int) $user->getID(). ", ".(int) $transition->getID().", ".$db->getCurrentDatetime().", ".$db->qstr($comment).")"; - if (!$db->getResult($queryStr)) - return false; - - /* Check if this transition is processed. Run the post function in - * that case. A transition is processed when all users and groups - * have triggered it. - */ - if($this->executeWorkflowTransitionIsAllowed($transition)) { - /* run post function of transition */ -// echo "run post function of transition ".$transition->getID()."
"; - } - - /* Go into the next state. This will only succeed if the pre condition - * function of that states succeeds. - */ - $nextstate = $transition->getNextState(); - if($this->enterNextState($user, $nextstate)) { - return $nextstate; - } - return true; - - } /* }}} */ - - /** - * Enter next state of workflow if possible - * - * The method will check if one of the following states in the workflow - * can be reached. - * It does it by running - * the precondition function of that state. The precondition function - * gets a list of all transitions leading to the state. It will - * determine, whether the transitions has been triggered and if that - * is sufficient to enter the next state. If no pre condition function - * is set, then 1 of n transtions are enough to enter the next state. - * - * If moving in the next state is possible and this state has a - * corresponding document state, then the document state will be - * updated and the workflow will be detached from the document. - * - * @param object $user - * @param object $nextstate - * @return boolean true if the state could be reached - * false if not - */ - function enterNextState($user, $nextstate) { /* {{{ */ - - /* run the pre condition of the next state. If it is not set - * the next state will be reached if one of the transitions - * leading to the given state can be processed. - */ - if($nextstate->getPreCondFunc() == '') { - $transitions = $this->_workflow->getPreviousTransitions($nextstate); - foreach($transitions as $transition) { -// echo "transition ".$transition->getID()." led to state ".$nextstate->getName()."
"; - if($this->executeWorkflowTransitionIsAllowed($transition)) { -// echo "stepping into next state
"; - $this->setWorkflowState($nextstate); - - /* Check if the new workflow state has a mapping into a - * document state. If yes, set the document state will - * be updated and the workflow will be removed from the - * document. - */ - $docstate = $nextstate->getDocumentStatus(); - if($docstate == S_RELEASED || $docstate == S_REJECTED) { - $this->setStatus($docstate, "Workflow has ended", $user); - /* Detach the workflow from the document, but keep the - * workflow log - */ - $this->removeWorkflow($user, true); - return true ; - } - - /* make sure the users and groups allowed to trigger the next - * transitions are also allowed to read the document - */ - $transitions = $this->_workflow->getNextTransitions($nextstate); - foreach($transitions as $tran) { -// echo "checking access for users/groups allowed to trigger transition ".$tran->getID()."
"; - $transusers = $tran->getUsers(); - foreach($transusers as $transuser) { - $u = $transuser->getUser(); -// echo $u->getFullName()."
"; - if($this->_document->getAccessMode($u) < M_READ) { - $this->_document->addAccess(M_READ, $u->getID(), 1); -// echo "granted read access
"; - } else { -// echo "has already access
"; - } - } - $transgroups = $tran->getGroups(); - foreach($transgroups as $transgroup) { - $g = $transgroup->getGroup(); -// echo $g->getName()."
"; - if ($this->_document->getGroupAccessMode($g) < M_READ) { - $this->_document->addAccess(M_READ, $g->getID(), 0); -// echo "granted read access
"; - } else { -// echo "has already access
"; - } - } - } - return(true); - } else { -// echo "transition not ready for process now
"; - } - } - return false; - } else { - } - - } /* }}} */ - - /** - * Get the so far logged operations on the document content within the - * workflow. Even after finishing the workflow (when the document content - * does not have workflow set anymore) this function returns the list of all - * log entries. - * - * @return array list of objects - */ - function getWorkflowLog($transition = null) { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - -/* - if(!$this->_workflow) - $this->getWorkflow(); - - if(!$this->_workflow) - return false; -*/ - $queryStr= - "SELECT * FROM `tblWorkflowLog` WHERE `version`='".$this->_version ."' AND `document` = '". $this->_document->getID() ."'"; // AND `workflow` = ". $this->_workflow->getID(); - if($transition) - $queryStr .= " AND `transition` = ".$transition->getID(); - $queryStr .= " ORDER BY `date`"; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - $workflowlogs = array(); - for ($i = 0; $i < count($resArr); $i++) { - $workflow = $this->_document->getDMS()->getWorkflow($resArr[$i]["workflow"]); - $workflowlog = new SeedDMS_Core_Workflow_Log($resArr[$i]["id"], $this->_document->getDMS()->getDocument($resArr[$i]["document"]), $resArr[$i]["version"], $workflow, $this->_document->getDMS()->getUser($resArr[$i]["userid"]), $workflow->getTransition($resArr[$i]["transition"]), $resArr[$i]["date"], $resArr[$i]["comment"]); - $workflowlog->setDMS($this); - $workflowlogs[$i] = $workflowlog; - } - - return $workflowlogs; - } /* }}} */ - - /** - * Get the latest workflow log entry for the document content within the - * workflow. Even after finishing the workflow (when the document content - * does not have workflow set anymore) this function returns the last - * log entry. - * - * @return object - */ - function getLastWorkflowLog() { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - -/* - if(!$this->_workflow) - $this->getWorkflow(); - - if(!$this->_workflow) - return false; - */ - $queryStr= - "SELECT * FROM `tblWorkflowLog` WHERE `version`='".$this->_version ."' AND `document` = '". $this->_document->getID() ."'"; // AND `workflow` = ". $this->_workflow->getID(); - $queryStr .= " ORDER BY `id` DESC LIMIT 1"; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - $i = 0; - $workflow = $this->_document->getDMS()->getWorkflow($resArr[$i]["workflow"]); - $workflowlog = new SeedDMS_Core_Workflow_Log($resArr[$i]["id"], $this->_document->getDMS()->getDocument($resArr[$i]["document"]), $resArr[$i]["version"], $workflow, $this->_document->getDMS()->getUser($resArr[$i]["userid"]), $workflow->getTransition($resArr[$i]["transition"]), $resArr[$i]["date"], $resArr[$i]["comment"]); - $workflowlog->setDMS($this); - - return $workflowlog; - } /* }}} */ - - /** - * Check if the document content needs an action by a user - * - * This method will return true if document content is in a transition - * which can be triggered by the given user. - * - * @param SeedDMS_Core_User $user - * @return boolean true is action is needed - */ - function needsWorkflowAction($user) { /* {{{ */ - $needwkflaction = false; - if($this->_workflow) { - if (!$this->_workflowState) - $this->getWorkflowState(); - $workflowstate = $this->_workflowState; - if($transitions = $this->_workflow->getNextTransitions($workflowstate)) { - foreach($transitions as $transition) { - if($this->triggerWorkflowTransitionIsAllowed($user, $transition)) { - $needwkflaction = true; - } - } - } - } - return $needwkflaction; - } /* }}} */ - - /** - * Checks the internal data of the document version and repairs it. - * Currently, this function only repairs a missing filetype - * - * @return boolean true on success, otherwise false - */ - function repair() { /* {{{ */ - $dms = $this->_document->getDMS(); - $db = $this->_dms->getDB(); - - if(SeedDMS_Core_File::file_exists($this->_dms->contentDir.$this->_document->getDir() . $this->_version . $this->_fileType)) { - if(strlen($this->_fileType) < 2) { - switch($this->_mimeType) { - case "application/pdf": - case "image/png": - case "image/gif": - case "image/jpg": - $expect = substr($this->_mimeType, -3, 3); - if($this->_fileType != '.'.$expect) { - $db->startTransaction(); - $queryStr = "UPDATE `tblDocumentContent` SET `fileType`='.".$expect."' WHERE `id` = ". $this->_id; - $res = $db->getResult($queryStr); - if ($res) { - if(!SeedDMS_Core_File::renameFile($this->_dms->contentDir.$this->_document->getDir() . $this->_version . $this->_fileType, $this->_dms->contentDir.$this->_document->getDir() . $this->_version . '.' . $expect)) { - $db->rollbackTransaction(); - } else { - $db->commitTransaction(); - } - } else { - $db->rollbackTransaction(); - } - } - break; - } - } - } elseif(SeedDMS_Core_File::file_exists($this->_document->getDir() . $this->_version . '.')) { - echo "no file"; - } else { - echo $this->_dms->contentDir.$this->_document->getDir() . $this->_version . $this->_fileType; - } - return true; - } /* }}} */ - -} /* }}} */ - - -/** - * Class to represent a link between two document - * - * Document links are to establish a reference from one document to - * another document. The owner of the document link may not be the same - * as the owner of one of the documents. - * Use {@link SeedDMS_Core_Document::addDocumentLink()} to add a reference - * to another document. - * - * @category DMS - * @package SeedDMS_Core - * @author Markus Westphal, Malcolm Cowe, Matteo Lucarelli, - * Uwe Steinmann - * @copyright Copyright (C) 2002-2005 Markus Westphal, - * 2006-2008 Malcolm Cowe, 2010 Matteo Lucarelli, - * 2010-2022 Uwe Steinmann - * @version Release: @package_version@ - */ -class SeedDMS_Core_DocumentLink { /* {{{ */ - /** - * @var integer internal id of document link - */ - protected $_id; - - /** - * @var SeedDMS_Core_Document reference to document this link belongs to - */ - protected $_document; - - /** - * @var object reference to target document this link points to - */ - protected $_target; - - /** - * @var integer id of user who is the owner of this link - */ - protected $_userID; - - /** - * @var integer 1 if this link is public, or 0 if is only visible to the owner - */ - protected $_public; - - /** - * SeedDMS_Core_DocumentLink constructor. - * @param $id - * @param $document - * @param $target - * @param $userID - * @param $public - */ - function __construct($id, $document, $target, $userID, $public) { - $this->_id = $id; - $this->_document = $document; - $this->_target = $target; - $this->_userID = $userID; - $this->_public = $public ? true : false; - } - - /** - * Check if this object is of type 'documentlink'. - * - * @param string $type type of object - */ - public function isType($type) { /* {{{ */ - return $type == 'documentlink'; - } /* }}} */ - - /** - * @return int - */ - function getID() { return $this->_id; } - - /** - * @return SeedDMS_Core_Document - */ - function getDocument() { - return $this->_document; - } - - /** - * @return object - */ - function getTarget() { - return $this->_target; - } - - /** - * @return bool|SeedDMS_Core_User - */ - function getUser() { - if (!isset($this->_user)) { - $this->_user = $this->_document->getDMS()->getUser($this->_userID); - } - return $this->_user; - } - - /** - * @return int - */ - function isPublic() { return $this->_public; } - - /** - * Returns the access mode similar to a document - * - * There is no real access mode for document links, so this is just - * another way to add more access restrictions than the default restrictions. - * It is only called for public document links, not accessed by the owner - * or the administrator. - * - * @param SeedDMS_Core_User $u user - * @param $source - * @param $target - * @return int either M_NONE or M_READ - */ - function getAccessMode($u, $source, $target) { /* {{{ */ - $dms = $this->_document->getDMS(); - - /* Check if 'onCheckAccessDocumentLink' callback is set */ - if(isset($dms->callbacks['onCheckAccessDocumentLink'])) { - foreach($dms->callbacks['onCheckAccessDocumentLink'] as $callback) { - if(($ret = call_user_func($callback[0], $callback[1], $this, $u, $source, $target)) > 0) { - return $ret; - } - } - } - - return M_READ; - } /* }}} */ - -} /* }}} */ - -/** - * Class to represent a file attached to a document - * - * Beside the regular document content arbitrary files can be attached - * to a document. This is a similar concept as attaching files to emails. - * The owner of the attached file and the document may not be the same. - * Use {@link SeedDMS_Core_Document::addDocumentFile()} to attach a file. - * - * @category DMS - * @package SeedDMS_Core - * @author Markus Westphal, Malcolm Cowe, Matteo Lucarelli, - * Uwe Steinmann - * @copyright Copyright (C) 2002-2005 Markus Westphal, - * 2006-2008 Malcolm Cowe, 2010 Matteo Lucarelli, - * 2010-2022 Uwe Steinmann - * @version Release: @package_version@ - */ -class SeedDMS_Core_DocumentFile { /* {{{ */ - /** - * @var integer internal id of document file - */ - protected $_id; - - /** - * @var SeedDMS_Core_Document reference to document this file belongs to - */ - protected $_document; - - /** - * @var integer id of user who is the owner of this link - */ - protected $_userID; - - /** - * @var string comment for the attached file - */ - protected $_comment; - - /** - * @var string date when the file was attached - */ - protected $_date; - - /** - * @var integer version of document this file is attached to - */ - protected $_version; - - /** - * @var integer 1 if this link is public, or 0 if is only visible to the owner - */ - protected $_public; - - /** - * @var string directory where the file is stored. This is the - * document id with a proceding '/'. - * FIXME: looks like this isn't used anymore. The file path is - * constructed by getPath() - */ - protected $_dir; - - /** - * @var string extension of the original file name with a leading '.' - */ - protected $_fileType; - - /** - * @var string mime type of the file - */ - protected $_mimeType; - - /** - * @var string name of the file that was originally uploaded - */ - protected $_orgFileName; - - /** - * @var string name of the file as given by the user - */ - protected $_name; - - /** - * SeedDMS_Core_DocumentFile constructor. - * @param $id - * @param $document - * @param $userID - * @param $comment - * @param $date - * @param $dir - * @param $fileType - * @param $mimeType - * @param $orgFileName - * @param $name - * @param $version - * @param $public - */ - function __construct($id, $document, $userID, $comment, $date, $dir, $fileType, $mimeType, $orgFileName,$name,$version,$public) { - $this->_id = $id; - $this->_document = $document; - $this->_userID = $userID; - $this->_comment = $comment; - $this->_date = $date; - $this->_dir = $dir; - $this->_fileType = $fileType; - $this->_mimeType = $mimeType; - $this->_orgFileName = $orgFileName; - $this->_name = $name; - $this->_version = $version; - $this->_public = $public ? true : false; - } - - /** - * Check if this object is of type 'documentfile'. - * - * @param string $type type of object - */ - public function isType($type) { /* {{{ */ - return $type == 'documentfile'; - } /* }}} */ - - /** - * @return int - */ - function getID() { return $this->_id; } - - /** - * @return SeedDMS_Core_Document - */ - function getDocument() { return $this->_document; } - - /** - * @return int - */ - function getUserID() { return $this->_userID; } - - /** - * @return string - */ - function getComment() { return $this->_comment; } - - /* - * Set the comment of the document file - * - * @param string $newComment string new comment of document - */ - function setComment($newComment) { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - $queryStr = "UPDATE `tblDocumentFiles` SET `comment` = ".$db->qstr($newComment)." WHERE `document` = ".$this->_document->getId()." AND `id` = ". $this->_id; - if (!$db->getResult($queryStr)) - return false; - - $this->_comment = $newComment; - return true; - } /* }}} */ - - /** - * @return string - */ - function getDate() { return $this->_date; } - - /** - * Set creation date of the document file - * - * @param integer $date timestamp of creation date. If false then set it - * to the current timestamp - * @return boolean true on success - */ - function setDate($date=null) { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - if(!$date) - $date = time(); - else { - if(!is_numeric($date)) - return false; - } - - $queryStr = "UPDATE `tblDocumentFiles` SET `date` = " . (int) $date . " WHERE `id` = ". $this->_id; - if (!$db->getResult($queryStr)) - return false; - $this->_date = $date; - return true; - } /* }}} */ - - /** - * @return string - */ - function getDir() { return $this->_dir; } - - /** - * @return string - */ - function getFileType() { return $this->_fileType; } - - /** - * @return string - */ - function getMimeType() { return $this->_mimeType; } - - /** - * @return string - */ - function getOriginalFileName() { return $this->_orgFileName; } - - /** - * @return string - */ - function getName() { return $this->_name; } - - /* - * Set the name of the document file - * - * @param $newComment string new name of document - */ - function setName($newName) { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - $queryStr = "UPDATE `tblDocumentFiles` SET `name` = ".$db->qstr($newName)." WHERE `document` = ".$this->_document->getId()." AND `id` = ". $this->_id; - if (!$db->getResult($queryStr)) - return false; - - $this->_name = $newName; - return true; - } /* }}} */ - - /** - * @return bool|SeedDMS_Core_User - */ - function getUser() { - if (!isset($this->_user)) - $this->_user = $this->_document->getDMS()->getUser($this->_userID); - return $this->_user; - } - - /** - * @return string - */ - function getPath() { - return $this->_document->getDir() . "f" .$this->_id . $this->_fileType; - } - - /** - * @return int - */ - function getVersion() { return $this->_version; } - - /* - * Set the version of the document file - * - * @param $newComment string new version of document - */ - function setVersion($newVersion) { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - if(!is_numeric($newVersion) && $newVersion != '') - return false; - - $queryStr = "UPDATE `tblDocumentFiles` SET `version` = ".(int) $newVersion." WHERE `document` = ".$this->_document->getId()." AND `id` = ". $this->_id; - if (!$db->getResult($queryStr)) - return false; - - $this->_version = (int) $newVersion; - return true; - } /* }}} */ - - /** - * @return int - */ - function isPublic() { return $this->_public; } - - /* - * Set the public flag of the document file - * - * @param $newComment string new comment of document - */ - function setPublic($newPublic) { /* {{{ */ - $db = $this->_document->getDMS()->getDB(); - - $queryStr = "UPDATE `tblDocumentFiles` SET `public` = ".($newPublic ? 1 : 0)." WHERE `document` = ".$this->_document->getId()." AND `id` = ". $this->_id; - if (!$db->getResult($queryStr)) - return false; - - $this->_public = $newPublic ? true : false; - return true; - } /* }}} */ - - /** - * Returns the access mode similar to a document - * - * There is no real access mode for document files, so this is just - * another way to add more access restrictions than the default restrictions. - * It is only called for public document files, not accessed by the owner - * or the administrator. - * - * @param object $u user - * @return integer either M_NONE or M_READ - */ - function getAccessMode($u) { /* {{{ */ - $dms = $this->_document->getDMS(); - - /* Check if 'onCheckAccessDocumentLink' callback is set */ - if(isset($this->_dms->callbacks['onCheckAccessDocumentFile'])) { - foreach($this->_dms->callbacks['onCheckAccessDocumentFile'] as $callback) { - if(($ret = call_user_func($callback[0], $callback[1], $this, $u)) > 0) { - return $ret; - } - } - } - - return M_READ; - } /* }}} */ - -} /* }}} */ - -// -// Perhaps not the cleanest object ever devised, it exists to encapsulate all -// of the data generated during the addition of new content to the database. -// The object stores a copy of the new DocumentContent object, the newly assigned -// reviewers and approvers and the status. -// -/** - * Class to represent a list of document contents - * - * @category DMS - * @package SeedDMS_Core - * @author Markus Westphal, Malcolm Cowe, Matteo Lucarelli, - * Uwe Steinmann - * @copyright Copyright (C) 2002-2005 Markus Westphal, - * 2006-2008 Malcolm Cowe, 2010 Matteo Lucarelli, - * 2010-2022 Uwe Steinmann - * @version Release: @package_version@ - */ -class SeedDMS_Core_AddContentResultSet { /* {{{ */ - - /** - * @var null - */ - protected $_indReviewers; - - /** - * @var null - */ - protected $_grpReviewers; - - /** - * @var null - */ - protected $_indApprovers; - - /** - * @var null - */ - protected $_grpApprovers; - - /** - * @var - */ - protected $_content; - - /** - * @var null - */ - protected $_status; - - /** - * @var SeedDMS_Core_DMS back reference to document management system - */ - protected $_dms; - - /** - * SeedDMS_Core_AddContentResultSet constructor. - * @param $content - */ - function __construct($content) { /* {{{ */ - $this->_content = $content; - $this->_indReviewers = null; - $this->_grpReviewers = null; - $this->_indApprovers = null; - $this->_grpApprovers = null; - $this->_status = null; - $this->_dms = null; - } /* }}} */ - - /** - * Set dms this object belongs to. - * - * Each object needs a reference to the dms it belongs to. It will be - * set when the object is created. - * The dms has a references to the currently logged in user - * and the database connection. - * - * @param SeedDMS_Core_DMS $dms reference to dms - */ - function setDMS($dms) { /* {{{ */ - $this->_dms = $dms; - } /* }}} */ - - /** - * @param $reviewer - * @param $type - * @param $status - * @return bool - */ - function addReviewer($reviewer, $type, $status) { /* {{{ */ - $dms = $this->_dms; - - if (!is_object($reviewer) || (strcasecmp($type, "i") && strcasecmp($type, "g")) && !is_integer($status)){ - return false; - } - if (!strcasecmp($type, "i")) { - if (strcasecmp(get_class($reviewer), $dms->getClassname("user"))) { - return false; - } - if ($this->_indReviewers == null) { - $this->_indReviewers = array(); - } - $this->_indReviewers[$status][] = $reviewer; - } - if (!strcasecmp($type, "g")) { - if (strcasecmp(get_class($reviewer), $dms->getClassname("group"))) { - return false; - } - if ($this->_grpReviewers == null) { - $this->_grpReviewers = array(); - } - $this->_grpReviewers[$status][] = $reviewer; - } - return true; - } /* }}} */ - - /** - * @param $approver - * @param $type - * @param $status - * @return bool - */ - function addApprover($approver, $type, $status) { /* {{{ */ - $dms = $this->_dms; - - if (!is_object($approver) || (strcasecmp($type, "i") && strcasecmp($type, "g")) && !is_integer($status)){ - return false; - } - if (!strcasecmp($type, "i")) { - if (strcasecmp(get_class($approver), $dms->getClassname("user"))) { - return false; - } - if ($this->_indApprovers == null) { - $this->_indApprovers = array(); - } - $this->_indApprovers[$status][] = $approver; - } - if (!strcasecmp($type, "g")) { - if (strcasecmp(get_class($approver), $dms->getClassname("group"))) { - return false; - } - if ($this->_grpApprovers == null) { - $this->_grpApprovers = array(); - } - $this->_grpApprovers[$status][] = $approver; - } - return true; - } /* }}} */ - - /** - * @param $status - * @return bool - */ - function setStatus($status) { /* {{{ */ - if (!is_integer($status)) { - return false; - } - if ($status<-3 || $status>3) { - return false; - } - $this->_status = $status; - return true; - } /* }}} */ - - /** - * @return null - */ - function getStatus() { /* {{{ */ - return $this->_status; - } /* }}} */ - - /** - * @return mixed - */ - function getContent() { /* {{{ */ - return $this->_content; - } /* }}} */ - - /** - * @param $type - * @return array|bool|null - */ - function getReviewers($type) { /* {{{ */ - if (strcasecmp($type, "i") && strcasecmp($type, "g")) { - return false; - } - if (!strcasecmp($type, "i")) { - return ($this->_indReviewers == null ? array() : $this->_indReviewers); - } - else { - return ($this->_grpReviewers == null ? array() : $this->_grpReviewers); - } - } /* }}} */ - - /** - * @param $type - * @return array|bool|null - */ - function getApprovers($type) { /* {{{ */ - if (strcasecmp($type, "i") && strcasecmp($type, "g")) { - return false; - } - if (!strcasecmp($type, "i")) { - return ($this->_indApprovers == null ? array() : $this->_indApprovers); - } - else { - return ($this->_grpApprovers == null ? array() : $this->_grpApprovers); - } - } /* }}} */ -} /* }}} */ diff --git a/SeedDMS_Core/Core/inc.ClassDocumentCategory.php b/SeedDMS_Core/Core/inc.ClassDocumentCategory.php deleted file mode 100644 index 4f39e2ef9..000000000 --- a/SeedDMS_Core/Core/inc.ClassDocumentCategory.php +++ /dev/null @@ -1,124 +0,0 @@ - - * @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 - * @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']; - } /* }}} */ - -} - -?> diff --git a/SeedDMS_Core/Core/inc.ClassFolder.php b/SeedDMS_Core/Core/inc.ClassFolder.php deleted file mode 100644 index 3d041043c..000000000 --- a/SeedDMS_Core/Core/inc.ClassFolder.php +++ /dev/null @@ -1,2115 +0,0 @@ - - * @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 folder in the document management system - * - * A folder in SeedDMS is equivalent to a directory in a regular file - * system. It can contain further subfolders and documents. Each folder - * has a single parent except for the root folder which has no parent. - * - * @category DMS - * @package SeedDMS_Core - * @version @version@ - * @author Uwe Steinmann - * @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe, - * 2010 Matteo Lucarelli, 2010 Uwe Steinmann - * @version Release: @package_version@ - */ -class SeedDMS_Core_Folder extends SeedDMS_Core_Object { - /** - * @var string name of folder - */ - protected $_name; - - /** - * @var integer id of parent folder - */ - protected $_parentID; - - /** - * @var string comment of document - */ - protected $_comment; - - /** - * @var integer id of user who is the owner - */ - protected $_ownerID; - - /** - * @var boolean true if access is inherited, otherwise false - */ - protected $_inheritAccess; - - /** - * @var integer default access if access rights are not inherited - */ - protected $_defaultAccess; - - /** - * @var array list of notifications for users and groups - */ - protected $_readAccessList; - - /** - * @var array list of notifications for users and groups - */ - public $_notifyList; - - /** - * @var integer position of folder within the parent folder - */ - protected $_sequence; - - /** - * @var - */ - protected $_date; - - /** - * @var SeedDMS_Core_Folder cached parent folder - */ - protected $_parent; - - /** - * @var SeedDMS_Core_User cached owner of folder - */ - protected $_owner; - - /** - * @var SeedDMS_Core_Folder[] cached array of sub folders - */ - protected $_subFolders; - - /** - * @var SeedDMS_Core_Document[] cache array of child documents - */ - protected $_documents; - - /** - * @var SeedDMS_Core_UserAccess[]|SeedDMS_Core_GroupAccess[] - */ - protected $_accessList; - - /** - * SeedDMS_Core_Folder constructor. - * @param $id - * @param $name - * @param $parentID - * @param $comment - * @param $date - * @param $ownerID - * @param $inheritAccess - * @param $defaultAccess - * @param $sequence - */ - function __construct($id, $name, $parentID, $comment, $date, $ownerID, $inheritAccess, $defaultAccess, $sequence) { /* {{{ */ - parent::__construct($id); - $this->_id = $id; - $this->_name = $name; - $this->_parentID = $parentID; - $this->_comment = $comment; - $this->_date = $date; - $this->_ownerID = $ownerID; - $this->_inheritAccess = $inheritAccess; - $this->_defaultAccess = $defaultAccess; - $this->_sequence = $sequence; - $this->_notifyList = array(); - /* Cache */ - $this->clearCache(); - } /* }}} */ - - /** - * Clear cache of this instance. - * - * The result of some expensive database actions (e.g. get all subfolders - * or documents) will be saved in a class variable to speed up consecutive - * calls of the same method. If a second call of the same method shall not - * use the cache, then it must be cleared. - * - */ - public function clearCache() { /* {{{ */ - $this->_parent = null; - $this->_owner = null; - $this->_subFolders = null; - $this->_documents = null; - $this->_accessList = null; - $this->_notifyList = null; - } /* }}} */ - - /** - * Check if this object is of type 'folder'. - * - * @param string $type type of object - */ - public function isType($type) { /* {{{ */ - return $type == 'folder'; - } /* }}} */ - - /** - * Return an array of database fields which used for searching - * a term entered in the database search form - * - * @param SeedDMS_Core_DMS $dms - * @param array $searchin integer list of search scopes (2=name, 3=comment, - * 4=attributes) - * @return array list of database fields - */ - public static function getSearchFields($dms, $searchin) { /* {{{ */ - $db = $dms->getDB(); - - $searchFields = array(); - if (in_array(2, $searchin)) { - $searchFields[] = "`tblFolders`.`name`"; - } - if (in_array(3, $searchin)) { - $searchFields[] = "`tblFolders`.`comment`"; - } - if (in_array(4, $searchin)) { - $searchFields[] = "`tblFolderAttributes`.`value`"; - } - if (in_array(5, $searchin)) { - $searchFields[] = $db->castToText("`tblFolders`.`id`"); - } - return $searchFields; - } /* }}} */ - - /** - * Return a sql statement with all tables used for searching. - * This must be a syntactically correct left join of all tables. - * - * @return string sql expression for left joining tables - */ - public static function getSearchTables() { /* {{{ */ - $sql = "`tblFolders` LEFT JOIN `tblFolderAttributes` on `tblFolders`.`id`=`tblFolderAttributes`.`folder`"; - return $sql; - } /* }}} */ - - /** - * Return a folder by its database record - * - * @param array $resArr array of folder data as returned by database - * @param SeedDMS_Core_DMS $dms - * @return SeedDMS_Core_Folder|bool instance of SeedDMS_Core_Folder if document exists - */ - public static function getInstanceByData($resArr, $dms) { /* {{{ */ - $classname = $dms->getClassname('folder'); - /** @var SeedDMS_Core_Folder $folder */ - $folder = new $classname($resArr["id"], $resArr["name"], $resArr["parent"], $resArr["comment"], $resArr["date"], $resArr["owner"], $resArr["inheritAccess"], $resArr["defaultAccess"], $resArr["sequence"]); - $folder->setDMS($dms); - $folder = $folder->applyDecorators(); - return $folder; - } /* }}} */ - - /** - * Return a folder by its id - * - * @param integer $id id of folder - * @param SeedDMS_Core_DMS $dms - * @return SeedDMS_Core_Folder|bool instance of SeedDMS_Core_Folder if document exists, null - * if document does not exist, false in case of error - */ - public static function getInstance($id, $dms) { /* {{{ */ - $db = $dms->getDB(); - - $queryStr = "SELECT * FROM `tblFolders` WHERE `id` = " . (int) $id; - if($dms->checkWithinRootDir && ($id != $dms->rootFolderID)) - $queryStr .= " AND `folderList` LIKE '%:".$dms->rootFolderID.":%'"; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && $resArr == false) - return false; - elseif (count($resArr) != 1) - return null; - - return self::getInstanceByData($resArr[0], $dms); - } /* }}} */ - - /** - * Return a folder by its name - * - * This function retrieves a folder from the database by its name. The - * search covers the whole database. If - * the parameter $folder is not null, it will search for the name - * only within this parent folder. It will not be done recursively. - * - * @param string $name name of the folder - * @param SeedDMS_Core_Folder $folder parent folder - * @return SeedDMS_Core_Folder|boolean found folder or false - */ - public static function getInstanceByName($name, $folder=null, $dms) { /* {{{ */ - if (!$name) return false; - - $db = $dms->getDB(); - $queryStr = "SELECT * FROM `tblFolders` WHERE `name` = " . $db->qstr($name); - if($folder) - $queryStr .= " AND `parent` = ". $folder->getID(); - if($dms->checkWithinRootDir && ($id != $dms->rootFolderID)) - $queryStr .= " AND `folderList` LIKE '%:".$dms->rootFolderID.":%'"; - $queryStr .= " LIMIT 1"; - $resArr = $db->getResultArray($queryStr); - - if (is_bool($resArr) && $resArr == false) - return false; - - if(!$resArr) - return null; - - return self::getInstanceByData($resArr[0], $dms); - } /* }}} */ - - /** - * Apply decorators - * - * @return object final object after all decorators has been applied - */ - function applyDecorators() { /* {{{ */ - if($decorators = $this->_dms->getDecorators('folder')) { - $s = $this; - foreach($decorators as $decorator) { - $s = new $decorator($s); - } - return $s; - } else { - return $this; - } - } /* }}} */ - - /** - * Get the name of the folder. - * - * @return string name of folder - */ - public function getName() { return $this->_name; } - - /** - * Set the name of the folder. - * - * @param string $newName set a new name of the folder - * @return bool - */ - public function setName($newName) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblFolders` SET `name` = " . $db->qstr($newName) . " WHERE `id` = ". $this->_id; - if (!$db->getResult($queryStr)) - return false; - - $this->_name = $newName; - - return true; - } /* }}} */ - - /** - * @return string - */ - public function getComment() { return $this->_comment; } - - /** - * @param $newComment - * @return bool - */ - public function setComment($newComment) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblFolders` SET `comment` = " . $db->qstr($newComment) . " WHERE `id` = ". $this->_id; - if (!$db->getResult($queryStr)) - return false; - - $this->_comment = $newComment; - return true; - } /* }}} */ - - /** - * Return creation date of folder - * - * @return integer unix timestamp of creation date - */ - public function getDate() { /* {{{ */ - return $this->_date; - } /* }}} */ - - /** - * Set creation date of the folder - * - * @param integer $date timestamp of creation date. If false then set it - * to the current timestamp - * @return boolean true on success - */ - function setDate($date) { /* {{{ */ - $db = $this->_dms->getDB(); - - if($date === false) - $date = time(); - else { - if(!is_numeric($date)) - return false; - } - - $queryStr = "UPDATE `tblFolders` SET `date` = " . (int) $date . " WHERE `id` = ". $this->_id; - if (!$db->getResult($queryStr)) - return false; - $this->_date = $date; - return true; - } /* }}} */ - - /** - * Returns the parent - * - * @return null|bool|SeedDMS_Core_Folder returns null, if there is no parent folder - * and false in case of an error - */ - public function getParent() { /* {{{ */ - if ($this->_id == $this->_dms->rootFolderID || empty($this->_parentID)) { - return null; - } - - if (!isset($this->_parent)) { - $this->_parent = $this->_dms->getFolder($this->_parentID); - } - return $this->_parent; - } /* }}} */ - - /** - * Check if the folder is subfolder - * - * This method checks if the current folder is in the path of the - * passed subfolder. In that case the current folder is a parent, - * grant parent, grant grant parent, etc. of the subfolder or - * to say it differently the passed folder is somewhere below the - * current folder. - * - * This is basically the opposite of {@see SeedDMS_Core_Folder::isDescendant()} - * - * @param SeedDMS_Core_Folder $subfolder folder to be checked if it is - * a subfolder on any level of the current folder - * @return bool true if passed folder is a subfolder, otherwise false - */ - function isSubFolder($subfolder) { /* {{{ */ - $target_path = $subfolder->getPath(); - foreach($target_path as $next_folder) { - // the target folder contains this instance in the parent path - if($this->getID() == $next_folder->getID()) return true; - } - return false; - } /* }}} */ - - /** - * Set a new folder - * - * This function moves a folder from one parent folder into another parent - * folder. It will fail if the root folder is moved. - * - * @param SeedDMS_Core_Folder $newParent new parent folder - * @return boolean true if operation was successful otherwise false - */ - public function setParent($newParent) { /* {{{ */ - $db = $this->_dms->getDB(); - - if ($this->_id == $this->_dms->rootFolderID || empty($this->_parentID)) { - return false; - } - - /* Check if the new parent is the folder to be moved or even - * a subfolder of that folder - */ - if($this->isSubFolder($newParent)) { - return false; - } - - // Update the folderList of the folder - $pathPrefix=""; - $path = $newParent->getPath(); - foreach ($path as $f) { - $pathPrefix .= ":".$f->getID(); - } - if (strlen($pathPrefix)>1) { - $pathPrefix .= ":"; - } - $queryStr = "UPDATE `tblFolders` SET `parent` = ".$newParent->getID().", `folderList`='".$pathPrefix."' WHERE `id` = ". $this->_id; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - $this->_parentID = $newParent->getID(); - $this->_parent = $newParent; - - // Must also ensure that any documents in this folder tree have their - // folderLists updated. - $pathPrefix=""; - $path = $this->getPath(); - foreach ($path as $f) { - $pathPrefix .= ":".$f->getID(); - } - if (strlen($pathPrefix)>1) { - $pathPrefix .= ":"; - } - - /* Update path in folderList for all documents */ - $queryStr = "SELECT `tblDocuments`.`id`, `tblDocuments`.`folderList` FROM `tblDocuments` WHERE `folderList` LIKE '%:".$this->_id.":%'"; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && $resArr == false) - return false; - - foreach ($resArr as $row) { - $newPath = preg_replace("/^.*:".$this->_id.":(.*$)/", $pathPrefix."\\1", $row["folderList"]); - $queryStr="UPDATE `tblDocuments` SET `folderList` = '".$newPath."' WHERE `tblDocuments`.`id` = '".$row["id"]."'"; - /** @noinspection PhpUnusedLocalVariableInspection */ - $res = $db->getResult($queryStr); - } - - /* Update path in folderList for all folders */ - $queryStr = "SELECT `tblFolders`.`id`, `tblFolders`.`folderList` FROM `tblFolders` WHERE `folderList` LIKE '%:".$this->_id.":%'"; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && $resArr == false) - return false; - - foreach ($resArr as $row) { - $newPath = preg_replace("/^.*:".$this->_id.":(.*$)/", $pathPrefix."\\1", $row["folderList"]); - $queryStr="UPDATE `tblFolders` SET `folderList` = '".$newPath."' WHERE `tblFolders`.`id` = '".$row["id"]."'"; - /** @noinspection PhpUnusedLocalVariableInspection */ - $res = $db->getResult($queryStr); - } - - return true; - } /* }}} */ - - /** - * Returns the owner - * - * @return object owner of the folder - */ - public function getOwner() { /* {{{ */ - if (!isset($this->_owner)) - $this->_owner = $this->_dms->getUser($this->_ownerID); - return $this->_owner; - } /* }}} */ - - /** - * Set the owner - * - * @param SeedDMS_Core_User $newOwner of the folder - * @return boolean true if successful otherwise false - */ - function setOwner($newOwner) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblFolders` set `owner` = " . $newOwner->getID() . " WHERE `id` = " . $this->_id; - if (!$db->getResult($queryStr)) - return false; - - $this->_ownerID = $newOwner->getID(); - $this->_owner = $newOwner; - return true; - } /* }}} */ - - /** - * @return bool|int - */ - function getDefaultAccess() { /* {{{ */ - if ($this->inheritsAccess()) { - /* Access is supposed to be inherited but it could be that there - * is no parent because the configured root folder id is somewhere - * below the actual root folder. - */ - $res = $this->getParent(); - if ($res) - return $this->_parent->getDefaultAccess(); - } - - return $this->_defaultAccess; - } /* }}} */ - - /** - * Set default access mode - * - * This method sets the default access mode and also removes all notifiers which - * will not have read access anymore. - * - * @param integer $mode access mode - * @param boolean $noclean set to true if notifier list shall not be clean up - * @return bool - */ - function setDefaultAccess($mode, $noclean=false) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblFolders` set `defaultAccess` = " . (int) $mode . " WHERE `id` = " . $this->_id; - if (!$db->getResult($queryStr)) - return false; - - $this->_defaultAccess = $mode; - - if(!$noclean) - $this->cleanNotifyList(); - - return true; - } /* }}} */ - - function inheritsAccess() { return $this->_inheritAccess; } - - /** - * Set inherited access mode - * Setting inherited access mode will set or unset the internal flag which - * controls if the access mode is inherited from the parent folder or not. - * It will not modify the - * access control list for the current object. It will remove all - * notifications of users which do not even have read access anymore - * after setting or unsetting inherited access. - * - * @param boolean $inheritAccess set to true for setting and false for - * unsetting inherited access mode - * @param boolean $noclean set to true if notifier list shall not be clean up - * @return boolean true if operation was successful otherwise false - */ - function setInheritAccess($inheritAccess, $noclean=false) { /* {{{ */ - $db = $this->_dms->getDB(); - - $inheritAccess = ($inheritAccess) ? "1" : "0"; - - $queryStr = "UPDATE `tblFolders` SET `inheritAccess` = " . (int) $inheritAccess . " WHERE `id` = " . $this->_id; - if (!$db->getResult($queryStr)) - return false; - - $this->_inheritAccess = $inheritAccess; - - if(!$noclean) - $this->cleanNotifyList(); - - return true; - } /* }}} */ - - function getSequence() { return $this->_sequence; } - - function setSequence($seq) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblFolders` SET `sequence` = " . $seq . " WHERE `id` = " . $this->_id; - if (!$db->getResult($queryStr)) - return false; - - $this->_sequence = $seq; - return true; - } /* }}} */ - - /** - * Check if folder has subfolders - * This function just checks if a folder has subfolders disregarding - * any access rights. - * - * @return int number of subfolders or false in case of an error - */ - function hasSubFolders() { /* {{{ */ - $db = $this->_dms->getDB(); - if (isset($this->_subFolders)) { - /** @noinspection PhpUndefinedFieldInspection */ - return count($this->_subFolders); - } - $queryStr = "SELECT count(*) as c FROM `tblFolders` WHERE `parent` = " . $this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - return (int) $resArr[0]['c']; - } /* }}} */ - - /** - * Check if folder has as subfolder with given name - * - * @param string $name - * @return bool true if subfolder exists, false if not or in case - * of an error - */ - function hasSubFolderByName($name) { /* {{{ */ - $db = $this->_dms->getDB(); - /* Always check the database instead of iterating over $this->_documents, because - * it is probably not slower - */ - $queryStr = "SELECT count(*) as c FROM `tblFolders` WHERE `parent` = " . $this->_id . " AND `name` = ".$db->qstr($name); - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - return ($resArr[0]['c'] > 0); - } /* }}} */ - - /** - * Returns a list of subfolders - * This function does not check for access rights. Use - * {@link SeedDMS_Core_DMS::filterAccess} for checking each folder against - * the currently logged in user and the access rights. - * - * @param string $orderby if set to 'n' the list is ordered by name, otherwise - * it will be ordered by sequence - * @param string $dir direction of sorting (asc or desc) - * @param integer $limit limit number of subfolders - * @param integer $offset offset in retrieved list of subfolders - * @return SeedDMS_Core_Folder[]|bool list of folder objects or false in case of an error - */ - function getSubFolders($orderby="", $dir="asc", $limit=0, $offset=0) { /* {{{ */ - $db = $this->_dms->getDB(); - - if (!isset($this->_subFolders)) { - $queryStr = "SELECT * FROM `tblFolders` WHERE `parent` = " . $this->_id; - - 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; - - $classname = $this->_dms->getClassname('folder'); - $this->_subFolders = array(); - for ($i = 0; $i < count($resArr); $i++) -// $this->_subFolders[$i] = $this->_dms->getFolder($resArr[$i]["id"]); - $this->_subFolders[$i] = $classname::getInstanceByData($resArr[$i], $this->_dms); - } - - return $this->_subFolders; - } /* }}} */ - - /** - * Add a new subfolder - * - * @param string $name name of folder - * @param string $comment comment of folder - * @param object $owner owner of folder - * @param integer $sequence position of folder in list of sub folders. - * @param array $attributes list of document attributes. The element key - * must be the id of the attribute definition. - * @return bool|SeedDMS_Core_Folder - * an error. - */ - function addSubFolder($name, $comment, $owner, $sequence, $attributes=array()) { /* {{{ */ - $db = $this->_dms->getDB(); - - // Set the folderList of the folder - $pathPrefix=""; - $path = $this->getPath(); - foreach ($path as $f) { - $pathPrefix .= ":".$f->getID(); - } - if (strlen($pathPrefix)>1) { - $pathPrefix .= ":"; - } - - $db->startTransaction(); - - //inheritAccess = true, defaultAccess = M_READ - $queryStr = "INSERT INTO `tblFolders` (`name`, `parent`, `folderList`, `comment`, `date`, `owner`, `inheritAccess`, `defaultAccess`, `sequence`) ". - "VALUES (".$db->qstr($name).", ".$this->_id.", ".$db->qstr($pathPrefix).", ".$db->qstr($comment).", ".$db->getCurrentTimestamp().", ".$owner->getID().", 1, ".M_READ.", ". $sequence.")"; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - $newFolder = $this->_dms->getFolder($db->getInsertID('tblFolders')); - unset($this->_subFolders); - - if($attributes) { - foreach($attributes as $attrdefid=>$attribute) { - if($attribute) - if($attrdef = $this->_dms->getAttributeDefinition($attrdefid)) { - if(!$newFolder->setAttributeValue($attrdef, $attribute)) { - $db->rollbackTransaction(); - return false; - } - } else { - $db->rollbackTransaction(); - return false; - } - } - } - - $db->commitTransaction(); - - /* Check if 'onPostAddSubFolder' callback is set */ - if(isset($this->_dms->callbacks['onPostAddSubFolder'])) { - foreach($this->_dms->callbacks['onPostAddSubFolder'] as $callback) { - /** @noinspection PhpStatementHasEmptyBodyInspection */ - if(!call_user_func($callback[0], $callback[1], $newFolder)) { - } - } - } - - return $newFolder; - } /* }}} */ - - /** - * Returns an array of all parents, grand parent, etc. up to root folder. - * The folder itself is the last element of the array. - * - * @return array|bool - */ - function getPath() { /* {{{ */ - if (!isset($this->_parentID) || ($this->_parentID == "") || ($this->_parentID == 0) || ($this->_id == $this->_dms->rootFolderID)) { - return array($this); - } - else { - $res = $this->getParent(); - if (!$res) return false; - - $path = $this->_parent->getPath(); - if (!$path) return false; - - array_push($path, $this); - return $path; - } - } /* }}} */ - - /** - * Returns a file system path - * - * This path contains by default spaces around the slashes for better readability. - * Run str_replace(' / ', '/', $path) on it or pass '/' as $sep to get a valid unix - * file system path. - * - * @param bool $skiproot skip the name of the root folder and start with $sep - * @param string $sep separator between path elements - * @return string path separated with ' / ' - */ - function getFolderPathPlain($skiproot = false, $sep = ' / ') { /* {{{ */ - $path="".$sep; - $folderPath = $this->getPath(); - for ($i = 0; $i < count($folderPath); $i++) { - if($i > 0 || !$skiproot) { - $path .= $folderPath[$i]->getName(); - if ($i+1 < count($folderPath)) - $path .= $sep; - } - } - return trim($path); - } /* }}} */ - - /** - * Check, if this folder is a subfolder of a given folder - * - * This is basically the opposite of {@see SeedDMS_Core_Folder::isSubFolder()} - * - * @param object $folder parent folder - * @return boolean true if folder is a subfolder - */ - function isDescendant($folder) { /* {{{ */ - /* If the current folder has no parent it cannot be a descendant */ - if(!$this->getParent()) - return false; - /* Check if the passed folder is the parent of the current folder. - * In that case the current folder is a subfolder of the passed folder. - */ - if($this->getParent()->getID() == $folder->getID()) - return true; - /* Recursively go up to the root folder */ - return $this->getParent()->isDescendant($folder); - } /* }}} */ - - /** - * Check if folder has documents - * This function just checks if a folder has documents diregarding - * any access rights. - * - * @return int number of documents or false in case of an error - */ - function hasDocuments() { /* {{{ */ - $db = $this->_dms->getDB(); - /* Do not use the cache because it may not contain all documents if - * the former call getDocuments() limited the number of documents - if (isset($this->_documents)) { - return count($this->_documents); - } - */ - $queryStr = "SELECT count(*) as c FROM `tblDocuments` WHERE `folder` = " . $this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - return (int) $resArr[0]['c']; - } /* }}} */ - - /** - * Check if folder has document with given name - * - * @param string $name - * @return bool true if document exists, false if not or in case - * of an error - */ - function hasDocumentByName($name) { /* {{{ */ - $db = $this->_dms->getDB(); - /* Always check the database instead of iterating over $this->_documents, because - * it is probably not slower - */ - $queryStr = "SELECT count(*) as c FROM `tblDocuments` WHERE `folder` = " . $this->_id . " AND `name` = ".$db->qstr($name); - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - return ($resArr[0]['c'] > 0); - } /* }}} */ - - /** - * Get all documents of the folder - * This function does not check for access rights. Use - * {@link SeedDMS_Core_DMS::filterAccess} for checking each document against - * the currently logged in user and the access rights. - * - * @param string $orderby if set to 'n' the list is ordered by name, otherwise - * it will be ordered by sequence - * @param string $dir direction of sorting (asc or desc) - * @param integer $limit limit number of documents - * @param integer $offset offset in retrieved list of documents - * @return SeedDMS_Core_Document[]|bool list of documents or false in case of an error - */ - function getDocuments($orderby="", $dir="asc", $limit=0, $offset=0) { /* {{{ */ - $db = $this->_dms->getDB(); - - if (!isset($this->_documents)) { - $queryStr = "SELECT `tblDocuments`.*, `tblDocumentLocks`.`userID` as `lock` FROM `tblDocuments` LEFT JOIN `tblDocumentLocks` ON `tblDocuments`.`id` = `tblDocumentLocks`.`document` WHERE `folder` = " . $this->_id; - 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) - return false; - - $this->_documents = array(); - $classname = $this->_dms->getClassname('document'); - foreach ($resArr as $row) { - $row['lock'] = !$row['lock'] ? -1 : $row['lock']; -// array_push($this->_documents, $this->_dms->getDocument($row["id"])); - array_push($this->_documents, $classname::getInstanceByData($row, $this->_dms)); - } - } - return $this->_documents; - } /* }}} */ - - /** - * Count all documents and subfolders of the folder - * - * This function also counts documents and folders of subfolders, so - * basically it works like recursively counting children. - * - * This function checks for access rights up the given limit. If more - * documents or folders are found, the returned value will be the number - * of objects available and the precise flag in the return array will be - * set to false. This number should not be revelead to the - * user, because it allows to gain information about the existens of - * objects without access right. - * Setting the parameter $limit to 0 will turn off access right checking - * which is reasonable if the $user is an administrator. - * - * @param SeedDMS_Core_User $user - * @param integer $limit maximum number of folders and documents that will - * be precisly counted by taken the access rights into account - * @return array|bool with four elements 'document_count', 'folder_count' - * 'document_precise', 'folder_precise' holding - * the counted number and a flag if the number is precise. - * @internal param string $orderby if set to 'n' the list is ordered by name, otherwise - * it will be ordered by sequence - */ - function countChildren($user, $limit=10000) { /* {{{ */ - $db = $this->_dms->getDB(); - - $pathPrefix=""; - $path = $this->getPath(); - foreach ($path as $f) { - $pathPrefix .= ":".$f->getID(); - } - if (strlen($pathPrefix)>1) { - $pathPrefix .= ":"; - } - - $queryStr = "SELECT id FROM `tblFolders` WHERE `folderList` like '".$pathPrefix. "%'"; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - $result = array(); - - $folders = array(); - $folderids = array($this->_id); - $cfolders = count($resArr); - if($cfolders < $limit) { - foreach ($resArr as $row) { - $folder = $this->_dms->getFolder($row["id"]); - if ($folder->getAccessMode($user) >= M_READ) { - array_push($folders, $folder); - array_push($folderids, $row['id']); - } - } - $result['folder_count'] = count($folders); - $result['folder_precise'] = true; - } else { - foreach ($resArr as $row) { - array_push($folderids, $row['id']); - } - $result['folder_count'] = $cfolders; - $result['folder_precise'] = false; - } - - $documents = array(); - if($folderids) { - $queryStr = "SELECT id FROM `tblDocuments` WHERE `folder` in (".implode(',', $folderids). ")"; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - $cdocs = count($resArr); - if($cdocs < $limit) { - foreach ($resArr as $row) { - $document = $this->_dms->getDocument($row["id"]); - if ($document->getAccessMode($user) >= M_READ) - array_push($documents, $document); - } - $result['document_count'] = count($documents); - $result['document_precise'] = true; - } else { - $result['document_count'] = $cdocs; - $result['document_precise'] = false; - } - } - - return $result; - } /* }}} */ - - // $comment will be used for both document and version leaving empty the version_comment - /** - * Add a new document to the folder - * This function will add a new document and its content from a given file. - * It does not check for access rights on the folder. The new documents - * default access right is read only and the access right is inherited. - * - * @param string $name name of new document - * @param string $comment comment of new document - * @param integer $expires expiration date as a unix timestamp or 0 for no - * expiration date - * @param object $owner owner of the new document - * @param SeedDMS_Core_User $keywords keywords of new document - * @param SeedDMS_Core_DocumentCategory[] $categories list of category objects - * @param string $tmpFile the path of the file containing the content - * @param string $orgFileName the original file name - * @param string $fileType usually the extension of the filename - * @param string $mimeType mime type of the content - * @param float $sequence position of new document within the folder - * @param array $reviewers list of users who must review this document - * @param array $approvers list of users who must approve this document - * @param int|string $reqversion version number of the content - * @param string $version_comment comment of the content. If left empty - * the $comment will be used. - * @param array $attributes list of document attributes. The element key - * must be the id of the attribute definition. - * @param array $version_attributes list of document version attributes. - * The element key must be the id of the attribute definition. - * @param SeedDMS_Core_Workflow $workflow - * @return array|bool false in case of error, otherwise an array - * containing two elements. The first one is the new document, the - * second one is the result set returned when inserting the content. - */ - function addDocument($name, $comment, $expires, $owner, $keywords, $categories, $tmpFile, $orgFileName, $fileType, $mimeType, $sequence, $reviewers=array(), $approvers=array(),$reqversion=0,$version_comment="", $attributes=array(), $version_attributes=array(), $workflow=null) { /* {{{ */ - $db = $this->_dms->getDB(); - - $expires = (!$expires) ? 0 : $expires; - - // Must also ensure that the document has a valid folderList. - $pathPrefix=""; - $path = $this->getPath(); - foreach ($path as $f) { - $pathPrefix .= ":".$f->getID(); - } - if (strlen($pathPrefix)>1) { - $pathPrefix .= ":"; - } - - $db->startTransaction(); - - $queryStr = "INSERT INTO `tblDocuments` (`name`, `comment`, `date`, `expires`, `owner`, `folder`, `folderList`, `inheritAccess`, `defaultAccess`, `locked`, `keywords`, `sequence`) VALUES ". - "(".$db->qstr($name).", ".$db->qstr($comment).", ".$db->getCurrentTimestamp().", ".(int) $expires.", ".$owner->getID().", ".$this->_id.",".$db->qstr($pathPrefix).", 1, ".M_READ.", -1, ".$db->qstr($keywords).", " . $sequence . ")"; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - $document = $this->_dms->getDocument($db->getInsertID('tblDocuments')); - - $res = $document->addContent($version_comment, $owner, $tmpFile, $orgFileName, $fileType, $mimeType, $reviewers, $approvers, $reqversion, $version_attributes, $workflow); - - if (is_bool($res) && !$res) { - $db->rollbackTransaction(); - return false; - } - - if($categories) { - if(!$document->setCategories($categories)) { - $document->remove(); - $db->rollbackTransaction(); - return false; - } - } - - if($attributes) { - foreach($attributes as $attrdefid=>$attribute) { - /* $attribute can be a string or an array */ - if($attribute) { - if($attrdef = $this->_dms->getAttributeDefinition($attrdefid)) { - if(!$document->setAttributeValue($attrdef, $attribute)) { - $document->remove(); - $db->rollbackTransaction(); - return false; - } - } else { - $document->remove(); - $db->rollbackTransaction(); - return false; - } - } - } - } - - $db->commitTransaction(); - - /* Check if 'onPostAddDocument' callback is set */ - if(isset($this->_dms->callbacks['onPostAddDocument'])) { - foreach($this->_dms->callbacks['onPostAddDocument'] as $callback) { - /** @noinspection PhpStatementHasEmptyBodyInspection */ - if(!call_user_func($callback[0], $callback[1], $document)) { - } - } - } - - return array($document, $res); - } /* }}} */ - - /** - * Remove a single folder - * - * Removes just a single folder, but not its subfolders or documents - * This function will fail if the folder has subfolders or documents - * because of referencial integrity errors. - * - * @return boolean true on success, false in case of an error - */ - protected function removeFromDatabase() { /* {{{ */ - $db = $this->_dms->getDB(); - - /* Check if 'onPreRemoveFolder' callback is set */ - if(isset($this->_dms->callbacks['onPreRemoveFromDatabaseFolder'])) { - foreach($this->_dms->callbacks['onPreRemoveFromDatabaseFolder'] as $callback) { - $ret = call_user_func($callback[0], $callback[1], $this); - if(is_bool($ret)) - return $ret; - } - } - - $db->startTransaction(); - // unset homefolder as it will no longer exist - $queryStr = "UPDATE `tblUsers` SET `homefolder`=NULL WHERE `homefolder` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - // Remove database entries - $queryStr = "DELETE FROM `tblFolders` WHERE `id` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - $queryStr = "DELETE FROM `tblFolderAttributes` WHERE `folder` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - $queryStr = "DELETE FROM `tblACLs` WHERE `target` = ". $this->_id. " AND `targetType` = " . T_FOLDER; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - $queryStr = "DELETE FROM `tblNotify` WHERE `target` = ". $this->_id. " AND `targetType` = " . T_FOLDER; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - $db->commitTransaction(); - - /* Check if 'onPostRemoveFolder' callback is set */ - if(isset($this->_dms->callbacks['onPostRemoveFromDatabaseFolder'])) { - foreach($this->_dms->callbacks['onPostRemoveFromDatabaseFolder'] as $callback) { - /** @noinspection PhpStatementHasEmptyBodyInspection */ - if(!call_user_func($callback[0], $callback[1], $this->_id)) { - } - } - } - - return true; - } /* }}} */ - - /** - * Remove recursively a folder - * - * Removes a folder, all its subfolders and documents - * This method triggers the callbacks onPreRemoveFolder and onPostRemoveFolder. - * If onPreRemoveFolder returns a boolean then this method will return - * imediately with the value returned by the callback. Otherwise the - * regular removal is executed, which in turn - * triggers further onPreRemoveFolder and onPostRemoveFolder callbacks - * and its counterparts for documents (onPreRemoveDocument, onPostRemoveDocument). - * - * @return boolean true on success, false in case of an error - */ - function remove() { /* {{{ */ - /** @noinspection PhpUnusedLocalVariableInspection */ - $db = $this->_dms->getDB(); - - // Do not delete the root folder. - if ($this->_id == $this->_dms->rootFolderID || !isset($this->_parentID) || ($this->_parentID == null) || ($this->_parentID == "") || ($this->_parentID == 0)) { - return false; - } - - /* Check if 'onPreRemoveFolder' callback is set */ - if(isset($this->_dms->callbacks['onPreRemoveFolder'])) { - foreach($this->_dms->callbacks['onPreRemoveFolder'] as $callback) { - $ret = call_user_func($callback[0], $callback[1], $this); - if(is_bool($ret)) - return $ret; - } - } - - //Entfernen der Unterordner und Dateien - $res = $this->getSubFolders(); - if (is_bool($res) && !$res) return false; - $res = $this->getDocuments(); - if (is_bool($res) && !$res) return false; - - foreach ($this->_subFolders as $subFolder) { - $res = $subFolder->remove(); - if (!$res) { - return false; - } - } - - foreach ($this->_documents as $document) { - $res = $document->remove(); - if (!$res) { - return false; - } - } - - $ret = $this->removeFromDatabase(); - if(!$ret) - return $ret; - - /* Check if 'onPostRemoveFolder' callback is set */ - if(isset($this->_dms->callbacks['onPostRemoveFolder'])) { - foreach($this->_dms->callbacks['onPostRemoveFolder'] as $callback) { - call_user_func($callback[0], $callback[1], $this); - } - } - - return $ret; - } /* }}} */ - - /** - * Empty recursively a folder - * - * Removes all subfolders and documents of a folder but not the folder itself - * This method will call remove() on all its children. - * This method triggers the callbacks onPreEmptyFolder and onPostEmptyFolder. - * If onPreEmptyFolder returns a boolean then this method will return - * imediately. - * Be aware that the recursive calls of remove() will trigger the callbacks - * onPreRemoveFolder, onPostRemoveFolder, onPreRemoveDocument and onPostRemoveDocument. - * - * @return boolean true on success, false in case of an error - */ - function emptyFolder() { /* {{{ */ - /** @noinspection PhpUnusedLocalVariableInspection */ - $db = $this->_dms->getDB(); - - /* Check if 'onPreEmptyFolder' callback is set */ - if(isset($this->_dms->callbacks['onPreEmptyFolder'])) { - foreach($this->_dms->callbacks['onPreEmptyFolder'] as $callback) { - $ret = call_user_func($callback[0], $callback[1], $this); - if(is_bool($ret)) - return $ret; - } - } - - //Entfernen der Unterordner und Dateien - $res = $this->getSubFolders(); - if (is_bool($res) && !$res) return false; - $res = $this->getDocuments(); - if (is_bool($res) && !$res) return false; - - foreach ($this->_subFolders as $subFolder) { - $res = $subFolder->remove(); - if (!$res) { - return false; - } - } - - foreach ($this->_documents as $document) { - $res = $document->remove(); - if (!$res) { - return false; - } - } - - /* Check if 'onPostEmptyFolder' callback is set */ - if(isset($this->_dms->callbacks['onPostEmptyFolder'])) { - foreach($this->_dms->callbacks['onPostEmptyFolder'] as $callback) { - call_user_func($callback[0], $callback[1], $this); - } - } - - return true; - } /* }}} */ - - /** - * Returns a list of access privileges - * - * If the folder inherits the access privileges from the parent folder - * those will be returned. - * $mode and $op can be set to restrict the list of returned access - * privileges. If $mode is set to M_ANY no restriction will apply - * regardless of the value of $op. The returned array contains a list - * of {@link SeedDMS_Core_UserAccess} and - * {@link SeedDMS_Core_GroupAccess} objects. Even if the document - * has no access list the returned array contains the two elements - * 'users' and 'groups' which are than empty. The methode returns false - * if the function fails. - * - * @param integer $mode access mode (defaults to M_ANY) - * @param integer $op operation (defaults to O_EQ) - * @return bool|SeedDMS_Core_GroupAccess|SeedDMS_Core_UserAccess - */ - function getAccessList($mode = M_ANY, $op = O_EQ) { /* {{{ */ - $db = $this->_dms->getDB(); - - if ($this->inheritsAccess()) { - /* Access is supposed to be inherited but it could be that there - * is no parent because the configured root folder id is somewhere - * below the actual root folder. - */ - $res = $this->getParent(); - if ($res) - return $this->_parent->getAccessList($mode, $op); - } - - if (!isset($this->_accessList[$mode])) { - if ($op!=O_GTEQ && $op!=O_LTEQ && $op!=O_EQ) { - return false; - } - $modeStr = ""; - if ($mode!=M_ANY) { - $modeStr = " AND `mode`".$op.(int)$mode; - } - $queryStr = "SELECT * FROM `tblACLs` WHERE `targetType` = ".T_FOLDER. - " AND `target` = " . $this->_id . $modeStr . " ORDER BY `targetType`"; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - $this->_accessList[$mode] = array("groups" => array(), "users" => array()); - foreach ($resArr as $row) { - if ($row["userID"] != -1) - array_push($this->_accessList[$mode]["users"], new SeedDMS_Core_UserAccess($this->_dms->getUser($row["userID"]), (int) $row["mode"])); - else //if ($row["groupID"] != -1) - array_push($this->_accessList[$mode]["groups"], new SeedDMS_Core_GroupAccess($this->_dms->getGroup($row["groupID"]), (int) $row["mode"])); - } - } - - return $this->_accessList[$mode]; - } /* }}} */ - - /** - * Delete all entries for this folder from the access control list - * - * @param boolean $noclean set to true if notifier list shall not be clean up - * @return boolean true if operation was successful otherwise false - */ - function clearAccessList($noclean=false) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "DELETE FROM `tblACLs` WHERE `targetType` = " . T_FOLDER . " AND `target` = " . $this->_id; - if (!$db->getResult($queryStr)) - return false; - - unset($this->_accessList); - - if(!$noclean) - $this->cleanNotifyList(); - - return true; - } /* }}} */ - - /** - * Add access right to folder - * This function may change in the future. Instead of passing the a flag - * and a user/group id a user or group object will be expected. - * - * @param integer $mode access mode - * @param integer $userOrGroupID id of user or group - * @param integer $isUser set to 1 if $userOrGroupID is the id of a - * user - * @return bool - */ - function addAccess($mode, $userOrGroupID, $isUser) { /* {{{ */ - $db = $this->_dms->getDB(); - - if($mode < M_NONE || $mode > M_ALL) - return false; - - $userOrGroup = ($isUser) ? "`userID`" : "`groupID`"; - - /* Adding a second access right will return false */ - $queryStr = "SELECT * FROM `tblACLs` WHERE `targetType` = ".T_FOLDER. - " AND `target` = " . $this->_id . " AND ". $userOrGroup . " = ".$userOrGroupID; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) || $resArr) - return false; - - $queryStr = "INSERT INTO `tblACLs` (`target`, `targetType`, ".$userOrGroup.", `mode`) VALUES - (".$this->_id.", ".T_FOLDER.", " . (int) $userOrGroupID . ", " .(int) $mode. ")"; - if (!$db->getResult($queryStr)) - return false; - - unset($this->_accessList); - - // Update the notify list, if necessary. - if ($mode == M_NONE) { - $this->removeNotify($userOrGroupID, $isUser); - } - - return true; - } /* }}} */ - - /** - * Change access right of folder - * This function may change in the future. Instead of passing the a flag - * and a user/group id a user or group object will be expected. - * - * @param integer $newMode access mode - * @param integer $userOrGroupID id of user or group - * @param integer $isUser set to 1 if $userOrGroupID is the id of a - * user - * @return bool - */ - function changeAccess($newMode, $userOrGroupID, $isUser) { /* {{{ */ - $db = $this->_dms->getDB(); - - $userOrGroup = ($isUser) ? "`userID`" : "`groupID`"; - - $queryStr = "UPDATE `tblACLs` SET `mode` = " . (int) $newMode . " WHERE `targetType` = ".T_FOLDER." AND `target` = " . $this->_id . " AND " . $userOrGroup . " = " . (int) $userOrGroupID; - if (!$db->getResult($queryStr)) - return false; - - unset($this->_accessList); - - // Update the notify list, if necessary. - if ($newMode == M_NONE) { - $this->removeNotify($userOrGroupID, $isUser); - } - - return true; - } /* }}} */ - - /** - * @param $userOrGroupID - * @param $isUser - * @return bool - */ - function removeAccess($userOrGroupID, $isUser) { /* {{{ */ - $db = $this->_dms->getDB(); - - $userOrGroup = ($isUser) ? "`userID`" : "`groupID`"; - - $queryStr = "DELETE FROM `tblACLs` WHERE `targetType` = ".T_FOLDER." AND `target` = ".$this->_id." AND ".$userOrGroup." = " . (int) $userOrGroupID; - if (!$db->getResult($queryStr)) - return false; - - unset($this->_accessList); - - // Update the notify list, if necessary. - $mode = ($isUser ? $this->getAccessMode($this->_dms->getUser($userOrGroupID)) : $this->getGroupAccessMode($this->_dms->getGroup($userOrGroupID))); - if ($mode == M_NONE) { - $this->removeNotify($userOrGroupID, $isUser); - } - - return true; - } /* }}} */ - - /** - * Get the access mode of a user on the folder - * - * The access mode is either M_READ, M_READWRITE, M_ALL, or M_NONE. - * It is determined - * - by the user (admins and owners have always access mode M_ALL) - * - by the access list for the user (possibly inherited) - * - by the default access mode - * - * This function returns the access mode for a given user. An administrator - * and the owner of the folder has unrestricted access. A guest user has - * read only access or no access if access rights are further limited - * by access control lists all the default access. - * All other users have access rights according - * to the access control lists or the default access. This function will - * recursively check for access rights of parent folders if access rights - * are inherited. - * - * Before checking the access itself a callback 'onCheckAccessFolder' - * is called. If it returns a value > 0, then this will be returned by this - * method without any further checks. The optional paramater $context - * will be passed as a third parameter to the callback. It contains - * the operation for which the access mode is retrieved. It is for example - * set to 'removeDocument' if the access mode is used to check for sufficient - * permission on deleting a document. This callback could be used to - * override any existing access mode in a certain context. - * - * @param SeedDMS_Core_User $user user for which access shall be checked - * @param string $context context in which the access mode is requested - * @return integer access mode - */ - function getAccessMode($user, $context='') { /* {{{ */ - if(!$user) - return M_NONE; - - /* Check if 'onCheckAccessFolder' callback is set */ - if(isset($this->_dms->callbacks['onCheckAccessFolder'])) { - foreach($this->_dms->callbacks['onCheckAccessFolder'] as $callback) { - if(($ret = call_user_func($callback[0], $callback[1], $this, $user, $context)) > 0) { - return $ret; - } - } - } - - /* Administrators have unrestricted access */ - if ($user->isAdmin()) return M_ALL; - - /* The owner of the folder has unrestricted access */ - if ($user->getID() == $this->_ownerID) return M_ALL; - - /* Check ACLs */ - $accessList = $this->getAccessList(); - if (!$accessList) return false; - - /** @var SeedDMS_Core_UserAccess $userAccess */ - foreach ($accessList["users"] as $userAccess) { - if ($userAccess->getUserID() == $user->getID()) { - $mode = $userAccess->getMode(); - if ($user->isGuest()) { - if ($mode >= M_READ) $mode = M_READ; - } - return $mode; - } - } - - /* Get the highest right defined by a group */ - if($accessList['groups']) { - $mode = 0; - /** @var SeedDMS_Core_GroupAccess $groupAccess */ - foreach ($accessList["groups"] as $groupAccess) { - if ($user->isMemberOfGroup($groupAccess->getGroup())) { - if ($groupAccess->getMode() > $mode) - $mode = $groupAccess->getMode(); - } - } - if($mode) { - if ($user->isGuest()) { - if ($mode >= M_READ) $mode = M_READ; - } - return $mode; - } - } - - $mode = $this->getDefaultAccess(); - if ($user->isGuest()) { - if ($mode >= M_READ) $mode = M_READ; - } - return $mode; - } /* }}} */ - - /** - * Get the access mode for a group on the folder - * This function returns the access mode for a given group. The algorithmn - * applied to get the access mode is the same as describe at - * {@link getAccessMode} - * - * @param SeedDMS_Core_Group $group group for which access shall be checked - * @return integer access mode - */ - function getGroupAccessMode($group) { /* {{{ */ - $highestPrivileged = M_NONE; - $foundInACL = false; - $accessList = $this->getAccessList(); - if (!$accessList) - return false; - - /** @var SeedDMS_Core_GroupAccess $groupAccess */ - foreach ($accessList["groups"] as $groupAccess) { - if ($groupAccess->getGroupID() == $group->getID()) { - $foundInACL = true; - if ($groupAccess->getMode() > $highestPrivileged) - $highestPrivileged = $groupAccess->getMode(); - if ($highestPrivileged == M_ALL) /* no need to check further */ - return $highestPrivileged; - } - } - if ($foundInACL) - return $highestPrivileged; - - /* Take default access */ - return $this->getDefaultAccess(); - } /* }}} */ - - /** @noinspection PhpUnusedParameterInspection */ - /** - * Get a list of all notification - * This function returns all users and groups that have registerd a - * notification for the folder - * - * @param integer $type type of notification (not yet used) - * @param bool $incdisabled set to true if disabled user shall be included - * @return SeedDMS_Core_User[]|SeedDMS_Core_Group[]|bool array with a the elements 'users' and 'groups' which - * contain a list of users and groups. - */ - function getNotifyList($type=0, $incdisabled=false) { /* {{{ */ - if (empty($this->_notifyList)) { - $db = $this->_dms->getDB(); - - $queryStr ="SELECT * FROM `tblNotify` WHERE `targetType` = " . T_FOLDER . " AND `target` = " . $this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && $resArr == false) - return false; - - $this->_notifyList = array("groups" => array(), "users" => array()); - foreach ($resArr as $row) - { - if ($row["userID"] != -1) { - $u = $this->_dms->getUser($row["userID"]); - if($u && (!$u->isDisabled() || $incdisabled)) - array_push($this->_notifyList["users"], $u); - } else {//if ($row["groupID"] != -1) - $g = $this->_dms->getGroup($row["groupID"]); - if($g) - array_push($this->_notifyList["groups"], $g); - } - } - } - return $this->_notifyList; - } /* }}} */ - - /** - * Make sure only users/groups with read access are in the notify list - * - */ - function cleanNotifyList() { /* {{{ */ - // If any of the notification subscribers no longer have read access, - // remove their subscription. - if (empty($this->_notifyList)) - $this->getNotifyList(); - - /* Make a copy of both notifier lists because removeNotify will empty - * $this->_notifyList and the second foreach will not work anymore. - */ - /** @var SeedDMS_Core_User[] $nusers */ - $nusers = $this->_notifyList["users"]; - $ngroups = $this->_notifyList["groups"]; - foreach ($nusers as $u) { - if ($this->getAccessMode($u) < M_READ) { - $this->removeNotify($u->getID(), true); - } - } - - /** @var SeedDMS_Core_Group[] $ngroups */ - foreach ($ngroups as $g) { - if ($this->getGroupAccessMode($g) < M_READ) { - $this->removeNotify($g->getID(), false); - } - } - } /* }}} */ - - /** - * Add a user/group to the notification list - * This function does not check if the currently logged in user - * is allowed to add a notification. This must be checked by the calling - * application. - * - * @param integer $userOrGroupID - * @param boolean $isUser true if $userOrGroupID is a user id otherwise false - * @return integer error code - * -1: Invalid User/Group ID. - * -2: Target User / Group does not have read access. - * -3: User is already subscribed. - * -4: Database / internal error. - * 0: Update successful. - */ - function addNotify($userOrGroupID, $isUser) { /* {{{ */ - $db = $this->_dms->getDB(); - - $userOrGroup = ($isUser) ? "`userID`" : "`groupID`"; - - /* Verify that user / group exists */ - /** @var SeedDMS_Core_User|SeedDMS_Core_Group $obj */ - $obj = ($isUser ? $this->_dms->getUser($userOrGroupID) : $this->_dms->getGroup($userOrGroupID)); - if (!is_object($obj)) { - return -1; - } - - /* Verify that the requesting user has permission to add the target to - * the notification system. - */ - /* - * The calling application should enforce the policy on who is allowed - * to add someone to the notification system. If is shall remain here - * the currently logged in user should be passed to this function - * - GLOBAL $user; - if ($user->isGuest()) { - return -2; - } - if (!$user->isAdmin()) { - if ($isUser) { - if ($user->getID() != $obj->getID()) { - return -2; - } - } - else { - if (!$obj->isMember($user)) { - return -2; - } - } - } - */ - - // - // Verify that user / group has read access to the document. - // - if ($isUser) { - // Users are straightforward to check. - if ($this->getAccessMode($obj) < M_READ) { - return -2; - } - } - else { - // FIXME: Why not check the access list first and if this returns - // not result, then use the default access? - // Groups are a little more complex. - if ($this->getDefaultAccess() >= M_READ) { - // If the default access is at least READ-ONLY, then just make sure - // that the current group has not been explicitly excluded. - $acl = $this->getAccessList(M_NONE, O_EQ); - $found = false; - /** @var SeedDMS_Core_GroupAccess $group */ - foreach ($acl["groups"] as $group) { - if ($group->getGroupID() == $userOrGroupID) { - $found = true; - break; - } - } - if ($found) { - return -2; - } - } - else { - // The default access is restricted. Make sure that the group has - // been explicitly allocated access to the document. - $acl = $this->getAccessList(M_READ, O_GTEQ); - if (is_bool($acl)) { - return -4; - } - $found = false; - /** @var SeedDMS_Core_GroupAccess $group */ - foreach ($acl["groups"] as $group) { - if ($group->getGroupID() == $userOrGroupID) { - $found = true; - break; - } - } - if (!$found) { - return -2; - } - } - } - // - // Check to see if user/group is already on the list. - // - $queryStr = "SELECT * FROM `tblNotify` WHERE `tblNotify`.`target` = '".$this->_id."' ". - "AND `tblNotify`.`targetType` = '".T_FOLDER."' ". - "AND `tblNotify`.".$userOrGroup." = '". (int) $userOrGroupID."'"; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr)) { - return -4; - } - if (count($resArr)>0) { - return -3; - } - - $queryStr = "INSERT INTO `tblNotify` (`target`, `targetType`, " . $userOrGroup . ") VALUES (" . $this->_id . ", " . T_FOLDER . ", " . (int) $userOrGroupID . ")"; - if (!$db->getResult($queryStr)) - return -4; - - unset($this->_notifyList); - return 0; - } /* }}} */ - - /** - * Removes notify for a user or group to folder - * This function does not check if the currently logged in user - * is allowed to remove a notification. This must be checked by the calling - * application. - * - * @param integer $userOrGroupID - * @param boolean $isUser true if $userOrGroupID is a user id otherwise false - * @param int $type type of notification (0 will delete all) Not used yet! - * @return int error code - * -1: Invalid User/Group ID. - * -3: User is not subscribed. - * -4: Database / internal error. - * 0: Update successful. - */ - function removeNotify($userOrGroupID, $isUser, $type=0) { /* {{{ */ - $db = $this->_dms->getDB(); - - /* Verify that user / group exists. */ - $obj = ($isUser ? $this->_dms->getUser($userOrGroupID) : $this->_dms->getGroup($userOrGroupID)); - if (!is_object($obj)) { - return -1; - } - - $userOrGroup = ($isUser) ? "`userID`" : "`groupID`"; - - /* Verify that the requesting user has permission to add the target to - * the notification system. - */ - /* - * The calling application should enforce the policy on who is allowed - * to add someone to the notification system. If is shall remain here - * the currently logged in user should be passed to this function - * - GLOBAL $user; - if ($user->isGuest()) { - return -2; - } - if (!$user->isAdmin()) { - if ($isUser) { - if ($user->getID() != $obj->getID()) { - return -2; - } - } - else { - if (!$obj->isMember($user)) { - return -2; - } - } - } - */ - - // - // Check to see if the target is in the database. - // - $queryStr = "SELECT * FROM `tblNotify` WHERE `tblNotify`.`target` = '".$this->_id."' ". - "AND `tblNotify`.`targetType` = '".T_FOLDER."' ". - "AND `tblNotify`.".$userOrGroup." = '". (int) $userOrGroupID."'"; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr)) { - return -4; - } - if (count($resArr)==0) { - return -3; - } - - $queryStr = "DELETE FROM `tblNotify` WHERE `target` = " . $this->_id . " AND `targetType` = " . T_FOLDER . " AND " . $userOrGroup . " = " . (int) $userOrGroupID; - /* If type is given then delete only those notifications */ - if($type) - $queryStr .= " AND `type` = ".(int) $type; - if (!$db->getResult($queryStr)) - return -4; - - unset($this->_notifyList); - return 0; - } /* }}} */ - - /** - * Get List of users and groups which have read access on the document - * - * This function is deprecated. Use - * {@see SeedDMS_Core_Folder::getReadAccessList()} instead. - */ - function getApproversList() { /* {{{ */ - return $this->getReadAccessList(0, 0); - } /* }}} */ - - /** - * Returns a list of groups and users with read access on the folder - * The list will not include any guest users, - * administrators and the owner of the folder unless $listadmin resp. - * $listowner is set to true. - * - * @param boolean $listadmin if set to true any admin will be listed too - * @param boolean $listowner if set to true the owner will be listed too - * @param boolean $listguest if set to true any guest will be listed too - * @return array list of users and groups - */ - function getReadAccessList($listadmin=0, $listowner=0, $listguest=0) { /* {{{ */ - $db = $this->_dms->getDB(); - - if (!isset($this->_readAccessList)) { - $this->_readAccessList = array("groups" => array(), "users" => array()); - $userIDs = ""; - $groupIDs = ""; - $defAccess = $this->getDefaultAccess(); - - /* Check if the default access is < read access or >= read access. - * If default access is less than read access, then create a list - * of users and groups with read access. - * If default access is equal or greater then read access, then - * create a list of users and groups without read access. - */ - if ($defAccessgetAccessList(M_READ, O_GTEQ); - } - else { - // Get the list of all users and groups that DO NOT have read access - // to the folder. - $tmpList = $this->getAccessList(M_NONE, O_LTEQ); - } - /** @var SeedDMS_Core_GroupAccess $groupAccess */ - foreach ($tmpList["groups"] as $groupAccess) { - $groupIDs .= (strlen($groupIDs)==0 ? "" : ", ") . $groupAccess->getGroupID(); - } - - /** @var SeedDMS_Core_UserAccess $userAccess */ - foreach ($tmpList["users"] as $userAccess) { - $user = $userAccess->getUser(); - if (!$listadmin && $user->isAdmin()) continue; - if (!$listowner && $user->getID() == $this->_ownerID) continue; - if (!$listguest && $user->isGuest()) continue; - $userIDs .= (strlen($userIDs)==0 ? "" : ", ") . $userAccess->getUserID(); - } - - // Construct a query against the users table to identify those users - // that have read access to this folder, either directly through an - // ACL entry, by virtue of ownership or by having administrative rights - // on the database. - $queryStr=""; - /* If default access is less then read, $userIDs and $groupIDs contains - * a list of user with read access - */ - if ($defAccess < M_READ) { - if (strlen($groupIDs)>0) { - $queryStr = "SELECT `tblUsers`.* FROM `tblUsers` ". - "LEFT JOIN `tblGroupMembers` ON `tblGroupMembers`.`userID`=`tblUsers`.`id` ". - "WHERE `tblGroupMembers`.`groupID` IN (". $groupIDs .") ". - "AND `tblUsers`.`role` != ".SeedDMS_Core_User::role_guest." UNION "; - } - $queryStr .= - "SELECT `tblUsers`.* FROM `tblUsers` ". - "WHERE (`tblUsers`.`role` != ".SeedDMS_Core_User::role_guest.") ". - "AND ((`tblUsers`.`id` = ". $this->_ownerID . ") ". - "OR (`tblUsers`.`role` = ".SeedDMS_Core_User::role_admin.")". - (strlen($userIDs) == 0 ? "" : " OR (`tblUsers`.`id` IN (". $userIDs ."))"). - ") ORDER BY `login`"; - } - /* If default access is equal or greater than M_READ, $userIDs and - * $groupIDs contains a list of user without read access - */ - else { - if (strlen($groupIDs)>0) { - $queryStr = "SELECT `tblUsers`.* FROM `tblUsers` ". - "LEFT JOIN `tblGroupMembers` ON `tblGroupMembers`.`userID`=`tblUsers`.`id` ". - "WHERE `tblGroupMembers`.`groupID` NOT IN (". $groupIDs .")". - "AND `tblUsers`.`role` != ".SeedDMS_Core_User::role_guest." ". - (strlen($userIDs) == 0 ? "" : " AND (`tblUsers`.`id` NOT IN (". $userIDs ."))")." UNION "; - } - $queryStr .= - "SELECT `tblUsers`.* FROM `tblUsers` ". - "WHERE (`tblUsers`.`id` = ". $this->_ownerID . ") ". - "OR (`tblUsers`.`role` = ".SeedDMS_Core_User::role_admin.") ". - "UNION ". - "SELECT `tblUsers`.* FROM `tblUsers` ". - "WHERE `tblUsers`.`role` != ".SeedDMS_Core_User::role_guest." ". - (strlen($userIDs) == 0 ? "" : " AND (`tblUsers`.`id` NOT IN (". $userIDs ."))"). - " ORDER BY `login`"; - } - $resArr = $db->getResultArray($queryStr); - if (!is_bool($resArr)) { - foreach ($resArr as $row) { - $user = $this->_dms->getUser($row['id']); - if (!$listadmin && $user->isAdmin()) continue; - if (!$listowner && $user->getID() == $this->_ownerID) continue; - $this->_readAccessList["users"][] = $user; - } - } - - // Assemble the list of groups that have read access to the folder. - $queryStr=""; - if ($defAccess < M_READ) { - if (strlen($groupIDs)>0) { - $queryStr = "SELECT `tblGroups`.* FROM `tblGroups` ". - "WHERE `tblGroups`.`id` IN (". $groupIDs .") ORDER BY `name`"; - } - } - else { - if (strlen($groupIDs)>0) { - $queryStr = "SELECT `tblGroups`.* FROM `tblGroups` ". - "WHERE `tblGroups`.`id` NOT IN (". $groupIDs .") ORDER BY `name`"; - } - else { - $queryStr = "SELECT `tblGroups`.* FROM `tblGroups` ORDER BY `name`"; - } - } - if (strlen($queryStr)>0) { - $resArr = $db->getResultArray($queryStr); - if (!is_bool($resArr)) { - foreach ($resArr as $row) { - $group = $this->_dms->getGroup($row["id"]); - $this->_readAccessList["groups"][] = $group; - } - } - } - } - return $this->_readAccessList; - } /* }}} */ - - /** - * Get the internally used folderList which stores the ids of folders from - * the root folder to the parent folder. - * - * @return string column separated list of folder ids - */ - function getFolderList() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT `folderList` FROM `tblFolders` where `id` = ".$this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - return $resArr[0]['folderList']; - } /* }}} */ - - /** - * Checks the internal data of the folder and repairs it. - * Currently, this function only repairs an incorrect folderList - * - * @return boolean true on success, otherwise false - */ - function repair() { /* {{{ */ - $db = $this->_dms->getDB(); - - $curfolderlist = $this->getFolderList(); - - // calculate the folderList of the folder - $parent = $this->getParent(); - $pathPrefix=""; - $path = $parent->getPath(); - foreach ($path as $f) { - $pathPrefix .= ":".$f->getID(); - } - if (strlen($pathPrefix)>1) { - $pathPrefix .= ":"; - } - if($curfolderlist != $pathPrefix) { - $queryStr = "UPDATE `tblFolders` SET `folderList`='".$pathPrefix."' WHERE `id` = ". $this->_id; - $res = $db->getResult($queryStr); - if (!$res) - return false; - } - return true; - } /* }}} */ - - /** - * Get the min and max sequence value for documents - * - * @return bool|array array with keys 'min' and 'max', false in case of an error - */ - function getDocumentsMinMax() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT min(`sequence`) AS `min`, max(`sequence`) AS `max` FROM `tblDocuments` WHERE `folder` = " . (int) $this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && $resArr == false) - return false; - - return $resArr[0]; - } /* }}} */ - - /** - * Get the min and max sequence value for folders - * - * @return bool|array array with keys 'min' and 'max', false in case of an error - */ - function getFoldersMinMax() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT min(`sequence`) AS `min`, max(`sequence`) AS `max` FROM `tblFolders` WHERE `parent` = " . (int) $this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && $resArr == false) - return false; - - return $resArr[0]; - } /* }}} */ - - /** - * Reorder documents of folder - * - * Fix the sequence numbers of all documents in the folder, by assigning new - * numbers starting from 1 incrementing by 1. This can be necessary if sequence - * numbers are not unique which makes manual reordering for documents with - * identical sequence numbers impossible. - * - * @return bool false in case of an error, otherwise true - */ - function reorderDocuments() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT `id` FROM `tblDocuments` WHERE `folder` = " . (int) $this->_id . " ORDER BY `sequence`"; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && $resArr == false) - return false; - - $db->startTransaction(); - $no = 1.0; - foreach($resArr as $doc) { - $queryStr = "UPDATE `tblDocuments` SET `sequence` = " . $no . " WHERE `id` = ". $doc['id']; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - $no += 1.0; - } - $db->commitTransaction(); - - return true; - } /* }}} */ - - -} - -?> diff --git a/SeedDMS_Core/Core/inc.ClassGroup.php b/SeedDMS_Core/Core/inc.ClassGroup.php deleted file mode 100644 index 66f5f8ee0..000000000 --- a/SeedDMS_Core/Core/inc.ClassGroup.php +++ /dev/null @@ -1,531 +0,0 @@ - - * @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 - * @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(); - - $classname = $this->_dms->getClassname('user'); - foreach ($resArr as $row) { - /** @var SeedDMS_Core_User $user */ - $user = new $classname($row["id"], $row["login"], $row["pwd"], $row["fullName"], $row["email"], $row["language"], $row["theme"], $row["comment"], $row["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(); - - $classname = $this->_dms->getClassname('user'); - foreach ($resArr as $row) { - /** @var SeedDMS_Core_User $user */ - $user = new $classname($row["id"], $row["login"], $row["pwd"], $row["fullName"], $row["email"], $row["language"], $row["theme"], $row["comment"], $row["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; - } - } - - $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; - } /* }}} */ - - /** - * 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; - } /* }}} */ - -} /* }}} */ diff --git a/SeedDMS_Core/Core/inc.ClassIterator.php b/SeedDMS_Core/Core/inc.ClassIterator.php deleted file mode 100644 index ffb8133dc..000000000 --- a/SeedDMS_Core/Core/inc.ClassIterator.php +++ /dev/null @@ -1,231 +0,0 @@ - - * @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
"; - $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
"; - $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()."
"; - } - */ -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()."
"; - return true; - } /* }}} */ -} /* }}} */ - -/** - $iter = new RecursiveFolderIterator($folder); - $iter2 = new RecursiveIteratorIterator($iter, RecursiveIteratorIterator::SELF_FIRST); - foreach($iter2 as $ff) { - echo $ff->getID().': '.$ff->getName()."
"; - } - */ -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()); - } /* }}} */ - -} /* }}} */ diff --git a/SeedDMS_Core/Core/inc.ClassKeywords.php b/SeedDMS_Core/Core/inc.ClassKeywords.php deleted file mode 100644 index 16afc994f..000000000 --- a/SeedDMS_Core/Core/inc.ClassKeywords.php +++ /dev/null @@ -1,207 +0,0 @@ - - * @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe, - * 2010-2023 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 - * @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe, - * 2010-2023 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 keywords in this list - */ - function getKeywordLists() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT * FROM `tblKeywords` WHERE `category` = " . $this->_id . " order by `keywords`"; - return $db->getResultArray($queryStr); - } - - /** - * @return integer number of keywords in this list - */ - function countKeywordLists() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT COUNT(*) as `c` FROM `tblKeywords` where `category`=".$this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - return $resArr[0]['c']; - } /* }}} */ - - /** - * @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; - } /* }}} */ -} diff --git a/SeedDMS_Core/Core/inc.ClassNotification.php b/SeedDMS_Core/Core/inc.ClassNotification.php deleted file mode 100644 index e4c70804d..000000000 --- a/SeedDMS_Core/Core/inc.ClassNotification.php +++ /dev/null @@ -1,116 +0,0 @@ - - * @copyright Copyright (C) 2010 Uwe Steinmann - * @version Release: @package_version@ - */ - -/** - * Class to represent a notification - * - * @category DMS - * @package SeedDMS_Core - * @author Uwe Steinmann - * @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); } -} /* }}} */ -?> diff --git a/SeedDMS_Core/Core/inc.ClassObject.php b/SeedDMS_Core/Core/inc.ClassObject.php deleted file mode 100644 index 8bcc68a15..000000000 --- a/SeedDMS_Core/Core/inc.ClassObject.php +++ /dev/null @@ -1,331 +0,0 @@ - - * @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 - * @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 $this->_attributes[$attrdef->getId()]->getParsedValue(); - } - } 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; - } /* }}} */ -} /* }}} */ diff --git a/SeedDMS_Core/Core/inc.ClassUser.php b/SeedDMS_Core/Core/inc.ClassUser.php deleted file mode 100644 index bbc0aac87..000000000 --- a/SeedDMS_Core/Core/inc.ClassUser.php +++ /dev/null @@ -1,1994 +0,0 @@ - - * @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe, - * 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 - * @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe, - * 2010 Uwe Steinmann - * @version Release: @package_version@ - */ -class SeedDMS_Core_User { /* {{{ */ - /** - * @var integer id of user - * - * @access protected - */ - protected $_id; - - /** - * @var string login name of user - * - * @access protected - */ - protected $_login; - - /** - * @var string password of user as saved in database (md5) - * - * @access protected - */ - protected $_pwd; - - /** - * @var string date when password expires - * - * @access protected - */ - protected $_pwdExpiration; - - /** - * @var string full human readable name of user - * - * @access protected - */ - protected $_fullName; - - /** - * @var string email address of user - * - * @access protected - */ - protected $_email; - - /** - * @var string prefered language of user - * possible values are subdirectories within the language directory - * - * @access protected - */ - protected $_language; - - /** - * @var string preselected theme of user - * - * @access protected - */ - protected $_theme; - - /** - * @var string comment of user - * - * @access protected - */ - protected $_comment; - - /** - * @var string role of user. Can be one of SeedDMS_Core_User::role_user, - * SeedDMS_Core_User::role_admin, SeedDMS_Core_User::role_guest - * - * @access protected - */ - protected $_role; - - /** - * @var boolean true if user shall be hidden - * - * @access protected - */ - protected $_isHidden; - - /** - * @var boolean true if user is disabled - * - * @access protected - */ - protected $_isDisabled; - - /** - * @var int number of login failures - * - * @access protected - */ - protected $_loginFailures; - - /** - * @var SeedDMS_Core_Folder home folder - * - * @access protected - */ - protected $_homeFolder; - - /** - * @var SeedDMS_Core_DMS reference to the dms instance this user belongs to - * - * @access protected - */ - protected $_dms; - - /** - * @var int - * - * @access protected - */ - protected $_quota; - - /** - * @var bool - * - * @access protected - */ - protected $_hasImage; - - const role_user = '0'; - const role_admin = '1'; - const role_guest = '2'; - - /** - * SeedDMS_Core_User constructor. - * @param $id - * @param $login - * @param $pwd - * @param $fullName - * @param $email - * @param $language - * @param $theme - * @param $comment - * @param $role - * @param int $isHidden - * @param int $isDisabled - * @param string $pwdExpiration - * @param int $loginFailures - * @param int $quota - * @param null $homeFolder - */ - function __construct($id, $login, $pwd, $fullName, $email, $language, $theme, $comment, $role, $isHidden=0, $isDisabled=0, $pwdExpiration='', $loginFailures=0, $quota=0, $homeFolder=null) { - $this->_id = $id; - $this->_login = $login; - $this->_pwd = $pwd; - $this->_fullName = $fullName; - $this->_email = $email; - $this->_language = $language; - $this->_theme = $theme; - $this->_comment = $comment; - $this->_role = $role; - $this->_isHidden = (bool) $isHidden; - $this->_isDisabled = (bool) $isDisabled; - $this->_pwdExpiration = $pwdExpiration; - $this->_loginFailures = $loginFailures; - $this->_quota = $quota; - $this->_homeFolder = $homeFolder; - $this->_dms = null; - } - - /** - * Create an instance of a user object - * - * @param string|integer $id Id, login name, or email of user, depending - * on the 3rd parameter. - * @param SeedDMS_Core_DMS $dms instance of dms - * @param string $by search by [name|email]. If 'name' is passed, the method - * will check for the 4th paramater and also filter by email. If this - * parameter is left empty, the user will be search by its Id. - * @param string $email optional email address if searching for name - * @return SeedDMS_Core_User|bool instance of class SeedDMS_Core_User if user was - * found, null if user was not found, false in case of error - */ - public static function getInstance($id, $dms, $by='', $email='') { /* {{{ */ - $db = $dms->getDB(); - - switch($by) { - case 'name': - $queryStr = "SELECT * FROM `tblUsers` WHERE `login` = ".$db->qstr($id); - if($email) - $queryStr .= " AND `email`=".$db->qstr($email); - break; - case 'email': - $queryStr = "SELECT * FROM `tblUsers` WHERE `email` = ".$db->qstr($id); - break; - default: - $queryStr = "SELECT * FROM `tblUsers` WHERE `id` = " . (int) $id; - } - $resArr = $db->getResultArray($queryStr); - - if (is_bool($resArr) && $resArr == false) return false; - if (count($resArr) != 1) return null; - - $resArr = $resArr[0]; - - $user = new self((int) $resArr["id"], $resArr["login"], $resArr["pwd"], $resArr["fullName"], $resArr["email"], $resArr["language"], $resArr["theme"], $resArr["comment"], $resArr["role"], $resArr["hidden"], $resArr["disabled"], $resArr["pwdExpiration"], $resArr["loginfailures"], $resArr["quota"], $resArr["homefolder"]); - $user->setDMS($dms); - return $user; - } /* }}} */ - - /** - * @param $orderby - * @param SeedDMS_Core_DMS $dms - * @return SeedDMS_Core_User[]|bool - */ - public static function getAllInstances($orderby, $dms) { /* {{{ */ - $db = $dms->getDB(); - - if($orderby == 'fullname') - $queryStr = "SELECT * FROM `tblUsers` ORDER BY `fullName`"; - else - $queryStr = "SELECT * FROM `tblUsers` ORDER BY `login`"; - $resArr = $db->getResultArray($queryStr); - - if (is_bool($resArr) && $resArr == false) - return false; - - $users = array(); - - for ($i = 0; $i < count($resArr); $i++) { - /** @var SeedDMS_Core_User $user */ - $user = new self($resArr[$i]["id"], $resArr[$i]["login"], $resArr[$i]["pwd"], $resArr[$i]["fullName"], $resArr[$i]["email"], (isset($resArr[$i]["language"])?$resArr[$i]["language"]:NULL), (isset($resArr[$i]["theme"])?$resArr[$i]["theme"]:NULL), $resArr[$i]["comment"], $resArr[$i]["role"], $resArr[$i]["hidden"], $resArr[$i]["disabled"], $resArr[$i]["pwdExpiration"], $resArr[$i]["loginfailures"], $resArr[$i]["quota"], $resArr[$i]["homefolder"]); - $user->setDMS($dms); - $users[$i] = $user; - } - - return $users; -} /* }}} */ - - /** - * Check if this object is of type 'user'. - * - * @param string $type type of object - */ - public function isType($type) { /* {{{ */ - return $type == 'user'; - } /* }}} */ - - /** - * @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 getLogin() { return $this->_login; } - - /** - * @param $newLogin - * @return bool - */ - function setLogin($newLogin) { /* {{{ */ - $newLogin = trim($newLogin); - if(!$newLogin) - return false; - - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblUsers` SET `login` =".$db->qstr($newLogin)." WHERE `id` = " . $this->_id; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - $this->_login = $newLogin; - return true; - } /* }}} */ - - /** - * @return string - */ - function getFullName() { return $this->_fullName; } - - /** - * @param $newFullName - * @return bool - */ - function setFullName($newFullName) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblUsers` SET `fullName` = ".$db->qstr($newFullName)." WHERE `id` = " . $this->_id; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - $this->_fullName = $newFullName; - return true; - } /* }}} */ - - /** - * @return string - */ - function getPwd() { return $this->_pwd; } - - /** - * @param $newPwd - * @return bool - */ - function setPwd($newPwd) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblUsers` SET `pwd` =".$db->qstr($newPwd)." WHERE `id` = " . $this->_id; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - $this->_pwd = $newPwd; - return true; - } /* }}} */ - - /** - * @return string - */ - function getPwdExpiration() { return $this->_pwdExpiration; } - - /** - * @param $newPwdExpiration - * @return bool - */ - function setPwdExpiration($newPwdExpiration) { /* {{{ */ - $db = $this->_dms->getDB(); - - if(trim($newPwdExpiration) == '' || trim($newPwdExpiration) == 'never') { - $newPwdExpiration = null; - $queryStr = "UPDATE `tblUsers` SET `pwdExpiration` = NULL WHERE `id` = " . $this->_id; - } else { - if(trim($newPwdExpiration) == 'now') - $newPwdExpiration = date('Y-m-d H:i:s'); - $queryStr = "UPDATE `tblUsers` SET `pwdExpiration` =".$db->qstr($newPwdExpiration)." WHERE `id` = " . $this->_id; - } - $res = $db->getResult($queryStr); - if (!$res) - return false; - - $this->_pwdExpiration = $newPwdExpiration; - return true; - } /* }}} */ - - /** - * @return string - */ - function getEmail() { return $this->_email; } - - /** - * @param $newEmail - * @return bool - */ - function setEmail($newEmail) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblUsers` SET `email` =".$db->qstr(trim($newEmail))." WHERE `id` = " . $this->_id; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - $this->_email = $newEmail; - return true; - } /* }}} */ - - /** - * @return string - */ - function getLanguage() { return $this->_language; } - - /** - * @param $newLanguage - * @return bool - */ - function setLanguage($newLanguage) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblUsers` SET `language` =".$db->qstr(trim($newLanguage))." WHERE `id` = " . $this->_id; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - $this->_language = $newLanguage; - return true; - } /* }}} */ - - /** - * @return string - */ - function getTheme() { return $this->_theme; } - - /** - * @param string $newTheme - * @return bool - */ - function setTheme($newTheme) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblUsers` SET `theme` =".$db->qstr(trim($newTheme))." WHERE `id` = " . $this->_id; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - $this->_theme = $newTheme; - return true; - } /* }}} */ - - /** - * @return string - */ - function getComment() { return $this->_comment; } - - /** - * @param $newComment - * @return bool - */ - function setComment($newComment) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblUsers` SET `comment` =".$db->qstr(trim($newComment))." WHERE `id` = " . $this->_id; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - $this->_comment = $newComment; - return true; - } /* }}} */ - - /** - * @return string - */ - function getRole() { return $this->_role; } - - /** - * @param integer $newrole - * @return bool - */ - function setRole($newrole) { /* {{{ */ - $db = $this->_dms->getDB(); - if(!in_array($newrole, array(SeedDMS_Core_User::role_admin, SeedDMS_Core_User::role_guest, SeedDMS_Core_User::role_user), true)) - return false; - - $queryStr = "UPDATE `tblUsers` SET `role` = " . $newrole . " WHERE `id` = " . $this->_id; - if (!$db->getResult($queryStr)) - return false; - - $this->_role = $newrole; - return true; - } /* }}} */ - - /** - * @return bool - */ - function isAdmin() { return ($this->_role == SeedDMS_Core_User::role_admin); } - - /** - * @return bool - */ - function setAdmin() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblUsers` SET `role` = " . SeedDMS_Core_User::role_admin . " WHERE `id` = " . $this->_id; - if (!$db->getResult($queryStr)) - return false; - - $this->_role = SeedDMS_Core_User::role_admin; - return true; - } /* }}} */ - - /** - * @return bool - */ - function isGuest() { return ($this->_role == SeedDMS_Core_User::role_guest); } - - /** - * @return bool - */ - function setGuest() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblUsers` SET `role` = " . SeedDMS_Core_User::role_guest . " WHERE `id` = " . $this->_id; - if (!$db->getResult($queryStr)) - return false; - - $this->_role = SeedDMS_Core_User::role_guest; - return true; - } /* }}} */ - - /** - * @return bool - */ - function isHidden() { return $this->_isHidden; } - - /** - * @param $isHidden - * @return bool - */ - function setHidden($isHidden) { /* {{{ */ - $db = $this->_dms->getDB(); - - $isHidden = ($isHidden) ? "1" : "0"; - $queryStr = "UPDATE `tblUsers` SET `hidden` = " . intval($isHidden) . " WHERE `id` = " . $this->_id; - if (!$db->getResult($queryStr)) - return false; - - $this->_isHidden = (bool) $isHidden; - return true; - } /* }}} */ - - /** - * @return bool|int - */ - function isDisabled() { return $this->_isDisabled; } - - /** - * @param $isDisabled - * @return bool - */ - function setDisabled($isDisabled) { /* {{{ */ - $db = $this->_dms->getDB(); - - $isDisabled = ($isDisabled) ? "1" : "0"; - $queryStr = "UPDATE `tblUsers` SET `disabled` = " . intval($isDisabled) . " WHERE `id` = " . $this->_id; - if (!$db->getResult($queryStr)) - return false; - - $this->_isDisabled = (bool) $isDisabled; - return true; - } /* }}} */ - - /** - * @return bool|int - */ - function addLoginFailure() { /* {{{ */ - $db = $this->_dms->getDB(); - - $this->_loginFailures++; - $queryStr = "UPDATE `tblUsers` SET `loginfailures` = " . $this->_loginFailures . " WHERE `id` = " . $this->_id; - if (!$db->getResult($queryStr)) - return false; - - return $this->_loginFailures; - } /* }}} */ - - /** - * @return bool - */ - function clearLoginFailures() { /* {{{ */ - $db = $this->_dms->getDB(); - - $this->_loginFailures = 0; - $queryStr = "UPDATE `tblUsers` SET `loginfailures` = " . $this->_loginFailures . " WHERE `id` = " . $this->_id; - if (!$db->getResult($queryStr)) - return false; - - return true; - } /* }}} */ - - /** - * Calculate the disk space for all documents owned by the user - * - * This is done by using the internal database field storing the - * filesize of a document version. - * - * @return integer total disk space in Bytes - */ - function getUsedDiskSpace() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT SUM(`fileSize`) sum FROM `tblDocumentContent` a LEFT JOIN `tblDocuments` b ON a.`document`=b.`id` WHERE b.`owner` = " . $this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && $resArr == false) - return false; - - return $resArr[0]['sum']; - } /* }}} */ - - /** - * @return int - */ - function getQuota() { return $this->_quota; } - - /** - * @param integer $quota - * @return bool - */ - function setQuota($quota) { /* {{{ */ - if (!is_numeric($quota)) - return false; - if($quota < 0) - return false; - - $db = $this->_dms->getDB(); - - $quota = intval($quota); - $queryStr = "UPDATE `tblUsers` SET `quota` = " . $quota . " WHERE `id` = " . $this->_id; - if (!$db->getResult($queryStr)) - return false; - - $this->_quota = $quota; - return true; - } /* }}} */ - - /** - * @return null|SeedDMS_Core_Folder - */ - function getHomeFolder() { return $this->_homeFolder; } - - /** - * @param integer $homefolder - * @return bool - */ - function setHomeFolder($homefolder) { /* {{{ */ - $db = $this->_dms->getDB(); - $homefolder = intval($homefolder); - - $queryStr = "UPDATE `tblUsers` SET `homefolder` = " . ($homefolder ? $homefolder : 'NULL') . " WHERE `id` = " . $this->_id; - if (!$db->getResult($queryStr)) - return false; - - $this->_homeFolder = $homefolder; - return true; - } /* }}} */ - - /** - * Remove user from all processes - * - * This method adds another log entry to the reviews and approvals - * which indicates the user has been deleted from the process. By default it will - * do so for each review/approval regardless of its current state unles - * the user has been removed already (status=-2). So even - * reviews/approvals already processed by the user will be added the log - * entry. Only, if the last log entry was a removal already, it will not be - * added a second time. - * - * This removal from processes will also take place for older versions of a document. - * - * This methode was initialy added to remove a user (which is going to be deleted - * afterwards) from all processes he or she is still involved in. - * - * If a new user is passed, then this user will be added as a new reviewer, approver, etc. - * Hence, this method does not replace the old user but actually deletes the old user and - * adds a new one. Adding the new reviewer, approver, etc. will also be done for old versions - * of a document. The same operation could be archieved by first calling - * SeedDMS_Core_DocumentVersion::delIndReviewer() followed by SeedDMS_Core_DocumentVersion::addIndReviewer() - * but this would require to do for each version of a document and the operation would not - * be in a single transaction. - * - * A new user is only added if the process (review, approval, etc.) is still in its initial - * state (have not been reviewed/approved or rejected). Unlike the removal of the user (see above). - * - * If a new user is given but has no read access on the document the transfer for that - * particular document will be skipped. Not even the removal of the user will take place. - * - * @param object $user the user doing the removal (needed for entry in - * review and approve log). - * @param array $states remove user only from reviews/approvals in one of the states - * e.g. if passing array('review'=>array(0)), the method will operate on - * reviews which has not been touched yet. - * @param object $newuser user who takes over the processes - * @param array $docs remove only processes from docs with the given document ids - * @return boolean true on success or false in case of an error - */ - private function __removeFromProcesses($user, $states = array(), $newuser=null, $docs=null) { /* {{{ */ - $db = $this->_dms->getDB(); - - /* Get a list of all reviews, even those of older document versions */ - $reviewStatus = $this->getReviewStatus(); - $db->startTransaction(); - foreach ($reviewStatus["indstatus"] as $ri) { - if(!($doc = $this->_dms->getDocument($ri['documentID']))) - continue; - if($docs) { - if(!in_array($doc->getID(), $docs)) - continue; - if(!$doc->isLatestContent($ri['version'])) - continue; - } - if($newuser && $doc->getAccessMode($newuser) < M_READ) - continue; - if($ri['status'] != -2 && (!isset($states['review']) || in_array($ri['status'], $states['review']))) { - $queryStr = "INSERT INTO `tblDocumentReviewLog` (`reviewID`, `status`, `comment`, `date`, `userID`) ". - "VALUES ('". $ri["reviewID"] ."', '-2', '".(($newuser && $ri['status'] == 0) ? 'Reviewer replaced by '.$newuser->getLogin() : 'Reviewer removed from process')."', ".$db->getCurrentDatetime().", '". $user->getID() ."')"; - $res=$db->getResult($queryStr); - if(!$res) { - $db->rollbackTransaction(); - return false; - } - /* Only reviews not done already can be transferred to a new user */ - if($newuser && $ri['status'] == 0) { - if($version = $doc->getContentByVersion($ri['version'])) { - $ret = $version->addIndReviewer($newuser, $user); - /* returns -3 if the user is already a reviewer */ - if($ret === false || ($ret < 0 && $ret != -3)) { - $db->rollbackTransaction(); - return false; - } - } - } - } - } - $db->commitTransaction(); - - /* Get a list of all approvals, even those of older document versions */ - $approvalStatus = $this->getApprovalStatus(); - $db->startTransaction(); - foreach ($approvalStatus["indstatus"] as $ai) { - if(!($doc = $this->_dms->getDocument($ai['documentID']))) - continue; - if($docs) { - if(!in_array($doc->getID(), $docs)) - continue; - if(!$doc->isLatestContent($ai['version'])) - continue; - } - if($newuser && $doc->getAccessMode($newuser) < M_READ) - continue; - if($ai['status'] != -2 && (!isset($states['approval']) || in_array($ai['status'], $states['approval']))) { - $queryStr = "INSERT INTO `tblDocumentApproveLog` (`approveID`, `status`, `comment`, `date`, `userID`) ". - "VALUES ('". $ai["approveID"] ."', '-2', '".(($newuser && $ai['status'] == 0)? 'Approver replaced by '.$newuser->getLogin() : 'Approver removed from process')."', ".$db->getCurrentDatetime().", '". $user->getID() ."')"; - $res=$db->getResult($queryStr); - if(!$res) { - $db->rollbackTransaction(); - return false; - } - /* Only approvals not done already can be transferred to a new user */ - if($newuser && $ai['status'] == 0) { - if($version = $doc->getContentByVersion($ai['version'])) { - $ret = $version->addIndReviewer($newuser, $user); - /* returns -3 if the user is already a reviewer */ - if($ret === false || ($ret < 0 && $ret != -3)) { - $db->rollbackTransaction(); - return false; - } - } - } - } - } - $db->commitTransaction(); - - return true; - } /* }}} */ - - /** - * Remove user from all processes - * - * This includes review, approval and workflow - * - * @param object $user the user doing the removal (needed for entry in - * review and approve log). - * @param array $states remove user only from reviews/approvals in one of the states - * @param object $newuser user who takes over the processes - * @return boolean true on success or false in case of an error - */ - public function removeFromProcesses($user, $states=array(), $newuser=null, $docs=null) { /* {{{ */ - $db = $this->_dms->getDB(); - - $db->startTransaction(); - if(!$this->__removeFromProcesses($user, $states, $newuser, $docs)) { - $db->rollbackTransaction(); - return false; - } - $db->commitTransaction(); - return true; - } /* }}} */ - - /** - * Transfer documents and folders to another user - * - * @param object $assignToUser the user who is new owner of folders and - * documents which previously were owned by the delete user. - * @return boolean true on success or false in case of an error - */ - private function __transferDocumentsFolders($assignToUser) { /* {{{ */ - $db = $this->_dms->getDB(); - - if(!$assignToUser) - return false; - - /* Assign documents of the removed user to the given user */ - $queryStr = "UPDATE `tblFolders` SET `owner` = " . $assignToUser->getID() . " WHERE `owner` = " . $this->_id; - if (!$db->getResult($queryStr)) { - return false; - } - - $queryStr = "UPDATE `tblDocuments` SET `owner` = " . $assignToUser->getID() . " WHERE `owner` = " . $this->_id; - if (!$db->getResult($queryStr)) { - return false; - } - - $queryStr = "UPDATE `tblDocumentContent` SET `createdBy` = " . $assignToUser->getID() . " WHERE `createdBy` = " . $this->_id; - if (!$db->getResult($queryStr)) { - return false; - } - - // ... but keep public links - $queryStr = "UPDATE `tblDocumentLinks` SET `userID` = " . $assignToUser->getID() . " WHERE `userID` = " . $this->_id; - if (!$db->getResult($queryStr)) { - return false; - } - - // set administrator for deleted user's attachments - $queryStr = "UPDATE `tblDocumentFiles` SET `userID` = " . $assignToUser->getID() . " WHERE `userID` = " . $this->_id; - if (!$db->getResult($queryStr)) { - return false; - } - - return true; - } /* }}} */ - - /** - * Transfer documents and folders to another user - * - * @param object $assignToUser the user who is new owner of folders and - * documents which previously were owned by the delete user. - * @return boolean true on success or false in case of an error - */ - public function transferDocumentsFolders($assignToUser) { /* {{{ */ - $db = $this->_dms->getDB(); - - if($assignToUser->getID() == $this->_id) - return true; - - $db->startTransaction(); - if(!$this->__transferDocumentsFolders($assignToUser)) { - $db->rollbackTransaction(); - return false; - } - $db->commitTransaction(); - return true; - } /* }}} */ - - /** - * Transfer events to another user - * - * @param object $assignToUser the user who is new owner of events - * @return boolean true on success or false in case of an error - */ - private function __transferEvents($assignToUser) { /* {{{ */ - $db = $this->_dms->getDB(); - - if(!$assignToUser) - return false; - - // set new owner of events - $queryStr = "UPDATE `tblEvents` SET `userID` = " . $assignToUser->getID() . " WHERE `userID` = " . $this->_id; - if (!$db->getResult($queryStr)) { - return false; - } - - return true; - } /* }}} */ - - /** - * Transfer events to another user - * - * @param object $assignToUser the user who is new owner of events - * @return boolean true on success or false in case of an error - */ - public function transferEvents($assignToUser) { /* {{{ */ - $db = $this->_dms->getDB(); - - if($assignToUser->getID() == $this->_id) - return true; - - $db->startTransaction(); - if(!$this->__transferEvents($assignToUser)) { - $db->rollbackTransaction(); - return false; - } - $db->commitTransaction(); - return true; - } /* }}} */ - - /** - * Remove the user and also remove all its keywords, notifications, etc. - * Do not remove folders and documents of the user, but assign them - * to a different user. - * - * @param SeedDMS_Core_User $user the user doing the removal (needed for entry in - * review and approve log). - * @param SeedDMS_Core_User $assignToUser the user who is new owner of folders and - * documents which previously were owned by the delete user. - * @return boolean true on success or false in case of an error - */ - function remove($user, $assignToUser=null) { /* {{{ */ - $db = $this->_dms->getDB(); - - /* Records like folders and documents that formely have belonged to - * the user will assign to another user. If no such user is set, - * the function now returns false and will not use the admin user - * anymore. - */ - if(!$assignToUser) - return false; - /** @noinspection PhpUnusedLocalVariableInspection */ - $assignTo = $assignToUser->getID(); - - $db->startTransaction(); - - // delete private keyword lists - $queryStr = "SELECT `tblKeywords`.`id` FROM `tblKeywords`, `tblKeywordCategories` WHERE `tblKeywords`.`category` = `tblKeywordCategories`.`id` AND `tblKeywordCategories`.`owner` = " . $this->_id; - $resultArr = $db->getResultArray($queryStr); - if (count($resultArr) > 0) { - $queryStr = "DELETE FROM `tblKeywords` WHERE "; - for ($i = 0; $i < count($resultArr); $i++) { - $queryStr .= "id = " . $resultArr[$i]["id"]; - if ($i + 1 < count($resultArr)) - $queryStr .= " OR "; - } - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - } - - $queryStr = "DELETE FROM `tblKeywordCategories` WHERE `owner` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - //Benachrichtigungen entfernen - $queryStr = "DELETE FROM `tblNotify` WHERE `userID` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - // Remove private links on documents ... - $queryStr = "DELETE FROM `tblDocumentLinks` WHERE `userID` = " . $this->_id . " AND `public` = 0"; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - /* Assign documents, folders, files, public document links of the removed user to the given user */ - if(!$this->__transferDocumentsFolders($assignToUser)) { - $db->rollbackTransaction(); - return false; - } - - // unlock documents locked by the user - $queryStr = "DELETE FROM `tblDocumentLocks` WHERE `userID` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - // Delete user from all groups - $queryStr = "DELETE FROM `tblGroupMembers` WHERE `userID` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - // User aus allen ACLs streichen - $queryStr = "DELETE FROM `tblACLs` WHERE `userID` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - // Delete image of user - $queryStr = "DELETE FROM `tblUserImages` WHERE `userID` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - // Delete entries in password history - $queryStr = "DELETE FROM `tblUserPasswordHistory` WHERE `userID` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - // Delete entries in password request - $queryStr = "DELETE FROM `tblUserPasswordRequest` WHERE `userID` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - // mandatory review/approve - $queryStr = "DELETE FROM `tblMandatoryReviewers` WHERE `reviewerUserID` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - $queryStr = "DELETE FROM `tblMandatoryApprovers` WHERE `approverUserID` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - $queryStr = "DELETE FROM `tblMandatoryReviewers` WHERE `userID` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - $queryStr = "DELETE FROM `tblMandatoryApprovers` WHERE `userID` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - $queryStr = "DELETE FROM `tblWorkflowMandatoryWorkflow` WHERE `userid` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - $queryStr = "DELETE FROM `tblWorkflowTransitionUsers` WHERE `userid` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - /* Assign events of the removed user to the given user */ - if(!$this->__transferEvents($assignToUser)) { - $db->rollbackTransaction(); - return false; - } - - // Delete user itself - $queryStr = "DELETE FROM `tblUsers` WHERE `id` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - // TODO : update document status if reviewer/approver has been deleted - // "DELETE FROM `tblDocumentApproveLog` WHERE `userID` = " . $this->_id; - // "DELETE FROM `tblDocumentReviewLog` WHERE `userID` = " . $this->_id; - - if(!$this->__removeFromProcesses($user)) { - $db->rollbackTransaction(); - return false; - } - - $db->commitTransaction(); - return true; - } /* }}} */ - - /** - * Make the user a member of a group - * This function uses {@link SeedDMS_Group::addUser} but checks before if - * the user is already a member of the group. - * - * @param SeedDMS_Core_Group $group group to be the member of - * @return boolean true on success or false in case of an error or the user - * is already a member of the group - */ - function joinGroup($group) { /* {{{ */ - if ($group->isMember($this)) - return false; - - if (!$group->addUser($this)) - return false; - - unset($this->_groups); - return true; - } /* }}} */ - - /** - * Removes the user from a group - * This function uses {@link SeedDMS_Group::removeUser} but checks before if - * the user is a member of the group at all. - * - * @param SeedDMS_Core_Group $group group to leave - * @return boolean true on success or false in case of an error or the user - * is not a member of the group - */ - function leaveGroup($group) { /* {{{ */ - if (!$group->isMember($this)) - return false; - - if (!$group->removeUser($this)) - return false; - - unset($this->_groups); - return true; - } /* }}} */ - - /** - * Get all groups the user is a member of - * - * @return SeedDMS_Core_Group[]|bool list of groups - */ - function getGroups() { /* {{{ */ - $db = $this->_dms->getDB(); - - if (!isset($this->_groups)) - { - $queryStr = "SELECT `tblGroups`.*, `tblGroupMembers`.`userID` FROM `tblGroups` ". - "LEFT JOIN `tblGroupMembers` ON `tblGroups`.`id` = `tblGroupMembers`.`groupID` ". - "WHERE `tblGroupMembers`.`userID`='". $this->_id ."'"; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && $resArr == false) - return false; - - $this->_groups = array(); - $classname = $this->_dms->getClassname('group'); - foreach ($resArr as $row) { - /** @var SeedDMS_Core_Group $group */ - $group = new $classname((int) $row["id"], $row["name"], $row["comment"]); - $group->setDMS($this->_dms); - array_push($this->_groups, $group); - } - } - return $this->_groups; - } /* }}} */ - - /** - * Checks if user is member of a given group - * - * @param SeedDMS_Core_Group $group - * @return boolean true if user is member of the given group otherwise false - */ - function isMemberOfGroup($group) { /* {{{ */ - return $group->isMember($this); - } /* }}} */ - - /** - * Check if user has an image in its profile - * - * @return boolean true if user has a picture of itself - */ - function hasImage() { /* {{{ */ - if (!isset($this->_hasImage)) { - $db = $this->_dms->getDB(); - - $queryStr = "SELECT COUNT(*) AS num FROM `tblUserImages` WHERE `userID` = " . $this->_id; - $resArr = $db->getResultArray($queryStr); - if ($resArr === false) - return false; - - if ($resArr[0]["num"] == 0) $this->_hasImage = false; - else $this->_hasImage = true; - } - - return $this->_hasImage; - } /* }}} */ - - /** - * Get the image from the users profile - * - * @return string|null|bool image data as a string or null if no image is set or - * false in case of an error - */ - function getImage() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT * FROM `tblUserImages` WHERE `userID` = " . $this->_id; - $resArr = $db->getResultArray($queryStr); - if ($resArr === false) - return false; - - if($resArr) - return $resArr[0]; - else - return null; - } /* }}} */ - - /** - * @param $tmpfile - * @param $mimeType - * @return bool - */ - function setImage($tmpfile, $mimeType) { /* {{{ */ - $db = $this->_dms->getDB(); - - $fp = fopen($tmpfile, "rb"); - if (!$fp) return false; - $content = fread($fp, filesize($tmpfile)); - fclose($fp); - - if ($this->hasImage()) - $queryStr = "UPDATE `tblUserImages` SET `image` = '".base64_encode($content)."', `mimeType` = ".$db->qstr($mimeType)." WHERE `userID` = " . $this->_id; - else - $queryStr = "INSERT INTO `tblUserImages` (`userID`, `image`, `mimeType`) VALUES (" . $this->_id . ", '".base64_encode($content)."', ".$db->qstr($mimeType).")"; - if (!$db->getResult($queryStr)) - return false; - - $this->_hasImage = true; - return true; - } /* }}} */ - - /** - * Returns all documents of a given user - * @return SeedDMS_Core_Document[]|bool list of documents - */ - function getDocuments() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT `tblDocuments`.*, `tblDocumentLocks`.`userID` as `lockUser` ". - "FROM `tblDocuments` ". - "LEFT JOIN `tblDocumentLocks` ON `tblDocuments`.`id`=`tblDocumentLocks`.`document` ". - "WHERE `tblDocuments`.`owner` = " . $this->_id . " ORDER BY `sequence`"; - - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - $documents = array(); - $classname = $this->_dms->getClassname('document'); - foreach ($resArr as $row) { - /** @var SeedDMS_Core_Document $document */ - $document = new $classname((int) $row["id"], $row["name"], $row["comment"], $row["date"], $row["expires"], $row["owner"], $row["folder"], $row["inheritAccess"], $row["defaultAccess"], $row["lockUser"], $row["keywords"], $row["sequence"]); - $document->setDMS($this->_dms); - $documents[] = $document; - } - return $documents; - } /* }}} */ - - /** - * Returns all documents locked by a given user - * - * @return bool|SeedDMS_Core_Document[] list of documents - */ - function getDocumentsLocked() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT `tblDocuments`.*, `tblDocumentLocks`.`userID` as `lockUser` ". - "FROM `tblDocumentLocks` LEFT JOIN `tblDocuments` ON `tblDocuments`.`id` = `tblDocumentLocks`.`document` ". - "WHERE `tblDocumentLocks`.`userID` = '".$this->_id."' ". - "ORDER BY `id` DESC"; - - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - $documents = array(); - $classname = $this->_dms->getClassname('document'); - foreach ($resArr as $row) { - /** @var SeedDMS_Core_Document $document */ - $document = new $classname((int) $row["id"], $row["name"], $row["comment"], $row["date"], $row["expires"], $row["owner"], $row["folder"], $row["inheritAccess"], $row["defaultAccess"], $row["lockUser"], $row["keywords"], $row["sequence"]); - $document->setDMS($this->_dms); - $documents[] = $document; - } - return $documents; - } /* }}} */ - - /** - * Returns all document links of a given user - * @return SeedDMS_Core_DocumentLink[]|bool list of document links - */ - function getDocumentLinks() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT * FROM `tblDocumentLinks` ". - "WHERE `userID` = " . $this->_id; - - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - $links = array(); - $classname = 'SeedDMS_Core_DocumentLink'; - foreach ($resArr as $row) { - $document = $this->_dms->getDocument($row["document"]); - $target = $this->_dms->getDocument($row["target"]); - /** @var SeedDMS_Core_Document $document */ - $link = new $classname((int) $row["id"], $document, $target, $row["userID"], $row["public"]); - $links[] = $link; - } - return $links; - } /* }}} */ - - /** - * Returns all document files of a given user - * @return SeedDMS_Core_DocumentFile[]|bool list of document files - */ - function getDocumentFiles() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT * FROM `tblDocumentFiles` ". - "WHERE `userID` = " . $this->_id; - - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - $files = array(); - $classname = 'SeedDMS_Core_DocumentFile'; - foreach ($resArr as $row) { - $document = $this->_dms->getDocument($row["document"]); - /** @var SeedDMS_Core_DocumentFile $file */ - $file = new $classname((int) $row["id"], $document, $row["userID"], $row["comment"], $row["date"], $row["dir"], $row["fileType"], $row["mimeType"], $row["orgFileName"], $row["name"],$row["version"],$row["public"]); - $files[] = $file; - } - return $files; - } /* }}} */ - - /** - * Returns all document contents of a given user - * @return SeedDMS_Core_DocumentContent[]|bool list of document contents - */ - function getDocumentContents() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT * FROM `tblDocumentContent` WHERE `createdBy` = " . $this->_id; - - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - $contents = array(); - $classname = $this->_dms->getClassname('documentcontent'); - foreach ($resArr as $row) { - $document = $this->_dms->getDocument($row["document"]); - /** @var SeedDMS_Core_DocumentContent $content */ - $content = new $classname((int) $row["id"], $document, $row["version"], $row["comment"], $row["date"], $row["createdBy"], $row["dir"], $row["orgFileName"], $row["fileType"], $row["mimeType"], $row['fileSize'], $row['checksum']); - $contents[] = $content; - } - return $contents; - } /* }}} */ - - /** - * Returns all folders of a given user - * @return SeedDMS_Core_Folder[]|bool list of folders - */ - function getFolders() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT * FROM `tblFolders` ". - "WHERE `owner` = " . $this->_id . " ORDER BY `sequence`"; - - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - $folders = array(); - $classname = $this->_dms->getClassname('folder'); - foreach ($resArr as $row) { - /** @var SeedDMS_Core_Folder $folder */ - $folder = new $classname((int) $row["id"], $row["name"], $row['parent'], $row["comment"], $row["date"], $row["owner"], $row["inheritAccess"], $row["defaultAccess"], $row["sequence"]); - $folder->setDMS($this->_dms); - $folders[] = $folder; - } - return $folders; - } /* }}} */ - - /** - * Get a list of reviews - * - * This function returns a list of all reviews and their latest log entry - * seperated by individuals and groups. If the document id - * is passed, then only this document will be checked for reviews. The - * same is true for the version of a document which limits the list - * further. If you do not limit on a version it will retrieve the status - * for each version, that includes even older versions which has been superseded - * by a new version. - * - * For a detailed description of the result array see - * {link SeedDMS_Core_User::getApprovalStatus} which does the same for - * approvals. - * - * @param int $documentID optional document id for which to retrieve the - * reviews - * @param int $version optional version of the document - * @return array|bool list of all reviews - */ - function getReviewStatus($documentID=null, $version=null) { /* {{{ */ - $db = $this->_dms->getDB(); - - if (!$db->createTemporaryTable("ttreviewid", true)) { - return false; - } - - $status = array("indstatus"=>array(), "grpstatus"=>array()); - - // See if the user is assigned as an individual reviewer. - // Attention: this method didn't use ttreviewid to filter out the latest - // log entry. This was added 2021-09-29 because $group->getReviewStatus() - // does it as well. The check below if the date is larger than the date - // of a previos entry is still required to just take the latest version - // of a document into account. - $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`='0' ". - "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) { - if(isset($status["indstatus"][$res['documentID']])) { - if($status["indstatus"][$res['documentID']]['date'] < $res['date']) { - $status["indstatus"][$res['documentID']] = $res; - } - } else { - $status["indstatus"][$res['documentID']] = $res; - } - } - } - - // See if the user is the member of a group that has been assigned to - // review the document version. - $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` ". - "LEFT JOIN `tblGroupMembers` ON `tblGroupMembers`.`groupID` = `tblDocumentReviewers`.`required` ". - "WHERE `ttreviewid`.`maxLogID`=`tblDocumentReviewLog`.`reviewLogID` ". - ($documentID==null ? "" : "AND `tblDocumentReviewers`.`documentID` = '". (int) $documentID ."' "). - ($version==null ? "" : "AND `tblDocumentReviewers`.`version` = '". (int) $version ."' "). - "AND `tblDocumentReviewers`.`type`='1' ". - "AND `tblGroupMembers`.`userID`='". $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) { - if(isset($status["grpstatus"][$res['documentID']])) { - if($status["grpstatus"][$res['documentID']]['date'] < $res['date']) { - $status["grpstatus"][$res['documentID']] = $res; - } - } else { - $status["grpstatus"][$res['documentID']] = $res; - } - } - } - return $status; - } /* }}} */ - - /** - * Get a list of approvals - * - * This function returns a list of all approvals and their latest log entry - * seperated by individuals and groups. If the document id - * is passed, then only this document will be checked for approvals. The - * same is true for the version of a document which limits the list - * further. If you do not limit on a version it will retrieve the status - * for each version, that includes even older versions which has been superseded - * by a new version. - * - * The result array has two elements: - * - indstatus: which contains the approvals by individuals (users) - * - grpstatus: which contains the approvals by groups - * - * Each element is itself an array of approvals with the following elements - * (it is a combination of fields from tblDocumentApprovers and tblDocumentApproveLog): - * - approveID: unique id of approval - * - documentID: id of document, that needs to be approved - * - version: version of document, that needs to be approved - * - type: 0 for individual approval, 1 for group approval - * - required: id of user who is required to do the approval - * - status: 0 not approved, .... - * - comment: comment given during approval - * - date: date of approval - * - userID: id of user who has done the approval - * - * @param int $documentID optional document id for which to retrieve the - * approvals - * @param int $version optional version of the document - * @return array|bool list of all approvals - */ - function getApprovalStatus($documentID=null, $version=null) { /* {{{ */ - $db = $this->_dms->getDB(); - - if (!$db->createTemporaryTable("ttapproveid")) { - return false; - } - - $status = array("indstatus"=>array(), "grpstatus"=>array()); - - // See if the user is assigned as an individual approver. - // Attention: this method didn't use ttapproveid to filter out the latest - // log entry. This was added 2021-09-29 because $group->getApprovalStatus() - // does it as well. The check below if the date is larger than the date - // of a previos entry is still required to just take the latest version - // of a document into account. - $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`='0' ". - "AND `tblDocumentApprovers`.`required`='". $this->_id ."' ". - "ORDER BY `tblDocumentApproveLog`.`approveLogID` DESC"; - - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && $resArr == false) - return false; - if (count($resArr)>0) { - foreach ($resArr as $res) { - if(isset($status["indstatus"][$res['documentID']])) { - if($status["indstatus"][$res['documentID']]['date'] < $res['date']) { - $status["indstatus"][$res['documentID']] = $res; - } - } else { - $status["indstatus"][$res['documentID']] = $res; - } - } - } - - // See if the user is the member of a group that has been assigned to - // approve the document version. - $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` ". - "LEFT JOIN `tblGroupMembers` ON `tblGroupMembers`.`groupID` = `tblDocumentApprovers`.`required` ". - "WHERE `ttapproveid`.`maxLogID`=`tblDocumentApproveLog`.`approveLogID` ". - ($documentID==null ? "" : "AND `tblDocumentApprovers`.`documentID` = '". (int) $documentID ."' "). - ($version==null ? "" : "AND `tblDocumentApprovers`.`version` = '". (int) $version ."' "). - "AND `tblDocumentApprovers`.`type`='1' ". - "AND `tblGroupMembers`.`userID`='". $this->_id ."' ". - "ORDER BY `tblDocumentApproveLog`.`approveLogID` DESC"; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && $resArr == false) - return false; - if (count($resArr)>0) { - foreach ($resArr as $res) { - if(isset($status["grpstatus"][$res['documentID']])) { - if($status["grpstatus"][$res['documentID']]['date'] < $res['date']) { - $status["grpstatus"][$res['documentID']] = $res; - } - } else { - $status["grpstatus"][$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 array|bool list of all workflows - */ - function getWorkflowStatus($documentID=null, $version=null) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = 'SELECT DISTINCT d.*, c.`userid` FROM `tblWorkflowTransitions` a LEFT JOIN `tblWorkflows` b ON a.`workflow`=b.`id` LEFT JOIN `tblWorkflowTransitionUsers` 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.`userid`='.$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['u'] = array(); - if (count($resArr)>0) { - foreach ($resArr as $res) { - $result['u'][] = $res; - } - } - - $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` left join `tblGroupMembers` e on c.`groupid` = e.`groupID` where d.`document` is not null and a.`state`=d.`state` and e.`userID`='.$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['g'] = array(); - if (count($resArr)>0) { - foreach ($resArr as $res) { - $result['g'][] = $res; - } - } - return $result; - } /* }}} */ - - /** - * Get a list of workflows this user is involved as in individual - * - * @return array|bool list of all workflows - */ - function getWorkflowsInvolved() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = 'SELECT DISTINCT b.*, c.`userid` FROM `tblWorkflowTransitions` a LEFT JOIN `tblWorkflows` b ON a.`workflow`=b.`id` LEFT JOIN `tblWorkflowTransitionUsers` c ON a.`id`=c.`transition` WHERE c.`userid`='.$this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && $resArr == false) - return false; - $result = array(); - if (count($resArr)>0) { - foreach ($resArr as $res) { - $result[] = $this->_dms->getWorkflow((int) $res['id']); - } - } - - return $result; - } /* }}} */ - - /** - * Get a list of mandatory reviewers - * A user which isn't trusted completely may have assigned mandatory - * reviewers (both users and groups). - * Whenever the user inserts a new document the mandatory reviewers are - * filled in as reviewers. - * - * @return array list of arrays with two elements containing the user id - * (reviewerUserID) and group id (reviewerGroupID) of the reviewer. - */ - function getMandatoryReviewers() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT * FROM `tblMandatoryReviewers` WHERE `userID` = " . $this->_id; - $resArr = $db->getResultArray($queryStr); - - return $resArr; - } /* }}} */ - - /** - * Get a list of mandatory approvers - * See {link SeedDMS_Core_User::getMandatoryReviewers} - * - * @return array list of arrays with two elements containing the user id - * (approverUserID) and group id (approverGroupID) of the approver. - */ - function getMandatoryApprovers() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT * FROM `tblMandatoryApprovers` WHERE `userID` = " . $this->_id; - $resArr = $db->getResultArray($queryStr); - - return $resArr; - } /* }}} */ - - /** - * Get a list of users this user is a mandatory reviewer of - * - * This method is the reverse function of getMandatoryReviewers(). It returns - * those user where the current user is a mandatory reviewer. - * - * @return SeedDMS_Core_User[]|bool list of users where this user is a mandatory reviewer. - */ - function isMandatoryReviewerOf() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT * FROM `tblMandatoryReviewers` WHERE `reviewerUserID` = " . $this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) return false; - - $users = array(); - foreach($resArr as $res) { - $users[] = self::getInstance($res['userID'], $this->_dms); - } - - return $users; - } /* }}} */ - - /** - * Get a list of users this user is a mandatory approver of - * - * This method is the reverse function of getMandatoryApprovers(). It returns - * those user where the current user is a mandatory approver. - * - * @return SeedDMS_Core_User[]|bool list of users where this user is a mandatory approver. - */ - function isMandatoryApproverOf() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT * FROM `tblMandatoryApprovers` WHERE `approverUserID` = " . $this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) return false; - - $users = array(); - foreach($resArr as $res) { - $users[] = self::getInstance($res['userID'], $this->_dms); - } - - return $users; - } /* }}} */ - - /** - * Get the mandatory workflow - * A user which isn't trusted completely may have assigned mandatory - * workflow - * Whenever the user inserts a new document the mandatory workflow is - * filled in as the workflow. - * - * @return SeedDMS_Core_Workflow|bool workflow - */ - function getMandatoryWorkflow() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT * FROM `tblWorkflowMandatoryWorkflow` WHERE `userid` = " . $this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) return false; - - if(!$resArr) - return null; - - $workflow = $this->_dms->getWorkflow($resArr[0]['workflow']); - return $workflow; - } /* }}} */ - - /** - * Get the mandatory workflows - * A user which isn't trusted completely may have assigned mandatory - * workflow - * Whenever the user inserts a new document the mandatory workflow is - * filled in as the workflow. - * - * @return SeedDMS_Core_Workflow[]|bool workflow - */ - function getMandatoryWorkflows() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT * FROM `tblWorkflowMandatoryWorkflow` WHERE `userid` = " . $this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) return false; - - if(!$resArr) - return null; - - $workflows = array(); - foreach($resArr as $res) { - $workflows[] = $this->_dms->getWorkflow($res['workflow']); - } - return $workflows; - } /* }}} */ - - /** - * Set a mandatory reviewer - * This function sets a mandatory reviewer if it isn't already set. - * - * @param integer $id id of reviewer - * @param boolean $isgroup true if $id is a group - * @return boolean true on success, otherwise false - */ - function setMandatoryReviewer($id, $isgroup=false) { /* {{{ */ - $db = $this->_dms->getDB(); - $id = (int) $id; - - if ($isgroup){ - - $queryStr = "SELECT * FROM `tblMandatoryReviewers` WHERE `userID` = " . $this->_id . " AND `reviewerGroupID` = " . $id; - $resArr = $db->getResultArray($queryStr); - if (count($resArr)!=0) return true; - - $queryStr = "INSERT INTO `tblMandatoryReviewers` (`userID`, `reviewerGroupID`) VALUES (" . $this->_id . ", " . $id .")"; - $resArr = $db->getResult($queryStr); - if (is_bool($resArr) && !$resArr) return false; - - }else{ - - $queryStr = "SELECT * FROM `tblMandatoryReviewers` WHERE `userID` = " . $this->_id . " AND `reviewerUserID` = " . $id; - $resArr = $db->getResultArray($queryStr); - if (count($resArr)!=0) return true; - - $queryStr = "INSERT INTO `tblMandatoryReviewers` (`userID`, `reviewerUserID`) VALUES (" . $this->_id . ", " . $id .")"; - $resArr = $db->getResult($queryStr); - if (is_bool($resArr) && !$resArr) return false; - } - - return true; - } /* }}} */ - - /** - * Set a mandatory approver - * This function sets a mandatory approver if it isn't already set. - * - * @param integer $id id of approver - * @param boolean $isgroup true if $id is a group - * @return boolean true on success, otherwise false - */ - function setMandatoryApprover($id, $isgroup=false) { /* {{{ */ - $db = $this->_dms->getDB(); - $id = (int) $id; - - if ($isgroup){ - - $queryStr = "SELECT * FROM `tblMandatoryApprovers` WHERE `userID` = " . $this->_id . " AND `approverGroupID` = " . $id; - $resArr = $db->getResultArray($queryStr); - if (count($resArr)!=0) return true; - - $queryStr = "INSERT INTO `tblMandatoryApprovers` (`userID`, `approverGroupID`) VALUES (" . $this->_id . ", " . $id .")"; - $resArr = $db->getResult($queryStr); - if (is_bool($resArr) && !$resArr) return false; - - }else{ - - $queryStr = "SELECT * FROM `tblMandatoryApprovers` WHERE `userID` = " . $this->_id . " AND `approverUserID` = " . $id; - $resArr = $db->getResultArray($queryStr); - if (count($resArr)!=0) return true; - - $queryStr = "INSERT INTO `tblMandatoryApprovers` (`userID`, `approverUserID`) VALUES (" . $this->_id . ", " . $id .")"; - $resArr = $db->getResult($queryStr); - if (is_bool($resArr) && !$resArr) return false; - } - - return true; - } /* }}} */ - - /** - * Set a mandatory workflow - * This function sets a mandatory workflow if it isn't already set. - * - * @param object $workflow workflow - * @return boolean true on success, otherwise false - */ - function setMandatoryWorkflow($workflow) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT * FROM `tblWorkflowMandatoryWorkflow` WHERE `userid` = " . $this->_id . " AND `workflow` = " . (int) $workflow->getID(); - $resArr = $db->getResultArray($queryStr); - if (count($resArr)!=0) return true; - - $queryStr = "INSERT INTO `tblWorkflowMandatoryWorkflow` (`userid`, `workflow`) VALUES (" . $this->_id . ", " . $workflow->getID() .")"; - $resArr = $db->getResult($queryStr); - if (is_bool($resArr) && !$resArr) return false; - - return true; - } /* }}} */ - - /** - * Set a mandatory workflows - * This function sets a list of mandatory workflows. - * - * @param SeedDMS_Core_Workflow[] $workflows list of workflow objects - * @return boolean true on success, otherwise false - */ - function setMandatoryWorkflows($workflows) { /* {{{ */ - $db = $this->_dms->getDB(); - - $db->startTransaction(); - $queryStr = "DELETE FROM `tblWorkflowMandatoryWorkflow` WHERE `userid` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - foreach($workflows as $workflow) { - $queryStr = "INSERT INTO `tblWorkflowMandatoryWorkflow` (`userid`, `workflow`) VALUES (" . $this->_id . ", " . $workflow->getID() .")"; - $resArr = $db->getResult($queryStr); - if (is_bool($resArr) && !$resArr) { - $db->rollbackTransaction(); - return false; - } - } - - $db->commitTransaction(); - return true; - } /* }}} */ - - /** - * Deletes all mandatory reviewers - * - * @return boolean true on success, otherwise false - */ - function delMandatoryReviewers() { /* {{{ */ - $db = $this->_dms->getDB(); - $queryStr = "DELETE FROM `tblMandatoryReviewers` WHERE `userID` = " . $this->_id; - if (!$db->getResult($queryStr)) return false; - return true; - } /* }}} */ - - /** - * Deletes all mandatory approvers - * - * @return boolean true on success, otherwise false - */ - function delMandatoryApprovers() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "DELETE FROM `tblMandatoryApprovers` WHERE `userID` = " . $this->_id; - if (!$db->getResult($queryStr)) return false; - return true; - } /* }}} */ - - /** - * Deletes the mandatory workflow - * - * @return boolean true on success, otherwise false - */ - function delMandatoryWorkflow() { /* {{{ */ - $db = $this->_dms->getDB(); - $queryStr = "DELETE FROM `tblWorkflowMandatoryWorkflow` WHERE `userid` = " . $this->_id; - if (!$db->getResult($queryStr)) return false; - return true; - } /* }}} */ - - /** - * Get all notifications of user - * - * @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`.`userID` = ". $this->_id; - if($type) { - $queryStr .= " AND `tblNotify`.`targetType` = ". (int) $type; - } - - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - $notifications = array(); - foreach ($resArr as $row) { - $not = new SeedDMS_Core_Notification($row["target"], $row["targetType"], $row["userID"], $row["groupID"]); - $not->setDMS($this); - array_push($notifications, $not); - } - - return $notifications; - } /* }}} */ - - /** - * Return list of personal keyword categories - * - * @return SeedDMS_Core_KeywordCategory[]|bool list of categories or false in case of an error - */ - function getKeywordCategories() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT * FROM `tblKeywordCategories` WHERE `owner` = ".$this->_id; - - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && !$resArr) - return false; - - $categories = array(); - foreach ($resArr as $row) { - $cat = new SeedDMS_Core_KeywordCategory((int) $row["id"], $row["owner"], $row["name"]); - $cat->setDMS($this->_dms); - array_push($categories, $cat); - } - - return $categories; - } /* }}} */ - -} /* }}} */ diff --git a/SeedDMS_Core/Core/inc.ClassWorkflow.php b/SeedDMS_Core/Core/inc.ClassWorkflow.php deleted file mode 100644 index ea104dee0..000000000 --- a/SeedDMS_Core/Core/inc.ClassWorkflow.php +++ /dev/null @@ -1,1400 +0,0 @@ - - * @copyright Copyright (C) 2012 Uwe Steinmann - * @version Release: @package_version@ - */ - -/** - * Class to represent an workflow in the document management system - * - * @category DMS - * @package SeedDMS_Core - * @author Markus Westphal, Malcolm Cowe, Uwe Steinmann - * @copyright Copyright (C) 2012 Uwe Steinmann - * @version Release: @package_version@ - */ -class SeedDMS_Core_Workflow { /* {{{ */ - /** - * @var integer id of workflow - * - * @access protected - */ - var $_id; - - /** - * @var string name of the workflow - * - * @access protected - */ - var $_name; - - /** - * @var SeedDMS_Core_Workflow_State initial state of the workflow - * - * @access protected - */ - var $_initstate; - - /** - * @var SeedDMS_Core_Workflow_Transition[] name of the workflow state - * - * @access protected - */ - var $_transitions; - - /** - * @var SeedDMS_Core_DMS reference to the dms instance this attribute belongs to - * - * @access protected - */ - var $_dms; - - /** - * SeedDMS_Core_Workflow constructor. - * @param int $id - * @param string $name - * @param SeedDMS_Core_Workflow_State $initstate - */ - function __construct($id, $name, $initstate) { /* {{{ */ - $this->_id = $id; - $this->_name = $name; - $this->_initstate = $initstate; - $this->_transitions = null; - $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; } - - /** - * @param $newName - * @return bool - */ - function setName($newName) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblWorkflows` SET `name` = ".$db->qstr($newName)." WHERE `id` = " . $this->_id; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - $this->_name = $newName; - return true; - } /* }}} */ - - /** - * @return SeedDMS_Core_Workflow_State - */ - function getInitState() { return $this->_initstate; } - - /** - * @param SeedDMS_Core_Workflow_State $state - * @return bool - */ - function setInitState($state) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblWorkflows` SET `initstate` = ".$state->getID()." WHERE `id` = " . $this->_id; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - $this->_initstate = $state; - return true; - } /* }}} */ - - /** - * @return SeedDMS_Core_Workflow_Transition[]|bool - */ - function getTransitions() { /* {{{ */ - $db = $this->_dms->getDB(); - - if($this->_transitions) - return $this->_transitions; - - $queryStr = "SELECT * FROM `tblWorkflowTransitions` WHERE `workflow`=".$this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && $resArr == false) - return false; - - $wkftransitions = array(); - for ($i = 0; $i < count($resArr); $i++) { - $wkftransition = new SeedDMS_Core_Workflow_Transition($resArr[$i]["id"], $this, $this->_dms->getWorkflowState($resArr[$i]["state"]), $this->_dms->getWorkflowAction($resArr[$i]["action"]), $this->_dms->getWorkflowState($resArr[$i]["nextstate"]), $resArr[$i]["maxtime"]); - $wkftransition->setDMS($this->_dms); - $wkftransitions[$resArr[$i]["id"]] = $wkftransition; - } - - $this->_transitions = $wkftransitions; - - return $this->_transitions; - } /* }}} */ - - /** - * Get all states this workflow at some point may reach - * - * It basically iterates through all transistions and makes a unique - * list of the start and end state. - * - * @return array list of states - */ - function getStates() { /* {{{ */ - /** @noinspection PhpUnusedLocalVariableInspection */ - $db = $this->_dms->getDB(); - - if(!$this->_transitions) - $this->getTransitions(); - - $states = array(); - foreach($this->_transitions as $transition) { - if(!isset($states[$transition->getState()->getID()])) - $states[$transition->getState()->getID()] = $transition->getState(); - if(!isset($states[$transition->getNextState()->getID()])) - $states[$transition->getNextState()->getID()] = $transition->getNextState(); - } - - return $states; - } /* }}} */ - - /** - * Get the transition by its id - * - * @param integer $id id of transition - * @return bool|SeedDMS_Core_Workflow_Transition - */ - function getTransition($id) { /* {{{ */ - /** @noinspection PhpUnusedLocalVariableInspection */ - $db = $this->_dms->getDB(); - - if(!$this->_transitions) - $this->getTransitions(); - - if($this->_transitions[$id]) - return $this->_transitions[$id]; - - return false; - } /* }}} */ - - /** - * Get the transitions that can be triggered while being in the given state - * - * @param SeedDMS_Core_Workflow_State $state current workflow state - * @return SeedDMS_Core_Workflow_Transition[]|bool - */ - function getNextTransitions($state) { /* {{{ */ - $db = $this->_dms->getDB(); - - if(!$state) - return false; - - $queryStr = "SELECT * FROM `tblWorkflowTransitions` WHERE `workflow`=".$this->_id." AND `state`=".$state->getID(); - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && $resArr == false) - return false; - - $wkftransitions = array(); - for ($i = 0; $i < count($resArr); $i++) { - $wkftransition = new SeedDMS_Core_Workflow_Transition($resArr[$i]["id"], $this, $this->_dms->getWorkflowState($resArr[$i]["state"]), $this->_dms->getWorkflowAction($resArr[$i]["action"]), $this->_dms->getWorkflowState($resArr[$i]["nextstate"]), $resArr[$i]["maxtime"]); - $wkftransition->setDMS($this->_dms); - $wkftransitions[$i] = $wkftransition; - } - - return $wkftransitions; - } /* }}} */ - - /** - * Get the transitions that lead to the given state - * - * @param SeedDMS_Core_Workflow_State $state current workflow state - * @return SeedDMS_Core_Workflow_Transition[]|bool - */ - function getPreviousTransitions($state) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT * FROM `tblWorkflowTransitions` WHERE `workflow`=".$this->_id." AND `nextstate`=".$state->getID(); - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && $resArr == false) - return false; - - $wkftransitions = array(); - for ($i = 0; $i < count($resArr); $i++) { - $wkftransition = new SeedDMS_Core_Workflow_Transition($resArr[$i]["id"], $this, $this->_dms->getWorkflowState($resArr[$i]["state"]), $this->_dms->getWorkflowAction($resArr[$i]["action"]), $this->_dms->getWorkflowState($resArr[$i]["nextstate"]), $resArr[$i]["maxtime"]); - $wkftransition->setDMS($this->_dms); - $wkftransitions[$i] = $wkftransition; - } - - return $wkftransitions; - } /* }}} */ - - /** - * Get all transitions from one state into another state - * - * @param SeedDMS_Core_Workflow_State $state state to start from - * @param SeedDMS_Core_Workflow_State $nextstate state after transition - * @return SeedDMS_Core_Workflow_Transition[]|bool - */ - function getTransitionsByStates($state, $nextstate) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT * FROM `tblWorkflowTransitions` WHERE `workflow`=".$this->_id." AND `state`=".$state->getID()." AND `nextstate`=".$nextstate->getID(); - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && $resArr == false) - return false; - - $wkftransitions = array(); - for ($i = 0; $i < count($resArr); $i++) { - $wkftransition = new SeedDMS_Core_Workflow_Transition($resArr[$i]["id"], $this, $this->_dms->getWorkflowState($resArr[$i]["state"]), $this->_dms->getWorkflowAction($resArr[$i]["action"]), $this->_dms->getWorkflowState($resArr[$i]["nextstate"]), $resArr[$i]["maxtime"]); - $wkftransition->setDMS($this->_dms); - $wkftransitions[$i] = $wkftransition; - } - - return $wkftransitions; - } /* }}} */ - - /** - * Remove a transition from a workflow - * Deprecated! User SeedDMS_Core_Workflow_Transition::remove() instead. - * - * @param SeedDMS_Core_Workflow_Transition $transition - * @return boolean true if no error occured, otherwise false - */ - function removeTransition($transition) { /* {{{ */ - return $transition->remove(); - } /* }}} */ - - /** - * Add new transition to workflow - * - * @param SeedDMS_Core_Workflow_State $state - * @param SeedDMS_Core_Workflow_Action $action - * @param SeedDMS_Core_Workflow_State $nextstate - * @param SeedDMS_Core_User[] $users - * @param SeedDMS_Core_Group[] $groups - * @return SeedDMS_Core_Workflow_Transition|bool instance of new transition - */ - function addTransition($state, $action, $nextstate, $users, $groups) { /* {{{ */ - $db = $this->_dms->getDB(); - - $db->startTransaction(); - $queryStr = "INSERT INTO `tblWorkflowTransitions` (`workflow`, `state`, `action`, `nextstate`) VALUES (".$this->_id.", ".$state->getID().", ".$action->getID().", ".$nextstate->getID().")"; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - /* force reloading all transitions otherwise getTransition() will fail if two - * transitions are added in a row, without reloading the workflow - */ - $this->_transitions = array(); - $transition = $this->getTransition($db->getInsertID('tblWorkflowTransitions')); - - foreach($users as $user) { - $queryStr = "INSERT INTO `tblWorkflowTransitionUsers` (`transition`, `userid`) VALUES (".$transition->getID().", ".$user->getID().")"; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - } - - foreach($groups as $group) { - $queryStr = "INSERT INTO `tblWorkflowTransitionGroups` (`transition`, `groupid`, `minusers`) VALUES (".$transition->getID().", ".$group->getID().", 1)"; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - } - - $db->commitTransaction(); - return $transition; - } /* }}} */ - - /** - * Check if workflow is currently used by any document - * - * @return boolean true if workflow is used, otherwise false - */ - function isUsed() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT * FROM `tblWorkflowDocumentContent` WHERE `workflow`=".$this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_array($resArr) && count($resArr) == 0) - return false; - return true; - } /* }}} */ - - /** - * @param SeedDMS_Core_Workflow_State[] $laststates - * @return SeedDMS_Core_Workflow_State[]|bool - */ - private function penetrate($laststates) { - $state = end($laststates); - $transitions = $this->getNextTransitions($state); - foreach($transitions as $transition) { - $nextstate = $transition->getNextState(); - /* Check if nextstate is already in list of previous states */ - foreach($laststates as $laststate) { - if($laststate->getID() == $nextstate->getID()) - return array_merge($laststates, array($nextstate)); - } - if($ret = $this->penetrate(array_merge($laststates, array($nextstate)))) - return $ret; - } - return false; - } - - /** - * Check if workflow contains cycles - * - * @return boolean list of states if workflow contains cycles, otherwise false - */ - function checkForCycles() { /* {{{ */ - /** @noinspection PhpUnusedLocalVariableInspection */ - $db = $this->_dms->getDB(); - - $initstate = $this->getInitState(); - - return $this->penetrate(array($initstate)); - } /* }}} */ - - /** - * Remove the workflow and all its transitions - * Do not remove actions and states of the workflow - * - * @return boolean true on success or false in case of an error - * false is also returned if the workflow is currently in use - */ - function remove() { /* {{{ */ - $db = $this->_dms->getDB(); - - if($this->isUsed()) - return false; - - $db->startTransaction(); - - $queryStr = "DELETE FROM `tblWorkflowTransitions` WHERE `workflow` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - $queryStr = "DELETE FROM `tblWorkflowMandatoryWorkflow` WHERE `workflow` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - // Delete workflow itself - $queryStr = "DELETE FROM `tblWorkflows` WHERE `id` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - $db->commitTransaction(); - - return true; - } /* }}} */ - -} /* }}} */ - -/** - * Class to represent a workflow state in the document management system - * - * @category DMS - * @package SeedDMS_Core - * @author Markus Westphal, Malcolm Cowe, Uwe Steinmann - * @copyright Copyright (C) 2012 Uwe Steinmann - * @version Release: @package_version@ - */ -class SeedDMS_Core_Workflow_State { /* {{{ */ - /** - * @var integer id of workflow state - * - * @access protected - */ - var $_id; - - /** - * @var string name of the workflow state - * - * @access protected - */ - var $_name; - - /** - * @var int maximum of seconds allowed in this state - * - * @access protected - */ - var $_maxtime; - - /** - * @var int maximum of seconds allowed in this state - * - * @access protected - */ - var $_precondfunc; - - /** - * @var int matching documentstatus when this state is reached - * - * @access protected - */ - var $_documentstatus; - - /** - * @var SeedDMS_Core_DMS reference to the dms instance this attribute belongs to - * - * @access protected - */ - var $_dms; - - /** - * SeedDMS_Core_Workflow_State constructor. - * @param $id - * @param $name - * @param $maxtime - * @param $precondfunc - * @param $documentstatus - */ - function __construct($id, $name, $maxtime, $precondfunc, $documentstatus) { - $this->_id = $id; - $this->_name = $name; - $this->_maxtime = $maxtime; - $this->_precondfunc = $precondfunc; - $this->_documentstatus = $documentstatus; - $this->_dms = null; - } - - /** - * @param $dms - */ - function setDMS($dms) { - $this->_dms = $dms; - } - - /** - * @return int - */ - function getID() { return $this->_id; } - - /** - * @return string - */ - function getName() { return $this->_name; } - - /** - * @param string $newName - * @return bool - */ - function setName($newName) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblWorkflowStates` SET `name` = ".$db->qstr($newName)." WHERE `id` = " . $this->_id; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - $this->_name = $newName; - return true; - } /* }}} */ - - /** - * @return int maximum - */ - function getMaxTime() { return $this->_maxtime; } - - /** - * @param $maxtime - * @return bool - */ - function setMaxTime($maxtime) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblWorkflowStates` SET `maxtime` = ".intval($maxtime)." WHERE `id` = " . $this->_id; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - $this->_maxtime = $maxtime; - return true; - } /* }}} */ - - /** - * @return int maximum - */ - function getPreCondFunc() { return $this->_precondfunc; } - - /** - * @param $precondfunc - * @return bool - */ - function setPreCondFunc($precondfunc) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblWorkflowStates` SET `precondfunc` = ".$db->qstr($precondfunc)." WHERE id = " . $this->_id; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - /** @noinspection PhpUndefinedVariableInspection */ - $this->_maxtime = $maxtime; /* @todo fix me */ - return true; - } /* }}} */ - - /** - * Get the document status which is set when this state is reached - * - * The document status uses the define states S_REJECTED and S_RELEASED - * Only those two states will update the document status - * - * @return integer document status - */ - function getDocumentStatus() { return $this->_documentstatus; } - - /** - * @param $docstatus - * @return bool - */ - function setDocumentStatus($docstatus) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblWorkflowStates` SET `documentstatus` = ".intval($docstatus)." WHERE id = " . $this->_id; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - $this->_documentstatus = $docstatus; - return true; - } /* }}} */ - - /** - * Check if workflow state is currently used by any workflow transition - * - * @return boolean true if workflow is used, otherwise false - */ - function isUsed() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT * FROM `tblWorkflowTransitions` WHERE `state`=".$this->_id. " OR `nextstate`=".$this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_array($resArr) && count($resArr) == 0) - return false; - return true; - } /* }}} */ - - /** - * Return workflow transitions the status is being used in - * - * @return SeedDMS_Core_Workflow_Transition[]|boolean array of workflow transitions or false in case of an error - */ - function getTransitions() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT * FROM `tblWorkflowTransitions` WHERE `state`=".$this->_id. " OR `nextstate`=".$this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_array($resArr) && count($resArr) == 0) - return false; - - $wkftransitions = array(); - for ($i = 0; $i < count($resArr); $i++) { - $wkftransition = new SeedDMS_Core_Workflow_Transition($resArr[$i]["id"], $this->_dms->getWorkflow($resArr[$i]["workflow"]), $this->_dms->getWorkflowState($resArr[$i]["state"]), $this->_dms->getWorkflowAction($resArr[$i]["action"]), $this->_dms->getWorkflowState($resArr[$i]["nextstate"]), $resArr[$i]["maxtime"]); - $wkftransition->setDMS($this->_dms); - $wkftransitions[$resArr[$i]["id"]] = $wkftransition; - } - - return $wkftransitions; - } /* }}} */ - - /** - * Remove the workflow state - * - * @return boolean true on success or false in case of an error - * false is also returned if the workflow state is currently in use - */ - function remove() { /* {{{ */ - $db = $this->_dms->getDB(); - - if($this->isUsed()) - return false; - - $db->startTransaction(); - - // Delete workflow state itself - $queryStr = "DELETE FROM `tblWorkflowStates` WHERE `id` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - $db->commitTransaction(); - - return true; - } /* }}} */ - -} /* }}} */ - -/** - * Class to represent a workflow action in the document management system - * - * @category DMS - * @package SeedDMS_Core - * @author Markus Westphal, Malcolm Cowe, Uwe Steinmann - * @copyright Copyright (C) 2012 Uwe Steinmann - * @version Release: @package_version@ - */ -class SeedDMS_Core_Workflow_Action { /* {{{ */ - /** - * @var integer id of workflow action - * - * @access protected - */ - var $_id; - - /** - * @var string name of the workflow action - * - * @access protected - */ - var $_name; - - /** - * @var SeedDMS_Core_DMS reference to the dms instance this attribute belongs to - * - * @access protected - */ - var $_dms; - - /** - * SeedDMS_Core_Workflow_Action constructor. - * @param $id - * @param $name - */ - function __construct($id, $name) { - $this->_id = $id; - $this->_name = $name; - $this->_dms = null; - } - - /** - * @param $dms - */ - function setDMS($dms) { - $this->_dms = $dms; - } - - /** - * @return int - */ - function getID() { return $this->_id; } - - /** - * @return string name - */ - function getName() { return $this->_name; } - - /** - * @param $newName - * @return bool - */ - function setName($newName) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblWorkflowActions` SET `name` = ".$db->qstr($newName)." WHERE `id` = " . $this->_id; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - $this->_name = $newName; - return true; - } /* }}} */ - - /** - * Check if workflow action is currently used by any workflow transition - * - * @return boolean true if workflow action is used, otherwise false - */ - function isUsed() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT * FROM `tblWorkflowTransitions` WHERE `action`=".$this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_array($resArr) && count($resArr) == 0) - return false; - return true; - } /* }}} */ - - /** - * Return workflow transitions the action is being used in - * - * @return SeedDMS_Core_Workflow_Transition[]|boolean array of workflow transitions or false in case of an error - */ - function getTransitions() { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "SELECT * FROM `tblWorkflowTransitions` WHERE `action`=".$this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_array($resArr) && count($resArr) == 0) - return false; - - $wkftransitions = array(); - for ($i = 0; $i < count($resArr); $i++) { - $wkftransition = new SeedDMS_Core_Workflow_Transition($resArr[$i]["id"], $this->_dms->getWorkflow($resArr[$i]["workflow"]), $this->_dms->getWorkflowState($resArr[$i]["state"]), $this->_dms->getWorkflowAction($resArr[$i]["action"]), $this->_dms->getWorkflowState($resArr[$i]["nextstate"]), $resArr[$i]["maxtime"]); - $wkftransition->setDMS($this->_dms); - $wkftransitions[$resArr[$i]["id"]] = $wkftransition; - } - - return $wkftransitions; - } /* }}} */ - - /** - * Remove the workflow action - * - * @return boolean true on success or false in case of an error - * false is also returned if the workflow action is currently in use - */ - function remove() { /* {{{ */ - $db = $this->_dms->getDB(); - - if($this->isUsed()) - return false; - - $db->startTransaction(); - - // Delete workflow state itself - $queryStr = "DELETE FROM `tblWorkflowActions` WHERE `id` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - $db->commitTransaction(); - - return true; - } /* }}} */ - -} /* }}} */ - -/** - * Class to represent a workflow transition in the document management system - * - * @category DMS - * @package SeedDMS_Core - * @author Markus Westphal, Malcolm Cowe, Uwe Steinmann - * @copyright Copyright (C) 2012 Uwe Steinmann - * @version Release: @package_version@ - */ -class SeedDMS_Core_Workflow_Transition { /* {{{ */ - /** - * @var integer id of workflow transition - * - * @access protected - */ - var $_id; - - /** - * @var SeedDMS_Core_Workflow workflow this transition belongs to - * - * @access protected - */ - var $_workflow; - - /** - * @var SeedDMS_Core_Workflow_State of the workflow transition - * - * @access protected - */ - var $_state; - - /** - * @var SeedDMS_Core_Workflow_State next state of the workflow transition - * - * @access protected - */ - var $_nextstate; - - /** - * @var SeedDMS_Core_Workflow_Action of the workflow transition - * - * @access protected - */ - var $_action; - - /** - * @var integer maximum of seconds allowed until this transition must be triggered - * - * @access protected - */ - var $_maxtime; - - /** - * @var SeedDMS_Core_User[] of users allowed to trigger this transaction - * - * @access protected - */ - var $_users; - - /** - * @var SeedDMS_Core_Group[] of groups allowed to trigger this transaction - * - * @access protected - */ - var $_groups; - - /** - * @var SeedDMS_Core_DMS reference to the dms instance this attribute belongs to - * - * @access protected - */ - var $_dms; - - /** - * SeedDMS_Core_Workflow_Transition constructor. - * @param $id - * @param $workflow - * @param $state - * @param $action - * @param $nextstate - * @param $maxtime - */ - function __construct($id, $workflow, $state, $action, $nextstate, $maxtime) { - $this->_id = $id; - $this->_workflow = $workflow; - $this->_state = $state; - $this->_action = $action; - $this->_nextstate = $nextstate; - $this->_maxtime = $maxtime; - $this->_dms = null; - } - - /** - * @param $dms - */ - function setDMS($dms) { - $this->_dms = $dms; - } - - /** - * @return int - */ - function getID() { return $this->_id; } - - /** - * @return SeedDMS_Core_Workflow - */ - function getWorkflow() { return $this->_workflow; } - - /** - * @param SeedDMS_Core_Workflow $newWorkflow - * @return bool - */ - function setWorkflow($newWorkflow) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblWorkflowTransitions` SET `workflow` = ".$newWorkflow->getID()." WHERE `id` = " . $this->_id; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - $this->_workflow = $newWorkflow; - return true; - } /* }}} */ - - - /** - * @return SeedDMS_Core_Workflow_State - */ - function getState() { return $this->_state; } - - /** - * @param SeedDMS_Core_Workflow_State $newState - * @return bool - */ - function setState($newState) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblWorkflowTransitions` SET `state` = ".$newState->getID()." WHERE `id` = " . $this->_id; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - $this->_state = $newState; - return true; - } /* }}} */ - - /** - * @return SeedDMS_Core_Workflow_State - */ - function getNextState() { return $this->_nextstate; } - - /** - * @param SeedDMS_Core_Workflow_State $newNextState - * @return bool - */ - function setNextState($newNextState) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblWorkflowTransitions` SET `nextstate` = ".$newNextState->getID()." WHERE `id` = " . $this->_id; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - $this->_nextstate = $newNextState; - return true; - } /* }}} */ - - /** - * @return SeedDMS_Core_Workflow_Action - */ - function getAction() { return $this->_action; } - - /** - * @param SeedDMS_Core_Workflow_Action $newAction - * @return bool - */ - function setAction($newAction) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblWorkflowTransitions` SET `action` = ".$newAction->getID()." WHERE `id` = " . $this->_id; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - $this->_action = $newAction; - return true; - } /* }}} */ - - /** - * @return int - */ - function getMaxTime() { return $this->_maxtime; } - - /** - * @param $maxtime - * @return bool - */ - function setMaxTime($maxtime) { /* {{{ */ - $db = $this->_dms->getDB(); - - $queryStr = "UPDATE `tblWorkflowTransitions` SET `maxtime` = ".intval($maxtime)." WHERE `id` = " . $this->_id; - $res = $db->getResult($queryStr); - if (!$res) - return false; - - $this->_maxtime = $maxtime; - return true; - } /* }}} */ - - /** - * Get all users allowed to trigger this transition - * - * @return SeedDMS_Core_User[]|bool list of users - */ - function getUsers() { /* {{{ */ - $db = $this->_dms->getDB(); - - if($this->_users) - return $this->_users; - - $queryStr = "SELECT * FROM `tblWorkflowTransitionUsers` WHERE `transition`=".$this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && $resArr == false) - return false; - - $users = array(); - for ($i = 0; $i < count($resArr); $i++) { - $user = new SeedDMS_Core_Workflow_Transition_User($resArr[$i]['id'], $this, $this->_dms->getUser($resArr[$i]['userid'])); - $user->setDMS($this->_dms); - $users[$i] = $user; - } - - $this->_users = $users; - - return $this->_users; - } /* }}} */ - - /** - * Get all users allowed to trigger this transition - * - * @return SeedDMS_Core_Group[]|bool list of users - */ - function getGroups() { /* {{{ */ - $db = $this->_dms->getDB(); - - if($this->_groups) - return $this->_groups; - - $queryStr = "SELECT * FROM `tblWorkflowTransitionGroups` WHERE `transition`=".$this->_id; - $resArr = $db->getResultArray($queryStr); - if (is_bool($resArr) && $resArr == false) - return false; - - $groups = array(); - for ($i = 0; $i < count($resArr); $i++) { - $group = new SeedDMS_Core_Workflow_Transition_Group($resArr[$i]['id'], $this, $this->_dms->getGroup($resArr[$i]['groupid']), $resArr[$i]['minusers']); - $group->setDMS($this->_dms); - $groups[$i] = $group; - } - - $this->_groups = $groups; - - return $this->_groups; - } /* }}} */ - - /** - * Remove the workflow transition - * - * @return boolean true on success or false in case of an error - * false is also returned if the workflow action is currently in use - */ - function remove() { /* {{{ */ - $db = $this->_dms->getDB(); - - $db->startTransaction(); - - // Delete workflow transition itself - $queryStr = "DELETE FROM `tblWorkflowTransitions` WHERE `id` = " . $this->_id; - if (!$db->getResult($queryStr)) { - $db->rollbackTransaction(); - return false; - } - - $db->commitTransaction(); - - return true; - } /* }}} */ - -} /* }}} */ - -/** - * Class to represent a user allowed to trigger a workflow transition - * - * @category DMS - * @package SeedDMS_Core - * @author Markus Westphal, Malcolm Cowe, Uwe Steinmann - * @copyright Copyright (C) 2012 Uwe Steinmann - * @version Release: @package_version@ - */ -class SeedDMS_Core_Workflow_Transition_User { /* {{{ */ - /** - * @var integer id of workflow transition - * - * @access protected - */ - var $_id; - - /** - * @var object reference to the transtion this user belongs to - * - * @access protected - */ - var $_transition; - - /** - * @var object user allowed to trigger a transition - * - * @access protected - */ - var $_user; - - /** - * @var object reference to the dms instance this attribute belongs to - _Core_Workflow_Transition_Group - * @access protected - */ - var $_dms; - - /** - * SeedDMS_Core_Workflow_Transition_User constructor. - * @param $id - * @param $transition - * @param $user - */ - function __construct($id, $transition, $user) { - $this->_id = $id; - $this->_transition = $transition; - $this->_user = $user; - } - - /** - * @param $dms - */ - function setDMS($dms) { /* {{{ */ - $this->_dms = $dms; - } /* }}} */ - - /** - * Get the transtion itself - * - * @return object group - */ - function getTransition() { /* {{{ */ - return $this->_transition; - } /* }}} */ - - /** - * Get the user who is allowed to trigger the transition - * - * @return object user - */ - function getUser() { /* {{{ */ - return $this->_user; - } /* }}} */ -} /* }}} */ - -/** - * Class to represent a group allowed to trigger a workflow transition - * - * @category DMS - * @package SeedDMS_Core - * @author Markus Westphal, Malcolm Cowe, Uwe Steinmann - * @copyright Copyright (C) 2012 Uwe Steinmann - * @version Release: @package_version@ - */ -class SeedDMS_Core_Workflow_Transition_Group { /* {{{ */ - /** - * @var integer id of workflow transition - * - * @access protected - */ - var $_id; - - /** - * @var object reference to the transtion this group belongs to - * - * @access protected - */ - var $_transition; - - /** - * @var integer number of users how must trigger the transition - * - * @access protected - */ - var $_numOfUsers; - - /** - * @var object group of users - * - * @access protected - */ - var $_group; - - /** - * @var object reference to the dms instance this attribute belongs to - * - * @access protected - */ - var $_dms; - - /** - * SeedDMS_Core_Workflow_Transition_Group constructor. - * @param $id - * @param $transition - * @param $group - * @param $numOfUsers - */ - function __construct($id, $transition, $group, $numOfUsers) { /* {{{ */ - $this->_id = $id; - $this->_transition = $transition; - $this->_group = $group; - $this->_numOfUsers = $numOfUsers; - } /* }}} */ - - /** - * @param $dms - */ - function setDMS($dms) { /* {{{ */ - $this->_dms = $dms; - } /* }}} */ - - /** - * Get the transtion itself - * - * @return object group - */ - function getTransition() { /* {{{ */ - return $this->_transition; - } /* }}} */ - - /** - * Get the group whose user are allowed to trigger the transition - * - * @return object group - */ - function getGroup() { /* {{{ */ - return $this->_group; - } /* }}} */ - - /** - * Returns the number of users of this group needed to trigger the transition - * - * @return integer number of users - */ - function getNumOfUsers() { /* {{{ */ - return $this->_numOfUsers; - } /* }}} */ - -} /* }}} */ - -/** - * Class to represent a group allowed to trigger a workflow transition - * - * @category DMS - * @package SeedDMS_Core - * @author Markus Westphal, Malcolm Cowe, Uwe Steinmann - * @copyright Copyright (C) 2012 Uwe Steinmann - * @version Release: @package_version@ - */ -class SeedDMS_Core_Workflow_Log { /* {{{ */ - /** - * @var integer id of workflow log - * - * @access protected - */ - var $_id; - - /** - * @var object document this log entry belongs to - * - * @access protected - */ - var $_document; - - /** - * @var integer version of document this log entry belongs to - * - * @access protected - */ - var $_version; - - /** - * @var object workflow - * - * @access protected - */ - var $_workflow; - - /** - * @var object user initiating this log entry - * - * @access protected - */ - var $_user; - - /** - * @var object transition - * - * @access protected - */ - var $_transition; - - /** - * @var string date - * - * @access protected - */ - var $_date; - - /** - * @var string comment - * - * @access protected - */ - var $_comment; - - /** - * @var object reference to the dms instance this attribute belongs to - * - * @access protected - */ - var $_dms; - - /** - * SeedDMS_Core_Workflow_Log constructor. - * @param $id - * @param $document - * @param $version - * @param $workflow - * @param $user - * @param $transition - * @param $date - * @param $comment - */ - function __construct($id, $document, $version, $workflow, $user, $transition, $date, $comment) { - $this->_id = $id; - $this->_document = $document; - $this->_version = $version; - $this->_workflow = $workflow; - $this->_user = $user; - $this->_transition = $transition; - $this->_date = $date; - $this->_comment = $comment; - $this->_dms = null; - } - - /** - * @param $dms - */ - function setDMS($dms) { /* {{{ */ - $this->_dms = $dms; - } /* }}} */ - - /** - * @return object - */ - function getTransition() { /* {{{ */ - return $this->_transition; - } /* }}} */ - - /** - * @return object - */ - function getWorkflow() { /* {{{ */ - return $this->_workflow; - } /* }}} */ - - /** - * @return object - */ - function getUser() { /* {{{ */ - return $this->_user; - } /* }}} */ - - /** - * @return string - */ - function getComment() { /* {{{ */ - return $this->_comment; - } /* }}} */ - - /** - * @return string - */ - function getDate() { /* {{{ */ - return $this->_date; - } /* }}} */ - -} /* }}} */ -?> diff --git a/SeedDMS_Core/Core/inc.DBAccessPDO.php b/SeedDMS_Core/Core/inc.DBAccessPDO.php deleted file mode 100644 index c9d986cef..000000000 --- a/SeedDMS_Core/Core/inc.DBAccessPDO.php +++ /dev/null @@ -1,1018 +0,0 @@ - - * @copyright Copyright (C) 2012 Uwe Steinmann - * @version Release: @package_version@ - */ -/** @noinspection PhpUndefinedClassInspection */ - -/** - * Class to represent the database access for the document management - * This class uses PDO for the actual database access. - * - * @category DMS - * @package SeedDMS_Core - * @author Uwe Steinmann - * @copyright Copyright (C) 2012 Uwe Steinmann - * @version Release: @package_version@ - */ -class SeedDMS_Core_DatabaseAccess { - /** - * @var boolean set to true for debug mode - */ - public $_debug; - - /** - * @var string name of database driver (mysql or sqlite) - */ - protected $_driver; - - /** - * @var string name of hostname - */ - protected $_hostname; - - /** - * @var int port number of database - */ - protected $_port; - - /** - * @var string name of database - */ - protected $_database; - - /** - * @var string name of database user - */ - protected $_user; - - /** - * @var string password of database user - */ - protected $_passw; - - /** - * @var object internal database connection - */ - private $_conn; - - /** - * @var boolean set to true if connection to database is established - */ - private $_connected; - - /** - * @var boolean set to true if temp. table for tree view has been created - */ - private $_ttreviewid; - - /** - * @var boolean set to true if temp. table for approvals has been created - */ - private $_ttapproveid; - - /** - * @var boolean set to true if temp. table for doc status has been created - */ - private $_ttstatid; - - /** - * @var boolean set to true if temp. table for doc content has been created - */ - private $_ttcontentid; - - /** - * @var boolean set to true if in a database transaction - */ - private $_intransaction; - - /** - * @var string set a valid file name for logging all sql queries - */ - private $_logfile; - - /** - * @var resource file pointer of log file - */ - private $_logfp; - - /** - * @var boolean set to true if views instead of temp. tables shall be used - */ - private $_useviews; - - /** - * Return list of all database tables - * - * This function is used to retrieve a list of database tables for backup - * - * @return string[]|bool list of table names - */ - function TableList() { /* {{{ */ - switch($this->_driver) { - case 'mysql': - $sql = "SELECT `TABLE_NAME` AS `name` FROM `information_schema`.`tables` WHERE `TABLE_SCHEMA`='".$this->_database."' AND `TABLE_TYPE`='BASE TABLE'"; - break; - case 'sqlite': - $sql = "SELECT tbl_name AS name FROM sqlite_master WHERE type='table'"; - break; - case 'pgsql': - $sql = "select tablename as name from pg_catalog.pg_tables where schemaname='public'"; - break; - default: - return false; - } - $arr = $this->getResultArray($sql); - $res = array(); - foreach($arr as $tmp) - $res[] = $tmp['name']; - return $res; - } /* }}} */ - - /** - * Check if database has a table - * - * This function will check if the database has a table with the given table name - * - * @return bool true if table exists, otherwise false - */ - function hasTable($name) { /* {{{ */ - switch($this->_driver) { - case 'mysql': - $sql = "SELECT `TABLE_NAME` AS `name` FROM `information_schema`.`tables` WHERE `TABLE_SCHEMA`='".$this->_database."' AND `TABLE_TYPE`='BASE TABLE' AND `TABLE_NAME`=".$this->qstr($name); - break; - case 'sqlite': - $sql = "SELECT tbl_name AS name FROM sqlite_master WHERE type='table' AND `tbl_name`=".$this->qstr($name); - break; - case 'pgsql': - $sql = "SELECT tablename AS name FROM pg_catalog.pg_tables WHERE schemaname='public' AND tablename=".$this->qstr($name); - break; - default: - return false; - } - $arr = $this->getResultArray($sql); - if($arr) - return true; - return false; - } /* }}} */ - - /** - * Return list of all database views - * - * This function is used to retrieve a list of database views - * - * @return array list of view names - */ - public function ViewList() { /* {{{ */ - switch($this->_driver) { - case 'mysql': - $sql = "select TABLE_NAME as name from information_schema.views where TABLE_SCHEMA='".$this->_database."'"; - break; - case 'sqlite': - $sql = "select tbl_name as name from sqlite_master where type='view'"; - break; - case 'pgsql': - $sql = "select viewname as name from pg_catalog.pg_views where schemaname='public'"; - break; - default: - return false; - } - $arr = $this->getResultArray($sql); - $res = array(); - foreach($arr as $tmp) - $res[] = $tmp['name']; - return $res; - } /* }}} */ - - /** - * Constructor of SeedDMS_Core_DatabaseAccess - * - * Sets all database parameters but does not connect. - * - * @param string $driver the database type e.g. mysql, sqlite - * @param string $hostname host of database server - * @param string $user name of user having access to database - * @param string $passw password of user - * @param bool|string $database name of database - */ - function __construct($driver, $hostname, $user, $passw, $database = false) { /* {{{ */ - $this->_driver = $driver; - $tmp = explode(":", $hostname); - $this->_hostname = $tmp[0]; - $this->_port = null; - if(!empty($tmp[1])) - $this->_port = $tmp[1]; - $this->_database = $database; - $this->_user = $user; - $this->_passw = $passw; - $this->_connected = false; - $this->_logfile = ''; - if($this->_logfile) { - $this->_logfp = fopen($this->_logfile, 'a+'); - if($this->_logfp) - fwrite($this->_logfp, microtime()." BEGIN ".$_SERVER['REQUEST_URI']." ------------------------------------------\n"); - } else - $this->_logfp = null; - // $tt*****id is a hack to ensure that we do not try to create the - // temporary table twice during a single connection. Can be fixed by - // using Views (MySQL 5.0 onward) instead of temporary tables. - // CREATE ... IF NOT EXISTS cannot be used because it has the - // unpleasant side-effect of performing the insert again even if the - // table already exists. - // - // See createTemporaryTable() method for implementation. - $this->_ttreviewid = false; - $this->_ttapproveid = false; - $this->_ttstatid = false; - $this->_ttcontentid = false; - $this->_useviews = false; // turn off views, because they are much slower then temp. tables - $this->_debug = false; - } /* }}} */ - - /** - * Return driver - * - * @return string name of driver as set in constructor - */ - public function getDriver() { /* {{{ */ - return $this->_driver; - } /* }}} */ - - /** - * Turn on views instead of temp. tables - * - * @param bool $onoff turn use of views instead of temp. table on/off - */ - function useViews($onoff) { /* {{{ */ - $this->_useviews = $onoff; - } /* }}} */ - - /** - * Destructor of SeedDMS_Core_DatabaseAccess - */ - function __destruct() { /* {{{ */ - if($this->_logfile && $this->_logfp) { - fwrite($this->_logfp, microtime()." END --------------------------------------------\n"); - fclose($this->_logfp); - } - } /* }}} */ - - /** - * Set the file pointer to a log file - * - * Once it is set, all queries will be logged into this file - */ - function setLogFp($fp) { /* {{{ */ - $this->_logfp = $fp; - } /* }}} */ - - /** - * Connect to database - * - * @return boolean true if connection could be established, otherwise false - */ - function connect() { /* {{{ */ - switch($this->_driver) { - case 'mysql': - case 'mysqli': - case 'mysqlnd': - case 'pgsql': - $dsn = $this->_driver.":dbname=".$this->_database.";host=".$this->_hostname; - if($this->_port) - $dsn .= ";port=".$this->_port; - break; - case 'sqlite': - $dsn = $this->_driver.":".$this->_database; - break; - } - try { - /** @noinspection PhpUndefinedVariableInspection */ - $this->_conn = new PDO($dsn, $this->_user, $this->_passw); - if (!$this->_conn) - return false; - - switch($this->_driver) { - case 'mysql': - $this->_conn->exec('SET NAMES utf8'); -// $this->_conn->setAttribute(PDO::ATTR_AUTOCOMMIT, FALSE); - /* Turn this on if you want strict checking of default values, etc. */ - /* $this->_conn->exec("SET SESSION sql_mode = 'STRICT_TRANS_TABLES'"); */ - /* The following is the default on Ubuntu 16.04 */ - /* $this->_conn->exec("SET SESSION sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'"); */ - break; - case 'sqlite': - $this->_conn->exec('PRAGMA foreign_keys = ON'); - break; - } - } catch (Exception $e) { - return false; - } - if($this->_useviews) { - $tmp = $this->ViewList(); - foreach(array('ttreviewid', 'ttapproveid', 'ttstatid', 'ttcontentid') as $viewname) { - if(in_array($viewname, $tmp)) { - $this->{"_".$viewname} = true; - } - } - } - - $this->_connected = true; - return true; - } /* }}} */ - - /** - * Make sure a database connection exisits - * - * This function checks for a database connection. If it does not exists - * it will reconnect. - * - * @return boolean true if connection is established, otherwise false - */ - function ensureConnected() { /* {{{ */ - if (!$this->_connected) return $this->connect(); - else return true; - } /* }}} */ - - /** - * Sanitize String used in database operations - * - * @param string $text - * @return string sanitized string - */ - function qstr($text) { /* {{{ */ - return $this->_conn->quote($text); - } /* }}} */ - - /** - * Replace back ticks by '"' - * - * @param string $text - * @return string sanitized string - */ - function rbt($text) { /* {{{ */ - return str_replace('`', '"', $text); - } /* }}} */ - - /** - * Return sql to concat strings or fields - * - * @param array $arr list of field names or strings - * @return string concated string - */ - function concat($arr) { /* {{{ */ - switch($this->_driver) { - case 'mysql': - return 'concat('.implode(',', $arr).')'; - break; - case 'pgsql': - return implode(' || ', $arr); - break; - case 'sqlite': - return implode(' || ', $arr); - break; - } - return ''; - } /* }}} */ - - /** - * Execute SQL query and return result - * - * Call this function only with sql query which return data records. - * - * @param string $queryStr sql query - * @param bool $retick - * @return array|bool data if query could be executed otherwise false - */ - function getResultArray($queryStr, $retick=true) { /* {{{ */ - $resArr = array(); - - if($retick && $this->_driver == 'pgsql') { - $queryStr = $this->rbt($queryStr); - } - - if($this->_logfp) { - fwrite($this->_logfp, microtime()." ".$queryStr."\n"); - } - $res = $this->_conn->query($queryStr); - if ($res === false) { - if($this->_debug) { - echo "error: ".$queryStr."
"; - print_r($this->_conn->errorInfo()); - } - return false; - } - $resArr = $res->fetchAll(PDO::FETCH_ASSOC); -// $res->Close(); - return $resArr; - } /* }}} */ - - /** - * Execute SQL query - * - * Call this function only with sql query which do not return data records. - * - * @param string $queryStr sql query - * @param boolean $retick replace all '`' by '"' - * @return boolean true if query could be executed otherwise false - */ - function getResult($queryStr, $retick=true) { /* {{{ */ - if($retick && $this->_driver == 'pgsql') { - $queryStr = $this->rbt($queryStr); - } - - if($this->_logfp) { - fwrite($this->_logfp, microtime()." ".$queryStr."\n"); - } - $res = $this->_conn->exec($queryStr); - if($res === false) { - if($this->_debug) { - echo "error: ".$queryStr."
"; - print_r($this->_conn->errorInfo()); - } - return false; - } else - return true; - - return $res; - } /* }}} */ - - function startTransaction() { /* {{{ */ - if(!$this->_intransaction) { - $this->_conn->beginTransaction(); - } - $this->_intransaction++; - if($this->_logfp) { - fwrite($this->_logfp, microtime()." START ".$htis->_intransaction."\n"); - } - } /* }}} */ - - function rollbackTransaction() { /* {{{ */ - if($this->_logfp) { - fwrite($this->_logfp, microtime()." ROLLBACK ".$htis->_intransaction."\n"); - } - if($this->_intransaction == 1) { - $this->_conn->rollBack(); - } - $this->_intransaction--; - } /* }}} */ - - function commitTransaction() { /* {{{ */ - if($this->_logfp) { - fwrite($this->_logfp, microtime()." COMMIT ".$htis->_intransaction."\n"); - } - if($this->_intransaction == 1) { - $this->_conn->commit(); - } - $this->_intransaction--; - } /* }}} */ - - /** - * Return the id of the last instert record - * - * @param string $tablename - * @param string $fieldname - * @return int id used in last autoincrement - */ - function getInsertID($tablename='', $fieldname='id') { /* {{{ */ - if($this->_driver == 'pgsql') - return $this->_conn->lastInsertId('"'.$tablename.'_'.$fieldname.'_seq"'); - else - return $this->_conn->lastInsertId(); - } /* }}} */ - - function getErrorMsg() { /* {{{ */ - $info = $this->_conn->errorInfo(); - return($info[2]); - } /* }}} */ - - function getErrorNo() { /* {{{ */ - return $this->_conn->errorCode(); - } /* }}} */ - - /** - * Create various temporary tables to speed up and simplify sql queries - * - * @param string $tableName - * @param bool $override - * @return bool - */ - private function __createTemporaryTable($tableName, $override=false) { /* {{{ */ - if (!strcasecmp($tableName, "ttreviewid")) { - switch($this->_driver) { - case 'sqlite': - $queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttreviewid` AS ". - "SELECT `tblDocumentReviewLog`.`reviewID` AS `reviewID`, ". - "MAX(`tblDocumentReviewLog`.`reviewLogID`) AS `maxLogID` ". - "FROM `tblDocumentReviewLog` ". - "GROUP BY `tblDocumentReviewLog`.`reviewID` "; //. -// "ORDER BY `maxLogID`"; - break; - case 'pgsql': - $queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttreviewid` (`reviewID` INTEGER, `maxLogID` INTEGER, PRIMARY KEY (`reviewID`));". - "INSERT INTO `ttreviewid` SELECT `tblDocumentReviewLog`.`reviewID`, ". - "MAX(`tblDocumentReviewLog`.`reviewLogID`) AS `maxLogID` ". - "FROM `tblDocumentReviewLog` ". - "GROUP BY `tblDocumentReviewLog`.`reviewID` ";//. -// "ORDER BY `maxLogID`"; - break; - default: - $queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttreviewid` (PRIMARY KEY (`reviewID`), INDEX (`maxLogID`)) ". - "SELECT `tblDocumentReviewLog`.`reviewID`, ". - "MAX(`tblDocumentReviewLog`.`reviewLogID`) AS `maxLogID` ". - "FROM `tblDocumentReviewLog` ". - "GROUP BY `tblDocumentReviewLog`.`reviewID` "; //. -// "ORDER BY `maxLogID`"; - } - if (!$this->_ttreviewid) { - if (!$this->getResult($queryStr)) - return false; - $this->_ttreviewid=true; - } - else { - if (is_bool($override) && $override) { - if (!$this->getResult("DROP TABLE IF EXISTS `ttreviewid`")) - return false; - if (!$this->getResult($queryStr)) - return false; - } - } - return $this->_ttreviewid; - } - elseif (!strcasecmp($tableName, "ttapproveid")) { - switch($this->_driver) { - case 'sqlite': - $queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttapproveid` AS ". - "SELECT `tblDocumentApproveLog`.`approveID` AS `approveID`, ". - "MAX(`tblDocumentApproveLog`.`approveLogID`) AS `maxLogID` ". - "FROM `tblDocumentApproveLog` ". - "GROUP BY `tblDocumentApproveLog`.`approveID` "; //. -// "ORDER BY `maxLogID`"; - break; - case 'pgsql': - $queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttapproveid` (`approveID` INTEGER, `maxLogID` INTEGER, PRIMARY KEY (`approveID`));". - "INSERT INTO `ttapproveid` SELECT `tblDocumentApproveLog`.`approveID`, ". - "MAX(`tblDocumentApproveLog`.`approveLogID`) AS `maxLogID` ". - "FROM `tblDocumentApproveLog` ". - "GROUP BY `tblDocumentApproveLog`.`approveID` "; //. -// "ORDER BY `maxLogID`"; - break; - default: - $queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttapproveid` (PRIMARY KEY (`approveID`), INDEX (`maxLogID`)) ". - "SELECT `tblDocumentApproveLog`.`approveID`, ". - "MAX(`tblDocumentApproveLog`.`approveLogID`) AS `maxLogID` ". - "FROM `tblDocumentApproveLog` ". - "GROUP BY `tblDocumentApproveLog`.`approveID` "; //. -// "ORDER BY `maxLogID`"; - } - if (!$this->_ttapproveid) { - if (!$this->getResult($queryStr)) - return false; - $this->_ttapproveid=true; - } - else { - if (is_bool($override) && $override) { - if (!$this->getResult("DROP TABLE IF NOT EXISTS `ttapproveid`")) - return false; - if (!$this->getResult($queryStr)) - return false; - } - } - return $this->_ttapproveid; - } - elseif (!strcasecmp($tableName, "ttstatid")) { - switch($this->_driver) { - case 'sqlite': - $queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttstatid` AS ". - "SELECT `tblDocumentStatusLog`.`statusID` AS `statusID`, ". - "MAX(`tblDocumentStatusLog`.`statusLogID`) AS `maxLogID` ". - "FROM `tblDocumentStatusLog` ". - "GROUP BY `tblDocumentStatusLog`.`statusID` "; //. -// "ORDER BY `maxLogID`"; - break; - case 'pgsql': - $queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttstatid` (`statusID` INTEGER, `maxLogID` INTEGER, PRIMARY KEY (`statusID`));". - "INSERT INTO `ttstatid` SELECT `tblDocumentStatusLog`.`statusID`, ". - "MAX(`tblDocumentStatusLog`.`statusLogID`) AS `maxLogID` ". - "FROM `tblDocumentStatusLog` ". - "GROUP BY `tblDocumentStatusLog`.`statusID` "; //. -// "ORDER BY `maxLogID`"; - break; - default: - $queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttstatid` (PRIMARY KEY (`statusID`), INDEX (`maxLogID`)) ". - "SELECT `tblDocumentStatusLog`.`statusID`, ". - "MAX(`tblDocumentStatusLog`.`statusLogID`) AS `maxLogID` ". - "FROM `tblDocumentStatusLog` ". - "GROUP BY `tblDocumentStatusLog`.`statusID` "; //. -// "ORDER BY `maxLogID`"; - } - if (!$this->_ttstatid) { - if (!$this->getResult($queryStr)) - return false; - $this->_ttstatid=true; - } - else { - if (is_bool($override) && $override) { - if (!$this->getResult("DROP TABLE IF NOT EXISTS `ttstatid`")) - return false; - if (!$this->getResult($queryStr)) - return false; - } - } - return $this->_ttstatid; - } - elseif (!strcasecmp($tableName, "ttcontentid")) { - switch($this->_driver) { - case 'sqlite': - $queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttcontentid` AS ". - "SELECT `tblDocumentContent`.`document` AS `document`, ". - "MAX(`tblDocumentContent`.`version`) AS `maxVersion` ". - "FROM `tblDocumentContent` ". - "GROUP BY `tblDocumentContent`.`document` ". - "ORDER BY `tblDocumentContent`.`document`"; - break; - case 'pgsql': - $queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttcontentid` (`document` INTEGER, `maxVersion` INTEGER, PRIMARY KEY (`document`)); ". - "INSERT INTO `ttcontentid` SELECT `tblDocumentContent`.`document` AS `document`, ". - "MAX(`tblDocumentContent`.`version`) AS `maxVersion` ". - "FROM `tblDocumentContent` ". - "GROUP BY `tblDocumentContent`.`document` ". - "ORDER BY `tblDocumentContent`.`document`"; - break; - default: - $queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttcontentid` (PRIMARY KEY (`document`), INDEX (`maxVersion`)) ". - "SELECT `tblDocumentContent`.`document`, ". - "MAX(`tblDocumentContent`.`version`) AS `maxVersion` ". - "FROM `tblDocumentContent` ". - "GROUP BY `tblDocumentContent`.`document` ". - "ORDER BY `tblDocumentContent`.`document`"; - } - if (!$this->_ttcontentid) { - if (!$this->getResult($queryStr)) - return false; - $this->_ttcontentid=true; - } - else { - if (is_bool($override) && $override) { - if (!$this->getResult("DROP TABLE IF NOT EXISTS `ttcontentid`")) - return false; - if (!$this->getResult($queryStr)) - return false; - } - } - return $this->_ttcontentid; - } - return false; - } /* }}} */ - - /** - * Drop various temporary tables to enforce recreation when needed - * - * @param string $tableName - * - * @return bool - */ - private function __dropTemporaryTable($tableName) { /* {{{ */ - $queryStr = ''; - if (!strcasecmp($tableName, "ttreviewid")) { - $queryStr = "DROP TABLE IF EXISTS `ttreviewid`"; - } - elseif (!strcasecmp($tableName, "ttapproveid")) { - $queryStr = "DROP TABLE IF EXISTS `ttapproveid`"; - } - elseif (!strcasecmp($tableName, "ttstatid")) { - $queryStr = "DROP TABLE IF EXISTS `ttstatid`"; - } - elseif (!strcasecmp($tableName, "ttcontentid")) { - $queryStr = "DROP TABLE IF EXISTS `ttcontentid`"; - } - if($queryStr) { - if (!$this->getResult($queryStr)) - return false; - else { - $this->{'_'.$tableName} = false; - return true; - } - } - return false; - } /* }}} */ - - /** - * Create various views to speed up and simplify sql queries - * - * @param string $tableName - * @param bool $override - * - * @return bool - */ - private function __createView($tableName, $override=false) { /* {{{ */ - if (!strcasecmp($tableName, "ttreviewid")) { - switch($this->_driver) { - case 'sqlite': - $queryStr = "CREATE VIEW `ttreviewid` AS ". - "SELECT `tblDocumentReviewLog`.`reviewID` AS `reviewID`, ". - "MAX(`tblDocumentReviewLog`.`reviewLogID`) AS `maxLogID` ". - "FROM `tblDocumentReviewLog` ". - "GROUP BY `tblDocumentReviewLog`.`reviewID` "; //. - break; - case 'pgsql': - $queryStr = "CREATE VIEW `ttreviewid` AS ". - "SELECT `tblDocumentReviewLog`.`reviewID` AS `reviewID`, ". - "MAX(`tblDocumentReviewLog`.`reviewLogID`) AS `maxLogID` ". - "FROM `tblDocumentReviewLog` ". - "GROUP BY `tblDocumentReviewLog`.`reviewID` "; - break; - default: - $queryStr = "CREATE".($override ? " OR REPLACE" : "")." VIEW `ttreviewid` AS ". - "SELECT `tblDocumentReviewLog`.`reviewID` AS `reviewID`, ". - "MAX(`tblDocumentReviewLog`.`reviewLogID`) AS `maxLogID` ". - "FROM `tblDocumentReviewLog` ". - "GROUP BY `tblDocumentReviewLog`.`reviewID` "; - } - if (!$this->_ttreviewid) { - if (!$this->getResult($queryStr)) - return false; - $this->_ttreviewid=true; - } - else { - if (is_bool($override) && $override) { - if (!$this->getResult("DROP VIEW `ttreviewid`")) - return false; - if (!$this->getResult($queryStr)) - return false; - } - } - return $this->_ttreviewid; - } - elseif (!strcasecmp($tableName, "ttapproveid")) { - switch($this->_driver) { - case 'sqlite': - $queryStr = "CREATE VIEW `ttapproveid` AS ". - "SELECT `tblDocumentApproveLog`.`approveID` AS `approveID`, ". - "MAX(`tblDocumentApproveLog`.`approveLogID`) AS `maxLogID` ". - "FROM `tblDocumentApproveLog` ". - "GROUP BY `tblDocumentApproveLog`.`approveID` "; //. - break; - case 'pgsql': - $queryStr = "CREATE VIEW `ttapproveid` AS ". - "SELECT `tblDocumentApproveLog`.`approveID` AS `approveID`, ". - "MAX(`tblDocumentApproveLog`.`approveLogID`) AS `maxLogID` ". - "FROM `tblDocumentApproveLog` ". - "GROUP BY `tblDocumentApproveLog`.`approveID` "; - break; - default: - $queryStr = "CREATE".($override ? " OR REPLACE" : "")." VIEW `ttapproveid` AS ". - "SELECT `tblDocumentApproveLog`.`approveID`, ". - "MAX(`tblDocumentApproveLog`.`approveLogID`) AS `maxLogID` ". - "FROM `tblDocumentApproveLog` ". - "GROUP BY `tblDocumentApproveLog`.`approveID` "; - } - if (!$this->_ttapproveid) { - if (!$this->getResult($queryStr)) - return false; - $this->_ttapproveid=true; - } - else { - if (is_bool($override) && $override) { - if (!$this->getResult("DROP VIEW `ttapproveid`")) - return false; - if (!$this->getResult($queryStr)) - return false; - } - } - return $this->_ttapproveid; - } - elseif (!strcasecmp($tableName, "ttstatid")) { - switch($this->_driver) { - case 'sqlite': - $queryStr = "CREATE VIEW `ttstatid` AS ". - "SELECT `tblDocumentStatusLog`.`statusID` AS `statusID`, ". - "MAX(`tblDocumentStatusLog`.`statusLogID`) AS `maxLogID` ". - "FROM `tblDocumentStatusLog` ". - "GROUP BY `tblDocumentStatusLog`.`statusID` "; - break; - case 'pgsql': - $queryStr = "CREATE VIEW `ttstatid` AS ". - "SELECT `tblDocumentStatusLog`.`statusID` AS `statusID`, ". - "MAX(`tblDocumentStatusLog`.`statusLogID`) AS `maxLogID` ". - "FROM `tblDocumentStatusLog` ". - "GROUP BY `tblDocumentStatusLog`.`statusID` "; - break; - default: - $queryStr = "CREATE".($override ? " OR REPLACE" : "")." VIEW `ttstatid` AS ". - "SELECT `tblDocumentStatusLog`.`statusID`, ". - "MAX(`tblDocumentStatusLog`.`statusLogID`) AS `maxLogID` ". - "FROM `tblDocumentStatusLog` ". - "GROUP BY `tblDocumentStatusLog`.`statusID` "; - } - if (!$this->_ttstatid) { - if (!$this->getResult($queryStr)) - return false; - $this->_ttstatid=true; - } - else { - if (is_bool($override) && $override) { - if (!$this->getResult("DROP VIEW `ttstatid`")) - return false; - if (!$this->getResult($queryStr)) - return false; - } - } - return $this->_ttstatid; - } - elseif (!strcasecmp($tableName, "ttcontentid")) { - switch($this->_driver) { - case 'sqlite': - $queryStr = "CREATE VIEW `ttcontentid` AS ". - "SELECT `tblDocumentContent`.`document` AS `document`, ". - "MAX(`tblDocumentContent`.`version`) AS `maxVersion` ". - "FROM `tblDocumentContent` ". - "GROUP BY `tblDocumentContent`.`document` ". - "ORDER BY `tblDocumentContent`.`document`"; - break; - case 'pgsql': - $queryStr = "CREATE VIEW `ttcontentid` AS ". - "SELECT `tblDocumentContent`.`document` AS `document`, ". - "MAX(`tblDocumentContent`.`version`) AS `maxVersion` ". - "FROM `tblDocumentContent` ". - "GROUP BY `tblDocumentContent`.`document` ". - "ORDER BY `tblDocumentContent`.`document`"; - break; - default: - $queryStr = "CREATE".($override ? " OR REPLACE" : "")." VIEW `ttcontentid` AS ". - "SELECT `tblDocumentContent`.`document`, ". - "MAX(`tblDocumentContent`.`version`) AS `maxVersion` ". - "FROM `tblDocumentContent` ". - "GROUP BY `tblDocumentContent`.`document` ". - "ORDER BY `tblDocumentContent`.`document`"; - } - if (!$this->_ttcontentid) { - if (!$this->getResult($queryStr)) - return false; - $this->_ttcontentid=true; - } - else { - if (is_bool($override) && $override) { - if (!$this->getResult("DROP VIEW `ttcontentid`")) - return false; - if (!$this->getResult($queryStr)) - return false; - } - } - return $this->_ttcontentid; - } - return false; - } /* }}} */ - - /** - * Create various temporary tables or view to speed up and simplify sql queries - * - * @param string $tableName - * @param bool $override - * - * @return bool - */ - public function createTemporaryTable($tableName, $override=false) { /* {{{ */ - if($this->_useviews) - return $this->__createView($tableName, $override); - else - return $this->__createTemporaryTable($tableName, $override); - } /* }}} */ - - /** - * Drop various temporary tables to force recreation when next time needed - * - * @param string $tableName - * - * @return bool - */ - public function dropTemporaryTable($tableName) { /* {{{ */ - if($this->_useviews) - return true; // No need to recreate a view - else - return $this->__dropTemporaryTable($tableName); - } /* }}} */ - - /** - * Return sql statement for extracting the date part from a field - * containing a unix timestamp - * - * @param string $fieldname name of field containing the timestamp - * @param string $format - * @return string sql code - */ - function getDateExtract($fieldname, $format='%Y-%m-%d') { /* {{{ */ - switch($this->_driver) { - case 'mysql': - return "from_unixtime(`".$fieldname."`, ".$this->qstr($format).")"; - break; - case 'sqlite': - return "strftime(".$this->qstr($format).", `".$fieldname."`, 'unixepoch')"; - break; - case 'pgsql': - switch($format) { - case '%Y-%m': - return "to_char(to_timestamp(`".$fieldname."`), 'YYYY-MM')"; - break; - default: - return "to_char(to_timestamp(`".$fieldname."`), 'YYYY-MM-DD')"; - break; - } - break; - } - return ''; - } /* }}} */ - - /** - * Return sql statement for returning the current date and time - * in format Y-m-d H:i:s - * - * @return string sql code - */ - function getCurrentDatetime() { /* {{{ */ - switch($this->_driver) { - case 'mysql': - return "CURRENT_TIMESTAMP"; - break; - case 'sqlite': - return "datetime('now', 'localtime')"; - break; - case 'pgsql': - return "now()"; - break; - } - return ''; - } /* }}} */ - - /** - * Return sql statement for returning the current timestamp - * - * @return string sql code - */ - function getCurrentTimestamp() { /* {{{ */ - switch($this->_driver) { - case 'mysql': - return "UNIX_TIMESTAMP()"; - break; - case 'sqlite': - return "strftime('%s', 'now')"; - break; - case 'pgsql': - return "date_part('epoch',CURRENT_TIMESTAMP)::int"; - break; - } - return ''; - } /* }}} */ - - /** - * Return sql statement for returning the current timestamp - * - * @param $field - * @return string sql code - */ - function castToText($field) { /* {{{ */ - switch($this->_driver) { - case 'pgsql': - return $field."::TEXT"; - break; - } - return $field; - } /* }}} */ - - /** - * Create an sql dump of the complete database - * - * @param resource $fp name of dump file - * @return bool - */ - function createDump($fp) { /* {{{ */ - $tables = $this->TableList('TABLES'); - foreach($tables as $table) { - if($table == 'sqlite_sequence') - continue; - $query = "SELECT * FROM `".$table."`"; - $records = $this->getResultArray($query); - fwrite($fp,"\n-- TABLE: ".$table."--\n\n"); - foreach($records as $record) { - $values=""; - $i = 1; - foreach ($record as $column) { - if (is_numeric($column)) $values .= $column; - else $values .= $this->qstr($column); - - if ($i<(count($record))) $values .= ","; - $i++; - } - - fwrite($fp, "INSERT INTO `".$table."` VALUES (".$values.");\n"); - } - } - return true; - } /* }}} */ -} diff --git a/SeedDMS_Core/Core/inc.FileUtils.php b/SeedDMS_Core/Core/inc.FileUtils.php deleted file mode 100644 index 43289fce8..000000000 --- a/SeedDMS_Core/Core/inc.FileUtils.php +++ /dev/null @@ -1,529 +0,0 @@ - - * @copyright Copyright (C) 2002-2005 Markus Westphal, - * 2006-2008 Malcolm Cowe, 2010 Matteo Lucarelli, - * 2010-2022 Uwe Steinmann - * @version Release: @package_version@ - */ - -/** - * Class to file operation in the document management system - * Use the methods of this class only for files below the content - * directory but not for temporäry files, cache files or log files. - * - * @category DMS - * @package SeedDMS_Core - * @author Markus Westphal, Malcolm Cowe, Uwe Steinmann - * @copyright Copyright (C) 2002-2005 Markus Westphal, - * 2006-2008 Malcolm Cowe, 2010 Matteo Lucarelli, - * 2010-2022 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; - } /* }}} */ - - /** - * Return the mimetype of a given file - * - * This method uses finfo to determine the mimetype - * but will correct some mimetypes which are - * not propperly determined or could be more specific, e.g. text/plain - * when it is actually text/markdown. In thoses cases - * the file extension will be taken into account. - * - * @param string $filename name of file on disc - * @return string mimetype - */ - static function mimetype($filename) { /* {{{ */ - $finfo = finfo_open(FILEINFO_MIME_TYPE); - $mimetype = finfo_file($finfo, $filename); - - switch($mimetype) { - case 'application/octet-stream': - case 'text/plain': - $lastDotIndex = strrpos($filename, "."); - if($lastDotIndex === false) $fileType = "."; - else $fileType = substr($filename, $lastDotIndex); - if($fileType == '.md') - $mimetype = 'text/markdown'; - break; - } - return $mimetype; - } /* }}} */ - - /** - * @param integer $size - * @param array $sizes list of units for 10^0, 10^3, 10^6, ..., 10^(n*3) bytes - * @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]); - } /* }}} */ - - /** - * Parses a string like '[0-9]+ *[BKMGT]*' into an integer - * B,K,M,G,T stand for byte, kilo byte, mega byte, giga byte, tera byte - * If the last character is omitted, bytes are assumed. - * - * @param $str - * @return bool|int - */ - static function parse_filesize($str) { /* {{{ */ - if(!preg_match('/^([0-9]+) *([BKMGT]*)$/', trim($str), $matches)) - return false; - $value = $matches[1]; - $unit = $matches[2] ? $matches[2] : 'B'; - switch($unit) { - case 'T': - return $value * 1024 * 1024 * 1024 *1024; - break; - case 'G': - return $value * 1024 * 1024 * 1024; - break; - case 'M': - return $value * 1024 * 1024; - break; - case 'K': - return $value * 1024; - break; - default; - return (int) $value; - break; - } - /** @noinspection PhpUnreachableStatementInspection */ - return false; - } /* }}} */ - - /** - * @param $file - * @return string - */ - static function file_exists($file) { /* {{{ */ - return file_exists($file); - } /* }}} */ - - /** - * @param $file - * @return string - */ - static function checksum($file) { /* {{{ */ - return md5_file($file); - } /* }}} */ - - /** - * @param $string mimetype - * @return string file extension with the dot or an empty string - */ - static function fileExtension($mimetype) { /* {{{ */ - switch($mimetype) { - case "application/pdf": - case "image/png": - case "image/gif": - case "image/jpg": - $expect = substr($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', - 'text/markdown' => 'md', - '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 (!self::copyDir($sourcePath, $targetPath)) - return false; - /** @noinspection PhpUndefinedFunctionInspection */ - return self::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; - } /* }}} */ -} diff --git a/SeedDMS_Core/bootstrap-5.php b/SeedDMS_Core/bootstrap-5.php deleted file mode 100644 index 5d0d0e4a5..000000000 --- a/SeedDMS_Core/bootstrap-5.php +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/SeedDMS_Core/oldtests/getfoldertree.php b/SeedDMS_Core/oldtests/getfoldertree.php deleted file mode 100644 index a5f12f160..000000000 --- a/SeedDMS_Core/oldtests/getfoldertree.php +++ /dev/null @@ -1,25 +0,0 @@ -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); - -?> diff --git a/SeedDMS_Core/oldtests/getusers.php b/SeedDMS_Core/oldtests/getusers.php deleted file mode 100644 index 083718ab2..000000000 --- a/SeedDMS_Core/oldtests/getusers.php +++ /dev/null @@ -1,14 +0,0 @@ -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"; - -?> diff --git a/SeedDMS_Core/oldtests/reverselookup.php b/SeedDMS_Core/oldtests/reverselookup.php deleted file mode 100644 index 93abec009..000000000 --- a/SeedDMS_Core/oldtests/reverselookup.php +++ /dev/null @@ -1,44 +0,0 @@ -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"; -} - -?> - diff --git a/SeedDMS_Core/package.xml b/SeedDMS_Core/package.xml deleted file mode 100644 index 9f4881c4f..000000000 --- a/SeedDMS_Core/package.xml +++ /dev/null @@ -1,2039 +0,0 @@ - - - SeedDMS_Core - pear.php.net - Document management system - SeedDMS is a web based document management system (DMS). This is - the core of it, providing the basic functionality to create/update and delete - folders and documents. It also contains a user and group managment - - Uwe Steinmann - steinm - uwe@steinmann.cx - yes - - 2022-11-21 - - - 5.1.29 - 5.1.29 - - - stable - stable - - GPL License - -- SeedDMS_Core_Folder::addDocument() does rollback transaction propperly when setting document categories fail -- add $skiproot and $sep parameter to SeedDMS_Core_Folder::getFolderPathPlain() -- add class name for 'documentfile' -- add method SeedDMS_Core_KeywordCategory::countKeywordLists() - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 4.3.0 - - - 1.5.4 - - - - - - - 2010-04-27 - - 3.0.0 - 3.0.0 - - - stable - stable - - GPL License - -Initial release - - - - 2011-07-23 - - - 3.2.0 - 3.2.0 - - - stable - stable - - GPL License - -New release - - - - 2012-02-08 - - - 3.3.0 - 3.3.0 - - - beta - stable - - GPL License - -- added methods to find and repair errors in document and folder records -- removed sendmail parameter from some methods in LetoDMS_Core_Document -- do not use some of the temporay tables anymore -- SetFetchMode(ADODB_FETCH_ASSOC) in LetoDMS_Core_DatabaseAccess::connect() - - - - 2012-03-21 - - - 3.3.1 - 3.3.1 - - - beta - stable - - GPL License - -- new release - - - - 2012-03-22 - - - 3.3.2 - 3.3.2 - - - beta - stable - - GPL License - -- fixed bug in LetoDMS_Core_Document::getDir() - - - - 2012-03-28 - - - 3.3.3 - 3.3.3 - - - beta - stable - - GPL License - -- fixed bug in LetoDMS_Core_Document::getPath() - - - - 2012-04-11 - - - 3.3.4 - 3.3.4 - - - beta - stable - - GPL License - -- fixed bug in LetoDMS_Core_DocumentFile::getPath() - - - - 2012-04-30 - - - 3.3.5 - 3.3.5 - - - beta - stable - - GPL License - -- minor corrections - - - - 2012-07-16 - - - 3.3.6 - 3.3.6 - - - beta - stable - - GPL License - -- no changes, just keep same version as letodms application - - - - 2012-08-25 - - - 3.3.7 - 3.3.7 - - - beta - stable - - GPL License - -- no changes, just keep same version as letodms application - - - - 2012-09-16 - - - 3.3.8 - 3.3.8 - - - beta - stable - - GPL License - -- more sql injection protection in LetoDMS_Core_User - - - - 2012-09-19 - - - 3.3.9 - 3.3.9 - - - beta - stable - - GPL License - -- version update to be in sync with letodms application - - - - 2012-12-13 - - - 3.4.0 - 3.4.0 - - - beta - stable - - GPL License - -- added PDO database driver, several sql changes for better compatiblity -- fixed bug when adding a new document category -- make sure the database remains consistent even in case of errors - - - - 2013-01-24 - - - 4.0.0pre1 - 4.0.0 - - - beta - stable - - GPL License - -- added database transactions -- new workflow -- replaced old var declaration - - - - 2013-02-06 - - - 4.0.0pre2 - 4.0.0 - - - beta - stable - - GPL License - -- lots of bug fixes -- replaced more of old var declaration -- more code documentation - - - - 2013-02-08 - - - 4.0.0pre3 - 4.0.0 - - - beta - stable - - GPL License - -- minor bug fixes - - - - 2013-02-11 - - - 4.0.0pre4 - 4.0.0 - - - beta - stable - - GPL License - -- calculate checksum for document versions -- some bug fixes -- some more documentation -- added new methods SeedDMS_Core_Document::getReadUserList() and - SeedDMS_Core_Folder::getReadUserList() which replaces getApproversList() -- fixed sql statement in getReadUserList() for sqlite3 - - - - 2013-02-14 - - - 4.0.0pre5 - 4.0.0 - - - beta - stable - - GPL License - -- changed name from letodms to seeddms -- fixed SeedDMS_Database::TableList() - - - - 2013-02-20 - - - 4.0.0RC1 - 4.0.0 - - - beta - stable - - GPL License - -- minor bugfixes - - - - 2013-02-26 - - - 4.0.0 - 4.0.0 - - - beta - stable - - GPL License - -- minor bugfixes - - - - 2013-03-28 - - - 4.1.0 - 4.1.0 - - - beta - stable - - GPL License - -- minor bugfixes - - - - 2013-04-05 - - - 4.1.1 - 4.1.1 - - - beta - stable - - GPL License - -- stay in sync with seeddms application - - - - 2013-04-05 - - - 4.1.2 - 4.1.0 - - - stable - stable - - GPL License - -- set propper folderList of sub folders after moving a folder - - - - 2013-04-08 - - - 4.1.3 - 4.1.0 - - - stable - stable - - GPL License - -- stay in sync with seeddms application - - - - 2013-04-22 - - - 4.2.0 - 4.2.0 - - - stable - stable - - GPL License - -- fixed bug in SeedDMS_Core_DocumentContent::addIndApp() - - - - 2013-04-30 - - - 4.2.1 - 4.2.1 - - - stable - stable - - GPL License - -- fixed bug in SeedDMS_Core_DocumentContent::addIndApp() - - - - 2013-05-17 - - - 4.2.2 - 4.2.1 - - - stable - stable - - GPL License - -- admins can be added as reviewer/approver again - - - - 2013-09-05 - - - 4.3.0 - 4.3.0 - - - stable - stable - - GPL License - -- various small corrections -- comment of version is no longer taken from document if version comment is empty -- passing an array of users to SeedDMЅ_Core_DMS::search() instead of a single user ist now allowed -- turn on foreign key constraints for sqlite3 -- SeedDMЅ_Core_Folder::getPath() can handle a subfolder treated as a root folder - - - - 2013-11-27 - - - 4.3.2 - 4.3.2 - - - stable - stable - - GPL License - -- new method SeedDMS_Core_Folder::isSubFolder() -- check for subFolder in SeedDMS_Core_Folder::setParent() -- new methods SeedDMS_Core_DMS::checkFolders() and SeedDMS_Core_DMS::checkDocuments() - - - - 2014-02-01 - - - 4.3.3 - 4.3.3 - - - stable - stable - - GPL License - -- SeedDMS_Folder::getDocuments() and SeedDMS_Folder::getSubFolders() do not - do any sorting if $orderby is not set. -- database hostname can have port seperated by ':' -- make all functions in SeedDMS_Core_File static (fixes problem with php 5.5.x) - - - - 2014-02-01 - - - 4.3.4 - 4.3.4 - - - stable - stable - - GPL License - -- fix handling of multivalue attributes - - - - 2014-03-04 - - - 4.3.5 - 4.3.5 - - - stable - stable - - GPL License - -no changes - - - - 2014-03-18 - - - 4.3.6 - 4.3.6 - - - stable - stable - - GPL License - -- add optional parameters $publiconly=false and $user=null to SeedDMS_Core_Document::getDocumentLinks() -- add new method SeedDMS_Core_Document::getReverseDocumentLinks() - - - - 2014-03-21 - - - 4.3.7 - 4.3.7 - - - stable - stable - - GPL License - -no changes - - - - 2014-04-09 - - - 4.3.8 - 4.3.8 - - - stable - stable - - GPL License - -- new method SeedDMS_Core_DMS::getStatisticalData() - - - - 2014-07-30 - - - 4.3.9 - 4.3.9 - - - stable - stable - - GPL License - -- SeedDMS_Core_KeywordCategory::getKeywordLists() sorts keywords aphabetically -- SeedDMS_Core_DMS::addUser() doesn't throw an error if sql_mode is set to STRICT_TRANS_TABLES and pwdexpiration is not set to a valid date. - - - - 2014-10-22 - - - 4.3.10 - 4.3.10 - - - stable - stable - - GPL License - -new release - - - - 2014-11-13 - - - 4.3.11 - 4.3.11 - - - stable - stable - - GPL License - -- fixed saving multivalue attributes -- add method SeedDMS_Core_Attribute::getValueAsArray() - - - - 2014-11-17 - - - 4.3.12 - 4.3.12 - - - stable - stable - - GPL License - -- fix searching folders with multivalue attributes - - - - 2014-11-27 - - - 4.3.13 - 4.3.13 - - - stable - stable - - GPL License - -- fix searching for attributes -- add some more documentation -- SeedDMS_Core_DMS::getDocumentCategories() returns categories sorted by name (Bug #181) -- new methode SeedDMS_Core_Document::replaceContent() which replaces the content of a version. - - - - - 4.3.14 - 4.3.14 - - - stable - stable - - GPL License - -- add missing start transaction in SeedDMD_Core_Folder::remove() -- SeedDMD_Core_Folder::isSubFolder() doesn't compare object instances anymore (Bug #194) - - - - 2015-02-12 - - - 4.3.15 - 4.3.15 - - - stable - stable - - GPL License - -users returned by SeedDMS_Core_DMS::getAllUsers() have language and theme set again - - - - 2015-03-20 - - - 4.3.16 - 4.3.16 - - - stable - stable - - GPL License - -no changes - - - - 2015-03-27 - - - 4.3.17 - 4.3.17 - - - stable - stable - - GPL License - -clean workflow log when a document version was deleted - - - - 2015-06-09 - - - 4.3.18 - 4.3.18 - - - stable - stable - - GPL License - -- add optional paramter $msg to SeedDMS_Core_DocumentContent::verifyStatus() -- add method SeedDMS_Core_DMS::getDuplicateDocumentContent() - - - - 2015-06-26 - - - 4.3.19 - 4.3.19 - - - stable - stable - - GPL License - -- add optional paramter $noclean to clearAccessList(), setDefaultAccess(), setInheritAccess() -- clearAccessList() will clean up the notifier list -- new method cleanNotifyList() - - - - 2015-06-26 - - - 4.3.20 - 4.3.20 - - - stable - stable - - GPL License - -- add method SeedDMS_Core_DMS::checkDate() -- add method SeedDMS_Core_Document::setDate() -- add method SeedDMS_Core_Folder::setDate() -- date can be passed to SeedDMS_Core_DocumentContent::setStatus() -- add method SeedDMS_Core_DocumentContent::rewriteStatusLog() -- add method SeedDMS_Core_DocumentContent::rewriteReviewLog() -- add method SeedDMS_Core_DocumentContent::rewriteApprovalLog() -- access rights for guest are also taken into account if set in an acl. Previously guest could gain read rights even if the access was probibited -by a group or user right - - - - 2015-09-28 - - - 4.3.21 - 4.3.21 - - - stable - stable - - GPL License - -- add method SeedDMS_Core_Database::getCurrentTimestamp() -- add method SeedDMS_Core_Database::getCurrentDatetime() -- user getCurrentTimestamp() and getCurrentDatetime() whenever possible - - - - 2015-11-09 - - - 4.3.22 - 4.3.22 - - - stable - stable - - GPL License - -- fix sql statement to reset password -- pass some more information for timeline - - - - 2016-01-21 - - - 4.3.23 - 4.3.23 - - - stable - stable - - GPL License - -- new method SeedDMS_Core_DMS::createDump() -- minor improvements int SeedDMS_Core_Document::getReadAccessList() - - - - 2016-01-22 - - - 4.3.24 - 4.3.24 - - - stable - stable - - GPL License - -- make sure boolean attribute is saved as 0/1 -- add SeedDMS_Core_User::[g|s]etMandatoryWorkflows() -- add SeedDMS_Core_User::getNotifications() -- add SeedDMS_Core_Group::getNotifications() -- SeedDMS_Core_DMS::getNotificationsByGroup() and -SeedDMS_Core_DMS::getNotificationsByUser() are deprecated -- SeedDMS_Core_DocumentCategory::getDocumentsByCategory() now returns the documents -- add SeedDMS_Core_Group::getWorkflowStatus() -- SeedDMS_Core_User::getDocumentsLocked() sets locking user propperly - - - - 2016-01-22 - - - 5.0.0 - 5.0.0 - - - stable - stable - - GPL License - -- classes can be overloaded -- clean workflow log when a document version was deleted - - - - 2016-01-21 - - - 4.3.24 - 4.3.24 - - - stable - stable - - GPL License - -- make sure boolean attribute is saved as 0/1 -- add SeedDMS_Core_User::[g|s]etMandatoryWorkflows() -- add SeedDMS_Core_User::getNotifications() -- add SeedDMS_Core_Group::getNotifications() -- SeedDMS_Core_DMS::getNotificationsByGroup() and -SeedDMS_Core_DMS::getNotificationsByUser() are deprecated -- SeedDMS_Core_DocumentCategory::getDocumentsByCategory() now returns the documents -- add SeedDMS_Core_Group::getWorkflowStatus() -- SeedDMS_Core_User::getDocumentsLocked() sets locking user propperly - - - - 2016-03-08 - - - 4.3.25 - 4.3.25 - - - stable - stable - - GPL License - -- rename SeedDMS_Core_Group::getNotificationsByGroup() to getNotifications() -- use __construct() for all constructors -- fix setting multi value attributes for versions - - - - 2016-04-04 - - - 4.3.26 - 4.3.26 - - - stable - stable - - GPL License - -- add more callbacks - - - - 2016-04-26 - - - 4.3.27 - 4.3.27 - - - stable - stable - - GPL License - -- callbacks can have more then one user function -- fix some sql statements, because they didn't work with mysql 5.7.5 anymore - - - - 2016-08-24 - - - 4.3.28 - 4.3.28 - - - stable - stable - - GPL License - -- SeedDMЅ_Core_DMS::search() searches also comment of document version - - - - 2016-09-06 - - - 4.3.29 - 4.3.29 - - - stable - stable - - GPL License - -- SeedDMЅ_Core_Object::getAttributes() orders attributes by name of attribute definition -- SeedDMЅ_Core_Workflow::addTransition() force reload of transition list after adding a -- SeedDMЅ_Core_Document::rewrite[Review|Approval]Log() will also copy file if it exists -- add method SeedDMЅ_Core_Document::rewriteWorkflowLog() - - - - 2016-10-07 - - - 4.3.30 - 4.3.30 - - - stable - stable - - GPL License - -- new method SeedDMЅ_Core_AttributeDefinition::getValueSetSeparator() -- trim each value of a value set before saving the complete value set as a string - - - - 2016-11-02 - - - 4.3.31 - 4.3.31 - - - stable - stable - - GPL License - -- new method SeedDMЅ_Core_WorkflowAction::getTransitions() -- new method SeedDMЅ_Core_WorkflowState::getTransitions() -- new method SeedDMЅ_Core_AttributeDefinition::parseValue() -- add check for cycles in workflow SeedDMS_Core_Workflow::checkForCycles() - - - - 2017-01-12 - - - 4.3.32 - 4.3.32 - - - stable - stable - - GPL License - -- order groups by name returned by getReadAccessList() -- add optional parameter to SeedDMS_Core_DMS::filterDocumentLinks() -- SeedDMS_Core_DMS::search() can search for document/folder id - - - - 2017-02-22 - - - 4.3.33 - 4.3.33 - - - stable - stable - - GPL License - -- SeedDMЅ_Core_DMS::getTimeline() no longer returns duplicate documents -- SeedDMЅ_Core_Document::addContent() sets workflow after status was set -- SeedDMЅ_Core_Keyword::setOwner() fix sql statement -- SeedDMЅ_Core_User::setFullname() minor fix in sql statement - - - - 2017-02-28 - - - 4.3.34 - 4.3.34 - - - stable - stable - - GPL License - -SeedDMS_Core_DMS::getDuplicateDocumentContent() returns complete document - - - - 2017-07-11 - - - 4.3.35 - 4.3.35 - - - stable - stable - - GPL License - -do not sort some temporary tables anymore, because it causes an error in mysql if sql_mode=only_full_group_by is set - - - - 2017-03-22 - - - 4.3.36 - 4.3.36 - - - stable - stable - - GPL License - -- fix sql statement for creating temp. tables (sqlite) - - - - 2018-02-14 - - - 4.3.37 - 4.3.37 - - - stable - stable - - GPL License - -- SeedDMS_Core_DMS::search() finds documents without a status log - - - - 2016-01-22 - - - 5.0.1 - 5.0.1 - - - stable - stable - - GPL License - -- all changes from 4.3.24 merged - - - - 2016-04-26 - - - 5.0.2 - 5.0.2 - - - stable - stable - - GPL License - -- all changes from 4.3.25 merged - - - - 2016-04-04 - - - 5.0.3 - 5.0.3 - - - stable - stable - - GPL License - -- use classname from SeedDMS_Core_DMS::_classnames for SeedDMS_Core_DocumentContent -- all changes from 4.3.26 merged - - - - 2016-05-03 - - - 5.0.4 - 5.0.4 - - - stable - stable - - GPL License - -- all changes from 4.3.27 merged - - - - 2016-08-09 - - - 5.0.5 - 5.0.5 - - - stable - stable - - GPL License - -- all changes from 4.3.28 merged - - - - 2016-09-06 - - - 5.0.6 - 5.0.6 - - - stable - stable - - GPL License - -- all changes from 4.3.29 merged - - - - 2016-11-02 - - - 5.0.7 - 5.0.7 - - - stable - stable - - GPL License - -- all changes from 4.3.30 merged -- better attribute value checking - - - - 2016-11-02 - - - 5.0.8 - 5.0.8 - - - stable - stable - - GPL License - -- all changes from 4.3.31 merged - - - - 2016-11-02 - - - 5.0.9 - 5.0.9 - - - stable - stable - - GPL License - -- all changes from 4.3.32 merged - - - - 2017-02-20 - - - 5.0.10 - 5.0.10 - - - stable - stable - - GPL License - -- all changes from 4.3.33 merged - - - - 2017-02-28 - - - 5.0.11 - 5.0.11 - - - stable - stable - - GPL License - -- all changes from 4.3.34 merged - - - - 2017-03-23 - - - 5.0.12 - 5.0.12 - - - stable - stable - - GPL License - -all sql statements can be logged to a file -do not sort some temporary tables anymore, because it causes an error in mysql if sql_mode=only_full_group_by is set - - - - 2017-07-13 - - - 5.0.13 - 5.0.13 - - - stable - stable - - GPL License - -- all changes from 4.3.36 merged - - - - 2017-02-20 - - - 5.1.0 - 5.1.0 - - - stable - stable - - GPL License - -- added postgres support - - - - 2017-02-20 - - - 5.1.1 - 5.1.1 - - - stable - stable - - GPL License - -- all changes from 5.0.11 merged - - - - 2017-03-23 - - - 5.1.2 - 5.1.2 - - - stable - stable - - GPL License - -- SeedDMS_Core_DMS::filterDocumentFiles() returns also documents which are not public - if the owner tries to access them -- Check return value of onPreRemove[Document|Folder], return from calling method if bool -- Add SeedDMS_Core_DMS::getDocumentList() -- Limit number of duplicate files to 1000 -- Add hook on(Pre|Post)RemoveContent -- Add hook onAttributeValidate - - - - 2017-08-23 - - - 5.1.3 - 5.1.3 - - - stable - stable - - GPL License - -- SeedDMS_Core_Document::getNotifyList() and SeedDMS_Core_Folder::getNotifyList() -returns just users which are not disabled -- add new methods removeFromProcesses(), getWorkflowsInvolved(), getKeywordCategories() to SeedDMS_Core_User -- add methods isMandatoryReviewerOf() and isMandatoryApproverOf() -- add methods transferDocumentsFolders() and transferEvents() -- add method SeedDMS_Core_DMS::getDocumentByOriginalFilename() - - - - 2017-09-05 - - - 5.1.4 - 5.1.4 - - - stable - stable - - GPL License - -- add virtual access mode for document links and attachments plus callbacks to - check access mode in a hook -- add new method SeedDMS_Core_DMS::getDocumentsExpired() -- all changes from 5.0.14 merged - - - - 2017-11-07 - - - 5.1.5 - 5.1.5 - - - stable - stable - - GPL License - -- use views instead of temp. tables -- add list of expired documents in SeedDMS_Core_DMS::getDocumentList() -- add methods to set comment, name, public, version of document files -- add method SeedDMS_Core_Document::transferToUser() -- SeedDMS_Core_Document::addDocumentFile() returns object of file -- add SeedDMS_Core_DocumentFile::setDate() -- remove SeedDMS_Core_DocumentCategory::addCategory() and getCategories() -- add optional parameters $limit and $offset to SeedDMS_Core_Folder::getDocuments() - and SeedDMS_Core_Folder::getSubFolders() -- getInstance() returns now null instead of false if the object was not found in the db -- add new methods SeedDMS_Core_Document::addCategories() and - SeedDMS_Core_Document::removeCategories() - - - - 2018-02-14 - - - 5.1.6 - 5.1.6 - - - stable - stable - - GPL License - -- add SeedDMS_Core_Folder::getDocumentsMinMax() -- add lots of DocBlocks from merge request #8 -- add SeedDMS_Core_AttributeDefinition::removeValue() - - - - 2018-04-05 - - - 5.1.7 - 5.1.7 - - - stable - stable - - GPL License - -- just bump version - - - - 2018-07-02 - - - 5.1.8 - 5.1.8 - - - stable - stable - - GPL License - -- SeedDMS_Core_DMS::search() returns false in case of an error -- do not use views in DBAccessPDO by default anymore, use temp. tables -- SeedDMS_Core_Document::getNotifyList() has new parameter to include disabled user in list -- fix possible sql injection in SeedDMS_Core_User - - - - 2018-11-13 - - - 5.1.9 - 5.1.9 - - - stable - stable - - GPL License - -- context can be passed to getAccessMode() -- call hook in SeedDMS_Core_Folder::getAccessMode() -- new optional parameter $listguest for SeedDMS_Core_Document::getReadAccessList() -- remove deprecated methods SeedDMS_Core_Document::convert(), SeedDMS_Core_Document::wasConverted(), SeedDMS_Core_Document::viewOnline(), SeedDMS_Core_Document::getUrl() - - - - 2019-04-04 - - - 5.1.10 - 5.1.10 - - - stable - stable - - GPL License - -- fix php warning if workflow state doesn' have next transition -- add method SeedDMS_Core_DatabaseAccess::setLogFp() - - - - 2019-05-03 - - - 5.1.11 - 5.1.11 - - - stable - stable - - GPL License - -- ??? - - - - 2019-07-01 - - - 5.1.12 - 5.1.12 - - - stable - stable - - GPL License - -- parameter $orderby passed to SeedDMS_Core_Folder::getDocuments() and SeedDMS_Core_Folder::getSubFolders() can be a string, but only the first char is evaluated -- SeedDMS_Core_DMS::search() excepts parameters as array, added orderby -- add SeedDMS_Core_Folder::hasSubFolderByName() -- fix SeedDMS_Core_Folder::hasDocumentByName() which returned an int > 0 if documents - has been loaded before and even if the document searching for was not among them. -- add new method SeedDMS_Core_Folder::empty() - - - - 2019-09-06 - - - 5.1.13 - 5.1.13 - - - stable - stable - - GPL License - -- add decorators -- add new methods SeedDMS_Core_Document::isType(), SeedDMS_Core_Folder::isType(), SeedDMS_Core_DocumentContent::isType(). Use them instead of checking the class name. -- skip a fileType with just a '.' - - - - 2020-02-17 - - - 5.1.14 - 5.1.14 - - - stable - stable - - GPL License - -- speed up SeedDMS_Core_Folder::getSubFolders() SeedDMS_Core_Folder::getDocuments() by minimizing the number of sql queries. - - - - 2020-03-02 - - - 5.1.15 - 5.1.15 - - - stable - stable - - GPL License - -- no changes, just keep same version as seeddms application - - - - 2020-04-14 - - - 5.1.16 - 5.1.16 - - - stable - stable - - GPL License - -- fix call of hooks in SeedDMS_Core -- add variable lasterror in SeedDMS_Core_DMS which can be set by hooks to pass an - error msg to the calling application -- better error checking in SeedDMS_Core_Document::addDocumentFile() - - - - 2020-05-22 - - - 5.1.17 - 5.1.17 - - - stable - stable - - GPL License - -- add new callback onSetStatus -- fix SeedDMS_Core_DMS::getExpiredDocuments(), sql statement failed because temp. tables were not created -- add parameters $orderdir, $orderby, $update to SeedDMS_Core::getExpiredDocuments() - - - - 2020-05-28 - - - 5.1.18 - 5.1.18 - - - stable - stable - - GPL License - -- fixed remaining todos -- fixed parsing of file size in SeedDMS_Core_File::parse_filesize() -- fix SeedDMS_Core_DMS::getDocumentByOriginalFilename() - - - - 2020-07-30 - - - 5.1.19 - 5.1.19 - - - stable - stable - - GPL License - -- add method SeedDMS_Core_Document::setParent() as an alias for setFolder() -- clear the save content list and latest content in SeedDMS_Core_Document after - a version has been deleted. -- new method SeedDMS_Core_Document::isLatestVersion() -- add new attribute types 'document', 'folder', 'user', 'group' - - - - 2020-09-29 - - - 5.1.20 - 5.1.20 - - - stable - stable - - GPL License - -- SeedDMS_Core_DMS::getDocumentList() returns false, if an unknown list is passed -- SeedDMS_Core_Document::getDocumentFiles() has new parameter to select only those files attached to a specific version of the document -- removing a document version will not remove attachments of the document anymore -- set dms of new user instances in SeedDMS_Core_Group - - - - 2020-09-29 - - - 5.1.21 - 5.1.21 - - - stable - stable - - GPL License - -- SeedDMS_Folder_DMS::getAccessList() and getDefaultAccess() do not return fals anymore if the parent does not exists. They just stop inheritance. -- pass attribute value to callback 'onAttributeValidate' -- new paramter 'new' of methode SeedDMЅ_Core_AttributeDefinition::validate() -- check if folder/document is below rootDir can be turned on (default off) -- SeedDMS_Core_User::setHomeFolder() can be used to unset the home folder -- check if attribute definition exists when setting attributes of folders and documents - - - - 2021-03-15 - - - 5.1.22 - 5.1.22 - - - stable - stable - - GPL License - -- add SeedDMS_Core_DatabaseAccess::hasTable() -- add SeedDMS_Core_User->isType() and SeedDMS_Core_Group->isType() -- add SeedDMS_Core_User->getDMS() and SeedDMS_Core_Group->getDMS() -- add new parameter to SeedDMS_Core_DMS->getDocumentList() for skipping expired documents -- add parameter $incdisabled to SeedDMS_Core_Folder::getNotifyList() -- do not validate value in SeedDMS_Core_Attribute::setValue(), it should have been done before -- SeedDMS_Core_DMS::search() can search for last date of document status change -- smarter caching in SeedDMS_Core_Document::getDocumentFiles() which fixes a potential - problem when removing a document - - - - 2021-08-19 - - - 5.1.23 - 5.1.23 - - - stable - stable - - GPL License - -- SeedDMS_Core_DMS::getTimeline() uses status log instead of document content -- add methods SeedDMS_Core_DocumentContent::getReviewers() and SeedDMS_Core_DocumentContent::getApprovers() -- add methods SeedDMS_Core_DocumentContent::getApproveLog() and SeedDMS_Core_DocumentContent::getReviewLog() -- better handling of document with an empty workflow state -- fix checking of email addresses by using filter_var instead of regex -- add new method SeedDMS_Core_Document::hasCategory() -- add new method SeedDMS_Core_DocumentContent::removeReview() -- add new method SeedDMS_Core_DocumentContent::removeApproval() -- add new method SeedDMS_Core_User::getFolders() -- add new method SeedDMS_Core_User::getDocumentContents() -- add new method SeedDMS_Core_User::getDocumentFiles() -- add new method SeedDMS_Core_User::getDocumentLinks() -- add new type 'foldersperuser' to method SeedDMS_Core_DMS::getStatisticalData() - - - - 2021-12-11 - - - 5.1.24 - 5.1.24 - - - stable - stable - - GPL License - -- in SeedDMS_Core_DocumentContent::removeWorkflow() remove records from tblWorklflowLog before tblDWorkflowDocumentContent -- make all class variables of SeedDMS_Core_User protected -- fix various errors in SeedDMS_Core_AttributeDefinition::validate() -- add lots of unit tests -- replace incorrect use of array_search() by in_array() -- move method SeedDMS_Core_DMS::createDump() into SeedDMS_Core_DatabaseAccess -- lots of parameter checking when calling methods() -- make sure callbacks are callable -- SeedDMS_Core_Folder::getParent() returns null if there is no parent (used to be false) -- SeedDMS_Core_DMS::search() will not find document without an expiration date anymore, if the search is limited by an expiration end date but no start date -- add method SeedDMS_Core_Folder::getFoldersMinMax() -- init internal cache variables of SeedDMS_Core_Folder/SeedDMS_Core_Document and add method clearCache() -- SeedDMS_Core_Folder::hasDocuments() does not use the interal document cache anymore -- SeedDMS_Core_Document::addDocumentLink() returns an object of type SeedDMS_Core_DocumentLink in case of success -- trim email, comment, language, theme when setting data of user -- more checks whether an id > 0 when getting a database record - - - - 2022-04-22 - - - 5.1.25 - 5.1.25 - - - stable - stable - - GPL License - -- rename getLastWorkflowTransition() to getLastWorkflowLog() -- getLastWorkflowLog() returns a workflow entry even if the workflow has ended -- backport setFileType() from 6.0.x -- add SeedDMS_Core_File::fileExtension() -- add callbacks on onPostUpdateAttribute, onPostRemoveAttribute, onPostAddAttribute -- fix searching for document content with a custom attribute having a value set - - - - 2022-05-20 - - - 5.1.26 - 5.1.26 - - - stable - stable - - GPL License - -- fix validating multi value attributes -- SeedDMS_Core_User::removeFromProcesses() can be limited to a list of documents. In that case only the last version will be modified. -- add more types to getStatisticalData() -- add optional parameter $op to SeedDMS_Core_AttributeDefinition::getObjects() -- SeedDMS_Core_AttributeDefinition::getObjects() will not filter by value if null is passed -- SeedDMS_Core_DMS::getAllAttributeDefinitions() has second parameter to filter attributes by type - - - - 2022-08-31 - - - 5.1.27 - 5.1.27 - - - stable - stable - - GPL License - -- fix SeedDMS_Core_DMS::addAttributeDefinition() when objtype is 0 -- sort search result even if sortorder is 'i' or 'n' -- pass an array as an attribute to search() will OR each element - - - - 2022-11-07 - - - 5.1.28 - 5.1.28 - - - stable - stable - - GPL License - -- fix SeedDMS_Core_User::getDocumentContents() -- fix SeedDMS_Core_File::fileExtension() -- SeedDMS_Core_DMS::createPasswordRequest() creates a cryptographically secure hash -- fix sql error when deleting a folder attribute -- add SeedDMS_Core_Attribute::getParsedValue() and use it in SeedDMS_Core_Object::getAttributeValue() -- add SeedDMS_Core_DMS::getDuplicateSequenceNo() and SeedDMS_Core_Folder::reorderDocuments() -- add SeedDMS_Core_File::mimetype(), fix SeedDMS_Core_File::moveDir() -- all file operations use methods of SeedDMS_Core_File -- change namespace of iterators from SeedDMS to SeedDMS\Core - - - - diff --git a/SeedDMS_Core/phpunit.xml b/SeedDMS_Core/phpunit.xml deleted file mode 100644 index 103f11089..000000000 --- a/SeedDMS_Core/phpunit.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - tests - - - - - - Core - - - diff --git a/SeedDMS_Core/tests/.phpunit.result.cache b/SeedDMS_Core/tests/.phpunit.result.cache deleted file mode 100644 index 007ae03d8..000000000 --- a/SeedDMS_Core/tests/.phpunit.result.cache +++ /dev/null @@ -1 +0,0 @@ -C:37:"PHPUnit\Runner\DefaultTestResultCache":106:{a:2:{s:7:"defects";a:1:{s:17:"DmsTest::testInit";i:3;}s:5:"times";a:1:{s:17:"DmsTest::testInit";d:0.002;}}} \ No newline at end of file diff --git a/SeedDMS_Core/tests/AttributeDefinitionTest.php b/SeedDMS_Core/tests/AttributeDefinitionTest.php deleted file mode 100644 index f6276e536..000000000 --- a/SeedDMS_Core/tests/AttributeDefinitionTest.php +++ /dev/null @@ -1,574 +0,0 @@ - - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version @package_version@ - * @link https://www.seeddms.org - */ - -use PHPUnit\Framework\TestCase; - -/** - * Attribute definition test class - * - * @category SeedDMS - * @package Tests - * @author Uwe Steinmann - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version Release: @package_version@ - * @link https://www.seeddms.org - */ -class AttributeDefinitionTest extends TestCase -{ - - /** - * Create a real dms object with a mocked db - * - * This mock is only used if \SeedDMS_Core_DatabaseAccess::getResult() is - * called once. This is the case for all \SeedDMS_Core_AttributeDefinition::setXXX() - * methods like setName(). - * - * @return \SeedDMS_Core_DMS - */ - protected function getDmsWithMockedDb() : \SeedDMS_Core_DMS - { - $db = $this->createMock(\SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE ")) - ->willReturn(true); - $dms = new \SeedDMS_Core_DMS($db, ''); - return $dms; - } - - /** - * Create a mocked dms - * - * @return \SeedDMS_Core_DMS - */ - protected function getDmsMock() : \SeedDMS_Core_DMS - { - $dms = $this->createMock(\SeedDMS_Core_DMS::class); - $dms->expects($this->any()) - ->method('getDocument') - ->with(1) - ->willReturn(true); - $dms->expects($this->any()) - ->method('getFolder') - ->with(1) - ->willReturn(true); - $dms->expects($this->any()) - ->method('getUser') - ->will( - $this->returnValueMap( - array( - array(1, new \SeedDMS_Core_User(1, 'admin', 'pass', 'Joe Foo', 'baz@foo.de', 'en_GB', 'bootstrap', 'My comment', \SeedDMS_Core_User::role_admin)), - array(2, new \SeedDMS_Core_User(2, 'admin2', 'pass', 'Joe Bar', 'bar@foo.de', 'en_GB', 'bootstrap', 'My comment', \SeedDMS_Core_User::role_admin)), - array(3, null) - ) - ) - ); - $dms->expects($this->any()) - ->method('getGroup') - ->will( - $this->returnValueMap( - array( - array(1, new \SeedDMS_Core_Group(1, 'admin group 1', 'My comment')), - array(2, new \SeedDMS_Core_Group(2, 'admin group 2', 'My comment')), - array(3, null) - ) - ) - ); - return $dms; - } - - /** - * Create a mock attribute definition object - * - * @param int $type type of attribute - * @param boolean $multiple set to true for multi value attributes - * @param int $minvalues minimum number of attribute values - * @param int $maxvalues maximum number of attribute values - * @param string $valueset list of allowed values separated by the first char - * @param string $regex regular expression that must match the attribute value - * - * @return \SeedDMS_Core_AttributeDefinition - */ - protected function getAttributeDefinition($type, $multiple=false, $minvalues=0, $maxvalues=0, $valueset='', $regex='') - { - $attrdef = new \SeedDMS_Core_AttributeDefinition(1, 'foo attr', \SeedDMS_Core_AttributeDefinition::objtype_folder, $type, $multiple, $minvalues, $maxvalues, $valueset, $regex); - return $attrdef; - } - - /** - * Test getId() - * - * @return void - */ - public function testGetId() - { - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int); - $this->assertEquals(1, $attrdef->getId()); - } - - /** - * Test getName() - * - * @return void - */ - public function testGetName() - { - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int); - $this->assertEquals('foo attr', $attrdef->getName()); - } - - /** - * Test setName() - * - * @return void - */ - public function testSetName() - { - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int); - /* A mocked dms is needed for updating the database */ - $attrdef->setDMS(self::getDmsWithMockedDb()); - $attrdef->setName('bar attr'); - $this->assertEquals('bar attr', $attrdef->getName()); - } - - /** - * Test getObjType() - * - * @return void - */ - public function testGetObjType() - { - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int); - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::objtype_folder, $attrdef->getObjType()); - } - - /** - * Test setObjType() - * - * @return void - */ - public function testSetObjType() - { - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int); - /* A mocked dms is needed for updating the database */ - $attrdef->setDMS(self::getDmsWithMockedDb()); - $attrdef->setObjType(\SeedDMS_Core_AttributeDefinition::objtype_document); - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::objtype_document, $attrdef->getObjType()); - } - - /** - * Test getType() - * - * @return void - */ - public function testGetType() - { - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int); - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::type_int, $attrdef->getType()); - } - - /** - * Test setType() - * - * @return void - */ - public function testSetType() - { - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int); - /* A mocked dms is needed for updating the database */ - $attrdef->setDMS(self::getDmsWithMockedDb()); - $attrdef->setType(\SeedDMS_Core_AttributeDefinition::type_string); - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::type_string, $attrdef->getType()); - } - - /** - * Test getMultipleValues() - * - * @return void - */ - public function testGetMultipleValues() - { - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int); - $this->assertEquals(false, $attrdef->getMultipleValues()); - } - - /** - * Test setMultipleValues() - * - * @return void - */ - public function testSetMultipleValues() - { - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int); - /* A mocked dms is needed for updating the database */ - $attrdef->setDMS(self::getDmsWithMockedDb()); - /* Toogle the current value of multiple values */ - $oldvalue = $attrdef->getMultipleValues(); - $attrdef->setMultipleValues(!$oldvalue); - $this->assertEquals(!$oldvalue, $attrdef->getMultipleValues()); - } - - /** - * Test getMinValues() - * - * @return void - */ - public function testGetMinValues() - { - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int); - $this->assertEquals(0, $attrdef->getMinValues()); - } - - /** - * Test setMinValues() - * - * @return void - */ - public function testSetMinValues() - { - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int); - /* A mocked dms is needed for updating the database */ - $attrdef->setDMS(self::getDmsWithMockedDb()); - /* add 5 to value of min values */ - $oldvalue = $attrdef->getMinValues(); - $attrdef->setMinValues($oldvalue+5); - $this->assertEquals($oldvalue+5, $attrdef->getMinValues()); - } - - /** - * Test getMaxValues() - * - * @return void - */ - public function testGetMaxValues() - { - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int); - $this->assertEquals(0, $attrdef->getMaxValues()); - } - - /** - * Test setMaxValues() - * - * @return void - */ - public function testSetMaxValues() - { - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int); - /* A mocked dms is needed for updating the database */ - $attrdef->setDMS(self::getDmsWithMockedDb()); - /* add 5 to value of max values */ - $oldvalue = $attrdef->getMaxValues(); - $attrdef->setMaxValues($oldvalue+5); - $this->assertEquals($oldvalue+5, $attrdef->getMaxValues()); - } - - /** - * Test getValueSet() - * - * @return void - */ - public function testGetValueSet() - { - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string, false, 0, 0, '|foo|bar|baz'); - $this->assertEquals('|foo|bar|baz', $attrdef->getValueSet()); - } - - /** - * Test getValueSetSeparator() - * - * @return void - */ - public function testGetValueSetSeparator() - { - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string, false, 0, 0, '|foo|bar|baz'); - $this->assertEquals('|', $attrdef->getValueSetSeparator()); - /* No value set will return no separator */ - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int); - $this->assertEmpty($attrdef->getValueSetSeparator()); - /* Even a 1 char value set will return no separator */ - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string, false, 0, 0, '|'); - $this->assertEmpty($attrdef->getValueSetSeparator()); - /* Multiple users or groups always use a ',' as a separator */ - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_user, true); - $this->assertEquals(',', $attrdef->getValueSetSeparator()); - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_group, true); - $this->assertEquals(',', $attrdef->getValueSetSeparator()); - } - - /** - * Test getValueSetAsArray() - * - * @return void - */ - public function testGetValueSetAsArray() - { - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string, false, 0, 0, '|foo|bar|baz '); - $valueset = $attrdef->getValueSetAsArray(); - $this->assertIsArray($valueset); - $this->assertCount(3, $valueset); - /* value set must contain 'baz' though 'baz ' was originally set */ - $this->assertContains('baz', $valueset); - /* No value set will return an empty array */ - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string); - $valueset = $attrdef->getValueSetAsArray(); - $this->assertIsArray($valueset); - $this->assertEmpty($valueset); - } - - /** - * Test getValueSetValue() - * - * @return void - */ - public function testGetValueSetValue() - { - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string, false, 0, 0, '|foo|bar|baz '); - $this->assertEquals('foo', $attrdef->getValueSetValue(0)); - /* Check if trimming of 'baz ' worked */ - $this->assertEquals('baz', $attrdef->getValueSetValue(2)); - /* Getting the value of a none existing index returns false */ - $this->assertFalse($attrdef->getValueSetValue(3)); - - /* Getting a value from a none existing value set returns false as well */ - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string); - $this->assertFalse($attrdef->getValueSetValue(0)); - } - - /** - * Test setValueSet() - * - * @return void - */ - public function testSetValueSet() - { - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int); - /* A mocked dms is needed for updating the database */ - $attrdef->setDMS(self::getDmsWithMockedDb()); - /* add 5 to value of min values */ - $attrdef->setValueSet(' |foo|bar | baz '); - $this->assertEquals('|foo|bar|baz', $attrdef->getValueSet()); - } - - /** - * Test getRegex() - * - * @return void - */ - public function testGetRegex() - { - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string, false, 0, 0, '', '[0-9].*'); - $this->assertEquals('[0-9].*', $attrdef->getRegex()); - } - - /** - * Test setRegex() - * - * @return void - */ - public function testSetRegex() - { - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string); - /* A mocked dms is needed for updating the database */ - $attrdef->setDMS(self::getDmsWithMockedDb()); - /* set a new valid regex */ - $this->assertTrue($attrdef->setRegex(' /[0-9].*/i ')); - $this->assertEquals('/[0-9].*/i', $attrdef->getRegex()); - /* set a new invalid regex will return false and keep the old regex */ - $this->assertFalse($attrdef->setRegex(' /([0-9].*/i ')); - $this->assertEquals('/[0-9].*/i', $attrdef->getRegex()); - } - - /** - * Test setEmptyRegex() - * - * @return void - */ - public function testSetEmptyRegex() - { - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string); - /* A mocked dms is needed for updating the database */ - $attrdef->setDMS(self::getDmsWithMockedDb()); - /* set an empty regex */ - $this->assertTrue($attrdef->setRegex('')); - } - - /** - * Test parseValue() - * - * @return void - */ - public function testParseValue() - { - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string); - $value = $attrdef->parseValue('foo'); - $this->assertIsArray($value); - $this->assertCount(1, $value); - $this->assertContains('foo', $value); - /* An attribute definition with multiple values will split the value by the first char */ - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string, true, 0, 0, '|baz|bar|foo'); - $value = $attrdef->parseValue('|bar|baz'); - $this->assertIsArray($value); - $this->assertCount(2, $value); - /* An attribute definition without multiple values, will treat the value as a string */ - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string, false, 0, 0, '|baz|bar|foo'); - $value = $attrdef->parseValue('|bar|baz'); - $this->assertIsArray($value); - $this->assertCount(1, $value); - $this->assertContains('|bar|baz', $value); - } - - /** - * Test validate() - * - * @TODO Instead of having a lengthy list of assert calls, this could be - * implemented with data providers for each attribute type - * - * @return void - */ - public function testValidate() - { - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string); - $this->assertTrue($attrdef->validate('')); // even an empty string is valid - $this->assertTrue($attrdef->validate('foo')); // there is no invalid string - - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string, false, 0, 0, '', '/[0-9]*S/'); - $this->assertFalse($attrdef->validate('foo')); // doesn't match the regex - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_regex, $attrdef->getValidationError()); - $this->assertTrue($attrdef->validate('S')); // no leading numbers needed - $this->assertTrue($attrdef->validate('8980S')); // leading numbers are ok - - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string, false, 0, 0, '|foo|bar|baz', ''); - $this->assertTrue($attrdef->validate('foo')); // is part of value map - $this->assertFalse($attrdef->validate('foz')); // is not part of value map - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_valueset, $attrdef->getValidationError()); - - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string, true, 0, 0, '|foo|bar|baz', ''); - $this->assertTrue($attrdef->validate('foo')); // is part of value map - $this->assertFalse($attrdef->validate('')); // an empty value cannot be in the valueset - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_valueset, $attrdef->getValidationError()); - $this->assertTrue($attrdef->validate('|foo|baz')); // both are part of value map - $this->assertFalse($attrdef->validate('|foz|baz')); // 'foz' is not part of value map - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_valueset, $attrdef->getValidationError()); - - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string, true, 1, 1, '|foo|bar|baz', ''); - $this->assertTrue($attrdef->validate('foo')); // is part of value map - $this->assertFalse($attrdef->validate('')); // empty string is invalid because of min values = 1 - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_min_values, $attrdef->getValidationError()); - $this->assertFalse($attrdef->validate('|foo|baz')); // both are part of value map, but only value is allowed - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_max_values, $attrdef->getValidationError()); - - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_boolean); - $this->assertTrue($attrdef->validate(0)); - $this->assertTrue($attrdef->validate(1)); - $this->assertFalse($attrdef->validate(2)); - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_boolean, $attrdef->getValidationError()); - - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int); - $this->assertTrue($attrdef->validate(0)); - $this->assertTrue($attrdef->validate('0')); - $this->assertFalse($attrdef->validate('a')); - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_int, $attrdef->getValidationError()); - - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_date); - $this->assertTrue($attrdef->validate('2021-09-30')); - $this->assertTrue($attrdef->validate('1968-02-29')); // 1968 was a leap year - $this->assertTrue($attrdef->validate('2000-02-29')); // 2000 was a leap year - $this->assertFalse($attrdef->validate('1900-02-29')); // 1900 didn't was a leap year - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_date, $attrdef->getValidationError()); - $this->assertFalse($attrdef->validate('1970-02-29')); // 1970 didn't was a leap year - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_date, $attrdef->getValidationError()); - $this->assertFalse($attrdef->validate('2010/02/28')); // This has the wrong format - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_date, $attrdef->getValidationError()); - $this->assertFalse($attrdef->validate('1970-00-29')); // 0 month is not allowed - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_date, $attrdef->getValidationError()); - $this->assertFalse($attrdef->validate('1970-01-00')); // 0 day is not allowed - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_date, $attrdef->getValidationError()); - - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_float); - $this->assertTrue($attrdef->validate('0.567')); - $this->assertTrue($attrdef->validate('1000')); - $this->assertTrue($attrdef->validate('1000e3')); - $this->assertTrue($attrdef->validate('1000e-3')); - $this->assertTrue($attrdef->validate('-1000')); - $this->assertTrue($attrdef->validate('+1000')); - $this->assertFalse($attrdef->validate('0,567')); // wrong decimal point - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_float, $attrdef->getValidationError()); - $this->assertFalse($attrdef->validate('0.56.7')); // two decimal point - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_float, $attrdef->getValidationError()); - - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_email); - $this->assertTrue($attrdef->validate('info@seeddms.org')); - $this->assertTrue($attrdef->validate('info@seeddms.verylongtopleveldomain')); - $this->assertFalse($attrdef->validate('@seeddms.org')); // no user - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_email, $attrdef->getValidationError()); - $this->assertFalse($attrdef->validate('info@localhost')); // no tld - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_email, $attrdef->getValidationError()); - $this->assertFalse($attrdef->validate('info@@seeddms.org')); // double @ - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_email, $attrdef->getValidationError()); - $this->assertTrue($attrdef->validate('info@subsubdomain.subdomain.seeddms.org')); // multiple subdomains are ok - $this->assertFalse($attrdef->validate('info@seeddms..org')); // double . is not allowed - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_email, $attrdef->getValidationError()); - $this->assertFalse($attrdef->validate('info@s.org')); // 2nd level domain name is too short - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_email, $attrdef->getValidationError()); - $this->assertFalse($attrdef->validate('info@seeddms.o')); // top level domain name is too short - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_email, $attrdef->getValidationError()); - $this->assertTrue($attrdef->validate('info@0123456789-0123456789-0123456789-0123456789-0123456789-01234567.org')); // domain name is 63 chars long, which is the max length - $this->assertFalse($attrdef->validate('info@0123456789-0123456789-0123456789-0123456789-0123456789-012345678.org')); // domain name is 1 char longer than 63 chars - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_email, $attrdef->getValidationError()); - - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_url); - $this->assertTrue($attrdef->validate('http://seeddms.org')); - $this->assertTrue($attrdef->validate('https://seeddms.org')); - $this->assertFalse($attrdef->validate('ftp://seeddms.org')); // ftp is not allowed - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_url, $attrdef->getValidationError()); - $this->assertTrue($attrdef->validate('http://localhost')); // no tld is just fine - $this->assertFalse($attrdef->validate('http://localhost.o')); // tld is to short - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_url, $attrdef->getValidationError()); - - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_user); - $attrdef->setDMS(self::getDmsMock()); - $this->assertTrue($attrdef->validate(1)); - $this->assertFalse($attrdef->validate(3)); - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_user, $attrdef->getValidationError()); - - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_group); - $attrdef->setDMS(self::getDmsMock()); - $this->assertTrue($attrdef->validate('1')); - $this->assertTrue($attrdef->validate('2')); - $this->assertFalse($attrdef->validate('3')); // there is no group with id=3 - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_group, $attrdef->getValidationError()); - - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_group, true); - $attrdef->setDMS(self::getDmsMock()); - $this->assertTrue($attrdef->validate(',1,2')); - $this->assertFalse($attrdef->validate(',1,2,3')); // there is no group with id=3 - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_group, $attrdef->getValidationError()); - - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_user); - $attrdef->setDMS(self::getDmsMock()); - $this->assertTrue($attrdef->validate('1')); - $this->assertTrue($attrdef->validate('2')); - $this->assertFalse($attrdef->validate('3')); // there is no user with id=3 - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_user, $attrdef->getValidationError()); - - $attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_user, true); - $attrdef->setDMS(self::getDmsMock()); - $this->assertTrue($attrdef->validate(',1,2')); - $this->assertFalse($attrdef->validate(',1,2,3')); // there is no user with id=3 - $this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_user, $attrdef->getValidationError()); - } - -} diff --git a/SeedDMS_Core/tests/AttributeTest.php b/SeedDMS_Core/tests/AttributeTest.php deleted file mode 100644 index 66d7dba84..000000000 --- a/SeedDMS_Core/tests/AttributeTest.php +++ /dev/null @@ -1,155 +0,0 @@ - - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version @package_version@ - * @link https://www.seeddms.org - */ - -use PHPUnit\Framework\TestCase; - -/** - * Attribute and attribute definition test class - * - * @category SeedDMS - * @package Tests - * @author Uwe Steinmann - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version Release: @package_version@ - * @link https://www.seeddms.org - */ -class AttributeTest extends TestCase -{ - - /** - * Create a mock dms object - * - * @return SeedDMS_Core_DMS - */ - protected function getMockDMS() : SeedDMS_Core_DMS - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->any()) - ->method('getResult') - ->with($this->stringContains("UPDATE ")) - ->willReturn(true); - $dms = new SeedDMS_Core_DMS($db, ''); - return $dms; - } - - /** - * Create a mock attribute definition object - * - * @param int $type type of attribute - * @param boolean $multiple true if multiple values are allowed - * @param int $minvalues minimum number of required values - * @param int $maxvalues maximum number of required value - * @param string $valueset list of allowed values separated by the first char - * @param string $regex regular expression the attribute value must match - * - * @return SeedDMS_Core_AttributeDefinition - */ - protected function getAttributeDefinition($type, $multiple=false, $minvalues=0, $maxvalues=0, $valueset='', $regex='') - { - $attrdef = new SeedDMS_Core_AttributeDefinition(1, 'foo attrdef', SeedDMS_Core_AttributeDefinition::objtype_folder, $type, $multiple, $minvalues, $maxvalues, $valueset, $regex); - return $attrdef; - } - - /** - * Create a mock attribute object - * - * @param SeedDMS_Core_AttributeDefinition $attrdef attribute defintion of attribute - * @param mixed $value value of attribute - * - * @return SeedDMS_Core_Attribute - */ - static protected function getAttribute($attrdef, $value) - { - $folder = new SeedDMS_Core_Folder(1, 'Folder', null, '', '', '', 0, 0, 0); - $attribute = new SeedDMS_Core_Attribute(1, $folder, $attrdef, $value); - $attribute->setDMS($attrdef->getDMS()); - return $attribute; - } - - /** - * Test getId() - * - * @return void - */ - public function testGetId() - { - $attrdef = self::getAttributeDefinition(SeedDMS_Core_AttributeDefinition::type_int); - $attribute = self::getAttribute($attrdef, ''); - $this->assertEquals(1, $attribute->getId()); - } - - /** - * Test getValue() - * - * @return void - */ - public function testGetValue() - { - $attrdef = self::getAttributeDefinition(SeedDMS_Core_AttributeDefinition::type_int); - $attribute = self::getAttribute($attrdef, 7); - $this->assertEquals(7, $attribute->getValue()); - } - - /** - * Test getValueAsArray() - * - * @return void - */ - public function testGetValueAsArray() - { - $attrdef = self::getAttributeDefinition(SeedDMS_Core_AttributeDefinition::type_int); - $attribute = self::getAttribute($attrdef, 7); - $this->assertIsArray($attribute->getValueAsArray()); - $this->assertCount(1, $attribute->getValueAsArray()); - $this->assertContains(7, $attribute->getValueAsArray()); - - /* Test a multi value integer */ - $attrdef = self::getAttributeDefinition(SeedDMS_Core_AttributeDefinition::type_int, true); - $attribute = self::getAttribute($attrdef, ',3,4,6'); - $value = $attribute->getValueAsArray(); - $this->assertIsArray($attribute->getValueAsArray()); - $this->assertCount(3, $attribute->getValueAsArray()); - $this->assertContains('6', $attribute->getValueAsArray()); - } - - /** - * Test setValue() - * - * @return void - */ - public function testSetValue() - { - $attrdef = self::getAttributeDefinition(SeedDMS_Core_AttributeDefinition::type_int); - $attrdef->setDMS(self::getMockDMS()); - $attribute = self::getAttribute($attrdef, 0); - $this->assertTrue($attribute->setValue(9)); - $this->assertEquals(9, $attribute->getValue()); - /* Setting an array of values for a none multi value attribute will just take the - * element of the array. - */ - $this->assertTrue($attribute->setValue([8,9])); - $this->assertEquals(8, $attribute->getValue()); - - $attrdef = self::getAttributeDefinition(SeedDMS_Core_AttributeDefinition::type_int, true); - $attrdef->setDMS(self::getMockDMS()); - $attribute = self::getAttribute($attrdef, ',3,4,6'); - $attribute->setValue([8,9,10]); - $this->assertEquals(',8,9,10', $attribute->getValue()); - $this->assertIsArray($attribute->getValueAsArray()); - $this->assertCount(3, $attribute->getValueAsArray()); - $this->assertContains('9', $attribute->getValueAsArray()); - } -} diff --git a/SeedDMS_Core/tests/DatabaseTest.php b/SeedDMS_Core/tests/DatabaseTest.php deleted file mode 100644 index bfbc5ce42..000000000 --- a/SeedDMS_Core/tests/DatabaseTest.php +++ /dev/null @@ -1,324 +0,0 @@ - - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version @package_version@ - * @link https://www.seeddms.org - */ - -namespace PHPUnit\Framework; - -use PHPUnit\Framework\SeedDmsTest; - -require_once('SeedDmsBase.php'); - -/** - * Low level Database test class - * - * @category SeedDMS - * @package Tests - * @author Uwe Steinmann - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version Release: @package_version@ - * @link https://www.seeddms.org - */ -class DatabaseTest extends SeedDmsTest -{ - - /** - * Create a sqlite database in memory - * - * @return void - */ - protected function setUp(): void - { - self::$dbh = self::createInMemoryDatabase(); - } - - /** - * Clean up at tear down - * - * @return void - */ - protected function tearDown(): void - { - self::$dbh = null; - } - - /** - * Check if connection to database exists - * - * @return void - */ - public function testIsConnected() - { - $this->assertTrue(self::$dbh->ensureConnected()); - } - - /** - * Test for number of tables in database - * - * @return void - */ - public function testTableList() - { - $tablelist = self::$dbh->TableList(); - $this->assertIsArray($tablelist); - // There are just 42 tables in SeedDMS5 and 55 tables in SeedDMS6, - // but one additional - // table 'sqlite_sequence' - $dms = new \SeedDMS_Core_DMS(null, ''); - if($dms->version[0] == '5') - $this->assertCount(43, $tablelist); - else - $this->assertCount(56, $tablelist); - } - - /** - * Test createTemporaryTable() - * - * @return void - */ - public function testCreateTemporaryTable() - { - foreach (['ttreviewid', 'ttapproveid', 'ttstatid', 'ttcontentid'] as $temp) { - $ret = self::$dbh->createTemporaryTable($temp); - $rec = self::$dbh->getResultArray("SELECT * FROM `".$temp."`"); - $this->assertIsArray($rec); - } - /* Running it again will not harm */ - foreach (['ttreviewid', 'ttapproveid', 'ttstatid', 'ttcontentid'] as $temp) { - $ret = self::$dbh->createTemporaryTable($temp); - $rec = self::$dbh->getResultArray("SELECT * FROM `".$temp."`"); - $this->assertIsArray($rec); - } - /* Running it again and overwrite the old table contents */ - foreach (['ttreviewid', 'ttapproveid', 'ttstatid', 'ttcontentid'] as $temp) { - $ret = self::$dbh->createTemporaryTable($temp, true); - $rec = self::$dbh->getResultArray("SELECT * FROM `".$temp."`"); - $this->assertIsArray($rec); - } - } - - /** - * Test createTemporaryTable() based on views - * - * @return void - */ - public function testCreateTemporaryTableBasedOnViews() - { - self::$dbh->useViews(true); - foreach (['ttreviewid', 'ttapproveid', 'ttstatid', 'ttcontentid'] as $temp) { - $ret = self::$dbh->createTemporaryTable($temp); - $rec = self::$dbh->getResultArray("SELECT * FROM `".$temp."`"); - $this->assertIsArray($rec); - } - $viewlist = self::$dbh->ViewList(); - $this->assertIsArray($viewlist); - $this->assertCount(4, $viewlist); - - /* Running it again will not harm */ - foreach (['ttreviewid', 'ttapproveid', 'ttstatid', 'ttcontentid'] as $temp) { - $ret = self::$dbh->createTemporaryTable($temp); - $rec = self::$dbh->getResultArray("SELECT * FROM `".$temp."`"); - $this->assertIsArray($rec); - } - /* Running it again and replace the old view */ - foreach (['ttreviewid', 'ttapproveid', 'ttstatid', 'ttcontentid'] as $temp) { - $ret = self::$dbh->createTemporaryTable($temp, true); - $rec = self::$dbh->getResultArray("SELECT * FROM `".$temp."`"); - $this->assertIsArray($rec); - } - } - - /** - * Test for number of views in database - * - * @return void - */ - public function testViewList() - { - $viewlist = self::$dbh->ViewList(); - $this->assertIsArray($viewlist); - // There are 0 views - $this->assertCount(0, $viewlist); - } - - /** - * Test getDriver() - * - * @return void - */ - public function testGetDriver() - { - $driver = self::$dbh->getDriver(); - $this->assertEquals('sqlite', $driver); - } - - /** - * Test rbt() - * - * @return void - */ - public function testRbt() - { - $str = self::$dbh->rbt("SELECT * FROM `tblUsers`"); - $this->assertEquals('SELECT * FROM "tblUsers"', $str); - } - - /** - * Test if table tblFolders has root folder - * - * @return void - */ - public function testInitialRootFolder() - { - $this->assertTrue(self::$dbh->hasTable('tblFolders')); - $query = 'SELECT * FROM `tblFolders`'; - $recs = self::$dbh->getResultArray($query); - $this->assertIsArray($recs); - $this->assertCount(1, $recs); - } - - /** - * Test if table tblUsers has two initial users - * - * @return void - */ - public function testInitialUsers() - { - $this->assertTrue(self::$dbh->hasTable('tblUsers')); - $query = 'SELECT * FROM `tblUsers`'; - $recs = self::$dbh->getResultArray($query); - $this->assertIsArray($recs); - $this->assertCount(2, $recs); - } - - /** - * Test getCurrentDatetime() - * - * @return void - */ - public function testGetCurrentDatetime() - { - $query = 'SELECT '.self::$dbh->getCurrentDatetime().' as a'; - $recs = self::$dbh->getResultArray($query); - $now = date('Y-m-d H:i:s'); - $this->assertIsArray($recs); - $this->assertEquals($now, $recs[0]['a'], 'Make sure php.ini has the proper timezone configured'); - } - - /** - * Test getCurrentTimestamp() - * - * @return void - */ - public function testGetCurrentTimestamp() - { - $query = 'SELECT '.self::$dbh->getCurrentTimestamp().' as a'; - $recs = self::$dbh->getResultArray($query); - $now = time(); - $this->assertIsArray($recs); - $this->assertEquals($now, $recs[0]['a'], 'Make sure php.ini has the proper timezone configured'); - } - - /** - * Test concat() - * - * @return void - */ - public function testConcat() - { - $query = 'SELECT '.self::$dbh->concat(["'foo'", "'baz'", "'bar'"]).' as a'; - $recs = self::$dbh->getResultArray($query); - $this->assertIsArray($recs); - $this->assertEquals('foobazbar', $recs[0]['a']); - } - - /** - * Test qstr() - * - * @return void - */ - public function testQstr() - { - $str = self::$dbh->qstr("bar"); - $this->assertEquals("'bar'", $str); - } - - /** - * Test getResult() if the sql fails - * - * @return void - */ - public function testGetResultSqlFail() - { - $ret = self::$dbh->getResult("UPDATE FOO SET `name`='foo'"); - $this->assertFalse($ret); - $errmsg = self::$dbh->getErrorMsg(); - $this->assertStringContainsString('no such table: FOO', $errmsg); - } - - /** - * Test getResultArray() if the sql fails - * - * @return void - */ - public function testGetResultArraySqlFail() - { - $ret = self::$dbh->getResultArray("SELECT * FROM FOO"); - $this->assertFalse($ret); - $errmsg = self::$dbh->getErrorMsg(); - $this->assertStringContainsString('no such table: FOO', $errmsg); - } - - /** - * Test logging into file - * - * @return void - */ - public function testLogging() - { - $fp = fopen('php://memory', 'r+'); - self::$dbh->setLogFp($fp); - $sql = "SELECT * FROM `tblUsers`"; - $ret = self::$dbh->getResultArray($sql); - $this->assertIsArray($ret); - fseek($fp, 0); - $contents = fread($fp, 200); - /* Check if sql statement was logged into file */ - $this->assertStringContainsString($sql, $contents); - fclose($fp); - } - - /** - * Test createDump() - * - * @return void - */ - public function testCreateDump() - { - $fp = fopen('php://memory', 'r+'); - $ret = self::$dbh->createDump($fp); - $this->assertTrue($ret); - $stat = fstat($fp); - $this->assertIsArray($stat); - $dms = new \SeedDMS_Core_DMS(null, ''); - if($dms->version[0] == '5') - $this->assertEquals(1724, $stat['size']); - else - $this->assertEquals(2272, $stat['size']); -// fseek($fp, 0); -// echo fread($fp, 200); - fclose($fp); - } -} - diff --git a/SeedDMS_Core/tests/DmsTest.php b/SeedDMS_Core/tests/DmsTest.php deleted file mode 100644 index a6811c5d6..000000000 --- a/SeedDMS_Core/tests/DmsTest.php +++ /dev/null @@ -1,2956 +0,0 @@ - - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version @package_version@ - * @link https://www.seeddms.org - */ - -use PHPUnit\Framework\SeedDmsTest; - -/** - * DMS test class - * - * @category SeedDMS - * @package Tests - * @author Uwe Steinmann - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version Release: @package_version@ - * @link https://www.seeddms.org - */ -class DmsTest extends SeedDmsTest -{ - - /** - * Create a real sqlite database in memory - * - * @return void - */ - protected function setUp(): void - { - self::$dbh = self::createInMemoryDatabase(); - self::$contentdir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'phpunit-'.time(); - mkdir(self::$contentdir); - // echo "Creating temp content dir: ".self::$contentdir."\n"; - self::$dms = new SeedDMS_Core_DMS(self::$dbh, self::$contentdir); - self::$dbversion = self::$dms->getDBVersion(); - } - - /** - * Clean up at tear down - * - * @return void - */ - protected function tearDown(): void - { - self::$dbh = null; - // echo "\nRemoving temp. content dir: ".self::$contentdir."\n"; - exec('rm -rf '.self::$contentdir); - } - - /** - * Create a mock admin role object (only used for SeedDMS 6) - * - * @return SeedDMS_Core_User - */ - protected function getAdminRole() - { - $role = new SeedDMS_Core_Role(1, 'admin', SeedDMS_Core_Role::role_admin); - return $role; - } - - /** - * Test checkIfEqual() - * - * @return void - */ - public function testCheckIfEqual() - { - $user1 = new SeedDMS_Core_User(1, 'user 1', '', '', '', '', '', '', 1); - $group1 = new SeedDMS_Core_Group(1, 'group 1', ''); - $group1n = new SeedDMS_Core_Group(1, 'group 1n', ''); - $group1c = clone $group1; - $group2 = new SeedDMS_Core_Group(2, 'group 1', ''); - $dms = new SeedDMS_Core_DMS(null, ''); - $this->assertFalse($dms->checkIfEqual($group1, $user1)); // different classes - $this->assertFalse($dms->checkIfEqual($group1, $group2)); // different id - $this->assertTrue($dms->checkIfEqual($group1, $group1c)); // a clone is always equal - $this->assertTrue($dms->checkIfEqual($group1, $group1n)); // different instances but same id is sufficient to be equal - } /* }}} */ - - /** - * Test checkDate() - * - * @return void - */ - public function testCheckDate() - { - $dms = new SeedDMS_Core_DMS(null, ''); - $this->assertTrue($dms->checkDate('2020-02-28 10:12:34')); - $this->assertTrue($dms->checkDate('2020-02-29 10:12:34')); // a leap year - $this->assertFalse($dms->checkDate('2020-02-30 10:12:34')); // feb has never 30 days - $this->assertFalse($dms->checkDate('2021-02-29 10:12:34')); // not a leap year - $this->assertFalse($dms->checkDate('2020-02-28 24:12:34')); // hour is out of range - $this->assertFalse($dms->checkDate('2020-02-28 23:60:34')); // minute is out of range - $this->assertFalse($dms->checkDate('2020-02-28 23:59:60')); // second is out of range - $this->assertFalse($dms->checkDate('2020-02-28 23:59:')); // second is missing - $this->assertTrue($dms->checkDate('2020-02-28', 'Y-m-d')); // just checking the date - $this->assertFalse($dms->checkDate('28.2.2020', 'd.m.Y')); // month must be 01-12 - $this->assertTrue($dms->checkDate('28.2.2020', 'd.n.Y')); // month must be 1-12 - $this->assertFalse($dms->checkDate('28.02.2020', 'd.n.Y')); // month must be 1-12 - } /* }}} */ - - /** - * Test getClassname() - * - * @return void - */ - public function testGetClassName() - { - /* Do not mess up the global instance self::$dms, but create my own */ - $dms = new SeedDMS_Core_DMS(null, ''); - $this->assertEquals('SeedDMS_Core_Folder', $dms->getClassname('folder')); - $this->assertEquals('SeedDMS_Core_Document', $dms->getClassname('document')); - $this->assertEquals('SeedDMS_Core_DocumentContent', $dms->getClassname('documentcontent')); - $this->assertEquals('SeedDMS_Core_User', $dms->getClassname('user')); - $this->assertEquals('SeedDMS_Core_Group', $dms->getClassname('group')); - $this->assertFalse($dms->getClassname('foo')); - } - - /** - * Test setClassname() - * - * @return void - */ - public function testSetClassName() - { - /* Do not mess up the global instance self::$dms, but create my own */ - $dms = new SeedDMS_Core_DMS(null, ''); - $this->assertEquals('SeedDMS_Core_Folder', $dms->setClassname('folder', 'MyNewFolderClass')); - $this->assertEquals('MyNewFolderClass', $dms->getClassname('folder')); - $this->assertEquals('MyNewFolderClass', $dms->setClassname('folder', 'MySuperNewFolderClass')); - $this->assertFalse($dms->setClassname('foo', 'MyNewFolderClass')); - } - - /** - * Test addCallback() - * - * @return void - */ - public function testAddCallback() - { - /* Do not mess up the global instance self::$dms, but create my own */ - $dms = new SeedDMS_Core_DMS(null, ''); - /* Add a closure as a callback is just fine */ - $this->assertTrue( - $dms->addCallback( - 'onPostSomething', function () { - } - ) - ); - /* An empty callback will make addCallback() fail */ - $this->assertFalse( - $dms->addCallback( - '', function () { - } - ) - ); - /* Passing a class method is ok */ - $this->assertTrue($dms->addCallback('onPostSomething', 'DmsTest::testAddCallback')); - /* Passing a none existing class mehtod makes addCallback() fail */ - $this->assertFalse($dms->addCallback('onPostSomething', 'DmsTest::thisMethodDoesNotExist')); - } - - /** - * Test for hasCallback - * - * @return void - */ - public function testHasCallback() - { - /* Do not mess up the global instance self::$dms, but create my own */ - $dms = new SeedDMS_Core_DMS(null, ''); - /* Add a closure as a callback is just fine */ - $this->assertTrue( - $dms->addCallback( - 'onPostSomething', function () { - } - ) - ); - $this->assertTrue($dms->hasCallback('onPostSomething')); - $this->assertFalse($dms->hasCallback('thisOneDoesNotExist')); - } - - /** - * Test for getDecorators - * - * @return void - */ - public function testGetDecorators() - { - /* Do not mess up the global instance self::$dms, but create my own */ - $dms = new SeedDMS_Core_DMS(null, ''); - $this->assertFalse($dms->getDecorators('folder')); - } - - /** - * Test for addDecorator - * - * @return void - */ - public function testaddDecorator() - { - /* Do not mess up the global instance self::$dms, but create my own */ - $dms = new SeedDMS_Core_DMS(null, ''); - $this->assertTrue($dms->addDecorator('folder', 'MyNewDecorator')); - $decorators = $dms->getDecorators('folder'); - $this->assertIsArray($decorators); - $this->assertCount(1, $decorators); - } - - /** - * Test getDb() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetDb() - { - $this->assertEquals(self::$dbh, self::$dms->getDb()); - } - - /** - * Test getDBVersion() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetDbVersion() - { - $version = self::$dms->getDBVersion(); - $this->assertCount(4, $version); - $this->assertGreaterThanOrEqual(5, $version['major']); - $this->assertGreaterThanOrEqual(0, $version['minor']); - } - - /** - * Test getDBVersionFailMissingTable() - * - * This method checks if getDBVersion() returns false if the table - * list of the database does not contain the table 'tblVersion' - * - * @return void - */ - public function testGetDbVersionFailMissingTable() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('TableList') - ->willReturn(['tblFolders', 'tblDocuments']); - $dms = new SeedDMS_Core_DMS($db, ''); - $version = $dms->getDBVersion(); - $this->assertFalse($version); - } - - /** - * Test getDBVersionSqlFail() - * - * This method checks if getDBVersion() returns false if the sql - * for selecting the records in table 'tblVersion' fail - * - * @return void - */ - public function testGetDbVersionSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with("SELECT * FROM `tblVersion` ORDER BY `major`,`minor`,`subminor` LIMIT 1") - ->willReturn(false); - $db->expects($this->once()) - ->method('TableList') - ->willReturn(['tblVersion', 'tblFolders', 'tblDocuments']); - $dms = new SeedDMS_Core_DMS($db, ''); - $version = $dms->getDBVersion(); - $this->assertFalse($version); - } - - /** - * Test getDBVersionNoRecord() - * - * This method checks if getDBVersion() returns false a table 'tblVersion' - * exists but has no record - * - * @return void - */ - public function testGetDbVersionNoRecord() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with("SELECT * FROM `tblVersion` ORDER BY `major`,`minor`,`subminor` LIMIT 1") - ->willReturn(array()); - $db->expects($this->once()) - ->method('TableList') - ->willReturn(['tblVersion', 'tblFolders', 'tblDocuments']); - $dms = new SeedDMS_Core_DMS($db, ''); - $version = $dms->getDBVersion(); - $this->assertFalse($version); - } - - /** - * Test checkVersion() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testCheckVersion() - { - $this->assertTrue(self::$dms->checkVersion()); - } - - /** - * Test checkVersionFail() - * - * This method checks if checkVersion() returns false if the version - * in table 'tblVersion' does not match the version in the class variable - * $version. To make this method independant of version changes, the - * current version is taken from SeedDMS_Core_DMS::version and modified - * in order to differ from the version stored in the database. - * - * @return void - */ - public function testcheckVersionFail() - { - $verstr = (new SeedDMS_Core_DMS(null, ''))->version; - $verarr = explode('.', $verstr); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with("SELECT * FROM `tblVersion` ORDER BY `major`,`minor`,`subminor` LIMIT 1") - ->willReturn([['major'=>$verarr[0], 'minor'=>$verarr[1]+1]]); - $db->expects($this->once()) - ->method('TableList') - ->willReturn(['tblVersion', 'tblFolders', 'tblDocuments']); - $dms = new SeedDMS_Core_DMS($db, ''); - $version = $dms->checkVersion(); - $this->assertFalse($version); - } - - /** - * Test checkVersionSqlFail() - * - * This method checks if checkVersion() returns false if the sql - * for selecting the records in table 'tblVersion' fail - * - * @return void - */ - public function testcheckVersionSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with("SELECT * FROM `tblVersion` ORDER BY `major`,`minor`,`subminor` LIMIT 1") - ->willReturn(false); - $db->expects($this->once()) - ->method('TableList') - ->willReturn(['tblVersion', 'tblFolders', 'tblDocuments']); - $dms = new SeedDMS_Core_DMS($db, ''); - $version = $dms->checkVersion(); - $this->assertFalse($version); - } - - /** - * Test checkVersionFailMissingTable() - * - * This method checks if checkVersion() returns false if the table - * list of the database does not contain the table 'tblVersion' - * - * @return void - */ - public function testCheckVersionFailMissingTable() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('TableList') - ->willReturn(['tblFolders', 'tblDocuments']); - $dms = new SeedDMS_Core_DMS($db, ''); - $version = $dms->checkVersion(); - $this->assertTrue($version); // A missing table tblVersion returns true! - } - - /** - * Test checkVersionNoRecord() - * - * This method checks if checkVersion() returns false a table 'tblVersion' - * exists but has no record - * - * @return void - */ - public function testCheckVersionNoRecord() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with("SELECT * FROM `tblVersion` ORDER BY `major`,`minor`,`subminor` LIMIT 1") - ->willReturn(array()); - $db->expects($this->once()) - ->method('TableList') - ->willReturn(['tblVersion', 'tblFolders', 'tblDocuments']); - $dms = new SeedDMS_Core_DMS($db, ''); - $version = $dms->checkVersion(); - $this->assertFalse($version); - } - - /** - * Test setRootFolderID() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testSetRootFolderID() - { - /* Setting the same root folder is ok */ - $oldid = self::$dms->setRootFolderID(1); - $this->assertEquals(1, $oldid); - /* Setting a none existing root folder id will not change the root folder */ - $oldid = self::$dms->setRootFolderID(2); - $this->assertFalse($oldid); - /* Make sure the old root folder is still set */ - $rootfolder = self::$dms->getRootFolder(); - $this->assertInstanceOf(SeedDMS_Core_Folder::class, $rootfolder); - $this->assertEquals(1, $rootfolder->getId()); - } - - /** - * Test getRootFolder() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetRootFolder() - { - $rootfolder = self::$dms->getRootFolder(); - $this->assertInstanceOf(SeedDMS_Core_Folder::class, $rootfolder); - $this->assertEquals(1, $rootfolder->getId()); - } - - /** - * Test setUser() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testSetUser() - { - $user = self::$dms->getUser(1); - $olduser = self::$dms->setUser($user); // returns null because there is no old user - $this->assertNull($olduser); - $olduser = self::$dms->setUser($user); // second call will return the user set before - $this->assertIsObject($olduser); - $olduser = self::$dms->setUser(null); // old user is still an object - $this->assertIsObject($olduser); - $olduser = self::$dms->setUser(8); // invalid user - $this->assertFalse($olduser); - } - - /** - * Test getLoggedInUser() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetLoggedInUser() - { - $olduser = self::$dms->getLoggedInUser(); // initially this is set to null - $this->assertNull($olduser); - $user = self::$dms->getUser(1); - self::$dms->setUser($user); - $olduser = self::$dms->getLoggedInUser(); - $this->assertEquals($olduser->getId(), $user->getId()); - } - - /** - * Test getDocument() - * - * As there is currently no document, getDocument() must return null. - * If false was returned it would indicated an sql error. - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetDocument() - { - $document = self::$dms->getDocument(1); - $this->assertNull($document); - } - - /** - * Test getDocumentsByUser() - * - * As there is currently no document, getDocumentsByUser() must return - * an empty array. - * If false was returned it would indicated an sql error. - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetDocumentsByUser() - { - $documents = self::$dms->getDocumentsByUser(self::$dms->getUser(1)); - $this->assertIsArray($documents); - $this->assertCount(0, $documents); - } - - /** - * Test getDocumentsLockedByUser() - * - * As there is currently no document, getDocumentsLockedByUser() must return - * an empty array. - * If false was returned it would indicated an sql error. - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetDocumentsLockedByUser() - { - $documents = self::$dms->getDocumentsLockedByUser(self::$dms->getUser(1)); - $this->assertIsArray($documents); - $this->assertCount(0, $documents); - } - - /** - * Test makeTimeStamp() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testMakeTimeStamp() - { - /* Assert correct date */ - $this->assertEquals(0, self::$dms->makeTimeStamp(1, 0, 0, 1970, 1, 1)); - $this->assertEquals(68166000, self::$dms->makeTimeStamp(0, 0, 0, 1972, 2, 29)); - /* Assert incorrect dates */ - $this->assertFalse(self::$dms->makeTimeStamp(0, 0, 0, 1970, 13, 1), 'Incorrect month not recognized'); - $this->assertFalse(self::$dms->makeTimeStamp(0, 0, 0, 1970, 1, 32), 'Incorrect day in january not recognized'); - $this->assertFalse(self::$dms->makeTimeStamp(0, 0, 0, 1970, 4, 31), 'Incorrect day in april not recognized'); - $this->assertFalse(self::$dms->makeTimeStamp(0, 0, 0, 1970, 2, 29), 'Incorrect day in february not recognized'); - $this->assertFalse(self::$dms->makeTimeStamp(24, 0, 0, 1970, 1, 1), 'Incorrect hour not recognized'); - $this->assertFalse(self::$dms->makeTimeStamp(0, 60, 0, 1970, 1, 1), 'Incorrect minute not recognized'); - $this->assertFalse(self::$dms->makeTimeStamp(0, 0, 60, 1970, 1, 1), 'Incorrect second not recognized'); - } - - /** - * Test search() - * - * Just search the root folder in different ways. Because the initial database - * does not have any documents, this method will test various ways to - * find the root folder 'DMS' with id=1 - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testSearchRootFolder() - { - /* searching for folders/documents in any field */ - $result = self::$dms->search( - array( - 'query'=>'DMS' - ) - ); - $this->assertEquals(1, $result['totalFolders']); - $this->assertCount(1, $result['folders']); - $this->assertEquals(0, $result['totalDocs']); - $this->assertCount(0, $result['docs']); - - /* searching for folders in any field */ - $result = self::$dms->search( - array( - 'query'=>'DMS', - 'mode'=>0x2 - ) - ); - $this->assertEquals(1, $result['totalFolders']); - $this->assertCount(1, $result['folders']); - $this->assertEquals(0, $result['totalDocs']); - $this->assertCount(0, $result['docs']); - - /* searching for documents in any field will not return any folders*/ - $result = self::$dms->search( - array( - 'query'=>'DMS', - 'mode'=>0x1 - ) - ); - $this->assertEquals(0, $result['totalFolders']); - $this->assertCount(0, $result['folders']); - $this->assertEquals(0, $result['totalDocs']); - $this->assertCount(0, $result['docs']); - - /* searching for folders with a bogus name may not return any folders */ - $result = self::$dms->search( - array( - 'query'=>'foo', - 'mode'=>0x2 - ) - ); - $this->assertEquals(0, $result['totalFolders']); - $this->assertCount(0, $result['folders']); - - /* searching for folders by its id */ - $result = self::$dms->search( - array( - 'query'=>'1', - 'mode'=>0x2 - ) - ); - $this->assertEquals(1, $result['totalFolders']); - $this->assertCount(1, $result['folders']); - - /* searching for folders by an unknown id */ - $result = self::$dms->search( - array( - 'query'=>'2', - 'mode'=>0x2 - ) - ); - $this->assertEquals(0, $result['totalFolders']); - $this->assertCount(0, $result['folders']); - - /* searching for folders with two terms ANDed, but only one matches */ - $result = self::$dms->search( - array( - 'query'=>'DMS foo', - 'mode'=>0x2, - 'logicalmode'=>'AND', - ) - ); - $this->assertEquals(0, $result['totalFolders']); - $this->assertCount(0, $result['folders']); - - /* searching for folders with two terms ORed, but only one matches */ - $result = self::$dms->search( - array( - 'query'=>'DMS foo', - 'mode'=>0x2, - 'logicalmode'=>'OR', - ) - ); - $this->assertEquals(1, $result['totalFolders']); - $this->assertCount(1, $result['folders']); - - /* searching for folders with two terms ANDed, both match, but in different fields (name and id) */ - $result = self::$dms->search( - array( - 'query'=>'DMS 1', - 'mode'=>0x2, - 'logicalmode'=>'AND', - ) - ); - $this->assertEquals(1, $result['totalFolders']); - $this->assertCount(1, $result['folders']); - - /* searching for folders with two terms ANDed, both match, but in different fields (name and id). But only one field is searched. */ - $result = self::$dms->search( - array( - 'query'=>'DMS 1', - 'mode'=>0x2, - 'logicalmode'=>'AND', - 'searchin'=>array(2,3), // name, comment - ) - ); - $this->assertEquals(0, $result['totalFolders']); - $this->assertCount(0, $result['folders']); - - /* searching for folders below a start folder will not find the folder 'DMS' - * anymore, because the start folder itself will not be found. - */ - $result = self::$dms->search( - array( - 'query'=>'DMS', - 'mode'=>0x2, - 'startFolder'=>self::$dms->getRootFolder() - ) - ); - $this->assertEquals(0, $result['totalFolders']); - $this->assertCount(0, $result['folders']); - - /* Restrict search to the owner of the folder 'DMS' - */ - $result = self::$dms->search( - array( - 'query'=>'DMS', - 'mode'=>0x2, - 'owner'=>self::$dms->getUser(1) - ) - ); - $this->assertEquals(1, $result['totalFolders']); - $this->assertCount(1, $result['folders']); - - /* Restrict search to user who does not own a document - */ - $result = self::$dms->search( - array( - 'query'=>'DMS', - 'mode'=>0x2, - 'owner'=>self::$dms->getUser(2) - ) - ); - $this->assertEquals(0, $result['totalFolders']); - $this->assertCount(0, $result['folders']); - - /* Restrict search to a list of owners (in this case all users) - */ - $result = self::$dms->search( - array( - 'query'=>'DMS', - 'mode'=>0x2, - 'owner'=>self::$dms->getAllUsers() - ) - ); - $this->assertEquals(1, $result['totalFolders']); - $this->assertCount(1, $result['folders']); - - } - - /** - * Test getFolder() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetFolder() - { - $folder = self::$dms->getFolder(1); - $this->assertInstanceOf(SeedDMS_Core_Folder::class, $folder); - $this->assertEquals(1, $folder->getId()); - } - - /** - * Test getFolderByName() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetFolderByName() - { - $folder = self::$dms->getFolderByName('DMS'); - $this->assertInstanceOf(SeedDMS_Core_Folder::class, $folder); - $this->assertEquals(1, $folder->getId()); - $folder = self::$dms->getFolderByName('FOO'); - $this->assertNull($folder); - } - - /** - * Test checkFolders() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testCheckFolders() - { - $errors = self::$dms->checkFolders(); - $this->assertIsArray($errors); - $this->assertCount(0, $errors); - } - - /** - * Test checkFoldersSqlFail() - * - * This test catches the case when the sql statement for getting all - * folders fails. - * - * @return void - */ - public function testCheckFoldersSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with("SELECT * FROM `tblFolders`") - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $this->assertFalse($dms->checkFolders()); - } - - /** - * Test checkFoldersFailNoParent() - * - * This test catches the case when a folder's parent is not present - * - * @return void - */ - public function testCheckFoldersFailNoParent() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with("SELECT * FROM `tblFolders`") - ->willReturn( - array( - array('id'=>1, 'name'=>'DMS', 'parent'=>0, 'folderList'=>''), - array('id'=>5, 'name'=>'Subfolder', 'parent'=>3, 'folderList'=>':1:'), - ) - ); - $dms = new SeedDMS_Core_DMS($db, ''); - $errors = $dms->checkFolders(); - $this->assertIsArray($errors); - $this->assertCount(1, $errors); // there should be 1 error - $this->assertArrayHasKey(5, $errors); // folder with id=5 has the wrong parent - $this->assertEquals('Missing parent', $errors[5]['msg']); - } - - /** - * Test checkFoldersFailWrongFolderList() - * - * This test catches the case when a folder's parent is not present - * - * @return void - */ - public function testCheckFoldersFailWrongFolderList() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with("SELECT * FROM `tblFolders`") - ->willReturn( - array( - array('id'=>1, 'name'=>'DMS', 'parent'=>0, 'folderList'=>''), - array('id'=>5, 'name'=>'Subfolder', 'parent'=>1, 'folderList'=>':1:2:'), - ) - ); - $dms = new SeedDMS_Core_DMS($db, ''); - $errors = $dms->checkFolders(); - $this->assertIsArray($errors); - $this->assertCount(1, $errors); // there should be 1 error - $this->assertArrayHasKey(5, $errors); // folder with id=5 has the wrong parent - $this->assertStringContainsString('Wrong folder list', $errors[5]['msg']); - } - - /** - /** - * Test checkDocuments() - * - * The intitial database does not have any documents which makes this - * test less usefull. - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testCheckDocuments() - { - $errors = self::$dms->checkDocuments(); - $this->assertIsArray($errors); - $this->assertCount(0, $errors); - } - - /** - * Test checkDocumentsSqlFoldersFail() - * - * This test catches the case when the sql statement for getting all - * folders fails. - * - * @return void - */ - public function testCheckDocumentsSqlFoldersFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with("SELECT * FROM `tblFolders`") - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $this->assertFalse($dms->checkDocuments()); - } - - /** - * Test checkDocumentsSqlDocumentsFail() - * - * This test catches the case when the sql statement for getting all - * documents fails, after getting all folders succeeded. - * - * @return void - */ - public function testCheckDocumentsSqlDocumentsFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->exactly(2)) - ->method('getResultArray') - ->will( - $this->returnValueMap( - array( - array("SELECT * FROM `tblFolders`", true, array( - array('id'=>1, 'name'=>'DMS', 'parent'=>0, 'folderList'=>'') - )), - array("SELECT * FROM `tblDocuments`", true, false) - ) - ) - ); - $dms = new SeedDMS_Core_DMS($db, ''); - $this->assertFalse($dms->checkDocuments()); - } - - /** - * Test checkDocumentsFailNoParent() - * - * This test catches the case when a documents's parent is not present - * - * @return void - */ - public function testCheckDocumentsFailNoParent() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->exactly(2)) - ->method('getResultArray') - ->will( - $this->returnValueMap( - array( - array("SELECT * FROM `tblFolders`", true, array( - array('id'=>1, 'name'=>'DMS', 'parent'=>0, 'folderList'=>''), - array('id'=>5, 'name'=>'Subfolder', 'parent'=>1, 'folderList'=>':1:'), - )), - array("SELECT * FROM `tblDocuments`", true, array( - array('id'=>1, 'name'=>'Document 1', 'folder'=>1, 'folderList'=>':1:'), - array('id'=>2, 'name'=>'Document 2', 'folder'=>2, 'folderList'=>':1:5:'), - )) - ) - ) - ); - $dms = new SeedDMS_Core_DMS($db, ''); - $errors = $dms->checkDocuments(); - $this->assertIsArray($errors); - $this->assertCount(1, $errors); // there should be 1 error - $this->assertArrayHasKey(2, $errors); // document with id=2 has the wrong parent - $this->assertEquals('Missing parent', $errors[2]['msg']); - } - - /** - * Test checkDocumentsFailWrongFolderList() - * - * This test catches the case when a documents's parent is not present - * - * @return void - */ - public function testCheckDocumentsFailWrongFolderList() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->exactly(2)) - ->method('getResultArray') - ->will( - $this->returnValueMap( - array( - array("SELECT * FROM `tblFolders`", true, array( - array('id'=>1, 'name'=>'DMS', 'parent'=>0, 'folderList'=>''), - array('id'=>5, 'name'=>'Subfolder', 'parent'=>1, 'folderList'=>':1:'), - )), - array("SELECT * FROM `tblDocuments`", true, array( - array('id'=>1, 'name'=>'Document 1', 'folder'=>1, 'folderList'=>':1:'), - array('id'=>2, 'name'=>'Document 2', 'folder'=>5, 'folderList'=>':1:2:'), - )) - ) - ) - ); - $dms = new SeedDMS_Core_DMS($db, ''); - $errors = $dms->checkDocuments(); - $this->assertIsArray($errors); - $this->assertCount(1, $errors); // there should be 1 error - $this->assertArrayHasKey(2, $errors); // document with id=2 has the wrong parent - $this->assertStringContainsString('Wrong folder list', $errors[2]['msg']); - } - - /** - * Test getUser() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetUser() - { - $user = self::$dms->getUser(1); - $this->assertInstanceOf(SeedDMS_Core_User::class, $user); - $this->assertEquals(1, $user->getId()); - } - - /** - * Test getUserByLogin() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetUserByLogin() - { - $user = self::$dms->getUserByLogin('admin'); - $this->assertInstanceOf(SeedDMS_Core_User::class, $user); - $this->assertEquals('admin', $user->getLogin()); - } - - /** - * Test getUserByEmail() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetUserByEmail() - { - $user = self::$dms->getUserByEmail('info@seeddms.org'); - $this->assertInstanceOf(SeedDMS_Core_User::class, $user); - $this->assertEquals('admin', $user->getLogin()); - } - - /** - * Test getAllUsers() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAllUsers() - { - $users = self::$dms->getAllUsers(); - $this->assertIsArray($users); - $this->assertCount(2, $users); - } - - /** - * Test addUser() - * - * Add a new user and retrieve it afterwards. Also check if the number - * of users has increased by one. Add a user with the same name a - * second time and check if it returns false. - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testAddUser() - { - /* Adding a new user */ - $user = self::$dms->addUser('new user', 'pwd', 'Full Name', 'newuser@seeddms.org', 'en_GB', 'bootstrap', 'with comment'); - $this->assertIsObject($user); - $this->assertEquals('new user', $user->getLogin()); - $this->assertEquals('with comment', $user->getComment()); - - /* Adding a user with the same login must fail */ - $user = self::$dms->addUser('new user', 'pwd', 'Full Name', 'newuser@seeddms.org', 'en_GB', 'bootstrap', 'with comment'); - $this->assertFalse($user); - - /* There should be 3 users now */ - $users = self::$dms->getAllUsers(); - $this->assertIsArray($users); - $this->assertCount(3, $users); - - /* Check if setting the password expiration to 'now' works */ - $now = date('Y-m-d H:i:s'); - $user = self::$dms->addUser('new user pwdexpiration 1', 'pwd', 'Full Name', 'newuser@seeddms.org', 'en_GB', 'bootstrap', 'with comment', '', false, false, 'now'); - $this->assertEquals($now, $user->getPwdExpiration()); - $now = date('Y-m-d H:i:s'); - $user = self::$dms->addUser('new user pwdexpiration 2', 'pwd', 'Full Name', 'newuser@seeddms.org', 'en_GB', 'bootstrap', 'with comment', '', false, false, $now); - $this->assertEquals($now, $user->getPwdExpiration()); - } - - /** - * Test addUserWithPostAddHook() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testAddUserWithPostAddHook() - { - /* Add the 'onPostAddUser' callback */ - $ret = 0; - $callback = function ($param, $user) use (&$ret) { - $ret = 1; - }; - self::$dms->addCallback('onPostAddUser', $callback, 1); - /* Adding a new user */ - $user = self::$dms->addUser('new user', 'pwd', 'Full Name', 'newuser@seeddms.org', 'en_GB', 'bootstrap', 'with comment'); - $this->assertIsObject($user); - $this->assertEquals('new user', $user->getLogin()); - $this->assertEquals(1, $ret); - } - - /** - * Test addUser() with sql failure - * - * @return void - */ - public function testAddUserSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("INSERT INTO `tblUsers`")) - ->willReturn(false); - $db->expects($this->once()) - ->method('getResultArray') - ->with("SELECT * FROM `tblUsers` WHERE `login` = ") - ->willReturn([]); - $dms = new SeedDMS_Core_DMS($db, ''); - if(self::$dbversion['major'] < 6) - $role = 1; - else - $role = $this->getAdminRole(); - $user = $dms->addUser('new user', 'pwd', 'Full Name', 'newuser@seeddms.org', 'en_GB', 'bootstrap', 'with comment', $role); - $this->assertFalse($user); - } - - /** - * Test getGroup() - * - * Get a group by its id - * - * @return void - */ - public function testGetGroup() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with("SELECT * FROM `tblGroups` WHERE `id` = 1") - ->willReturn([['id'=>1, 'name'=>'foo', 'comment'=>'']]); - $dms = new SeedDMS_Core_DMS($db, ''); - $group = $dms->getGroup(1); - $this->assertIsObject($group); - $this->assertEquals(1, $group->getId()); - } - - /** - * Test getGroupByName() - * - * Get a group by its name - * - * qstr must be mocked because it is used in the sql statement to quote - * the name. - * - * @return void - */ - public function testGetGroupByName() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with("SELECT * FROM `tblGroups` WHERE `name` = 'foo'") - ->willReturn([['id'=>1, 'name'=>'foo', 'comment'=>'']]); - $db->expects($this->once()) - ->method('qstr') - ->will( - $this->returnCallback( - function ($a) { - return "'".$a."'"; - } - ) - ); - $dms = new SeedDMS_Core_DMS($db, ''); - $group = $dms->getGroupByName('foo'); - $this->assertIsObject($group); - $this->assertEquals('foo', $group->getName()); - } - - /** - * Test getAllGroups() - * - * The intitial database does not have any groups - * - * @return void - */ - public function testGetAllGroups() - { - $groups = self::$dms->getAllGroups(); - $this->assertIsArray($groups); - $this->assertCount(0, $groups); - } - - /** - * Test addGroup() - * - * Add a new group and retrieve it afterwards. Also check if the number - * of groups has increased by one. Add a group with the same name a - * second time and check if it returns false. - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testAddGroup() - { - /* Adding a new group */ - $group = self::$dms->addGroup('new group', 'with comment'); - $this->assertIsObject($group); - $this->assertEquals('new group', $group->getName()); - /* Adding a group with the same name must fail */ - $group = self::$dms->addGroup('new group', 'with comment'); - $this->assertFalse($group); - /* There should be one group now */ - $groups = self::$dms->getAllGroups(); - $this->assertIsArray($groups); - $this->assertCount(1, $groups); - } - - /** - * Test addGroupWithPostAddHook() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testAddGroupWithPostAddHook() - { - /* Add the 'onPostAddGroup' callback */ - $ret = 0; - $callback = function ($param, $group) use (&$ret) { - $ret = 1; - }; - self::$dms->addCallback('onPostAddGroup', $callback, 1); - /* Adding a new group */ - $group = self::$dms->addGroup('new group', 'with comment'); - $this->assertIsObject($group); - $this->assertEquals('new group', $group->getName()); - $this->assertEquals(1, $ret); - } - - /** - * Test addGroup() with sql failure - * - * @return void - */ - public function testAddGroupSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("INSERT INTO `tblGroups`")) - ->willReturn(false); - $db->expects($this->once()) - ->method('getResultArray') - ->with("SELECT * FROM `tblGroups` WHERE `name` = ") - ->willReturn([]); - $dms = new SeedDMS_Core_DMS($db, ''); - $group = $dms->addGroup('new group', 'with comment'); - $this->assertFalse($group); - } - - /** - * Test getAllKeywordCategories() - * - * The intitial database does not have any keyword categories - * - * @return void - */ - public function testGetAllKeywordCategories() - { - $cats = self::$dms->getAllKeywordCategories(); - $this->assertIsArray($cats); - $this->assertCount(0, $cats); - /* Even passing bogus ids is handled propperly */ - $cats = self::$dms->getAllKeywordCategories(['kk', '0', 3, true]); - $this->assertIsArray($cats); - $this->assertCount(0, $cats); - } - - /** - * Test getAllUserKeywordCategories() - * - * Method getAllUserKeywordCategories() actually uses - * getAllKeywordCategories() - * - * The intitial database does not have any keyword categories - * - * @return void - */ - public function testGetAllUserKeywordCategories() - { - $cats = self::$dms->getAllUserKeywordCategories(1); - $this->assertIsArray($cats); - $this->assertCount(0, $cats); - /* Passing a none existing user id will return an empty array */ - $cats = self::$dms->getAllUserKeywordCategories(3); - $this->assertIsArray($cats); - $this->assertCount(0, $cats); - /* Passing an invalid user id will return false */ - $cats = self::$dms->getAllUserKeywordCategories(0); - $this->assertFalse($cats); - } - - /** - * Test getAllKeywordCategories() with sql failure - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAllKeywordCategoriesSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblKeywordCategories`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $cats = $dms->getAllKeywordCategories(); - $this->assertFalse($cats); - } - - /** - * Test addKeywordCategory() - * - * Add a new keyword category and retrieve it afterwards. Also check if the - * number of keyword categories has increased by one. Add a keyword category - * with the same name a second time and check if it returns false. - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testAddKeywordCategory() - { - /* Adding a new keyword category */ - $cat = self::$dms->addKeywordCategory(1, 'new category'); - $this->assertIsObject($cat); - $this->assertEquals('new category', $cat->getName()); - - /* Adding a keyword category for the same user and with the same name must fail */ - $cat = self::$dms->addKeywordCategory(1, 'new category'); - $this->assertFalse($cat); - - /* Adding a keyword category with a non existing user id must fail */ - $cat = self::$dms->addKeywordCategory(0, 'new category'); - $this->assertFalse($cat); - - /* Adding a keyword category with an empty name must fail */ - $cat = self::$dms->addKeywordCategory(1, ' '); - $this->assertFalse($cat); - - /* Adding a keyword category with a non existing user id must fail */ - // $cat = self::$dms->addKeywordCategory(3, 'new category'); - // $this->assertFalse($cat); - - /* There should be 1 keyword category now */ - $cats = self::$dms->getAllKeywordCategories(); - $this->assertIsArray($cats); - $this->assertCount(1, $cats); - } - - /** - * Test addKeywordCategoryWithPostAddHook() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testAddKeywordCategoryWithPostAddHook() - { - /* Add the 'onPostAddKeywordCategory' callback */ - $ret = 0; - $callback = function ($param, $cat) use (&$ret) { - $ret = 1; - }; - self::$dms->addCallback('onPostAddKeywordCategory', $callback, 1); - /* Adding a new keyword category */ - $cat = self::$dms->addKeywordCategory(1, 'new category'); - $this->assertIsObject($cat); - $this->assertEquals('new category', $cat->getName()); - $this->assertEquals(1, $ret); - } - - /** - * Test addKeywordCategory() with sql failure - * - * @return void - */ - public function testAddKeywordCategorySqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("INSERT INTO `tblKeywordCategories`")) - ->willReturn(false); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblKeywordCategories` WHERE `name` =")) - ->willReturn([]); - $dms = new SeedDMS_Core_DMS($db, ''); - $cat = $dms->addKeywordCategory(1, 'new category'); - $this->assertFalse($cat); - } - - /** - * Test getKeywordCategory() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetKeywordCategory() - { - $cat = self::$dms->addKeywordCategory(1, 'new category'); - $cat = self::$dms->getKeywordCategory(1); - $this->assertInstanceOf(SeedDMS_Core_Keywordcategory::class, $cat); - $this->assertEquals(1, $cat->getId()); - /* Return false if the id is invalid */ - $cat = self::$dms->getKeywordCategory(0); - $this->assertFalse($cat); - /* Return null if the keyword category with the id does not exist */ - $cat = self::$dms->getKeywordCategory(2); - $this->assertNull($cat); - } - - /** - * Test getKeywordCategory() with sql failure - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetKeywordCategorySqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with("SELECT * FROM `tblKeywordCategories` WHERE `id` = 1") - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $cat = $dms->getKeywordCategory(1); - $this->assertFalse($cat); - } - - /** - * Test getKeywordCategoryByName() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetKeywordCategoryByName() - { - $cat = self::$dms->addKeywordCategory(1, 'new category'); - $cat = self::$dms->getKeywordCategory(1); - $this->assertInstanceOf(SeedDMS_Core_Keywordcategory::class, $cat); - $this->assertEquals(1, $cat->getId()); - /* Return false if the user id is invalid */ - $cat = self::$dms->getKeywordCategoryByName('new category', 0); - $this->assertFalse($cat); - /* Return null if the keyword category with the passed name does not exist */ - $cat = self::$dms->getKeywordCategoryByName('foo', 1); - $this->assertNull($cat); - /* Return category if the keyword category with the passed name exists */ - $cat = self::$dms->getKeywordCategoryByName('new category', 1); - $this->assertIsObject($cat); - $this->assertInstanceOf(SeedDMS_Core_Keywordcategory::class, $cat); - } - - /** - * Test getKeywordCategoryByName() with sql failure - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetKeywordCategoryByNameSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblKeywordCategories` WHERE `name` =")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $cat = $dms->getKeywordCategoryByName('foo', 1); - $this->assertFalse($cat); - } - - /** - * Test getDocumentCategories() - * - * The intitial database does not have any document categories - * - * @return void - */ - public function testGetDocumentCategories() - { - $cats = self::$dms->getDocumentCategories(); - $this->assertIsArray($cats); - $this->assertCount(0, $cats); - } - - /** - * Test getDocumentCategories() with sql failure - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetDocumentCategoriesNameSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblCategory`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $cats = $dms->getDocumentCategories(); - $this->assertFalse($cats); - } - - /** - * Test getDocumentCategory() - * - * The intitial database does not have any document categories - * - * @return void - */ - public function testGetDocumentCategory() - { - /* Adding a new keyword category */ - $cat = self::$dms->addDocumentCategory('new category'); - $this->assertIsObject($cat); - $this->assertEquals('new category', $cat->getName()); - - $cat = self::$dms->getDocumentCategory($cat->getId()); - $this->assertIsObject($cat); - - /* Return false if the id is out of range */ - $cat = self::$dms->getDocumentCategory(0); - $this->assertFalse($cat); - - /* Return null if the keyword category with the id does not exist */ - $cat = self::$dms->getDocumentCategory(2); - $this->assertNull($cat); - } - - /** - * Test getDocumentCategory() with sql failure - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetDocumentCategorySqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with("SELECT * FROM `tblCategory` WHERE `id` = 1") - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $cat = $dms->getDocumentCategory(1); - $this->assertFalse($cat); - } - - /** - * Test getDocumentCategoryByName() - * - * The intitial database does not have any document categories - * - * @return void - */ - public function testGetDocumentCategoryByName() - { - /* Adding a new keyword category with leading and trailing spaces*/ - $cat = self::$dms->addDocumentCategory(' new category '); - $this->assertIsObject($cat); - $this->assertEquals('new category', $cat->getName()); - - $cat = self::$dms->getDocumentCategoryByName($cat->getName()); - $this->assertIsObject($cat); - - $cat = self::$dms->getDocumentCategoryByName(' '); - $this->assertFalse($cat); - } - - /** - * Test getDocumentCategoryByName() with sql failure - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetDocumentCategoryByNameSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblCategory` WHERE `name`=")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $cat = $dms->getDocumentCategoryByName('foo'); - $this->assertFalse($cat); - } - - /** - * Test addDocumentCategory() - * - * Add a new keyword category and retrieve it afterwards. Also check if the - * number of keyword categories has increased by one. Add a keyword category - * with the same name a second time and check if it returns false. - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testAddDocumentCategory() - { - /* Adding a new keyword category */ - $cat = self::$dms->addDocumentCategory('new category'); - $this->assertIsObject($cat); - $this->assertEquals('new category', $cat->getName()); - - /* Adding a document category with the same name must fail */ - $cat = self::$dms->addDocumentCategory('new category'); - $this->assertFalse($cat); - - /* Adding a document category with an empty name must fail */ - $cat = self::$dms->addDocumentCategory(' '); - $this->assertFalse($cat); - - /* There should be 1 document category now */ - $cats = self::$dms->getDocumentCategories(); - $this->assertIsArray($cats); - $this->assertCount(1, $cats); - } - - /** - * Test addDocumentCategoryWithPostAddHook() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testAddDocumentCategoryWithPostAddHook() - { - /* Add the 'onPostAddDocumentCategory' callback */ - $ret = 0; - $callback = function ($param, $group) use (&$ret) { - $ret = 1; - }; - self::$dms->addCallback('onPostAddDocumentCategory', $callback, 1); - /* Adding a new group */ - $cat = self::$dms->addDocumentCategory('new category'); - $this->assertIsObject($cat); - $this->assertEquals('new category', $cat->getName()); - $this->assertEquals(1, $ret); - } - - /** - * Test addDocumentCategory() with sql failure - * - * @return void - */ - public function testAddDocumentCategorySqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("INSERT INTO `tblCategory`")) - ->willReturn(false); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblCategory` WHERE `name`=")) - ->willReturn([]); - $dms = new SeedDMS_Core_DMS($db, ''); - $cat = $dms->addDocumentCategory('new category'); - $this->assertFalse($cat); - } - - /** - * Test getAttributeDefinition() with a none existing workflow - * - * The intitial database does not have any workflows - * - * @return void - */ - public function testGetAttributeDefinitionNoExists() - { - $workflow = self::$dms->getAttributeDefinition(1); - $this->assertNull($workflow); - /* Passing an id not a numeric value returns false */ - $workflow = self::$dms->getAttributeDefinition('foo'); - $this->assertFalse($workflow); - /* Passing an id out of range returns false */ - $workflow = self::$dms->getAttributeDefinition(0); - $this->assertFalse($workflow); - } - - /** - * Test getAttributeDefinition() with sql failure - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAttributeDefinitionSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblAttributeDefinitions` WHERE `id` =")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $attrdef = $dms->getAttributeDefinition(1); - $this->assertFalse($attrdef); - } - - /** - * Test getAttributeDefinitionByName() with a none existing workflow - * - * The intitial database does not have any workflows - * - * @return void - */ - public function testGetAttributeDefinitionByNameNoExists() - { - $workflow = self::$dms->getAttributeDefinitionByName('foo'); - $this->assertNull($workflow); - } - - /** - * Test getAttributeDefinitionByName() with sql failure - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAttributeDefinitionByNameSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblAttributeDefinitions` WHERE `name` =")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $attrdef = $dms->getAttributeDefinitionByName('foo'); - $this->assertFalse($attrdef); - } - - /** - * Test getAllAttributeDefinitions() - * - * The intitial database does not have any attribute definitions - * - * @return void - */ - public function testGetAllAttributeDefinitions() - { - $attrdefs = self::$dms->getAllAttributeDefinitions(); - $this->assertIsArray($attrdefs); - $this->assertCount(0, $attrdefs); - } - - /** - * Test getAllAttributeDefinitions() with sql failure - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAllAttributeDefinitionsSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblAttributeDefinitions`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $attrdef = $dms->getAllAttributeDefinitions(); - $this->assertFalse($attrdef); - } - - /** - * Test addAttributeDefinition() - * - * Add a new group and retrieve it afterwards. Also check if the number - * of groups has increased by one. Add a group with the same name a - * second time and check if it returns false. - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testAddAttributeDefinition() - { - /* Adding a new attribute definition */ - $attrdef = self::$dms->addAttributeDefinition('new attribute definition', SeedDMS_Core_AttributeDefinition::objtype_folder, SeedDMS_Core_AttributeDefinition::type_int, false, 0, 0, '', ''); - $this->assertIsObject($attrdef); - $this->assertEquals('new attribute definition', $attrdef->getName()); - /* Get the new attribute definition by its id */ - $newattrdef = self::$dms->getAttributeDefinition($attrdef->getId()); - $this->assertIsObject($newattrdef); - $this->assertEquals($attrdef->getId(), $newattrdef->getId()); - /* Get the new attribute definition by its name */ - $newattrdef = self::$dms->getAttributeDefinitionByName('new attribute definition'); - $this->assertIsObject($newattrdef); - $this->assertEquals($attrdef->getId(), $newattrdef->getId()); - /* Adding an attribute definition with the same name must fail */ - $attrdef = self::$dms->addAttributeDefinition('new attribute definition', SeedDMS_Core_AttributeDefinition::objtype_folder, SeedDMS_Core_AttributeDefinition::type_int, false, 0, 0, '', ''); - $this->assertFalse($attrdef); - /* Adding an attribute definition with an empty name must fail */ - $attrdef = self::$dms->addAttributeDefinition(' ', SeedDMS_Core_AttributeDefinition::objtype_folder, SeedDMS_Core_AttributeDefinition::type_int, false, 0, 0, '', ''); - $this->assertFalse($attrdef); - /* Adding an attribute definition with an invalid object type must fail */ - $attrdef = self::$dms->addAttributeDefinition('no object type', -1, SeedDMS_Core_AttributeDefinition::type_int, false, 0, 0, '', ''); - $this->assertFalse($attrdef); - /* Adding an attribute definition without a type must fail */ - $attrdef = self::$dms->addAttributeDefinition('no type', SeedDMS_Core_AttributeDefinition::objtype_folder, 0, 0, '', ''); - $this->assertFalse($attrdef); - /* There should be one attribute definition now */ - $attrdefs = self::$dms->getAllAttributeDefinitions(); - $this->assertIsArray($attrdefs); - $this->assertCount(1, $attrdefs); - /* There should be one attribute definition of object type folder now */ - $attrdefs = self::$dms->getAllAttributeDefinitions(SeedDMS_Core_AttributeDefinition::objtype_folder); - $this->assertIsArray($attrdefs); - $this->assertCount(1, $attrdefs); - /* The object type can also be passed as an array */ - $attrdefs = self::$dms->getAllAttributeDefinitions([SeedDMS_Core_AttributeDefinition::objtype_folder]); - $this->assertIsArray($attrdefs); - $this->assertCount(1, $attrdefs); - /* Adding more attribute definitions of different object type */ - $attrdef = self::$dms->addAttributeDefinition('new attribute definition all', SeedDMS_Core_AttributeDefinition::objtype_all, SeedDMS_Core_AttributeDefinition::type_int, false, 0, 0, '', ''); - $this->assertIsObject($attrdef); - $this->assertEquals('new attribute definition all', $attrdef->getName()); - $attrdef = self::$dms->addAttributeDefinition('new attribute definition document', SeedDMS_Core_AttributeDefinition::objtype_all, SeedDMS_Core_AttributeDefinition::type_int, false, 0, 0, '', ''); - $this->assertIsObject($attrdef); - $this->assertEquals('new attribute definition document', $attrdef->getName()); - $attrdef = self::$dms->addAttributeDefinition('new attribute definition documentcontent', SeedDMS_Core_AttributeDefinition::objtype_all, SeedDMS_Core_AttributeDefinition::type_int, false, 0, 0, '', ''); - $this->assertIsObject($attrdef); - $this->assertEquals('new attribute definition documentcontent', $attrdef->getName()); - /* There should be four attribute definitions now */ - $attrdefs = self::$dms->getAllAttributeDefinitions(); - $this->assertIsArray($attrdefs); - $this->assertCount(4, $attrdefs); - } - - /** - * Test getAllWorkflows() - * - * The intitial database does not have any workflows - * - * @return void - */ - public function testGetAllWorkflows() - { - $workflows = self::$dms->getAllWorkflows(); - $this->assertIsArray($workflows); - $this->assertCount(0, $workflows); - } - - /** - * Test getAllWorkflows() with sql failure - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAllWorkflowsSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblWorkflows`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $workflows = $dms->getAllWorkflows(); - $this->assertFalse($workflows); - } - - /** - * Test getWorkflow() with a none existing workflow - * - * The intitial database does not have any workflows - * - * @return void - */ - public function testGetWorkflowNoExists() - { - $workflow = self::$dms->getWorkflow(1); - $this->assertNull($workflow); - /* Passing an id not a numeric value returns false */ - $workflow = self::$dms->getWorkflow('foo'); - $this->assertFalse($workflow); - /* Passing an id out of range returns false */ - $workflow = self::$dms->getWorkflow(0); - $this->assertFalse($workflow); - } - - /** - * Test getWorkflow() with sql failure - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetWorkflowSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblWorkflows` WHERE `id`=")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $workflow = $dms->getWorkflow(1); - $this->assertFalse($workflow); - } - - /** - * Test getWorkflowByName() with a none existing workflow - * - * The intitial database does not have any workflows - * - * @return void - */ - public function testGetWorkflowByNameNoExists() - { - $workflow = self::$dms->getWorkflowByName('foo'); - $this->assertNull($workflow); - } - - /** - * Test getWorkflowByName() with sql failure - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetWorkflowByNameSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblWorkflows` WHERE `name`=")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $workflow = $dms->getWorkflowByName('foo'); - $this->assertFalse($workflow); - } - - /** - * Test addWorkflow() - * - * Add a new workflow and retrieve it afterwards. Also check if the number - * of workflows has increased by one. Add a workflow with the same name a - * second time and check if it returns false. - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testAddWorkflow() - { - /* Adding a new workflow */ - $workflowstate = self::$dms->addWorkflowState('new workflow state', S_RELEASED); - $workflow = self::$dms->addWorkflow('new workflow', $workflowstate); - $this->assertIsObject($workflow); - $this->assertEquals('new workflow', $workflow->getName()); - /* Adding a workflow with the same name must fail */ - $workflow = self::$dms->addWorkflow('new workflow', $workflowstate); - $this->assertFalse($workflow); - /* Adding a workflow with an empty name must fail */ - $workflow = self::$dms->addWorkflow(' ', $workflowstate); - $this->assertFalse($workflow); - /* There should be one workflow now */ - $workflows = self::$dms->getAllWorkflows(); - $this->assertIsArray($workflows); - $this->assertCount(1, $workflows); - } - - /** - * Test getAllWorkflowStates() - * - * The intitial database does not have any workflow states - * - * @return void - */ - public function testGetAllWorkflowStates() - { - $states = self::$dms->getAllWorkflowStates(); - $this->assertIsArray($states); - $this->assertCount(0, $states); - } - - /** - * Test getAllWorkflowStates() with sql failure - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAllWorkflowStatesSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblWorkflowStates`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $states = $dms->getAllWorkflowStates(); - $this->assertFalse($states); - } - - /** - * Test getWorkflowState() with a none existing workflow state - * - * The intitial database does not have any workflow states - * - * @return void - */ - public function testGetWorkflowStateNoExists() - { - $workflowstate = self::$dms->getWorkflowState(1); - $this->assertNull($workflowstate); - /* Passing an id not a numeric value returns false */ - $workflowstate = self::$dms->getWorkflowState('foo'); - $this->assertFalse($workflowstate); - /* Passing an id out of range returns false */ - $workflowstate = self::$dms->getWorkflowState(0); - $this->assertFalse($workflowstate); - } - - /** - * Test getWorkflowState() with sql failure - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetWorkflowStateSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblWorkflowStates` WHERE `id` =")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $state = $dms->getWorkflowState(1); - $this->assertFalse($state); - } - - /** - * Test getWorkflowStateByName() with a none existing workflow state - * - * The intitial database does not have any workflow states - * - * @return void - */ - public function testGetWorkflowStateByNameNoExists() - { - $workflowstate = self::$dms->getWorkflowStateByName('foo'); - $this->assertNull($workflowstate); - } - - /** - * Test getWorkflowStateByName() with sql failure - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetWorkflowStateByNameSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblWorkflowStates` WHERE `name`=")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $state = $dms->getWorkflowStateByName('foo'); - $this->assertFalse($state); - } - - /** - * Test addWorkflowState() - * - * Add a new workflow state and retrieve it afterwards. Also check if the number - * of workflow states has increased by one. Add a workflow state with the same name a - * second time and check if it returns false. - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testAddWorkflowState() - { - /* Adding a new workflow state */ - $workflowstate = self::$dms->addWorkflowState('new workflow state', S_RELEASED); - $this->assertIsObject($workflowstate); - $this->assertEquals('new workflow state', $workflowstate->getName()); - /* Adding a workflow state with the same name must fail */ - $workflowstate = self::$dms->addWorkflowState('new workflow state', S_RELEASED); - $this->assertFalse($workflowstate); - /* Adding a workflow state with an empty name must fail */ - $workflowstate = self::$dms->addWorkflowState(' ', S_RELEASED); - $this->assertFalse($workflowstate); - /* There should be one workflow state now */ - $workflowstates = self::$dms->getAllWorkflowStates(); - $this->assertIsArray($workflowstates); - $this->assertCount(1, $workflowstates); - } - - /** - * Test getAllWorkflowActions() - * - * The intitial database does not have any workflow actions - * - * @return void - */ - public function testGetAllWorkflowActions() - { - $actions = self::$dms->getAllWorkflowActions(); - $this->assertIsArray($actions); - $this->assertCount(0, $actions); - } - - /** - * Test getAllWorkflowActions() with sql failure - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAllWorkflowActionsSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblWorkflowActions`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $actions = $dms->getAllWorkflowActions(); - $this->assertFalse($actions); - } - - /** - * Test getWorkflowAction() with a none existing workflow - * - * The intitial database does not have any workflow actions - * - * @return void - */ - public function testGetWorkflowActionNoExists() - { - $workflowaction = self::$dms->getWorkflowAction(1); - $this->assertNull($workflowaction); - /* Passing an id not a numeric value returns false */ - $workflowaction = self::$dms->getWorkflowAction('foo'); - $this->assertFalse($workflowaction); - /* Passing an id out of range returns false */ - $workflowaction = self::$dms->getWorkflowAction(0); - $this->assertFalse($workflowaction); - } - - /** - * Test getWorkflowAction() with sql failure - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetWorkflowActionSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblWorkflowActions` WHERE `id` =")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $action = $dms->getWorkflowAction(1); - $this->assertFalse($action); - } - - /** - * Test getWorkflowActionByName() with a none existing workflow action - * - * The intitial database does not have any workflow actions - * - * @return void - */ - public function testGetWorkflowActionByNameNoExists() - { - $workflowaction = self::$dms->getWorkflowActionByName('foo'); - $this->assertNull($workflowaction); - } - - /** - * Test getWorkflowActionByName() with sql failure - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetWorkflowActionByNameSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblWorkflowActions` WHERE `name` =")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $action = $dms->getWorkflowActionByName('foo'); - $this->assertFalse($action); - } - - /** - * Test addWorkflowAction() - * - * Add a new workflow state and retrieve it afterwards. Also check if the number - * of workflow states has increased by one. Add a workflow state with the same name a - * second time and check if it returns false. - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testAddWorkflowAction() - { - /* Adding a new workflow action */ - $workflowaction = self::$dms->addWorkflowAction('new workflow action', S_RELEASED); - $this->assertIsObject($workflowaction); - $this->assertEquals('new workflow action', $workflowaction->getName()); - /* Adding a workflow action with the same name must fail */ - $workflowaction = self::$dms->addWorkflowAction('new workflow action', S_RELEASED); - $this->assertFalse($workflowaction); - /* Adding a workflow action with an empty name must fail */ - $workflowaction = self::$dms->addWorkflowAction(' ', S_RELEASED); - $this->assertFalse($workflowaction); - /* There should be one workflow action now */ - $workflowactions = self::$dms->getAllWorkflowActions(); - $this->assertIsArray($workflowactions); - $this->assertCount(1, $workflowactions); - } - - /** - * Test getStatisticalData() - * - * @return void - */ - public function testGetStatisticalData() - { - /* There should one folder (root folder) */ - $data = self::$dms->getStatisticalData('foldersperuser'); - $this->assertIsArray($data); - $this->assertEquals(1, $data[0]['total']); - /* There should be no documents */ - foreach (array('docsperuser', 'docspermimetype', 'docspercategory', 'docspermonth', 'docsperstatus', 'docsaccumulated', 'sizeperuser') as $type) { - $data = self::$dms->getStatisticalData($type); - $this->assertIsArray($data); - $this->assertCount(0, $data); - } - /* Passing an unknown name returns an empty array */ - $data = self::$dms->getStatisticalData('foo'); - $this->assertIsArray($data); - $this->assertCount(0, $data); - } - - /** - * Test getStatisticalDataFail() - * - * Check if getStatisticalData() fails if the sql statements fail - * - * @return void - */ - public function testGetStatisticalDataFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->any()) - ->method('getResultArray') - ->with($this->stringContains("SELECT ")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - foreach (array('foldersperuser', 'docsperuser', 'docspermimetype', 'docspercategory', 'docspermonth', 'docsperstatus', 'docsaccumulated', 'sizeperuser') as $type) { - $data = $dms->getStatisticalData($type); - $this->assertFalse($data); - } - } - - /** - * Test createPasswordRequest() and checkPasswordRequest() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testCreateAndCheckAndDeletePasswordRequest() - { - $user = self::$dms->getUser(1); - $hash = self::$dms->createPasswordRequest($user); - $this->assertIsString($hash); - $user = self::$dms->checkPasswordRequest($hash); - $this->assertIsObject($user); - $this->assertEquals(1, $user->getId()); - /* Check a non existing hash */ - $user = self::$dms->checkPasswordRequest('foo'); - $this->assertFalse($user); - /* Delete the hash */ - $ret = self::$dms->deletePasswordRequest($hash); - $this->assertTrue($ret); - /* Checking the hash again must return false, because it was deleted */ - $user = self::$dms->checkPasswordRequest($hash); - $this->assertFalse($user); - } - - /** - * Test method checkPasswordRequest() with sql failure - * - * @return void - */ - public function testCheckPasswordRequestSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblUserPasswordRequest`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $this->assertFalse($dms->checkPasswordRequest('foo')); - } - - /** - * Test method deletePasswordRequest() with sql failure - * - * @return void - */ - public function testDeletePasswordRequestSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("DELETE FROM `tblUserPasswordRequest`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $this->assertFalse($dms->deletePasswordRequest('foo')); - } - - /** - * Test getTimeline() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetTimeline() - { - $timeline = self::$dms->getTimeline(); - $this->assertIsArray($timeline); - } - - /** - * Test getUnlinkedDocumentContent() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetUnlinkedDocumentContent() - { - $contents = self::$dms->getUnlinkedDocumentContent(); - $this->assertIsArray($contents); - $this->assertCount(0, $contents); - } - - /** - * Test getNoFileSizeDocumentContent() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetNoFileSizeDocumentContent() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - $document = self::createDocument($rootfolder, $user, 'Document 1'); - $contents = self::$dms->getNoFileSizeDocumentContent(); - $this->assertIsArray($contents); - $this->assertCount(0, $contents); - /* Manipulate the file size right in the database */ - $dbh = self::$dms->getDB(); - $ret = $dbh->getResult("UPDATE `tblDocumentContent` SET `fileSize` = 0"); - $this->assertTrue($ret); - $contents = self::$dms->getNoFileSizeDocumentContent(); - $this->assertIsArray($contents); - $this->assertCount(1, $contents); - } - - /** - * Test getNoFileSizeDocumentContent() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetNoFileSizeDocumentContentSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblDocumentContent` WHERE `fileSize`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $this->assertFalse($dms->getNoFileSizeDocumentContent()); - } - - /** - * Test getNoChecksumDocumentContent() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetNoChecksumDocumentContent() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - $document = self::createDocument($rootfolder, $user, 'Document 1'); - $contents = self::$dms->getNoChecksumDocumentContent(); - $this->assertIsArray($contents); - $this->assertCount(0, $contents); - /* Manipulate the checksum right in the database */ - $dbh = self::$dms->getDB(); - $ret = $dbh->getResult("UPDATE `tblDocumentContent` SET `checksum` = null"); - $this->assertTrue($ret); - $contents = self::$dms->getNoChecksumDocumentContent(); - $this->assertIsArray($contents); - $this->assertCount(1, $contents); - } - - /** - * Test getNoChecksumDocumentContent() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetNoChecksumDocumentContentSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblDocumentContent` WHERE `checksum`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $this->assertFalse($dms->getNoChecksumDocumentContent()); - } - - /** - * Test getDuplicateDocumentContent() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetDuplicateDocumentContent() - { - $contents = self::$dms->getDuplicateDocumentContent(); - $this->assertIsArray($contents); - $this->assertCount(0, $contents); - } - - /** - * Test getDuplicateDocumentContent() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetDuplicateDocumentContentWithDuplicates() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - $document1 = self::createDocument($rootfolder, $user, 'Document 1'); - - $filename = self::createTempFile(200); - list($document2, $res) = $rootfolder->addDocument( - 'Documet 2', // name - '', // comment - null, // no expiration - $user, // owner - '', // keywords - [], // categories - $filename, // name of file - 'file1.txt', // original file name - '.txt', // file type - 'text/plain', // mime type - 1.0 // sequence - ); - list($document3, $res) = $rootfolder->addDocument( - 'Documet 3', // name - '', // comment - null, // no expiration - $user, // owner - '', // keywords - [], // categories - $filename, // name of file - 'file1.txt', // original file name - '.txt', // file type - 'text/plain', // mime type - 1.0 // sequence - ); - $this->assertTrue(SeedDMS_Core_File::removeFile($filename)); - - $contents = self::$dms->getDuplicateDocumentContent(); - $this->assertIsArray($contents); - $this->assertCount(1, $contents); - } - - /** - * Test method getDuplicateDocumentContent() with sql failure - * - * @return void - */ - public function testGetDuplicateDocumentContentSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT a.*, b.`id` as dupid FROM `tblDocumentContent`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $this->assertFalse($dms->getDuplicateDocumentContent()); - } - - /** - * Test getNotificationsByUser() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetNotificationsByUser() - { - $user = self::$dms->getUser(1); - $notifications = self::$dms->getNotificationsByUser($user, 0); - $this->assertIsArray($notifications); - $this->assertCount(0, $notifications); - $notifications = self::$dms->getNotificationsByUser($user, 1); - $this->assertIsArray($notifications); - $this->assertCount(0, $notifications); - } - - /** - * Test getNotificationsByGroup() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetNotificationsByGroup() - { - $group = self::$dms->addGroup('new group', 'with comment'); - $this->assertIsObject($group); - $notifications = self::$dms->getNotificationsByGroup($group, 0); - $this->assertIsArray($notifications); - $this->assertCount(0, $notifications); - $notifications = self::$dms->getNotificationsByGroup($group, 1); - $this->assertIsArray($notifications); - $this->assertCount(0, $notifications); - } - - /** - * Test getDocumentsExpired() - * - * Check if getDocumentsExpired() fails if the parameters are wrong - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetDocumentsExpiredFail() - { - $documents = self::$dms->getDocumentsExpired(false); - $this->assertFalse($documents); - $documents = self::$dms->getDocumentsExpired('2021-04'); - $this->assertFalse($documents); - $documents = self::$dms->getDocumentsExpired('2021-01-32'); - $this->assertFalse($documents); - $documents = self::$dms->getDocumentsExpired('2021-01-31'); // valid date - $this->assertIsArray($documents); - } - - /** - * Test method getDocumentsExpired() with sql failure - * - * @return void - */ - public function testGetDocumentsExpiredSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('createTemporaryTable') - ->with('ttstatid') - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $this->assertFalse($dms->getDocumentsExpired(1)); - } - - /** - * Test getDocumentByName() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetDocumentByName() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - $this->assertInstanceOf(SeedDMS_Core_Folder::class, $rootfolder); - $subfolder = $rootfolder->addSubFolder('Subfolder 1', '', $user, 2.0); - $this->assertInstanceOf(SeedDMS_Core_Folder::class, $subfolder); - - /* Add a new document */ - $filename = self::createTempFile(200); - list($document, $res) = $subfolder->addDocument( - 'Document 1', // name - '', // comment - null, // no expiration - $user, // owner - '', // keywords - [], // categories - $filename, // name of file - 'file1.txt', // original file name - '.txt', // file type - 'text/plain', // mime type - 1.0 // sequence - ); - $this->assertIsObject($document); - $this->assertTrue(SeedDMS_Core_File::removeFile($filename)); - /* Search without a parent folder restriction */ - $document = self::$dms->getDocumentByName('Document 1'); - $this->assertInstanceOf(SeedDMS_Core_Document::class, $document); - /* Searching in the root folder will return no document */ - $document = self::$dms->getDocumentByName('Document 1', $rootfolder); - $this->assertNull($document); - /* Searching in the sub folder will return the document */ - $document = self::$dms->getDocumentByName('Document 1', $subfolder); - $this->assertInstanceOf(SeedDMS_Core_Document::class, $document); - /* Searching for an empty name returns false */ - $document = self::$dms->getDocumentByName(' '); - $this->assertFalse($document); - } - - /** - * Test getDocumentByName() with sql failure - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetDocumentByNameSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT `tblDocuments`.*, `tblDocumentLocks`.`userID` as `lockUser`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $document = $dms->getDocumentByName('foo'); - $this->assertFalse($document); - } - - /** - * Test getDocumentByOriginalFilename() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetDocumentByOriginalFilename() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - $this->assertInstanceOf(SeedDMS_Core_Folder::class, $rootfolder); - $subfolder = $rootfolder->addSubFolder('Subfolder 1', '', $user, 2.0); - $this->assertInstanceOf(SeedDMS_Core_Folder::class, $subfolder); - - /* Add a new document */ - $filename = self::createTempFile(200); - list($document, $res) = $subfolder->addDocument( - 'Document 1', // name - '', // comment - null, // no expiration - $user, // owner - '', // keywords - [], // categories - $filename, // name of file - 'file1.txt', // original file name - '.txt', // file type - 'text/plain', // mime type - 1.0 // sequence - ); - $this->assertIsObject($document); - $this->assertTrue(SeedDMS_Core_File::removeFile($filename)); - /* Search without a parent folder restriction */ - $document = self::$dms->getDocumentByOriginalFilename('file1.txt'); - $this->assertInstanceOf(SeedDMS_Core_Document::class, $document); - /* Searching in the root folder will return no document */ - $document = self::$dms->getDocumentByOriginalFilename('file1.txt', $rootfolder); - $this->assertNull($document); - /* Searching in the sub folder will return the document */ - $document = self::$dms->getDocumentByOriginalFilename('file1.txt', $subfolder); - $this->assertInstanceOf(SeedDMS_Core_Document::class, $document); - /* Searching for an empty name returns false */ - $document = self::$dms->getDocumentByOriginalFilename(' '); - $this->assertFalse($document); - } - - /** - * Test method getDocumentByOriginalFilename() with sql failure - * - * @return void - */ - public function testGetDocumentByOriginalFilenameSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('createTemporaryTable') - ->with('ttcontentid') - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $this->assertFalse($dms->getDocumentByOriginalFilename(1)); - } - - /** - * Test getDocumentList() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetDocumentList() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - $this->assertInstanceOf(SeedDMS_Core_Folder::class, $rootfolder); - - /* Add a new document */ - $filename = self::createTempFile(200); - list($document, $res) = $rootfolder->addDocument( - 'Document 1', // name - '', // comment - null, // no expiration - $user, // owner - '', // keywords - [], // categories - $filename, // name of file - 'file1.txt', // original file name - '.txt', // file type - 'text/plain', // mime type - 1.0 // sequence - ); - $this->assertTrue(SeedDMS_Core_File::removeFile($filename)); - $this->assertIsObject($document); - - /* Add a second new document */ - $filename = self::createTempFile(200); - list($document, $res) = $rootfolder->addDocument( - 'Document 2', // name - '', // comment - mktime(0, 0, 0), // expires today - $user, // owner - '', // keywords - [], // categories - $filename, // name of file - 'file2.txt', // original file name - '.txt', // file type - 'text/plain', // mime type - 1.0 // sequence - ); - $this->assertTrue(SeedDMS_Core_File::removeFile($filename)); - $this->assertIsObject($document); - - $documents = self::$dms->getDocumentList('MyDocs', $user); - $this->assertIsArray($documents); - $this->assertCount(2, $documents); - /* All documents expiring from 1 year ago till today */ - $documents = self::$dms->getDocumentList('ExpiredOwner', $user); - $this->assertIsArray($documents); - $this->assertCount(1, $documents); - /* All documents expiring today */ - $documents = self::$dms->getDocumentList('ExpiredOwner', $user, 0); - $this->assertIsArray($documents); - $this->assertCount(1, $documents); - /* All documents expiring tomorrow */ - $documents = self::$dms->getDocumentList('ExpiredOwner', $user, date("Y-m-d", time()+86400)); - $this->assertIsArray($documents); - $this->assertCount(1, $documents); - /* Get unknown list */ - $documents = self::$dms->getDocumentList('foo', $user); - $this->assertFalse($documents); - } - - /** - * Test search() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testSearch() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - $this->assertInstanceOf(SeedDMS_Core_Folder::class, $rootfolder); - $subfolder = $rootfolder->addSubFolder('Subfolder 1', '', $user, 2.0); - $this->assertInstanceOf(SeedDMS_Core_Folder::class, $subfolder); - - /* Add a new document to the subfolder*/ - $filename = self::createTempFile(200); - list($document, $res) = $subfolder->addDocument( - 'Document 1', // name - '', // comment - null, // no expiration - $user, // owner - '', // keywords - [], // categories - $filename, // name of file - 'file1.txt', // original file name - '.txt', // file type - 'text/plain', // mime type - 1.0 // sequence - ); - $this->assertTrue(SeedDMS_Core_File::removeFile($filename)); - /* Add a new document to the root folder. All documents expire. The first - * expires today, the second expires tomorrow, etc. - */ - for ($i=2; $i<=30; $i++) { - $filename = self::createTempFile(200); - list($document, $res) = $rootfolder->addDocument( - 'Document '.$i, // name - '', // comment - mktime(0, 0, 0)+($i-2)*86400, // expires in $i-2 days - $user, // owner - '', // keywords - [], // categories - $filename, // name of file - 'file'.$i.'.txt', // original file name - '.txt', // file type - 'text/plain', // mime type - 1.0+$i // sequence - ); - $this->assertTrue(SeedDMS_Core_File::removeFile($filename)); - } - $hits = self::$dms->search(['query'=>'Document']); - $this->assertIsArray($hits); - $this->assertCount(5, $hits); - $this->assertEquals(30, $hits['totalDocs']); - $this->assertCount(30, $hits['docs']); - /* Limit number of documents to 10 */ - $hits = self::$dms->search(['query'=>'Document', 'limit'=>10]); - $this->assertIsArray($hits); - $this->assertCount(5, $hits); - $this->assertEquals(30, $hits['totalDocs']); - $this->assertCount(10, $hits['docs']); - /* Same number of documents if startFolder is the root folder */ - $hits = self::$dms->search(['query'=>'Document', 'startFolder'=>$rootfolder]); - $this->assertIsArray($hits); - $this->assertCount(5, $hits); - $this->assertEquals(30, $hits['totalDocs']); - $this->assertCount(30, $hits['docs']); - /* There is just one document below the sub folder */ - $hits = self::$dms->search(['query'=>'Document', 'startFolder'=>$subfolder]); - $this->assertIsArray($hits); - $this->assertCount(5, $hits); - $this->assertEquals(1, $hits['totalDocs']); - /* Get documents with a given expiration date in the future - * All documents in subfolder, but not the one in the root folder - */ - $expts = mktime(0, 0, 0); - $expstart = [ - 'year'=>date('Y', $expts), - 'month'=>date('m', $expts), - 'day'=>date('d', $expts), - 'hour'=>date('H', $expts), - 'minute'=>date('i', $expts), - 'second'=>date('s', $expts) - ]; - $hits = self::$dms->search(['query'=>'Document', 'expirationstartdate'=>$expstart]); - $this->assertIsArray($hits); - $this->assertCount(5, $hits); - $this->assertEquals(29, $hits['totalDocs']); - /* Get documents with a given expiration date in the future, starting tomorrow - * All documents in subfolder - 1 - */ - $expts = mktime(0, 0, 0)+86400; - $expstart = [ - 'year'=>date('Y', $expts), - 'month'=>date('m', $expts), - 'day'=>date('d', $expts), - 'hour'=>date('H', $expts), - 'minute'=>date('i', $expts), - 'second'=>date('s', $expts) - ]; - $hits = self::$dms->search(['query'=>'Document', 'expirationstartdate'=>$expstart]); - $this->assertIsArray($hits); - $this->assertCount(5, $hits); - $this->assertEquals(28, $hits['totalDocs']); - /* Get documents expire today or tomorrow - * 2 documents in subfolder - */ - $expts = mktime(0, 0, 0); - $expstart = [ - 'year'=>date('Y', $expts), - 'month'=>date('m', $expts), - 'day'=>date('d', $expts), - 'hour'=>date('H', $expts), - 'minute'=>date('i', $expts), - 'second'=>date('s', $expts) - ]; - $expts += 1*86400; - $expstop = [ - 'year'=>date('Y', $expts), - 'month'=>date('m', $expts), - 'day'=>date('d', $expts), - 'hour'=>date('H', $expts), - 'minute'=>date('i', $expts), - 'second'=>date('s', $expts) - ]; - $hits = self::$dms->search(['query'=>'Document', 'expirationstartdate'=>$expstart, 'expirationenddate'=>$expstop]); - $this->assertIsArray($hits); - $this->assertCount(5, $hits); - $this->assertEquals(2, $hits['totalDocs']); - /* Get documents expire before and tomorrow - * 2 documents in subfolder - */ - $expts = mktime(0, 0, 0); // Start of today - $expts += 1*86400; // Start of tomorrow - $expstop = [ - 'year'=>date('Y', $expts), - 'month'=>date('m', $expts), - 'day'=>date('d', $expts), - 'hour'=>date('H', $expts), - 'minute'=>date('i', $expts), - 'second'=>date('s', $expts) - ]; - $hits = self::$dms->search(['query'=>'Document', 'expirationenddate'=>$expstop]); - $this->assertIsArray($hits); - $this->assertCount(5, $hits); - $this->assertEquals(2, $hits['totalDocs']); - } - -} - diff --git a/SeedDMS_Core/tests/DmsWithDataTest.php b/SeedDMS_Core/tests/DmsWithDataTest.php deleted file mode 100644 index 17fde09e7..000000000 --- a/SeedDMS_Core/tests/DmsWithDataTest.php +++ /dev/null @@ -1,290 +0,0 @@ - - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version @package_version@ - * @link https://www.seeddms.org - */ - -use PHPUnit\Framework\SeedDmsTest; - -/** - * DMS test class - * - * @category SeedDMS - * @package Tests - * @author Uwe Steinmann - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version Release: @package_version@ - * @link https://www.seeddms.org - */ -class DmsWithDataTest extends SeedDmsTest -{ - - /** - * Create a real sqlite database in memory - * - * @return void - */ - protected function setUp(): void - { - self::$dbh = self::createInMemoryDatabase(); - self::$contentdir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'phpunit-'.time(); - mkdir(self::$contentdir); - // echo "Creating temp content dir: ".self::$contentdir."\n"; - self::$dms = new SeedDMS_Core_DMS(self::$dbh, self::$contentdir); - } - - /** - * Clean up at tear down - * - * @return void - */ - protected function tearDown(): void - { - self::$dbh = null; - // echo "\nRemoving temp. content dir: ".self::$contentdir."\n"; - exec('rm -rf '.self::$contentdir); - } - - /** - * Test getFoldersMinMax() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetFoldersMinMax() - { - self::createSimpleFolderStructure(); - $rootfolder = self::$dms->getRootFolder(); - $minmax = $rootfolder->getFoldersMinMax(); - $this->assertIsArray($minmax); - $this->assertCount(2, $minmax); - $this->assertEquals(0.5, $minmax['min']); - $this->assertEquals(2.0, $minmax['max']); - } - - /** - * Test method getFoldersMinMax() - * - * @return void - */ - public function testGetFoldersMinMaxSqlFail() - { - $rootfolder = $this->getMockedRootFolder(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT min(`sequence`) AS `min`, max(`sequence`) AS `max` FROM `tblFolders`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $rootfolder->setDMS($dms); - $this->assertFalse($rootfolder->getFoldersMinMax()); - } - - /** - * Test getDocumentsMinMax() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetDocumentsMinMax() - { - self::createSimpleFolderStructureWithDocuments(); - $subfolder = self::$dms->getFolderByName('Subfolder 1'); - $this->assertIsObject($subfolder); - $minmax = $subfolder->getDocumentsMinMax(); - $this->assertIsArray($minmax); - $this->assertCount(2, $minmax); - $this->assertEquals(2.0, $minmax['min']); - $this->assertEquals(16.0, $minmax['max']); - } - - /** - * Test method getDocumentsMinMax() - * - * @return void - */ - public function testGetDocumentsMinMaxSqlFail() - { - $rootfolder = $this->getMockedRootFolder(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT min(`sequence`) AS `min`, max(`sequence`) AS `max` FROM `tblDocuments`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $rootfolder->setDMS($dms); - $this->assertFalse($rootfolder->getDocumentsMinMax()); - } - - /** - * Test addDocument() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testAddDocument() - { - self::createSimpleFolderStructure(); - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - $this->assertInstanceOf(SeedDMS_Core_Folder::class, $rootfolder); - $this->assertEquals(1, $rootfolder->getId()); - /* Add a new document */ - $filename = self::createTempFile(200); - list($document, $res) = $rootfolder->addDocument( - 'Document 1', // name - '', // comment - null, // expiration - $user, // owner - '', // keywords - [], // categories - $filename, // name of file - 'file1.txt', // original file name - '.txt', // file type - 'text/plain', // mime type - 1.0 // sequence - ); - $this->assertTrue(SeedDMS_Core_File::removeFile($filename)); - $this->assertIsObject($document); - $this->assertInstanceOf(SeedDMS_Core_Document::class, $document); - $this->assertEquals('Document 1', $document->getName()); - } - - /** - * Test getDocumentsExpired() - * - * Create two documents which will expired today and tomorrow - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetDocumentsExpiredFuture() - { - self::createSimpleFolderStructure(); - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - $this->assertInstanceOf(SeedDMS_Core_Folder::class, $rootfolder); - $this->assertEquals(1, $rootfolder->getId()); - /* Add a new document */ - $filename = self::createTempFile(200); - list($document, $res) = $rootfolder->addDocument( - 'Document 1', // name - '', // comment - mktime(23,59,59), // expiration is still today at 23:59:59 - $user, // owner - '', // keywords - [], // categories - $filename, // name of file - 'file1.txt', // original file name - '.txt', // file type - 'text/plain', // mime type - 1.0 // sequence - ); - $this->assertIsObject($document); - list($document, $res) = $rootfolder->addDocument( - 'Document 2', // name - '', // comment - mktime(23,59,59)+1, // expiration is tomorrow today at 0:00:00 - $user, // owner - '', // keywords - [], // categories - $filename, // name of file - 'file1.txt', // original file name - '.txt', // file type - 'text/plain', // mime type - 1.0 // sequence - ); - $this->assertIsObject($document); - $this->assertTrue(SeedDMS_Core_File::removeFile($filename)); - $documents = self::$dms->getDocumentsExpired(0); /* Docs expire today */ - $this->assertIsArray($documents); - $this->assertCount(1, $documents); - $documents = self::$dms->getDocumentsExpired(date('Y-m-d')); /* Docs expire today */ - $this->assertIsArray($documents); - $this->assertCount(1, $documents); - $documents = self::$dms->getDocumentsExpired(1); /* Docs expire till tomorrow 23:59:59 */ - $this->assertIsArray($documents); - $this->assertCount(2, $documents); - $documents = self::$dms->getDocumentsExpired(date('Y-m-d', time()+86400)); /* Docs expire till tomorrow 23:59:59 */ - $this->assertIsArray($documents); - $this->assertCount(2, $documents); - $documents = self::$dms->getDocumentsExpired(date('Y-m-d', time()+86400), $user); /* Docs expire till tomorrow 23:59:59 owned by $user */ - $this->assertIsArray($documents); - $this->assertCount(2, $documents); - } - - /** - * Test getDocumentsExpired() - * - * Create two documents which have expired yesterday and the day before - * yesterday - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetDocumentsExpiredPast() - { - self::createSimpleFolderStructure(); - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - $this->assertInstanceOf(SeedDMS_Core_Folder::class, $rootfolder); - $this->assertEquals(1, $rootfolder->getId()); - /* Add a new document */ - $filename = self::createTempFile(200); - list($document, $res) = $rootfolder->addDocument( - 'Document 1', // name - '', // comment - mktime(0,0,0)-1, // expiration was yesterday - $user, // owner - '', // keywords - [], // categories - $filename, // name of file - 'file1.txt', // original file name - '.txt', // file type - 'text/plain', // mime type - 1.0 // sequence - ); - $this->assertIsObject($document); - list($document, $res) = $rootfolder->addDocument( - 'Document 2', // name - '', // comment - mktime(0,0,0)-1-86400, // expiration the day before yesterday - $user, // owner - '', // keywords - [], // categories - $filename, // name of file - 'file1.txt', // original file name - '.txt', // file type - 'text/plain', // mime type - 1.0 // sequence - ); - $this->assertTrue(SeedDMS_Core_File::removeFile($filename)); - $this->assertIsObject($document); - $documents = self::$dms->getDocumentsExpired(0); /* No Docs expire today */ - $this->assertIsArray($documents); - $this->assertCount(0, $documents); - $documents = self::$dms->getDocumentsExpired(-1); /* Docs expired yesterday */ - $this->assertIsArray($documents); - $this->assertCount(1, $documents); - $documents = self::$dms->getDocumentsExpired(-2); /* Docs expired since the day before yesterday */ - $this->assertIsArray($documents); - $this->assertCount(2, $documents); - } - - -} diff --git a/SeedDMS_Core/tests/DocumentCategoryTest.php b/SeedDMS_Core/tests/DocumentCategoryTest.php deleted file mode 100644 index 37309d9a1..000000000 --- a/SeedDMS_Core/tests/DocumentCategoryTest.php +++ /dev/null @@ -1,295 +0,0 @@ - - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version @package_version@ - * @link https://www.seeddms.org - */ - -use PHPUnit\Framework\SeedDmsTest; - -/** - * User test class - * - * @category SeedDMS - * @package Tests - * @author Uwe Steinmann - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version Release: @package_version@ - * @link https://www.seeddms.org - */ -class DocumentCategoryTest extends SeedDmsTest -{ - - /** - * Create a real sqlite database in memory - * - * @return void - */ - protected function setUp(): void - { - self::$dbh = self::createInMemoryDatabase(); - self::$contentdir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'phpunit-'.time(); - mkdir(self::$contentdir); - // echo "Creating temp content dir: ".self::$contentdir."\n"; - self::$dms = new SeedDMS_Core_DMS(self::$dbh, self::$contentdir); - } - - /** - * Clean up at tear down - * - * @return void - */ - protected function tearDown(): void - { - self::$dbh = null; - // echo "\nRemoving temp. content dir: ".self::$contentdir."\n"; - exec('rm -rf '.self::$contentdir); - } - - /** - * Test method getName() and setName() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetName() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $cat = self::$dms->addDocumentCategory('Category 1'); - $name = $cat->getName(); - $ret = $cat->setName('foo'); - $this->assertTrue($ret); - $name = $cat->getName(); - $this->assertEquals('foo', $name); - $ret = $cat->setName(' '); - $this->assertFalse($ret); - } - - /** - * Test method addCategories(), hasCategory(), setCategory() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testAddCategoryToDocument() - { - $rootfolder = self::$dms->getRootFolder(); - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - - /* Add a new document and two categories */ - $document = self::createDocument($rootfolder, $user, 'Document 1'); - $cat1 = self::$dms->addDocumentCategory('Category 1'); - $cat2 = self::$dms->addDocumentCategory('Category 2'); - - /* There are no categories yet */ - $ret = $document->hasCategory($cat1); - $this->assertFalse($ret); - - /* Not passing a category yields on error */ - $ret = $document->hasCategory(null); - $this->assertFalse($ret); - - /* Adding a category ... */ - $ret = $document->addCategories([$cat1]); - $this->assertTrue($ret); - - /* ... and check if it is there */ - $ret = $document->hasCategory($cat1); - $this->assertTrue($ret); - - /* There should be one category now */ - $cats = $document->getCategories(); - $this->assertIsArray($cats); - $this->assertCount(1, $cats); - $this->assertEquals($cat1->getName(), $cats[0]->getName()); - - /* Adding the same category shouldn't change anything */ - $ret = $document->addCategories([$cat1]); - $this->assertTrue($ret); - - /* Check if category is used */ - $ret = $cat1->isUsed(); - $this->assertTrue($ret); - $ret = $cat2->isUsed(); - $this->assertFalse($ret); - - /* There is one document with cat 1 but none with cat 2 */ - $docs = $cat1->getDocumentsByCategory(); - $this->assertIsArray($docs); - $this->assertCount(1, $docs); - $num = $cat1->countDocumentsByCategory(); - $this->assertEquals(1, $num); - $docs = $cat2->getDocumentsByCategory(); - $this->assertIsArray($docs); - $this->assertCount(0, $docs); - $num = $cat2->countDocumentsByCategory(); - $this->assertEquals(0, $num); - - /* Still only one category */ - $cats = $document->getCategories(); - $this->assertIsArray($cats); - $this->assertCount(1, $cats); - - /* Setting new categories will replace the old ones */ - $ret = $document->setCategories([$cat1, $cat2]); - $this->assertTrue($ret); - - /* Now we have two categories */ - $cats = $document->getCategories(); - $this->assertIsArray($cats); - $this->assertCount(2, $cats); - - /* Remove a category */ - $ret = $document->removeCategories([$cat1]); - $this->assertTrue($ret); - - /* Removing the same category again does not harm*/ - $ret = $document->removeCategories([$cat1]); - $this->assertTrue($ret); - - /* We are back to one category */ - $cats = $document->getCategories(); - $this->assertIsArray($cats); - $this->assertCount(1, $cats); - - /* Remove the remaining category from the document */ - $ret = $document->removeCategories($cats); - $this->assertTrue($ret); - - /* No category left */ - $cats = $document->getCategories(); - $this->assertIsArray($cats); - $this->assertCount(0, $cats); - - /* Remove the category itself */ - $cats = self::$dms->getDocumentCategories(); - $this->assertIsArray($cats); - $this->assertCount(2, $cats); - $ret = $cat1->remove(); - $cats = self::$dms->getDocumentCategories(); - $this->assertIsArray($cats); - $this->assertCount(1, $cats); - } - - /** - * Test method getCategories() with sql fail - * - * @return void - */ - public function testGetCategoriesSqlFail() - { - $document = $this->getMockedDocument(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblCategory` WHERE")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $document->setDMS($dms); - $this->assertFalse($document->getCategories()); - } - - /** - * Test method addCategories() with sql fail - * - * @return void - */ - public function testAddCategoriesSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - /* mock sql statement in getCategories() which is called in addCategories() */ - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblCategory` WHERE")) - ->willReturn([]); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("INSERT INTO `tblDocumentCategory`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $document = $this->getMockedDocument(); - $document->setDMS($dms); - $cat = new SeedDMS_Core_DocumentCategory(1, 'Category'); - $cat->setDMS($dms); - $this->assertFalse($document->addCategories([$cat])); - } - - /** - * Test method removeCategories() with sql fail - * - * @return void - */ - public function testRemoveCategoriesSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("DELETE FROM `tblDocumentCategory` WHERE")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $document = $this->getMockedDocument(); - $document->setDMS($dms); - $cat = new SeedDMS_Core_DocumentCategory(1, 'Category'); - $cat->setDMS($dms); - $this->assertFalse($document->removeCategories([$cat])); - } - - /** - * Test method setCategories() with sql fail when deleting categories - * - * @return void - */ - public function testSetCategoriesSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("DELETE FROM `tblDocumentCategory` WHERE")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $document = $this->getMockedDocument(); - $document->setDMS($dms); - $cat = new SeedDMS_Core_DocumentCategory(1, 'Category'); - $cat->setDMS($dms); - $this->assertFalse($document->setCategories([$cat])); - } - - /** - * Test method setCategories() with sql fail when inserting new categories - * - * @return void - */ - public function testSetCategoriesSqlFail2() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->exactly(2)) - ->method('getResult') - ->will( - $this->returnValueMap( - array( - array("DELETE FROM `tblDocumentCategory` WHERE `documentID` = 1", true, true), - array("INSERT INTO `tblDocumentCategory`", true, false) - ) - ) - ); - $dms = new SeedDMS_Core_DMS($db, ''); - $document = $this->getMockedDocument(); - $document->setDMS($dms); - $cat = new SeedDMS_Core_DocumentCategory(1, 'Category'); - $cat->setDMS($dms); - $this->assertFalse($document->setCategories([$cat])); - } - -} - diff --git a/SeedDMS_Core/tests/DocumentContentTest.php b/SeedDMS_Core/tests/DocumentContentTest.php deleted file mode 100644 index 9a8e9a14b..000000000 --- a/SeedDMS_Core/tests/DocumentContentTest.php +++ /dev/null @@ -1,593 +0,0 @@ - - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version @package_version@ - * @link https://www.seeddms.org - */ - -use PHPUnit\Framework\SeedDmsTest; - -/** - * Group test class - * - * @category SeedDMS - * @package Tests - * @author Uwe Steinmann - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version Release: @package_version@ - * @link https://www.seeddms.org - */ -class DocumentContentTest extends SeedDmsTest -{ - - /** - * Create a real sqlite database in memory - * - * @return void - */ - protected function setUp(): void - { - self::$dbh = self::createInMemoryDatabase(); - self::$contentdir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'phpunit-'.time(); - mkdir(self::$contentdir); - // echo "Creating temp content dir: ".self::$contentdir."\n"; - self::$dms = new SeedDMS_Core_DMS(self::$dbh, self::$contentdir); - } - - /** - * Clean up at tear down - * - * @return void - */ - protected function tearDown(): void - { - self::$dbh = null; - // echo "\nRemoving temp. content dir: ".self::$contentdir."\n"; - exec('rm -rf '.self::$contentdir); - } - - /** - * Test method getContent(), getContentByVersion(), getLatestContent() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetContent() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - /* Add a new document */ - $document = self::createDocument($rootfolder, $user, 'Document 1'); - $this->assertIsObject($document); - $lcontent = $document->getLatestContent(); - $this->assertIsObject($lcontent); - $version = $document->getContentByVersion(1); - $this->assertIsObject($version); - $this->assertEquals($version->getId(), $lcontent->getId()); - $content = $document->getContent(); - $this->assertIsArray($content); - $this->assertCount(1, $content); - $this->assertEquals($version->getId(), $content[0]->getId()); - } - - /** - * Test method getContent() mit sql fail - * - * @return void - */ - public function testGetContentSqlFail() - { - $document = $this->getMockedDocument(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblDocumentContent` WHERE `document` ")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $document->setDMS($dms); - $this->assertFalse($document->getContent()); - } - - /** - * Test method getContentByVersion() mit sql fail - * - * @return void - */ - public function testGetContentByVersionSqlFail() - { - $document = $this->getMockedDocument(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblDocumentContent` WHERE `document` ")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $document->setDMS($dms); - $this->assertFalse($document->getContentByVersion(1)); - } - - /** - * Test method getLatestContent() mit sql fail - * - * @return void - */ - public function testGetLatestContentSqlFail() - { - $document = $this->getMockedDocument(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblDocumentContent` WHERE `document` ")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $document->setDMS($dms); - $this->assertFalse($document->getLatestContent()); - } - - /** - * Test method removeContent() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testRemoveContent() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - /* Add a new document */ - $document = self::createDocument($rootfolder, $user, 'Document 1'); - $this->assertIsObject($document); - $lcontent = $document->getLatestContent(); - $this->assertIsObject($lcontent); - - /* Removing the only version will fail */ - $ret = $document->removeContent($lcontent); - $this->assertFalse($ret); - - /* Add a new version */ - $filename = self::createTempFile(300); - $result = $document->addContent('', $user, $filename, 'file2.txt', '.txt', 'text/plain'); - $this->assertTrue(SeedDMS_Core_File::removeFile($filename)); - $this->assertIsObject($result); - $this->assertIsObject($result->getContent()); - - /* Second trial to remove a version. Now it succeeds because it is not - * the last version anymore. - */ - $ret = $document->removeContent($lcontent); - $this->assertTrue($ret); - - /* The latest version is now version 2 */ - $lcontent = $document->getLatestContent(); - $this->assertIsObject($lcontent); - $this->assertEquals(2, $lcontent->getVersion()); - - /* There is only 1 version left */ - $contents = $document->getContent(); - $this->assertIsArray($contents); - $this->assertCount(1, $contents); - } - - /** - * Test method isType() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testIsType() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - /* Add a new document */ - $document = self::createDocument($rootfolder, $user, 'Document 1'); - $this->assertIsObject($document); - $lcontent = $document->getLatestContent(); - $this->assertIsObject($lcontent); - $ret = $lcontent->isType('documentcontent'); - $this->assertTrue($ret); - } - - /** - * Test method getUser(), getDocument() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testVarious() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - /* Add a new document */ - $document = self::createDocument($rootfolder, $user, 'Document 1'); - $this->assertIsObject($document); - $lcontent = $document->getLatestContent(); - $this->assertIsObject($lcontent); - $ret = $lcontent->isType('documentcontent'); - $this->assertTrue($ret); - $doc = $lcontent->getDocument(); - $this->assertEquals($document->getId(), $doc->getId()); - $u = $lcontent->getUser(); - $this->assertEquals($user->getId(), $u->getId()); - $filetype = $lcontent->getFileType(); - $this->assertEquals('.txt', $filetype); - $origfilename = $lcontent->getOriginalFileName(); - $this->assertEquals('file1.txt', $origfilename); - } - - /** - * Test method getComment(), setComment() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetComment() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - /* Add a new document */ - $document = self::createDocument($rootfolder, $user, 'Document 1'); - $this->assertIsObject($document); - $lcontent = $document->getLatestContent(); - $this->assertIsObject($lcontent); - $comment = $lcontent->getComment(); - $this->assertEquals('', $comment); - $ret = $lcontent->setComment('Document content comment'); - $this->assertTrue($ret); - /* Retrieve the document content from the database again */ - $content = self::$dms->getDocumentContent($lcontent->getId()); - $comment = $content->getComment(); - $this->assertEquals('Document content comment', $comment); - } - - /** - * Test method getDate(), setDate() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetDate() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - /* Add a new document */ - $document = self::createDocument($rootfolder, $user, 'Document 1'); - $this->assertIsObject($document); - $lcontent = $document->getLatestContent(); - $this->assertIsObject($lcontent); - $date = $lcontent->getDate(); - $this->assertIsInt($date); - $this->assertGreaterThanOrEqual(time(), $date); - - /* Set date as timestamp */ - $ret = $lcontent->setDate($date-1000); - $this->assertTrue($ret); - /* Retrieve the document content from the database again */ - $content = self::$dms->getDocumentContent($lcontent->getId()); - $newdate = $content->getDate(); - $this->assertEquals($date-1000, $newdate); - - /* Set date in Y-m-d H:i:s format */ - $date = time()-500; - $ret = $lcontent->setDate(date('Y-m-d H:i:s', $date)); - $this->assertTrue($ret); - /* Retrieve the document content from the database again */ - $content = self::$dms->getDocumentContent($lcontent->getId()); - $newdate = $content->getDate(); - $this->assertEquals($date, $newdate); - - /* Not passing a date will set the current date/time */ - $date = time(); - $ret = $lcontent->setDate(); - $this->assertTrue($ret); - /* Retrieve the document content from the database again */ - $content = self::$dms->getDocumentContent($lcontent->getId()); - $newdate = $content->getDate(); - $this->assertEquals($date, $newdate); - } - - /** - * Test method getFileSize(), setFileSize() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetFileSize() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - /* Add a new document */ - $document = self::createDocument($rootfolder, $user, 'Document 1', 200); - $this->assertIsObject($document); - $lcontent = $document->getLatestContent(); - $this->assertIsObject($lcontent); - $filesize = $lcontent->getFileSize(); - $this->assertEquals(200, $filesize); - - /* Intentially corrupt the file size */ - $db = self::$dms->getDb(); - $ret = $db->getResult("UPDATE `tblDocumentContent` SET `fileSize` = 300 WHERE `document` = " . $document->getID() . " AND `version` = " . $lcontent->getVersion()); - $this->assertTrue($ret); - - $corcontent = self::$dms->getDocumentContent($lcontent->getId()); - $filesize = $corcontent->getFileSize(); - $this->assertEquals(300, $filesize); - - /* Repair filesize by calling setFileSize() */ - $ret = $corcontent->setFileSize(); - $this->assertTrue($ret); - $filesize = $corcontent->getFileSize(); - $this->assertEquals(200, $filesize); - } - - /** - * Test method getChecksum(), setChecksum() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetChecksum() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - /* Add a new document */ - $document = self::createDocument($rootfolder, $user, 'Document 1', 200); - $this->assertIsObject($document); - $lcontent = $document->getLatestContent(); - $this->assertIsObject($lcontent); - $orgchecksum = $lcontent->getChecksum(); - $this->assertIsString($orgchecksum); - $this->assertEquals(32, strlen($orgchecksum)); - - /* Intentially corrupt the checksum */ - $db = self::$dms->getDb(); - $ret = $db->getResult("UPDATE `tblDocumentContent` SET `checksum` = 'foobar' WHERE `document` = " . $document->getID() . " AND `version` = " . $lcontent->getVersion()); - $this->assertTrue($ret); - - $corcontent = self::$dms->getDocumentContent($lcontent->getId()); - $checksum = $corcontent->getChecksum(); - $this->assertEquals('foobar', $checksum); - - /* Repair filesize by calling setChecksum() */ - $ret = $corcontent->setChecksum(); - $this->assertTrue($ret); - $checksum = $corcontent->getChecksum(); - $this->assertEquals($orgchecksum, $checksum); - } - - /** - * Test method getStatus(), setStatus(), getStatusLog() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetStatus() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - /* Add a new document */ - $document = self::createDocument($rootfolder, $user, 'Document 1', 200); - $this->assertIsObject($document); - $lcontent = $document->getLatestContent(); - $this->assertIsObject($lcontent); - - $status = $lcontent->getStatus(); - $this->assertIsArray($status); - $this->assertEquals(S_RELEASED, $status['status']); - - $statuslog = $lcontent->getStatusLog(); - $this->assertIsArray($statuslog); - $this->assertCount(1, $statuslog); - - /* Missing update user returns false */ - $ret = $lcontent->setStatus(S_OBSOLETE, '', null); - $this->assertFalse($ret); - - /* A status out of range returns false */ - $ret = $lcontent->setStatus(9, '', $user); - $this->assertFalse($ret); - - /* A wrong date returns false */ - $ret = $lcontent->setStatus(S_OBSOLETE, '', $user, '2021-02-29 10:10:10'); - $this->assertFalse($ret); - - $ret = $lcontent->setStatus(S_OBSOLETE, 'No longer valid', $user, date('Y-m-d H:i:s')); - $status = $lcontent->getStatus(); - $this->assertIsArray($status); - $this->assertEquals(S_OBSOLETE, $status['status']); - - /* Status log has now 2 entries */ - $statuslog = $lcontent->getStatusLog(); - $this->assertIsArray($statuslog); - $this->assertCount(2, $statuslog); - - /* Add the 'onSetStatus' callback */ - $callret = ''; - $callback = function ($param, $content, $updateuser, $oldstatus, $newstatus) use (&$callret) { - $callret = $oldstatus.' to '.$newstatus; - return $param; - }; - /* Because the callback will return false, the status will not be set */ - self::$dms->setCallback('onSetStatus', $callback, false); - /* Trying to go back to status released with a callback returning false */ - $ret = $lcontent->setStatus(S_RELEASED, 'Valid again', $user); - $status = $lcontent->getStatus(); - $this->assertIsArray($status); - /* Status is still S_OBSOLETE because the callback returned false */ - $this->assertEquals(S_OBSOLETE, $status['status']); - $this->assertEquals(S_OBSOLETE.' to '.S_RELEASED, $callret); - - /* Do it again, but this time the callback returns true */ - self::$dms->setCallback('onSetStatus', $callback, true); - /* Trying to go back to status released with a callback returning true */ - $ret = $lcontent->setStatus(S_RELEASED, 'Valid again', $user); - $status = $lcontent->getStatus(); - $this->assertIsArray($status); - /* Status updated to S_RELEASED because the callback returned true */ - $this->assertEquals(S_RELEASED, $status['status']); - $this->assertEquals(S_OBSOLETE.' to '.S_RELEASED, $callret); - - /* Status log has now 3 entries */ - $statuslog = $lcontent->getStatusLog(); - $this->assertIsArray($statuslog); - $this->assertCount(3, $statuslog); - - /* Get just the last entry */ - $statuslog = $lcontent->getStatusLog(1); - $this->assertIsArray($statuslog); - $this->assertCount(1, $statuslog); - $this->assertEquals('Valid again', $statuslog[0]['comment']); - } - - /** - * Test method getMimeType(), setMimeType() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetMimeType() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - /* Add a new document */ - $document = self::createDocument($rootfolder, $user, 'Document 1', 200); - $this->assertIsObject($document); - $lcontent = $document->getLatestContent(); - $this->assertIsObject($lcontent); - - $ret = $lcontent->setMimeType('text/csv'); - $this->assertTrue($ret); - - /* Retrieve the document content from the database again */ - $content = self::$dms->getDocumentContent($lcontent->getId()); - $this->assertIsObject($content); - $this->assertEquals('text/csv', $content->getMimeType()); - } - - /** - * Test method getFileType(), setFileType() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetFileType() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - /* Add a new document */ - $document = self::createDocument($rootfolder, $user, 'Document 1', 200); - $this->assertIsObject($document); - $lcontent = $document->getLatestContent(); - $this->assertIsObject($lcontent); - - $ret = $lcontent->setMimeType('text/css'); - $this->assertTrue($ret); - - $ret = $lcontent->setFileType(); - $this->assertTrue($ret); - - /* Retrieve the document content from the database again */ - $content = self::$dms->getDocumentContent($lcontent->getId()); - $this->assertIsObject($content); - $this->assertEquals('.css', $content->getFileType()); - - /* Also get the file content to ensure the renaming of the file - * on disc has succeeded. - */ - $c = file_get_contents(self::$dms->contentDir.$lcontent->getPath()); - $this->assertEquals(200, strlen($c)); - } - - /** - * Test method replaceContent() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testReplaceContent() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - $guest = self::$dms->getUser(2); - /* Add a new document */ - $document = self::createDocument($rootfolder, $user, 'Document 1', 200); - $this->assertIsObject($document); - $lcontent = $document->getLatestContent(); - $this->assertIsObject($lcontent); - - $filename = self::createTempFile(300); - /* Not using the same user yields an error */ - $ret = $document->replaceContent(1, $guest, $filename, 'file1.txt', '.txt', 'text/plain'); - $this->assertFalse($ret); - /* Not using the same orig. file name yields an error */ - $ret = $document->replaceContent(1, $user, $filename, 'file2.txt', '.txt', 'text/plain'); - $this->assertFalse($ret); - /* Not using the same file type yields an error */ - $ret = $document->replaceContent(1, $user, $filename, 'file1.txt', '.csv', 'text/plain'); - $this->assertFalse($ret); - /* Not using the same mime type yields an error */ - $ret = $document->replaceContent(1, $user, $filename, 'file1.txt', '.txt', 'text/csv'); - $this->assertFalse($ret); - - /* Setting version to 0 will replace the latest version */ - $ret = $document->replaceContent(0, $user, $filename, 'file1.txt', '.txt', 'text/plain'); - $this->assertTrue($ret); - - $this->assertTrue(SeedDMS_Core_File::removeFile($filename)); - - /* Retrieve the document content from the database again */ - $newcontent = $document->getLatestContent(); - $this->assertIsObject($newcontent); - $this->assertEquals('text/plain', $newcontent->getMimeType()); - /* File size has grown from 200 to 300 bytes */ - $filesize = $newcontent->getFileSize(); - $this->assertEquals(300, $filesize); - /* Still version 1 */ - $version = $newcontent->getVersion(); - $this->assertEquals(1, $version); - } - - /** - * Test method replaceContent() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAccessMode() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - $guest = self::$dms->getUser(2); - /* Add a new document */ - $document = self::createDocument($rootfolder, $user, 'Document 1', 200); - $this->assertIsObject($document); - $lcontent = $document->getLatestContent(); - $this->assertIsObject($lcontent); - - /* Access rights on a document content are always M_READ unless the callback - * onCheckAccessDocumentContent is implemented */ - $mode = $lcontent->getAccessMode($user); - $this->assertEquals(M_READ, $mode); - } -} diff --git a/SeedDMS_Core/tests/DocumentFileTest.php b/SeedDMS_Core/tests/DocumentFileTest.php deleted file mode 100644 index 95d758c56..000000000 --- a/SeedDMS_Core/tests/DocumentFileTest.php +++ /dev/null @@ -1,290 +0,0 @@ - - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version @package_version@ - * @link https://www.seeddms.org - */ - -use PHPUnit\Framework\SeedDmsTest; - -/** - * Group test class - * - * @category SeedDMS - * @package Tests - * @author Uwe Steinmann - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version Release: @package_version@ - * @link https://www.seeddms.org - */ -class DocumentFileTest extends SeedDmsTest -{ - - /** - * Create a real sqlite database in memory - * - * @return void - */ - protected function setUp(): void - { - self::$dbh = self::createInMemoryDatabase(); - self::$contentdir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'phpunit-'.time(); - mkdir(self::$contentdir); - // echo "Creating temp content dir: ".self::$contentdir."\n"; - self::$dms = new SeedDMS_Core_DMS(self::$dbh, self::$contentdir); - self::$dbversion = self::$dms->getDBVersion(); - } - - /** - * Clean up at tear down - * - * @return void - */ - protected function tearDown(): void - { - self::$dbh = null; - // echo "\nRemoving temp. content dir: ".self::$contentdir."\n"; - exec('rm -rf '.self::$contentdir); - } - - /** - * Test method getInstance() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetMockedDocumentFile() - { - $user = self::getMockedUser(); - $document1 = self::getMockedDocument(1, 'Document 1'); - $file = new SeedDMS_Core_DocumentFile(1, $document1, $user->getId(), 'comment', time(), '', '.txt', 'text/plain', 'test.txt', 'name', 1, true); - $this->assertIsObject($file); - $this->assertTrue($file->isType('documentfile')); - - $document = $file->getDocument(); - $this->assertIsObject($document); - $this->assertTrue($document->isType('document')); - $this->assertEquals('Document 1', $document->getName()); - - $ispublic = $file->isPublic(); - $this->assertTrue($ispublic); - - $comment = $file->getComment(); - $this->assertEquals('comment', $comment); - - $filetype = $file->getFileType(); - $this->assertEquals('.txt', $filetype); - - $mimetype = $file->getMimeType(); - $this->assertEquals('text/plain', $mimetype); - - $name = $file->getName(); - $this->assertEquals('name', $name); - - $origfilename = $file->getOriginalFileName(); - $this->assertEquals('test.txt', $origfilename); - - $version = $file->getVersion(); - $this->assertEquals(1, $version); - - $accessmode = $file->getAccessMode($user); - $this->assertEquals(M_READ, $accessmode); - } - - /** - * Test method setComment() mit sql fail - * - * @return void - */ - public function testSetCommentSqlFail() - { - $user = self::getMockedUser(); - $document = $this->getMockedDocument(); - $file = new SeedDMS_Core_DocumentFile(1, $document, $user->getId(), 'comment', time(), '', '.txt', 'text/plain', 'test.txt', 'name', 1, true); - $this->assertIsObject($file); - $this->assertTrue($file->isType('documentfile')); - - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblDocumentFiles` SET `comment`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $document->setDMS($dms); - $this->assertFalse($file->setComment('my comment')); - } - - /** - * Test method setName() mit sql fail - * - * @return void - */ - public function testSetNameSqlFail() - { - $user = self::getMockedUser(); - $document = $this->getMockedDocument(); - $file = new SeedDMS_Core_DocumentFile(1, $document, $user->getId(), 'comment', time(), '', '.txt', 'text/plain', 'test.txt', 'name', 1, true); - $this->assertIsObject($file); - $this->assertTrue($file->isType('documentfile')); - - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblDocumentFiles` SET `name`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $document->setDMS($dms); - $this->assertFalse($file->setName('my name')); - } - - /** - * Test method setDate() mit sql fail - * - * @return void - */ - public function testSetDateSqlFail() - { - $user = self::getMockedUser(); - $document = $this->getMockedDocument(); - $file = new SeedDMS_Core_DocumentFile(1, $document, $user->getId(), 'comment', time(), '', '.txt', 'text/plain', 'test.txt', 'name', 1, true); - $this->assertIsObject($file); - $this->assertTrue($file->isType('documentfile')); - - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblDocumentFiles` SET `date`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $document->setDMS($dms); - $this->assertFalse($file->setDate()); - } - - /** - * Test method setVersion() mit sql fail - * - * @return void - */ - public function testSetVersionSqlFail() - { - $user = self::getMockedUser(); - $document = $this->getMockedDocument(); - $file = new SeedDMS_Core_DocumentFile(1, $document, $user->getId(), 'comment', time(), '', '.txt', 'text/plain', 'test.txt', 'name', 1, true); - $this->assertIsObject($file); - $this->assertTrue($file->isType('documentfile')); - - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblDocumentFiles` SET `version`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $document->setDMS($dms); - $this->assertFalse($file->setVersion(1)); - } - - /** - * Test method setPublic() mit sql fail - * - * @return void - */ - public function testSetPublicnSqlFail() - { - $user = self::getMockedUser(); - $document = $this->getMockedDocument(); - $file = new SeedDMS_Core_DocumentFile(1, $document, $user->getId(), 'comment', time(), '', '.txt', 'text/plain', 'test.txt', 'name', 1, true); - $this->assertIsObject($file); - $this->assertTrue($file->isType('documentfile')); - - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblDocumentFiles` SET `public`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $document->setDMS($dms); - $this->assertFalse($file->setPublic(true)); - } - - /** - * Test method addDocumentFile(), getDocumentFile() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testAddDocumentFile() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - $document = self::createDocument($rootfolder, $user, 'Document 1'); - $this->assertIsObject($document); - $tmpfile = self::createTempFile(); - $file = $document->addDocumentFile('attachment.txt', 'comment', $user, $tmpfile, 'attachment.txt', '.txt', 'text/plain', 0, true); - $this->assertTrue(SeedDMS_Core_File::removeFile($tmpfile)); - $this->assertIsObject($file); - $this->assertTrue($file->isType('documentfile')); - - $files = $document->getDocumentFiles(); - $this->assertIsArray($files); - $this->assertCount(1, $files); - - $file = $files[0]; - - $document = $file->getDocument(); - $this->assertIsObject($document); - $this->assertTrue($document->isType('document')); - $this->assertEquals('Document 1', $document->getName()); - - $ispublic = $file->isPublic(); - $this->assertTrue($ispublic); - - $luser = $file->getUser(); - $this->assertIsObject($luser); - $this->assertTrue($luser->isType('user')); - - $ret = $file->setComment('new comment'); - $this->assertTrue($ret); - $comment = $file->getComment(); - $this->assertEquals('new comment', $comment); - - $ret = $file->setName('new name'); - $this->assertTrue($ret); - $name = $file->getName(); - $this->assertEquals('new name', $name); - - $now = time(); - $ret = $file->setDate($now); - $this->assertTrue($ret); - $date = $file->getDate(); - $this->assertEquals($now, $date); - - $ret = $file->setDate('fail'); - $this->assertFalse($ret); - - $ret = $file->setVersion(2); - $this->assertTrue($ret); - $version = $file->getVersion(); - $this->assertEquals(2, $version); - - $ret = $file->setVersion('fail'); - $this->assertFalse($ret); - - $ret = $file->setPublic(true); - $this->assertTrue($ret); - $ispublic = $file->isPublic(); - $this->assertEquals(1, $ispublic); - - - } -} diff --git a/SeedDMS_Core/tests/DocumentLinkTest.php b/SeedDMS_Core/tests/DocumentLinkTest.php deleted file mode 100644 index d646607e9..000000000 --- a/SeedDMS_Core/tests/DocumentLinkTest.php +++ /dev/null @@ -1,125 +0,0 @@ - - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version @package_version@ - * @link https://www.seeddms.org - */ - -use PHPUnit\Framework\SeedDmsTest; - -/** - * Group test class - * - * @category SeedDMS - * @package Tests - * @author Uwe Steinmann - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version Release: @package_version@ - * @link https://www.seeddms.org - */ -class DocumentLinkTest extends SeedDmsTest -{ - - /** - * Create a real sqlite database in memory - * - * @return void - */ - protected function setUp(): void - { - self::$dbh = self::createInMemoryDatabase(); - self::$contentdir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'phpunit-'.time(); - mkdir(self::$contentdir); - // echo "Creating temp content dir: ".self::$contentdir."\n"; - self::$dms = new SeedDMS_Core_DMS(self::$dbh, self::$contentdir); - self::$dbversion = self::$dms->getDBVersion(); - } - - /** - * Clean up at tear down - * - * @return void - */ - protected function tearDown(): void - { - self::$dbh = null; - // echo "\nRemoving temp. content dir: ".self::$contentdir."\n"; - exec('rm -rf '.self::$contentdir); - } - - /** - * Test method getInstance() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetMockedDocumentLink() - { - $user = self::getMockedUser(); - $document1 = self::getMockedDocument(1, 'Document 1'); - $document2 = self::getMockedDocument(2, 'Document 2'); - $link = new SeedDMS_Core_DocumentLink(1, $document1, $document2, $user, true); - $this->assertIsObject($link); - $this->assertTrue($link->isType('documentlink')); - - $document = $link->getDocument(); - $this->assertIsObject($document); - $this->assertTrue($document->isType('document')); - $this->assertEquals('Document 1', $document->getName()); - - $document = $link->getTarget(); - $this->assertIsObject($document); - $this->assertTrue($document->isType('document')); - $this->assertEquals('Document 2', $document->getName()); - - $ispublic = $link->isPublic(); - $this->assertTrue($ispublic); - } - - /** - * Test method addDocumentLink(), getDocumentLink() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testAddDocumentLink() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - $document1 = self::createDocument($rootfolder, $user, 'Document 1'); - $this->assertIsObject($document1); - $document2 = self::createDocument($rootfolder, $user, 'Document 2'); - $this->assertIsObject($document2); - $link = $document1->addDocumentLink($document2->getId(), $user->getId(), true); - $this->assertIsObject($link); - $this->assertTrue($link->isType('documentlink')); - - $document = $link->getDocument(); - $this->assertIsObject($document); - $this->assertTrue($document->isType('document')); - $this->assertEquals('Document 1', $document->getName()); - - $document = $link->getTarget(); - $this->assertIsObject($document); - $this->assertTrue($document->isType('document')); - $this->assertEquals('Document 2', $document->getName()); - - $ispublic = $link->isPublic(); - $this->assertTrue($ispublic); - - $luser = $link->getUser(); - $this->assertIsObject($luser); - $this->assertTrue($luser->isType('user')); - } -} diff --git a/SeedDMS_Core/tests/DocumentTest.php b/SeedDMS_Core/tests/DocumentTest.php deleted file mode 100644 index 5331f367d..000000000 --- a/SeedDMS_Core/tests/DocumentTest.php +++ /dev/null @@ -1,1323 +0,0 @@ - - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version @package_version@ - * @link https://www.seeddms.org - */ - -use PHPUnit\Framework\SeedDmsTest; - -/** - * Group test class - * - * @category SeedDMS - * @package Tests - * @author Uwe Steinmann - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version Release: @package_version@ - * @link https://www.seeddms.org - */ -class DocumentTest extends SeedDmsTest -{ - - /** - * Create a real sqlite database in memory - * - * @return void - */ - protected function setUp(): void - { - self::$dbh = self::createInMemoryDatabase(); - self::$contentdir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'phpunit-'.time(); - mkdir(self::$contentdir); - // echo "Creating temp content dir: ".self::$contentdir."\n"; - self::$dms = new SeedDMS_Core_DMS(self::$dbh, self::$contentdir); - self::$dbversion = self::$dms->getDBVersion(); - } - - /** - * Clean up at tear down - * - * @return void - */ - protected function tearDown(): void - { - self::$dbh = null; - // echo "\nRemoving temp. content dir: ".self::$contentdir."\n"; - exec('rm -rf '.self::$contentdir); - } - - /** - * Test method getInstance() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetInstance() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - /* Add a new document */ - $document = self::createDocument($rootfolder, $user, 'Document 1'); - /* Get the document with id 1, which must be 'Document 1' */ - $document = SeedDMS_Core_Document::getInstance(1, self::$dms); - $this->assertIsObject($document); - $this->assertTrue($document->isType('document')); - $this->assertEquals('Document 1', $document->getName()); - /* Get a none existing document */ - $document = SeedDMS_Core_Document::getInstance(2, self::$dms); - $this->assertNull($document); - } - - /** - * Test method getInstance() within a root folder - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetInstanceWithinRoot() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - /* The simple folder structure will create to subfolders, each - * with 15 documents. - */ - self::createSimpleFolderStructureWithDocuments(); - $subfolder = self::$dms->getFolderByName('Subfolder 1'); - /* Get a document in Subfolder 1 */ - $document1 = self::$dms->getDocumentByName('Document 1-1'); - /* Get a document in Subfolder 2 */ - $document2 = self::$dms->getDocumentByName('Document 2-1'); - - /* Getting a document in subfolder 1 without any restrictions must succeed */ - $document = SeedDMS_Core_Document::getInstance($document1->getId(), self::$dms); - $this->assertIsObject($document); - $this->assertTrue($document->isType('document')); - - /* Make Subfolder 1 the root folder */ - self::$dms->checkWithinRootDir = true; - self::$dms->setRootFolderID($subfolder->getId()); - - /* Getting a document by id in subfolder 1 still must succeed */ - $document = SeedDMS_Core_Document::getInstance($document1->getId(), self::$dms); - $this->assertIsObject($document); - $this->assertTrue($document->isType('document')); - - /* Getting a document by id in subfolder 2 must fail */ - $document = SeedDMS_Core_Document::getInstance($document2->getId(), self::$dms); - $this->assertNull($document); - - /* Get a document in Subfolder 1 */ - $document = self::$dms->getDocumentByName('Document 1-1'); - $this->assertIsObject($document); - $this->assertTrue($document->isType('document')); - - /* Get a document in Subfolder 2 */ - $document = self::$dms->getDocumentByName('Document 2-1'); - $this->assertNull($document); - } - - /** - * Test method getInstance() - * - * @return void - */ - public function testGetInstanceSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT `tblDocuments`.*, `tblDocumentLocks`.`userID` as `lock` FROM `tblDocuments`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $this->assertFalse(SeedDMS_Core_Document::getInstance(1, $dms)); - } - - /** - * Test method getDir() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetDir() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - /* Add a new document */ - $document = self::createDocument($rootfolder, $user, 'Document 1'); - $this->assertIsObject($document); - $this->assertEquals('1/', $document->getDir()); - } - - /** - * Test method getComment() and setComment() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetComment() - { - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $user = self::$dms->getUser(1); - $document = self::createDocument($folder, $user, 'Document 1'); - $this->assertIsObject($document); - $comment = $document->getComment(); - $this->assertEquals('', $comment); - $ret = $document->setComment('foo'); - $this->assertTrue($ret); - $comment = $document->getComment(); - $this->assertEquals('foo', $comment); - } - - /** - * Test method setComment() mit sql fail - * - * @return void - */ - public function testSetCommentSqlFail() - { - $document = $this->getMockedDocument(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblDocuments` SET `comment`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $document->setDMS($dms); - $this->assertFalse($document->setComment('my comment')); - } - - /** - * Test method getKeywords() and setKeywords() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetKeywords() - { - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $user = self::$dms->getUser(1); - $document = self::createDocument($folder, $user, 'Document 1'); - $this->assertIsObject($document); - $keywords = $document->getKeywords(); - $this->assertEquals('', $keywords); - $ret = $document->setKeywords('foo bar'); - $this->assertTrue($ret); - $keywords = $document->getKeywords(); - $this->assertEquals('foo bar', $keywords); - } - - /** - * Test method setKeywords() mit sql fail - * - * @return void - */ - public function testSetKeywordsSqlFail() - { - $document = $this->getMockedDocument(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblDocuments` SET `keywords`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $document->setDMS($dms); - $this->assertFalse($document->setKeywords('keywords')); - } - - /** - * Test method getName() and setName() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetName() - { - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $user = self::$dms->getUser(1); - $document = self::createDocument($folder, $user, 'Document 1'); - $this->assertIsObject($document); - $name = $document->getName(); - $this->assertEquals('Document 1', $name); - $ret = $document->setName('foo'); - $this->assertTrue($ret); - $name = $document->getName(); - $this->assertEquals('foo', $name); - } - - /** - * Test method setName() mit sql fail - * - * @return void - */ - public function testSetNameSqlFail() - { - $document = $this->getMockedDocument(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblDocuments` SET `name`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $document->setDMS($dms); - $this->assertFalse($document->setName('my name')); - } - - /** - * Test method getDate() and setDate() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetDate() - { - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $user = self::$dms->getUser(1); - $document = self::createDocument($folder, $user, 'Document 1'); - $now = time(); - /* Passing false as a time stamp will take current time stamp */ - $ret = $document->setDate(false); - $this->assertTrue($ret); - $date = $document->getDate(); - $this->assertEquals($now, $date); - /* Setting a time stamp */ - $now -= 1000; - $ret = $document->setDate($now); - $this->assertTrue($ret); - $date = $document->getDate(); - $this->assertEquals($now, $date); - /* Setting a none numeric value will fail */ - $ret = $document->setDate('foo'); - $this->assertFalse($ret); - } - - /** - * Test method setDate() with sql fail - * - * @return void - */ - public function testSetDateSqlFail() - { - $document = $this->getMockedDocument(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblDocuments` SET `date` = ")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $document->setDMS($dms); - $this->assertFalse($document->setDate(null)); - } - - /** - * Test method getDefaultAccess() and setDefaultAccess() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetDefaultAccess() - { - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $user = self::$dms->getUser(1); - $document = self::createDocument($folder, $user, 'Document 1'); - $this->assertIsObject($document); - $this->assertTrue($document->isType('document')); - $defaultaccess = $document->getDefaultAccess(); - $this->assertEquals(M_READ, $defaultaccess); - - /* Setting a default access out of range yields an error */ - $ret = $document->setDefaultAccess(0, true); - $this->assertFalse($ret); - - /* Setting a default access out of range yields an error */ - $ret = $document->setDefaultAccess(M_ALL+1, true); - $this->assertFalse($ret); - - /* Setting the default access will have no effect as long as access - * rights are inherited. */ - $ret = $document->setDefaultAccess(M_READWRITE, true); - $this->assertTrue($ret); - $defaultaccess = $document->getDefaultAccess(); - $this->assertEquals(M_READ, $defaultaccess); - - /* Once inheritance of access rights is turned off, the previously - * set default access right will take effect. */ - $ret = $document->setInheritAccess(false, true); - $this->assertTrue($ret); - $defaultaccess = $document->getDefaultAccess(); - $this->assertEquals(M_READWRITE, $defaultaccess); - - /* Also check if inherited access was turned off */ - $ret = $document->getInheritAccess(); - $this->assertFalse($ret); - } - - /** - * Test method setDefaultAccess() mit sql fail - * - * @return void - */ - public function testSetDefaultAccessSqlFail() - { - $document = $this->getMockedDocument(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblDocuments` SET `defaultAccess`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $document->setDMS($dms); - $this->assertFalse($document->setDefaultAccess(M_READ)); - } - - /** - * Test method setInheritAccess() mit sql fail - * - * @return void - */ - public function testSetInheritAccessSqlFail() - { - $document = $this->getMockedDocument(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblDocuments` SET `inheritAccess`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $document->setDMS($dms); - $this->assertFalse($document->setInheritAccess(0)); - } - - /** - * Test method addAccess(), removeAccess(), changeAccess(), getAccessList() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetAccess() - { - self::createGroupsAndUsers(); - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $adminuser = self::$dms->getUser(1); - $guestuser = self::$dms->getUser(2); - $user = self::$dms->getUserByLogin('user-1-1'); - $this->assertIsObject($user); - $this->assertTrue($user->isType('user')); - $group = self::$dms->getGroupByName('Group 1'); - $this->assertIsObject($group); - $this->assertTrue($group->isType('group')); - $document = self::createDocument($folder, $adminuser, 'Document 1'); - $this->assertIsObject($document); - $this->assertTrue($document->isType('document')); - $defaultaccess = $document->getDefaultAccess(); - $this->assertEquals(M_READ, $defaultaccess); - - /* Turn off inheritance, otherwise the access rights have no effect */ - $ret = $document->setInheritAccess(false, true); - $this->assertTrue($ret); - - /* Retrieving an access mode without a valid user will always return M_NONE */ - $mode = $document->getAccessMode(null); - $this->assertEquals(M_NONE, $mode); - - /* The admin user has always unlimited access */ - $mode = $document->getAccessMode($adminuser); - $this->assertEquals(M_ALL, $mode); - - /* Without setting any specific access, the document has a default mode M_READ */ - $mode = $document->getAccessMode($user); - $this->assertEquals(M_READ, $mode); - - /* Access mode for group is also the default access */ - $mode = $document->getGroupAccessMode($group); - $this->assertEquals(M_READ, $mode); - - /* Set unlimited access rights for everybody */ - $ret = $document->setDefaultAccess(M_ALL); - $this->assertTrue($ret); - $mode = $document->getAccessMode($user); - $this->assertEquals(M_ALL, $mode); - $mode = $document->getGroupAccessMode($group); - $this->assertEquals(M_ALL, $mode); - - /* Guest still have just read access */ - $mode = $document->getAccessMode($guestuser); - $this->assertEquals(M_READ, $mode); - - /* Add wrong access type returns false */ - $ret = $document->addAccess(M_ALL+1, $user->getId(), true); - $this->assertFalse($ret); - - /* Add read/write access on the document for user */ - $ret = $document->addAccess(M_READWRITE, $user->getId(), true); - $this->assertTrue($ret); - /* Adding another access right (not matter which one) for the - * same user yields an error - */ - $ret = $document->addAccess(M_READ, $user->getId(), true); - $this->assertFalse($ret); - - /* Passing an invalid second parameter will return false */ - $accesslist = $document->getAccessList(M_ANY, 5); - $this->assertFalse($accesslist); - - /* Searching for mode == M_READ will return neither a group nor - * the user, because the user has read&write access - */ - $accesslist = $document->getAccessList(M_READ); - $this->assertIsArray($accesslist); - $this->assertCount(0, $accesslist['groups']); - $this->assertCount(0, $accesslist['users']); - - $accesslist = $document->getAccessList(M_READWRITE); - $this->assertIsArray($accesslist); - $this->assertCount(0, $accesslist['groups']); - $this->assertCount(1, $accesslist['users']); - - $accesslist = $document->getAccessList(); - $this->assertIsArray($accesslist); - $this->assertCount(0, $accesslist['groups']); - $this->assertCount(1, $accesslist['users']); - - /* Access mode is just read/write for the user thought the default is unlimited */ - $mode = $document->getAccessMode($user); - $this->assertEquals(M_READWRITE, $mode); - /* Access mode for the group is still unlimited */ - $mode = $document->getGroupAccessMode($group); - $this->assertEquals(M_ALL, $mode); - - /* Setting default access to M_READ - * is just a precaution to ensure the unlimeted access rights is not - * derived from the default access which was set to M_ALL above. - */ - $ret = $document->setDefaultAccess(M_READ); - $this->assertTrue($ret); - $mode = $document->getGroupAccessMode($group); - $this->assertEquals(M_READ, $mode); - - /* Add unlimeted access on the document for group */ - $ret = $document->addAccess(M_ALL, $group->getId(), false); - $this->assertTrue($ret); - /* Adding another access right (not matter which one) for the - * same group yields an error - */ - $ret = $document->addAccess(M_READ, $group->getId(), false); - $this->assertFalse($ret); - - $accesslist = $document->getAccessList(); - $this->assertIsArray($accesslist); - $this->assertCount(1, $accesslist['groups']); - $this->assertCount(1, $accesslist['users']); - - /* The group has now unlimited access rights */ - $mode = $document->getGroupAccessMode($group); - $this->assertEquals(M_ALL, $mode); - - /* The user still has just read/write access, though the group he belongs - * to has unlimeted rights. The specific user rights has higher priority. - */ - $mode = $document->getAccessMode($user); - $this->assertEquals(M_READWRITE, $mode); - - /* Remove all specific access rights for the user */ - $ret = $document->removeAccess($user->getId(), true); - $this->assertTrue($ret); - - /* Now the group rights apply for the user, because there are no - * specific user rights anymore. - */ - $mode = $document->getAccessMode($user); - $this->assertEquals(M_ALL, $mode); - - /* change unlimeted access on the document for group to none */ - $ret = $document->changeAccess(M_NONE, $group->getId(), false); - $this->assertTrue($ret); - $mode = $document->getAccessMode($user); - $this->assertEquals(M_NONE, $mode); - - /* clear all access rights */ - $ret = $document->clearAccessList(); - $this->assertTrue($ret); - $accesslist = $document->getAccessList(); - $this->assertIsArray($accesslist); - $this->assertCount(0, $accesslist['groups']); - $this->assertCount(0, $accesslist['users']); - - /* We are back to the default access rights */ - $mode = $document->getAccessMode($user); - $this->assertEquals(M_READ, $mode); - - } - - /** - * Test method addNotify(), removeNotify(), getNotifyList(), cleanNotifyList() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetNotify() - { - self::createGroupsAndUsers(); - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $adminuser = self::$dms->getUser(1); - $guestuser = self::$dms->getUser(2); - $user = self::$dms->getUserByLogin('user-1-1'); - $this->assertIsObject($user); - $this->assertTrue($user->isType('user')); - $group = self::$dms->getGroupByName('Group 1'); - $this->assertIsObject($group); - $this->assertTrue($group->isType('group')); - $document = self::createDocument($folder, $adminuser, 'Document 1'); - $this->assertIsObject($document); - $this->assertTrue($document->isType('document')); - - $notifylist = $document->getNotifyList(); - $this->assertIsArray($notifylist); - $this->assertCount(0, $notifylist['groups']); - $this->assertCount(0, $notifylist['users']); - - /* Add notify on the document for user */ - $ret = $document->addNotify($user->getId(), true); - $this->assertEquals(0, $ret); - - /* Add notify on the document for group */ - $ret = $document->addNotify($group->getId(), false); - $this->assertEquals(0, $ret); - - /* Add notify on the document for a user that does not exists */ - $ret = $document->addNotify(15, true); - $this->assertEquals(-1, $ret); - - $notifylist = $document->getNotifyList(); - $this->assertIsArray($notifylist); - $this->assertCount(1, $notifylist['groups']); - $this->assertCount(1, $notifylist['users']); - - /* Setting the default access to M_NONE and turning off inheritance - * will clean the notification list, because the notifiers have no - * longer read access on the document and therefore will be removed - * from the notification list. - */ - $ret = $document->setInheritAccess(false); - $this->assertTrue($ret); - $ret = $document->setDefaultAccess(M_NONE); - $this->assertTrue($ret); - - $notifylist = $document->getNotifyList(); - $this->assertIsArray($notifylist); - $this->assertCount(0, $notifylist['groups']); - $this->assertCount(0, $notifylist['users']); - } - - /** - * Test method isDescendant() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testIsDescendant() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - $subfolder1 = $rootfolder->addSubFolder('Subfolder 1', '', $user, 2.0); - $subfolder2 = $rootfolder->addSubFolder('Subfolder 2', '', $user, 1.0); - $document = self::createDocument($subfolder1, $user, 'Document 1'); - /* document is a descendant of root folder and subfolder 1 */ - $this->assertTrue($document->isDescendant($rootfolder)); - $this->assertTrue($document->isDescendant($subfolder1)); - /* subfolder is not a descendant of subfolder 2 */ - $this->assertFalse($document->isDescendant($subfolder2)); - } - - /** - * Test method getParent() - * - * Create a new document below root folder and check if parent - * of the document is the root folder. - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetParent() - { - $user = self::$dms->getUser(1); - $rootfolder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $document = self::createDocument($rootfolder, $user, 'Document 1'); - $parent = $document->getParent(); - $this->assertIsObject($parent); - $this->assertInstanceOf(SeedDMS_Core_Folder::class, $parent); - $this->assertEquals(1, $parent->getId()); - } - - /** - * Test method setParent() - * - * Create a new document below root folder, move it to a subfolder - * and check if parent of the document is the sub folder. - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testSetParent() - { - $user = self::$dms->getUser(1); - $rootfolder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $subfolder = $rootfolder->addSubFolder('Subfolder 1', '', $user, 0); - $document = self::createDocument($rootfolder, $user, 'Document 1'); - /* Setting a null folder is not allowed */ - $ret = $document->setParent(null); - $this->assertFalse($ret); - - /* Passed object must be a folder */ - $ret = $document->setParent($user); - $this->assertFalse($ret); - - $ret = $document->setParent($subfolder); - $this->assertTrue($ret); - $parent = $document->getParent(); - $this->assertIsObject($parent); - $this->assertInstanceOf(SeedDMS_Core_Folder::class, $parent); - $this->assertEquals(2, $parent->getId()); - } - - /** - * Test method setParent() mit sql fail - * - * @return void - */ - public function testSetParentSqlFail() - { - $document = $this->getMockedDocument(); - $rootfolder = $this->getMockedRootFolder(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblDocuments` SET `folder`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $document->setDMS($dms); - $this->assertFalse($document->setParent($rootfolder)); - } - - /** - * Test method setOwner() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testSetOwner() - { - $adminuser = self::$dms->getUser(1); - $rootfolder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $user = self::$dms->addUser('user1', 'user1', 'User One', 'user1@seeddms.org', 'en_GB', 'bootstrap', ''); - $this->assertIsObject($user); - $document = self::createDocument($rootfolder, $adminuser, 'Document 1'); - /* Setting a null user is not allowed */ - $ret = $document->setOwner(null); - $this->assertFalse($ret); - - /* Passed object must be a folder */ - $ret = $document->setOwner($rootfolder); - $this->assertFalse($ret); - - $res = $document->setOwner($user); - $this->assertTrue($res); - $owner = $document->getOwner(); - $this->assertIsObject($owner); - $this->assertInstanceOf(SeedDMS_Core_User::class, $owner); - $this->assertEquals($user->getId(), $owner->getId()); - } - - /** - * Test method setOwner() mit sql fail - * - * @return void - */ - public function testSetOwnerSqlFail() - { - $document = $this->getMockedDocument(); - $user = $this->getMockedUser(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblDocuments` SET `owner`")) - ->willReturn(false); - // SeedDMS 6 will fetch the old owner in setOwner() before setting the - // new owner - if(self::$dbversion['major'] == 6) { - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblUsers` WHERE `id` = ")) - ->willReturn([]); - } - $dms = new SeedDMS_Core_DMS($db, ''); - $document->setDMS($dms); - $this->assertFalse($document->setOwner($user)); - } - - /** - * Test method expires(), setExpires(), getExpires() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetExpires() - { - $adminuser = self::$dms->getUser(1); - $rootfolder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $document = self::createDocument($rootfolder, $adminuser, 'Document 1'); - $expires = $document->expires(); - $this->assertFalse($expires); - $expires = $document->getExpires(); - $this->assertFalse($expires); - $now = time(); - $res = $document->setExpires($now); - $this->assertTrue($res); - /* Setting it again will return true */ - $res = $document->setExpires($now); - $this->assertTrue($res); - $expires = $document->expires(); - $this->assertTrue($res); - $expirets = $document->getExpires(); - $this->assertEquals($now, $expirets); - } - - /** - * Test method setExpires() mit sql fail - * - * @return void - */ - public function testSetExpiresSqlFail() - { - $document = $this->getMockedDocument(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblDocuments` SET `expires`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $document->setDMS($dms); - $this->assertFalse($document->setExpires(time())); - } - - /** - * Test method setLocked(), isLocked() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testSetAndIsLocked() - { - $adminuser = self::$dms->getUser(1); - $rootfolder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $user = self::$dms->addUser('user1', 'user1', 'User One', 'user1@seeddms.org', 'en_GB', 'bootstrap', ''); - $this->assertIsObject($user); - $document = self::createDocument($rootfolder, $adminuser, 'Document 1'); - $res = $document->isLocked(); - $this->assertFalse($res); - $res = $document->setLocked($user); - $this->assertTrue($res); - $res = $document->isLocked(); - $this->assertTrue($res); - $lockuser = $document->getLockingUser(); - $this->assertIsObject($lockuser); - $this->assertInstanceOf(SeedDMS_Core_User::class, $lockuser); - $this->assertEquals($user->getId(), $lockuser->getId()); - /* parameter passed to setLocked must be false or a user */ - $res = $document->setLocked(null); - /* document is still locked and locking user is unchanged */ - $res = $document->isLocked(); - $this->assertTrue($res); - $lockuser = $document->getLockingUser(); - $this->assertIsObject($lockuser); - $this->assertInstanceOf(SeedDMS_Core_User::class, $lockuser); - $this->assertEquals($user->getId(), $lockuser->getId()); - /* Unlock the document */ - $res = $document->setLocked(false); - $this->assertTrue($res); - $res = $document->isLocked(); - $this->assertFalse($res); - $lockuser = $document->getLockingUser(); - $this->assertFalse($lockuser); - } - - /** - * Test method setLocked() with sql fail - * - * @return void - */ - public function testSetLockedSqlFail() - { - $document = $this->getMockedDocument(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("DELETE FROM `tblDocumentLocks`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $document->setDMS($dms); - $this->assertFalse($document->setLocked(false)); - } - - /** - * Test method getSequence() and setSequence() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetSequence() - { - $adminuser = self::$dms->getUser(1); - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $document = self::createDocument($folder, $adminuser, 'Document 1'); - /* The document still has sequence = 1.0 */ - $sequence = $document->getSequence(); - $this->assertEquals(1.0, $sequence); - $ret = $document->setSequence(1.5); - $this->assertTrue($ret); - $sequence = $document->getSequence(); - $this->assertEquals(1.5, $sequence); - } - - /** - * Test method setSequence() mit sql fail - * - * @return void - */ - public function testSetSequenceSqlFail() - { - $document = $this->getMockedDocument(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblDocuments` SET `sequence`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $document->setDMS($dms); - $this->assertFalse($document->setSequence(1.1)); - } - - /** - * Test method getContentByVersion(), isLatestContent() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetContentByVersion() - { - $adminuser = self::$dms->getUser(1); - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $document = self::createDocument($folder, $adminuser, 'Document 1'); - /* Get version 1 */ - $content = $document->getContentByVersion(1); - $this->assertIsObject($content); - $this->assertInstanceOf(SeedDMS_Core_DocumentContent::class, $content); - /* There is no version 2 */ - $content = $document->getContentByVersion(2); - $this->assertNull($content); - /* version must be numeric */ - $content = $document->getContentByVersion('foo'); - $this->assertFalse($content); - /* Check if 1 is the latest version number */ - $ret = $document->isLatestContent(1); - $this->assertTrue($ret); - $ret = $document->isLatestContent(2); - $this->assertFalse($ret); - } - - /** - * Test method getDocumentContent() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetDocumentContent() - { - $adminuser = self::$dms->getUser(1); - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $document = self::createDocument($folder, $adminuser, 'Document 1'); - /* Get version 1 */ - $content = $document->getContentByVersion(1); - $this->assertIsObject($content); - $this->assertInstanceOf(SeedDMS_Core_DocumentContent::class, $content); - $again = self::$dms->getDocumentContent($content->getId()); - $this->assertIsObject($again); - $this->assertInstanceOf(SeedDMS_Core_DocumentContent::class, $again); - $this->assertEquals($content->getId(), $again->getId()); - $none = self::$dms->getDocumentContent(2); - $this->assertNull($none); - } - - /** - * Test method getDocumentContent() with sql failure - * - * @return void - */ - public function testGetDocumentContentSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblDocumentContent` WHERE `id`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $this->assertFalse($dms->getDocumentContent(1)); - } - - /** - * Test method addDocumentLink(), getDocumentLinks(), getReverseDocumentLinks() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testAddAndGetDocumentLinks() - { - $adminuser = self::$dms->getUser(1); - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $user = self::$dms->addUser('user1', 'user1', 'User One', 'user1@seeddms.org', 'en_GB', 'bootstrap', ''); - $this->assertIsObject($user); - $document1 = self::createDocument($folder, $adminuser, 'Document 1'); - $document2 = self::createDocument($folder, $adminuser, 'Document 2'); - - /* document 1 has no links */ - $links = $document1->getDocumentLinks(); - $this->assertIsArray($links); - $this->assertCount(0, $links); - $links = $document1->getReverseDocumentLinks(); - $this->assertIsArray($links); - $this->assertCount(0, $links); - - /* Adding a link to none existing target or by a none existing user fails */ - $ret = $document1->addDocumentLink(3, $user->getId(), false); - $this->assertFalse($ret); - $ret = $document1->addDocumentLink($document2->getId(), 4, false); - $this->assertFalse($ret); - - /* Adding a link with a bogus target or user must fail */ - $ret = $document1->addDocumentLink('foo', 1, false); - $this->assertFalse($ret); - $ret = $document1->addDocumentLink(3, 'foo', false); - $this->assertFalse($ret); - - /* Adding a link to myself must fail */ - $ret = $document1->addDocumentLink($document1->getId(), $user->getId(), false); - $this->assertFalse($ret); - - /* Add a non public link to document 2 by user */ - $link = $document1->addDocumentLink($document2->getId(), $user->getId(), false); - $this->assertIsObject($link); - $this->assertInstanceOf(SeedDMS_Core_DocumentLink::class, $link); - $links = $document1->getDocumentLinks(); - $this->assertIsArray($links); - $this->assertCount(1, $links); - $links = $document2->getReverseDocumentLinks(); - $this->assertIsArray($links); - $this->assertCount(1, $links); - /* There is one reverse link of a user */ - $links = $document2->getReverseDocumentLinks(false, $user); - $this->assertIsArray($links); - $this->assertCount(1, $links); - /* There are no public reverse links */ - $links = $document2->getReverseDocumentLinks(true); - $this->assertIsArray($links); - $this->assertCount(0, $links); - - /* There are no public links of document 1 */ - $document1->clearCache(); - $links = $document1->getDocumentLinks(true); - $this->assertIsArray($links); - $this->assertCount(0, $links); - - /* There are no links by adminuser of document 1 */ - $document1->clearCache(); - $links = $document1->getDocumentLinks(false, $adminuser); - $this->assertIsArray($links); - $this->assertCount(0, $links); - - /* There are links by user of document 1 */ - $document1->clearCache(); - $links = $document1->getDocumentLinks(false, $user); - $this->assertIsArray($links); - $this->assertCount(1, $links); - - $link = $document1->getDocumentLink($links[0]->getId()); - $this->assertIsObject($link); - $this->assertTrue($link->isType('documentlink')); - } - - /** - * Test method addDocumentLink(), removeDocumentLinks() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testAddAndRemoveDocumentLink() - { - $adminuser = self::$dms->getUser(1); - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $user = self::$dms->addUser('user1', 'user1', 'User One', 'user1@seeddms.org', 'en_GB', 'bootstrap', ''); - $this->assertIsObject($user); - $document1 = self::createDocument($folder, $adminuser, 'Document 1'); - $document2 = self::createDocument($folder, $adminuser, 'Document 2'); - - /* Add a non public link to document 2 by user */ - $link = $document1->addDocumentLink($document2->getId(), $user->getId(), false); - $this->assertIsObject($link); - $this->assertInstanceOf(SeedDMS_Core_DocumentLink::class, $link); - $links = $document1->getDocumentLinks(); - $this->assertIsArray($links); - $this->assertCount(1, $links); - - /* Remove the link again */ - $link = $links[0]; - $ret = $document1->removeDocumentLink($link->getId()); - $this->assertTrue($ret); - $links = $document1->getDocumentLinks(); - $this->assertIsArray($links); - $this->assertCount(0, $links); - } - - /** - * Test method addDocumentFile(), getDocumentFiles() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testAddAndGetDocumentFiles() - { - $adminuser = self::$dms->getUser(1); - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $user = self::$dms->addUser('user1', 'user1', 'User One', 'user1@seeddms.org', 'en_GB', 'bootstrap', ''); - $this->assertIsObject($user); - $document = self::createDocument($folder, $adminuser, 'Document 1'); - - /* document has no files */ - $files = $document->getDocumentFiles(); - $this->assertIsArray($files); - $this->assertCount(0, $files); - - $filename = self::createTempFile(100); - $file1 = $document->addDocumentFile('Attachment 1', '', $user, $filename, 'attachment1.txt', '.txt', 'plain/text'); - unlink($filename); - $this->assertIsObject($file1); - $this->assertInstanceOf(SeedDMS_Core_DocumentFile::class, $file1); - - $filename = self::createTempFile(100); - $file2 = $document->addDocumentFile('Attachment 2', '', $user, $filename, 'attachment2.txt', '.txt', 'plain/text', 1); - unlink($filename); - $this->assertIsObject($file2); - $this->assertInstanceOf(SeedDMS_Core_DocumentFile::class, $file2); - - /* Get all attachments */ - $files = $document->getDocumentFiles(); - $this->assertIsArray($files); - $this->assertCount(2, $files); - - /* Get attachments for version 1 only */ - $files = $document->getDocumentFiles(1, false); - $this->assertIsArray($files); - $this->assertCount(1, $files); - - /* Get attachments for version 1 and version independed */ - $files = $document->getDocumentFiles(1, true); - $this->assertIsArray($files); - $this->assertCount(2, $files); - } - - /** - * Test method addDocumentFile(), removeDocumentFile() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testAddAndRemoveDocumentFiles() - { - $adminuser = self::$dms->getUser(1); - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $user = self::$dms->addUser('user1', 'user1', 'User One', 'user1@seeddms.org', 'en_GB', 'bootstrap', ''); - $this->assertIsObject($user); - $document = self::createDocument($folder, $adminuser, 'Document 1'); - - /* document has no files */ - $files = $document->getDocumentFiles(); - $this->assertIsArray($files); - $this->assertCount(0, $files); - - $filename = self::createTempFile(100); - $file1 = $document->addDocumentFile('Attachment 1', '', $user, $filename, 'attachment1.txt', '.txt', 'plain/text'); - $this->assertTrue(SeedDMS_Core_File::removeFile($filename)); - $this->assertIsObject($file1); - $this->assertInstanceOf(SeedDMS_Core_DocumentFile::class, $file1); - - /* document has now 1 file */ - $files = $document->getDocumentFiles(); - $this->assertIsArray($files); - $this->assertCount(1, $files); - - /* Removing a file with a none exiting or bogus id must fail */ - $ret = $document->removeDocumentFile(2); - $this->assertFalse($ret); - $ret = $document->removeDocumentFile('foo'); - $this->assertFalse($ret); - - $ret = $document->removeDocumentFile($files[0]->getId()); - $this->assertTrue($ret); - - $files = $document->getDocumentFiles(); - $this->assertIsArray($files); - $this->assertCount(0, $files); - } - - /** - * Test method addDocument(), removeDocument() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testAddAndRemoveDocument() - { - $adminuser = self::$dms->getUser(1); - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $user = self::$dms->addUser('user1', 'user1', 'User One', 'user1@seeddms.org', 'en_GB', 'bootstrap', ''); - $this->assertIsObject($user); - $document = self::createDocument($folder, $adminuser, 'Document 1'); - $docid = $document->getId(); - - $filename = self::createTempFile(100); - $file1 = $document->addDocumentFile('Attachment 1', '', $user, $filename, 'attachment1.txt', '.txt', 'plain/text'); - $this->assertTrue(SeedDMS_Core_File::removeFile($filename)); - $this->assertIsObject($file1); - $this->assertInstanceOf(SeedDMS_Core_DocumentFile::class, $file1); - - $ret = $document->remove(); - $this->assertTrue($ret); - $document = self::$dms->getDocument($docid); - $this->assertNull($document); - } - - /** - * Test method getUsedDiskSpace() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetUsedDiskSpace() - { - $adminuser = self::$dms->getUser(1); - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - /* Create a document with 1234 Bytes */ - $document = self::createDocument($folder, $adminuser, 'Document 1', 1234); - $size = $document->getUsedDiskSpace(); - $this->assertEquals(1234, $size); - } - - /** - * Test method getTimeline() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetTimeline() - { - $adminuser = self::$dms->getUser(1); - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - /* Create a document */ - $document = self::createDocument($folder, $adminuser, 'Document 1'); - /* Attach a file */ - $filename = self::createTempFile(100); - $file1 = $document->addDocumentFile('Attachment 1', '', $adminuser, $filename, 'attachment1.txt', '.txt', 'plain/text'); - $this->assertTrue(SeedDMS_Core_File::removeFile($filename)); - $this->assertIsObject($file1); - $this->assertInstanceOf(SeedDMS_Core_DocumentFile::class, $file1); - - /* Get the timeline. It must contain two entries - * - the initial release of the document - * - adding the attachment - */ - $timeline = $document->getTimeLine(); - $this->assertIsArray($timeline); - $this->assertCount(2, $timeline); - } - - /** - * Test method transferToUser() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testTransferToUser() - { - $adminuser = self::$dms->getUser(1); - $user = self::$dms->addUser('user1', 'user1', 'User One', 'user1@seeddms.org', 'en_GB', 'bootstrap', ''); - $this->assertIsObject($user); - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - /* Create two documents */ - $document1 = self::createDocument($folder, $adminuser, 'Document 1'); - $document2 = self::createDocument($folder, $adminuser, 'Document 2'); - - /* Attach a file */ - $filename = self::createTempFile(100); - $file1 = $document1->addDocumentFile('Attachment 1', '', $adminuser, $filename, 'attachment1.txt', '.txt', 'plain/text'); - $this->assertTrue(SeedDMS_Core_File::removeFile($filename)); - $this->assertIsObject($file1); - $this->assertInstanceOf(SeedDMS_Core_DocumentFile::class, $file1); - - /* Add a non public link to document 2 */ - $link = $document1->addDocumentLink($document2->getId(), $adminuser->getId(), false); - $this->assertIsObject($link); - $this->assertInstanceOf(SeedDMS_Core_DocumentLink::class, $link); - - /* Transfer document to $user */ - $this->assertEquals('admin', $document1->getOwner()->getLogin()); - $links = $document1->getDocumentLinks(false, $adminuser); - $this->assertIsArray($links); - $this->assertCount(1, $links); - - $ret = $document1->transferToUser($user); - $this->assertTrue($ret); - $this->assertEquals('user1', $document1->getOwner()->getLogin()); - $links = $document1->getDocumentLinks(false, $user); - $this->assertIsArray($links); - $this->assertCount(1, $links); - $files = $document1->getDocumentFiles(); - $this->assertIsArray($files); - $this->assertCount(1, $files); - $this->assertEquals($files[0]->getUserID(), $user->getId()); - } -} diff --git a/SeedDMS_Core/tests/FileUtilsTest.php b/SeedDMS_Core/tests/FileUtilsTest.php deleted file mode 100644 index 7e1b87cfb..000000000 --- a/SeedDMS_Core/tests/FileUtilsTest.php +++ /dev/null @@ -1,219 +0,0 @@ - - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version @package_version@ - * @link https://www.seeddms.org - */ - -use PHPUnit\Framework\SeedDmsTest; - -/** - * Group test class - * - * @category SeedDMS - * @package Tests - * @author Uwe Steinmann - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version Release: @package_version@ - * @link https://www.seeddms.org - */ -class FileUtilsTest extends SeedDmsTest -{ - /** - * Create temporary directory - * - * @return void - */ - protected function setUp(): void - { - self::$contentdir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'phpunit-'.time(); - mkdir(self::$contentdir); - } - - /** - * Clean up at tear down - * - * @return void - */ - protected function tearDown(): void - { - exec('rm -rf '.self::$contentdir); - } - - /** - * Test method format_filesize() - * - * @return void - */ - public function testFormatFileSize() - { - $this->assertEquals('1 Byte', SeedDMS_Core_File::format_filesize(1)); - $this->assertEquals('0 Bytes', SeedDMS_Core_File::format_filesize(0)); - $this->assertEquals('1000 Bytes', SeedDMS_Core_File::format_filesize(1000)); - $this->assertEquals('1 KiB', SeedDMS_Core_File::format_filesize(1024)); - $this->assertEquals('1 KiB', SeedDMS_Core_File::format_filesize(1025)); - $this->assertEquals('2 KiB', SeedDMS_Core_File::format_filesize(2047)); - $this->assertEquals('1 MiB', SeedDMS_Core_File::format_filesize(1024*1024)); - $this->assertEquals('1 GiB', SeedDMS_Core_File::format_filesize(1024*1024*1024)); - } - - /** - * Test method format_filesize() - * - * @return void - */ - public function testParseFileSize() - { - $this->assertEquals(200, SeedDMS_Core_File::parse_filesize('200B')); - $this->assertEquals(200, SeedDMS_Core_File::parse_filesize('200 B')); - $this->assertEquals(200, SeedDMS_Core_File::parse_filesize('200')); - $this->assertEquals(1024, SeedDMS_Core_File::parse_filesize('1K')); - $this->assertEquals(2*1024*1024, SeedDMS_Core_File::parse_filesize('2M')); - $this->assertEquals(3*1024*1024*1024, SeedDMS_Core_File::parse_filesize('3 G')); - $this->assertEquals(4*1024*1024*1024*1024, SeedDMS_Core_File::parse_filesize('4 T')); - $this->assertFalse(SeedDMS_Core_File::parse_filesize('4 t')); - $this->assertFalse(SeedDMS_Core_File::parse_filesize('-4T')); - } - - /** - * Test method fileSize() - * - * @return void - */ - public function testFileSize() - { - $filename = self::createTempFile(200, self::$contentdir); - $this->assertEquals(200, SeedDMS_Core_File::fileSize($filename)); - /* Getting the size of a none existing file returns false */ - $this->assertFalse(SeedDMS_Core_File::fileSize('foobar')); - $this->assertTrue(SeedDMS_Core_File::removeFile($filename)); - } - - /** - * Test method file_exists() - * - * @return void - */ - public function testFileExists() - { - $filename = self::createTempFile(200, self::$contentdir); - $this->assertTrue(SeedDMS_Core_File::file_exists($filename)); - $this->assertFalse(SeedDMS_Core_File::file_exists($filename.'bla')); - $this->assertTrue(SeedDMS_Core_File::removeFile($filename)); - } - - /** - * Test method fileExtension() - * - * @return void - */ - public function testFileExtension() - { - $this->assertEquals('png', SeedDMS_Core_File::fileExtension('image/png')); - $this->assertEquals('', SeedDMS_Core_File::fileExtension('image/kpng')); - $this->assertEquals('txt', SeedDMS_Core_File::fileExtension('text/plain')); - $this->assertEquals('md', SeedDMS_Core_File::fileExtension('text/markdown')); - } - - /** - * Test method moveFile() - * - * @return void - */ - public function testMoveFile() - { - $filename = self::createTempFile(200, self::$contentdir); - $this->assertEquals(200, SeedDMS_Core_File::fileSize($filename)); - $ret = SeedDMS_Core_File::moveFile($filename, self::$contentdir.DIRECTORY_SEPARATOR."foobar"); - $this->assertTrue($ret); - /* Getting the file size of the old doc must fail now */ - $this->assertFalse(SeedDMS_Core_File::fileSize($filename)); - /* Getting the file size of the new doc succeds */ - $this->assertEquals(200, SeedDMS_Core_File::fileSize(self::$contentdir.DIRECTORY_SEPARATOR."foobar")); - $this->assertTrue(SeedDMS_Core_File::removeFile(self::$contentdir.DIRECTORY_SEPARATOR."foobar")); - } - - /** - * Test method makeDir(), renameDir(), removeDir() - * - * @return void - */ - public function testMakeRenameAndRemoveDir() - { - /* Create a directory and put a file into it */ - $ret = SeedDMS_Core_File::makeDir(self::$contentdir.DIRECTORY_SEPARATOR."foobar"); - system('touch '.self::$contentdir.DIRECTORY_SEPARATOR."foobar".DIRECTORY_SEPARATOR."tt"); - /* Rename the directory */ - $ret = SeedDMS_Core_File::renameDir(self::$contentdir.DIRECTORY_SEPARATOR."foobar", self::$contentdir.DIRECTORY_SEPARATOR."bazfoo"); - $this->assertTrue($ret); - /* The new must exist and the old one is gone */ - $this->assertTrue(is_dir(self::$contentdir.DIRECTORY_SEPARATOR."bazfoo")); - $this->assertFalse(is_dir(self::$contentdir.DIRECTORY_SEPARATOR."foobar")); - $this->assertTrue(SeedDMS_Core_File::removeDir(self::$contentdir.DIRECTORY_SEPARATOR."bazfoo")); - $this->assertFalse(SeedDMS_Core_File::removeDir(self::$contentdir.DIRECTORY_SEPARATOR."bazfoo")); - $this->assertFalse(SeedDMS_Core_File::removeDir(self::$contentdir.DIRECTORY_SEPARATOR."foobar")); - - /* Create a directory, a sub directory and a file */ - $ret = SeedDMS_Core_File::makeDir(self::$contentdir.DIRECTORY_SEPARATOR."foobar"); - $this->assertTrue($ret); - $ret = SeedDMS_Core_File::makeDir(self::$contentdir.DIRECTORY_SEPARATOR."foobar".DIRECTORY_SEPARATOR."bazfoo"); - $this->assertTrue($ret); - system('touch '.self::$contentdir.DIRECTORY_SEPARATOR."foobar".DIRECTORY_SEPARATOR."bazfoo".DIRECTORY_SEPARATOR."tt"); - $this->assertTrue(SeedDMS_Core_File::file_exists(self::$contentdir.DIRECTORY_SEPARATOR."foobar".DIRECTORY_SEPARATOR."bazfoo".DIRECTORY_SEPARATOR."tt")); - - $ret = SeedDMS_Core_File::removeDir(self::$contentdir.DIRECTORY_SEPARATOR."foobar"); - $this->assertTrue($ret); - $this->assertFalse(SeedDMS_Core_File::file_exists(self::$contentdir.DIRECTORY_SEPARATOR."foobar")); - $this->assertFalse(SeedDMS_Core_File::file_exists(self::$contentdir.DIRECTORY_SEPARATOR."foobar".DIRECTORY_SEPARATOR."bazfoo")); - $this->assertFalse(SeedDMS_Core_File::file_exists(self::$contentdir.DIRECTORY_SEPARATOR."foobar".DIRECTORY_SEPARATOR."bazfoo".DIRECTORY_SEPARATOR."tt")); - } - - /** - * Test method makeDir(), copyDir(), removeDir() - * - * @return void - */ - public function testMakeCopyAndRemoveDir() - { - /* Create a directory and put a file into it */ - $ret = SeedDMS_Core_File::makeDir(self::$contentdir.DIRECTORY_SEPARATOR."foobar"); - system('touch '.self::$contentdir.DIRECTORY_SEPARATOR."foobar".DIRECTORY_SEPARATOR."tt"); - /* Rename the directory */ - $ret = SeedDMS_Core_File::copyDir(self::$contentdir.DIRECTORY_SEPARATOR."foobar", self::$contentdir.DIRECTORY_SEPARATOR."bazfoo"); - $this->assertTrue($ret); - /* The new and the old dir must exist */ - $this->assertTrue(is_dir(self::$contentdir.DIRECTORY_SEPARATOR."bazfoo")); - $this->assertTrue(is_dir(self::$contentdir.DIRECTORY_SEPARATOR."foobar")); - $this->assertTrue(SeedDMS_Core_File::removeDir(self::$contentdir.DIRECTORY_SEPARATOR."bazfoo")); - $this->assertTrue(SeedDMS_Core_File::removeDir(self::$contentdir.DIRECTORY_SEPARATOR."foobar")); - } - - /** - * Test method moveDir() - * - * @return void - */ - public function testMakeAndMoveDir() - { - /* Create a directory and put a file into it */ - $ret = SeedDMS_Core_File::makeDir(self::$contentdir.DIRECTORY_SEPARATOR."foobar"); - system('touch '.self::$contentdir.DIRECTORY_SEPARATOR."foobar".DIRECTORY_SEPARATOR."tt"); - /* Rename the directory */ - $ret = SeedDMS_Core_File::moveDir(self::$contentdir.DIRECTORY_SEPARATOR."foobar", self::$contentdir.DIRECTORY_SEPARATOR."bazfoo"); - $this->assertTrue($ret); - /* The new must exist and the old dir must be disappeared */ - $this->assertTrue(is_dir(self::$contentdir.DIRECTORY_SEPARATOR."bazfoo")); - $this->assertFalse(is_dir(self::$contentdir.DIRECTORY_SEPARATOR."foobar")); - $this->assertTrue(SeedDMS_Core_File::removeDir(self::$contentdir.DIRECTORY_SEPARATOR."bazfoo")); - $this->assertFalse(is_dir(self::$contentdir.DIRECTORY_SEPARATOR."bazfoo")); - } -} diff --git a/SeedDMS_Core/tests/FolderTest.php b/SeedDMS_Core/tests/FolderTest.php deleted file mode 100644 index ee05f0b8c..000000000 --- a/SeedDMS_Core/tests/FolderTest.php +++ /dev/null @@ -1,1221 +0,0 @@ - - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version @package_version@ - * @link https://www.seeddms.org - */ - -use PHPUnit\Framework\SeedDmsTest; - -/** - * Group test class - * - * @category SeedDMS - * @package Tests - * @author Uwe Steinmann - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version Release: @package_version@ - * @link https://www.seeddms.org - */ -class FolderTest extends SeedDmsTest -{ - - /** - * Create a real sqlite database in memory - * - * @return void - */ - protected function setUp(): void - { - self::$dbh = self::createInMemoryDatabase(); - self::$contentdir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'phpunit-'.time(); - mkdir(self::$contentdir); - // echo "Creating temp content dir: ".self::$contentdir."\n"; - self::$dms = new SeedDMS_Core_DMS(self::$dbh, self::$contentdir); - } - - /** - * Clean up at tear down - * - * @return void - */ - protected function tearDown(): void - { - self::$dbh = null; - // echo "\nRemoving temp. content dir: ".self::$contentdir."\n"; - exec('rm -rf '.self::$contentdir); - } - - /** - * Test method getInstance() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetInstanceRootFolder() - { - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $this->assertIsObject($folder); - $this->assertEquals('DMS', $folder->getName()); - /* get instance of none existing folder */ - $folder = SeedDMS_Core_Folder::getInstance(2, self::$dms); - $this->assertNull($folder); - } - - /** - * Test method isType() - * - * @return void - */ - public function testIsType() - { - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $this->assertTrue($folder->isType('folder')); - } - - /** - * Test method getInstance() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetInstance() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - $subfolder = $rootfolder->addSubFolder('Subfolder 1', '', $user, 2.0); - $subsubfolder = $subfolder->addSubFolder('Subsubfolder 1', '', $user, 1.0); - /* Get the folder with id 2, which must be 'Subfolder 1' */ - $folder = SeedDMS_Core_Folder::getInstance(2, self::$dms); - $this->assertIsObject($folder); - $this->assertEquals('Subfolder 1', $folder->getName()); - /* Get a none existing folder */ - $folder = SeedDMS_Core_Folder::getInstance(4, self::$dms); - $this->assertNull($folder); - } - - /** - * Test method getInstance() - * - * @return void - */ - public function testGetInstanceSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblFolders`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $this->assertFalse(SeedDMS_Core_Folder::getInstance(1, $dms)); - } - - /** - * Test method getInstanceByName() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetInstanceByName() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - $subfolder = $rootfolder->addSubFolder('Subfolder 1', '', $user, 2.0); - $subsubfolder = $subfolder->addSubFolder('Subsubfolder 1', '', $user, 1.0); - /* Search for it anywhere in the folder hierarchy */ - $folder = SeedDMS_Core_Folder::getInstanceByName('Subsubfolder 1', null, self::$dms); - $this->assertIsObject($folder); - $this->assertEquals('Subsubfolder 1', $folder->getName()); - /* Search for it within 'Subfolder 1' will find it */ - $folder = SeedDMS_Core_Folder::getInstanceByName('Subsubfolder 1', $subfolder, self::$dms); - $this->assertIsObject($folder); - $this->assertEquals('Subsubfolder 1', $folder->getName()); - /* Search for it within root folder will not find it */ - $folder = SeedDMS_Core_Folder::getInstanceByName('Subsubfolder 1', $rootfolder, self::$dms); - $this->assertNull($folder); - } - - /** - * Test method getInstanceByName() - * - * @return void - */ - public function testGetInstanceByNameSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblFolders`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $this->assertFalse(SeedDMS_Core_Folder::getInstanceByName('foo', null, $dms)); - } - - /** - * Test method getName() and setName() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetName() - { - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $name = $folder->getName(); - $this->assertEquals('DMS', $name); - $ret = $folder->setName('foo'); - $this->assertTrue($ret); - $name = $folder->getName(); - $this->assertEquals('foo', $name); - } - - /** - * Test method setName() - * - * @return void - */ - public function testSetNameSqlFail() - { - $rootfolder = $this->getMockedRootFolder(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblFolders` SET `name`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $rootfolder->setDMS($dms); - $this->assertFalse($rootfolder->setName('foo')); - } - - /** - * Test method getComment() and setComment() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetComment() - { - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $comment = $folder->getComment(); - $this->assertEquals('DMS root', $comment); - $ret = $folder->setComment('foo'); - $this->assertTrue($ret); - $comment = $folder->getComment(); - $this->assertEquals('foo', $comment); - } - - /** - * Test method setComment() - * - * @return void - */ - public function testSetCommentSqlFail() - { - $rootfolder = $this->getMockedRootFolder(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblFolders` SET `comment`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $rootfolder->setDMS($dms); - $this->assertFalse($rootfolder->setComment('foo')); - } - - /** - * Test method getSequence() and setSequence() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetSequence() - { - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - /* The root folder's sequence in the initial database is 0.0 */ - $sequence = $folder->getSequence(); - $this->assertEquals(0.0, $sequence); - $ret = $folder->setSequence(1.5); - $this->assertTrue($ret); - $sequence = $folder->getSequence(); - $this->assertEquals(1.5, $sequence); - } - - /** - * Test method setSequence() - * - * @return void - */ - public function testSetSequenceSqlFail() - { - $rootfolder = $this->getMockedRootFolder(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblFolders` SET `sequence`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $rootfolder->setDMS($dms); - $this->assertFalse($rootfolder->setSequence(0.0)); - } - - /** - * Test method getDate() and setDate() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetDate() - { - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $now = time(); - /* Passing false as a time stamp will take current time stamp */ - $ret = $folder->setDate(false); - $this->assertTrue($ret); - $date = $folder->getDate(); - $this->assertEquals($now, $date); - /* Setting a time stamp */ - $now -= 1000; - $ret = $folder->setDate($now); - $this->assertTrue($ret); - $date = $folder->getDate(); - $this->assertEquals($now, $date); - /* Setting a none numeric value will fail */ - $ret = $folder->setDate('foo'); - $this->assertFalse($ret); - } - - /** - * Test method setDate() - * - * @return void - */ - public function testSetDateSqlFail() - { - $rootfolder = $this->getMockedRootFolder(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblFolders` SET `date`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $rootfolder->setDMS($dms); - $this->assertFalse($rootfolder->setDate(time())); - } - - /** - * Test method getParent() - * - * Get parent of root folder which is always null. - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetParentRootFolder() - { - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $parent = $folder->getParent(); - $this->assertNull($parent); - } - - /** - * Test method getParent() - * - * Create a new subfolder below root folder and check if parent - * of the folder is the root folder. - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetParent() - { - $adminuser = self::$dms->getUser(1); - $rootfolder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $subfolder = $rootfolder->addSubFolder('Subfolder 1', '', $adminuser, 0); - $parent = $subfolder->getParent(); - $this->assertIsObject($parent); - $this->assertInstanceOf(SeedDMS_Core_Folder::class, $parent); - $this->assertEquals(1, $parent->getId()); - } - - /** - * Test method setParent() on root folder - * - * Moving the root folder will always fail - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testSetParentRootFolder() - { - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $ret = $folder->setParent(1); - $this->assertFalse($ret); - } - - /** - * Test method getOwner() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetOwner() - { - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $owner = $folder->getOwner(); - $this->assertIsObject($owner); - $this->assertInstanceOf(SeedDMS_Core_User::class, $owner); - $this->assertEquals(1, $owner->getId()); - } - - /** - * Test method setOwner() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testSetOwner() - { - $adminuser = self::$dms->getUser(1); - $rootfolder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $user = self::$dms->addUser('user1', 'user1', 'User One', 'user1@seeddms.org', 'en_GB', 'bootstrap', ''); - $subfolder = $rootfolder->addSubFolder('Subfolder 1', '', $adminuser, 0); - $res = $subfolder->setOwner($user); - $this->assertTrue($res); - $owner = $subfolder->getOwner(); - $this->assertIsObject($owner); - $this->assertInstanceOf(SeedDMS_Core_User::class, $owner); - $this->assertEquals($user->getId(), $owner->getId()); - } - - /** - * Test method setOwner() - * - * @return void - */ - public function testSetOwnerSqlFail() - { - $rootfolder = $this->getMockedRootFolder(); - $user = new SeedDMS_Core_User(1, 'admin', 'pass', 'Joe Foo', 'baz@foo.de', 'en_GB', 'bootstrap', 'My comment', SeedDMS_Core_User::role_admin); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblFolders` SET `owner`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $rootfolder->setDMS($dms); - $this->assertFalse($rootfolder->setOwner($user)); - } - - /** - * Test method getDefaultAccess() - * - * The default access is always M_READ unless it was set differently - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetDefaultAccess() - { - $adminuser = self::$dms->getUser(1); - $rootfolder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $accessmode = $rootfolder->getDefaultAccess(); - $this->assertEquals(M_READ, $accessmode); - $subfolder = $rootfolder->addSubFolder('Subfolder 1', '', $adminuser, 0); - $accessmode = $subfolder->getDefaultAccess(); - $this->assertEquals(M_READ, $accessmode); - } - - /** - * Test method setDefaultAccess() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testSetDefaultAccess() - { - $adminuser = self::$dms->getUser(1); - $rootfolder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $subfolder = $rootfolder->addSubFolder('Subfolder 1', '', $adminuser, 0); - /* Setting the default access to something != M_READ will not have - * any effect as long as inheritage of access rights is turned on. - */ - $subfolder->setDefaultAccess(M_READWRITE, true); - $accessmode = $subfolder->getDefaultAccess(); - $this->assertEquals(M_READ, $accessmode); - /* Turning inheritage off will use the default access */ - $subfolder->setInheritAccess(false, true); - $accessmode = $subfolder->getDefaultAccess(); - $this->assertEquals(M_READWRITE, $accessmode); - } - - /** - * Test method setDefaultAccess() - * - * @return void - */ - public function testSetDefaultAccessSqlFail() - { - $rootfolder = $this->getMockedRootFolder(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblFolders` SET `defaultAccess`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $rootfolder->setDMS($dms); - $this->assertFalse($rootfolder->setDefaultAccess(M_NONE)); - } - - /** - * Test method setInheritAccess() - * - * @return void - */ - public function testSetInheritAccessSqlFail() - { - $rootfolder = $this->getMockedRootFolder(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblFolders` SET `inheritAccess`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $rootfolder->setDMS($dms); - $this->assertFalse($rootfolder->setInheritAccess(true)); - } - - /** - * Test method hasSubFolders() on root folder and after adding - * new subfolders. - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testHasSubFolders() - { - $user = self::$dms->getUser(1); - $rootfolder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $ret = $rootfolder->hasSubFolders(); - $this->assertIsInt($ret); - $this->assertEquals(0, $ret); - $subfolder1 = $rootfolder->addSubFolder('Subfolder 1', '', $user, 2.0); - $subfolder2 = $rootfolder->addSubFolder('Subfolder 2', '', $user, 1.0); - $ret = $rootfolder->hasSubFolders(); - $this->assertIsInt($ret); - $this->assertEquals(2, $ret); - /* hasSubFolderByName() just returns true or false */ - $ret = $rootfolder->hasSubFolderByName('Subfolder 1'); - $this->assertTrue($ret); - $ret = $rootfolder->hasSubFolderByName('Subfolder 3'); - $this->assertFalse($ret); - } - - /** - * Test method hasSubFolders with sql fail() - * - * @return void - */ - public function testHasSubFoldersSqlFail() - { - $rootfolder = $this->getMockedRootFolder(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT count(*) as c FROM `tblFolders`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $rootfolder->setDMS($dms); - $this->assertFalse($rootfolder->hasSubFolders()); - } - - /** - * Test method hasSubFolderByName with sql fail() - * - * @return void - */ - public function testHasSubFolderByNameSqlFail() - { - $rootfolder = $this->getMockedRootFolder(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT count(*) as c FROM `tblFolders`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $rootfolder->setDMS($dms); - $this->assertFalse($rootfolder->hasSubFolderByName('foo')); - } - - /** - * Test method getSubFolders() on root folder - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetSubFoldersRootOnly() - { - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $folders = $folder->getSubFolders(); - $this->assertIsArray($folders); - $this->assertCount(0, $folders); - } - - /** - * Test method getSubFolders() on root folder - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetSubFolders() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - $subfolder1 = $rootfolder->addSubFolder('Subfolder 1', '', $user, 2.0); - $subfolder2 = $rootfolder->addSubFolder('Subfolder 2', '', $user, 1.0); - $folders = $rootfolder->getSubFolders(); - $this->assertIsArray($folders); - $this->assertCount(2, $folders); - - /* Get sub folders order by name descending */ - $rootfolder->clearCache(); // Force retrieving sub folders from database - $folders = $rootfolder->getSubFolders('n', 'desc', 1, 0); - $this->assertIsArray($folders); - $this->assertCount(1, $folders); - $this->assertEquals('Subfolder 2', $folders[0]->getName()); - - /* Get sub folders order by name descending with an offset of 1 */ - $rootfolder->clearCache(); // Force retrieving sub folders from database - $folders = $rootfolder->getSubFolders('n', 'desc', 1, 1); - $this->assertIsArray($folders); - $this->assertCount(1, $folders); - $this->assertEquals('Subfolder 1', $folders[0]->getName()); - - /* Get sub folders order by sequence ascending */ - $rootfolder->clearCache(); // Force retrieving sub folders from database - $folders = $rootfolder->getSubFolders('s', 'asc', 1, 0); - $this->assertIsArray($folders); - $this->assertCount(1, $folders); - $this->assertEquals('Subfolder 2', $folders[0]->getName()); - - /* Get sub folders order by sequence ascending with a bogus offset */ - $rootfolder->clearCache(); // Force retrieving sub folders from database - $folders = $rootfolder->getSubFolders('s', 'asc', 0, 4); - $this->assertIsArray($folders); - $this->assertCount(2, $folders); - $this->assertEquals('Subfolder 2', $folders[0]->getName()); - } - - /** - * Test method getSubFolders() - * - * @return void - */ - public function testGetSubFoldersSqlFail() - { - $rootfolder = $this->getMockedRootFolder(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblFolders`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $rootfolder->setDMS($dms); - $this->assertFalse($rootfolder->getSubFolders()); - } - - /** - * Test method isDescendant() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testIsDescendant() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - $subfolder = $rootfolder->addSubFolder('Subfolder 1', '', $user, 2.0); - $subsubfolder = $subfolder->addSubFolder('Subsubfolder 1', '', $user, 1.0); - /* subsubfolder is a descendant of root folder */ - $this->assertTrue($subsubfolder->isDescendant($rootfolder)); - /* subfolder is not a descendant of subsubfolder */ - $this->assertFalse($subfolder->isDescendant($subsubfolder)); - } - - /** - * Test method isSubFolder() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testIsSubFolder() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - $subfolder = $rootfolder->addSubFolder('Subfolder 1', '', $user, 2.0); - $subsubfolder = $subfolder->addSubFolder('Subsubfolder 1', '', $user, 1.0); - $this->assertTrue($rootfolder->isSubFolder($subsubfolder)); - $this->assertFalse($subsubfolder->isSubFolder($subfolder)); - } - - /** - * Test method setParent() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testSetParent() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - $subfolder = $rootfolder->addSubFolder('Subfolder 1', '', $user, 2.0); - $subsubfolder = $subfolder->addSubFolder('Subsubfolder 1', '', $user, 1.0); - /* Add a new document for folderList checking afterwards */ - $document = self::createDocument($subsubfolder, $user, 'Document 1'); - $folderlist = $subsubfolder->getFolderList(); - $this->assertEquals(':1:2:', $folderlist); - $folderlist = $document->getFolderList(); - $this->assertEquals(':1:2:3:', $folderlist); - /* Making $subsubfolder parent of $subfolder will fail, because - * $subfolder is a parent of $subsubfolder - */ - $this->assertFalse($subfolder->setParent($subsubfolder)); - /* Moving $subsubfolder into rool folder is possible */ - $this->assertTrue($subsubfolder->setParent($rootfolder)); - /* Root folder has now two children */ - $children = $rootfolder->getSubFolders(); - $this->assertIsArray($children); - $this->assertCount(2, $children); - /* Move the folder will have changed the folder list. Check it */ - $errors = self::$dms->checkFolders(); - $this->assertIsArray($errors); - $this->assertCount(0, $errors); - $errors = self::$dms->checkDocuments(); - $this->assertIsArray($errors); - $this->assertCount(0, $errors); - } - - /** - * Test method getPath() on root folder - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetPathRootOnly() - { - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $path = $folder->getPath(); - $this->assertIsArray($path); - $this->assertCount(1, $path); - /* The only folder in the path is the root folder itself */ - $this->assertEquals(1, $path[0]->getId()); - } - - /** - * Test method getPath() on root folder - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetPath() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - $subfolder = $rootfolder->addSubFolder('Subfolder 1', '', $user, 2.0); - $subsubfolder = $subfolder->addSubFolder('Subsubfolder 1', '', $user, 1.0); - $path = $subsubfolder->getPath(); - $this->assertIsArray($path); - $this->assertCount(3, $path); - } - - /** - * Test method getFolderPathPlain() on root folder - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetFolderPathPlain() - { - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $path = $folder->getFolderPathPlain(); - $this->assertIsString($path); - $this->assertEquals('/ DMS', $path); - } - - /** - * Test method hasDocuments() on root folder - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testHasDocuments() - { - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $user = self::$dms->getUser(1); - $documents = $folder->hasDocuments(); - $this->assertIsInt($documents); - $this->assertEquals(0, $documents); - /* Add a new document for calling hasDocuments() afterwards */ - $document = self::createDocument($folder, $user, 'Document 1'); - $documents = $folder->hasDocuments(); - $this->assertIsInt($documents); - $this->assertEquals(1, $documents); - } - - /** - * Test method hasDocuments() - * - * @return void - */ - public function testHasDokumentsSqlFail() - { - $rootfolder = $this->getMockedRootFolder(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT count(*) as c FROM `tblDocuments`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $rootfolder->setDMS($dms); - $this->assertFalse($rootfolder->hasDocuments()); - } - - /** - * Test method hasDocumentByName() on root folder - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testHasDocumentByName() - { - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $user = self::$dms->getUser(1); - $res = $folder->hasDocumentByName('foo'); - $this->assertFalse($res); - /* Add a new document for calling hasDocumentByName() afterwards */ - $document = self::createDocument($folder, $user, 'Document 1'); - $res = $folder->hasDocumentByName('Document 1'); - $this->assertTrue($res); - } - - /** - * Test method hasDocumentByName() - * - * @return void - */ - public function testHasDokumentByNameSqlFail() - { - $rootfolder = $this->getMockedRootFolder(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT count(*) as c FROM `tblDocuments`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $rootfolder->setDMS($dms); - $this->assertFalse($rootfolder->hasDocumentByName('foo')); - } - - /** - * Test method getDocuments() on root folder - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetDocuments() - { - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $user = self::$dms->getUser(1); - $documents = $folder->getDocuments(); - $this->assertIsArray($documents); - $this->assertCount(0, $documents); - /* Add a new document for calling getDocuments() afterwards */ - $folder->clearCache(); - $document = self::createDocument($folder, $user, 'Document 1'); - $document = self::createDocument($folder, $user, 'Document 2'); - $documents = $folder->getDocuments(); - $this->assertIsArray($documents); - $this->assertCount(2, $documents); - $folder->clearCache(); - /* sort by name asc, limit 1, offset 0 */ - $documents = $folder->getDocuments('n', 'asc', 1); - $this->assertIsArray($documents); - $this->assertCount(1, $documents); - $this->assertEquals('Document 1', $documents[0]->getName()); - $folder->clearCache(); - /* sort by name desc, limit 1, offset 0 */ - $documents = $folder->getDocuments('n', 'desc', 1); - $this->assertIsArray($documents); - $this->assertCount(1, $documents); - $this->assertEquals('Document 2', $documents[0]->getName()); - $folder->clearCache(); - /* sort by name asc, limit 1, offset 1 */ - $documents = $folder->getDocuments('n', 'asc', 1, 1); - $this->assertIsArray($documents); - $this->assertCount(1, $documents); - $this->assertEquals('Document 2', $documents[0]->getName()); - } - - /** - * Test method getDocuments() - * - * @return void - */ - public function testGetDokumentsSqlFail() - { - $rootfolder = $this->getMockedRootFolder(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT `tblDocuments`.*, `tblDocumentLocks`.`userID` as `lock` FROM `tblDocuments`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $rootfolder->setDMS($dms); - $this->assertFalse($rootfolder->getDocuments()); - } - - /** - * Test method countChildren() on root folder - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testCountChildren() - { - $folder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $user = self::$dms->getUser(1); - $count = $folder->countChildren($user, 0); - $this->assertIsArray($count); - $this->assertCount(4, $count); - $this->assertEquals(0, $count['folder_count']); - $this->assertEquals(0, $count['document_count']); - /* Add some folders and documents */ - $this->createSimpleFolderStructure(); - $document = self::createDocument($folder, $user, 'Document 1'); - $count = $folder->countChildren($user, 6); - $this->assertIsArray($count); - $this->assertCount(4, $count); - $this->assertEquals(5, $count['folder_count']); - $this->assertEquals(1, $count['document_count']); - } - - /** - * Test method emptyFolder() on root folder - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testEmptyFolder() - { - $rootfolder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $user = self::$dms->getUser(1); - /* Add some folders and documents */ - $this->createSimpleFolderStructure(); - $document = self::createDocument($rootfolder, $user, 'Document 1'); - $res = $rootfolder->emptyFolder(); - $this->assertTrue($res); - } - - /** - * Test method emptyFolder() on root folder - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testEmptyFolderWithCallback() - { - $rootfolder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $user = self::$dms->getUser(1); - /* Add some folders and documents */ - $this->createSimpleFolderStructure(); - $document = self::createDocument($rootfolder, $user, 'Document 1'); - - /* Add the 'onPostAddUser' callback */ - $msgs = []; - $callback = function ($param, $object) use (&$msgs) { - $msgs[] = $param." ".$object->getName(). " (".$object->getId().")"; - }; - self::$dms->addCallback('onPreRemoveFolder', $callback, 'onPreRemoveFolder'); - self::$dms->addCallback('onPostRemoveFolder', $callback, 'onPostRemoveFolder'); - self::$dms->addCallback('onPreRemoveDocument', $callback, 'onPreRemoveDocument'); - self::$dms->addCallback('onPostRemoveDocument', $callback, 'onPostRemoveDocument'); - self::$dms->addCallback('onPreEmptyFolder', $callback, 'onPreEmptyFolder'); - self::$dms->addCallback('onPostEmptyFolder', $callback, 'onPostEmptyFolder'); - - $res = $rootfolder->emptyFolder(); - $this->assertTrue($res); - $this->assertIsArray($msgs); - $this->assertCount(14, $msgs); // 5 folders x 2 callbacks + 1 document x 2 callbacks + 2 emptyFolder callbacks - } - - /** - * Test method getAccessList() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAccessList() - { - /* Add some folders and documents */ - $this->createSimpleFolderStructure(); - $this->createGroupsAndUsers(); - - $rootfolder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $user = self::$dms->getUser(1); - $this->assertIsObject($user); - $group = self::$dms->getGroup(1); - $this->assertIsObject($group); - $subfolder = self::$dms->getFolderByName('Subfolder 1'); - $this->assertIsObject($subfolder); - $subsubfolder = self::$dms->getFolderByName('Subsubfolder 1'); - $this->assertIsObject($subsubfolder); - - /* Adding an access rule will have no effect until the inheritance - * is turned off. - */ - $subfolder->addAccess(M_NONE, $user->getId(), true); - $subfolder->addAccess(M_READWRITE, $group->getId(), false); - $accesslist = $subfolder->getAccessList(); - $this->assertIsArray($accesslist); - $this->assertCount(0, $accesslist['users']); - $this->assertCount(0, $accesslist['groups']); - /* Turn inheritance off */ - $res = $subfolder->setInheritAccess(false); - $this->assertTrue($res); - /* Now the access rules on $subfolder take effect */ - $accesslist = $subfolder->getAccessList(); - $this->assertIsArray($accesslist); - $this->assertCount(1, $accesslist['users']); - $this->assertCount(1, $accesslist['groups']); - /* get list of users/groups which no access */ - $accesslist = $subfolder->getAccessList(M_NONE, O_EQ); - $this->assertIsArray($accesslist); - $this->assertCount(1, $accesslist['users']); - $this->assertCount(0, $accesslist['groups']); - /* get list of users/groups which read+write access */ - $accesslist = $subfolder->getAccessList(M_READWRITE, O_EQ); - $this->assertIsArray($accesslist); - $this->assertCount(0, $accesslist['users']); - $this->assertCount(1, $accesslist['groups']); - /* get list of users/groups which have at least read access */ - $accesslist = $subfolder->getAccessList(M_READ, O_GTEQ); - $this->assertIsArray($accesslist); - $this->assertCount(0, $accesslist['users']); - $this->assertCount(1, $accesslist['groups']); - /* get list of users/groups which have at least unlimited access */ - $accesslist = $subfolder->getAccessList(M_ALL, O_GTEQ); - $this->assertIsArray($accesslist); - $this->assertCount(0, $accesslist['users']); - $this->assertCount(0, $accesslist['groups']); - /* Subsubfolder 1 inherits from Subfolder 1 */ - $accesslist = $subsubfolder->getAccessList(); - $this->assertIsArray($accesslist); - $this->assertCount(1, $accesslist['users']); - $this->assertCount(1, $accesslist['groups']); - /* clear the access list */ - $res = $subfolder->clearAccessList(); - $this->assertTrue($res); - $accesslist = $subfolder->getAccessList(); - $this->assertIsArray($accesslist); - $this->assertCount(0, $accesslist['users']); - $this->assertCount(0, $accesslist['groups']); - /* calling getAccessList() on the $subsubfolder will still return - * the user and group, because the getParent() call in getAccessList() - * will not return the same instance like $subfolder. Hence calling - * $subfolder->clearAccessList() won't clear the accesslist of $subsubfolder's - * parent. You would have to explicitly - * clear acceslist of $subsubfolder's parent. - $res = $subsubfolder->getParent()->clearAccessList(); - $this->assertTrue($res); - $accesslist = $subsubfolder->getAccessList(); - $this->assertIsArray($accesslist); - $this->assertCount(0, $accesslist['users']); - $this->assertCount(0, $accesslist['groups']); - */ - } - - /** - * Test method addAccess() - * - * @return void - */ - public function testAddAccessWrongMode() - { - $rootfolder = $this->getMockedRootFolder(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $dms = new SeedDMS_Core_DMS($db, ''); - $rootfolder->setDMS($dms); - $this->assertFalse($rootfolder->addAccess(M_ANY, 1, true)); - } - - /** - * Test method addAccess() - * - * @return void - */ - public function testAddAccessSqlFail() - { - $rootfolder = $this->getMockedRootFolder(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("INSERT INTO `tblACLs`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $rootfolder->setDMS($dms); - $this->assertFalse($rootfolder->addAccess(M_NONE, 1, true)); - } - - /** - * Test method getAccessMode() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAccessMode() - { - /* Add some folders and documents */ - $this->createSimpleFolderStructureWithDocuments(); - $this->createGroupsAndUsers(); - - $rootfolder = SeedDMS_Core_Folder::getInstance(1, self::$dms); - $admin = self::$dms->getUser(1); - $this->assertIsObject($admin); - $this->assertTrue($admin->isAdmin()); - $guest = self::$dms->getUser(2); - $this->assertTrue($guest->isGuest()); - $user = self::$dms->getUser(3); - $this->assertIsObject($user); - if(self::$dms->version[0] == '5') - $this->assertTrue($user->getRole() == SeedDMS_Core_User::role_user); - else - $this->assertTrue($user->getRole()->getRole() == SeedDMS_Core_Role::role_user); - $joe = self::$dms->getUser(4); - $this->assertIsObject($joe); - if(self::$dms->version[0] == '5') - $this->assertTrue($joe->getRole() == SeedDMS_Core_User::role_user); - else - $this->assertTrue($joe->getRole()->getRole() == SeedDMS_Core_Role::role_user); - $sally = self::$dms->getUser(6); - $this->assertIsObject($sally); - if(self::$dms->version[0] == '5') - $this->assertTrue($sally->getRole() == SeedDMS_Core_User::role_user); - else - $this->assertTrue($sally->getRole()->getRole() == SeedDMS_Core_Role::role_user); - $group = self::$dms->getGroup(1); - $this->assertIsObject($group); - /* add guest and joe to group */ - if(!$group->isMember($guest)) { - $res = $guest->joinGroup($group); - $this->assertTrue($res); - } - if(!$group->isMember($joe)) { - $res = $joe->joinGroup($group); - $this->assertTrue($res); - } - - $subfolder1 = self::$dms->getFolderByName('Subfolder 1'); - $this->assertIsObject($subfolder1); - $subsubfolder = self::$dms->getFolderByName('Subsubfolder 1'); - $this->assertIsObject($subsubfolder); - $subfolder2 = self::$dms->getFolderByName('Subfolder 2'); - $this->assertIsObject($subfolder2); - $subfolder3 = self::$dms->getFolderByName('Subfolder 3'); - $this->assertIsObject($subfolder3); - $res = $subfolder3->setOwner($sally); - $this->assertTrue($res); - - /* Setup Subfolder 1: - * no inheritance, user has read-write access, group has unlimited access, - * default is no access - */ - $res = $subfolder1->setInheritAccess(false); - $this->assertTrue($res); - $res = $subfolder1->setDefaultAccess(M_NONE); - $this->assertTrue($res); - $res = $subfolder1->addAccess(M_READWRITE, $user->getId(), true); - $this->assertTrue($res); - $res = $subfolder1->addAccess(M_ALL, $group->getId(), false); - $this->assertTrue($res); - - /* Admin has always access mode M_ALL */ - $mode = $subfolder1->getAccessMode($admin); - $this->assertEquals(M_ALL, $mode); - /* Guest has max read access, though it's group has any access */ - $mode = $subfolder1->getAccessMode($guest); - $this->assertEquals(M_READ, $mode); - /* Joe has any access, because it's group has any access */ - $mode = $subfolder1->getAccessMode($joe); - $this->assertEquals(M_ALL, $mode); - /* Sally has no access, because it has no explicit access right and the - * default access is M_NONE. - */ - $mode = $subfolder1->getAccessMode($sally); - $this->assertEquals(M_NONE, $mode); - - /* Subfolder 3 inherits from the root folder, but sally is the owner */ - $mode = $subfolder3->getAccessMode($sally); - $this->assertEquals(M_ALL, $mode); - /* joe has just read access which is the default inherited from root */ - $mode = $subfolder3->getAccessMode($joe); - $this->assertEquals(M_READ, $mode); - - } - - /** - * Test method getFolderList() - * - * @return void - */ - public function testGetFolderListSqlFail() - { - $rootfolder = $this->getMockedRootFolder(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT `folderList` FROM `tblFolders`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $rootfolder->setDMS($dms); - $this->assertFalse($rootfolder->getFolderList()); - } - -} diff --git a/SeedDMS_Core/tests/GroupTest.php b/SeedDMS_Core/tests/GroupTest.php deleted file mode 100644 index df14a13f5..000000000 --- a/SeedDMS_Core/tests/GroupTest.php +++ /dev/null @@ -1,410 +0,0 @@ - - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version @package_version@ - * @link https://www.seeddms.org - */ - -use PHPUnit\Framework\SeedDmsTest; - -/** - * Group test class - * - * @category SeedDMS - * @package Tests - * @author Uwe Steinmann - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version Release: @package_version@ - * @link https://www.seeddms.org - */ -class GroupTest extends SeedDmsTest -{ - - /** - * Create a real sqlite database in memory - * - * @return void - */ - protected function setUp(): void - { - self::$dbh = self::createInMemoryDatabase(); - self::$contentdir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'phpunit-'.time(); - mkdir(self::$contentdir); - // echo "Creating temp content dir: ".self::$contentdir."\n"; - self::$dms = new SeedDMS_Core_DMS(self::$dbh, self::$contentdir); - self::$dbversion = self::$dms->getDBVersion(); - } - - /** - * Clean up at tear down - * - * @return void - */ - protected function tearDown(): void - { - self::$dbh = null; - // echo "\nRemoving temp. content dir: ".self::$contentdir."\n"; - exec('rm -rf '.self::$contentdir); - } - - /** - * Create a mock group object - * - * @return SeedDMS_Core_Group - */ - protected function getMockGroup() - { - $user = $this->getMockBuilder(SeedDMS_Core_Group::class) - ->onlyMethods([]) - ->disableOriginalConstructor()->getMock(); - return $user; - } - - /** - * Create a mock group object - * - * @return SeedDMS_Core_Group - */ - protected function getGroup() - { - $group = new SeedDMS_Core_Group(1, 'foogroup', 'My comment'); - return $group; - } - - /** - * Create a mock regular user object - * - * @return SeedDMS_Core_User - */ - protected function getUser() - { - $user = new SeedDMS_Core_User(2, 'user', 'pass', 'Joe Baz', 'joe@foo.de', 'en_GB', 'bootstrap', 'My comment', SeedDMS_Core_User::role_user); - return $user; - } - - /** - * Test method isType() - * - * @return void - */ - public function testIsType() - { - $group = $this->getGroup(); - $this->assertTrue($group->isType('group')); - } - - /** - * Test method getName() - * - * @return void - */ - public function testGetName() - { - $group = $this->getGroup(); - $this->assertEquals('foogroup', $group->getName()); - } - - /** - * Test method getName() and setName() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetName() - { - $group = self::$dms->addGroup('Group', ''); - $ret = $group->setName('foo'); - $this->assertTrue($ret); - $name = $group->getName(); - $this->assertEquals('foo', $name); - /* Setting an empty name must fail */ - $ret = $group->setName(' '); - $this->assertFalse($ret); - } - - /** - * Test method setName() - * - * @return void - */ - public function testSetNameSqlFail() - { - $group = $this->getGroup(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblGroups` SET `name`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $group->setDMS($dms); - $this->assertFalse($group->setName('my name')); - } - - /** - * Test method getComment() - * - * @return void - */ - public function testGetComment() - { - $group = $this->getGroup(); - $this->assertEquals('My comment', $group->getComment()); - } - - /** - * Test method getComment() and setComment() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetComment() - { - $group = self::$dms->addGroup('Group', ''); - $ret = $group->setComment('foo'); - $this->assertTrue($ret); - $comment = $group->getComment(); - $this->assertEquals('foo', $comment); - } - - /** - * Test method setComment() - * - * @return void - */ - public function testSetCommentSqlFail() - { - $group = $this->getGroup(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblGroups` SET `comment`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $group->setDMS($dms); - $this->assertFalse($group->setComment('my comment')); - } - - /** - * Test method getUsers() - * - * @return void - */ - public function testGetUsersSqlFail() - { - $group = $this->getGroup(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT `tblUsers`.* FROM `tblUsers`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $group->setDMS($dms); - $this->assertFalse($group->getUsers()); - } - - /** - * Test method addUser(), isMember(), and removeUser() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testAddAndRemoveUser() - { - $group = self::$dms->addGroup('Group', ''); - if(self::$dms->version[0] == '5') - $role = SeedDMS_Core_User::role_user; - else { - $role = SeedDMS_Core_Role::getInstance(3, self::$dms); - $this->assertIsObject($role); - $this->assertEquals($role->getRole(), SeedDMS_Core_Role::role_user); - } - $user1 = self::$dms->addUser('joe', 'pass', 'Joe Foo', 'joe@foo.de', 'en_GB', 'bootstrap', 'My comment', $role); - $user2 = self::$dms->addUser('sally', 'pass', 'Sally Foo', 'sally@foo.de', 'en_GB', 'bootstrap', 'My comment', $role); - - /* Add user1 and user2. user2 is also a manager */ - $ret = $group->addUser($user1); - $this->assertTrue($ret); - $ret = $group->addUser($user2, true); - $this->assertTrue($ret); - - $users = $group->getUsers(); - $this->assertIsArray($users); - $this->assertCount(2, $users); - - $ret = $group->removeUser($user1); - $this->assertTrue($ret); - $users = $group->getUsers(); - $this->assertIsArray($users); - $this->assertCount(1, $users); - } - - /** - * Test method isMember(), toggleManager() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testIsMember() - { - $group = self::$dms->addGroup('Group', ''); - $user1 = self::$dms->addUser('joe', 'pass', 'Joe Foo', 'joe@foo.de', 'en_GB', 'bootstrap', 'My comment'); - $user2 = self::$dms->addUser('sally', 'pass', 'Sally Foo', 'sally@foo.de', 'en_GB', 'bootstrap', 'My comment'); - - /* Add user1 and user2. user2 is also a manager */ - $ret = $group->addUser($user1); - $this->assertTrue($ret); - $ret = $group->addUser($user2, true); - $this->assertTrue($ret); - - /* user1 is a member but not a manager */ - $ret = $group->isMember($user1); - $this->assertTrue($ret); - $ret = $group->isMember($user1, true); - $this->assertFalse($ret); - - /* user2 is a member and a manager */ - $ret = $group->isMember($user2, true); - $this->assertTrue($ret); - } - - /** - * Test method toggleManager() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testToggleManager() - { - $group = self::$dms->addGroup('Group', ''); - $user1 = self::$dms->addUser('joe', 'pass', 'Joe Foo', 'joe@foo.de', 'en_GB', 'bootstrap', 'My comment'); - - /* Add user1 */ - $ret = $group->addUser($user1); - $this->assertTrue($ret); - - /* user1 is a member but not a manager */ - $ret = $group->isMember($user1); - $this->assertTrue($ret); - $ret = $group->isMember($user1, true); - $this->assertFalse($ret); - - /* Toggle manager mode of user 1 and check again */ - $ret = $group->toggleManager($user1); - $ret = $group->isMember($user1, true); - $this->assertTrue($ret); - } - - /** - * Test method getUsers() - * - * @return void - */ - public function testGetUsers() - { - $group = $this->getGroup(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - if(self::$dbversion['major'] == 6) { - $db->expects($this->exactly(2)) - ->method('getResultArray') - ->withConsecutive([$this->stringContains("`tblGroupMembers`.`groupID` = '".$group->getId()."'")], [$this->stringContains("SELECT * FROM `tblRoles` WHERE `id` =")]) - ->willReturnOnConsecutiveCalls(array(array('id'=>2, 'login'=>'user', 'pwd'=>'pass', 'fullName'=>'Joe Baz', 'email'=>'joe@foo.de', 'language'=>'en_GB', 'theme'=>'bootstrap', 'comment'=>'', 'role'=>SeedDMS_Core_User::role_user, 'hidden'=>0, 'role'=>1)), array('id'=>1, 'name'=>'role', 'role'=>1, 'noaccess'=>'')); - } else { - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("`tblGroupMembers`.`groupID` = '".$group->getId()."'")) - ->willReturn(array(array('id'=>2, 'login'=>'user', 'pwd'=>'pass', 'fullName'=>'Joe Baz', 'email'=>'joe@foo.de', 'language'=>'en_GB', 'theme'=>'bootstrap', 'comment'=>'', 'role'=>SeedDMS_Core_User::role_user, 'hidden'=>0, 'role'=>1))); - } - $dms = new SeedDMS_Core_DMS($db, ''); - - $group->setDMS($dms); - $users = $group->getUsers(); - $this->assertIsArray($users); - $this->assertCount(1, $users); - } - - /** - * Test method getManagers() - * - * @return void - */ - public function testGetManagers() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - if(self::$dbversion['major'] == 6) { - $db->expects($this->exactly(2)) - ->method('getResultArray') - ->withConsecutive([$this->stringContains("`manager` = 1")], [$this->stringContains("SELECT * FROM `tblRoles` WHERE `id` =")]) - ->willReturnOnConsecutiveCalls(array(array('id'=>2, 'login'=>'user', 'pwd'=>'pass', 'fullName'=>'Joe Baz', 'email'=>'joe@foo.de', 'language'=>'en_GB', 'theme'=>'bootstrap', 'comment'=>'', 'role'=>SeedDMS_Core_User::role_user, 'hidden'=>0, 'role'=>1)), array('id'=>1, 'name'=>'role', 'role'=>1, 'noaccess'=>'')); - } else { - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains('`manager` = 1')) - ->willReturn(array(array('id'=>2, 'login'=>'user', 'pwd'=>'pass', 'fullName'=>'Joe Baz', 'email'=>'joe@foo.de', 'language'=>'en_GB', 'theme'=>'bootstrap', 'comment'=>'', 'role'=>SeedDMS_Core_User::role_user, 'hidden'=>0))); - } - $dms = new SeedDMS_Core_DMS($db, ''); - - $group = $this->getGroup(); - $group->setDMS($dms); - $managers = $group->getManagers(); - $this->assertIsArray($managers); - $this->assertCount(1, $managers); - } - - /** - * Test method getNotifications() - * - * @return void - */ - public function testGetNotifications() - { - $group = $this->getGroup(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("WHERE `tblNotify`.`groupID` = ".$group->getId())) - ->willReturn(array(array('target'=>2, 'targetType'=>'0', 'userID'=>0, 'groupID'=>$group->getId()))); - $dms = new SeedDMS_Core_DMS($db, ''); - $group->setDMS($dms); - $notifications = $group->getNotifications(); - $this->assertIsArray($notifications); - $this->assertCount(1, $notifications); - $this->assertInstanceOf(SeedDMS_Core_Notification::class, $notifications[0]); - } - - /** - * Test method getNotifications() with target type - * - * @return void - */ - public function testGetNotificationsWithTargetType() - { - $group = $this->getGroup(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("WHERE `tblNotify`.`groupID` = ".$group->getId()." AND `tblNotify`.`targetType` = 1")) - ->willReturn(array(array('target'=>2, 'targetType'=>'1', 'userID'=>0, 'groupID'=>$group->getId()))); - $dms = new SeedDMS_Core_DMS($db, ''); - $group->setDMS($dms); - $notifications = $group->getNotifications(1); - $this->assertIsArray($notifications); - $this->assertCount(1, $notifications); - $this->assertInstanceOf(SeedDMS_Core_Notification::class, $notifications[0]); - } - - -} diff --git a/SeedDMS_Core/tests/KeywordCategoryTest.php b/SeedDMS_Core/tests/KeywordCategoryTest.php deleted file mode 100644 index e22d138ed..000000000 --- a/SeedDMS_Core/tests/KeywordCategoryTest.php +++ /dev/null @@ -1,147 +0,0 @@ - - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version @package_version@ - * @link https://www.seeddms.org - */ - -use PHPUnit\Framework\SeedDmsTest; - -/** - * User test class - * - * @category SeedDMS - * @package Tests - * @author Uwe Steinmann - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version Release: @package_version@ - * @link https://www.seeddms.org - */ -class KeywordCategoryTest extends SeedDmsTest -{ - - /** - * Create a real sqlite database in memory - * - * @return void - */ - protected function setUp(): void - { - self::$dbh = self::createInMemoryDatabase(); - self::$contentdir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'phpunit-'.time(); - mkdir(self::$contentdir); - // echo "Creating temp content dir: ".self::$contentdir."\n"; - self::$dms = new SeedDMS_Core_DMS(self::$dbh, self::$contentdir); - } - - /** - * Clean up at tear down - * - * @return void - */ - protected function tearDown(): void - { - self::$dbh = null; - // echo "\nRemoving temp. content dir: ".self::$contentdir."\n"; - exec('rm -rf '.self::$contentdir); - } - - /** - * Test method getName() and setName() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetName() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $cat = self::$dms->addKeywordCategory($user->getId(), 'Category 1'); - $name = $cat->getName(); - $ret = $cat->setName('foo'); - $this->assertTrue($ret); - $name = $cat->getName(); - $this->assertEquals('foo', $name); - $ret = $cat->setName(' '); - $this->assertFalse($ret); - } - - /** - * Test method getOwner() and setOwner() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetOwner() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $guest = SeedDMS_Core_User::getInstance(2, self::$dms); - $cat = self::$dms->addKeywordCategory($user->getId(), 'Category 1'); - $this->assertIsObject($cat); - $ret = $cat->setOwner($guest); - $this->assertTrue($ret); - $owner = $cat->getOwner(); - $this->assertEquals(2, $owner->getId()); - $ret = $cat->setOwner(null); - $this->assertFalse($ret); - } - - /** - * Test method addKeywordList() and editKeywordList(), getKeywordLists(), removeKeywordList() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetSetEditAndRemoveKeywordList() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $cat = self::$dms->addKeywordCategory($user->getId(), 'Category 1'); - $this->assertIsObject($cat); - $ret = $cat->addKeywordList('foo'); - $this->assertTrue($ret); - $ret = $cat->addKeywordList('bar'); - $this->assertTrue($ret); - $list = $cat->getKeywordLists(); - $this->assertIsArray($list); - $this->assertCount(2, $list); - $ret = $cat->editKeywordList(1, 'baz'); - $this->assertTrue($ret); - - $ret = $cat->removeKeywordList(1); - $this->assertTrue($ret); - $list = $cat->getKeywordLists(); - $this->assertIsArray($list); - $this->assertCount(1, $list); - } - - /** - * Test method addKeywordCategory() and remove() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testAndAndRemoveKeywordCategory() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $cat = self::$dms->addKeywordCategory($user->getId(), 'Category 1'); - $this->assertIsObject($cat); - $ret = $cat->addKeywordList('foo'); - $this->assertTrue($ret); - $ret = $cat->addKeywordList('bar'); - $this->assertTrue($ret); - $ret = $cat->remove(); - $this->assertTrue($ret); - } -} diff --git a/SeedDMS_Core/tests/ReviewApprovalTest.php b/SeedDMS_Core/tests/ReviewApprovalTest.php deleted file mode 100644 index aea040e39..000000000 --- a/SeedDMS_Core/tests/ReviewApprovalTest.php +++ /dev/null @@ -1,477 +0,0 @@ - - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version @package_version@ - * @link https://www.seeddms.org - */ - -use PHPUnit\Framework\SeedDmsTest; - -/** - * Group test class - * - * @category SeedDMS - * @package Tests - * @author Uwe Steinmann - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version Release: @package_version@ - * @link https://www.seeddms.org - */ -class ReviewApprovalTest extends SeedDmsTest -{ - - /** - * Create a real sqlite database in memory - * - * @return void - */ - protected function setUp(): void - { - self::$dbh = self::createInMemoryDatabase(); - self::$contentdir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'phpunit-'.time(); - mkdir(self::$contentdir); - // echo "Creating temp content dir: ".self::$contentdir."\n"; - self::$dms = new SeedDMS_Core_DMS(self::$dbh, self::$contentdir); - } - - /** - * Clean up at tear down - * - * @return void - */ - protected function tearDown(): void - { - self::$dbh = null; - // echo "\nRemoving temp. content dir: ".self::$contentdir."\n"; - exec('rm -rf '.self::$contentdir); - } - - /** - * Test method addIndReviewer(), addGrpReviewer(), verifyStatus(), - * getReviewStatus(), removeReview(), delIndReviewer() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testReviewDocumentByUserAndGroup() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - $this->assertIsObject($user); - - /* Add a new user who will be the reviewer */ - $reviewer = self::$dms->addUser('reviewer', 'reviewer', 'Reviewer One', 'user1@seeddms.org', 'en_GB', 'bootstrap', ''); - $this->assertIsObject($reviewer); - - /* Add a new group which will be the reviewer */ - $reviewergrp = self::$dms->addGroup('reviewer', ''); - $this->assertIsObject($reviewergrp); - - /* Add a new document */ - $document = self::createDocument($rootfolder, $user, 'Document 1'); - $content = $document->getLatestContent(); - $this->assertIsObject($content); - $status = $content->getStatus(); - $this->assertIsArray($status); - $this->assertEquals(S_RELEASED, $status['status']); - - /* A missing reviewer or user causes an error */ - $ret = $content->addIndReviewer($reviewer, null); - $this->assertEquals(-1, $ret); - - /* A missing reviewer or user causes an error */ - $ret = $content->addIndReviewer(null, $user); - $this->assertEquals(-1, $ret); - - /* Adding a group instead of a user causes an error */ - $ret = $content->addIndReviewer($reviewergrp, $user); - $this->assertEquals(-1, $ret); - - /* Finally add the reviewer */ - $ret = $content->addIndReviewer($reviewer, $user); - $this->assertGreaterThan(0, $ret); - - /* Adding the user again will yield in an error */ - $ret = $content->addIndReviewer($reviewer, $user); - $this->assertEquals(-3, $ret); - - /* Needs to call verifyStatus() in order to recalc the status */ - $newstatus = $content->verifyStatus(false, $user); - $this->assertIsInt($newstatus); - $this->assertEquals(S_DRAFT_REV, $newstatus); - - /* Get all reviews */ - $reviewstatus = $content->getReviewStatus(); - $this->assertIsArray($reviewstatus); - $this->assertCount(1, $reviewstatus); - - /* Get list of individual und group reviewers */ - $reviewers = $content->getReviewers(); - $this->assertIsArray($reviewers); - $this->assertCount(2, $reviewers); - $this->assertCount(1, $reviewers['i']); - $this->assertCount(0, $reviewers['g']); -/* - $db = self::$dms->getDB(); - $db->createTemporaryTable("ttreviewid", true); - $queryStr = "SELECT * FROM ttreviewid"; - $recs = $db->getResultArray($queryStr); - echo $db->getErrorMsg(); - var_dump($recs); -*/ - - /* A missing reviewer or user causes an error */ - $ret = $content->addGrpReviewer($reviewergrp, null); - $this->assertEquals(-1, $ret); - - /* A missing reviewer or user causes an error */ - $ret = $content->addGrpReviewer(null, $user); - $this->assertEquals(-1, $ret); - - /* Adding a user instead of a group causes an error */ - $ret = $content->addGrpReviewer($reviewer, $user); - $this->assertEquals(-1, $ret); - - /* Finally add the reviewer */ - $ret = $content->addGrpReviewer($reviewergrp, $user); - $this->assertGreaterThan(0, $ret); - $groupstatus = $reviewergrp->getReviewStatus(); - - /* Adding the group again will yield in an error */ - $ret = $content->addGrpReviewer($reviewergrp, $user); - $this->assertEquals(-3, $ret); - - /* Get all reviews */ - $reviewstatus = $content->getReviewStatus(); - $this->assertIsArray($reviewstatus); - $this->assertCount(2, $reviewstatus); - - /* Get list of individual und group reviewers */ - $reviewers = $content->getReviewers(); - $this->assertIsArray($reviewers); - $this->assertCount(2, $reviewers); - $this->assertCount(1, $reviewers['i']); - $this->assertCount(1, $reviewers['g']); - - $userstatus = $reviewer->getReviewStatus(); - $groupstatus = $reviewergrp->getReviewStatus(); - - /* There should be two log entries, one for each reviewer */ - $reviewlog = $content->getReviewLog(5); - $this->assertIsArray($reviewlog); - $this->assertCount(2, $reviewlog); - - /* Adding a review without a user of reviewer causes an error */ - $ret = $content->setReviewByInd($reviewer, null, S_LOG_ACCEPTED, 'Comment of individual reviewer'); - $this->assertEquals(-1, $ret); - $ret = $content->setReviewByInd(null, $user, S_LOG_ACCEPTED, 'Comment of individual reviewer'); - $this->assertEquals(-1, $ret); - - /* Adding a review as an individual but passing a group causes an error */ - $ret = $content->setReviewByInd($reviewergrp, $user, S_LOG_ACCEPTED, 'Comment of individual reviewer'); - $this->assertEquals(-1, $ret); - - /* Individual reviewer reviews document */ - $ret = $content->setReviewByInd($reviewer, $user, S_LOG_ACCEPTED, 'Comment of individual reviewer'); - $this->assertIsInt(0, $ret); - $this->assertGreaterThan(0, $ret); - - /* Get the last 5 review log entries (actually there are just 3 now) */ - $reviewlog = $content->getReviewLog(5); - $this->assertIsArray($reviewlog); - $this->assertCount(3, $reviewlog); - $this->assertEquals('Comment of individual reviewer', $reviewlog[0]['comment']); - $this->assertEquals(1, $reviewlog[0]['status']); - - /* Needs to call verifyStatus() in order to recalc the status. - * It must not be changed because the group reviewer has not done the - * review. - */ - $newstatus = $content->verifyStatus(false, $user); - $this->assertIsInt($newstatus); - $this->assertEquals(S_DRAFT_REV, $newstatus); - - /* Adding a review without a user of reviewer causes an error */ - $ret = $content->setReviewByGrp($reviewergrp, null, S_LOG_ACCEPTED, 'Comment of group reviewer'); - $this->assertEquals(-1, $ret); - $ret = $content->setReviewByGrp(null, $user, S_LOG_ACCEPTED, 'Comment of group reviewer'); - $this->assertEquals(-1, $ret); - - /* Adding a review as an group but passing a user causes an error */ - $ret = $content->setReviewByGrp($reviewer, $user, S_LOG_ACCEPTED, 'Comment of group reviewer'); - $this->assertEquals(-1, $ret); - - /* Group reviewer reviews document */ - $ret = $content->setReviewByGrp($reviewergrp, $user, S_LOG_ACCEPTED, 'Comment of group reviewer'); - $this->assertIsInt(0, $ret); - $this->assertGreaterThan(0, $ret); - - /* Get the last 5 review log entries (actually there are just 4 now) */ - $reviewlog = $content->getReviewLog(5); - $this->assertIsArray($reviewlog); - $this->assertCount(4, $reviewlog); - $this->assertEquals('Comment of group reviewer', $reviewlog[0]['comment']); - $this->assertEquals(1, $reviewlog[0]['status']); - - /* Now the document has received all reviews */ - $newstatus = $content->verifyStatus(false, $user); - $this->assertIsInt($newstatus); - $this->assertEquals(S_RELEASED, $newstatus); - - /* Remove the last review of the user */ - $userstatus = $reviewer->getReviewStatus($document->getId(), $content->getVersion()); - $this->assertIsArray($userstatus); - $this->assertCount(2, $userstatus); - $this->assertCount(1, $userstatus['indstatus']); - $ret = $content->removeReview($userstatus['indstatus'][$document->getId()]['reviewID'], $user, 'Undo review'); - $this->assertTrue($ret); - - /* Get the last 8 review log entries (actually there are just 5 now) */ - $reviewlog = $content->getReviewLog(8); - $this->assertIsArray($reviewlog); - $this->assertCount(5, $reviewlog); - $this->assertEquals('Undo review', $reviewlog[0]['comment']); - $this->assertEquals(0, $reviewlog[0]['status']); - - /* Now the document must be back in draft mode */ - $newstatus = $content->verifyStatus(false, $user); - $this->assertIsInt($newstatus); - $this->assertEquals(S_DRAFT_REV, $newstatus); - - /* Removing the user as a reviewer completly will release the - * document again, because the group reviewer became the only - * reviewer and has done the review already. - */ - $ret = $content->delIndReviewer($reviewer, $user, 'Reviewer removed'); - $this->assertIsInt($ret); - $this->assertEquals(0, $ret); - - /* Get the last 8 review log entries (actually there are just 6 now) */ - $reviewlog = $content->getReviewLog(8); - $this->assertIsArray($reviewlog); - $this->assertCount(6, $reviewlog); - $this->assertEquals('Reviewer removed', $reviewlog[0]['comment']); - $this->assertEquals(-2, $reviewlog[0]['status']); - - /* Now the document will be released again */ - $newstatus = $content->verifyStatus(false, $user); - $this->assertIsInt($newstatus); - $this->assertEquals(S_RELEASED, $newstatus); - } - - /** - * Test method addIndApprover(), addGrpApprover(), verifyStatus(), - * getApprovalStatus(), removeApproval(), delIndApprover() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testApproveDocumentByUserAndGroup() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - $this->assertIsObject($user); - - /* Add a new user who will be the approver */ - $approver = self::$dms->addUser('approver', 'approver', 'Approver One', 'user1@seeddms.org', 'en_GB', 'bootstrap', ''); - $this->assertIsObject($approver); - - /* Add a new group which will be the approver */ - $approvergrp = self::$dms->addGroup('approver', ''); - $this->assertIsObject($approvergrp); - - /* Add a new document */ - $document = self::createDocument($rootfolder, $user, 'Document 1'); - $content = $document->getLatestContent(); - $this->assertIsObject($content); - $status = $content->getStatus(); - $this->assertIsArray($status); - $this->assertEquals(S_RELEASED, $status['status']); - - /* A missing approver or user causes an error */ - $ret = $content->addIndApprover($approver, null); - $this->assertEquals(-1, $ret); - - /* A missing approver or user causes an error */ - $ret = $content->addIndApprover(null, $user); - $this->assertEquals(-1, $ret); - - /* Adding a group instead of a user causes an error */ - $ret = $content->addIndApprover($approvergrp, $user); - $this->assertEquals(-1, $ret); - - /* Finally add the reviewer */ - $ret = $content->addIndApprover($approver, $user); - $this->assertGreaterThan(0, $ret); - - /* Adding the user again will yield in an error */ - $ret = $content->addIndApprover($approver, $user); - $this->assertEquals(-3, $ret); - - /* Needs to call verifyStatus() in order to recalc the status */ - $newstatus = $content->verifyStatus(false, $user); - $this->assertIsInt($newstatus); - $this->assertEquals(S_DRAFT_APP, $newstatus); - - /* Get all approvals */ - $approvalstatus = $content->getApprovalStatus(); - $this->assertIsArray($approvalstatus); - $this->assertCount(1, $approvalstatus); - - /* Get list of individual und group approvers */ - $approvers = $content->getApprovers(); - $this->assertIsArray($approvers); - $this->assertCount(2, $approvers); - $this->assertCount(1, $approvers['i']); - $this->assertCount(0, $approvers['g']); - - /* A missing approver or user causes an error */ - $ret = $content->addGrpApprover($approvergrp, null); - $this->assertEquals(-1, $ret); - - /* A missing approver or user causes an error */ - $ret = $content->addGrpApprover(null, $user); - $this->assertEquals(-1, $ret); - - /* Adding a user instead of a group causes an error */ - $ret = $content->addGrpApprover($approver, $user); - $this->assertEquals(-1, $ret); - - /* Finally add the reviewer */ - $ret = $content->addGrpApprover($approvergrp, $user); - $this->assertGreaterThan(0, $ret); - $groupstatus = $approvergrp->getApprovalStatus(); - - /* Adding the group again will yield in an error */ - $ret = $content->addGrpApprover($approvergrp, $user); - $this->assertEquals(-3, $ret); - - /* Get all approvals */ - $approvalstatus = $content->getApprovalStatus(); - $this->assertIsArray($approvalstatus); - $this->assertCount(2, $approvalstatus); - - /* Get list of individual und group approvers */ - $approvers = $content->getApprovers(); - $this->assertIsArray($approvers); - $this->assertCount(2, $approvers); - $this->assertCount(1, $approvers['i']); - $this->assertCount(1, $approvers['g']); - - $userstatus = $approver->getApprovalStatus(); - $groupstatus = $approvergrp->getApprovalStatus(); - - /* There should be two log entries, one for each approver */ - $approvallog = $content->getApproveLog(5); - $this->assertIsArray($approvallog); - $this->assertCount(2, $approvallog); - - /* Adding a approval without a user of approver causes an error */ - $ret = $content->setApprovalByInd($approver, null, S_LOG_ACCEPTED, 'Comment of individual approver'); - $this->assertEquals(-1, $ret); - $ret = $content->setApprovalByInd(null, $user, S_LOG_ACCEPTED, 'Comment of individual approver'); - $this->assertEquals(-1, $ret); - - /* Adding a approval as an individual but passing a group causes an error */ - $ret = $content->setApprovalByInd($approvergrp, $user, S_LOG_ACCEPTED, 'Comment of individual approver'); - $this->assertEquals(-1, $ret); - - /* Individual approver approvals document */ - $ret = $content->setApprovalByInd($approver, $user, S_LOG_ACCEPTED, 'Comment of individual approver'); - $this->assertIsInt(0, $ret); - $this->assertGreaterThan(0, $ret); - - /* Get the last 5 approval log entries (actually there are just 3 now) */ - $approvallog = $content->getApproveLog(5); - $this->assertIsArray($approvallog); - $this->assertCount(3, $approvallog); - $this->assertEquals('Comment of individual approver', $approvallog[0]['comment']); - $this->assertEquals(1, $approvallog[0]['status']); - - /* Needs to call verifyStatus() in order to recalc the status. - * It must not be changed because the group approver has not done the - * approval. - */ - $newstatus = $content->verifyStatus(false, $user); - $this->assertIsInt($newstatus); - $this->assertEquals(S_DRAFT_APP, $newstatus); - - /* Adding a approval without a user of approver causes an error */ - $ret = $content->setApprovalByGrp($approvergrp, null, S_LOG_ACCEPTED, 'Comment of group approver'); - $this->assertEquals(-1, $ret); - $ret = $content->setApprovalByGrp(null, $user, S_LOG_ACCEPTED, 'Comment of group approver'); - $this->assertEquals(-1, $ret); - - /* Adding a approval as an group but passing a user causes an error */ - $ret = $content->setApprovalByGrp($approver, $user, S_LOG_ACCEPTED, 'Comment of group approver'); - $this->assertEquals(-1, $ret); - - /* Group approver approvals document */ - $ret = $content->setApprovalByGrp($approvergrp, $user, S_LOG_ACCEPTED, 'Comment of group approver'); - $this->assertIsInt(0, $ret); - $this->assertGreaterThan(0, $ret); - - /* Get the last 5 approval log entries (actually there are just 4 now) */ - $approvallog = $content->getApproveLog(5); - $this->assertIsArray($approvallog); - $this->assertCount(4, $approvallog); - $this->assertEquals('Comment of group approver', $approvallog[0]['comment']); - $this->assertEquals(1, $approvallog[0]['status']); - - /* Now the document has received all approvals */ - $newstatus = $content->verifyStatus(false, $user); - $this->assertIsInt($newstatus); - $this->assertEquals(S_RELEASED, $newstatus); - - /* Remove the last approval of the user */ - $userstatus = $approver->getApprovalStatus($document->getId(), $content->getVersion()); - $this->assertIsArray($userstatus); - $this->assertCount(2, $userstatus); - $this->assertCount(1, $userstatus['indstatus']); - $ret = $content->removeApproval($userstatus['indstatus'][$document->getId()]['approveID'], $user, 'Undo approval'); - $this->assertTrue($ret); - - /* Get the last 8 approval log entries (actually there are just 5 now) */ - $approvallog = $content->getApproveLog(8); - $this->assertIsArray($approvallog); - $this->assertCount(5, $approvallog); - $this->assertEquals('Undo approval', $approvallog[0]['comment']); - $this->assertEquals(0, $approvallog[0]['status']); - - /* Now the document must be back in draft mode */ - $newstatus = $content->verifyStatus(false, $user); - $this->assertIsInt($newstatus); - $this->assertEquals(S_DRAFT_APP, $newstatus); - - /* Removing the user as a approver completly will release the - * document again, because the group approver became the only - * approver and has done the approval already. - */ - $ret = $content->delIndApprover($approver, $user, 'Approver removed'); - $this->assertIsInt($ret); - $this->assertEquals(0, $ret); - - /* Get the last 8 approval log entries (actually there are just 6 now) */ - $approvallog = $content->getApproveLog(8); - $this->assertIsArray($approvallog); - $this->assertCount(6, $approvallog); - $this->assertEquals('Approver removed', $approvallog[0]['comment']); - $this->assertEquals(-2, $approvallog[0]['status']); - - /* Now the document will be released again */ - $newstatus = $content->verifyStatus(false, $user); - $this->assertIsInt($newstatus); - $this->assertEquals(S_RELEASED, $newstatus); - } -} diff --git a/SeedDMS_Core/tests/SeedDmsBase.php b/SeedDMS_Core/tests/SeedDmsBase.php deleted file mode 100644 index dc8f7e920..000000000 --- a/SeedDMS_Core/tests/SeedDmsBase.php +++ /dev/null @@ -1,365 +0,0 @@ - - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version @package_version@ - * @link https://www.seeddms.org - */ - -namespace PHPUnit\Framework; - -use PHPUnit\Framework\TestCase; - -/** - * Database test class - * - * @category SeedDMS - * @package Tests - * @author Uwe Steinmann - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version Release: @package_version@ - * @link https://www.seeddms.org - */ -class SeedDmsTest extends TestCase -{ - - public static $dbh; - - public static $dms; - - public static $contentdir; - - public static $dbversion; - - /** - * Create a sqlite database in memory - * - * @return void - */ - public static function createInMemoryDatabase(): object - { - $dbh = new \SeedDMS_Core_DatabaseAccess('sqlite', '', '', '', ':memory:'); - $dbh->connect(); - $queries = file_get_contents(getenv("SEEDDMS_CORE_SQL")); - // generate SQL query - $queries = explode(";", $queries); - - // execute queries - $errorMsg = ''; - foreach ($queries as $query) { - //echo $query; - $query = trim($query); - if (!empty($query)) { - $dbh->getResult($query); - - if ($dbh->getErrorNo() != 0) { - //echo $dbh->getErrorMsg()."\n"; - $errorMsg .= $dbh->getErrorMsg()."\n"; - } - } - } - return $dbh; - } - - /** - * Create a mocked root folder object - * - * @return \SeedDMS_Core_Folder - */ - protected function getMockedRootFolder($id=1, $name='DMS') - { - $folder = new \SeedDMS_Core_Folder($id, $name, 0, 'DMS root', time(), 1, 0, 0, 0.0); - return $folder; - } - - /** - * Create a mocked document object - * - * @return \SeedDMS_Core_Document - */ - protected function getMockedDocument($id=1, $name='Document') - { - $document = new \SeedDMS_Core_Document($id, $name, '', time(), null, 1, 1, 1, M_READ, 0, '', 1.0); - return $document; - } - - /** - * Create a mocked user object - * - * @return \SeedDMS_Core_User - */ - protected function getMockedUser() - { - $user = new \SeedDMS_Core_User(1, 'login', '', 'New User', 'email@seeddms.org', 'de_DE', 'bootstrap', '', null); - return $user; - } - - /** - * Create a temporary file with random content and the given length. - * - * @param integer $length length of file - * - * @return string name of temporary file - */ - protected static function createTempFile($length=200, $dir='') - { - if($tmpfname = @tempnam($dir ? $dir : sys_get_temp_dir(), 'foo')) { - file_put_contents($tmpfname, substr(str_shuffle(str_repeat($x='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', (int) ceil($length/strlen($x)) )),1,$length)); - return $tmpfname; - } else - return false; - } - - /** - * Create a temporary directory with random name in systems temp dir. - * - * @param integer $mode access mode of new directory - * - * @return string name of temporary directory - */ - protected static function createTempDir(string $dir = null, int $mode = 0700): string { - /* Use the system temp dir by default. */ - if (is_null($dir)) { - $dir = sys_get_temp_dir(); - } - - do { $tmp = $dir . '/' . mt_rand(); } - while (!@mkdir($tmp, $mode)); - return $tmp; - } - - /** - * Create a simple document. - * - * @param \SeedDMS_Core_Folder $parent parent folder - * @param \SeedDMS_Core_User $owner owner of document - * @param string $name name of document - * @param integer $length length of file - * - * @return string name of temporary file - */ - protected static function createDocument($parent, $owner, $name, $length=200) - { - $filename = self::createTempFile($length); - list($document, $res) = $parent->addDocument( - $name, // name - '', // comment - null, // no expiration - $owner, // owner - '', // keywords - [], // categories - $filename, // name of file - 'file1.txt', // original file name - '.txt', // file type - 'text/plain', // mime type - 1.0 // sequence - ); - unlink($filename); - return $document; - } - - /** - * Create a simple folder structure without documents - * - * DMS root -+- Subfolder 1 -+- Subsubfolder 1 -+- Subsubsubfolder 1 - * | - * +- Subfolder 2 - * | - * +- Subfolder 3 - * - * The sequence field of Subfolder x is: - * Subfolder 1: 2.0 - * Subfolder 2: 1.0 - * Subfolder 1: 0.5 - * - * @return void - */ - protected static function createSimpleFolderStructure() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - /* Set up a folder structure */ - $subfolder = $rootfolder->addSubFolder('Subfolder 1', '', $user, 2.0); - $subsubfolder = $subfolder->addSubFolder('Subsubfolder 1', '', $user, 1.0); - $subsubsubfolder = $subsubfolder->addSubFolder('Subsubsubfolder 1', '', $user, 1.0); - $rootfolder->addSubFolder('Subfolder 2', '', $user, 1.0); - $rootfolder->addSubFolder('Subfolder 3', '', $user, 0.5); - } - - /** - * Create a simple folder structure with documents - * - * Creates the same folder structure like createSimpleFolderStructure() - * but adds 30 documents to 'Subfolder 1'. They are named 'Document 1' - * to 'Document 30'. - * - * @return void - */ - protected static function createSimpleFolderStructureWithDocuments() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - self::createSimpleFolderStructure(); - /* Add documents to 'Subfolder 1' */ - $subfolder = self::$dms->getFolderByName('Subfolder 1'); - for ($i=1; $i<=15; $i++) { - $filename = self::createTempFile(200); - list($document, $res) = $subfolder->addDocument( - 'Document 1-'.$i, // name - '', // comment - null, - $user, // owner - '', // keywords - [], // categories - $filename, // name of file - 'file-1-'.$i.'.txt', // original file name - '.txt', // file type - 'text/plain', // mime type - 1.0+$i // sequence - ); - unlink($filename); - } - /* Add documents to 'Subfolder 2' */ - $subfolder = self::$dms->getFolderByName('Subfolder 2'); - for ($i=1; $i<=15; $i++) { - $filename = self::createTempFile(200); - list($document, $res) = $subfolder->addDocument( - 'Document 2-'.$i, // name - '', // comment - null, - $user, // owner - '', // keywords - [], // categories - $filename, // name of file - 'file-2-'.$i.'.txt', // original file name - '.txt', // file type - 'text/plain', // mime type - 1.0+$i // sequence - ); - unlink($filename); - } - } - - /** - * Create two groups with 3 users each - * The groups are named 'Group 1' and 'Group 2'. The users in Group 1 - * are named 'User-1-1', 'User-1-2', 'User-1-3'. The users in Group 2 - * are named 'User-2-1', 'User-2-2', 'User-2-3'. - * The login name is the lower case of the name. - * - * @return void - */ - protected static function createGroupsAndUsers() - { - for($i=1; $i<=2; $i++) { - $group = self::$dms->addGroup('Group '.$i, ''); - for($j=1; $j<=3; $j++) { - $user = self::$dms->addUser('user-'.$i.'-'.$j, '', 'User '.$j.' in group '.$i, 'user@seeddms.org', 'en_GB', 'bootstrap', ''); - $user->joinGroup($group); - } - } - } - - /** - * Creates a workflow with two transitions identical to the traditional - * workflow - * - * NR --- review --> NA -+- approve --> RL - * +- reject --> RJ | - * +- reject ---> RJ - * - * States: - * NR = needs review - * NA = needs approval - * RL = released - * RJ = rejected - * - * Actions: - * review - * approve - * reject - * - * Transitions: - * NR -- review -> NA maybe done by reviewer - * NR -- reject -> RJ maybe done by reviewer - * NA -- approve -> RL maybe done by approver - * NA -- reject -> RJ maybe done by approver - */ - protected function createWorkflow(\SeedDMS_Core_User $reviewer, \SeedDMS_Core_User $approver): \SeedDMS_Core_Workflow - { - /* Create workflow states */ - $ws_nr = self::$dms->addWorkflowState('needs review', S_IN_WORKFLOW); - $ws_na = self::$dms->addWorkflowState('needs approval', S_IN_WORKFLOW); - $ws_rl = self::$dms->addWorkflowState('released', S_RELEASED); - $ws_rj = self::$dms->addWorkflowState('rejected', S_REJECTED); - - /* Create workflow actions */ - $wa_rv = self::$dms->addWorkflowAction('review', S_IN_WORKFLOW); - $wa_rj = self::$dms->addWorkflowAction('reject', S_REJECTED); - $wa_ap = self::$dms->addWorkflowAction('approve', S_RELEASED); - - /* Create a workflow which starts in state 'needs review' */ - $workflow = self::$dms->addWorkflow('traditional workflow', $ws_nr); - /* Add transition NR -- review -> NA */ - $wt_nr_na = $workflow->addTransition($ws_nr, $wa_rv, $ws_na, [$reviewer], []); - /* Add transition NR -- review -> RJ */ - $wt_nr_rj = $workflow->addTransition($ws_nr, $wa_rj, $ws_rj, [$reviewer], []); - /* Add transition NA -- approve -> RL */ - $wt_na_rl = $workflow->addTransition($ws_na, $wa_ap, $ws_rl, [$approver], []); - /* Add transition NA -- reject -> RJ */ - $wt_na_rj = $workflow->addTransition($ws_na, $wa_rj, $ws_rj, [$approver], []); - - return $workflow; - } - - /** - * Creates a workflow with one transitions for approving a document - * - * NA -+- approve --> RL - * | - * +- reject ---> RJ - * - * States: - * NA = needs approval - * RL = released - * RJ = rejected - * - * Actions: - * approve - * reject - * - * Transitions: - * NA -- approve -> RL maybe done by approver - * NA -- reject -> RJ maybe done by approver - */ - protected function createSimpleWorkflow(\SeedDMS_Core_User $approver): \SeedDMS_Core_Workflow - { - /* Create workflow states */ - $ws_na = self::$dms->addWorkflowState('simple needs approval', S_IN_WORKFLOW); - $ws_rl = self::$dms->addWorkflowState('simple released', S_RELEASED); - $ws_rj = self::$dms->addWorkflowState('simple rejected', S_REJECTED); - - /* Create workflow actions */ - $wa_rj = self::$dms->addWorkflowAction('simple reject', S_REJECTED); - $wa_ap = self::$dms->addWorkflowAction('simple approve', S_RELEASED); - - /* Create a workflow which starts in state 'needs approval' */ - $workflow = self::$dms->addWorkflow('simple workflow', $ws_na); - /* Add transition NA -- approve -> RL */ - $wt_na_rl = $workflow->addTransition($ws_na, $wa_ap, $ws_rl, [$approver], []); - /* Add transition NA -- reject -> RJ */ - $wt_na_rj = $workflow->addTransition($ws_na, $wa_rj, $ws_rj, [$approver], []); - - return $workflow; - } - -} - diff --git a/SeedDMS_Core/tests/UserTest.php b/SeedDMS_Core/tests/UserTest.php deleted file mode 100644 index 6d2e6f208..000000000 --- a/SeedDMS_Core/tests/UserTest.php +++ /dev/null @@ -1,1679 +0,0 @@ - - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version @package_version@ - * @link https://www.seeddms.org - */ - -use PHPUnit\Framework\SeedDmsTest; - -/** - * User test class - * - * @category SeedDMS - * @package Tests - * @author Uwe Steinmann - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version Release: @package_version@ - * @link https://www.seeddms.org - */ -class UserTest extends SeedDmsTest -{ - - /** - * Create a real sqlite database in memory - * - * @return void - */ - protected function setUp(): void - { - self::$dbh = self::createInMemoryDatabase(); - self::$contentdir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'phpunit-'.time(); - mkdir(self::$contentdir); - // echo "Creating temp content dir: ".self::$contentdir."\n"; - self::$dms = new SeedDMS_Core_DMS(self::$dbh, self::$contentdir); - self::$dbversion = self::$dms->getDBVersion(); - } - - /** - * Clean up at tear down - * - * @return void - */ - protected function tearDown(): void - { - self::$dbh = null; - // echo "\nRemoving temp. content dir: ".self::$contentdir."\n"; - exec('rm -rf '.self::$contentdir); - } - - /** - * Create a mock admin user object - * - * @return SeedDMS_Core_User - */ - protected function getAdminUser() - { - $user = new SeedDMS_Core_User(1, 'admin', 'pass', 'Joe Foo', 'baz@foo.de', 'en_GB', 'bootstrap', 'My comment', SeedDMS_Core_User::role_admin); - return $user; - } - - /** - * Create a mock admin role object (only used for SeedDMS 6) - * - * @return SeedDMS_Core_User - */ - protected function getAdminRole() - { - $role = new SeedDMS_Core_Role(1, 'admin', SeedDMS_Core_Role::role_admin); - return $role; - } - - /** - * Create a mock regular user object - * - * @return SeedDMS_Core_User - */ - protected function getUser() - { - $user = new SeedDMS_Core_User(2, 'user', 'pass', 'Joe Baz', 'joe@foo.de', 'en_GB', 'bootstrap', 'My comment', SeedDMS_Core_User::role_user); - return $user; - } - - /** - * Test method setDMS() and getDMS() - * - * @return void - */ - public function testSetAndGetDMS() - { - $user = $this->getAdminUser(); - $user->setDMS(self::$dms); - $this->assertInstanceOf(SeedDMS_Core_DMS::class, $user->getDMS()); - } - - /** - * Test method isType() - * - * @return void - */ - public function testIsType() - { - $user = $this->getAdminUser(); - $this->assertTrue($user->isType('user')); - } - - /** - * Test method getPwd() - * - * @return void - */ - public function testGetPwd() - { - $user = $this->getAdminUser(); - $this->assertEquals('pass', $user->getPwd()); - } - - /** - * Test method getEmail() - * - * @return void - */ - public function testGetEmail() - { - $user = $this->getAdminUser(); - $this->assertEquals('baz@foo.de', $user->getEmail()); - } - - /** - * Test method getLanguage() - * - * @return void - */ - public function testGetLanguage() - { - $user = $this->getAdminUser(); - $this->assertEquals('en_GB', $user->getLanguage()); - } - - /** - * Test method getTheme() - * - * @return void - */ - public function testGetTheme() - { - $user = $this->getAdminUser(); - $this->assertEquals('bootstrap', $user->getTheme()); - } - - /** - * Test method getComment() - * - * @return void - */ - public function testGetComment() - { - $user = $this->getAdminUser(); - $this->assertEquals('My comment', $user->getComment()); - } - - /** - * Test method getRole() - * - * @return void - */ - public function testGetRole() - { - $user = $this->getAdminUser(); - $this->assertEquals(1, $user->getRole()); - } - - /** - * Test method isAdmin() - * - * @return void - */ - public function testIsAdmin() - { - $user = $this->getAdminUser(); - $this->assertTrue($user->isAdmin()); - $this->assertFalse($user->isGuest()); - } - - /** - * Test method isGuest() - * - * @return void - */ - public function testIsGuest() - { - $user = $this->getAdminUser(); - $this->assertFalse($user->isGuest()); - } - - /** - * Test method isHidden() - * - * @return void - */ - public function testIsHidden() - { - $user = $this->getAdminUser(); - $this->assertFalse($user->isHidden()); - } - - /** - * Test method getQuota() - * - * @return void - */ - public function testGetQuota() - { - $user = $this->getAdminUser(); - $this->assertEquals(0, $user->getQuota()); - } - - /** - * Test method getSecret() - * - * @return void - */ - public function testGetSecret() - { - if(self::$dbversion['major'] < 6) { - $this->markTestSkipped( - 'This test is not applicable for SeedDMS 5.' - ); - } else { - $user = $this->getAdminUser(); - $this->assertEquals('', $user->getSecret()); - } - } - - /** - * Test method getInstance() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetInstance() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $this->assertIsObject($user); - $this->assertEquals('admin', $user->getLogin()); - $user = SeedDMS_Core_User::getInstance('admin', self::$dms, 'name'); - $this->assertIsObject($user); - $this->assertEquals('admin', $user->getLogin()); - $user = SeedDMS_Core_User::getInstance('admin', self::$dms, 'name', 'info@seeddms.org'); - $this->assertIsObject($user); - $this->assertEquals('admin', $user->getLogin()); - /* get instance of none existing user */ - $user = SeedDMS_Core_User::getInstance('foo', self::$dms, 'name'); - $this->assertNull($user); - } - - /** - * Test method getAllInstances() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAllInstancesSqlFail() - { - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->exactly(2)) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblUsers` ORDER BY")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - /* Order by login */ - $users = SeedDMS_Core_User::getAllInstances('', $dms); - $this->assertFalse($users); - /* Order by fullname */ - $users = SeedDMS_Core_User::getAllInstances('fullname', $dms); - $this->assertFalse($users); - } - - /** - * Test method getLogin() - * - * @return void - */ - public function testGetLogin() - { - $user = $this->getAdminUser(); - $this->assertEquals('admin', $user->getLogin()); - } - - /** - * Test method setLogin() - * - * @return void - */ - public function testSetLoginSqlFail() - { - $user = $this->getAdminUser(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblUsers` SET `login`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $user->setDMS($dms); - $this->assertFalse($user->setLogin('foo')); - } - - /** - * Test method getLogin() and setLogin() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetLogin() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $login = $user->getLogin(); - $ret = $user->setLogin('foo'); - $this->assertTrue($ret); - $login = $user->getLogin(); - $this->assertEquals('foo', $login); - $ret = $user->setLogin(' '); - $this->assertFalse($ret); - } - - /** - * Test method getFullName() - * - * @return void - */ - public function testGetFullName() - { - $user = $this->getAdminUser(); - $this->assertEquals('Joe Foo', $user->getFullName()); - } - - /** - * Test method setFullName() - * - * @return void - */ - public function testSetFullNameSqlFail() - { - $user = $this->getAdminUser(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblUsers` SET `fullName`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $user->setDMS($dms); - $this->assertFalse($user->setFullName('foo')); - } - - /** - * Test method getFullName() and setFullName() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetFullName() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $fullname = $user->getFullName(); - $ret = $user->setFullName('foo'); - $this->assertTrue($ret); - $fullname = $user->getFullName(); - $this->assertEquals('foo', $fullname); - } - - /** - * Test method getPwd() and setPwd() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetPwd() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $pwd = $user->getPwd(); - $ret = $user->setPwd('foo'); - $this->assertTrue($ret); - $pwd = $user->getPwd(); - $this->assertEquals('foo', $pwd); - } - - /** - * Test method setPwd() - * - * @return void - */ - public function testSetPwdSqlFail() - { - $user = $this->getAdminUser(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblUsers` SET `pwd`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $user->setDMS($dms); - $this->assertFalse($user->setPwd('foo')); - } - - /** - * Test method getPwdExpiration() and setPwdExpiration() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetPwdExpiration() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $pwdexp = $user->getPwdExpiration(); - /* Set password expiration to 'never' */ - $ret = $user->setPwdExpiration('never'); - $this->assertTrue($ret); - $pwdexp = $user->getPwdExpiration(); - $this->assertNull($pwdexp); - - /* Set password expiration to 'now' */ - $now = date('Y-m-d H:i:s'); - $ret = $user->setPwdExpiration('now'); - $this->assertTrue($ret); - $pwdexp = $user->getPwdExpiration(); - $this->assertEquals($now, $pwdexp); - } - - /** - * Test method setPwdExpiration() - * - * @return void - */ - public function testSetPwdExpirationSqlFail() - { - $user = $this->getAdminUser(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblUsers` SET `pwdExpiration`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $user->setDMS($dms); - $this->assertFalse($user->setPwdExpiration('foo')); - } - - /** - * Test method getEmail() and setEmail() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetEmail() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $email = $user->getEmail(); - $ret = $user->setEmail('new@seeddms.org'); - $this->assertTrue($ret); - $email = $user->getEmail(); - $this->assertEquals('new@seeddms.org', $email); - } - - /** - * Test method setEmail() - * - * @return void - */ - public function testSetEmailSqlFail() - { - $user = $this->getAdminUser(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblUsers` SET `email`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $user->setDMS($dms); - $this->assertFalse($user->setEmail('foo')); - } - - /** - * Test method getLanguage() and setLanguage() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetLanguage() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $language = $user->getLanguage(); - $ret = $user->setLanguage('de_DE'); - $this->assertTrue($ret); - $language = $user->getLanguage(); - $this->assertEquals('de_DE', $language); - } - - /** - * Test method setLanguage() - * - * @return void - */ - public function testSetLanguageSqlFail() - { - $user = $this->getAdminUser(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblUsers` SET `language`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $user->setDMS($dms); - $this->assertFalse($user->setLanguage('de_DE')); - } - - /** - * Test method getTheme() and setTheme() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetTheme() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $theme = $user->getTheme(); - $ret = $user->setTheme('bootstrap4'); - $this->assertTrue($ret); - $theme = $user->getTheme(); - $this->assertEquals('bootstrap4', $theme); - } - - /** - * Test method setTheme() - * - * @return void - */ - public function testSetThemeSqlFail() - { - $user = $this->getAdminUser(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblUsers` SET `theme`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $user->setDMS($dms); - $this->assertFalse($user->setTheme('bootstrap')); - } - - /** - * Test method getComment() and setComment() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetComment() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $comment = $user->getComment(); - $ret = $user->setComment('my comment'); - $this->assertTrue($ret); - $comment = $user->getComment(); - $this->assertEquals('my comment', $comment); - } - - /** - * Test method setComment() - * - * @return void - */ - public function testSetCommentSqlFail() - { - $user = $this->getAdminUser(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblUsers` SET `comment`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $user->setDMS($dms); - $this->assertFalse($user->setComment('my comment')); - } - - /** - * Test method getRole() and setRole() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetRole() - { - if(self::$dbversion['major'] < 6) { - // SeedDMS 5 use integers for roles: 0=user, 1=admin, 2=guest - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - // User with id=1 is the admin user in the initial database - $role = $user->getRole(); - $this->assertEquals(SeedDMS_Core_User::role_admin, $role); - $ret = $user->setRole(SeedDMS_Core_User::role_guest); - $this->assertTrue($ret); - $role = $user->getRole(); - $this->assertEquals(SeedDMS_Core_User::role_guest, $role); - $ret = $user->setRole(''); - $this->assertFalse($ret); - } else { - // Starting with SeedDMS 6 a role is an object - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - // User with id=1 is the admin user in the initial database - $role = $user->getRole(); - $this->assertTrue($role->isAdmin()); - // SeedDMS_Core_User has an isAdmin() method too, which internally - // uses SeedDMS_Core_Role::isAdmin() - $this->assertTrue($user->isAdmin()); - // Get the guest role, which is supposed to have id=2 in the - // initial database - $guestrole = SeedDMS_Core_Role::getInstance(2, self::$dms); - $this->assertTrue($guestrole->isGuest()); - // Assign guest role and check if the user is a guest - $ret = $user->setRole($guestrole); - $this->assertTrue($ret); - $this->assertTrue($user->isGuest()); - } - } - - /** - * Test method setRole() - * - * @return void - */ - public function testSetRoleSqlFail() - { - if(self::$dbversion['major'] > 5) { - $role = $this->getAdminRole(); - } - $user = $this->getAdminUser(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblUsers` SET `role`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $user->setDMS($dms); - if(self::$dbversion['major'] > 5) { - $this->assertFalse($user->setRole($role)); - } else { - $this->assertFalse($user->setRole(SeedDMS_Core_User::role_admin)); - } - } - - /** - * Test method setGuest() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testSetGuest() - { - if(self::$dbversion['major'] == '5') { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $role = $user->getRole(); - $ret = $user->setGuest(); - $this->assertTrue($ret); - $role = $user->getRole(); - $this->assertEquals(SeedDMS_Core_User::role_guest, $role); - } else { - $this->markTestSkipped( - 'This test is not applicable for SeedDMS 6.' - ); - } - } - - /** - * Test method setGuest() - * - * @return void - */ - public function testSetGuestSqlFail() - { - $dms = new SeedDMS_Core_DMS(null, ''); - if(self::$dbversion['major'] == '5') { - $user = $this->getAdminUser(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblUsers` SET `role`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $user->setDMS($dms); - $this->assertFalse($user->setGuest()); - } else { - $this->markTestSkipped( - 'This test is not applicable for SeedDMS 6.' - ); - } - } - - /** - * Test method setAdmin() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testSetAdmin() - { - if(self::$dbversion['major'] == '5') { - $user = SeedDMS_Core_User::getInstance(2, self::$dms); - $role = $user->getRole(); - $ret = $user->setAdmin(); - $this->assertTrue($ret); - $role = $user->getRole(); - $this->assertEquals(SeedDMS_Core_User::role_admin, $role); - } else { - $this->markTestSkipped( - 'This test is not applicable for SeedDMS 6.' - ); - } - } - - /** - * Test method setAdmin() - * - * @return void - */ - public function testSetAdminSqlFail() - { - $dms = new SeedDMS_Core_DMS(null, ''); - if(self::$dbversion['major'] == '5') { - $user = $this->getAdminUser(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblUsers` SET `role`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $user->setDMS($dms); - $this->assertFalse($user->setAdmin()); - } else { - $this->markTestSkipped( - 'This test is not applicable for SeedDMS 6.' - ); - } - } - - /** - * Test method getQuota() and setQuota() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetQuota() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $quota = $user->getQuota(); - $ret = $user->setQuota(100000); - $this->assertTrue($ret); - $quota = $user->getQuota(); - $this->assertEquals(100000, $quota); - /* Setting a non numeric or negative value will fail */ - $ret = $user->setQuota('foo'); - $this->assertFalse($ret); - $ret = $user->setQuota(-100); - $this->assertFalse($ret); - } - - /** - * Test method setQuota() - * - * @return void - */ - public function testSetQuotaSqlFail() - { - $user = $this->getAdminUser(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblUsers` SET `quota`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $user->setDMS($dms); - $this->assertFalse($user->setQuota(10000)); - } - - /** - * Test method getSecret() and setSecret() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetSecret() - { - if(self::$dbversion['major'] < 6) { - $this->markTestSkipped( - 'This test is not applicable for SeedDMS 5.' - ); - } else { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $secret = $user->getSecret(); - $ret = $user->setSecret('secret'); - $this->assertTrue($ret); - $secret = $user->getSecret(); - $this->assertEquals('secret', $secret); - } - } - - /** - * Test method setSecret() - * - * @return void - */ - public function testSetSecretSqlFail() - { - if(self::$dbversion['major'] < 6) { - $this->markTestSkipped( - 'This test is not applicable for SeedDMS 5.' - ); - } else { - $user = $this->getAdminUser(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblUsers` SET `secret`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $user->setDMS($dms); - $this->assertFalse($user->setSecret('secret')); - } - } - - /** - * Test method isHidden() and setHidden() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testIsAndSetHidden() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $ishidden = $user->isHidden(); - /* set hidden to true */ - $ret = $user->setHidden(true); - $this->assertTrue($ret); - $ishidden = $user->isHidden(); - $this->assertTrue($ishidden); - /* set hidden to false */ - $ret = $user->setHidden(false); - $this->assertTrue($ret); - $ishidden = $user->isHidden(); - $this->assertFalse($ishidden); - } - - /** - * Test method setHidden() - * - * @return void - */ - public function testSetHiddentSqlFail() - { - $user = $this->getAdminUser(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblUsers` SET `hidden`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $user->setDMS($dms); - $this->assertFalse($user->setHidden(true)); - } - - /** - * Test method isDisabled() and setDisabled() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testIsAndSetDisabled() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $isdisabled = $user->isDisabled(); - /* set disabled to true */ - $ret = $user->setDisabled(true); - $this->assertTrue($ret); - $isdisabled = $user->isDisabled(); - $this->assertTrue($isdisabled); - /* set disabled to false */ - $ret = $user->setDisabled(false); - $this->assertTrue($ret); - $isdisabled = $user->isDisabled(); - $this->assertFalse($isdisabled); - } - - /** - * Test method setDisabled() - * - * @return void - */ - public function testSetDisabledtSqlFail() - { - $user = $this->getAdminUser(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblUsers` SET `disabled`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $user->setDMS($dms); - $this->assertFalse($user->setDisabled(true)); - } - - /** - * Test method addLoginFailure() - * - * @return void - */ - public function testAddLoginFailure() - { - $user = $this->getAdminUser(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->exactly(2)) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblUsers` SET `loginfailures`")) - ->willReturn(true); - $dms = new SeedDMS_Core_DMS($db, ''); - $user->setDMS($dms); - $this->assertEquals(1, $user->addLoginFailure()); - $this->assertEquals(2, $user->addLoginFailure()); - } - - /** - * Test method addLoginFailure() - * - * @return void - */ - public function testAddLoginFailureSqlFail() - { - $user = $this->getAdminUser(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblUsers` SET `loginfailures`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $user->setDMS($dms); - $this->assertFalse($user->addLoginFailure()); - } - - /** - * Test method clearLoginFailure() - * - * @return void - */ - public function testClearLoginFailure() - { - $user = $this->getAdminUser(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->exactly(2)) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblUsers` SET `loginfailures`")) - ->willReturn(true); - $dms = new SeedDMS_Core_DMS($db, ''); - $user->setDMS($dms); - $this->assertEquals(1, $user->addLoginFailure()); - $this->assertEquals(true, $user->clearLoginFailures()); - } - - /** - * Test method clearLoginFailure() - * - * @return void - */ - public function testClearLoginFailureSqlFail() - { - $user = $this->getAdminUser(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblUsers` SET `loginfailures`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $user->setDMS($dms); - $this->assertFalse($user->clearLoginFailures()); - } - - /** - * Test method setHomeFolder() and getHomeFolder() - * - * @return void - */ - public function testSetAndGetHomeFolder() - { - $user = $this->getAdminUser(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblUsers` SET `homefolder`")) - ->willReturn(true); - $dms = new SeedDMS_Core_DMS($db, ''); - $user->setDMS($dms); - $this->assertTrue($user->setHomeFolder(1)); - $this->assertEquals(1, $user->getHomeFolder()); - } - - /** - * Test method setHomeFolder() - * - * @return void - */ - public function testSetHomeFolderSqlFail() - { - $user = $this->getAdminUser(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResult') - ->with($this->stringContains("UPDATE `tblUsers` SET `homefolder`")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $user->setDMS($dms); - $this->assertFalse($user->setHomeFolder(1)); - } - - /** - * Test method getUsedDiskSpace() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetUsedDiskSpace() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $size = $user->getUsedDiskSpace(); - $this->assertEquals(0, $size); - } - - /** - * Test method getUsedDiskSpace() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetUsedDiskSpaceSqlFail() - { - $user = $this->getAdminUser(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT SUM(`fileSize`) sum")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $user->setDMS($dms); - $this->assertFalse($user->getUsedDiskSpace()); - } - - /** - * Test method removeFromProcesses() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testRemoveFromProcesses() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $ret = $user->removeFromProcesses($user); - $this->assertTrue($ret); - } - - /** - * Test method transferDocumentsFolders() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testTransferDocumentsFolders() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - self::createSimpleFolderStructureWithDocuments(); - $newuser = self::$dms->addUser('newuser', '', 'New User', 'newuser@seeddms.org', 'en_GB', 'bootstrap', ''); - /* Transfering documents and folders to the same user returns true */ - $ret = $user->transferDocumentsFolders($user); - $this->assertTrue($ret); - /* A subfolder still belongs to $user */ - $subfolder = self::$dms->getFolder(2); - $this->assertEquals($user->getId(), $subfolder->getOwner()->getId()); - /* A document still belongs to $user */ - $document = self::$dms->getDocument(1); - $this->assertEquals($user->getId(), $document->getOwner()->getId()); - /* Transfer the documents and folders to $newuser */ - $ret = $user->transferDocumentsFolders($newuser); - $this->assertTrue($ret); - /* Get the folder again, because the owner has changed */ - $subfolder = self::$dms->getFolder(2); - $this->assertEquals($newuser->getId(), $subfolder->getOwner()->getId()); - /* Get the document again, because the owner has changed */ - $document = self::$dms->getDocument(1); - $this->assertEquals($newuser->getId(), $document->getOwner()->getId()); - } - - /** - * Test method remove() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testRemove() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - self::createSimpleFolderStructureWithDocuments(); - $newuser = self::$dms->addUser('newuser', '', 'New User', 'newuser@seeddms.org', 'en_GB', 'bootstrap', ''); - /* removing a user without passed a new user for docs and folders will fail */ - $ret = $user->remove($newuser, null); - $this->assertFalse($ret); - - $ret = $user->remove($newuser, $newuser); - $this->assertTrue($ret); - - /* all documents and folders now belong to $newuser */ - $document = self::$dms->getDocument(1); - $this->assertEquals($newuser->getId(), $document->getOwner()->getId()); - $subfolder = self::$dms->getFolder(1); - $this->assertEquals($newuser->getId(), $subfolder->getOwner()->getId()); - } - - /** - * Test method getDocuments() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetDocuments() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $documents = $user->getDocuments(); - $this->assertIsArray($documents); - $this->assertCount(0, $documents); - } - - /** - * Test method getDocumentsLocked() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetDocumentsLocked() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $documents = $user->getDocumentsLocked(); - $this->assertIsArray($documents); - $this->assertCount(0, $documents); - } - - /** - * Test method getDocumentLinks() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetDocumentLinks() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $links = $user->getDocumentLinks(); - $this->assertIsArray($links); - $this->assertCount(0, $links); - } - - /** - * Test method getDocumentFiles() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetDocumentFiles() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $files = $user->getDocumentFiles(); - $this->assertIsArray($files); - $this->assertCount(0, $files); - } - - /** - * Test method getDocumentContents() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetDocumentContents() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $contents = $user->getDocumentContents(); - $this->assertIsArray($contents); - $this->assertCount(0, $contents); - } - - /** - * Test method getFolders() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetFolders() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $folders = $user->getFolders(); - $this->assertIsArray($folders); - $this->assertCount(1, $folders); - } - - /** - * Test method getReviewStatus() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetReviewStatus() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $status = $user->getReviewStatus(); - $this->assertIsArray($status); - $this->assertCount(2, $status); - $this->assertCount(0, $status['indstatus']); - $this->assertCount(0, $status['grpstatus']); - } - - /** - * Test method getApprovalStatus() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetApprovalStatus() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $status = $user->getApprovalStatus(); - $this->assertIsArray($status); - $this->assertCount(2, $status); - $this->assertCount(0, $status['indstatus']); - $this->assertCount(0, $status['grpstatus']); - } - - /** - * Test method getWorkflowStatus() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetWorkflowStatus() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $status = $user->getWorkflowStatus(); - $this->assertIsArray($status); - $this->assertCount(2, $status); - $this->assertCount(0, $status['u']); - $this->assertCount(0, $status['g']); - } - - /** - * Test method getWorkflowsInvolved() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetWorkflowsInvolved() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $workflows = $user->getWorkflowsInvolved(); - $this->assertIsArray($workflows); - $this->assertCount(0, $workflows); - } - - /** - * Test method getMandatoryReviewers() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetMandatoryReviewers() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $reviewers = $user->getMandatoryReviewers(); - $this->assertIsArray($reviewers); - $this->assertCount(0, $reviewers); - } - - /** - * Test method setMandatoryReviewer() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testSetMandatoryReviewer() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $newuser = self::$dms->addUser('newuser', '', 'New User', 'newuser@seeddms.org', 'en_GB', 'bootstrap', ''); - $ret = $user->setMandatoryReviewer($newuser->getId(), false); - $this->assertTrue($ret); - $reviewers = $user->getMandatoryReviewers(); - $this->assertIsArray($reviewers); - $this->assertCount(1, $reviewers); - /* $newuser is now a mandatory user of $user */ - $mandatoryreviewers = $newuser->isMandatoryReviewerOf(); - $this->assertIsArray($mandatoryreviewers); - $this->assertCount(1, $mandatoryreviewers); - $this->assertEquals($user->getId(), $mandatoryreviewers[0]->getId()); - - $group = self::$dms->addGroup('Group', ''); - $ret = $user->setMandatoryReviewer($group->getId(), true); - $this->assertTrue($ret); - $reviewers = $user->getMandatoryReviewers(); - $this->assertIsArray($reviewers); - $this->assertCount(2, $reviewers); - /* FIXME: there is not isMandatoryReviewerOf() for groups */ - } - - /** - * Test method getMandatoryApprovers() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetMandatoryApprovers() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $approvers = $user->getMandatoryApprovers(); - $this->assertIsArray($approvers); - $this->assertCount(0, $approvers); - } - - /** - * Test method setMandatoryApprover() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testSetMandatoryApprover() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $newuser = self::$dms->addUser('newuser', '', 'New User', 'newuser@seeddms.org', 'en_GB', 'bootstrap', ''); - $ret = $user->setMandatoryApprover($newuser->getId(), false); - $this->assertTrue($ret); - $approvers = $user->getMandatoryApprovers(); - $this->assertIsArray($approvers); - $this->assertCount(1, $approvers); - /* $newuser is now a mandatory user of $user */ - $mandatoryapprovers = $newuser->isMandatoryApproverOf(); - $this->assertIsArray($mandatoryapprovers); - $this->assertCount(1, $mandatoryapprovers); - $this->assertEquals($user->getId(), $mandatoryapprovers[0]->getId()); - - $group = self::$dms->addGroup('Group', ''); - $ret = $user->setMandatoryApprover($group->getId(), true); - $this->assertTrue($ret); - $approvers = $user->getMandatoryApprovers(); - $this->assertIsArray($approvers); - $this->assertCount(2, $approvers); - /* FIXME: there is not isMandatoryApproverOf() for groups */ - } - - /** - * Test method setMandatoryWorkflow() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testSetMandatoryWorkflow() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $approver = self::$dms->addUser('approver', '', 'Approver', 'newuser@seeddms.org', 'en_GB', 'bootstrap', ''); - $reviewer = self::$dms->addUser('reviewer', '', 'Reviewer', 'newuser@seeddms.org', 'en_GB', 'bootstrap', ''); - $simpleworkflow = self::createSimpleWorkflow($approver); - $traditionalworkflow = self::createWorkflow($reviewer, $approver); - $newuser = self::$dms->addUser('newuser', '', 'New User', 'newuser@seeddms.org', 'en_GB', 'bootstrap', ''); - /* Set a single mandatory workflow */ - $ret = $newuser->setMandatoryWorkflow($simpleworkflow); - $this->assertTrue($ret); - $workflows = $newuser->getMandatoryWorkflows(); - $this->assertIsArray($workflows); - $this->assertCount(1, $workflows); - - /* Set a single mandatory workflow will add it to the list of workflows */ - $ret = $newuser->setMandatoryWorkflow($traditionalworkflow); - $this->assertTrue($ret); - $workflows = $newuser->getMandatoryWorkflows(); - $this->assertIsArray($workflows); - $this->assertCount(2, $workflows); - - /* Set a single mandatory workflow with setMandatoryWorkflows() will delete - * all existing workflows and set a new list of workflows - */ - $ret = $newuser->setMandatoryWorkflows([$simpleworkflow]); - $this->assertTrue($ret); - $workflows = $newuser->getMandatoryWorkflows(); - $this->assertIsArray($workflows); - $this->assertCount(1, $workflows); - - /* Set several mandatory workflows will delete all existing workflows - * and set new workflows. - */ - $ret = $newuser->setMandatoryWorkflows([$simpleworkflow, $traditionalworkflow]); - $this->assertTrue($ret); - $workflows = $newuser->getMandatoryWorkflows(); - $this->assertIsArray($workflows); - $this->assertCount(2, $workflows); - - /* Setting an empty list will delete all mandatory workflows */ - $ret = $newuser->setMandatoryWorkflows([]); - $this->assertTrue($ret); - $workflows = $newuser->getMandatoryWorkflows(); - $this->assertNull($workflows); - } - - /** - * Test method getMandatoryWorkflow() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetMandatoryWorkflow() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $workflow = $user->getMandatoryWorkflow(); - $this->assertNull($workflow); - } - - /** - * Test method getMandatoryWorkflows() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetMandatoryWorkflows() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $workflow = $user->getMandatoryWorkflows(); - $this->assertNull($workflow); - } - - /** - * Test method getGroups() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetGroups() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $groups = $user->getGroups(); - $this->assertIsArray($groups); - $this->assertCount(0, $groups); - $group = self::$dms->addGroup('Group', ''); - $ret = $user->joinGroup($group); - $this->assertTrue($ret); - /* Adding the user a twice to a group will fail */ - $ret = $user->joinGroup($group); - $this->assertFalse($ret); - /* user now belongs to two groups */ - $groups = $user->getGroups(); - $this->assertIsArray($groups); - $this->assertCount(1, $groups); - /* Leave the group */ - $ret = $user->leaveGroup($group); - $this->assertTrue($ret); - /* Leave the group again will fail */ - $ret = $user->leaveGroup($group); - $this->assertFalse($ret); - /* the user is no longer in any group */ - $groups = $user->getGroups(); - $this->assertIsArray($groups); - $this->assertCount(0, $groups); - } - - /** - * Test method hasImage() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testHasImage() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $image = $user->hasImage(); - $this->assertFalse($image); - } - - /** - * Test method hasImage() - * - * @return void - */ - public function testHasImageSqlFail() - { - $user = $this->getAdminUser(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT COUNT(*) AS num FROM `tblUserImages` WHERE")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $user->setDMS($dms); - $this->assertFalse($user->hasImage()); - } - - /** - * Test method getImage() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetImage() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $image = $user->getImage(); - $this->assertNull($image); - } - - /** - * Test method getImage() - * - * @return void - */ - public function testGetImageSqlFail() - { - $user = $this->getAdminUser(); - $db = $this->createMock(SeedDMS_Core_DatabaseAccess::class); - $db->expects($this->once()) - ->method('getResultArray') - ->with($this->stringContains("SELECT * FROM `tblUserImages` WHERE")) - ->willReturn(false); - $dms = new SeedDMS_Core_DMS($db, ''); - $user->setDMS($dms); - $this->assertFalse($user->getImage()); - } - - /** - * Test method setImage() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testSetImage() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $file = self::createTempFile(200); - $ret = $user->setImage($file, 'text/plain'); - $this->assertTrue(SeedDMS_Core_File::removeFile($file)); - $this->assertTrue($ret); - $ret = $user->hasImage(); - $this->assertTrue($ret); - $image = $user->getImage(); - $this->assertIsArray($image); - $this->assertEquals('text/plain', $image['mimeType']); - } - - /** - * Test method delMandatoryReviewers() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testDelMandatoryReviewers() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $ret = $user->delMandatoryReviewers(); - $this->assertTrue($ret); - } - - /** - * Test method delMandatoryApprovers() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testDelMandatoryApprovers() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $ret = $user->delMandatoryApprovers(); - $this->assertTrue($ret); - } - - /** - * Test method delMandatoryWorkflow() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testDelMandatoryWorkflow() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $ret = $user->delMandatoryWorkflow(); - $this->assertTrue($ret); - } - - /** - * Test method getNotifications() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetNotifications() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $notifications = $user->getNotifications(); - $this->assertIsArray($notifications); - $this->assertCount(0, $notifications); - $notifications = $user->getNotifications(0); - $this->assertIsArray($notifications); - $this->assertCount(0, $notifications); - $notifications = $user->getNotifications(1); - $this->assertIsArray($notifications); - $this->assertCount(0, $notifications); - } - - /** - * Test method getKeywordCategories() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetKeywordCategories() - { - $user = SeedDMS_Core_User::getInstance(1, self::$dms); - $cats = $user->getKeywordCategories(); - $this->assertIsArray($cats); - $this->assertCount(0, $cats); - } -} - diff --git a/SeedDMS_Core/tests/WorkflowTest.php b/SeedDMS_Core/tests/WorkflowTest.php deleted file mode 100644 index 3abe1c26d..000000000 --- a/SeedDMS_Core/tests/WorkflowTest.php +++ /dev/null @@ -1,638 +0,0 @@ - - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version @package_version@ - * @link https://www.seeddms.org - */ - -use PHPUnit\Framework\SeedDmsTest; - -/** - * Group test class - * - * @category SeedDMS - * @package Tests - * @author Uwe Steinmann - * @copyright 2021 Uwe Steinmann - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @version Release: @package_version@ - * @link https://www.seeddms.org - */ -class WorkflowTest extends SeedDmsTest -{ - - /** - * Create a real sqlite database in memory - * - * @return void - */ - protected function setUp(): void - { - self::$dbh = self::createInMemoryDatabase(); - self::$contentdir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'phpunit-'.time(); - mkdir(self::$contentdir); - // echo "Creating temp content dir: ".self::$contentdir."\n"; - self::$dms = new \SeedDMS_Core_DMS(self::$dbh, self::$contentdir); - self::$dbversion = self::$dms->getDBVersion(); - } - - /** - * Clean up at tear down - * - * @return void - */ - protected function tearDown(): void - { - self::$dbh = null; - // echo "\nRemoving temp. content dir: ".self::$contentdir."\n"; - exec('rm -rf '.self::$contentdir); - } - - /** - * Test method getInitState() and setInitState() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetInitState() - { - $ws_nr = self::$dms->addWorkflowState('needs review', S_IN_WORKFLOW); - $ws_na = self::$dms->addWorkflowState('needs approval', S_IN_WORKFLOW); - $workflow = self::$dms->addWorkflow('traditional workflow', $ws_nr); - $initstate = $workflow->getInitState(); - $this->assertEquals($ws_nr->getName(), $initstate->getName()); - $ret = $workflow->setInitState($ws_na); - $this->assertTrue($ret); - $initstate = $workflow->getInitState(); - $this->assertEquals($ws_na->getName(), $initstate->getName()); - } - - /** - * Test method getName() and setName() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetStateName() - { - $state = self::$dms->addWorkflowState('needs review', S_IN_WORKFLOW); - $name = $state->getName(); - $this->assertEquals('needs review', $name); - $ret = $state->setName('foobar'); - $this->assertTrue($ret); - $name = $state->getName(); - $this->assertEquals('foobar', $name); - } - - /** - * Test method getName() and setName() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetActionName() - { - $action = self::$dms->addWorkflowAction('action'); - $name = $action->getName(); - $this->assertEquals('action', $name); - $ret = $action->setName('foobar'); - $this->assertTrue($ret); - $name = $action->getName(); - $this->assertEquals('foobar', $name); - } - - /** - * Test method getName() and setName() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetWorkflowName() - { - $ws_nr = self::$dms->addWorkflowState('needs review', S_IN_WORKFLOW); - $workflow = self::$dms->addWorkflow('traditional workflow', $ws_nr); - $name = $workflow->getName(); - $this->assertEquals('traditional workflow', $name); - $ret = $workflow->setName('foo'); - $this->assertTrue($ret); - $name = $workflow->getName(); - $this->assertEquals('foo', $name); - } - - /** - * Test method getDocumentStatus() and setDocumentStatus() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testGetAndSetDocumentStatus() - { - $state = self::$dms->addWorkflowState('some name', S_RELEASED); - $docstatus = $state->getDocumentStatus(); - $this->assertEquals(S_RELEASED, $docstatus); - $ret = $state->setDocumentStatus(S_REJECTED); - $this->assertTrue($ret); - $docstatus = $state->getDocumentStatus(); - $this->assertEquals(S_REJECTED, $docstatus); - } - - /** - * Test method workflow->remove() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testCreateAndRemoveWorkflow() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - $this->assertIsObject($user); - - /* Add a new user who will be the reviewer */ - $reviewer = self::$dms->addUser('reviewer', 'reviewer', 'Reviewer One', 'user1@seeddms.org', 'en_GB', 'bootstrap', ''); - $this->assertIsObject($reviewer); - - /* Add a new user who will be the approver */ - $approver = self::$dms->addUser('approver', 'approver', 'Approver One', 'user1@seeddms.org', 'en_GB', 'bootstrap', ''); - $this->assertIsObject($approver); - - $workflow = self::createWorkflow($reviewer, $approver); - $this->assertIsObject($workflow); - - $ret = $workflow->remove(); - $this->assertTrue($ret); - - $states = self::$dms->getAllWorkflowStates(); - $this->assertIsArray($states); - $this->assertCount(4, $states); - foreach($states as $state) - $this->assertFalse($state->isUsed()); - - $actions = self::$dms->getAllWorkflowActions(); - $this->assertIsArray($actions); - $this->assertCount(3, $actions); - foreach($actions as $action) - $this->assertFalse($action->isUsed()); - - } - - /** - * Test method remove() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testCreateAndRemoveAction() - { - $action = self::$dms->addWorkflowAction('action'); - $this->assertIsObject($action); - $actions = self::$dms->getAllWorkflowActions(); - $this->assertIsArray($actions); - $this->assertCount(1, $actions); - $ret = $action->remove(); - $this->assertTrue($ret); - $actions = self::$dms->getAllWorkflowActions(); - $this->assertIsArray($actions); - $this->assertCount(0, $actions); - } - - /** - * Test method remove() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testCreateAndRemoveState() - { - $state = self::$dms->addWorkflowState('needs review', S_IN_WORKFLOW); - $this->assertIsObject($state); - $states = self::$dms->getAllWorkflowStates(); - $this->assertIsArray($states); - $this->assertCount(1, $states); - $ret = $state->remove(); - $this->assertTrue($ret); - $states = self::$dms->getAllWorkflowStates(); - $this->assertIsArray($states); - $this->assertCount(0, $states); - } - - /** - * Test method setWorkflow(), getWorkflow(), getWorkflowState() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testAssignWorkflow() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - $this->assertIsObject($user); - - /* Add a new user who will be the reviewer */ - $reviewer = self::$dms->addUser('reviewer', 'reviewer', 'Reviewer One', 'user1@seeddms.org', 'en_GB', 'bootstrap', ''); - $this->assertIsObject($reviewer); - - /* Add a new user who will be the approver */ - $approver = self::$dms->addUser('approver', 'approver', 'Approver One', 'user1@seeddms.org', 'en_GB', 'bootstrap', ''); - $this->assertIsObject($approver); - - $workflow = self::createWorkflow($reviewer, $approver); - $this->assertIsObject($workflow); - - /* Check for cycles */ - $cycles = $workflow->checkForCycles(); - $this->assertFalse($cycles); - - /* Add a new document */ - $document = self::createDocument($rootfolder, $user, 'Document 1'); - $content = $document->getLatestContent(); - $this->assertIsObject($content); - $status = $content->getStatus(); - $this->assertIsArray($status); - $this->assertEquals(S_RELEASED, $status['status']); - - /* Assign the workflow */ - $ret = $content->setWorkflow($workflow, $user); - $this->assertTrue($ret); - - /* Assign a workflow again causes an error */ - $ret = $content->setWorkflow($workflow, $user); - $this->assertFalse($ret); - - /* Get a fresh copy of the content from the database and get the workflow */ - $again = self::$dms->getDocumentContent($content->getId()); - $this->assertIsObject($again); - $w = $again->getWorkflow(); - $this->assertEquals($workflow->getId(), $w->getId()); - - /* Status of content should be S_IN_WORKFLOW now */ - $status = $content->getStatus(); - $this->assertIsArray($status); - $this->assertEquals(S_IN_WORKFLOW, $status['status']); - - /* Get current workflow state */ - $state = $content->getWorkflowState(); - $this->assertEquals('needs review', $state->getName()); - - $workflowlog = $content->getWorkflowLog(); - $this->assertIsArray($workflowlog); - $this->assertCount(0, $workflowlog); - - /* The workflow has altogether 4 states */ - $states = $workflow->getStates(); - $this->assertIsArray($states); - $this->assertCount(4, $states); - - /* Check the initial state */ - $initstate = $workflow->getInitState(); - $this->assertEquals('needs review', $initstate->getName()); - - /* init state is definitely used */ - $ret = $initstate->isUsed(); - $this->assertTrue($ret); - - /* init state has two transistions linked to it */ - $transitions = $initstate->getTransitions(); - $this->assertIsArray($transitions); - $this->assertCount(2, $transitions); - - /* Check if workflow is used by any document */ - $isused = $workflow->isUsed(); - $this->assertTrue($isused); - - } - - /** - * Test method setWorkflow(), getWorkflow(), getWorkflowState() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testStepThroughWorkflow() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - $this->assertIsObject($user); - - /* Add a new user who will be the reviewer */ - $reviewer = self::$dms->addUser('reviewer', 'reviewer', 'Reviewer One', 'user1@seeddms.org', 'en_GB', 'bootstrap', ''); - $this->assertIsObject($reviewer); - - /* Add a new user who will be the approver */ - $approver = self::$dms->addUser('approver', 'approver', 'Approver One', 'user1@seeddms.org', 'en_GB', 'bootstrap', ''); - $this->assertIsObject($approver); - - $workflow = self::createWorkflow($reviewer, $approver); - - /* Add a new document */ - $document = self::createDocument($rootfolder, $user, 'Document 1'); - $content = $document->getLatestContent(); - $this->assertIsObject($content); - $status = $content->getStatus(); - $this->assertIsArray($status); - $this->assertEquals(S_RELEASED, $status['status']); - - /* Assign the workflow */ - $ret = $content->setWorkflow($workflow, $user); - $this->assertTrue($ret); - - $status = $content->getStatus(); - $this->assertIsArray($status); - $this->assertEquals(S_IN_WORKFLOW, $status['status']); - - /* Remove the workflow */ - $ret = $content->removeWorkflow($user); - $this->assertTrue($ret); - - $status = $content->getStatus(); - $this->assertIsArray($status); - $this->assertEquals(S_RELEASED, $status['status']); - - /* Remove the workflow again is just fine */ - $ret = $content->removeWorkflow($user); - $this->assertTrue($ret); - - /* Assign the workflow again */ - $ret = $content->setWorkflow($workflow, $user); - $this->assertTrue($ret); - - $status = $content->getStatus(); - $this->assertIsArray($status); - $this->assertEquals(S_IN_WORKFLOW, $status['status']); - - - /* Check if workflow needs action by the reviewer/approver */ - $ret = $content->needsWorkflowAction($reviewer); - $this->assertTrue($ret); - $ret = $content->needsWorkflowAction($approver); - $this->assertFalse($ret); - - /* Get current workflow state*/ - $state = $content->getWorkflowState(); - $this->assertEquals('needs review', $state->getName()); - - /* There should be two possible transitions now - * NR -- review -> NA - * NR -- reject -> RJ - */ - $nexttransitions = $workflow->getNextTransitions($state); - $this->assertIsArray($nexttransitions); - $this->assertCount(2, $nexttransitions); - - /* But of course, there were no previous transitions */ - $prevtransitions = $workflow->getPreviousTransitions($state); - $this->assertIsArray($prevtransitions); - $this->assertCount(0, $prevtransitions); - - /* Check if reviewer is allowed to trigger the transition. - * As we are still in the intitial state, the possible transitions - * may both be triggered by the reviewer but not by the approver. - */ - foreach($nexttransitions as $nexttransition) { - if($nexttransition->getNextState()->getDocumentStatus() == S_REJECTED) - $rejecttransition = $nexttransition; - elseif($nexttransition->getNextState()->getDocumentStatus() == S_IN_WORKFLOW) - $reviewtransition = $nexttransition; - $ret = $content->triggerWorkflowTransitionIsAllowed($reviewer, $nexttransition); - $this->assertTrue($ret); - $ret = $content->triggerWorkflowTransitionIsAllowed($approver, $nexttransition); - $this->assertFalse($ret); - } - - /* Trigger the successful review transition. - * As there is only one reviewer the transition will fire and the workflow - * moves forward into the next state. triggerWorkflowTransition() returns the - * next state. - */ - $nextstate = $content->triggerWorkflowTransition($reviewer, $reviewtransition, 'Review succeeded'); - $this->assertIsObject($nextstate); - $this->assertEquals('needs approval', $nextstate->getName()); - - $state = $content->getWorkflowState(); - $this->assertEquals($nextstate->getId(), $state->getId()); - $this->assertEquals('needs approval', $state->getName()); - - /* The workflow log has one entry now */ - $workflowlog = $content->getLastWorkflowLog(); - $this->assertIsObject($workflowlog); - $this->assertEquals('Review succeeded', $workflowlog->getComment()); - - /* There should be two possible transitions now - * NA -- approve -> RL - * NA -- reject -> RJ - */ - $nexttransitions = $workflow->getNextTransitions($state); - $this->assertIsArray($nexttransitions); - $this->assertCount(2, $nexttransitions); - - /* But of course, there is one previous transitions, the one that led to - * the current state of the workflow. - */ - $prevtransitions = $workflow->getPreviousTransitions($state); - $this->assertIsArray($prevtransitions); - $this->assertCount(1, $prevtransitions); - $this->assertEquals($reviewtransition->getId(), $prevtransitions[0]->getId()); - - /* Check if approver is allowed to trigger the transition. - * As we are now in 'needs approval' state, the possible transitions - * may both be triggered by the approver but not by the reviewer. - */ - foreach($nexttransitions as $nexttransition) { - if($nexttransition->getNextState()->getDocumentStatus() == S_REJECTED) - $rejecttransition = $nexttransition; - elseif($nexttransition->getNextState()->getDocumentStatus() == S_RELEASED) - $releasetransition = $nexttransition; - $ret = $content->triggerWorkflowTransitionIsAllowed($approver, $nexttransition); - $this->assertTrue($ret); - $ret = $content->triggerWorkflowTransitionIsAllowed($reviewer, $nexttransition); - $this->assertFalse($ret); - } - - /* Trigger the successful approve transition. - * As there is only one approver the transition will fire and the workflow - * moves forward into the next state. triggerWorkflowTransition() returns the - * next state. - */ - $nextstate = $content->triggerWorkflowTransition($approver, $releasetransition, 'Approval succeeded'); - $this->assertIsObject($nextstate); - $this->assertEquals('released', $nextstate->getName()); - - /* The workflow log has two entries now */ - $workflowlog = $content->getLastWorkflowLog(); - $this->assertIsObject($workflowlog); - $this->assertEquals('Approval succeeded', $workflowlog->getComment()); - - /* Because the workflow has reached a final state, the workflow will no - * longer be attached to the document. - */ - $workflow = $content->getWorkflow(); - $this->assertFalse($workflow); - - /* There is also no way to get the state anymore */ - $state = $content->getWorkflowState(); - $this->assertFalse($state); - - $status = $content->getStatus(); - $this->assertIsArray($status); - $this->assertEquals(S_RELEASED, $status['status']); - - /* Even after the workflow has been finished the log can still be retrieved */ - $workflowlog = $content->getLastWorkflowLog(); - $this->assertIsObject($workflowlog); - $this->assertEquals('Approval succeeded', $workflowlog->getComment()); - } - - /** - * Test method rewindWorkflow() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testRewindWorkflow() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - $this->assertIsObject($user); - - /* Add a new user who will be the reviewer */ - $reviewer = self::$dms->addUser('reviewer', 'reviewer', 'Reviewer One', 'user1@seeddms.org', 'en_GB', 'bootstrap', ''); - $this->assertIsObject($reviewer); - - /* Add a new user who will be the approver */ - $approver = self::$dms->addUser('approver', 'approver', 'Approver One', 'user1@seeddms.org', 'en_GB', 'bootstrap', ''); - $this->assertIsObject($approver); - - $workflow = self::createWorkflow($reviewer, $approver); - - /* Add a new document */ - $document = self::createDocument($rootfolder, $user, 'Document 1'); - $content = $document->getLatestContent(); - $this->assertIsObject($content); - $status = $content->getStatus(); - $this->assertIsArray($status); - $this->assertEquals(S_RELEASED, $status['status']); - - /* Assign the workflow */ - $ret = $content->setWorkflow($workflow, $user); - $this->assertTrue($ret); - - $status = $content->getStatus(); - $this->assertIsArray($status); - $this->assertEquals(S_IN_WORKFLOW, $status['status']); - - /* Check if workflow needs action by the reviewer */ - $ret = $content->needsWorkflowAction($reviewer); - $this->assertTrue($ret); - - /* Get current workflow state*/ - $state = $content->getWorkflowState(); - $this->assertEquals('needs review', $state->getName()); - - /* There should be two possible transitions now - * NR -- review -> NA - * NR -- reject -> RJ - */ - $nexttransitions = $workflow->getNextTransitions($state); - $this->assertIsArray($nexttransitions); - $this->assertCount(2, $nexttransitions); - - /* Check if reviewer is allowed to trigger the transition. - * As we are still in the intitial state, the possible transitions - * may both be triggered by the reviewer but not by the approver. - */ - foreach($nexttransitions as $nexttransition) { - if($nexttransition->getNextState()->getDocumentStatus() == S_IN_WORKFLOW) - $reviewtransition = $nexttransition; - } - - /* Trigger the successful review transition. - * As there is only one reviewer the transition will fire and the workflow - * moves forward into the next state. triggerWorkflowTransition() returns the - * next state. - */ - $nextstate = $content->triggerWorkflowTransition($reviewer, $reviewtransition, 'Review succeeded'); - $this->assertIsObject($nextstate); - $this->assertEquals('needs approval', $nextstate->getName()); - - /* Get current workflow state*/ - $state = $content->getWorkflowState(); - $this->assertEquals('needs approval', $state->getName()); - - /* The workflow log has one entry now */ - $workflowlogs = $content->getWorkflowLog(); - $this->assertIsArray($workflowlogs); - $this->assertCount(1, $workflowlogs); - if(self::$dbversion['major'] > 5) - $this->assertEquals('Review succeeded', $workflowlogs[1][0]->getComment()); - else - $this->assertEquals('Review succeeded', $workflowlogs[0]->getComment()); - - $ret = $content->rewindWorkflow(); - $this->assertTrue($ret); - - /* After rewinding the workflow the initial state is set ... */ - $state = $content->getWorkflowState(); - $this->assertEquals('needs review', $state->getName()); - - /* and the workflow log has been cleared */ - $workflowlogs = $content->getWorkflowLog(); - $this->assertIsArray($workflowlogs); - $this->assertCount(0, $workflowlogs); - } - - /** - * Test method getTransitionsByStates() - * - * This method uses a real in memory sqlite3 database. - * - * @return void - */ - public function testTransitionsByStateWorkflow() - { - $rootfolder = self::$dms->getRootFolder(); - $user = self::$dms->getUser(1); - $this->assertIsObject($user); - - /* Add a new user who will be the reviewer */ - $reviewer = self::$dms->addUser('reviewer', 'reviewer', 'Reviewer One', 'user1@seeddms.org', 'en_GB', 'bootstrap', ''); - $this->assertIsObject($reviewer); - - /* Add a new user who will be the approver */ - $approver = self::$dms->addUser('approver', 'approver', 'Approver One', 'user1@seeddms.org', 'en_GB', 'bootstrap', ''); - $this->assertIsObject($approver); - - $workflow = self::createWorkflow($reviewer, $approver); - - /* Check the initial state */ - $initstate = $workflow->getInitState(); - $this->assertEquals('needs review', $initstate->getName()); - - /* init state has two transistions linked to it */ - $transitions = $initstate->getTransitions(); - $this->assertIsArray($transitions); - $this->assertCount(2, $transitions); - - $t = $workflow->getTransitionsByStates($initstate, $transitions[1]->getNextState()); - $this->assertEquals($transitions[1]->getId(), $t[0]->getId()); - } - -} diff --git a/SeedDMS_Lucene/CHANGELOG.md b/SeedDMS_Lucene/CHANGELOG.md deleted file mode 100644 index ce4685461..000000000 --- a/SeedDMS_Lucene/CHANGELOG.md +++ /dev/null @@ -1,94 +0,0 @@ -1.1.18 (2023-01-09) ---------------------- -- IndexedDocument() accepts a callable for conversion to text -- SeedDMS_Lucene_Search::open and create return itself but Zend_Search_Lucene - -1.1.17 (2021-05-10) ---------------------- -- close pipes in execWithTimeout(), also return exit code of command - - -1.1.16 (2020-12-12) ---------------------- -- add indexing of folders - -1.1.15 (2020-09-10) ---------------------- -- 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() - -1.1.14 (2020-09-02) ---------------------- -- Index users with at least read access on the document - -1.1.13 (2018-04-11) ---------------------- -- IndexedDocument() remembers cmd and mimetype - -1.1.12 (2018-01-30) ---------------------- -- execWithTimeout() reads data from stderr and saves it into error msg - -1.1.11 (2017-12-04) ---------------------- -- allow conversion commands for mimetypes with wildcards - -1.1.10 (2017-03-01) ---------------------- -- catch exception in execWithTimeout() - -1.1.9 (2016-04-28) ---------------------- -- pass variables to stream_select() to fullfill strict standards. -- make all functions in Indexer.php static - -1.1.8 (2016-03-29) ---------------------- -- set last parameter of stream_select() to 200000 micro sec. in case the timeout in sec. is set to 0 - -1.1.7 (2016-02-01) ---------------------- -- add command for indexing postѕcript files - -1.1.6 (2015-08-05) ---------------------- -- run external commands with a timeout - -1.1.5 (2014-07-30) ---------------------- -- field for original filename is treated as utf-8 -- declare SeeDMS_Lucene_Indexer::open() static - -1.1.4 (2013-08-13) ---------------------- -- class SeedDMS_Lucene_Search::search returns false if query is invalid instead of an empty result record - -1.1.3 (2013-06-27) ---------------------- -- explicitly set encoding to utf-8 when adding fields -- do not check if deleting document from index fails, update it in any case - -1.1.2 (2013-06-17) ---------------------- -- parse query term and catch errors before using it - -1.1.1 (2012-12-03) ---------------------- -- catch exception if index is opened but not available - -1.1.0 (2012-11-06) ---------------------- -- use a configurable list of mime type converters, fixed indexing and searching - of special chars like german umlaute. - -1.0.1 (2011-11-06) ---------------------- -- New Release - -0.0.1 (2009-04-27) ---------------------- - diff --git a/SeedDMS_Lucene/Lucene.php b/SeedDMS_Lucene/Lucene.php deleted file mode 100644 index 96dee03e3..000000000 --- a/SeedDMS_Lucene/Lucene.php +++ /dev/null @@ -1,44 +0,0 @@ - diff --git a/SeedDMS_Lucene/Lucene/IndexedDocument.php b/SeedDMS_Lucene/Lucene/IndexedDocument.php deleted file mode 100644 index c8e76b26c..000000000 --- a/SeedDMS_Lucene/Lucene/IndexedDocument.php +++ /dev/null @@ -1,266 +0,0 @@ - - * @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 - * @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())); - $this->addField(Zend_Search_Lucene_Field::Keyword('record_type', 'document')); - $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')); - $this->addField(Zend_Search_Lucene_Field::UnIndexed('created', $version->getDate())); - if(!$nocontent) - $this->addField(Zend_Search_Lucene_Field::UnIndexed('indexed', time())); - 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_callable($convcmd)) { - $result = $convcmd($document); - if($result['content']) { - self::setContent($result['content']); - } elseif($result['content'] === false) { - $this->errormsg = $result['errormsg']; - } - $this->cmd = $result['cmd']; - } elseif(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::Keyword('record_type', 'folder')); - $this->addField(Zend_Search_Lucene_Field::UnIndexed('created', $document->getDate())); - $this->addField(Zend_Search_Lucene_Field::UnIndexed('indexed', time())); - } - } /* }}} */ - - 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; - } /* }}} */ -} -?> diff --git a/SeedDMS_Lucene/Lucene/Indexer.php b/SeedDMS_Lucene/Lucene/Indexer.php deleted file mode 100644 index f0dee91ce..000000000 --- a/SeedDMS_Lucene/Lucene/Indexer.php +++ /dev/null @@ -1,208 +0,0 @@ - - * @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 - * @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; - - /** - * @var string $index lucene index - * @access protected - */ - protected $index; - - public function __construct($index) { - $this->index = $index; - } - - static function open($conf) { /* {{{ */ - try { - $index = Zend_Search_Lucene::open($conf['indexdir']); - if($index) - return new self($index); - else - return null; - } catch (Exception $e) { - return null; - } - } /* }}} */ - - static function create($conf) { /* {{{ */ - try { - $index = Zend_Search_Lucene::create($conf['indexdir']); - if($index) - return new self($index); - else - return null; - } catch (Exception $e) { - return null; - } - } /* }}} */ - - /** - * Do some initialization - * - */ - public 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); - } /* }}} */ - - /** - * Add document to index - * - * @param object $doc indexed document of class - * SeedDMS_Lucene_IndexedDocument - * @return boolean false in case of an error, otherwise true - */ - function addDocument($doc) { /* {{{ */ - if(!$this->index) - return false; - - return $this->index->addDocument($doc); - } /* }}} */ - - /** - * Remove document from index - * - * @param object $id internal id of document - * @return boolean false in case of an error, otherwise true - */ - public function delete($id) { /* {{{ */ - if(!$this->index) - return false; - - return $this->index->delete($id); - } /* }}} */ - - /** - * Check if document was deleted - * - * @param object $id internal id of document - * @return boolean true if document was deleted - */ - public function isDeleted($id) { /* {{{ */ - if(!$this->index) - return false; - - return $this->index->isDeleted($id); - } /* }}} */ - - /** - * Search in index - * - * @param string $query - * @return array result - */ - public function find($query) { /* {{{ */ - if(!$this->index) - return false; - - return $this->index->find($query); - } /* }}} */ - - /** - * 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->index) - return false; - - return $this->index->findById($id); - } /* }}} */ - - /** - * 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->index) - return false; - - return $this->index->getDocument($id); - } /* }}} */ - - /** - * Return list of terms in index - * - * @return array list of Zend_Lucene_Term - */ - public function terms($prefix='', $col='') { /* {{{ */ - if(!$this->index) - return false; - - return $this->index->terms(); - } /* }}} */ - - /** - * Return number of documents in index - * - * @return interger number of documents - */ - public function count() { /* {{{ */ - if(!$this->index) - return false; - - return $this->index->count(); - } /* }}} */ - - /** - * Commit changes - * - * This function does nothing! - */ - function commit() { /* {{{ */ - if(!$this->index) - return false; - - return $this->index->commit(); - } /* }}} */ - - /** - * Optimize index - * - * This function does nothing! - */ - function optimize() { /* {{{ */ - if(!$this->index) - return false; - - return $this->index->optimize(); - } /* }}} */ -} -?> diff --git a/SeedDMS_Lucene/Lucene/Search.php b/SeedDMS_Lucene/Lucene/Search.php deleted file mode 100644 index 38827a02b..000000000 --- a/SeedDMS_Lucene/Lucene/Search.php +++ /dev/null @@ -1,160 +0,0 @@ - - * @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 - * @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($fields['owner'])) { - if($querystr) - $querystr .= ' && '; - $querystr .= 'owner:'.$fields['owner']; - } elseif(is_array($fields['owner'])) { - if($querystr) - $querystr .= ' && '; - $querystr .= '(owner:"'; - $querystr .= implode('" || owner:"', $fields['owner']); - $querystr .= '")'; - } - } - if(!empty($fields['record_type'])) { - if($querystr) - $querystr .= ' && '; - $querystr .= '(record_type:'; - $querystr .= implode(' || record_type:', $fields['record_type']); - $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['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; - } - } /* }}} */ -} -?> diff --git a/SeedDMS_Lucene/composer.json b/SeedDMS_Lucene/composer.json deleted file mode 100644 index 68a37caaf..000000000 --- a/SeedDMS_Lucene/composer.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "seeddms/lucene", - "description": "Lucene based fulltext search for SeedDMS ", - "type": "library", - "license": "GPL-2.0-or-later", - "minimum-stability": "dev", - "autoload": { - "psr-4": { - "Seeddms\\Lucene\\": "Lucene/" - }, - "classmap": ["Lucene/"] - }, - "authors": [ - { - "name": "Uwe Steinmann", - "email": "info@seeddms.org" - } - ], - "require-dev": { - "phpunit/phpunit": "^9" - } - -} diff --git a/SeedDMS_Lucene/package.xml b/SeedDMS_Lucene/package.xml deleted file mode 100644 index eeb33269a..000000000 --- a/SeedDMS_Lucene/package.xml +++ /dev/null @@ -1,389 +0,0 @@ - - - SeedDMS_Lucene - pear.php.net - Fulltext search for SeedDMS - SeedDMS is a web based document management system (DMS). This is - the fulltext search engine for it, based on Lucene. - - Uwe Steinmann - steinm - uwe@steinmann.cx - yes - - 2023-01-09 - - - 1.1.18 - 1.1.18 - - - stable - stable - - GPL License - -- IndexedDocument() accepts a callable for conversion to text -- SeedDMS_Lucene_Search::open and create return itself but Zend_Search_Lucene - - - - - - - - - - - - - - - - - - - - - - - - - 4.3.0 - - - 1.5.4 - - - - - - - 2009-04-27 - - 0.0.1 - 0.0.1 - - - alpha - alpha - - BSD License - - - - - 2011-11-06 - - - 1.0.1 - 1.0.0 - - - beta - beta - - GPL License - -- New Release - - - - 2012-11-06 - - - 1.1.0 - 1.1.0 - - - beta - beta - - GPL License - -- use a configurable list of mime type converters, fixed indexing and searching - of special chars like german umlaute. - - - - 2012-12-03 - - - 1.1.1 - 1.1.1 - - - stable - stable - - GPL License - -- catch exception if index is opened but not available - - - - 2013-06-17 - - - 1.1.2 - 1.1.1 - - - stable - stable - - GPL License - -- parse query term and catch errors before using it - - - - 2013-06-27 - - - 1.1.3 - 1.1.1 - - - stable - stable - - GPL License - -- explicitly set encoding to utf-8 when adding fields -- do not check if deleting document from index fails, update it in any case - - - - 2013-08-13 - - - 1.1.4 - 1.1.4 - - - stable - stable - - GPL License - -- class SeedDMS_Lucene_Search::search returns false if query is invalid instead of an empty result record - - - - 2014-07-30 - - - 1.1.5 - 1.1.5 - - - stable - stable - - GPL License - -- field for original filename is treated as utf-8 -- declare SeeDMS_Lucene_Indexer::open() static - - - - 2015-08-05 - - - 1.1.6 - 1.1.6 - - - stable - stable - - GPL License - -- run external commands with a timeout - - - - 2016-02-01 - - - 1.1.7 - 1.1.7 - - - stable - stable - - GPL License - -- add command for indexing postѕcript files - - - - 2016-03-29 - - - 1.1.8 - 1.1.7 - - - stable - stable - - GPL License - -- set last parameter of stream_select() to 200000 micro sec. in case the timeout in sec. is set to 0 - - - - 2016-04-28 - - - 1.1.9 - 1.1.7 - - - stable - stable - - GPL License - -- pass variables to stream_select() to fullfill strict standards. -- make all functions in Indexer.php static - - - - 2017-03-01 - - - 1.1.10 - 1.1.10 - - - stable - stable - - GPL License - -- catch exception in execWithTimeout() - - - - 2017-12-04 - - - 1.1.11 - 1.1.11 - - - stable - stable - - GPL License - -- allow conversion commands for mimetypes with wildcards - - - - 2018-01-30 - - - 1.1.12 - 1.1.12 - - - stable - stable - - GPL License - -- execWithTimeout() reads data from stderr and saves it into error msg - - - - 2018-04-11 - - - 1.1.13 - 1.1.13 - - - stable - stable - - GPL License - -- IndexedDocument() remembers cmd and mimetype - - - - 2020-09-02 - - - 1.1.14 - 1.1.14 - - - stable - stable - - GPL License - -- Index users with at least read access on the document - - - - 2020-09-10 - - - 1.1.15 - 1.1.15 - - - stable - stable - - GPL License - -- 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() - - - - 2020-12-12 - - - 1.1.16 - 1.1.16 - - - stable - stable - - GPL License - -- add indexing of folders - - - - 2021-05-10 - - - 1.1.17 - 1.1.17 - - - stable - stable - - GPL License - -- close pipes in execWithTimeout(), also return exit code of command - - - - diff --git a/SeedDMS_Preview/CHANGELOG.md b/SeedDMS_Preview/CHANGELOG.md deleted file mode 100644 index 76b1546c5..000000000 --- a/SeedDMS_Preview/CHANGELOG.md +++ /dev/null @@ -1,128 +0,0 @@ -1.5.0 (2023-01-09) ---------------------- -- add previewer which creates txt - -1.4.0 (2021-10-16) ---------------------- -- use new conversion service if available -- createRawPreview() checks early if a converter exists - - -1.3.3 (2020-12-23) ---------------------- -- 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 - -1.3.2 (2020-12-23) ---------------------- -- set header Content-Length -- update package description - -1.3.1 (2020-03-21) ---------------------- -- add parameter $target to SeedDMS_Preview_pdfPreviewer::hasRawPreview() and SeedDMS_Preview_pdfPreviewer::getRawPreview() - -1.3.0 (2020-02-17) ---------------------- -- add new methode getPreviewFile() - -1.2.10 (2019-02-11) ---------------------- -- new parameter for enabling/disabling xsendfile -- fix creation of pdf preview if document content class is not SeedDMS_Core_DocumentContent - -1.2.9 (2018-07-13) ---------------------- -- make sure list of converters is always an array -- usage of mod_sendfile can be configured - -1.2.8 (2018-03-08) ---------------------- -- preview is also created if SeedDMS_Core_DocumentContent has a child class - -1.2.7 (2018-01-18) ---------------------- -- 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 - -1.2.6 (2017-12-04) ---------------------- -- SeedDMS_Preview_Base::setConverters() overrides existing converters. -- New method SeedDMS_Preview_Base::addConverters() merges new converters with old ones. - -1.2.5 (2017-10-11) ---------------------- -- SeedDMS_Preview_Base::hasConverter() returns only try if command is set - -1.2.4 (2017-10-11) ---------------------- -- fix typo in converter for tar.gz files - -1.2.3 (2017-09-18) ---------------------- -- createPreview() returns false if running the converter command fails - -1.2.2 (2017-03-02) ---------------------- -- commands can be set for mimetypes 'xxxx/*' and '*' -- pass mimetype as parameter '%m' to converter - -1.2.1 (2016-11-15) ---------------------- -- setConverters() overrides exiting converters - -1.2.0 (2016-11-07) ---------------------- -- add new previewer which converts document to pdf instead of png - -1.1.9 (2016-04-26) ---------------------- -- 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() - -1.1.8 (2016-04-05) ---------------------- -- pass variables to stream_select (required by php7) - -1.1.7 (2016-03-29) ---------------------- -- set last parameter of stream_select() to 200000 micro sec. in case the timeout in sec. is set to 0 - -1.1.6 (2016-03-08) ---------------------- -- check if object passed to createPreview(), hasPreview() is not null - -1.1.5 (2016-02-11) ---------------------- -- add method getFilesize() -- timeout for external commands can be passed to contructor of SeedDMS_Preview_Previewer - -1.1.4 (2015-08-08) ---------------------- -- command for creating the preview will be called with a given timeout - -1.1.3 (2015-02-13) ---------------------- -- 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. - -1.1.2 (2014-04-10) ---------------------- -- create fixed width image with proportional height - -1.1.1 (2014-03-18) ---------------------- -- add converters for .tar.gz, .ps, .txt - -1.1.0 (2013-04-29) ---------------------- -- preview image can also be created from a document file (SeedDMS_Core_DocumentFile) - -1.0.0 (2012-11-20) ---------------------- -- initial version - diff --git a/SeedDMS_Preview/Preview.php b/SeedDMS_Preview/Preview.php deleted file mode 100644 index ce5853001..000000000 --- a/SeedDMS_Preview/Preview.php +++ /dev/null @@ -1,39 +0,0 @@ - diff --git a/SeedDMS_Preview/Preview/Base.php b/SeedDMS_Preview/Preview/Base.php deleted file mode 100644 index 9fb401ada..000000000 --- a/SeedDMS_Preview/Preview/Base.php +++ /dev/null @@ -1,247 +0,0 @@ - - * @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 - * @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); - } - } /* }}} */ - - /** - * Get preview dir - * - * @return string name of preview directory on disc - */ - public function getPreviewDir() { /* {{{ */ - return $this->previewDir; - } /* }}} */ - - /** - * 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; - } /* }}} */ -} - diff --git a/SeedDMS_Preview/Preview/PdfPreviewer.php b/SeedDMS_Preview/Preview/PdfPreviewer.php deleted file mode 100644 index 2a219b476..000000000 --- a/SeedDMS_Preview/Preview/PdfPreviewer.php +++ /dev/null @@ -1,309 +0,0 @@ - - * @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 - * @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.DIRECTORY_SEPARATOR.'pdf', $timeout, $xsendfile); - $this->converters = array( - ); - } /* }}} */ - - /** - * Return the physical filename of the preview image on disc - * including the path - * - * @param object $object document content or document file - * @return string file name of preview image - */ - public function getFileName($object) { /* {{{ */ - if(!$object) - return false; - - $document = $object->getDocument(); - $dms = $document->_dms; - $dir = $this->previewDir.DIRECTORY_SEPARATOR.$document->getDir(); - switch(get_class($object)) { - case $dms->getClassname('documentcontent'): - $target = $dir.'p'.$object->getVersion(); - break; - case $dms->getClassname('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.DIRECTORY_SEPARATOR.$dir)) { - if (!SeedDMS_Core_File::makeDir($this->previewDir.DIRECTORY_SEPARATOR.$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); - $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 - * @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.DIRECTORY_SEPARATOR.$document->getDir(); - if(file_exists($dir) && is_dir($dir)) { - return SeedDMS_Preview_Previewer::recurseRmdir($dir); - } else { - return false; - } - - } /* }}} */ -} -?> diff --git a/SeedDMS_Preview/Preview/Previewer.php b/SeedDMS_Preview/Preview/Previewer.php deleted file mode 100644 index f53780e7a..000000000 --- a/SeedDMS_Preview/Preview/Previewer.php +++ /dev/null @@ -1,371 +0,0 @@ - - * @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 - * @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; - - /** - * Create instance of image previewer - * - * @param string $previewDir path of base directory where all images are - * stored. This directory will have a subdirectory derived from the object id. - * @param integer $width default width of an image - * @param integer $timeout timeout for shell commands to create a preview image - * @param boolean $xsendfile if set to true the apache module xsendfile will - * be used. - */ - function __construct($previewDir, $width=40, $timeout=5, $xsendfile=true) { /* {{{ */ - parent::__construct($previewDir.DIRECTORY_SEPARATOR.'png', $timeout, $xsendfile); - $this->converters = array( - ); - $this->width = intval($width); - } /* }}} */ - - /** - * Return the physical filename of the preview image on disc - * including the path - * - * @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=0) { /* {{{ */ - if(!$object) - return false; - - if($width == 0) - $width = $this->width; - else - $width = intval($width); - - $document = $object->getDocument(); - $dms = $document->_dms; - $dir = $this->previewDir.DIRECTORY_SEPARATOR.$document->getDir(); - switch(get_class($object)) { - case $dms->getClassname('documentcontent'): - $target = $dir.'p'.$object->getVersion().'-'.$width; - break; - case $dms->getClassname('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) - * @param boolean $new will be set to true if the preview images was created - * @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.DIRECTORY_SEPARATOR.$dir)) { - if (!SeedDMS_Core_File::makeDir($this->previewDir.DIRECTORY_SEPARATOR.$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 - * @param boolean $new will be set to true if the preview images was created - * @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.DIRECTORY_SEPARATOR.$document->getDir(); - if(file_exists($dir) && is_dir($dir)) { - return SeedDMS_Preview_Previewer::recurseRmdir($dir); - } else { - return false; - } - - } /* }}} */ -} -?> diff --git a/SeedDMS_Preview/Preview/TxtPreviewer.php b/SeedDMS_Preview/Preview/TxtPreviewer.php deleted file mode 100644 index 7826ff793..000000000 --- a/SeedDMS_Preview/Preview/TxtPreviewer.php +++ /dev/null @@ -1,306 +0,0 @@ - - * @copyright Copyright (C) 2010, Uwe Steinmann - * @version Release: @package_version@ - */ - - -/** - * Class for managing creation of text preview for documents. - * - * @category DMS - * @package SeedDMS_Preview - * @version @version@ - * @author Uwe Steinmann - * @copyright Copyright (C) 2011, Uwe Steinmann - * @version Release: @package_version@ - */ -class SeedDMS_Preview_TxtPreviewer extends SeedDMS_Preview_Base { - - function __construct($previewDir, $timeout=5, $xsendfile=true) { /* {{{ */ - parent::__construct($previewDir.DIRECTORY_SEPARATOR.'txt', $timeout, $xsendfile); - $this->converters = array( - ); - } /* }}} */ - - /** - * Return the physical filename of the preview image on disc - * including the path - * - * @param object $object document content or document file - * @return string file name of preview image - */ - public function getFileName($object) { /* {{{ */ - if(!$object) - return false; - - $document = $object->getDocument(); - $dms = $document->_dms; - $dir = $this->previewDir.DIRECTORY_SEPARATOR.$document->getDir(); - switch(get_class($object)) { - case $dms->getClassname('documentcontent'): - $target = $dir.'t'.$object->getVersion(); - 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, 'text/plain'); - } /* }}} */ - - /** - * Create a text preview for a given file - * - * This method creates a preview in text 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.text (if set) or md5($infile).text. - * The $mimetype is used to select the propper conversion programm. - * An already existing text 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 true; - - if(!$this->previewDir) - return false; - if(!is_dir($this->previewDir.DIRECTORY_SEPARATOR.$dir)) { - if (!SeedDMS_Core_File::makeDir($this->previewDir.DIRECTORY_SEPARATOR.$dir)) { - return false; - } - } - if(!file_exists($infile)) - return false; - if(!$target) - $target = $this->previewDir.$dir.md5($infile); - $this->lastpreviewfile = $target.'.txt'; - if($target != '' && (!file_exists($target.'.txt') || filectime($target.'.txt') < filectime($infile))) { - if($this->conversionmgr) { - if(!$this->conversionmgr->convert($infile, $mimetype, 'text/plain', $target.'.txt')) { - $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.'.txt', $mimetype), $this->converters[$mimetype]); - } elseif(isset($this->converters[$mimeparts[0].'/*'])) { - $cmd = str_replace(array('%f', '%o', '%m'), array($infile, $target.'.txt', $mimetype), $this->converters[$mimeparts[0].'/*']); - } elseif(isset($this->converters['*'])) { - $cmd = str_replace(array('%f', '%o', '%m'), array($infile, $target.'.txt', $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 - * @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.'.txt') && filectime($target.'.txt') >= filectime($infile)) { - return true; - } - return false; - } /* }}} */ - - /** - * Check if a preview txt 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.'.txt') && filectime($target.'.txt') >= $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.'.txt')) { - $this->sendFile($target.'.txt'); - } - } /* }}} */ - - /** - * 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.'.txt')) { - $this->sendFile($target.'.txt'); - } - } /* }}} */ - - /** - * 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.'.txt')) { - return(filesize($target.'.txt')); - } 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.'.txt')) { - return(unlink($target.'.txt')); - } 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 text belonging to a document - * - * This function removes the preview text 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.DIRECTORY_SEPARATOR.$document->getDir(); - if(file_exists($dir) && is_dir($dir)) { - return SeedDMS_Preview_Previewer::recurseRmdir($dir); - } else { - return false; - } - - } /* }}} */ -} -?> diff --git a/SeedDMS_Preview/composer.json b/SeedDMS_Preview/composer.json deleted file mode 100644 index 9a4b5a11a..000000000 --- a/SeedDMS_Preview/composer.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "seeddms/preview", - "description": "Create Preview images, pdf and txt for for SeedDMS ", - "type": "library", - "license": "GPL-2.0-or-later", - "minimum-stability": "dev", - "autoload": { - "psr-4": { - "Seeddms\\Preview\\": "Preview/" - }, - "classmap": ["Preview/"] - }, - "authors": [ - { - "name": "Uwe Steinmann", - "email": "info@seeddms.org" - } - ], - "require-dev": { - "phpunit/phpunit": "^9" - } - -} diff --git a/SeedDMS_Preview/package.xml b/SeedDMS_Preview/package.xml deleted file mode 100644 index d6dd7bc59..000000000 --- a/SeedDMS_Preview/package.xml +++ /dev/null @@ -1,511 +0,0 @@ - - - SeedDMS_Preview - pear.php.net - Create thumbnails from document content for SeedDMS - SeedDMS is a web based document management system (DMS). These - are the classes to create preview images and pdf file from the document content. - - Uwe Steinmann - steinm - uwe@steinmann.cx - yes - - 2023-01-09 - - - 1.5.0 - 1.5.0 - - - stable - stable - - GPL License - -- add previewer which creates txt - - - - - - - - - - - - - - - - - - - - - - - - - - - - 7.4.0 - - - 1.5.4 - - - - - - - 2012-11-20 - - - 1.0.0 - 1.0.0 - - - stable - stable - - GPL License - -- initial version - - - - 2013-04-29 - - - 1.1.0 - 1.1.0 - - - stable - stable - - GPL License - -- preview image can also be created from a document file (SeedDMS_Core_DocumentFile) - - - - 2014-03-18 - - - 1.1.1 - 1.1.0 - - - stable - stable - - GPL License - -- add converters for .tar.gz, .ps, .txt - - - - 2014-04-10 - - - 1.1.2 - 1.1.0 - - - stable - stable - - GPL License - -- create fixed width image with proportional height - - - - 2015-02-13 - - - 1.1.3 - 1.1.0 - - - stable - stable - - GPL License - -- 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. - - - - 2015-08-08 - - - 1.1.4 - 1.1.0 - - - stable - stable - - GPL License - -- command for creating the preview will be called with a given timeout - - - - 2016-02-11 - - - 1.1.5 - 1.1.5 - - - stable - stable - - GPL License - -- add method getFilesize() -- timeout for external commands can be passed to contructor of SeedDMS_Preview_Previewer - - - - 2016-03-08 - - - 1.1.6 - 1.1.6 - - - stable - stable - - GPL License - -- check if object passed to createPreview(), hasPreview() is not null - - - - 2016-03-29 - - - 1.1.7 - 1.1.7 - - - stable - stable - - GPL License - -- set last parameter of stream_select() to 200000 micro sec. in case the timeout in sec. is set to 0 - - - - 2016-04-05 - - - 1.1.8 - 1.1.8 - - - stable - stable - - GPL License - -- pass variables to stream_select (required by php7) - - - - 2016-04-26 - - - 1.1.9 - 1.1.9 - - - stable - stable - - GPL License - -- 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() - - - - 2016-11-07 - - - 1.2.0 - 1.2.0 - - - stable - stable - - GPL License - -- add new previewer which converts document to pdf instead of png - - - - 2016-11-15 - - - 1.2.1 - 1.2.0 - - - stable - stable - - GPL License - -- setConverters() overrides exiting converters - - - - 2017-03-02 - - - 1.2.2 - 1.2.0 - - - stable - stable - - GPL License - -- commands can be set for mimetypes 'xxxx/*' and '*' -- pass mimetype as parameter '%m' to converter - - - - 2017-09-18 - - - 1.2.3 - 1.2.0 - - - stable - stable - - GPL License - -- createPreview() returns false if running the converter command fails - - - - 2017-10-11 - - - 1.2.4 - 1.2.0 - - - stable - stable - - GPL License - -- fix typo in converter for tar.gz files - - - - 2017-10-11 - - - 1.2.5 - 1.2.0 - - - stable - stable - - GPL License - -- SeedDMS_Preview_Base::hasConverter() returns only try if command is set - - - - 2017-12-04 - - - 1.2.6 - 1.2.0 - - - stable - stable - - GPL License - -- SeedDMS_Preview_Base::setConverters() overrides existing converters. -- New method SeedDMS_Preview_Base::addConverters() merges new converters with old ones. - - - - 2018-01-18 - - - 1.2.7 - 1.2.0 - - - stable - stable - - GPL License - -- 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 - - - - 2018-03-08 - - - 1.2.8 - 1.2.0 - - - stable - stable - - GPL License - -- preview is also created if SeedDMS_Core_DocumentContent has a child class - - - - 2018-07-13 - - - 1.2.9 - 1.2.9 - - - stable - stable - - GPL License - -- make sure list of converters is always an array -- usage of mod_sendfile can be configured - - - - 2019-02-11 - - - 1.2.10 - 1.2.10 - - - stable - stable - - GPL License - -- new parameter for enabling/disabling xsendfile -- fix creation of pdf preview if document content class is not SeedDMS_Core_DocumentContent - - - - 2020-02-17 - - - 1.3.0 - 1.3.0 - - - stable - stable - - GPL License - -- add new methode getPreviewFile() - - - - 2020-03-21 - - - 1.3.1 - 1.3.1 - - - stable - stable - - GPL License - -- add parameter $target to SeedDMS_Preview_pdfPreviewer::hasRawPreview() and SeedDMS_Preview_pdfPreviewer::getRawPreview() - - - - 2020-12-23 - - - 1.3.2 - 1.3.1 - - - stable - stable - - GPL License - -- set header Content-Length -- update package description - - - - 2020-12-23 - - - 1.3.3 - 1.3.3 - - - stable - stable - - GPL License - -- 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 - - - - 2021-10-16 - - - 1.4.0 - 1.4.0 - - - stable - stable - - GPL License - -- use new conversion service if available -- createRawPreview() checks early if a converter exists - - - - diff --git a/SeedDMS_Preview/tests/Preview.php b/SeedDMS_Preview/tests/Preview.php deleted file mode 100644 index e69de29bb..000000000 diff --git a/SeedDMS_SQLiteFTS/CHANGELOG.md b/SeedDMS_SQLiteFTS/CHANGELOG.md deleted file mode 100644 index d75aace4c..000000000 --- a/SeedDMS_SQLiteFTS/CHANGELOG.md +++ /dev/null @@ -1,89 +0,0 @@ -1.0.18 (2023-01-09) ---------------------- -- add optional parameter $order to SeedDMS_SQLiteFTS_Indexer::find() -- add optional parameters $query and $col to SeedDMS_SQLiteFTS_Indexer::terms() -- IndexedDocument() accepts a callable for conversion to text -- remove stop words from content - -1.0.17 (2022-03-04) ---------------------- -- throw exeption in find() instead of returning false -- fix query if rootFolder or startFolder is set - - -1.0.16 (2021-05-10) ---------------------- -- close pipes in execWithTimeout(), also return exit code of command -- add support for fts5 (make it the default) -- add class SeedDMS_SQLiteFTS_Field - -1.0.15 (2020-12-12) ---------------------- -- add indexing folders - -1.0.14 (2020-09-11) ---------------------- -- 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() - -1.0.13 (2020-09-02) ---------------------- -- add user to list of terms - -1.0.12 (2020-09-02) ---------------------- -- Index users with at least read access on a document - -1.0.11 (2019-11-28) ---------------------- -- Set 'created' in index to creation date of indexed content (was set to current -timestamp) - -1.0.10 (2018-04-11) ---------------------- -- IndexedDocument() remembers cmd and mimetype - -1.0.9 (2018-01-30) ---------------------- -- execWithTimeout() reads data from stderr and saves it into error msg - -1.0.8 (2017-12-04) ---------------------- -- allow conversion commands for mimetypes with wildcards - -1.0.7 (2017-03-01) ---------------------- -- catch exception in execWithTimeout() - -1.0.6 (2016-03-29) ---------------------- -- fix calculation of timeout (see bug #269) - -1.0.5 (2016-03-29) ---------------------- -- set last parameter of stream_select() to 200000 micro sec. in case the timeout in sec. is set to 0 - -1.0.4 (2016-03-15) ---------------------- -- make it work with sqlite3 < 3.8.0 - -1.0.3 (2016-02-01) ---------------------- -- add command for indexing postѕcript files - -1.0.2 (2016-01-10) ---------------------- -- check if index exists before removing it when creating a new one - -1.0.1 (2015-11-16) ---------------------- -- add __get() to SQLiteFTS_Document because class.IndexInfo.php access class variable title which doesn't exists - -1.0.0 (2015-08-10) ---------------------- -- initial release - diff --git a/SeedDMS_SQLiteFTS/SQLiteFTS.php b/SeedDMS_SQLiteFTS/SQLiteFTS.php deleted file mode 100644 index 338a79e1c..000000000 --- a/SeedDMS_SQLiteFTS/SQLiteFTS.php +++ /dev/null @@ -1,49 +0,0 @@ - diff --git a/SeedDMS_SQLiteFTS/SQLiteFTS/Document.php b/SeedDMS_SQLiteFTS/SQLiteFTS/Document.php deleted file mode 100644 index 7b299a9a0..000000000 --- a/SeedDMS_SQLiteFTS/SQLiteFTS/Document.php +++ /dev/null @@ -1,117 +0,0 @@ - - * @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 - * @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; - } -} -?> diff --git a/SeedDMS_SQLiteFTS/SQLiteFTS/Exception.php b/SeedDMS_SQLiteFTS/SQLiteFTS/Exception.php deleted file mode 100644 index 281947dce..000000000 --- a/SeedDMS_SQLiteFTS/SQLiteFTS/Exception.php +++ /dev/null @@ -1,41 +0,0 @@ - - * @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 - * @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); - } -} diff --git a/SeedDMS_SQLiteFTS/SQLiteFTS/IndexedDocument.php b/SeedDMS_SQLiteFTS/SQLiteFTS/IndexedDocument.php deleted file mode 100644 index 1bb3a32f0..000000000 --- a/SeedDMS_SQLiteFTS/SQLiteFTS/IndexedDocument.php +++ /dev/null @@ -1,266 +0,0 @@ - - * @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 - * @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())); - $this->addField(SeedDMS_SQLiteFTS_Field::Keyword('created', $version->getDate(), 'unindexed')); - if(!$nocontent) - $this->addField(SeedDMS_SQLiteFTS_Field::Keyword('indexed', time(), '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_callable($convcmd)) { - $result = $convcmd($document); - if($result['content']) { - self::setContent($result['content']); - } elseif($result['content'] === false) { - $this->errormsg = $result['errormsg']; - } - $this->cmd = $result['cmd']; - } elseif(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')); - $this->addField(SeedDMS_SQLiteFTS_Field::Keyword('indexed', time(), '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; - } /* }}} */ -} -?> diff --git a/SeedDMS_SQLiteFTS/SQLiteFTS/Indexer.php b/SeedDMS_SQLiteFTS/SQLiteFTS/Indexer.php deleted file mode 100644 index 559b93bc4..000000000 --- a/SeedDMS_SQLiteFTS/SQLiteFTS/Indexer.php +++ /dev/null @@ -1,463 +0,0 @@ - - * @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 - * @copyright Copyright (C) 2011, Uwe Steinmann - * @version Release: @package_version@ - */ -class SeedDMS_SQLiteFTS_Indexer { - - /** - * @var string $_ftstype - * @access protected - */ - protected $_ftstype; - - /** - * @var object $_conn sqlite index - * @access protected - */ - protected $_conn; - - /** - * @var array $_stop_words array of stop words - * @access protected - */ - protected $_stop_words; - - const ftstype = 'fts5'; - - /** - * Remove stopwords from string - */ - protected function strip_stopwords($str = "") { /* {{{ */ - // 1.) break string into words - // [^-\w\'] matches characters, that are not [0-9a-zA-Z_-'] - // if input is unicode/utf-8, the u flag is needed: /pattern/u - $words = preg_split('/[^-\w\']+/u', $str, -1, PREG_SPLIT_NO_EMPTY); - - // 2.) if we have at least 2 words, remove stopwords - if(!empty($words)) { - $stopwords = $this->_stop_words; - $words = array_filter($words, function ($w) use (&$stopwords) { - return ((mb_strlen($w, 'utf-8') > 2) && !isset($stopwords[mb_strtolower($w, "utf-8")])); - }); - } - - // check if not too much was removed such as "the the" would return empty - if(!empty($words)) - return implode(" ", $words); - return $str; - } /* }}} */ - - /** - * 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'; - $this->_stop_words = []; - } /* }}} */ - - /** - * 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 static::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, indexed, users, status, path, notindexed=created, notindexed=indexed, matchinfo=fts3)'; - else - $sql = 'CREATE VIRTUAL TABLE docs USING fts4(documentid, record_type, title, comment, keywords, category, mimetype, origfilename, owner, content, created, indexed, 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, indexed 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 - * - */ - public function init($stopWordsFile='') { /* {{{ */ - if($stopWordsFile) - $this->_stop_words = array_flip(preg_split("/[\s,]+/", file_get_contents($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', 'indexed') 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; - } - if($this->_stop_words) - $content = $this->strip_stopwords($content); - - $sql = "INSERT INTO docs (documentid, record_type, title, comment, keywords, category, owner, content, mimetype, origfilename, created, indexed, 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.", ".(int)$indexed.", ".$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 $id internal id of document - * @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, $filter='', $limit=array(), $order=array()) { /* {{{ */ - if(!$this->_conn) - return false; - - /* First count some records for facets */ - foreach(array('owner', 'mimetype', 'category', 'status') as $facetname) { - $sql = "SELECT `".$facetname."`, count(*) AS `c` FROM `docs`"; - if($query) { - $sql .= " WHERE docs MATCH ".$this->_conn->quote($query); - } - if($filter) { - if($query) - $sql .= " AND ".$filter; - else - $sql .= " WHERE ".$filter; - } - $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']; - } - } elseif($facetname == 'status') { - $facets[$facetname][($row[$facetname]-10).''] = $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); - if($filter) { - if($query) - $sql .= " AND ".$filter; - else - $sql .= " WHERE ".$filter; - } - $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($filter) { - if($query) - $sql .= " AND ".$filter; - else - $sql .= " WHERE ".$filter; - } - if($this->_ftstype == 'fts5') { - //$sql .= " ORDER BY rank"; - // boost documentid, record_type, title, comment, keywords, category, mimetype, origfilename, owner, content, created unindexed, users, status, path - if(!empty($order['by'])) { - switch($order['by']) { - case "title": - $sql .= " ORDER BY title"; - break; - case "created": - $sql .= " ORDER BY created"; - break; - default: - $sql .= " ORDER BY bm25(docs, 10.0, 0.0, 10.0, 5.0, 5.0, 10.0)"; - } - if(!empty($order['dir'])) { - if($order['dir'] == 'desc') - $sql .= " DESC"; - } - } - } - 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, indexed, 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::Keyword('indexed', $rec['indexed'])); - $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', explode('x', substr($rec['path'], 1, -1)))); - if($content) - $doc->addField(SeedDMS_SQLiteFTS_Field::UnStored('content', $rec['content'])); - } - return $doc; - } /* }}} */ - - /** - * Return list of terms in index - * - * @return array list of SeedDMS_SQLiteFTS_Term - */ - public function terms($prefix='', $col='') { /* {{{ */ - if(!$this->_conn) - return false; - - if($this->_ftstype == 'fts5') { - $sql = "SELECT term, col, doc as occurrences FROM docs_terms"; - if($prefix || $col) { - $sql .= " WHERE"; - if($prefix) { - $sql .= " term like '".$prefix."%'"; - if($col) - $sql .= " AND"; - } - if($col) - $sql .= " col = '".$col."'"; - } - $sql .= " ORDER BY col, occurrences desc"; - } else { - $sql = "SELECT term, col, occurrences FROM docs_terms WHERE col!='*'"; - if($prefix) - $sql .= " AND term like '".$prefix."%'"; - if($col) - $sql .= " AND col = '".$col."'"; - $sql .= " ORDER BY col, occurrences desc"; - } - $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 number of documents in index - * - * @return interger number of documents - */ - 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() { /* {{{ */ - } /* }}} */ -} -?> diff --git a/SeedDMS_SQLiteFTS/SQLiteFTS/QueryHit.php b/SeedDMS_SQLiteFTS/SQLiteFTS/QueryHit.php deleted file mode 100644 index 843be973d..000000000 --- a/SeedDMS_SQLiteFTS/SQLiteFTS/QueryHit.php +++ /dev/null @@ -1,72 +0,0 @@ - - * @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 - * @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; - $this->_document = null; - } /* }}} */ - - /** - * 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; - } /* }}} */ -} -?> diff --git a/SeedDMS_SQLiteFTS/SQLiteFTS/Search.php b/SeedDMS_SQLiteFTS/SQLiteFTS/Search.php deleted file mode 100644 index 22c43a1e5..000000000 --- a/SeedDMS_SQLiteFTS/SQLiteFTS/Search.php +++ /dev/null @@ -1,166 +0,0 @@ - - * @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 - * @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(), $order=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 .= '*)'; - } - - $filterstr = ''; - if(!empty($fields['created_start'])) { - if($filterstr) - $filterstr .= ' AND '; - $filterstr .= '(created>='.$fields['created_start'].')'; - } - if(!empty($fields['created_end'])) { - if($filterstr) - $filterstr .= ' AND '; - $filterstr .= '(created<'.$fields['created_end'].')'; - } - try { - $result = $this->index->find($querystr, $filterstr, $limit, $order); - $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; - } - } /* }}} */ -} -?> diff --git a/SeedDMS_SQLiteFTS/SQLiteFTS/Term.php b/SeedDMS_SQLiteFTS/SQLiteFTS/Term.php deleted file mode 100644 index e31ff56bc..000000000 --- a/SeedDMS_SQLiteFTS/SQLiteFTS/Term.php +++ /dev/null @@ -1,75 +0,0 @@ - - * @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 - * @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', - 13 => 'indexed', - ); - /* 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; - } /* }}} */ - -} -?> diff --git a/SeedDMS_SQLiteFTS/composer.json b/SeedDMS_SQLiteFTS/composer.json deleted file mode 100644 index 90a19cd7d..000000000 --- a/SeedDMS_SQLiteFTS/composer.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "seeddms/lucene", - "description": "SQLiteFTS based fulltext search for SeedDMS ", - "type": "library", - "license": "GPL-2.0-or-later", - "minimum-stability": "dev", - "autoload": { - "psr-4": { - "Seeddms\\SQLiteFTS\\": "SQLiteFTS/" - }, - "classmap": ["SQLiteFTS/"] - }, - "authors": [ - { - "name": "Uwe Steinmann", - "email": "info@seeddms.org" - } - ], - "require-dev": { - "phpunit/phpunit": "^9" - } - -} diff --git a/SeedDMS_SQLiteFTS/package.xml b/SeedDMS_SQLiteFTS/package.xml deleted file mode 100644 index 2b7dfe0b5..000000000 --- a/SeedDMS_SQLiteFTS/package.xml +++ /dev/null @@ -1,376 +0,0 @@ - - - SeedDMS_SQLiteFTS - pear.php.net - Fulltext search based on sqlite for SeedDMS - SeedDMS is a web based document management system (DMS). This is - the fulltext search engine for it, based on SQLite FTS. - - Uwe Steinmann - steinm - uwe@steinmann.cx - yes - - 2023-01-09 - - - 1.0.18 - 1.0.18 - - - stable - stable - - GPL License - -- add optional parameter $order to SeedDMS_SQLiteFTS_Indexer::find() -- add optional parameters $query and $col to SeedDMS_SQLiteFTS_Indexer::terms() -- IndexedDocument() accepts a callable for conversion to text -- remove stop words from content - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 4.3.0 - - - 1.5.4 - - - - - - - 2015-08-10 - - - 1.0.0 - 1.0.0 - - - stable - stable - - GPL License - -- initial release - - - - 2015-11-16 - - - 1.0.1 - 1.0.1 - - - stable - stable - - GPL License - -- add __get() to SQLiteFTS_Document because class.IndexInfo.php access class variable title which doesn't exists - - - - 2016-01-10 - - - 1.0.2 - 1.0.1 - - - stable - stable - - GPL License - -- check if index exists before removing it when creating a new one - - - - 2016-02-01 - - - 1.0.3 - 1.0.1 - - - stable - stable - - GPL License - -- add command for indexing postѕcript files - - - - 2016-03-15 - - - 1.0.4 - 1.0.1 - - - stable - stable - - GPL License - -- make it work with sqlite3 < 3.8.0 - - - - 2016-03-29 - - - 1.0.5 - 1.0.1 - - - stable - stable - - GPL License - -- set last parameter of stream_select() to 200000 micro sec. in case the timeout in sec. is set to 0 - - - - 2016-03-29 - - - 1.0.6 - 1.0.1 - - - stable - stable - - GPL License - -- fix calculation of timeout (see bug #269) - - - - 2017-03-01 - - - 1.0.7 - 1.0.7 - - - stable - stable - - GPL License - -- catch exception in execWithTimeout() - - - - 2017-12-04 - - - 1.0.8 - 1.0.8 - - - stable - stable - - GPL License - -- allow conversion commands for mimetypes with wildcards - - - - 2018-01-30 - - - 1.0.9 - 1.0.9 - - - stable - stable - - GPL License - -- execWithTimeout() reads data from stderr and saves it into error msg - - - - 2018-04-11 - - - 1.0.10 - 1.0.10 - - - stable - stable - - GPL License - -- IndexedDocument() remembers cmd and mimetype - - - - 2019-11-28 - - - 1.0.11 - 1.0.11 - - - stable - stable - - GPL License - -- Set 'created' in index to creation date of indexed content (was set to current -timestamp) - - - - 2020-09-02 - - - 1.0.12 - 1.0.12 - - - stable - stable - - GPL License - -- Index users with at least read access on a document - - - - 2020-09-02 - - - 1.0.13 - 1.0.13 - - - stable - stable - - GPL License - -- add user to list of terms - - - - 2020-09-11 - - - 1.0.14 - 1.0.14 - - - stable - stable - - GPL License - -- 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() - - - - 2020-12-12 - - - 1.0.15 - 1.0.15 - - - stable - stable - - GPL License - -- add indexing folders - - - - 2021-05-10 - - - 1.0.16 - 1.0.16 - - - stable - stable - - GPL License - -- close pipes in execWithTimeout(), also return exit code of command -- add support for fts5 (make it the default) -- add class SeedDMS_SQLiteFTS_Field - - - - 2022-03-04 - - - 1.0.17 - 1.0.17 - - - stable - stable - - GPL License - -- throw exeption in find() instead of returning false -- fix query if rootFolder or startFolder is set - - - - diff --git a/SeedDMS_SQLiteFTS/tests/Index.php b/SeedDMS_SQLiteFTS/tests/Index.php deleted file mode 100644 index e69de29bb..000000000