mirror of
				https://git.code.sf.net/p/seeddms/code
				synced 2025-10-31 13:18:06 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			366 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			366 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php declare(strict_types=1);
 | |
| /**
 | |
|  * Implementation of the database tests
 | |
|  *
 | |
|  * PHP version 7
 | |
|  *
 | |
|  * @category  SeedDMS
 | |
|  * @package   Tests
 | |
|  * @author    Uwe Steinmann <uwe@steinmann.cx>
 | |
|  * @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 <uwe@steinmann.cx>
 | |
|  * @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;
 | |
|     }
 | |
| 
 | |
| }
 | |
| 
 | 
