mirror of
				https://git.code.sf.net/p/seeddms/code
				synced 2025-10-31 05:11:27 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			4018 lines
		
	
	
		
			170 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			4018 lines
		
	
	
		
			170 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | ||
| //    MyDMS. Document Management System
 | ||
| //    Copyright (C) 2002-2005  Markus Westphal
 | ||
| //    Copyright (C) 2006-2008 Malcolm Cowe
 | ||
| //    Copyright (C) 2010 Matteo Lucarelli
 | ||
| //    Copyright (C) 2009-2012 Uwe Steinmann
 | ||
| //
 | ||
| //    This program is free software; you can redistribute it and/or modify
 | ||
| //    it under the terms of the GNU General Public License as published by
 | ||
| //    the Free Software Foundation; either version 2 of the License, or
 | ||
| //    (at your option) any later version.
 | ||
| //
 | ||
| //    This program is distributed in the hope that it will be useful,
 | ||
| //    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | ||
| //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | ||
| //    GNU General Public License for more details.
 | ||
| //
 | ||
| //    You should have received a copy of the GNU General Public License
 | ||
| //    along with this program; if not, write to the Free Software
 | ||
| //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 | ||
| 
 | ||
| 
 | ||
| class SeedDMS_Theme_Style extends SeedDMS_View_Common {
 | ||
| 	/**
 | ||
| 	 * @var string $extraheader extra html code inserted in the html header
 | ||
| 	 * of the page
 | ||
| 	 *
 | ||
| 	 * @access protected
 | ||
| 	 */
 | ||
| 	protected $extraheader;
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * @var array $nonces list of nonces
 | ||
| 	 *
 | ||
| 	 * @access protected
 | ||
| 	 */
 | ||
| 	protected $nonces;
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * @var string $footerjs js placed in footer of html page
 | ||
| 	 *
 | ||
| 	 * @access protected
 | ||
| 	 */
 | ||
| 	protected $footerjs;
 | ||
| 
 | ||
| 	function __construct($params, $theme='bootstrap') {
 | ||
| 		parent::__construct($params, $theme);
 | ||
| 		$this->extraheader = array('js'=>'', 'css'=>'', 'favicon'=>'', 'logo'=>'', 'logolink'=>'');
 | ||
| 		$this->footerjs = array();
 | ||
| 		$this->nonces = array();
 | ||
| 	}
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Add javascript to an internal array which is output at the
 | ||
| 	 * end of the page within a document.ready() function.
 | ||
| 	 *
 | ||
| 	 * @param string $script javascript to be added
 | ||
| 	 */
 | ||
| 	function addFooterJS($script) { /* {{{ */
 | ||
| 		$this->footerjs[] = $script;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function htmlStartPage($title="", $bodyClass="", $base="", $httpheader=array()) { /* {{{ */
 | ||
| 		if(1 || method_exists($this, 'js')) {
 | ||
| 			/* We still need unsafe-eval, because printDocumentChooserHtml and
 | ||
| 			 * printFolderChooserHtml will include a javascript file with ajax
 | ||
| 			 * which is evaluated by jquery
 | ||
| 			 * worker-src blob: is needed for cytoscape
 | ||
| 			 * X-WebKit-CSP is deprecated, Chrome understands Content-Security-Policy
 | ||
| 			 * since version 25+
 | ||
| 			 * X-Content-Security-Policy is deprecated, Firefox understands
 | ||
| 			 * Content-Security-Policy since version 23+
 | ||
| 			 * 'worker-src blob:' is needed for cytoscape
 | ||
| 			 * 'unsafe-inline' is needed for jquery 3.6.1 when loading the remote
 | ||
| 			 * content of a modal box
 | ||
| 			 */
 | ||
| 			$csp_rules = [];
 | ||
| 			$csp_rule = "script-src 'self' 'unsafe-eval' 'unsafe-inline'";
 | ||
| 			if($this->nonces) {
 | ||
| 				$csp_rule .= " 'nonce-".implode("' 'nonce-", $this->nonces)."'";
 | ||
| 			}
 | ||
| 			$csp_rules[] = $csp_rule;
 | ||
| 			$csp_rules[] = "worker-src blob:";
 | ||
| 			//$csp_rules[] = "style-src 'self'";
 | ||
| 			/* Do not allow to embed myself into frames on foreigns pages */
 | ||
| 			$csp_rules[] = "frame-ancestors 'self'";
 | ||
| 			if($this->hasHook('getCspRules')) {
 | ||
| 				$csp_rules = $this->callHook('getCspRules', $csp_rules);
 | ||
| 			}
 | ||
| 			foreach (array("X-WebKit-CSP", "X-Content-Security-Policy", "Content-Security-Policy") as $csp) {
 | ||
| 				header($csp . ": " . implode('; ', $csp_rules).';');
 | ||
| 			}
 | ||
| 		}
 | ||
| 		header('X-Content-Type-Options: nosniff');
 | ||
| 		header('Strict-Transport-Security: max-age=15768000; includeSubDomains; preload');
 | ||
| 		if($httpheader) {
 | ||
| 			foreach($httpheader as $name=>$value) {
 | ||
| 				header($name . ": " . $value);
 | ||
| 			}
 | ||
| 		}
 | ||
| 		if($this->hasHook('startPage'))
 | ||
| 				$this->callHook('startPage');
 | ||
| 		echo "<!DOCTYPE html>\n";
 | ||
| 		echo "<html lang=\"";
 | ||
| 		if(!empty($this->params['session']) && ($slang = $this->params['session']->getLanguage())) {
 | ||
| 			echo substr($slang, 0, 2);
 | ||
| //			echo str_replace('_', '-', $slang);
 | ||
| 		} else {
 | ||
| 			echo substr($this->params['settings']->_language, 0, 2);
 | ||
| //			echo str_replace('_', '-', $this->params['settings']->_language);
 | ||
| 		}
 | ||
| 		echo "\">\n<head>\n";
 | ||
| 		echo "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n";
 | ||
| 		echo '<meta name="viewport" content="width=device-width, initial-scale=1.0" />'."\n";
 | ||
| 		if($base)
 | ||
| 			echo '<base href="'.$base.'">'."\n";
 | ||
| 		elseif($this->baseurl)
 | ||
| 			echo '<base href="'.$this->baseurl.'">'."\n";
 | ||
| 		$sitename = trim(strip_tags($this->params['sitename']));
 | ||
| 		if(!empty($this->params['session']))
 | ||
| 			echo '<link rel="search" type="application/opensearchdescription+xml" href="'.$this->params['settings']->_httpRoot.'out/out.OpensearchDesc.php" title="'.(strlen($sitename)>0 ? $sitename : "").'"/>'."\n";
 | ||
| 		$parenttheme = 'bootstrap';
 | ||
| 		echo '<link href="'.$this->params['settings']->_httpRoot.'views/'.$this->theme.'/styles/seeddms.css" rel="stylesheet"/>'."\n";
 | ||
| 		echo '<link href="'.$this->params['settings']->_httpRoot.'views/'.$this->theme.'/vendors/font-awesome/css/font-awesome.min.css" rel="stylesheet"/>'."\n";
 | ||
| 		echo '<link href="'.$this->params['settings']->_httpRoot.'views/'.$this->theme.'/vendors/bootstrap-datepicker/css/bootstrap-datepicker.css" rel="stylesheet"/>'."\n";
 | ||
| 		echo '<link href="'.$this->params['settings']->_httpRoot.'styles/'.$parenttheme.'/chosen/css/chosen.css" rel="stylesheet"/>'."\n";
 | ||
| 		echo '<link href="'.$this->params['settings']->_httpRoot.'views/'.$this->theme.'/vendors/select2/css/select2.min.css" rel="stylesheet"/>'."\n";
 | ||
| 		echo '<link href="'.$this->params['settings']->_httpRoot.'views/'.$this->theme.'/vendors/select2-bootstrap4-theme/select2-bootstrap4.min.css" rel="stylesheet"/>'."\n";
 | ||
| 		echo '<link href="'.$this->params['settings']->_httpRoot.'views/'.$this->theme.'/vendors/jqtree/jqtree.css" rel="stylesheet"/>'."\n";
 | ||
| 		echo '<link href="'.$this->params['settings']->_httpRoot.'views/'.$this->theme.'/styles/application.css" rel="stylesheet"/>'."\n";
 | ||
| 		echo '<link href="'.$this->params['settings']->_httpRoot.'views/'.$this->theme.'/styles/styles.css" rel="stylesheet"/>'."\n";
 | ||
| 		if($this->extraheader['css'])
 | ||
| 			echo $this->extraheader['css'];
 | ||
| 		if(method_exists($this, 'css'))
 | ||
| 			echo '<link href="'.$this->params['absbaseprefix'].'out/out.'.$this->params['class'].'.php?action=css'.(!empty($_SERVER['QUERY_STRING']) ? '&'.$_SERVER['QUERY_STRING'] : '').'" rel="stylesheet"/>'."\n";
 | ||
| 
 | ||
| 		echo '<script type="text/javascript" src="'.$this->params['settings']->_httpRoot.'views/'.$this->theme.'/vendors/jquery/jquery.min.js"></script>'."\n";
 | ||
| 		if($this->extraheader['js'])
 | ||
| 			echo $this->extraheader['js'];
 | ||
| 		echo '<script type="text/javascript" src="'.$this->params['settings']->_httpRoot.'styles/'.$parenttheme.'/passwordstrength/jquery.passwordstrength.js"></script>'."\n";
 | ||
| 		echo '<script type="text/javascript" src="'.$this->params['settings']->_httpRoot.'views/'.$this->theme.'/vendors/noty/jquery.noty.js"></script>'."\n";
 | ||
| 		echo '<script type="text/javascript" src="'.$this->params['settings']->_httpRoot.'views/'.$this->theme.'/vendors/noty/layouts/topRight.js"></script>'."\n";
 | ||
| 		echo '<script type="text/javascript" src="'.$this->params['settings']->_httpRoot.'views/'.$this->theme.'/vendors/noty/layouts/topCenter.js"></script>'."\n";
 | ||
| 		echo '<script type="text/javascript" src="'.$this->params['settings']->_httpRoot.'views/'.$this->theme.'/vendors/noty/themes/default.js"></script>'."\n";
 | ||
| 		echo '<script type="text/javascript" src="'.$this->params['settings']->_httpRoot.'views/'.$this->theme.'/vendors/jqtree/tree.jquery.js"></script>'."\n";
 | ||
| 		echo '<script type="text/javascript" src="'.$this->params['settings']->_httpRoot.'views/'.$this->theme.'/vendors/bootbox/bootbox.min.js"></script>'."\n";
 | ||
| 		echo '<script type="text/javascript" src="'.$this->params['settings']->_httpRoot.'views/'.$this->theme.'/vendors/bootbox/bootbox.locales.min.js"></script>'."\n";
 | ||
| 		if(!empty($this->extraheader['favicon']))
 | ||
| 			echo $this->extraheader['favicon'];
 | ||
| 		else {
 | ||
| 			echo '<link rel="icon" href="'.$this->params['settings']->_httpRoot.'views/'.$this->theme.'/images/favicon.svg" type="image/svg+xml"/>'."\n";
 | ||
| 			echo '<link rel="apple-touch-icon" sizes="180x180" href="'.$this->params['settings']->_httpRoot.'views/'.$this->theme.'/images/apple-touch-icon.png">'."\n";
 | ||
| 		}
 | ||
| 		if(!empty($this->params['session']) && $this->params['session']->getSu()) {
 | ||
| ?>
 | ||
| <style type="text/css">
 | ||
| nav.navbar.fixed-top {
 | ||
| background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#882222), to(#111111));
 | ||
| background-image: webkit-linear-gradient(top, #882222, #111111);
 | ||
| background-image: linear-gradient(to bottom, #882222, #111111);;
 | ||
| }
 | ||
| </style>
 | ||
| <?php
 | ||
| 		}
 | ||
| 		echo "<title>".(strlen($sitename)>0 ? $sitename : "SeedDMS").(strlen($title)>0 ? ": " : "").htmlspecialchars($title)."</title>\n";
 | ||
| 		echo "</head>\n";
 | ||
| 		echo "<body".(strlen($bodyClass)>0 ? " class=\"".$bodyClass."\"" : "").">\n";
 | ||
| 		if(!empty($this->params['session']) && $flashmsg = $this->params['session']->getSplashMsg()) {
 | ||
| 			$this->params['session']->clearSplashMsg();
 | ||
| 			echo "<div class=\"splash\" data-type=\"".$flashmsg['type']."\"".(!empty($flashmsg['timeout']) ? ' data-timeout="'.$flashmsg['timeout'].'"': '').">".$flashmsg['msg']."</div>\n";
 | ||
| 		}
 | ||
| 		echo "<div class=\"statusbar-container\"><h1>".getMLText('recent_uploads')."</h1></div>\n";
 | ||
| 		if($this->hasHook('startBody'))
 | ||
| 				$this->callHook('startBody');
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function htmlAddHeader($head, $type='js') { /* {{{ */
 | ||
| 		if($type == 'logo' || $type == 'favicon' || $type == 'logolink')
 | ||
| 			$this->extraheader[$type] = $head;
 | ||
| 		else
 | ||
| 			$this->extraheader[$type] .= $head;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function htmlAddJsHeader($script) { /* {{{ */
 | ||
| 		$nonce = createNonce();
 | ||
| 		$this->nonces[] = $nonce;
 | ||
| 		$this->extraheader['js'] .= '<script type="text/javascript" src="'.$script.'" nonce="'.$nonce.'"></script>'."\n";
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function htmlEndPage($nofooter=false) { /* {{{ */
 | ||
| 		if(!$nofooter) {
 | ||
| 			$html = $this->footNote();
 | ||
| 			if($this->hasHook('footNote'))
 | ||
| 				$html = $this->callHook('footNote', $html);
 | ||
| 			echo $html;
 | ||
| 			if($this->params['showmissingtranslations']) {
 | ||
| 				$this->missingLanguageKeys();
 | ||
| 			}
 | ||
| 		}
 | ||
| 		$parenttheme = 'bootstrap';
 | ||
| 		echo '<script src="'.$this->params['settings']->_httpRoot.'views/'.$this->theme.'/vendors/popper/popper.min.js"></script>'."\n";
 | ||
| 		//echo '<script src="'.$this->params['settings']->_httpRoot.'styles/bootstrap/popper.js-1.14.3/dist/umd/popper.js"></script>'."\n";
 | ||
| 		echo '<script src="'.$this->params['settings']->_httpRoot.'views/'.$this->theme.'/vendors/bootstrap/bootstrap.min.js"></script>'."\n";
 | ||
| 		echo '<script src="'.$this->params['settings']->_httpRoot.'styles/'.$parenttheme.'/bootstrap/js/bootstrap-typeahead.js"></script>'."\n";
 | ||
| 		echo '<script src="'.$this->params['settings']->_httpRoot.'views/'.$this->theme.'/vendors/bootstrap-datepicker/js/bootstrap-datepicker.js"></script>'."\n";
 | ||
| 		foreach(array('de', 'es', 'ar', 'el', 'bg', 'ru', 'hr', 'hu', 'ko', 'pl', 'ro', 'sk', 'tr', 'uk', 'ca', 'nl', 'fi', 'cs', 'it', 'fr', 'sv', 'sl', 'pt-BR', 'zh-CN', 'zh-TW') as $lang)
 | ||
| 			echo '<script src="'.$this->params['settings']->_httpRoot.'views/'.$this->theme.'/vendors/bootstrap-datepicker/locales/bootstrap-datepicker.'.$lang.'.min.js"></script>'."\n";
 | ||
| 		echo '<script src="'.$this->params['settings']->_httpRoot.'styles/'.$parenttheme.'/chosen/js/chosen.jquery.min.js"></script>'."\n";
 | ||
| 		echo '<script src="'.$this->params['settings']->_httpRoot.'views/'.$this->theme.'/vendors/select2/js/select2.min.js"></script>'."\n";
 | ||
| 		parse_str($_SERVER['QUERY_STRING'], $tmp);
 | ||
| 		$tmp['action'] = 'webrootjs';
 | ||
| 		if(isset($tmp['formtoken']))
 | ||
| 			unset($tmp['formtoken']);
 | ||
| 		if(isset($tmp['referuri']))
 | ||
| 			unset($tmp['referuri']);
 | ||
| 		if(!empty($this->params['class']))
 | ||
| 			echo '<script src="'.$this->params['absbaseprefix'].'out/out.'.$this->params['class'].'.php?'.htmlentities(http_build_query($tmp)).'"></script>'."\n";
 | ||
| 		echo '<script src="'.$this->params['settings']->_httpRoot.'views/'.$this->theme.'/styles/application.js"></script>'."\n";
 | ||
| 		if($this->params['enablemenutasks'] && isset($this->params['user']) && $this->params['user']) {
 | ||
| 			$this->addFooterJS('SeedDMSTask.run();');
 | ||
| 		}
 | ||
| 		if($this->params['enabledropfolderlist'] && isset($this->params['user']) && $this->params['user']) {
 | ||
| 			$this->addFooterJS("SeedDMSTask.add({name: 'dropfolder', interval: 30, func: function(){\$('#menu-dropfolder > div.ajax').trigger('update', {folderid: seeddms_folder, noinit: true});}});");
 | ||
| 		}
 | ||
| 		if($this->footerjs) {
 | ||
| 			$jscode = "$(document).ready(function () {\n";
 | ||
| 			foreach($this->footerjs as $script) {
 | ||
| 				$jscode .= $script."\n";
 | ||
| 			}
 | ||
| 			$jscode .= "});\n";
 | ||
| 			$hashjs = md5($jscode);
 | ||
| 			if(!is_dir($this->params['cachedir'].'/js')) {
 | ||
| 				SeedDMS_Core_File::makeDir($this->params['cachedir'].'/js');
 | ||
| 			}
 | ||
| 			if(is_dir($this->params['cachedir'].'/js')) {
 | ||
| 				file_put_contents($this->params['cachedir'].'/js/'.$hashjs.'.js', $jscode);
 | ||
| 			}
 | ||
| 			$tmp['action'] = 'footerjs';
 | ||
| 			$tmp['hashjs'] = $hashjs;
 | ||
| 			echo '<script src="'.$this->params['absbaseprefix'].'out/out.'.$this->params['class'].'.php?'.htmlentities(http_build_query($tmp)).'"></script>'."\n";
 | ||
| 		}
 | ||
| 		if(method_exists($this, 'js')) {
 | ||
| 			parse_str($_SERVER['QUERY_STRING'], $tmp);
 | ||
| 			$tmp['action'] = 'js';
 | ||
| 			echo '<script src="'.$this->params['absbaseprefix'].'out/out.'.$this->params['class'].'.php?'.htmlentities(http_build_query($tmp)).'"></script>'."\n";
 | ||
| 		}
 | ||
| 		echo "</body>\n</html>\n";
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function webrootjs() { /* {{{ */
 | ||
| 		header('Content-Type: application/javascript; charset=UTF-8');
 | ||
| 		echo "var seeddms_absbaseprefix=\"".$this->params['absbaseprefix']."\";\n";
 | ||
| 		echo "var seeddms_webroot=\"".$this->params['settings']->_httpRoot."\";\n";
 | ||
| 		/* Place the current folder id in a js variable, just in case some js code
 | ||
| 		 * needs it, e.g. for reloading parts of the page via ajax.
 | ||
| 		 */
 | ||
| 		if(!empty($_REQUEST['folderid']))
 | ||
| 			echo "var seeddms_folder=".(int) $_REQUEST['folderid'].";\n";
 | ||
| 		else
 | ||
| 			echo "var seeddms_folder=0;\n";
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function footerjs() { /* {{{ */
 | ||
| 		header('Content-Type: application/javascript');
 | ||
| 		if(file_exists($this->params['cachedir'].'/js/'.$_GET['hashjs'].'.js')) {
 | ||
| 			readfile($this->params['cachedir'].'/js/'.$_GET['hashjs'].'.js');
 | ||
| 		}
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function missingLanguageKeys() { /* {{{ */
 | ||
| 		global $MISSING_LANG, $LANG;
 | ||
| 		if($MISSING_LANG) {
 | ||
| 			echo '<div class="container-fluid">'."\n";
 | ||
| 			$this->rowStart();
 | ||
| 			$this->columnStart(12);
 | ||
| 			echo $this->errorMsg("This page contains missing translations in the selected language. Please help to improve SeedDMS and provide the translation.");
 | ||
| 			echo "<table class=\"table table-sm\">";
 | ||
| 			echo "<tr><th>Key</th><th>engl. Text</th><th>Your translation</th></tr>\n";
 | ||
| 			foreach($MISSING_LANG as $key=>$lang) {
 | ||
| 				echo "<tr><td>".htmlspecialchars($key)."</td><td>".(isset($LANG['en_GB'][$key]) ? $LANG['en_GB'][$key] : '')."</td><td><div class=\"input-group send-missing-translation\"><input name=\"missing-lang-key\" type=\"hidden\" value=\"".$key."\" /><input name=\"missing-lang-lang\" type=\"hidden\" value=\"".$lang."\" /><input type=\"text\" class=\"form-control\" name=\"missing-lang-translation\" placeholder=\"Your translation in '".$lang."'\"/><div class=\"input-group-append\"><button class=\"btn btn-secondary\">Submit</button></div></div></td></tr>";
 | ||
| 			}
 | ||
| 			echo "</table>";
 | ||
| 			echo "<div class=\"splash\" data-type=\"error\" data-timeout=\"5500\"><b>There are missing translations on this page!</b><br />Please check the bottom of the page.</div>\n";
 | ||
| 			echo "</div>\n";
 | ||
| 			$this->columnEnd();
 | ||
| 			$this->rowEnd();
 | ||
| 		}
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function footNote() { /* {{{ */
 | ||
| 		$html = "<footer class=\"footer border-top\">\n";
 | ||
| 		$html .= '<div class="container">'."\n";
 | ||
| 
 | ||
| 		if ($this->params['printdisclaimer']){
 | ||
| 			$html .= "<div class=\"disclaimer\">".getMLText("disclaimer")."</div>";
 | ||
| 		}
 | ||
| 
 | ||
| 		if (isset($this->params['footnote']) && strlen((string)$this->params['footnote'])>0) {
 | ||
| 			$html .= "<div class=\"footNote\">".(string)$this->params['footnote']."</div>";
 | ||
| 		}
 | ||
| 		$html .= "</div>\n";
 | ||
| 		$html .= "</footer>\n";
 | ||
| 	
 | ||
| 		return $html;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function contentStart() { /* {{{ */
 | ||
| /*
 | ||
| 		echo "<div class=\"container-fluid\">\n";
 | ||
| 		echo "<div class=\"row\">\n";
 | ||
| 		echo "<nav class=\"_col-md-2 d-none d-md-block bg-light sidebar\">\n";
 | ||
| 		echo "<div class=\"sidebar-sticky\">\n";
 | ||
| 		echo "lsajdlf";
 | ||
| 		echo "</div>\n";
 | ||
| 		echo "</nav>\n";
 | ||
| 		echo "<main role=\"main\" class=\"_col-md-10 _ml-sm-auto pb-3 px-4\">\n";
 | ||
| */
 | ||
| 		echo "<main role=\"main\" class=\"container-fluid mt-3 pb-3\">\n";
 | ||
| 		echo " <div class=\"row-fluid\">\n";
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function contentEnd() { /* {{{ */
 | ||
| 		echo " </div>\n";
 | ||
| 		echo "</main>\n";
 | ||
| /*
 | ||
| 		echo "</div>\n";
 | ||
| 		echo "</div>\n";
 | ||
| */
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function globalBanner() { /* {{{ */
 | ||
| 		echo "<nav class=\"navbar navbar-expand-lg navbar-dark bg-dark fixed-top\">\n";
 | ||
| 		echo " <a class=\"navbar-brand\" href=\"".(!empty($this->extraheader['logolink']) ? $this->extraheader['logolink'] : $this->params['settings']->_httpRoot."out/out.ViewFolder.php")."\">".(!empty($this->extraheader['logo']) ? '<img id="navbar-logo" src="'.$this->extraheader['logo'].'"/>' : '<img id="navbar-logo" src="'.$this->params['settings']->_httpRoot.'views/bootstrap4/images/seeddms-logo.svg"/>')." <span class=\"d-none d-md-inline-block ml-4\">".(strlen($this->params['sitename'])>0 ? $this->params['sitename'] : "")."</span></a>\n";
 | ||
| 		echo "</nav>\n";
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function globalNavigation($folder=null) { /* {{{ */
 | ||
| 		$dms = $this->params['dms'];
 | ||
| 		$accessobject = $this->params['accessobject'];
 | ||
| 		echo "<nav class=\"navbar navbar-expand-lg navbar-dark bg-dark border-bottom fixed-top\">\n";
 | ||
| 		echo " <a class=\"navbar-brand\" href=\"".(!empty($this->extraheader['logolink']) ? $this->extraheader['logolink'] : $this->params['settings']->_httpRoot."out/out.ViewFolder.php")."\">".(!empty($this->extraheader['logo']) ? '<img id="navbar-logo" src="'.$this->extraheader['logo'].'">' : '<img id="navbar-logo" src="'.$this->params['settings']->_httpRoot.'views/bootstrap4/images/seeddms-logo.svg">')." <span class=\"d-none d-md-inline-block ml-4\">".(strlen($this->params['sitename'])>0 ? $this->params['sitename'] : "")."</span></a>\n";
 | ||
| 
 | ||
| 		if(isset($this->params['user']) && $this->params['user']) {
 | ||
| 			/* search form {{{ */
 | ||
| 			echo "     <form action=\"".$this->params['settings']->_httpRoot."out/out.Search.php\" class=\"form-inline ml-4 mr-auto\" autocomplete=\"off\">";
 | ||
| 			if ($folder!=null && is_object($folder) && !strcasecmp(get_class($folder), $dms->getClassname('folder'))) {
 | ||
| 				echo "      <input type=\"hidden\" name=\"folderid\" value=\"".$folder->getID()."\" />";
 | ||
| 			}
 | ||
| 			echo "      <input type=\"hidden\" name=\"navBar\" value=\"1\" />";
 | ||
| 			echo "      <input name=\"query\" class=\"form-control mr-sm-2 search-query\" ".($this->params['defaultsearchmethod'] == 'fulltext_' ? "id=\"searchfield\"" : "id=\"searchfield\"")." data-provide=\"typeahead\" type=\"search\" style=\"width: 150px;\" placeholder=\"".getMLText("search")."\" aria-label=\"".getMLText("search")."\"/>";
 | ||
| 			if($this->params['defaultsearchmethod'] == 'fulltext')
 | ||
| 				echo "      <input type=\"hidden\" name=\"fullsearch\" value=\"1\" />";
 | ||
| 			echo "</form>\n";
 | ||
| 			/* }}} End of search form */
 | ||
| 
 | ||
| 			echo " <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#navbarMain\" aria-controls=\"navbarMain\" aria-expanded=\"false\" aria-label=\"Toggle navigation\">\n";
 | ||
| 			echo "  <span class=\"navbar-toggler-icon\"></span>\n";
 | ||
| 			echo " </button>\n";
 | ||
| 
 | ||
| 			echo " <div class=\"collapse navbar-collapse\" id=\"navbarMain\">\n";
 | ||
| 			echo "  <ul class=\"navbar-nav\">\n";
 | ||
| 			$menuitems = array();
 | ||
| 			/* calendar {{{ */
 | ||
| 			if ($this->params['enablecalendar'] && $accessobject->check_view_access('Calendar')) $menuitems['calendar'] = array('link'=>$this->params['settings']->_httpRoot.'out/out.Calendar.php?mode='.$this->params['calendardefaultview'], 'label'=>getMLText("calendar"));
 | ||
| 			if ($this->params['user']->isAdmin()) $menuitems['admintools'] = array('link'=>$this->params['settings']->_httpRoot.'out/out.AdminTools.php', 'label'=>getMLText("admin_tools"));
 | ||
| 			if($this->params['enablehelp']) {
 | ||
| 				$tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME']));
 | ||
| 				$menuitems['help'] = array('link'=>$this->params['settings']->_httpRoot.'out/out.Help.php?context='.$tmp[1], 'label'=>getMLText("help"));
 | ||
| 			}
 | ||
| 			/* }}} End of calendar */
 | ||
| 
 | ||
| 			/* Check if hook exists because otherwise callHook() will override $menuitems */
 | ||
| 			if($this->hasHook('globalNavigationBar'))
 | ||
| 				$menuitems = $this->callHook('globalNavigationBar', $menuitems);
 | ||
| 			foreach($menuitems as $menuitem) {
 | ||
| 				if(!empty($menuitem['children'])) {
 | ||
| 					echo "   <li class=\"nav-item dropdown\">\n";
 | ||
| 					echo "     <a class=\"nav-link dropdown-toggle\" data-toggle=\"dropdown\">".$menuitem['label']."</a>\n";
 | ||
| 					echo "     <div class=\"dropdown-menu dropdown-menu-left\">\n";
 | ||
| 					foreach($menuitem['children'] as $submenuitem) {
 | ||
| 						echo "      <a class=\"dropdown-item\" href=\"".$submenuitem['link']."\"".(isset($submenuitem['target']) ? ' target="'.$submenuitem['target'].'"' : '').">".$submenuitem['label']."</a>\n";
 | ||
| 					}
 | ||
| 					echo "     </div>\n";
 | ||
| 				} else {
 | ||
| 					echo "<li class=\"nav-item\"><a class=\"nav-link\" href=\"".$menuitem['link']."\"".(isset($menuitem['target']) ? ' target="'.$menuitem['target'].'"' : '').">".$menuitem['label']."</a></li>";
 | ||
| 				}
 | ||
| 			}
 | ||
| 			echo "   </ul>\n";
 | ||
| 
 | ||
| 			/* menu tasks {{{ */
 | ||
| 			if($this->params['enablemenutasks'] && !$this->params['user']->isGuest()) {
 | ||
| 				if($accessobject->check_view_access('Tasks', array('action'=>'menuTasks'))) {
 | ||
| 					echo "   <div id=\"menu-tasks\" class=\"ml-auto\">";
 | ||
| 					echo "     <div class=\"ajax\" data-no-spinner=\"true\" data-view=\"Tasks\" data-action=\"menuTasks\"></div>";
 | ||
| 					echo "   </div>";
 | ||
| 				}
 | ||
| 			}
 | ||
| 			/* }}} End of menu tasks */
 | ||
| 
 | ||
| 			/* drop folder dir {{{ */
 | ||
| 			if($this->params['dropfolderdir'] && $this->params['enabledropfolderlist']) {
 | ||
| 				echo "   <div id=\"menu-dropfolder\">";
 | ||
| 				echo "     <div class=\"ajax\" data-no-spinner=\"true\" data-view=\"DropFolderChooser\" data-action=\"menuList\"";
 | ||
| 				$query = 'recursive=1';
 | ||
| 				if ($folder!=null && is_object($folder) && $folder->isType('folder'))
 | ||
| 					$query .= "&folderid=".$folder->getID();
 | ||
| 				echo " data-query=\"".$query."\"";
 | ||
| 				echo "></div>";
 | ||
| 				echo "   </div>";
 | ||
| 			}
 | ||
| 			/* }}} End of drop folder dir */
 | ||
| 
 | ||
| 			/* session list {{{ */
 | ||
| 			if($this->params['enablesessionlist']) {
 | ||
| 				echo "   <div id=\"menu-session\">";
 | ||
| 				echo "     <div class=\"ajax\" data-no-spinner=\"true\" data-view=\"Session\" data-action=\"menuSessions\"></div>";
 | ||
| 				echo "   </div>";
 | ||
| 			}
 | ||
| 			/* }}} End of session list */
 | ||
| 
 | ||
| 			/* clipboard {{{ */
 | ||
| 			if($this->params['enableclipboard']) {
 | ||
| 				echo "   <div id=\"menu-clipboard\">";
 | ||
| 				echo "     <div class=\"ajax add-clipboard-area\" data-no-spinner=\"true\" data-view=\"Clipboard\" data-action=\"menuClipboard\" data-query=\"folderid=".($folder != null ? $folder->getID() : 0)."\"></div>";
 | ||
| 				echo "   </div>";
 | ||
| 			}
 | ||
| 			/* }}} End of clipboard */
 | ||
| 
 | ||
| 			/* user profile menu {{{ */
 | ||
| 			echo "  <ul class=\"navbar-nav ml-auto\">\n";
 | ||
| 			echo "   <li class=\"nav-item dropdown\">\n";
 | ||
| 			echo "    <a href=\"#\" class=\"nav-link dropdown-toggle\" data-toggle=\"dropdown\" id=\"navbarMainUser\" aria-haspopup=\"true\" aria-expanded=\"false\">".($this->params['session']->getSu() ? getMLText("switched_to") : getMLText("signed_in_as"))." '".htmlspecialchars($this->params['user']->getFullName())."'</a>\n";
 | ||
| 			echo "    <div class=\"dropdown-menu dropdown-menu-right\" aria-labelledby=\"navbarMainUser\">\n";
 | ||
| 			if (!$this->params['user']->isGuest()) {
 | ||
| 				$menuitems = array();
 | ||
| 				if ($accessobject->check_view_access('Dashboard'))
 | ||
| 					$menuitems['dashboard'] = array('link'=>$this->params['settings']->_httpRoot."out/out.Dashboard.php", 'label'=>getMLText('dashboard'));
 | ||
| 				if ($accessobject->check_view_access('MyDocuments'))
 | ||
| 					$menuitems['my_documents'] = array('link'=>$this->params['settings']->_httpRoot."out/out.MyDocuments.php?inProcess=1", 'label'=>getMLText('my_documents'));
 | ||
| 				if ($accessobject->check_view_access('MyAccount'))
 | ||
| 					$menuitems['my_account'] = array('link'=>$this->params['settings']->_httpRoot."out/out.MyAccount.php", 'label'=>getMLText('my_account'));
 | ||
| 				if($this->hasHook('userMenuItems'))
 | ||
| 					$menuitems = $this->callHook('userMenuItems', $menuitems);
 | ||
| 				if($menuitems) {
 | ||
| 					foreach($menuitems as $menuitem) {
 | ||
| 						echo "     <a class=\"dropdown-item\" href=\"".$menuitem['link']."\">".$menuitem['label']."</a>\n";
 | ||
| 					}
 | ||
| 					echo "     <div class=\"dropdown-divider\"></div>\n";
 | ||
| 				}
 | ||
| 			}
 | ||
| 			$showdivider = false;
 | ||
| 			if($this->params['enablelanguageselector']) {
 | ||
| 				$showdivider = true;
 | ||
| 				echo "     <div class=\"dropdown-submenu\">\n";
 | ||
| 				echo "      <a href=\"#\" class=\"dropdown-item dropdown-toggle\" data-toggle=\"dropdown\">".getMLText("language")."</a>\n";
 | ||
| 				echo "      <div class=\"dropdown-menu dropdown-submenu-left\">\n";
 | ||
| 				$languages = getLanguages();
 | ||
| 				foreach ($languages as $currLang) {
 | ||
| 					if($this->params['session']->getLanguage() == $currLang)
 | ||
| 						echo "      <a class=\"dropdown-item active\"";
 | ||
| 					else
 | ||
| 						echo "      <a class=\"dropdown-item\"";
 | ||
| 					echo " href=\"".$this->params['settings']->_httpRoot."op/op.SetLanguage.php?lang=".$currLang."&referer=".$_SERVER["REQUEST_URI"]."\">";
 | ||
| 					echo getMLText($currLang)."</a>\n";
 | ||
| 				}
 | ||
| 				echo "     </div>\n";
 | ||
| 				echo "    </div>\n";
 | ||
| 			}
 | ||
| 			if(!$this->params['session']->getSu()) {
 | ||
| 				if($this->params['user']->isAdmin()) {
 | ||
| 					$showdivider = true;
 | ||
| 					echo "    <a class=\"dropdown-item\" href=\"".$this->params['settings']->_httpRoot."out/out.SubstituteUser.php\">".getMLText("substitute_user")."</a>\n";
 | ||
| 				}
 | ||
| 			}
 | ||
| 			if($showdivider)
 | ||
| 				echo "    <div class=\"dropdown-divider\"></div>\n";
 | ||
| 			if($this->params['session']->getSu()) {
 | ||
| 				echo "    <a class=\"dropdown-item\" href=\"".$this->params['settings']->_httpRoot."op/op.ResetSu.php\">".getMLText("sign_out_user")."</a>\n";
 | ||
| 			} else {
 | ||
| 				echo "    <a class=\"dropdown-item\" href=\"".$this->params['settings']->_httpRoot."op/op.Logout.php\">".getMLText("sign_out")."</a>\n";
 | ||
| 			}
 | ||
| 			echo "     </div>\n";
 | ||
| 			echo "    </li>\n";
 | ||
| 			echo "   </ul>\n";
 | ||
| 			/* }}} End of user profile menu */
 | ||
| 
 | ||
| 			echo "    </div>\n";
 | ||
| 		}
 | ||
| //		echo "  </div>\n";
 | ||
| //		echo " </div>\n";
 | ||
| 		echo "</nav>\n";
 | ||
| 		return;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function getFolderPathHTML($folder, $tagAll=false, $document=null) { /* {{{ */
 | ||
| 		$path = $folder->getPath();
 | ||
| 		$txtpath = "";
 | ||
| 		for ($i = 0; $i < count($path); $i++) {
 | ||
| 			$txtpath .= "<li class=\"breadcrumb-item\">";
 | ||
| 			if ($i+1 < count($path)) {
 | ||
| 				$txtpath .= "<a href=\"".$this->params['settings']->_httpRoot."out/out.ViewFolder.php?folderid=".$path[$i]->getID()."&showtree=".showtree()."\" data-droptarget=\"folder_".$path[$i]->getID()."\" rel=\"folder_".$path[$i]->getID()."\" data-name=\"".htmlspecialchars($path[$i]->getName())."\" class=\"table-row-folder droptarget\" data-uploadformtoken=\"".createFormKey('')."\" formtoken=\"".createFormKey('')."\">".
 | ||
| 					htmlspecialchars($path[$i]->getName())."</a>";
 | ||
| 			}
 | ||
| 			else {
 | ||
| 				$txtpath .= ($tagAll ? "<a href=\"".$this->params['settings']->_httpRoot."out/out.ViewFolder.php?folderid=".$path[$i]->getID()."&showtree=".showtree()."\" data-droptarget=\"folder_".$path[$i]->getID()."\" rel=\"folder_".$path[$i]->getID()."\" data-name=\"".htmlspecialchars($path[$i]->getName())."\" class=\"table-row-folder droptarget\" data-uploadformtoken=\"".createFormKey('')."\" formtoken=\"".createFormKey('')."\">".htmlspecialchars($path[$i]->getName())."</a>" : htmlspecialchars($path[$i]->getName()));
 | ||
| 			}
 | ||
| 		}
 | ||
| 		if($document)
 | ||
| 			$txtpath .= "<li class=\"breadcrumb-item active table-row-document\" aria-current=\"page\"><a href=\"".$this->params['settings']->_httpRoot."out/out.ViewDocument.php?documentid=".$document->getId()."\" class=\"table-document-row\" rel=\"document_".$document->getId()."\" data-name=\"".htmlspecialchars($document->getName())."\" formtoken=\"".createFormKey('')."\">".htmlspecialchars($document->getName())."</a></li>";
 | ||
| 
 | ||
| 		return '<nav aria-label="breadcrumb"><ol class="breadcrumb">'.$txtpath.'</ol></nav>';
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function pageNavigation($pageTitle, $pageType=null, $extra=null) { /* {{{ */
 | ||
| 
 | ||
| 		if ($pageType!=null && strcasecmp($pageType, "noNav")) {
 | ||
| //			echo "<div class=\"fixed-top\" style=\"z-index: 1029; margin-top: 51px;\">";
 | ||
| 			echo "<nav class=\"navbar navbar-expand-lg mb-4 bg-light navbar-light\">\n";
 | ||
| 			echo '<a class="navbar-brand">'.getMLText('nav_brand_'.$pageType).'</a>';
 | ||
| 			echo "<button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#navbarPageContent\" aria-controls=\"navbarMain\" aria-expanded=\"false\" aria-label=\"Toggle navigation\">\n";
 | ||
| 			echo " <span class=\"navbar-toggler-icon\"></span>\n";
 | ||
| 			echo "</button>\n";
 | ||
| 			echo "<div class=\"collapse navbar-collapse\" id=\"navbarPageContent\">\n";
 | ||
| 			switch ($pageType) {
 | ||
| 				case "view_folder":
 | ||
| 					$this->folderNavigationBar($extra);
 | ||
| 					break;
 | ||
| 				case "view_document":
 | ||
| 					$this->documentNavigationBar($extra);
 | ||
| 					break;
 | ||
| 				case "my_documents":
 | ||
| 					$this->myDocumentsNavigationBar();
 | ||
| 					break;
 | ||
| 				case "my_account":
 | ||
| 					$this->accountNavigationBar();
 | ||
| 					break;
 | ||
| 				case "admin_tools":
 | ||
| 					$this->adminToolsNavigationBar();
 | ||
| 					break;
 | ||
| 				case "calendarold";
 | ||
| 					$this->calendarOldNavigationBar($extra);
 | ||
| 					break;
 | ||
| 				case "calendar";
 | ||
| 					$this->calendarNavigationBar($extra);
 | ||
| 					break;
 | ||
| 				default:
 | ||
| 					if($this->hasHook('pageNavigationBar')) {
 | ||
| 						$menubar = $this->callHook('pageNavigationBar', $pageType, $extra);
 | ||
| 						if(is_string($menubar))
 | ||
| 							echo $menubar;
 | ||
| 					}
 | ||
| 			}
 | ||
| 			echo " 	</div>\n";
 | ||
| 			echo "</nav>\n";
 | ||
| 			if($pageType == "view_folder" || $pageType == "view_document")
 | ||
| 				echo $pageTitle."\n";
 | ||
| //			echo "</div>";
 | ||
| 		} else {
 | ||
| 			echo "<legend>".$pageTitle."</legend>\n";
 | ||
| 		}
 | ||
| 
 | ||
| 		return;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	protected function showNavigationBar($menuitems, $options=array()) { /* {{{ */
 | ||
| 		$content = '';
 | ||
| 		$content .= "<ul".(isset($options['id']) ? ' id="'.$options['id'].'"' : '')." class=\"navbar-nav".(isset($options['right']) ? ' ml-auto' : '')."\">\n";
 | ||
| 		foreach($menuitems as $menuitem) {
 | ||
| 			if(!empty($menuitem['children'])) {
 | ||
| 				$content .= "    <li class=\"nav-item dropdown\">\n";
 | ||
| 				$content .= "     <a href=\"#\" class=\"nav-link dropdown-toggle\" data-toggle=\"dropdown\">".$menuitem['label']."</a>\n";
 | ||
| 				$content .= "     <div class=\"dropdown-menu\">\n";
 | ||
| 				foreach($menuitem['children'] as $submenuitem) {
 | ||
| 					if(!empty($submenuitem['children'])) {
 | ||
| 						$content .= "      <div class=\"dropdown-submenu\">\n";
 | ||
| 						$content .=	"       <a href=\"#\" class=\"dropdown-item dropdown-toggle\" data-toggle=\"dropdown\">".$submenuitem['label']."</a>\n";
 | ||
| 						$content .= "       <div class=\"dropdown-menu dropdown-submenu-left\">\n";
 | ||
| 						foreach($submenuitem['children'] as $subsubmenuitem) {
 | ||
| 							if(!empty($submenuitem['divider'])) {
 | ||
| 								$content .= "      <div class=\"dropdown-divider\"></div>\n";
 | ||
| 							} else {
 | ||
| 								$content .= "      <a href=\"".$subsubmenuitem['link']."\" class=\"dropdown-item".(isset($subsubmenuitem['class']) ? " ".$subsubmenuitem['class'] : "")."\"".(isset($subsubmenuitem['rel']) ? " rel=\"".$subsubmenuitem['rel']."\"" : "");
 | ||
| 								if(!empty($subsubmenuitem['attributes']))
 | ||
| 									foreach($subsubmenuitem['attributes'] as $attr)
 | ||
| 										$content .= ' '.$attr[0].'="'.$attr[1].'"';
 | ||
| 								$content .= ">".$subsubmenuitem['label']."</a>";
 | ||
| 							}
 | ||
| 						}
 | ||
| 						$content .= "       </div>\n";
 | ||
| 						$content .= "      </div>\n";
 | ||
| 					} else {
 | ||
| 						if(!empty($submenuitem['divider'])) {
 | ||
| 							$content .= "      <div class=\"dropdown-divider\"></div>\n";
 | ||
| 						} else {
 | ||
| 							$content .= "      <a class=\"dropdown-item".(isset($submenuitem['class']) ? " ".$submenuitem['class'] : "")."\"".(isset($submenuitem['link']) ? " href=\"".$submenuitem['link']."\"" : "").(isset($submenuitem['target']) ? ' target="'.$submenuitem['target'].'"' : '');
 | ||
| 							if(!empty($submenuitem['attributes']))
 | ||
| 								foreach($submenuitem['attributes'] as $attr)
 | ||
| 									$content .= ' '.$attr[0].'="'.$attr[1].'"';
 | ||
| 							$content .= ">".$submenuitem['label']."</a>\n";
 | ||
| 						}
 | ||
| 					}
 | ||
| 				}
 | ||
| 				$content .= "     </div>\n";
 | ||
| 			} else {
 | ||
| 				if(!empty($menuitem['divider'])) {
 | ||
| 					$content .= "      <div class=\"dropdown-divider\"></div>\n";
 | ||
| 				} else {
 | ||
| 					$content .= "    <li class=\"nav-item\">\n";
 | ||
| 					$content .= "<a class=\"nav-link".(isset($menuitem['class']) ? " ".$menuitem['class'] : "")."\"".(isset($menuitem['link']) ? " href=\"".$menuitem['link']."\"" : "").(isset($menuitem['target']) ? ' target="'.$menuitem['target'].'"' : '');
 | ||
| 					if(!empty($menuitem['attributes']))
 | ||
| 						foreach($menuitem['attributes'] as $attr)
 | ||
| 							$content .= ' '.$attr[0].'="'.$attr[1].'"';
 | ||
| 					$content .= ">".$menuitem['label']."</a>";
 | ||
| 					$content .= "</li>";
 | ||
| 				}
 | ||
| 			}
 | ||
| 		}
 | ||
| 		$content .= "</ul>\n";
 | ||
| 		echo $content;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	protected function showNavigationListWithBadges($menuitems, $options=array()) { /* {{{ */
 | ||
| 		$content = '';
 | ||
| 		$content .= "<ul".(isset($options['id']) ? ' id="'.$options['id'].'"' : '')." class=\"list-group sidenav\">\n";
 | ||
| 		foreach($menuitems as $menuitem) {
 | ||
| 			$content .= "  <li class=\"list-group-item d-flex justify-content-between align-items-center".(!empty($menuitem['active']) ? ' active' : '')."\">\n";
 | ||
| 			$content .= '    <a';
 | ||
| 			$content .= !empty($menuitem['link']) ? ' href="'.$menuitem['link'].'"' : '';
 | ||
| 			if(!empty($menuitem['attributes']))
 | ||
| 				foreach($menuitem['attributes'] as $attr)
 | ||
| 					$content .= ' '.$attr[0].'="'.$attr[1].'"';
 | ||
| 			$content .= '>';
 | ||
| 			$content .= $menuitem['label'];
 | ||
| 			$content .= '    </a>'."\n";
 | ||
| 			if(!empty($menuitem['badge']))
 | ||
| 				$content .= '<span class="badge badge-primary badge-pill">'.$menuitem['badge']."</span>";
 | ||
| 			$content .= "  </li>\n";
 | ||
| 		}
 | ||
| 
 | ||
| 		$content .= "</ul>\n";
 | ||
| 		echo $content;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	protected function showButtonwithMenu($button, $options=array()) { /* {{{ */
 | ||
| 		$content = '';
 | ||
| 		$content .= '
 | ||
| <div class="btn-group" role="group">
 | ||
| 	<div class="btn-group" role="group">
 | ||
| 		<button type="button" class="btn btn-secondary dropdown-toggle" data-toggle="dropdown" href="#">
 | ||
| 		'.$button['label'].'
 | ||
| 		</button>
 | ||
| ';
 | ||
| 		if($button['menuitems']) {
 | ||
| 			$content .= '
 | ||
| 	<div class="dropdown-menu">
 | ||
| ';
 | ||
| 			foreach($button['menuitems'] as $menuitem) {
 | ||
| 				$content .= '
 | ||
| 		<a class="dropdown-item" href="'.$menuitem['link'].'">'.$menuitem['label'].'</a>
 | ||
| ';
 | ||
| 			}
 | ||
| 			$content .= '
 | ||
| 	</div>
 | ||
| ';
 | ||
| 		}
 | ||
| 		$content .= '
 | ||
| </div>
 | ||
| ';
 | ||
| 		echo $content;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	protected function showPaneHeader($name, $title, $isactive) { /* {{{ */
 | ||
| 		echo '<li class="nav-item '.($isactive ? 'active' : '').'"><a class="nav-link '.($isactive ? 'active' : '').'" data-target="#'.$name.'" data-toggle="tab" role="button">'.$title.'</a></li>'."\n";
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	protected function showStartPaneContent($name, $isactive) { /* {{{ */
 | ||
| 		echo '<div class="tab-pane'.($isactive ? ' active' : '').'" id="'.$name.'" role="tabpanel">';
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	protected function showEndPaneContent($name, $currentab) { /* {{{ */
 | ||
| 		echo '</div>';
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	private function folderNavigationBar($folder) { /* {{{ */
 | ||
| 		$dms = $this->params['dms'];
 | ||
| 		$enableClipboard = $this->params['enableclipboard'];
 | ||
| 		$accessobject = $this->params['accessobject'];
 | ||
| 		if (!is_object($folder) || !$folder->isType('folder')) {
 | ||
| 			self::showNavigationBar(array());
 | ||
| 			return;
 | ||
| 		}
 | ||
| 		$accessMode = $folder->getAccessMode($this->params['user']);
 | ||
| 		$folderID = $folder->getID();
 | ||
| 		$menuitems = array();
 | ||
| 
 | ||
| 		if ($accessMode == M_READ && !$this->params['user']->isGuest()) {
 | ||
| 			if ($accessobject->check_view_access('FolderNotify'))
 | ||
| 				$menuitems['edit_folder_notify'] = array('link'=>$this->params['settings']->_httpRoot."out/out.FolderNotify.php?folderid=".$folderID."&showtree=".showtree(), 'label'=>getMLText('edit_folder_notify'));
 | ||
| 		}
 | ||
| 		else if ($accessMode >= M_READWRITE) {
 | ||
| 			if ($accessobject->check_view_access('AddSubFolder'))
 | ||
| 				$menuitems['add_subfolder'] = array('link'=>$this->params['settings']->_httpRoot."out/out.AddSubFolder.php?folderid=". $folderID ."&showtree=".showtree(), 'label'=>getMLText('add_subfolder'));
 | ||
| 			if ($accessobject->check_view_access('AddDocument'))
 | ||
| 				$menuitems['add_document'] = array('link'=>$this->params['settings']->_httpRoot."out/out.AddDocument.php?folderid=". $folderID ."&showtree=".showtree(), 'label'=>getMLText('add_document'));
 | ||
| 			if(0 && $this->params['enablelargefileupload'])
 | ||
| 				$menuitems['add_multiple_documents'] = array('link'=>$this->params['settings']->_httpRoot."out/out.AddMultiDocument.php?folderid=". $folderID ."&showtree=".showtree(), 'label'=>getMLText('add_multiple_documents'));
 | ||
| 			$menuitems['edit_folder_props'] = array('link'=>$this->params['settings']->_httpRoot."out/out.EditFolder.php?folderid=". $folderID ."&showtree=".showtree(), 'label'=>getMLText('edit_folder_props'));
 | ||
| 			if ($folderID != $this->params['rootfolderid'] && $folder->getParent())
 | ||
| 				$menuitems['move_folder'] = array('link'=>$this->params['settings']->_httpRoot."out/out.MoveFolder.php?folderid=". $folderID ."&showtree=".showtree(), 'label'=>getMLText('move_folder'));
 | ||
| 
 | ||
| 			if ($accessMode == M_ALL) {
 | ||
| 				if ($folderID != $this->params['rootfolderid'] && $folder->getParent())
 | ||
| 					if ($accessobject->check_view_access('RemoveFolder'))
 | ||
| 						$menuitems['rm_folder'] = array('link'=>$this->params['settings']->_httpRoot."out/out.RemoveFolder.php?folderid=". $folderID ."&showtree=".showtree(), 'label'=>getMLText('rm_folder'));
 | ||
| 			}
 | ||
| 			if ($accessMode == M_ALL) {
 | ||
| 				if ($accessobject->check_view_access('FolderAccess'))
 | ||
| 					$menuitems['edit_folder_access'] = array('link'=>$this->params['settings']->_httpRoot."out/out.FolderAccess.php?folderid=".$folderID."&showtree=".showtree(), 'label'=>getMLText('edit_folder_access'));
 | ||
| 			}
 | ||
| 			if ($accessobject->check_view_access('FolderNotify'))
 | ||
| 				$menuitems['edit_folder_notify'] = array('link'=>$this->params['settings']->_httpRoot."out/out.FolderNotify.php?folderid=". $folderID ."&showtree=". showtree(), 'label'=>getMLText('edit_folder_notify'));
 | ||
| 		}
 | ||
| 		if($enableClipboard) {
 | ||
| 			$menuitems['add_to_clipboard'] = array('class'=>'addtoclipboard', 'attributes'=>array(['rel', 'F'.$folder->getId()], ['msg', getMLText('splash_added_to_clipboard')], ['title', getMLText("add_to_clipboard")]), 'label'=>getMLText("add_to_clipboard"));
 | ||
| 		}
 | ||
| 		if ($this->params['user']->isAdmin() && $this->params['enablefullsearch']) {
 | ||
| 			$menuitems['index_folder'] = array('link'=>$this->params['settings']->_httpRoot."out/out.Indexer.php?folderid=". $folderID."&showtree=".showtree(), 'label'=>getMLText('index_folder'));
 | ||
| 		}
 | ||
| 
 | ||
| 		/* Do not use $this->callHook() because $menuitems must be returned by the the
 | ||
| 		 * first hook and passed to next hook. $this->callHook() will just pass
 | ||
| 		 * the menuitems to each single hook. Hence, the last hook will win.
 | ||
| 		 */
 | ||
| 		$hookObjs = $this->getHookObjects();
 | ||
| 		foreach($hookObjs as $hookObj) {
 | ||
| 			if (method_exists($hookObj, 'folderNavigationBar')) {
 | ||
| 	      $menuitems = $hookObj->folderNavigationBar($this, $folder, $menuitems);
 | ||
| 			}
 | ||
| 		}
 | ||
| 
 | ||
| 		self::showNavigationBar($menuitems);
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	private function documentNavigationBar($document)	{ /* {{{ */
 | ||
| 		$accessobject = $this->params['accessobject'];
 | ||
| 		$enableClipboard = $this->params['enableclipboard'];
 | ||
| 		$accessMode = $document->getAccessMode($this->params['user']);
 | ||
| 		$docid=".php?documentid=" . $document->getID();
 | ||
| 		$menuitems = array();
 | ||
| 
 | ||
| 		if ($accessMode >= M_READWRITE) {
 | ||
| 			if (!$document->isLocked()) {
 | ||
| 				if($accessobject->check_controller_access('UpdateDocument'))
 | ||
| 					$menuitems['update_document'] = array('link'=>$this->params['settings']->_httpRoot."out/out.UpdateDocument".$docid, 'label'=>getMLText('update_document'));
 | ||
| 				if($accessobject->check_controller_access('LockDocument'))
 | ||
| 					$menuitems['lock_document'] = array('link'=>$this->params['settings']->_httpRoot."op/op.LockDocument".$docid."&formtoken=".createFormKey('lockdocument'), 'label'=>getMLText('lock_document'));
 | ||
| 				if($accessobject->check_controller_access('EditDocument'))
 | ||
| 					$menuitems['edit_document_props'] = array('link'=>$this->params['settings']->_httpRoot."out/out.EditDocument".$docid , 'label'=>getMLText('edit_document_props'));
 | ||
| 				$menuitems['move_document'] = array('link'=>$this->params['settings']->_httpRoot."out/out.MoveDocument".$docid, 'label'=>getMLText('move_document'));
 | ||
| 			}
 | ||
| 			else {
 | ||
| 				$lockingUser = $document->getLockingUser();
 | ||
| 				if (($lockingUser->getID() == $this->params['user']->getID()) || ($document->getAccessMode($this->params['user']) == M_ALL)) {
 | ||
| 					if($accessobject->check_controller_access('UpdateDocument'))
 | ||
| 						$menuitems['update_document'] = array('link'=>$this->params['settings']->_httpRoot."out/out.UpdateDocument".$docid, 'label'=>getMLText('update_document'));
 | ||
| 					if($accessobject->check_controller_access('UnlockDocument'))
 | ||
| 						$menuitems['unlock_document'] = array('link'=>$this->params['settings']->_httpRoot."op/op.UnlockDocument".$docid."&formtoken=".createFormKey('unlockdocument'), 'label'=>getMLText('unlock_document'));
 | ||
| 					if($accessobject->check_controller_access('EditDocument'))
 | ||
| 						$menuitems['edit_document_props'] = array('link'=>$this->params['settings']->_httpRoot."out/out.EditDocument".$docid, 'label'=>getMLText('edit_document_props'));
 | ||
| 					$menuitems['move_document'] = array('link'=>$this->params['settings']->_httpRoot."out/out.MoveDocument".$docid, 'label'=>getMLText('move_document'));
 | ||
| 				}
 | ||
| 			}
 | ||
| 			if($accessobject->maySetExpires()) {
 | ||
| 				if ($accessobject->check_view_access('SetExpires'))
 | ||
| 					$menuitems['expires'] = array('link'=>$this->params['settings']->_httpRoot."out/out.SetExpires".$docid, 'label'=>getMLText('expires'));
 | ||
| 			}
 | ||
| 		}
 | ||
| 		if ($document->getAccessMode($this->params['user'], 'removeDocument') == M_ALL) {
 | ||
| 			if ($accessobject->check_view_access('RemoveDocument'))
 | ||
| 				$menuitems['rm_document'] = array('link'=>$this->params['settings']->_httpRoot."out/out.RemoveDocument".$docid, 'label'=>getMLText('rm_document'));
 | ||
| 		}
 | ||
| 		if($accessMode == M_ALL) {
 | ||
| 			if ($accessobject->check_view_access('DocumentAccess'))
 | ||
| 				$menuitems['edit_document_access'] = array('link'=>$this->params['settings']->_httpRoot."out/out.DocumentAccess". $docid, 'label'=>getMLText('edit_document_access'));
 | ||
| 		}
 | ||
| 		if ($accessMode >= M_READ && !$this->params['user']->isGuest()) {
 | ||
| 			if ($accessobject->check_view_access('DocumentNotify'))
 | ||
| 				$menuitems['edit_document_notify'] = array('link'=>$this->params['settings']->_httpRoot."out/out.DocumentNotify". $docid, 'label'=>getMLText('edit_document_notify'));
 | ||
| 		}
 | ||
| 		if($enableClipboard) {
 | ||
| 			$menuitems['add_to_clipboard'] = array('class'=>'addtoclipboard', 'attributes'=>array(['rel', 'D'.$document->getId()], ['msg', getMLText('splash_added_to_clipboard')], ['title', getMLText("add_to_clipboard")]), 'label'=>getMLText("add_to_clipboard"));
 | ||
| 		}
 | ||
| 		if ($accessobject->check_view_access('TransferDocument')) {
 | ||
| 			$menuitems['transfer_document'] = array('link'=>$this->params['settings']->_httpRoot."out/out.TransferDocument". $docid, 'label'=>getMLText('transfer_document'));
 | ||
| 		}
 | ||
| 
 | ||
| 		/* Do not use $this->callHook() because $menuitems must be returned by the the
 | ||
| 		 * first hook and passed to next hook. $this->callHook() will just pass
 | ||
| 		 * the menuitems to each single hook. Hence, the last hook will win.
 | ||
| 		 */
 | ||
| 		$hookObjs = $this->getHookObjects();
 | ||
| 		foreach($hookObjs as $hookObj) {
 | ||
| 			if (method_exists($hookObj, 'documentNavigationBar')) {
 | ||
| 	      $menuitems = $hookObj->documentNavigationBar($this, $document, $menuitems);
 | ||
| 			}
 | ||
| 		}
 | ||
| 
 | ||
| 		self::showNavigationBar($menuitems);
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	private function accountNavigationBar() { /* {{{ */
 | ||
| 		$accessobject = $this->params['accessobject'];
 | ||
| 
 | ||
| 		$menuitems = array();
 | ||
| 		if ($this->params['user']->isAdmin() || !$this->params['disableselfedit'])
 | ||
| 			$menuitems['edit_user_details'] = array('link'=>$this->params['settings']->_httpRoot."out/out.EditUserData.php", 'label'=>getMLText('edit_user_details'));
 | ||
| 		
 | ||
| 		if (!$this->params['user']->isAdmin()) 
 | ||
| 			$menuitems['edit_default_keywords'] = array('link'=>$this->params['settings']->_httpRoot."out/out.UserDefaultKeywords.php", 'label'=>getMLText('edit_default_keywords'));
 | ||
| 
 | ||
| 		if ($accessobject->check_view_access('ManageNotify'))
 | ||
| 			$menuitems['edit_notify'] = array('link'=>$this->params['settings']->_httpRoot."out/out.ManageNotify.php", 'label'=>getMLText('edit_existing_notify'));
 | ||
| 
 | ||
| 		if ($this->params['enableusersview']){
 | ||
| 			if ($accessobject->check_view_access('UsrView'))
 | ||
| 				$menuitems['users'] = array('link'=>$this->params['settings']->_httpRoot."out/out.UsrView.php", 'label'=>getMLText('users'));
 | ||
| 			if ($accessobject->check_view_access('GroupView'))
 | ||
| 				$menuitems['groups'] = array('link'=>$this->params['settings']->_httpRoot."out/out.GroupView.php", 'label'=>getMLText('groups'));
 | ||
| 		}		
 | ||
| 
 | ||
| 		/* Do not use $this->callHook() because $menuitems must be returned by the the
 | ||
| 		 * first hook and passed to next hook. $this->callHook() will just pass
 | ||
| 		 * the menuitems to each single hook. Hence, the last hook will win.
 | ||
| 		 */
 | ||
| 		$hookObjs = $this->getHookObjects();
 | ||
| 		foreach($hookObjs as $hookObj) {
 | ||
| 			if (method_exists($hookObj, 'accountNavigationBar')) {
 | ||
| 	      $menuitems = $hookObj->accountNavigationBar($this, $menuitems);
 | ||
| 			}
 | ||
| 		}
 | ||
| 
 | ||
| 		self::showNavigationBar($menuitems);
 | ||
| 
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	private function myDocumentsNavigationBar() { /* {{{ */
 | ||
| 		$accessobject = $this->params['accessobject'];
 | ||
| 
 | ||
| 		$menuitems = array();
 | ||
| 		if ($accessobject->check_view_access('MyDocuments')) {
 | ||
| 			$menuitems['inprocess'] = array('link'=>$this->params['settings']->_httpRoot."out/out.MyDocuments.php?inProcess=1", 'label'=>getMLText('documents_in_process'));
 | ||
| 			$menuitems['all_documents'] = array('link'=>$this->params['settings']->_httpRoot."out/out.MyDocuments.php", 'label'=>getMLText('all_documents'));
 | ||
| 		}
 | ||
| 		if($this->params['workflowmode'] == 'traditional' || $this->params['workflowmode'] == 'traditional_only_approval') {
 | ||
| 			if ($accessobject->check_view_access('ReviewSummary'))
 | ||
| 				$menuitems['review_summary'] = array('link'=>$this->params['settings']->_httpRoot."out/out.ReviewSummary.php", 'label'=>getMLText('review_summary'));
 | ||
| 			if ($accessobject->check_view_access('ApprovalSummary'))
 | ||
| 				$menuitems['approval_summary'] = array('link'=>$this->params['settings']->_httpRoot."out/out.ApprovalSummary.php", 'label'=>getMLText('approval_summary'));
 | ||
| 		} else {
 | ||
| 			if ($accessobject->check_view_access('WorkflowSummary'))
 | ||
| 				$menuitems['workflow_summary'] = array('link'=>$this->params['settings']->_httpRoot."out/out.WorkflowSummary.php", 'label'=>getMLText('workflow_summary'));
 | ||
| 		}
 | ||
| 
 | ||
| 		/* Do not use $this->callHook() because $menuitems must be returned by the the
 | ||
| 		 * first hook and passed to next hook. $this->callHook() will just pass
 | ||
| 		 * the menuitems to each single hook. Hence, the last hook will win.
 | ||
| 		 */
 | ||
| 		$hookObjs = $this->getHookObjects();
 | ||
| 		foreach($hookObjs as $hookObj) {
 | ||
| 			if (method_exists($hookObj, 'mydocumentsNavigationBar')) {
 | ||
| 	      $menuitems = $hookObj->mydocumentsNavigationBar($this, $menuitems);
 | ||
| 			}
 | ||
| 		}
 | ||
| 
 | ||
| 		self::showNavigationBar($menuitems);
 | ||
| 
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	private function adminToolsNavigationBar() { /* {{{ */
 | ||
| 		$accessobject = $this->params['accessobject'];
 | ||
| 		$settings = $this->params['settings'];
 | ||
| 
 | ||
| 		$menuitems = array();
 | ||
| 		if($accessobject->check_view_access(array('UsrMgr', 'GroupMgr', 'UserList'))) {
 | ||
| 			$menuitems['user_group_management'] = array('link'=>"#", 'label'=>getMLText('user_group_management'));
 | ||
| 			if ($accessobject->check_view_access('UsrMgr'))
 | ||
| 				$menuitems['user_group_management']['children']['user_management'] = array('link'=>$this->params['settings']->_httpRoot."out/out.UsrMgr.php", 'label'=>getMLText('user_management'));
 | ||
| 			if ($accessobject->check_view_access('GroupMgr'))
 | ||
| 				$menuitems['user_group_management']['children']['group_management'] = array('link'=>$this->params['settings']->_httpRoot."out/out.GroupMgr.php", 'label'=>getMLText('group_management'));
 | ||
| 			if ($accessobject->check_view_access('UserList'))
 | ||
| 				$menuitems['user_group_management']['children']['user_list'] = array('link'=>$this->params['settings']->_httpRoot."out/out.UserList.php", 'label'=>getMLText('user_list'));
 | ||
| 			}
 | ||
| 
 | ||
| 			if($accessobject->check_view_access(array('DefaultKeywords', 'Categories', 'AttributeMgr', 'WorkflowMgr', 'WorkflowStatesMgr', 'WorkflowActionsMgr'))) {
 | ||
| 				$menuitems['definitions'] = array('link'=>"#", 'label'=>getMLText('definitions'));
 | ||
| 			if ($accessobject->check_view_access('DefaultKeywords'))
 | ||
| 				$menuitems['definitions']['children']['default_keywords'] = array('link'=>$this->params['settings']->_httpRoot."out/out.DefaultKeywords.php", 'label'=>getMLText('global_default_keywords'));
 | ||
| 			if ($accessobject->check_view_access('Categories'))
 | ||
| 				$menuitems['definitions']['children']['document_categories'] = array('link'=>$this->params['settings']->_httpRoot."out/out.Categories.php", 'label'=>getMLText('global_document_categories'));
 | ||
| 			if ($accessobject->check_view_access('AttributeMgr'))
 | ||
| 				$menuitems['definitions']['children']['attribute_definitions'] = array('link'=>$this->params['settings']->_httpRoot."out/out.AttributeMgr.php", 'label'=>getMLText('global_attributedefinitions'));
 | ||
| 			if($this->params['workflowmode'] == 'advanced') {
 | ||
| 				if ($accessobject->check_view_access('WorkflowMgr'))
 | ||
| 					$menuitems['definitions']['children']['workflows'] = array('link'=>$this->params['settings']->_httpRoot."out/out.WorkflowMgr.php", 'label'=>getMLText('global_workflows'));
 | ||
| 				if ($accessobject->check_view_access('WorkflowStatesMgr'))
 | ||
| 					$menuitems['definitions']['children']['workflow_states'] = array('link'=>$this->params['settings']->_httpRoot."out/out.WorkflowStatesMgr.php", 'label'=>getMLText('global_workflow_states'));
 | ||
| 				if ($accessobject->check_view_access('WorkflowActionsMgr'))
 | ||
| 					$menuitems['definitions']['children']['workflow_actions'] = array('link'=>$this->params['settings']->_httpRoot."out/out.WorkflowActionsMgr.php", 'label'=>getMLText('global_workflow_actions'));
 | ||
| 			}
 | ||
| 		}
 | ||
| 
 | ||
| 		if($this->params['enablefullsearch']) {
 | ||
| 			if($accessobject->check_view_access(array('Indexer', 'CreateIndex', 'IndexInfo'))) {
 | ||
| 				$menuitems['fulltext'] = array('link'=>"#", 'label'=>getMLText('fullsearch'));
 | ||
| 			if ($accessobject->check_view_access('Indexer'))
 | ||
| 				$menuitems['fulltext']['children']['update_fulltext_index'] = array('link'=>$this->params['settings']->_httpRoot."out/out.Indexer.php", 'label'=>getMLText('update_fulltext_index'));
 | ||
| 			if ($accessobject->check_view_access('CreateIndex'))
 | ||
| 				$menuitems['fulltext']['children']['create_fulltext_index'] = array('link'=>$this->params['settings']->_httpRoot."out/out.CreateIndex.php", 'label'=>getMLText('create_fulltext_index'));
 | ||
| 			if ($accessobject->check_view_access('IndexInfo'))
 | ||
| 				$menuitems['fulltext']['children']['fulltext_info'] = array('link'=>$this->params['settings']->_httpRoot."out/out.IndexInfo.php", 'label'=>getMLText('fulltext_info'));
 | ||
| 			}
 | ||
| 		}
 | ||
| 
 | ||
| 		if($accessobject->check_view_access(array('BackupTools', 'LogManagement'))) {
 | ||
| 			$menuitems['backup_log_management'] = array('link'=>"#", 'label'=>getMLText('backup_log_management'));
 | ||
| 			if ($accessobject->check_view_access('BackupTools'))
 | ||
| 				$menuitems['backup_log_management']['children'][] = array('link'=>$this->params['settings']->_httpRoot."out/out.BackupTools.php", 'label'=>getMLText('backup_tools'));
 | ||
| 			if ($this->params['logfileenable'])
 | ||
| 				if ($accessobject->check_view_access('LogManagement'))
 | ||
| 					$menuitems['backup_log_management']['children'][] = array('link'=>$this->params['settings']->_httpRoot."out/out.LogManagement.php", 'label'=>getMLText('log_management'));
 | ||
| 		}
 | ||
| 
 | ||
| 		if($accessobject->check_view_access(array('ImportFS', 'ImportUsers', 'Statistic', 'Charts', 'Timeline', 'ObjectCheck', 'ExtensionMgr', 'Info'))) {
 | ||
| 			$menuitems['misc'] = array('link'=>"#", 'label'=>getMLText('misc'));
 | ||
| 			if ($accessobject->check_view_access('ImportFS'))
 | ||
| 				$menuitems['misc']['children']['import_fs'] = array('link'=>$this->params['settings']->_httpRoot."out/out.ImportFS.php", 'label'=>getMLText('import_fs'));
 | ||
| 			if ($accessobject->check_view_access('ImportUsers'))
 | ||
| 				$menuitems['misc']['children']['import_users'] = array('link'=>$this->params['settings']->_httpRoot."out/out.ImportUsers.php", 'label'=>getMLText('import_users'));
 | ||
| 			if ($accessobject->check_view_access('Statistic'))
 | ||
| 				$menuitems['misc']['children']['folders_and_documents_statistic'] = array('link'=>$this->params['settings']->_httpRoot."out/out.Statistic.php", 'label'=>getMLText('folders_and_documents_statistic'));
 | ||
| 			if ($accessobject->check_view_access('Charts'))
 | ||
| 				$menuitems['misc']['children']['charts'] = array('link'=>$this->params['settings']->_httpRoot."out/out.Charts.php", 'label'=>getMLText('charts'));
 | ||
| 			if ($accessobject->check_view_access('Timeline'))
 | ||
| 				$menuitems['misc']['children']['timeline'] = array('link'=>$this->params['settings']->_httpRoot."out/out.Timeline.php", 'label'=>getMLText('timeline'));
 | ||
| 			if ($accessobject->check_view_access('ObjectCheck'))
 | ||
| 				$menuitems['misc']['children']['objectcheck'] = array('link'=>$this->params['settings']->_httpRoot."out/out.ObjectCheck.php", 'label'=>getMLText('objectcheck'));
 | ||
| 			if ($accessobject->check_view_access('ExpiredDocuments'))
 | ||
| 				$menuitems['misc']['children']['documents_expired'] = array('link'=>$this->params['settings']->_httpRoot."out/out.ExpiredDocuments.php", 'label'=>getMLText('documents_expired'));
 | ||
| 			if ($accessobject->check_view_access('ExtensionMgr'))
 | ||
| 				$menuitems['misc']['children']['extension_manager'] = array('link'=>$this->params['settings']->_httpRoot."out/out.ExtensionMgr.php", 'label'=>getMLText('extension_manager'));
 | ||
| 			if ($accessobject->check_view_access('ClearCache'))
 | ||
| 				$menuitems['misc']['children']['clear_cache'] = array('link'=>$this->params['settings']->_httpRoot."out/out.ClearCache.php", 'label'=>getMLText('clear_cache'));
 | ||
| 			if ($accessobject->check_view_access('Info'))
 | ||
| 				$menuitems['misc']['children']['version_info'] = array('link'=>$this->params['settings']->_httpRoot."out/out.Info.php", 'label'=>getMLText('version_info'));
 | ||
| 		}
 | ||
| 
 | ||
| 		if ($settings->_enableDebugMode) {
 | ||
| 			if($accessobject->check_view_access(array('Hooks', 'NotificationServices'))) {
 | ||
| 				$menuitems['debug'] = array('link'=>"#", 'label'=>getMLText('debug'));
 | ||
| 				if ($accessobject->check_view_access('Hooks'))
 | ||
| 					$menuitems['debug']['children']['hooks'] = array('link'=>$this->params['settings']->_httpRoot."out/out.Hooks.php", 'label'=>getMLText('list_hooks'));
 | ||
| 				if ($accessobject->check_view_access('NotificationServices'))
 | ||
| 					$menuitems['debug']['children']['notification_services'] = array('link'=>$this->params['settings']->_httpRoot."out/out.NotificationServices.php", 'label'=>getMLText('list_notification_services'));
 | ||
| 				if ($accessobject->check_view_access('SendNotification'))
 | ||
| 					$menuitems['debug']['children']['send_notification'] = array('link'=>$this->params['settings']->_httpRoot."out/out.SendNotification.php", 'label'=>getMLText('send_notification'));
 | ||
| 				if ($accessobject->check_view_access('ConversionServices'))
 | ||
| 					$menuitems['debug']['children']['conversion_services'] = array('link'=>$this->params['settings']->_httpRoot."out/out.ConversionServices.php", 'label'=>getMLText('list_conversion_services'));
 | ||
| 			}
 | ||
| 		}
 | ||
| 
 | ||
| 		/* Do not use $this->callHook() because $menuitems must be returned by the the
 | ||
| 		 * first hook and passed to next hook. $this->callHook() will just pass
 | ||
| 		 * the menuitems to each single hook. Hence, the last hook will win.
 | ||
| 		 */
 | ||
| 		$hookObjs = $this->getHookObjects();
 | ||
| 		foreach($hookObjs as $hookObj) {
 | ||
| 			if (method_exists($hookObj, 'admintoolsNavigationBar')) {
 | ||
| 	      $menuitems = $hookObj->admintoolsNavigationBar($this, $menuitems);
 | ||
| 			}
 | ||
| 		}
 | ||
| 
 | ||
| 		self::showNavigationBar($menuitems);
 | ||
| 
 | ||
| 	} /* }}} */
 | ||
| 	
 | ||
| 	private function calendarOldNavigationBar($d){ /* {{{ */
 | ||
| 		$accessobject = $this->params['accessobject'];
 | ||
| 		$ds="&day=".$d[0]."&month=".$d[1]."&year=".$d[2];
 | ||
| 		echo "<id=\"first\"><a href=\"".$this->params['settings']->_httpRoot."out/out.CalendarOld.php?mode=y\" class=\"brand\">".getMLText("calendar")."</a>\n";
 | ||
| 		echo "<div class=\"nav-collapse col2\">\n";
 | ||
| 		echo "<ul class=\"nav\">\n";
 | ||
| 
 | ||
| 		echo "<li><a href=\"".$this->params['settings']->_httpRoot."out/out.CalendarOld.php?mode=w".$ds."\">".getMLText("week_view")."</a></li>\n";
 | ||
| 		echo "<li><a href=\"".$this->params['settings']->_httpRoot."out/out.CalendarOld.php?mode=m".$ds."\">".getMLText("month_view")."</a></li>\n";
 | ||
| 		echo "<li><a href=\"".$this->params['settings']->_httpRoot."out/out.CalendarOld.php?mode=y".$ds."\">".getMLText("year_view")."</a></li>\n";
 | ||
| 		if (!$this->params['user']->isGuest())
 | ||
| 			echo "<li><a href=\"".$this->params['settings']->_httpRoot."out/out.AddEvent.php\">".getMLText("add_event")."</a></li>\n";
 | ||
| 		echo "</ul>\n";
 | ||
| 		echo "</div>\n";
 | ||
| 		return;
 | ||
| 	
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	private function calendarNavigationBar($d){ /* {{{ */
 | ||
| 		$accessobject = $this->params['accessobject'];
 | ||
| 
 | ||
| 		$menuitems = array();
 | ||
| 		if (!$this->params['user']->isGuest())
 | ||
| 			$menuitems['addevent'] = array('link'=>$this->params['settings']->_httpRoot."out/out.AddEvent.php", 'label'=>getMLText('add_event'));
 | ||
| 
 | ||
| 		/* Do not use $this->callHook() because $menuitems must be returned by the the
 | ||
| 		 * first hook and passed to next hook. $this->callHook() will just pass
 | ||
| 		 * the menuitems to each single hook. Hence, the last hook will win.
 | ||
| 		 */
 | ||
| 		$hookObjs = $this->getHookObjects();
 | ||
| 		foreach($hookObjs as $hookObj) {
 | ||
| 			if (method_exists($hookObj, 'calendarNavigationBar')) {
 | ||
| 	      $menuitems = $hookObj->calendarNavigationBar($this, $menuitems);
 | ||
| 			}
 | ||
| 		}
 | ||
| 
 | ||
| 		self::showNavigationBar($menuitems);
 | ||
| 
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function pageList($pageNumber, $totalPages, $baseURI, $params, $dataparams=[]) { /* {{{ */
 | ||
| 
 | ||
| 		$maxpages = 25; // skip pages when more than this is shown
 | ||
| 		$range = 2; // pages left and right of current page
 | ||
| 		if (!is_numeric($pageNumber) || !is_numeric($totalPages) || $totalPages<2) {
 | ||
| 			return;
 | ||
| 		}
 | ||
| 
 | ||
| 		// Construct the basic URI based on the $_GET array. One could use a
 | ||
| 		// regular expression to strip out the pg (page number) variable to
 | ||
| 		// achieve the same effect. This seems to be less haphazard though...
 | ||
| 		$resultsURI = $baseURI;
 | ||
| 		unset($params['pg']);
 | ||
| 		$first=true;
 | ||
| 		if($params) {
 | ||
| 			$resultsURI .= '?'.http_build_query($params);
 | ||
| 			$first=false;
 | ||
| 		}
 | ||
| 
 | ||
| 		$datastr = '';
 | ||
| 		if($dataparams) {
 | ||
| 			$datastr .= ' ';
 | ||
| 			foreach($dataparams as $k=>$v)
 | ||
| 				$datastr .= 'data-'.$k.'="'.$v.'"';
 | ||
| 		}
 | ||
| 		echo "<nav aria-label=\"pagination\">";
 | ||
| 		echo "<ul class=\"pagination pagination-sm\">";
 | ||
| 		if($totalPages <= $maxpages) {
 | ||
| 			for ($i = 1; $i <= $totalPages; $i++) {
 | ||
| 				echo "<li class=\"page-item".($i == $pageNumber ? ' active' : "" )."\"><a class=\"page-link\" href=\"".$resultsURI.($first ? "?" : "&")."pg=".$i."\" data-page=\"".$i."\"".$datastr.">".$i."</a></li>";
 | ||
| 			}
 | ||
| 		} else {
 | ||
| 			if($pageNumber-$range > 1)
 | ||
| 				$start = $pageNumber-$range;
 | ||
| 			else
 | ||
| 				$start = 2;
 | ||
| 			if($pageNumber+$range < $totalPages)
 | ||
| 				$end = $pageNumber+$range;
 | ||
| 			else
 | ||
| 				$end = $totalPages-1;
 | ||
| 			/* Move start or end to always show 2*$range items */
 | ||
| 			$diff = $end-$start-2*$range;
 | ||
| 			if($diff < 0) {
 | ||
| 				if($start > 2)
 | ||
| 					$start += $diff;
 | ||
| 				if($end < $totalPages-1)
 | ||
| 					$end -= $diff;
 | ||
| 			}
 | ||
| //			if($pageNumber > 1)
 | ||
| 				echo "<li class=\"page-item".($pageNumber == 1 ? " disabled" : "")."\"><a class=\"page-link\" href=\"".$resultsURI.($first ? "?" : "&")."pg=".($pageNumber-1)."\" data-page=\"".($pageNumber-1)."\"".$datastr.">«</a></li>";
 | ||
| 			echo "<li class=\"page-item".(1 == $pageNumber ? ' active' : "" )."\"><a class=\"page-link\" href=\"".$resultsURI.($first ? "?" : "&")."pg=1\" data-page=\"1\"".$datastr.">1</a></li>";
 | ||
| 			if($start > 2)
 | ||
| 				echo "<li class=\"page-item disabled\"><a class=\"page-link\">...</a></li>";
 | ||
| 			for($j=$start; $j<=$end; $j++)
 | ||
| 				echo "<li class=\"page-item".($j == $pageNumber ? ' active' : "" )."\"><a class=\"page-link\" href=\"".$resultsURI.($first ? "?" : "&")."pg=".$j."\" data-page=\"".$j."\"".$datastr.">".$j."</a></li>";
 | ||
| 			if($end < $totalPages-1)
 | ||
| 				echo "<li class=\"page-item disabled\"><a class=\"page-link\">...</a></li>";
 | ||
| 			if($end < $totalPages)
 | ||
| 				echo "<li class=\"page-item".($totalPages == $pageNumber ? ' active' : "" )."\"><a class=\"page-link\" href=\"".$resultsURI.($first ? "?" : "&")."pg=".$totalPages."\" data-page=\"".$totalPages."\"".$datastr.">".$totalPages."</a></li>";
 | ||
| 			if($pageNumber < $totalPages)
 | ||
| 				echo "<li class=\"page-item\"><a class=\"page-link\" href=\"".$resultsURI.($first ? "?" : "&")."pg=".($pageNumber+1)."\" data-page=\"".($pageNumber+1)."\"".$datastr.">»</a></li>";
 | ||
| 		}
 | ||
| 		if ($totalPages>1) {
 | ||
| 			echo "<li class=\"page-item".(0 == $pageNumber ? ' active' : "" )."\"><a class=\"page-link\" href=\"".$resultsURI.($first ? "?" : "&")."pg=all\" data-page=\"all\"".$datastr.">".getMLText("all_pages")."</a></li>";
 | ||
| 		}
 | ||
| 		echo "</ul>";
 | ||
| 		echo "</nav>";
 | ||
| 
 | ||
| 		return;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function contentContainer($content) { /* {{{ */
 | ||
| 		echo "<div class=\"border\">\n";
 | ||
| 		echo $content;
 | ||
| 		echo "</div>\n";
 | ||
| 		return;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function contentContainerStart($class='', $id='') { /* {{{ */
 | ||
| 		echo "<div class=\"p-3 _border mb-4 bg-light _rounded".($class ? " ".$class : "")."\"".($id ? " id=\"".$id."\"" : "").">\n";
 | ||
| 		return;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function contentContainerEnd() { /* {{{ */
 | ||
| 
 | ||
| 		echo "</div>\n";
 | ||
| 		return;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function contentHeading($heading, $noescape=false) { /* {{{ */
 | ||
| 
 | ||
| 		if($noescape)
 | ||
| 			echo "<legend class=\"border-bottom\">".$heading."</legend>\n";
 | ||
| 		else
 | ||
| 			echo "<legend class=\"border-bottom\">".htmlspecialchars($heading)."</legend>\n";
 | ||
| 		return;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function contentSubHeading($heading, $first=false) { /* {{{ */
 | ||
| 
 | ||
| //		echo "<div class=\"contentSubHeading\"".($first ? " id=\"first\"" : "").">".htmlspecialchars($heading)."</div>\n";
 | ||
| 		echo "<h5>".$heading."</h5>";
 | ||
| 		return;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function rowStart() { /* {{{ */
 | ||
| 		echo "<div class=\"row\">\n";
 | ||
| 		return;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function rowEnd() { /* {{{ */
 | ||
| 		echo "</div>\n";
 | ||
| 		return;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function columnStart($width=6) { /* {{{ */
 | ||
| 		echo "<div class=\"col-lg-".$width." col-sm-12\">\n";
 | ||
| 		return;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function columnEnd() { /* {{{ */
 | ||
| 		echo "</div>\n";
 | ||
| 		return;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function formField($title, $value, $params=array()) { /* {{{ */
 | ||
| 		if($title !== null) {
 | ||
| 			echo "<div class=\"form-group row\">";
 | ||
| 			echo "	<label class=\"col-sm-4 col-lg-4 pt-0 col-form-label\"".(!empty($params['help']) ? " title=\"".$params['help']."\" style=\"cursor: help;\"" : "").(!empty($value['id']) ? ' for="'.$value['id'].'"' : '').">".$title.":</label>";
 | ||
| 			echo "	<div class=\"col-sm-8 col-lg-8\">";
 | ||
| 		}
 | ||
| 		if(isset($params['field_wrap'][0]))
 | ||
| 			echo $params['field_wrap'][0];
 | ||
| 		if(is_string($value)) {
 | ||
| 			echo $value;
 | ||
| 		} elseif(is_array($value)) {
 | ||
| 			switch($value['element']) {
 | ||
| 			case 'select':
 | ||
| 				$allowempty = empty($value['allow_empty']) ? false : $value['allow_empty'];
 | ||
| 				echo '<select'.
 | ||
| 					(!empty($value['id']) ? ' id="'.$value['id'].'"' : '').
 | ||
| 					(!empty($value['name']) ? ' name="'.$value['name'].'"' : '').
 | ||
| 					(empty($value['class']) ? ' class="form-control"' : ' class="form-control '.$value['class'].'"').
 | ||
| 					(!empty($value['placeholder']) ? ' data-placeholder="'.$value['placeholder'].'"' : '').
 | ||
| 					(!empty($value['required']) ? ' required="required"' : '').
 | ||
| 					($allowempty	? ' data-allow-clear="true"' : '').
 | ||
| 					(!empty($value['multiple']) ? ' multiple' : '');
 | ||
| 				if(!empty($value['attributes']) && is_array($value['attributes']))
 | ||
| 					foreach($value['attributes'] as $a)
 | ||
| 						echo ' '.$a[0].'="'.$a[1].'"';
 | ||
| 				echo ">";
 | ||
| 				if(isset($value['options']) && is_array($value['options'])) {
 | ||
| 					if($allowempty)
 | ||
| 						echo "<option value=\"\"></option>";
 | ||
| 					foreach($value['options'] as $val) {
 | ||
| 						if(is_string($val)) {
 | ||
| 							echo '<optgroup label="'.$val.'">';
 | ||
| 						} elseif(is_array($val)) {
 | ||
| 						echo '<option value="'.$val[0].'"'.(!empty($val[2]) ? ' selected' : '');
 | ||
| 						if(!empty($val[3]) && is_array($val[3]))
 | ||
| 							foreach($val[3] as $a)
 | ||
| 								echo ' '.$a[0].'="'.$a[1].'"';
 | ||
| 						echo '>'.$val[1].'</option>';
 | ||
| 						}
 | ||
| 					}
 | ||
| 				}
 | ||
| 				echo '</select>';
 | ||
| 				break;
 | ||
| 			case 'textarea':
 | ||
| 				echo '<textarea'.
 | ||
| 					(!empty($value['id']) ? ' id="'.$value['id'].'"' : '').
 | ||
| 					(!empty($value['name']) ? ' name="'.$value['name'].'"' : '').
 | ||
| 					(empty($value['class']) ? ' class="form-control"' : ' class="form-control '.$value['class'].'"').
 | ||
| 					(!empty($value['rows']) ? ' rows="'.$value['rows'].'"' : '').
 | ||
| 					(!empty($value['cols']) ? ' cols="'.$value['cols'].'"' : '').
 | ||
| 					(!empty($value['placeholder']) ? ' placeholder="'.$value['placeholder'].'"' : '').
 | ||
| 					(!empty($value['required']) ? ' required="required"' : '').">".(!empty($value['value']) ? $value['value'] : '')."</textarea>";
 | ||
| 				break;
 | ||
| 			case 'plain':
 | ||
| 				echo $value['value'];
 | ||
| 				break;
 | ||
| 			case 'input':
 | ||
| 			default:
 | ||
| 				switch($value['type']) {
 | ||
| 				case 'checkbox':
 | ||
| 					if(isset($value['default']) && !empty($value['name']))
 | ||
| 						echo '<input type="hidden" name="'.$value['name'].'" value="'.$value['default'].'" />';
 | ||
| 					echo '<div class="form-check">';
 | ||
| 					echo '<input'.
 | ||
| 						(!empty($value['type']) ? ' type="'.$value['type'].'"' : '').
 | ||
| 						(!empty($value['id']) ? ' id="'.$value['id'].'"' : '').
 | ||
| 						(!empty($value['name']) ? ' name="'.$value['name'].'"' : '').
 | ||
| 						(empty($value['class']) ? ' class="form-check-input"' : ' class="form-check-input '.$value['class'].'"').
 | ||
| 						((isset($value['value']) && is_string($value['value'])) || !empty($value['value']) ? ' value="'.$value['value'].'"' : '').
 | ||
| 						(!empty($value['placeholder']) ? ' placeholder="'.$value['placeholder'].'"' : '').
 | ||
| 						(!empty($value['autocomplete']) ? ' autocomplete="'.$value['autocomplete'].'"' : '').
 | ||
| 						(!empty($value['checked']) ? ' checked' : '').
 | ||
| 						(!empty($value['required']) ? ' required="required"' : '');
 | ||
| 					if(!empty($value['attributes']) && is_array($value['attributes']))
 | ||
| 						foreach($value['attributes'] as $a)
 | ||
| 							echo ' '.$a[0].'="'.$a[1].'"';
 | ||
| 					echo ">";
 | ||
| 					echo '<label class="form-check-label" '.(!empty($value['id']) ?? 'for="'.$value['id'].'"').'>'.(!empty($value['label']) ?? $value['label']).'</label>';
 | ||
| 					echo "</div>";
 | ||
| 					break;
 | ||
| 				default:
 | ||
| 					if(!empty($value['addon']))
 | ||
| 						echo '<div class="input-group date">';
 | ||
| 					echo '<input'.
 | ||
| 						(!empty($value['type']) ? ' type="'.$value['type'].'"' : '').
 | ||
| 						(!empty($value['id']) ? ' id="'.$value['id'].'"' : '').
 | ||
| 						(!empty($value['name']) ? ' name="'.$value['name'].'"' : '').
 | ||
| 						(empty($value['class']) ? ' class="form-control"' : ' class="form-control '.$value['class'].'"').
 | ||
| 						((isset($value['value']) && is_string($value['value'])) || !empty($value['value']) ? ' value="'.$value['value'].'"' : '').
 | ||
| 						(!empty($value['placeholder']) ? ' placeholder="'.$value['placeholder'].'"' : '').
 | ||
| 						(!empty($value['autocomplete']) ? ' autocomplete="'.$value['autocomplete'].'"' : '').
 | ||
| 						(isset($value['min']) ? ' min="'.$value['min'].'"' : '').
 | ||
| 						(!empty($value['checked']) ? ' checked' : '').
 | ||
| 						(!empty($value['required']) ? ' required="required"' : '');
 | ||
| 					if(!empty($value['attributes']) && is_array($value['attributes']))
 | ||
| 						foreach($value['attributes'] as $a)
 | ||
| 							echo ' '.$a[0].'="'.$a[1].'"';
 | ||
| 					echo "/>";
 | ||
| 					if(!empty($value['addon'])) {
 | ||
| 						echo '<div class="input-group-append">';
 | ||
| 						echo '<span class="input-group-text">'.$value['addon'].'</span>';
 | ||
| 						echo '</div>';
 | ||
| 						echo '</div>';
 | ||
| 					}
 | ||
| 					break;
 | ||
| 				}
 | ||
| 				break;
 | ||
| 			}
 | ||
| 		}
 | ||
| 		if(isset($params['field_wrap'][1]))
 | ||
| 			echo $params['field_wrap'][1];
 | ||
| 		if($title !== null) {
 | ||
| 			echo "</div>";
 | ||
| 			echo "</div>";
 | ||
| 		}
 | ||
| 		return;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function formSubmit($value, $name='', $target='', $type='primary') { /* {{{ */
 | ||
| 		switch($type) {
 | ||
| 		case 'danger':
 | ||
| 			$class = 'btn-danger';
 | ||
| 			break;
 | ||
| 		case 'secondary':
 | ||
| 			$class = 'btn-secondary';
 | ||
| 			break;
 | ||
| 		case 'neutral':
 | ||
| 			$class = '';
 | ||
| 			break;
 | ||
| 		case 'primary':
 | ||
| 		default:
 | ||
| 			$class = 'btn-primary';
 | ||
| 		}
 | ||
| //		echo "<div class=\"controls\">\n";
 | ||
| 		if(is_string($value)) {
 | ||
| 			echo "<button type=\"submit\" class=\"btn ".$class."\"".($name ? ' name="'.$name.'" id="'.$name.'"' : '').($target ? ' formtarget="'.$target.'"' : '').">".$value."</button>\n";
 | ||
| 		} else {
 | ||
| 			if(is_array($value)) {
 | ||
| 				foreach($value as $i=>$v)
 | ||
| 					echo "<button type=\"submit\" class=\"btn ".$class."\"".(!empty($name[$i]) ? ' name="'.$name[$i].'" id="'.$name[$i].'"' : '').(!empty($target[$i]) ? ' formtarget="'.$name[$i].'"' : '').">".$v."</button>\n";
 | ||
| 			}
 | ||
| 		}
 | ||
| //		echo "</div>\n";
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function getMimeIcon($fileType) { /* {{{ */
 | ||
| 		// for extension use LOWER CASE only
 | ||
| 		$icons = array();
 | ||
| 		$icons["txt"]  = "text-x-preview.svg";
 | ||
| 		$icons["text"] = "text-x-preview.svg";
 | ||
| 		$icons["tex"]  = "text-x-preview.svg";
 | ||
| 		$icons["doc"]  = "office-document.svg";
 | ||
| 		$icons["dot"]  = "office-document.svg";
 | ||
| 		$icons["docx"] = "office-document.svg";
 | ||
| 		$icons["dotx"] = "office-document.svg";
 | ||
| 		$icons["rtf"]  = "office-document.svg";
 | ||
| 		$icons["xls"]  = "office-spreadsheet.svg";
 | ||
| 		$icons["xlt"]  = "office-spreadsheet.svg";
 | ||
| 		$icons["xlsx"] = "office-spreadsheet.svg";
 | ||
| 		$icons["xltx"] = "office-spreadsheet.svg";
 | ||
| 		$icons["ppt"]  = "office-presentation.svg";
 | ||
| 		$icons["pot"]  = "office-presentation.svg";
 | ||
| 		$icons["pptx"] = "office-presentation.svg";
 | ||
| 		$icons["potx"] = "office-presentation.svg";
 | ||
| 		$icons["exe"]  = "executable.svg";
 | ||
| 		$icons["html"] = "web.svg";
 | ||
| 		$icons["htm"]  = "web.svg";
 | ||
| 		$icons["gif"]  = "image.svg";
 | ||
| 		$icons["jpg"]  = "image.svg";
 | ||
| 		$icons["jpeg"] = "image.svg";
 | ||
| 		$icons["bmp"]  = "image.svg";
 | ||
| 		$icons["png"]  = "image.svg";
 | ||
| 		$icons["tif"]  = "image.svg";
 | ||
| 		$icons["tiff"] = "image.svg";
 | ||
| 		$icons["log"]  = "text-x-preview.svg";
 | ||
| 		$icons["midi"] = "audio.svg";
 | ||
| 		$icons["pdf"]  = "gnome-mime-application-pdf.svg";
 | ||
| 		$icons["wav"]  = "audio.svg";
 | ||
| 		$icons["mp3"]  = "audio.svg";
 | ||
| 		$icons["m4a"]  = "audio.svg";
 | ||
| 		$icons["ogg"]  = "audio.svg";
 | ||
| 		$icons["opus"]  = "audio.svg";
 | ||
| 		$icons["c"]    = "text-x-preview.svg";
 | ||
| 		$icons["cpp"]  = "text-x-preview.svg";
 | ||
| 		$icons["h"]    = "text-x-preview.svg";
 | ||
| 		$icons["java"] = "text-x-preview.svg";
 | ||
| 		$icons["py"]   = "text-x-preview.svg";
 | ||
| 		$icons["tar"]  = "package.svg";
 | ||
| 		$icons["gz"]   = "package.svg";
 | ||
| 		$icons["7z"]   = "package.svg";
 | ||
| 		$icons["bz"]   = "package.svg";
 | ||
| 		$icons["bz2"]  = "package.svg";
 | ||
| 		$icons["tgz"]  = "package.svg";
 | ||
| 		$icons["zip"]  = "package.svg";
 | ||
| 		$icons["rar"]  = "package.svg";
 | ||
| 		$icons["mpg"]  = "video.svg";
 | ||
| 		$icons["mp4"]  = "video.svg";
 | ||
| 		$icons["avi"]  = "video.svg";
 | ||
| 		$icons["webm"]  = "video.svg";
 | ||
| 		$icons["mkv"]  = "video.svg";
 | ||
| 		$icons["ods"]  = "office-spreadsheet.svg";
 | ||
| 		$icons["ots"]  = "office-spreadsheet.svg";
 | ||
| 		$icons["sxc"]  = "office-spreadsheet.svg";
 | ||
| 		$icons["stc"]  = "office-spreadsheet.svg";
 | ||
| 		$icons["odt"]  = "office-document.svg";
 | ||
| 		$icons["ott"]  = "office-document.svg";
 | ||
| 		$icons["sxw"]  = "office-document.svg";
 | ||
| 		$icons["stw"]  = "office-document.svg";
 | ||
| 		$icons["odp"]  = "office-presentation.svg";
 | ||
| 		$icons["otp"]  = "office-presentation.svg";
 | ||
| 		$icons["sxi"]  = "office-presentation.svg";
 | ||
| 		$icons["sti"]  = "office-presentation.svg";
 | ||
| 		$icons["odg"]  = "office-drawing.svg";
 | ||
| 		$icons["otg"]  = "office-drawing.svg";
 | ||
| 		$icons["sxd"]  = "office-drawing.svg";
 | ||
| 		$icons["std"]  = "office-drawing.svg";
 | ||
| 		$icons["odf"]  = "ooo_formula.png";
 | ||
| 		$icons["sxm"]  = "ooo_formula.png";
 | ||
| 		$icons["smf"]  = "ooo_formula.png";
 | ||
| 		$icons["mml"]  = "ooo_formula.png";
 | ||
| 		$icons["folder"]  = "folder.svg";
 | ||
| 
 | ||
| 		$icons["default"] = "text-x-preview.svg"; //"default.png";
 | ||
| 
 | ||
| 		$ext = strtolower(substr($fileType, 1));
 | ||
| 		if (isset($icons[$ext])) {
 | ||
| 			return $this->imgpath.$icons[$ext];
 | ||
| 		}
 | ||
| 		else {
 | ||
| 			return $this->imgpath.$icons["default"];
 | ||
| 		}
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| function getOverallStatusIcon($status) { /* {{{ */
 | ||
| 	if (is_null($status)) {
 | ||
| 		return '';
 | ||
| 	} else {
 | ||
| 		$icon = '';
 | ||
| 		$color = '';
 | ||
| 		switch($status) {
 | ||
| 			case S_IN_WORKFLOW:
 | ||
| 				$icon = 'fa fa-circle in-workflow';
 | ||
| 				break;
 | ||
| 			case S_DRAFT_REV:
 | ||
| 				$icon = 'fa fa-circle in-workflow';
 | ||
| 				break;
 | ||
| 			case S_DRAFT_APP:
 | ||
| 				$icon = 'fa fa-circle in-workflow';
 | ||
| 				break;
 | ||
| 			case S_RELEASED:
 | ||
| 				$icon = 'fa-circle released';
 | ||
| 				break;
 | ||
| 			case S_REJECTED:
 | ||
| 				$icon = 'fa-circle rejected';
 | ||
| 				break;
 | ||
| 			case S_OBSOLETE:
 | ||
| 				$icon = 'fa-circle obsolete';
 | ||
| 				break;
 | ||
| 			case S_EXPIRED:
 | ||
| 				$icon = 'fa-circle expired';
 | ||
| 				break;
 | ||
| 			default:
 | ||
| 				$icon = 'fa fa-question';
 | ||
| 				break;
 | ||
| 		}
 | ||
| 		return '<div style="display: inline-block; white-space: nowrap;"><i class="fa '.$icon.'"'.($color ? ' style="color: '.$color.';"' : '').'  title="'.getOverallStatusText($status).'"></i> <span class="d-none d-md-inline-block">'.getOverallStatusText($status).'</span></div>';
 | ||
| 	}
 | ||
| } /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Get attributes for a button opening a modal box
 | ||
| 	 *
 | ||
| 	 * @param array $config contains elements
 | ||
| 	 *   target: id of modal box
 | ||
| 	 *   remote: URL of data to be loaded into box
 | ||
| 	 * @return string
 | ||
| 	 */
 | ||
| 	function getModalBoxLinkAttributes($config) { /* {{{ */
 | ||
| 		$attrs = array();
 | ||
| 		$attrs[] = array('data-target', '#'.$config['target']);
 | ||
| 		if(isset($config['remote'])) {
 | ||
| 			$attrs[] = array('href', $config['remote']);
 | ||
| 			$attrs[] = array('data-remote', $config['remote']);
 | ||
| 		}
 | ||
| 		$attrs[] = array('data-toggle', 'modal');
 | ||
| 		$attrs[] = array('role', 'button');
 | ||
| 		if(isset($config['class'])) {
 | ||
| 			if($config['class'])
 | ||
| 				$attrs[] = array('class', $config['class']);
 | ||
| 		} else
 | ||
| 			$attrs[] = array('class', 'btn');
 | ||
| 		return $attrs;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Get html for button opening a modal box
 | ||
| 	 *
 | ||
| 	 * @param array $config contains elements
 | ||
| 	 *   target: id of modal box
 | ||
| 	 *   remote: URL of data to be loaded into box
 | ||
| 	 *   title: text on button
 | ||
| 	 * @return string
 | ||
| 	 */
 | ||
| 	function getModalBoxLink($config) { /* {{{ */
 | ||
| //		$content = '';
 | ||
| //		$content .= "<a data-target=\"#".$config['target']."\"".(isset($config['remote']) ? " href=\"".$config['remote']."\"" : "")." role=\"button\" class=\"".(isset($config['class']) ? $config['class'] : "btn btn-secondary")."\" data-toggle=\"modal\"";
 | ||
| 		$attrs = self::getModalBoxLinkAttributes($config);
 | ||
| 		$content = '<a';
 | ||
| 		if($attrs) {
 | ||
| 			foreach($attrs as $attr)
 | ||
| 				$content .= ' '.$attr[0].'="'.$attr[1].'"';
 | ||
| 		}
 | ||
| 		if(!empty($config['attributes'])) {
 | ||
| 			foreach($config['attributes'] as $attrname=>$attrval)
 | ||
| 				$content .= ' '.$attrname.'="'.$attrval.'"';
 | ||
| 		}
 | ||
| 		$content .= ">".$config['title']."</a>\n";
 | ||
| 		return $content;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Get html for a modal box with buttons
 | ||
| 	 *
 | ||
| 	 * @param array $config contains elements
 | ||
| 	 *   id: id of modal box (must match target of getModalBoxLink())
 | ||
| 	 *   title: title of modal box
 | ||
| 	 *   content: content to be shown in the body of the box. Can be left
 | ||
| 	 *   empty if the body is loaded from the remote link passed to the button
 | ||
| 	 *   to open this box.
 | ||
| 	 *   buttons: array of buttons, each having a title and an optional id
 | ||
| 	 * @return string
 | ||
| 	 */
 | ||
| 	function getModalBox($config) { /* {{{ */
 | ||
| 		$content = '';
 | ||
| 		$content .= '
 | ||
| <div class="modal fade" id="'.$config['id'].'" tabindex="-1" role="dialog" aria-labelledby="'.$config['id'].'Label" aria-hidden="true">
 | ||
| 	<div class="modal-dialog modal-lg" role="document">
 | ||
| 		<div class="modal-content">
 | ||
| 			<div class="modal-header">
 | ||
| 				<h3 id="'.$config['id'].'Label">'.$config['title'].'</h3>
 | ||
| 				<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
 | ||
| 			</div>
 | ||
| 			<div class="modal-body">
 | ||
| ';
 | ||
| 		if(!empty($config['content']))
 | ||
| 			$content .= $config['content'];
 | ||
| 		else
 | ||
| 			$content .= '<p>'.getMLText('data_loading').'</p>';
 | ||
| 		$content .= '
 | ||
| 			</div>
 | ||
| 			<div class="modal-footer">
 | ||
| ';
 | ||
| 		if($config['buttons']) {
 | ||
| 			foreach($config['buttons'] as $button)
 | ||
| 				$content .= '<button class="btn'.(!empty($button['id']) ? ' btn-primary" id="'.$button['id'].'"': ' btn-secondary" ').' data-dismiss="modal" aria-hidden="true">'.$button['title'].'</button>';
 | ||
| 		}
 | ||
| 		$content .= '
 | ||
| 			</div>
 | ||
| 		</div>
 | ||
| 	</div>
 | ||
| </div>
 | ||
| ';
 | ||
| 	return $content;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function printFileChooserJs() { /* {{{ */
 | ||
| 		$maxfilesize = $this->getParam('maxfilesize');
 | ||
| ?>
 | ||
| $(document).ready(function() {
 | ||
| /* do not use bootstrap4 custom form element because it is difficult to localize
 | ||
| 	$(document).on('change', '.custom-file-input',function(){
 | ||
| 		//get the file name
 | ||
| 		var fileName = $(this).val().replace(/\\/g, '/').replace(/.*\//, '');
 | ||
| 		//replace the "Choose a file" label
 | ||
| 		$(this).next('.custom-file-label').html(fileName);
 | ||
| 	})
 | ||
| */
 | ||
| 	/* Triggered after the file has been selected */
 | ||
| 	$(document).on('change', '.btn-file :file', function() {
 | ||
| 		var input = $(this),
 | ||
| 		numFiles = input.get(0).files ? input.get(0).files.length : 1,
 | ||
| 		label = input.val().replace(/\\/g, '/').replace(/.*\//, '');
 | ||
| <?php if($maxfilesize): ?>
 | ||
| 		if(input.get(0).files[0].size > <?= $maxfilesize ?>) {
 | ||
| 			noty({
 | ||
| 				text: "<?= getMLText('uploading_maxsize') ?>",
 | ||
| 				type: 'error',
 | ||
| 				dismissQueue: true,
 | ||
| 				layout: 'topRight',
 | ||
| 				theme: 'defaultTheme',
 | ||
| 				timeout: 1500,
 | ||
| 			});
 | ||
| 			return;
 | ||
| 		}
 | ||
| <?php endif; ?>
 | ||
| 		input.trigger('fileselect', [numFiles, label]);
 | ||
| 	});
 | ||
| 
 | ||
| 	$(document).on('fileselect', '.upload-file .btn-file :file', function(event, numFiles, label) {
 | ||
| 		var input = $(this).parents('.input-group').find(':text'),
 | ||
| 		log = numFiles > 1 ? numFiles + ' files selected' : label;
 | ||
| 
 | ||
| 		if( input.length ) {
 | ||
| 			input.val(log);
 | ||
| 		} else {
 | ||
| //			if( log ) alert(log);
 | ||
| 		}
 | ||
| 	});
 | ||
| });
 | ||
| <?php
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function getFileChooserHtml($varname='userfile', $multiple=false, $accept='') { /* {{{ */
 | ||
| 		$id = preg_replace('/[^A-Za-z]/', '', $varname);
 | ||
| /* do not use bootstrap4 custom form element because it is difficult to localize
 | ||
| 		$html = '
 | ||
| <div class="custom-file">
 | ||
|   <input type="file" class="custom-file-input" id="'.$id.'" name="'.$varname.'">
 | ||
|   <label class="custom-file-label" for="'.$id.'">'.getMLText("browse").'…'.'</label>
 | ||
| </div>
 | ||
| ';
 | ||
| 		return $html;
 | ||
|  */
 | ||
| 		$html = '
 | ||
| 	<div id="'.$id.'-upload-files">
 | ||
| 		<div id="'.$id.'-upload-file" class="upload-file">
 | ||
| 			<div class="input-group">
 | ||
| 				<input type="text" class="form-control fileupload-group" id="kkll'.$id.'" readonly>
 | ||
| 				<div class="input-group-append">
 | ||
| 				<a class="btn btn-secondary btn-file">
 | ||
| 					'.getMLText("browse").'… <input id="'.$id.'" type="file" name="'.$varname.'"'.($multiple ? " multiple" : "").($accept ? ' accept="'.$accept.'"' : "").' data-target-highlight="kkll'.$id.'">
 | ||
| 				</a>
 | ||
| 				</div>
 | ||
| 			</div>
 | ||
| 		</div>
 | ||
| 	</div>
 | ||
| ';
 | ||
| 		return $html;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function printFileChooser($varname='userfile', $multiple=false, $accept='') { /* {{{ */
 | ||
| 		echo self::getFileChooserHtml($varname, $multiple, $accept);
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function printDateChooser($defDate, $varName, $lang='', $dateformat='', $startdate='', $enddate='', $weekstart=null) { /* {{{ */
 | ||
| 		echo self::getDateChooser($defDate, $varName, $lang, $dateformat, $startdate, $enddate, $weekstart);
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function getDateChooser($defDate, $varName, $lang='', $dateformat='', $startdate='', $enddate='', $weekstart=null, $placeholder='', $nogroup=false) { /* {{{ */
 | ||
| 		if(!$dateformat)
 | ||
| 			$dateformat = getConvertDateFormat($this->params['settings']->_dateformat);
 | ||
| 		$content = '';
 | ||
| 		if(!$nogroup)
 | ||
| 			$content .= '<div class="input-group date" id="'.$varName.'date">';
 | ||
| 		$content .= '<input type="text" class="form-control datepicker" autocomplete="off" placeholder="'.htmlspecialchars($placeholder).'" name="'.$varName.'" id="'.$varName.'" value="'.$defDate. '" data-date-calendar-weeks="true" '.($weekstart == null ? '' : 'data-date-week-start="'.intval($weekstart).'" ').'data-date="'.$defDate.'" data-selectmenu="presetexpdate" data-date-format="'.$dateformat.'"'.($lang ? 'data-date-language="'.str_replace('_', '-', $lang).'"' : '').($startdate ? ' data-date-start-date="'.$startdate.'"' : '').($enddate ? ' data-date-end-date="'.$enddate.'"' : '').' data-date-autoclose="true" data-provide="datepicker">';
 | ||
| 		if(!$nogroup) {
 | ||
| 			$content .= '<div class="input-group-append">
 | ||
| 			<span class="input-group-text"><i class="fa fa-calendar"></i></span>
 | ||
| 		</div>';
 | ||
| 			$content .= '</div>';
 | ||
| 		}
 | ||
| 		return $content;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function __printDateChooser($defDate, $varName) { /* {{{ */
 | ||
| 	
 | ||
| 		if ($defDate == -1)
 | ||
| 			$defDate = mktime();
 | ||
| 		$day   = date("d", $defDate);
 | ||
| 		$month = date("m", $defDate);
 | ||
| 		$year  = date("Y", $defDate);
 | ||
| 
 | ||
| 		print "<select name=\"" . $varName . "day\">\n";
 | ||
| 		for ($i = 1; $i <= 31; $i++)
 | ||
| 		{
 | ||
| 			print "<option value=\"" . $i . "\"";
 | ||
| 			if (intval($day) == $i)
 | ||
| 				print " selected";
 | ||
| 			print ">" . $i . "</option>\n";
 | ||
| 		}
 | ||
| 		print "</select> \n";
 | ||
| 		print "<select name=\"" . $varName . "month\">\n";
 | ||
| 		for ($i = 1; $i <= 12; $i++)
 | ||
| 		{
 | ||
| 			print "<option value=\"" . $i . "\"";
 | ||
| 			if (intval($month) == $i)
 | ||
| 				print " selected";
 | ||
| 			print ">" . $i . "</option>\n";
 | ||
| 		}
 | ||
| 		print "</select> \n";
 | ||
| 		print "<select name=\"" . $varName . "year\">\n";	
 | ||
| 		for ($i = $year-5 ; $i <= $year+5 ; $i++)
 | ||
| 		{
 | ||
| 			print "<option value=\"" . $i . "\"";
 | ||
| 			if (intval($year) == $i)
 | ||
| 				print " selected";
 | ||
| 			print ">" . $i . "</option>\n";
 | ||
| 		}
 | ||
| 		print "</select>";
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function printSequenceChooser($parent, $type, $keepID = -1) { /* {{{ */
 | ||
| 		echo $this->getSequenceChooser($parent, $type, $keepID);
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Return html code for sequence chooser
 | ||
| 	 *
 | ||
| 	 * This method will return the html code of the ѕelect menu for setting
 | ||
| 	 * the ѕequence number of a document or folder. The select menu will contain
 | ||
| 	 * a list of all siblings to select to positon relative to a sibling.
 | ||
| 	 * For performance reasons the select menu will not contain any siblings
 | ||
| 	 * if the number of siblings is greater than 50.
 | ||
| 	 *
 | ||
| 	 * @param $parent object parent folder of new or updated document/folder
 | ||
| 	 * @param $type string type of new object 'f'=folder, 'd'=document
 | ||
| 	 * @param $keepID integer id of current object
 | ||
| 	 */
 | ||
| 	function getSequenceChooser($parent, $type, $keepID = -1) { /* {{{ */
 | ||
| 		$objArr = [];
 | ||
| 		if($type == 'd') {
 | ||
| 			if(($c = $parent->hasDocuments()) < 200)
 | ||
| 				$objArr = $parent->getDocuments('s');
 | ||
| 			$minmax = $parent->getDocumentsMinMax();
 | ||
| 		} elseif($type = 'f') {
 | ||
| 			if(($c = $parent->hasSubFolders()) < 200)
 | ||
| 				$objArr = $parent->getSubFolders('s');
 | ||
| 			$minmax = $parent->getFoldersMinMax();
 | ||
| 		} else
 | ||
| 			return '';
 | ||
| 
 | ||
| 		if ($objArr) {
 | ||
| 			$min = $minmax['min']-1.0;
 | ||
| 			$max = $minmax['max']+1.0;
 | ||
| 		}
 | ||
| 		else {
 | ||
| 			$min = (float) $minmax['min'];
 | ||
| 			$max = $minmax['max']+1.0;
 | ||
| 		}
 | ||
| 		$content = "<select class=\"form-control chzn-select\" data-allow-clear=\"false\" name=\"sequence\">\n";
 | ||
| 		if ($keepID != -1) {
 | ||
| 			$content .= "  <option value=\"keep\">" . getMLText("seq_keep");
 | ||
| 		}
 | ||
| 		if($this->params['defaultposition'] != 'start')
 | ||
| 			$content .= "  <option value=\"".$max."\">" . getMLText("seq_end");
 | ||
| 		if ($c > 0) {
 | ||
| 			$content .= "  <option value=\"".$min."\">" . getMLText("seq_start");
 | ||
| 		}
 | ||
| 		if($this->params['defaultposition'] == 'start')
 | ||
| 			$content .= "  <option value=\"".$max."\">" . getMLText("seq_end");
 | ||
| 		for ($i = 0; $i < count($objArr) - 1; $i++) {
 | ||
| 			if (($objArr[$i]->getID() == $keepID) || (($i + 1 < count($objArr)) && ($objArr[$i+1]->getID() == $keepID))) {
 | ||
| 				continue;
 | ||
| 			}
 | ||
| 			$index = ($objArr[$i]->getSequence() + $objArr[$i+1]->getSequence()) / 2;
 | ||
| 			$content .= "  <option value=\"".$index."\">" . getMLText("seq_after", array("prevname" => htmlspecialchars($objArr[$i]->getName())));
 | ||
| 		}
 | ||
| 		$content .= "</select>";
 | ||
| 		return $content;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function getDocumentChooserHtml($form, $default=false, $formname='', $skiptree=false) { /* {{{ */
 | ||
| 		if(!$formname)
 | ||
| 			$formname = "docid";
 | ||
| 		$formid = md5($formname.$form);
 | ||
| 
 | ||
| 		$content = '';
 | ||
| 		$content .= "<input type=\"hidden\" class=\"fileupload-group\" id=\"".$formid."\" name=\"".$formname."\" data-target-highlight=\"choosedocsearch".$formid."\" value=\"". ($default ? $default->getID() : "") ."\">";
 | ||
| 		$content .= "<div class=\"input-group\">\n";
 | ||
| 		$content .= "<input class=\"form-control\" type=\"text\" id=\"choosedocsearch".$formid."\" data-target=\"".$formid."\" data-provide=\"typeahead\" name=\"docname".$formid."\"value=\"" . (($default) ? htmlspecialchars($default->getName()) : "") ."\" placeholder=\"".getMLText('type_to_search')."\" autocomplete=\"off\" />";
 | ||
| 		$content .= '<div class="input-group-append">';
 | ||
| 		$content .= "<button type=\"button\" class=\"btn btn-secondary\" id=\"cleardocument".$form."\" data-target=\"".$formid."\"><i class=\"fa fa-remove\"></i></button>";
 | ||
| 		if(!$skiptree)
 | ||
| 			$content .= $this->getModalBoxLink(
 | ||
| 				array(
 | ||
| 					'target' => 'docChooser'.$formid,
 | ||
| 					'remote' => $this->params['settings']->_httpRoot."out/out.DocumentChooser.php?form=".$formid."&folderid=".$this->params['dms']->getRootFolder()->getId(),
 | ||
| 					'class' => 'btn btn-secondary',
 | ||
| 					'title' => getMLText('document').'…'
 | ||
| 				));
 | ||
| 		$content .= "</div>\n";
 | ||
| 		$content .= "</div>\n";
 | ||
| 		if(!$skiptree)
 | ||
| 			$content .= $this->getModalBox(
 | ||
| 				array(
 | ||
| 					'id' => 'docChooser'.$formid,
 | ||
| 					'title' => getMLText('choose_target_document'),
 | ||
| 					'buttons' => array(
 | ||
| 						array('title'=>getMLText('close'))
 | ||
| 					)
 | ||
| 				));
 | ||
| 		return $content;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function printDocumentChooserHtml($formName) { /* {{{ */
 | ||
| 		echo self::getDocumentChooserHtml($formName);
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * This function is deprecated. Don't use it anymore. There is a generic
 | ||
| 	 * folderSelected and documentSelected function in application.js
 | ||
| 	 * If you need extra functions to be called then define them in your own js code
 | ||
| 	 */
 | ||
| 	function printDocumentChooserJs($form, $formname='') { /* {{{ */
 | ||
| 		if(!$formname)
 | ||
| 			$formname = "docid";
 | ||
| 		$formid = md5($formname.$form);
 | ||
| ?>
 | ||
| function documentSelected<?php echo $formid ?>(id, name) {
 | ||
| 	$('#<?php echo $formid ?>').val(id);
 | ||
| 	$('#choosedocsearch<?php echo $formid ?>').val(name);
 | ||
| 	$('#docChooser<?php echo $formid ?>').modal('hide');
 | ||
| }
 | ||
| function folderSelected<?php echo $formid ?>(id, name) {
 | ||
| }
 | ||
| <?php
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function printDocumentChooser($form) { /* {{{ */
 | ||
| 		$this->printDocumentChooserHtml($form);
 | ||
| ?>
 | ||
| 		<script language="JavaScript">
 | ||
| <?php
 | ||
| 		$this->printDocumentChooserJs($form);
 | ||
| ?>
 | ||
| 		</script>
 | ||
| <?php
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function getFolderChooserHtml($form, $accessMode, $exclude = -1, $default = false, $formname = '', $skiptree = false) { /* {{{ */
 | ||
| 		if(!$formname)
 | ||
| 			$formname = "targetid";
 | ||
| 		$formid = md5($formname.$form);
 | ||
| 		$content = '';
 | ||
| 		$content .= "<input type=\"hidden\" id=\"".$formid."\" name=\"".$formname."\" value=\"". ($default ? $default->getID() : "") ."\" data-target-highlight=\"choosefoldersearch".$formid."\">";
 | ||
| 		$content .= "<div class=\"input-group\">\n";
 | ||
| 		$content .= "<input class=\"form-control\" type=\"text\" id=\"choosefoldersearch".$formid."\" data-target=\"".$formid."\" data-provide=\"typeahead\" name=\"targetname".$formid."\" value=\"". (($default) ? htmlspecialchars($default->getName()) : "") ."\" placeholder=\"".getMLText('type_to_search')."\" autocomplete=\"off\" target=\"".$formid."\"/>";
 | ||
| 		$content .= '<div class="input-group-append">';
 | ||
| 		$content .= "<button type=\"button\" class=\"btn btn-secondary\" id=\"clearfolder".$form."\" data-target=\"".$formid."\"><i class=\"fa fa-remove\"></i></button>";
 | ||
| 		if(!$skiptree) {
 | ||
| 			$content .= $this->getModalBoxLink(
 | ||
| 				array(
 | ||
| 					'target' => 'folderChooser'.$formid,
 | ||
| 					'remote' => $this->params['settings']->_httpRoot."out/out.FolderChooser.php?form=".$formid."&mode=".$accessMode."&exclude=".$exclude,
 | ||
| 					'class' => 'btn btn-secondary',
 | ||
| 					'title' => getMLText('folder').'…'
 | ||
| 				));
 | ||
| 		}
 | ||
| 		$content .= "</div>\n";
 | ||
| 		$content .= "</div>\n";
 | ||
| 		if(!$skiptree) {
 | ||
| 			$content .= $this->getModalBox(
 | ||
| 				array(
 | ||
| 					'id' => 'folderChooser'.$formid,
 | ||
| 					'title' => getMLText('choose_target_folder'),
 | ||
| 					'buttons' => array(
 | ||
| 						array('title'=>getMLText('close'))
 | ||
| 					)
 | ||
| 				));
 | ||
| 		}
 | ||
| 		return $content;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function printFolderChooserHtml($form, $accessMode, $exclude = -1, $default = false, $formname = '') { /* {{{ */
 | ||
| 		echo self::getFolderChooserHtml($form, $accessMode, $exclude, $default, $formname);
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * This function is deprecated. Don't use it anymore. There is a generic
 | ||
| 	 * folderSelected and documentSelected function in application.js
 | ||
| 	 * If you need extra functions to be called then define them in your own js code
 | ||
| 	 */
 | ||
| 	function printFolderChooserJs($form, $formname='') { /* {{{ */
 | ||
| 		if(!$formname)
 | ||
| 			$formname = "targetid";
 | ||
| 		$formid = md5($formname.$form);
 | ||
| ?>
 | ||
| function folderSelected<?php echo $formid ?>(id, name) {
 | ||
| 	$('#<?php echo $formid ?>').val(id);
 | ||
| 	$('#choosefoldersearch<?php echo $formid ?>').val(name);
 | ||
| 	$('#folderChooser<?php echo $formid ?>').modal('hide');
 | ||
| }
 | ||
| /*
 | ||
| $(document).ready(function() {
 | ||
| 	$('#clearfolder<?php print $formid ?>').click(function(ev) {
 | ||
| 		$('#choosefoldersearch<?php echo $formid ?>').val('');
 | ||
| 		$('#<?php echo $formid ?>').val('');
 | ||
| 	});
 | ||
| });
 | ||
| */
 | ||
| <?php
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function printFolderChooser($form, $accessMode, $exclude = -1, $default = false, $formname='') { /* {{{ */
 | ||
| 		$this->printFolderChooserHtml($form, $accessMode, $exclude, $default, $formname);
 | ||
| ?>
 | ||
| 		<script language="JavaScript">
 | ||
| <?php
 | ||
| 		$this->printFolderChooserJs($form, $formname);
 | ||
| ?>
 | ||
| 		</script>
 | ||
| <?php
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function printKeywordChooserHtml($formName, $keywords='', $fieldname='keywords') { /* {{{ */
 | ||
| 		echo self::getKeywordChooserHtml($formName, $keywords, $fieldname); 
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function getKeywordChooserHtml($formName, $keywords='', $fieldname='keywords') { /* {{{ */
 | ||
| 		$strictformcheck = $this->params['strictformcheck'];
 | ||
| 		$content = '';
 | ||
| 		$content .= '
 | ||
| 		    <div class="input-group">
 | ||
| 				<input class="form-control" type="text" name="'.$fieldname.'" id="'.$fieldname.'" value="'.htmlspecialchars($keywords).'"'.($strictformcheck ? ' required="required"' : '').' />
 | ||
| 		    <div class="input-group-append">';
 | ||
| 		$content .= $this->getModalBoxLink(
 | ||
| 			array(
 | ||
| 				'target' => 'keywordChooser',
 | ||
| 				'remote' => $this->params['settings']->_httpRoot."out/out.KeywordChooser.php?target=".$formName,
 | ||
| 				'class' => 'btn btn-secondary',
 | ||
| 				'title' => getMLText('keywords').'…'
 | ||
| 			));
 | ||
| 		$content .= '
 | ||
| 			</div>
 | ||
| 			</div>
 | ||
| ';
 | ||
| 		$content .= $this->getModalBox(
 | ||
| 			array(
 | ||
| 				'id' => 'keywordChooser',
 | ||
| 				'title' => getMLText('use_default_keywords'),
 | ||
| 				'buttons' => array(
 | ||
| 					array('id'=>'acceptkeywords', 'title'=>getMLText('save')),
 | ||
| 					array('title'=>getMLText('close')),
 | ||
| 				)
 | ||
| 			));
 | ||
| 		return $content;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function printKeywordChooserJs($formName) { /* {{{ */
 | ||
| ?>
 | ||
| $(document).ready(function() {
 | ||
| 	$('#acceptkeywords').click(function(ev) {
 | ||
| 		acceptKeywords();
 | ||
| 	});
 | ||
| });
 | ||
| <?php
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function printKeywordChooser($formName, $keywords='', $fieldname='keywords') { /* {{{ */
 | ||
| 		$this->printKeywordChooserHtml($formName, $keywords, $fieldname);
 | ||
| ?>
 | ||
| 		<script language="JavaScript">
 | ||
| <?php
 | ||
| 		$this->printKeywordChooserJs($formName);
 | ||
| ?>
 | ||
| 		</script>
 | ||
| <?php
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Output a single attribute in the document info section
 | ||
| 	 *
 | ||
| 	 * @param object $attribute attribute
 | ||
| 	 */
 | ||
| 	protected function printAttributeValue($attribute) { /* {{{ */
 | ||
| 		echo self::getAttributeValue($attribute);
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function getAttributeValue($attribute) { /* {{{ */
 | ||
| 		$dms = $this->params['dms'];
 | ||
| 		$attrdef = $attribute->getAttributeDefinition();
 | ||
| 		switch($attrdef->getType()) {
 | ||
| 		case SeedDMS_Core_AttributeDefinition::type_url:
 | ||
| 			$attrs = $attribute->getValueAsArray();
 | ||
| 			$tmp = array();
 | ||
| 			foreach($attrs as $attr) {
 | ||
| 				$tmp[] = '<a href="'.htmlspecialchars($attr).'">'.htmlspecialchars($attr).'</a>';
 | ||
| 			}
 | ||
| 			return implode('<br />', $tmp);
 | ||
| 			break;
 | ||
| 		case SeedDMS_Core_AttributeDefinition::type_email:
 | ||
| 			$attrs = $attribute->getValueAsArray();
 | ||
| 			$tmp = array();
 | ||
| 			foreach($attrs as $attr) {
 | ||
| 				$tmp[] = '<a mailto="'.htmlspecialchars($attr).'">'.htmlspecialchars($attr).'</a>';
 | ||
| 			}
 | ||
| 			return implode('<br />', $tmp);
 | ||
| 			break;
 | ||
| 		case SeedDMS_Core_AttributeDefinition::type_folder:
 | ||
| 			$attrs = $attribute->getValueAsArray();
 | ||
| 			$tmp = array();
 | ||
| 			foreach($attrs as $targetfolder) {
 | ||
| 				$tmp[] = '<a href="'.$this->params['settings']->_httpRoot.'out/out.ViewFolder.php?folderid='.$targetfolder->getId().'">'.htmlspecialchars($targetfolder->getName()).'</a>';
 | ||
| 			}
 | ||
| 			return implode('<br />', $tmp);
 | ||
| 			break;
 | ||
| 		case SeedDMS_Core_AttributeDefinition::type_document:
 | ||
| 			$attrs = $attribute->getValueAsArray();
 | ||
| 			$tmp = array();
 | ||
| 			foreach($attrs as $targetdoc) {
 | ||
| 				$tmp[] = '<a href="'.$this->params['settings']->_httpRoot.'out/out.ViewDocument.php?documentid='.$targetdoc->getId().'">'.htmlspecialchars($targetdoc->getName()).'</a>';
 | ||
| 			}
 | ||
| 			return implode('<br />', $tmp);
 | ||
| 			break;
 | ||
| 		case SeedDMS_Core_AttributeDefinition::type_user:
 | ||
| 			$attrs = $attribute->getValueAsArray();
 | ||
| 			$tmp = array();
 | ||
| 			foreach($attrs as $curuser) {
 | ||
| 				$tmp[] = htmlspecialchars($curuser->getFullname()." (".$curuser->getLogin().")");
 | ||
| 			}
 | ||
| 			return implode('<br />', $tmp);
 | ||
| 			break;
 | ||
| 		case SeedDMS_Core_AttributeDefinition::type_group:
 | ||
| 			$attrs = $attribute->getValueAsArray();
 | ||
| 			$tmp = array();
 | ||
| 			foreach($attrs as $curgroup) {
 | ||
| 				$tmp[] = htmlspecialchars($curgroup->getName());
 | ||
| 			}
 | ||
| 			return implode('<br />', $tmp);
 | ||
| 			break;
 | ||
| 		case SeedDMS_Core_AttributeDefinition::type_date:
 | ||
| 			$attrs = $attribute->getValueAsArray();
 | ||
| 			$tmp = array();
 | ||
| 			foreach($attrs as $attr) {
 | ||
| 				$tmp[] = getReadableDate($attr);
 | ||
| 			}
 | ||
| 			return implode(', ', $tmp);
 | ||
| 			break;
 | ||
| 		default:
 | ||
| 			return htmlspecialchars(implode(', ', $attribute->getValueAsArray()));
 | ||
| 		}
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function printAttributeEditField($attrdef, $attribute, $fieldname='attributes', $norequire=false, $namepostfix='', $alwaysmultiple=false) { /* {{{ */
 | ||
| 		echo self::getAttributeEditField($attrdef, $attribute, $fieldname, $norequire, $namepostfix, $alwaysmultiple);
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function getAttributeEditField($attrdef, $attribute, $fieldname='attributes', $norequire=false, $namepostfix='', $alwaysmultiple=false) { /* {{{ */
 | ||
| 		$dms = $this->params['dms'];
 | ||
| 		$attr_id = $fieldname.'_'.$attrdef->getId().($namepostfix ? '_'.$namepostfix : '');
 | ||
| 		$attr_name = $fieldname.'['.$attrdef->getId().']'.($namepostfix ? '['.$namepostfix.']' : '');
 | ||
| 		$content = '';
 | ||
| 		switch($attrdef->getType()) {
 | ||
| 		case SeedDMS_Core_AttributeDefinition::type_boolean:
 | ||
| 			$objvalue = $attribute ? (is_object($attribute) ? $attribute->getValue() : $attribute) : '';
 | ||
| 			$content .= "<input type=\"hidden\" name=\"".$attr_name."\" value=\"\" />";
 | ||
| 			$content .= "<input type=\"checkbox\" id=\"".$attr_id."\" name=\"".$attr_name."\" value=\"1\" ".($objvalue ? 'checked' : '')." />";
 | ||
| 			$content .= '<label class="form-check-label" for="'.$attr_id.'"></label>';
 | ||
| 			break;
 | ||
| 		case SeedDMS_Core_AttributeDefinition::type_date:
 | ||
| 			$objvalue = $attribute ? getReadableDate((is_object($attribute) ? $attribute->getValue() : $attribute)) : '';
 | ||
| 			$dateformat = getConvertDateFormat($this->params['settings']->_dateformat);
 | ||
| 			$content = '
 | ||
| <div class="input-group date">
 | ||
| 	<input type="text" class="form-control" id="'.$attr_id.'" name="'.$attr_name.'" value="'.($objvalue ? $objvalue : '').'" data-date="'.getReadableDate().'" data-date-format="'.$dateformat.'" data-date-language="'.str_replace('_', '-', $this->params['session']->getLanguage()).'" data-date-autoclose="true" data-provide="datepicker">
 | ||
| 	<div class="input-group-append">
 | ||
| 		<span class="input-group-text"><i class="fa fa-calendar"></i></span>
 | ||
| 	</div>
 | ||
| </div>
 | ||
| ';
 | ||
| 			break;
 | ||
| 		case SeedDMS_Core_AttributeDefinition::type_email:
 | ||
| 			$objvalue = $attribute ? (is_object($attribute) ? $attribute->getValue() : $attribute) : '';
 | ||
| 			$content .= "<input type=\"text\" class=\"form-control\" id=\"".$attr_id."\" name=\"".$attr_name."\" value=\"".htmlspecialchars($objvalue)."\"".((!$norequire && $attrdef->getMinValues() > 0) ? ' required="required"' : '').' data-rule-email="true"'." />";
 | ||
| 			break;
 | ||
| 		/* case SeedDMS_Core_AttributeDefinition::type_float:
 | ||
| 			$objvalue = $attribute ? (is_object($attribute) ? $attribute->getValue() : $attribute) : '';
 | ||
| 			$content .= "<input type=\"text\" class=\"form-control\" id=\"".$attr_id."\" name=\"".$attr_name."\" value=\"".htmlspecialchars($objvalue)."\"".((!$norequire && $attrdef->getMinValues() > 0) ? ' required="required"' : '')." data-rule-number=\"true\"/>";
 | ||
| 			break; */
 | ||
| 		case SeedDMS_Core_AttributeDefinition::type_folder:
 | ||
| 			$target = $attribute ? $attribute->getValue() : null;
 | ||
| 			$content .= $this->getFolderChooserHtml("attr".$attrdef->getId(), M_READWRITE, -1, $target, $attr_name, false);
 | ||
| 			break;
 | ||
| 		case SeedDMS_Core_AttributeDefinition::type_document:
 | ||
| 			$target = $attribute ? $attribute->getValue() : null;
 | ||
| 			$content .= $this->getDocumentChooserHtml("attr".$attrdef->getId(), $target, $attr_name);
 | ||
| 			break;
 | ||
| 		case SeedDMS_Core_AttributeDefinition::type_user:
 | ||
| 			$target = $attribute ? $attribute->getValueAsArray() : [];
 | ||
| 			$objvalue = [];
 | ||
| 			foreach($target as $t)
 | ||
| 				$objvalue[] = $t->getId();
 | ||
| 			$users = $dms->getAllUsers();
 | ||
| 			if($users) {
 | ||
| 				$allowempty = $attrdef->getMinValues() == 0;
 | ||
| 				$allowmultiple = $attrdef->getMultipleValues() || $alwaysmultiple;
 | ||
| 				$content .= "<select class=\"form-control chzn-select\"".($allowempty ? " data-allow-clear=\"true\"" : "")."\" id=\"".$attr_id."\" name=\"".$attr_name.($allowmultiple ? '[]' : '')."\"".($allowmultiple ? " multiple" : "")." data-placeholder=\"".getMLText("select_user")."\">";
 | ||
| 				if($allowempty)
 | ||
| 					$content .= "<option value=\"\"></option>";
 | ||
| 				foreach($users as $curuser) {
 | ||
| 					$content .= "<option value=\"".$curuser->getID()."\"";
 | ||
| 					if(in_array($curuser->getID(), $objvalue))
 | ||
| 						$content .= " selected";
 | ||
| 					$content .= ">".htmlspecialchars($curuser->getLogin()." - ".$curuser->getFullName())."</option>";
 | ||
| 				}
 | ||
| 				$content .= "</select>";
 | ||
| 			} else {
 | ||
| 				$content .= getMLText('no_users');
 | ||
| 			}
 | ||
| 			break;
 | ||
| 		case SeedDMS_Core_AttributeDefinition::type_group:
 | ||
| 			$target = $attribute ? $attribute->getValueAsArray() : [];
 | ||
| 			$objvalue = [];
 | ||
| 			foreach($target as $t)
 | ||
| 				$objvalue[] = $t->getId();
 | ||
| 			$groups = $dms->getAllGroups();
 | ||
| 			if($groups) {
 | ||
| 				$allowempty = $attrdef->getMinValues() == 0;
 | ||
| 				$allowmultiple = $attrdef->getMultipleValues() || $alwaysmultiple;
 | ||
| 				$content .= "<select class=\"form-control chzn-select\"".($allowempty ? " data-allow-clear=\"true\"" : "")."\" id=\"".$attr_id."\" name=\"".$attr_name.($allowmultiple ? '[]' : '')."\"".($allowmultiple ? " multiple" : "")." data-placeholder=\"".getMLText("select_group")."\">";
 | ||
| 				if($allowempty)
 | ||
| 					$content .= "<option value=\"\"></option>";
 | ||
| 				foreach($groups as $curgroup) {
 | ||
| 					$content .= "<option value=\"".$curgroup->getID()."\"";
 | ||
| 					if(in_array($curgroup->getID(), $objvalue))
 | ||
| 						$content .= " selected";
 | ||
| 					$content .= ">".htmlspecialchars($curgroup->getName())."</option>";
 | ||
| 				}
 | ||
| 				$content .= "</select>";
 | ||
| 			} else {
 | ||
| 				$content .= getMLText('no_groups');
 | ||
| 			}
 | ||
| 			break;
 | ||
| 		default:
 | ||
| 			if($valueset = $attrdef->getValueSetAsArray()) {
 | ||
| 				$content .= "<input type=\"hidden\" name=\"".$attr_name."\" value=\"\"/>";
 | ||
| 				$content .= "<select id=\"".$attr_id."\" name=\"".$attr_name;
 | ||
| 				if($attrdef->getMultipleValues() || $alwaysmultiple) {
 | ||
| 					$content .= "[]\" multiple";
 | ||
| 				} else {
 | ||
| 					$content .= "\" data-allow-clear=\"true\"";
 | ||
| 				}
 | ||
| 				$content .= "".((!$norequire && $attrdef->getMinValues() > 0) ? ' required="required"' : '')." class=\"form-control chzn-select\" data-placeholder=\"".getMLText("select_value")."\">";
 | ||
| 				if(!$attrdef->getMultipleValues() && !$alwaysmultiple) {
 | ||
| 					$content .= "<option value=\"\"></option>";
 | ||
| 				}
 | ||
| 				$objvalue = $attribute ? (is_object($attribute) ? $attribute->getValueAsArray() : $attribute) : array();
 | ||
| 				foreach($valueset as $value) {
 | ||
| 					if($value) {
 | ||
| 						$content .= "<option value=\"".htmlspecialchars($value)."\"";
 | ||
| 						if(is_array($objvalue) && in_array($value, $objvalue))
 | ||
| 							$content .= " selected";
 | ||
| 						elseif($value == $objvalue)
 | ||
| 							$content .= " selected";
 | ||
| 						$content .= ">".htmlspecialchars($value)."</option>";
 | ||
| 					}
 | ||
| 				}
 | ||
| 				$content .= "</select>";
 | ||
| 			} else {
 | ||
| 				$objvalue = $attribute ? (is_object($attribute) ? $attribute->getValue() : $attribute) : '';
 | ||
| 				if(strlen($objvalue) > 80) {
 | ||
| 					$content .= "<textarea class=\"form-control\" id=\"".$attr_id."\" class=\"input-xxlarge\" name=\"".$attr_name."\"".((!$norequire && $attrdef->getMinValues() > 0) ? ' required="required"' : '').">".htmlspecialchars($objvalue)."</textarea>";
 | ||
| 				} else {
 | ||
| 					$content .= "<input type=\"text\" class=\"form-control\" id=\"".$attr_id."\" name=\"".$attr_name."\" value=\"".htmlspecialchars($objvalue)."\"".((!$norequire && $attrdef->getMinValues() > 0) ? ' required="required"' : '').(in_array($attrdef->getType(), [SeedDMS_Core_AttributeDefinition::type_int, SeedDMS_Core_AttributeDefinition::type_float]) ? ' data-rule-digits="true"' : '')." />";
 | ||
| 				}
 | ||
| 			}
 | ||
| 			break;
 | ||
| 		}
 | ||
| 		return $content;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function printDropFolderChooserHtml($formName, $dropfolderfile="", $showfolders=0, $recursive=1) { /* {{{ */
 | ||
| 		echo self::getDropFolderChooserHtml($formName, $dropfolderfile, $showfolders, $recursive);
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function getDropFolderChooserHtml($formName, $dropfolderfile="", $showfolders=0, $recursive=1) { /* {{{ */
 | ||
| 		$content =  "<div class=\"input-group\">\n";
 | ||
| 		$content .= "<input class=\"form-control fileupload-group\" readonly type=\"text\" id=\"dropfolderfile".$formName."\" name=\"dropfolderfile".$formName."\" value=\"".htmlspecialchars($dropfolderfile)."\">";
 | ||
| 		$content .= '<div class="input-group-append">';
 | ||
| 		$content .= "<button type=\"button\" class=\"btn btn-secondary\" id=\"clearfilename".$formName."\"><i class=\"fa fa-remove\"></i></button>";
 | ||
| 		$content .= $this->getModalBoxLink(
 | ||
| 			array(
 | ||
| 				'target' => 'dropfolderChooser',
 | ||
| 				'remote' => $this->params['settings']->_httpRoot."out/out.DropFolderChooser.php?form=".$formName."&dropfolderfile=".urlencode($dropfolderfile)."&showfolders=".$showfolders."&recursive=".$recursive,
 | ||
| 				'class' => 'btn btn-secondary',
 | ||
| 				'title' => ($showfolders ? getMLText("choose_target_folder"): getMLText("choose_target_file")).'…'
 | ||
| 			));
 | ||
| 		$content .= "</div>\n";
 | ||
| 		$content .= "</div>\n";
 | ||
| 		$content .= $this->getModalBox(
 | ||
| 			array(
 | ||
| 				'id' => 'dropfolderChooser',
 | ||
| 				'title' => ($showfolders ? getMLText("choose_target_folder"): getMLText("choose_target_file")),
 | ||
| 				'buttons' => array(
 | ||
| 					array('title'=>getMLText('close')),
 | ||
| 				)
 | ||
| 			));
 | ||
| 		return $content;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function printDropFolderChooserJs($formName, $showfolders=0) { /* {{{ */
 | ||
| ?>
 | ||
| /* Set up a callback which is called when a folder in the tree is selected */
 | ||
| modalDropfolderChooser = $('#dropfolderChooser');
 | ||
| function fileSelected(name, form) {
 | ||
| //	$('#dropfolderfile<?php echo $formName ?>').val(name);
 | ||
| 	$('#dropfolderfile'+form).val(name);
 | ||
| 	modalDropfolderChooser.modal('hide');
 | ||
| }
 | ||
| <?php if($showfolders) { ?>
 | ||
| function folderSelected(name, form) {
 | ||
| //	$('#dropfolderfile<?php echo $formName ?>').val(name);
 | ||
| 	$('#dropfolderfile'+form).val(name);
 | ||
| 	modalDropfolderChooser.modal('hide');
 | ||
| }
 | ||
| <?php } ?>
 | ||
| $(document).ready(function() {
 | ||
| 	$('#clearfilename<?php print $formName ?>').click(function(ev) {
 | ||
| 		$('#dropfolderfile<?php echo $formName ?>').val('');
 | ||
| 	});
 | ||
| });
 | ||
| <?php
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function printDropFolderChooser($formName, $dropfolderfile="", $showfolders=0, $recursive=1) { /* {{{ */
 | ||
| 		$this->printDropFolderChooserHtml($formName, $dropfolderfile, $showfolders, $recursive);
 | ||
| ?>
 | ||
| 		<script language="JavaScript">
 | ||
| <?php
 | ||
| 		$this->printDropFolderChooserJs($formName, $showfolders);
 | ||
| ?>
 | ||
| 		</script>
 | ||
| <?php
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function getImgPath($img) { /* {{{ */
 | ||
| 
 | ||
| //		if ( is_file($this->imgpath.$img) ) {
 | ||
| 			return $this->imgpath.$img;
 | ||
| //		}
 | ||
| 		return "";
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function getCountryFlag($lang) { /* {{{ */
 | ||
| 		switch($lang) {
 | ||
| 		case "en_GB":
 | ||
| 			return 'flags/gb.png';
 | ||
| 			break;
 | ||
| 		default:
 | ||
| 			return 'flags/'.substr($lang, 0, 2).'.png';
 | ||
| 		}
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function printImgPath($img) { /* {{{ */
 | ||
| 		print $this->getImgPath($img);
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function infoMsg($msg) { /* {{{ */
 | ||
| 		echo "<div class=\"alert alert-info\">\n";
 | ||
| 		echo $msg;
 | ||
| 		echo "</div>\n";
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function warningMsg($msg) { /* {{{ */
 | ||
| 		echo "<div class=\"alert alert-warning\">\n";
 | ||
| 		echo $msg;
 | ||
| 		echo "</div>\n";
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function errorMsg($msg) { /* {{{ */
 | ||
| 		echo "<div class=\"alert alert-danger\">\n";
 | ||
| 		echo $msg;
 | ||
| 		echo "</div>\n";
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function successMsg($msg) { /* {{{ */
 | ||
| 		echo "<div class=\"alert alert-success\">\n";
 | ||
| 		echo $msg;
 | ||
| 		echo "</div>\n";
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function ___exitError($pagetitle, $error, $noexit=false, $plain=false) { /* {{{ */
 | ||
| 
 | ||
| 		/* This is just a hack to prevent creation of js files in an error
 | ||
| 		 * case, because they will contain this error page again. It would be much
 | ||
| 		 * better, if there was extra error() function similar to show() and calling
 | ||
| 		 * $view() after setting the action to 'error'. This would also allow to
 | ||
| 		 * set separate error pages for each view.
 | ||
| 		 */
 | ||
| 		if(!$noexit && isset($_REQUEST['action'])) {
 | ||
| 			if(in_array($_REQUEST['action'], array('js', 'footerjs'))) {
 | ||
| 				exit;
 | ||
| 			}
 | ||
| 
 | ||
| 			if($_REQUEST['action'] == 'webrootjs') {
 | ||
| 				$this->webrootjs();
 | ||
| 				exit;
 | ||
| 			}
 | ||
| 		}
 | ||
| 
 | ||
| 		if(!$plain) {	
 | ||
| 			$this->htmlStartPage($pagetitle);
 | ||
| 			$this->globalNavigation();
 | ||
| 			$this->contentStart();
 | ||
| 		}
 | ||
| 
 | ||
| 		$html = '';
 | ||
| 		$html .= "<h4>".getMLText('error')."!</h4>";
 | ||
| 		$html .= htmlspecialchars($error);
 | ||
| 		$this->errorMsg($html);
 | ||
| 		if(!$plain) {	
 | ||
| 			print "<div><button class=\"btn history-back\">".getMLText('back')."</button></div>";
 | ||
| 
 | ||
| 			$this->contentEnd();
 | ||
| 			$this->htmlEndPage();
 | ||
| 		}
 | ||
| 		
 | ||
| 		add_log_line(" UI::exitError error=".$error." pagetitle=".$pagetitle, PEAR_LOG_ERR);
 | ||
| 
 | ||
| 		if($noexit)
 | ||
| 			return;
 | ||
| 
 | ||
| 		exit;	
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function printNewTreeNavigation($folderid=0, $accessmode=M_READ, $showdocs=0, $formid='form1', $expandtree=0, $orderby='') { /* {{{ */
 | ||
| 		$this->printNewTreeNavigationHtml($folderid, $accessmode, $showdocs, $formid, $expandtree, $orderby);
 | ||
| ?>
 | ||
| 		<script language="JavaScript">
 | ||
| <?php
 | ||
| 		$this->printNewTreeNavigationJs($folderid, $accessmode, $showdocs, $formid, $expandtree, $orderby);
 | ||
| ?>
 | ||
| 	</script>
 | ||
| <?php
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function printNewTreeNavigationHtml($folderid=0, $accessmode=M_READ, $showdocs=0, $formid='form1', $expandtree=0, $orderby='') { /* {{{ */
 | ||
| 		//echo "<div id=\"jqtree".$formid."\" style=\"margin-left: 10px;\" data-url=\"../op/op.Ajax.php?command=subtree&showdocs=".$showdocs."&orderby=".$orderby."\"></div>\n";
 | ||
| 		echo "<div id=\"jqtree".$formid."\" style=\"margin-left: 10px;\" data-url=\"".$_SERVER['SCRIPT_NAME']."?action=subtree\"></div>\n";
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Create a tree of folders using jqtree.
 | ||
| 	 *
 | ||
| 	 * The tree can contain folders only or include documents.
 | ||
| 	 *
 | ||
| 	 * @param integer $folderid current folderid. If set the tree will be
 | ||
| 	 *   folded out and the all folders in the path will be visible
 | ||
| 	 * @param integer $accessmode use this access mode when retrieving folders
 | ||
| 	 *   and documents shown in the tree
 | ||
| 	 * @param boolean $showdocs set to true if tree shall contain documents
 | ||
| 	 *   as well.
 | ||
| 	 * @param integer $expandtree level to which the tree shall be opened
 | ||
| 	 * @param boolean $partialtree set to true if the given folder is the start folder
 | ||
| 	 */
 | ||
| 	function printNewTreeNavigationJs($folderid=0, $accessmode=M_READ, $showdocs=0, $formid='form1', $expandtree=0, $orderby='', $partialtree=false) { /* {{{ */
 | ||
| 		function jqtree($path, $folder, $user, $accessmode, $showdocs=1, $expandtree=0, $orderby='', $level=0) { /* {{{ */
 | ||
| 			$orderdir = (isset($orderby[1]) ? ($orderby[1] == 'd' ? 'desc' : 'asc') : 'asc');
 | ||
| 			if($path/* || $expandtree>=$level*/) {
 | ||
| 				if($path)
 | ||
| 					$pathfolder = array_shift($path);
 | ||
| 				$children = array();
 | ||
| 				if($expandtree) {
 | ||
| 					$subfolders = $folder->getSubFolders(isset($orderby[0]) ? $orderby[0] : '', $orderdir);
 | ||
| 					$subfolders = SeedDMS_Core_DMS::filterAccess($subfolders, $user, $accessmode);
 | ||
| 				} else {
 | ||
| 					$subfolders = array($pathfolder);
 | ||
| 				}
 | ||
| 				foreach($subfolders as $subfolder) {
 | ||
| 					$node = array('label'=>$subfolder->getName(), 'id'=>$subfolder->getID(), 'load_on_demand'=>(1 && ($subfolder->hasSubFolders() || ($subfolder->hasDocuments() && $showdocs))) ? true : false, 'is_folder'=>true);
 | ||
| 					/* if the subfolder is in the path then further unfold the tree. */
 | ||
| 					if(/*$expandtree>=$level ||*/ $path && ($path[0]->getID() == $subfolder->getID())) {
 | ||
| 						$node['children'] = jqtree($path, $subfolder, $user, $accessmode, $showdocs, $expandtree, $orderby, $level+1);
 | ||
| 						if($showdocs) {
 | ||
| 							$documents = $subfolder->getDocuments(isset($orderby[0]) ? $orderby[0] : '', $orderdir);
 | ||
| 							$documents = SeedDMS_Core_DMS::filterAccess($documents, $user, $accessmode);
 | ||
| 							foreach($documents as $document) {
 | ||
| 								$node2 = array('label'=>$document->getName(), 'id'=>$document->getID(), 'load_on_demand'=>false, 'is_folder'=>false);
 | ||
| 								$node['children'][] = $node2;
 | ||
| 							}
 | ||
| 						}
 | ||
| 					}
 | ||
| 					$children[] = $node;
 | ||
| 				}
 | ||
| 				return $children;
 | ||
| 			} else {
 | ||
| 				$subfolders = $folder->getSubFolders(isset($orderby[0]) ? $orderby[0] : '', $orderdir);
 | ||
| 				$subfolders = SeedDMS_Core_DMS::filterAccess($subfolders, $user, $accessmode);
 | ||
| 				$children = array();
 | ||
| 				foreach($subfolders as $subfolder) {
 | ||
| 					$node = array('label'=>$subfolder->getName(), 'id'=>$subfolder->getID(), 'load_on_demand'=>($subfolder->hasSubFolders() || ($subfolder->hasDocuments() && $showdocs)) ? true : false, 'is_folder'=>true);
 | ||
| 					$children[] = $node;
 | ||
| 				}
 | ||
| 				return $children;
 | ||
| 			}
 | ||
| 			return array();
 | ||
| 		} /* }}} */
 | ||
| 
 | ||
| 		$orderdir = (isset($orderby[1]) ? ($orderby[1] == 'd' ? 'desc' : 'asc') : 'asc');
 | ||
| 		if($folderid && ($folder = $this->params['dms']->getFolder($folderid))) {
 | ||
| 			$path = null;
 | ||
| 			if(!$partialtree) {
 | ||
| 				$path = $folder->getPath();
 | ||
| 				/* Get the first folder (root folder) of path */
 | ||
| 				$folder = array_shift($path);
 | ||
| 			}
 | ||
| 			$node = array('label'=>$folder->getName(), 'id'=>$folder->getID(), 'load_on_demand'=>false, 'is_folder'=>true);
 | ||
| 			if(!$folder->hasSubFolders()) {
 | ||
| 				$node['load_on_demand'] = true;
 | ||
| 				$node['children'] = array();
 | ||
| 			} else {
 | ||
| 				$node['children'] = jqtree($path, $folder, $this->params['user'], $accessmode, $showdocs, 1 /*$expandtree*/, $orderby, 0);
 | ||
| 				if($showdocs) {
 | ||
| 					$documents = $folder->getDocuments(isset($orderby[0]) ? $orderby[0] : '', $orderdir);
 | ||
| 					$documents = SeedDMS_Core_DMS::filterAccess($documents, $this->params['user'], $accessmode);
 | ||
| 					foreach($documents as $document) {
 | ||
| 						$node2 = array('label'=>$document->getName(), 'id'=>$document->getID(), 'load_on_demand'=>false, 'is_folder'=>false);
 | ||
| 						$node['children'][] = $node2;
 | ||
| 					}
 | ||
| 				}
 | ||
| 			}
 | ||
| 			/* Nasty hack to remove the highest folder */
 | ||
| 			if(isset($this->params['remove_root_from_tree']) && $this->params['remove_root_from_tree']) {
 | ||
| 				foreach($node['children'] as $n)
 | ||
| 					$tree[] = $n;
 | ||
| 			} else {
 | ||
| 				$tree[] = $node;
 | ||
| 			}
 | ||
| 		} else {
 | ||
| 			if($root = $this->params['dms']->getFolder($this->params['rootfolderid']))
 | ||
| 				$tree = array(array('label'=>$root->getName(), 'id'=>$root->getID(), 'load_on_demand'=>false, 'is_folder'=>true));
 | ||
| 			else
 | ||
| 				$tree = array();
 | ||
| 		}
 | ||
| ?>
 | ||
| var data = <?php echo json_encode($tree); ?>;
 | ||
| $(function() {
 | ||
| 	const $tree = $('#jqtree<?php echo $formid ?>');
 | ||
| 	$tree.tree({
 | ||
| //		saveState: false,
 | ||
| 		selectable: false,
 | ||
| 		data: data,
 | ||
| 		saveState: 'jqtree<?php echo $formid; ?>',
 | ||
| 		openedIcon: $('<i class="fa fa-minus-circle"></i>'),
 | ||
| 		closedIcon: $('<i class="fa fa-plus-circle"></i>'),
 | ||
| /*
 | ||
| 		_onCanSelectNode: function(node) {
 | ||
| 			if(node.is_folder) {
 | ||
| 				folderSelected<?= $formid ?>(node.id, node.name);
 | ||
| 				treeFolderSelected('<?= $formid ?>', node.id, node.name);
 | ||
| 			} else {
 | ||
| 				documentSelected<?= $formid ?>(node.id, node.name);
 | ||
| 				treeDocumentSelected('<?= $formid ?>', node.id, node.name);
 | ||
| 			}
 | ||
| 		},
 | ||
| */
 | ||
| 		autoOpen: false,
 | ||
| 		drapAndDrop: true,
 | ||
| 		onCreateLi: function(node, $li) {
 | ||
| 			// Add 'icon' span before title
 | ||
| 			if(node.is_folder)
 | ||
| 				$li.find('.jqtree-title').prepend('<i class="fa fa-folder-o"></i> ').attr('data-name', node.name).attr('rel', 'folder_' + node.id).attr('formtoken', '<?php echo createFormKey(''); ?>').attr('data-uploadformtoken', '<?php echo createFormKey(''); ?>').attr('data-droptarget', 'folder_' + node.id).addClass('droptarget');
 | ||
| 			else
 | ||
| 				$li.find('.jqtree-title').prepend('<i class="fa fa-file"></i> ');
 | ||
| 		}
 | ||
| 	});
 | ||
| 	// Unfold node for currently selected folder
 | ||
| 	$('#jqtree<?php echo $formid ?>').tree('selectNode', $('#jqtree<?php echo $formid ?>').tree('getNodeById', <?php echo $folderid ?>), false, true);
 | ||
| 	$('#jqtree<?php echo $formid ?>').on(
 | ||
| 		'tree.click',
 | ||
| 		function(event) {
 | ||
| 			var node = event.node;
 | ||
| 			if(!node)
 | ||
| 				return;
 | ||
| 			if(node.is_folder) {
 | ||
| 				$('#jqtree<?php echo $formid ?>').tree('openNode', node);
 | ||
| <?php if($showdocs) { ?>
 | ||
| //			event.preventDefault();
 | ||
| 				if(typeof node.fetched == 'undefined') {
 | ||
| 					node.fetched = true;
 | ||
| 					$(this).tree('loadDataFromUrl', node, function () {
 | ||
| 						$(this).tree('openNode', node);
 | ||
| 					});
 | ||
| 				}
 | ||
| <?php } ?>
 | ||
| 				/* folderSelectedXXXX() can still be set, e.g. for the main tree
 | ||
| 				 * to update the folder list.
 | ||
| 				 */
 | ||
| 				if (typeof folderSelected<?= $formid ?> === 'function') { 
 | ||
| 					folderSelected<?= $formid ?>(node.id, node.name);
 | ||
| 				}
 | ||
| 				treeFolderSelected('<?= $formid ?>', node.id, node.name);
 | ||
| 			} else {
 | ||
| <?php if($showdocs) { ?>
 | ||
| 				if (typeof documentSelected<?= $formid ?> === 'function') { 
 | ||
| 					documentSelected<?= $formid ?>(node.id, node.name);
 | ||
| 				}
 | ||
| 				treeDocumentSelected('<?= $formid ?>', node.id, node.name);
 | ||
| <?php } ?>
 | ||
| 			}
 | ||
| 		}
 | ||
| 	);
 | ||
| 	$('#jqtree<?php echo $formid ?>').on(
 | ||
| 		'tree.contextmenu',
 | ||
| 		function(event) {
 | ||
| 			// The clicked node is 'event.node'
 | ||
| 			var node = event.node;
 | ||
| 			if(typeof node.fetched == 'undefined') {
 | ||
| 				node.fetched = true;
 | ||
| 				$(this).tree('loadDataFromUrl', node);
 | ||
| 			}
 | ||
| 			$(this).tree('openNode', node);
 | ||
| 		}
 | ||
| 	);
 | ||
| 	$("#jqtree").on('dragenter', function (e) {
 | ||
| 		attr_rel = $(e.srcElement).attr('rel');
 | ||
| 		if(typeof attr_rel == 'undefined')
 | ||
| 			return;
 | ||
| 		target_type = attr_rel.split("_")[0];
 | ||
| 		target_id = attr_rel.split("_")[1];
 | ||
| 		var node = $(this).tree('getNodeById', parseInt(target_id));
 | ||
| 		if(typeof node.fetched == 'undefined') {
 | ||
| 			node.fetched = true;
 | ||
| 			$(this).tree('loadDataFromUrl', node, function() {$(this).tree('openNode', node);});
 | ||
| 		}
 | ||
| 	});
 | ||
| });
 | ||
| <?php
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Return json data for sub tree of navigation tree
 | ||
| 	 */
 | ||
| 	function printNewTreeNavigationSubtree($folderid, $showdocs=0, $orderby='') { /* {{{ */
 | ||
| 		$dms = $this->params['dms'];
 | ||
| 		$user = $this->params['user'];
 | ||
| 
 | ||
| 		$folder = $dms->getFolder($folderid);
 | ||
| 		if (!is_object($folder)) return '';
 | ||
| 		
 | ||
| 		$subfolders = $folder->getSubFolders($orderby);
 | ||
| 		$subfolders = SeedDMS_Core_DMS::filterAccess($subfolders, $user, M_READ);
 | ||
| 		$tree = array();
 | ||
| 		foreach($subfolders as $subfolder) {
 | ||
| 			$loadondemand = $subfolder->hasSubFolders() || ($subfolder->hasDocuments() && $showdocs);
 | ||
| 			$level = array('label'=>$subfolder->getName(), 'id'=>$subfolder->getID(), 'load_on_demand'=>$loadondemand, 'is_folder'=>true);
 | ||
| 			if(!$subfolder->hasSubFolders())
 | ||
| 				$level['children'] = array();
 | ||
| 			$tree[] = $level;
 | ||
| 		}
 | ||
| 		if($showdocs) {
 | ||
| 			$documents = $folder->getDocuments($orderby);
 | ||
| 			$documents = SeedDMS_Core_DMS::filterAccess($documents, $user, M_READ);
 | ||
| 			foreach($documents as $document) {
 | ||
| 				$level = array('label'=>$document->getName(), 'id'=>$document->getID(), 'load_on_demand'=>false, 'is_folder'=>false);
 | ||
| 				$tree[] = $level;
 | ||
| 			}
 | ||
| 		}
 | ||
| 
 | ||
| 		header('Content-Type: application/json');
 | ||
| 		echo json_encode($tree);
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Deprecated!
 | ||
| 	 */
 | ||
| 	function __printTreeNavigation($folderid, $showtree){ /* {{{ */
 | ||
| 		if ($showtree==1){
 | ||
| 			$this->contentHeading("<a href=\"".$this->params['settings']->_httpRoot."out/out.ViewFolder.php?folderid=". $folderid."&showtree=0\"><i class=\"fa fa-minus-circle\"></i></a>", true);
 | ||
| 			$this->contentContainerStart();
 | ||
| ?>
 | ||
| 	<script language="JavaScript">
 | ||
| 	function folderSelected(id, name) {
 | ||
| 		window.location = '<?= $this->params['settings']->_httpRoot ?>out/out.ViewFolder.php?folderid=' + id;
 | ||
| 	}
 | ||
| 	</script>
 | ||
| <?php
 | ||
| 			$this->printNewTreeNavigation($folderid, M_READ, 0, '');
 | ||
| 			$this->contentContainerEnd();
 | ||
| 		} else {
 | ||
| 			$this->contentHeading("<a href=\"".$this->params['settings']->_httpRoot."out/out.ViewFolder.php?folderid=". $folderid."&showtree=1\"><i class=\"fa fa-plus-circle\"></i></a>", true);
 | ||
| 		}
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Print clipboard in div container
 | ||
| 	 *
 | ||
| 	 * @param array clipboard
 | ||
| 	 */
 | ||
| 	function printClipboard($clipboard, $previewer){ /* {{{ */
 | ||
| 		echo "<div id=\"clipboard-container\" class=\"_clipboard-container\">\n";
 | ||
| 		$this->contentHeading(getMLText("clipboard").'<span id="clipboard-float"><i class="fa fa-sort"></i></span>', true);
 | ||
| 		echo "<div id=\"main-clipboard\">\n";
 | ||
| ?>
 | ||
| 		<div class="ajax" data-view="Clipboard" data-action="mainClipboard"></div>
 | ||
| <?php
 | ||
| 		echo "</div>\n";
 | ||
| 		echo "</div>\n";
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Wrap text in inline editing tags
 | ||
| 	 *
 | ||
| 	 * @param string text
 | ||
| 	 */
 | ||
| 	function printInlineEdit($text, $object){ /* {{{ */
 | ||
| 		if(!empty($this->params['settings']->_inlineEditing)) {
 | ||
| 			echo "<span class=\"editable\" contenteditable=\"true\"";
 | ||
| 			if($object->isType('document'))
 | ||
| 				echo " data-document=\"".$object->getId()."\" data-formtoken=\"".createFormKey('setdocumentname')."\"";
 | ||
| 			echo ">".$text;
 | ||
| 			echo "</span>\n";
 | ||
| 		} else
 | ||
| 			echo $text;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Print button with link for deleting a document
 | ||
| 	 *
 | ||
| 	 * This button is used in document listings (e.g. on the ViewFolder page)
 | ||
| 	 * for deleting a document. In seeddms version < 4.3.9 this was just a
 | ||
| 	 * link to the out/out.RemoveDocument.php page which asks for confirmation
 | ||
| 	 * an than calls op/op.RemoveDocument.php. Starting with version 4.3.9
 | ||
| 	 * the button just opens a small popup asking for confirmation and than
 | ||
| 	 * calls the ajax command 'deletedocument'. The ajax call is called
 | ||
| 	 * in the click function of 'button.removedocument'. That button needs
 | ||
| 	 * to have two attributes: 'rel' for the id of the document, and 'msg'
 | ||
| 	 * for the message shown by notify if the document could be deleted.
 | ||
| 	 *
 | ||
| 	 * @param object $document document to be deleted
 | ||
| 	 * @param string $msg message shown in case of successful deletion
 | ||
| 	 * @param boolean $return return html instead of printing it
 | ||
| 	 * @return string html content if $return is true, otherwise an empty string
 | ||
| 	 */
 | ||
| 	function printDeleteDocumentButton($document, $msg, $return=false){ /* {{{ */
 | ||
| 		$docid = $document->getID();
 | ||
| 		$content = '';
 | ||
| 		$content .= '<a class="delete-document-btn" rel="'.$docid.'" msg="'.getMLText($msg).'" confirmmsg="'.htmlspecialchars(getMLText("confirm_rm_document", array ("documentname" => $document->getName())), ENT_QUOTES).'" title="'.getMLText("delete").'"><i class="fa fa-remove"></i></a>';
 | ||
| 		if($return)
 | ||
| 			return $content;
 | ||
| 		else
 | ||
| 			echo $content;
 | ||
| 		return '';
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function printDeleteDocumentButtonJs(){ /* {{{ */
 | ||
| 		echo "
 | ||
| 		$(document).ready(function () {
 | ||
| //			$('.delete-document-btn').click(function(ev) {
 | ||
| 			$('body').on('click', 'a.delete-document-btn', function(ev){
 | ||
| 				ev.stopPropagation();
 | ||
| 				id = $(ev.currentTarget).attr('rel');
 | ||
| 				confirmmsg = $(ev.currentTarget).attr('confirmmsg');
 | ||
| 				msg = $(ev.currentTarget).attr('msg');
 | ||
| 				formtoken = '".createFormKey('removedocument')."';
 | ||
| 				bootbox.confirm({
 | ||
| 					\"message\": confirmmsg,
 | ||
| 					\"buttons\": {
 | ||
| 						\"confirm\": {
 | ||
| 							\"label\" : \"<i class='fa fa-remove'></i> ".getMLText("rm_document")."\",
 | ||
| 							\"className\" : \"btn-danger\",
 | ||
| 						},
 | ||
| 						\"cancel\": {
 | ||
| 							\"label\" : \"".getMLText("cancel")."\",
 | ||
| 							\"className\" : \"btn-secondary\",
 | ||
| 						}
 | ||
| 					},
 | ||
| 					\"callback\": function(result) {
 | ||
| 						if(result) {
 | ||
| 							$.get('".$this->params['settings']->_httpRoot."op/op.Ajax.php',
 | ||
| 								{ command: 'deletedocument', id: id, formtoken: formtoken },
 | ||
| 								function(data) {
 | ||
| 									if(data.success) {
 | ||
| 										$('#table-row-document-'+id).hide('slow');
 | ||
| 										noty({
 | ||
| 											text: msg,
 | ||
| 											type: 'success',
 | ||
| 											dismissQueue: true,
 | ||
| 											layout: 'topRight',
 | ||
| 											theme: 'defaultTheme',
 | ||
| 											timeout: 1500,
 | ||
| 										});
 | ||
| 									} else {
 | ||
| 										noty({
 | ||
| 											text: data.message,
 | ||
| 											type: 'error',
 | ||
| 											dismissQueue: true,
 | ||
| 											layout: 'topRight',
 | ||
| 											theme: 'defaultTheme',
 | ||
| 											timeout: 3500,
 | ||
| 										});
 | ||
| 									}
 | ||
| 								},
 | ||
| 								'json'
 | ||
| 							);
 | ||
| 						}
 | ||
| 					}
 | ||
| 				});
 | ||
| 			});
 | ||
| 		});
 | ||
| 		";
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Print button with link for deleting a folder
 | ||
| 	 *
 | ||
| 	 * This button works like document delete button
 | ||
| 	 * {@link SeedDMS_Bootstrap_Style::printDeleteDocumentButton()}
 | ||
| 	 *
 | ||
| 	 * @param object $folder folder to be deleted
 | ||
| 	 * @param string $msg message shown in case of successful deletion
 | ||
| 	 * @param boolean $return return html instead of printing it
 | ||
| 	 * @return string html content if $return is true, otherwise an empty string
 | ||
| 	 */
 | ||
| 	function printDeleteFolderButton($folder, $msg, $return=false){ /* {{{ */
 | ||
| 		$folderid = $folder->getID();
 | ||
| 		$content = '';
 | ||
| 		$content .= '<a class="delete-folder-btn" rel="'.$folderid.'" msg="'.getMLText($msg).'" confirmmsg="'.htmlspecialchars(getMLText("confirm_rm_folder", array ("foldername" => $folder->getName())), ENT_QUOTES).'" title="'.getMLText("delete").'"><i class="fa fa-remove"></i></a>';
 | ||
| 		if($return)
 | ||
| 			return $content;
 | ||
| 		else
 | ||
| 			echo $content;
 | ||
| 		return '';
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function printDeleteFolderButtonJs(){ /* {{{ */
 | ||
| 		echo "
 | ||
| 		$(document).ready(function () {
 | ||
| //			$('.delete-folder-btn').click(function(ev) {
 | ||
| 			$('body').on('click', 'a.delete-folder-btn', function(ev){
 | ||
| 				ev.stopPropagation();
 | ||
| 				id = $(ev.currentTarget).attr('rel');
 | ||
| 				confirmmsg = $(ev.currentTarget).attr('confirmmsg');
 | ||
| 				msg = $(ev.currentTarget).attr('msg');
 | ||
| 				formtoken = '".createFormKey('removefolder')."';
 | ||
| 				bootbox.confirm({
 | ||
| 					\"message\": confirmmsg,
 | ||
| 					\"buttons\": {
 | ||
| 						\"confirm\": {
 | ||
| 							\"label\" : \"<i class='fa fa-remove'></i> ".getMLText("rm_folder")."\",
 | ||
| 							\"className\" : \"btn-danger\",
 | ||
| 						},
 | ||
| 						\"cancel\": {
 | ||
| 							\"label\" : \"".getMLText("cancel")."\",
 | ||
| 							\"className\" : \"btn-secondary\",
 | ||
| 						}
 | ||
| 					},
 | ||
| 					\"callback\": function(result) {
 | ||
| 						if(result) {
 | ||
| 							$.get('".$this->params['settings']->_httpRoot."op/op.Ajax.php',
 | ||
| 								{ command: 'deletefolder', id: id, formtoken: formtoken },
 | ||
| 								function(data) {
 | ||
| 									if(data.success) {
 | ||
| 										$('#table-row-folder-'+id).hide('slow');
 | ||
| 										noty({
 | ||
| 											text: msg,
 | ||
| 											type: 'success',
 | ||
| 											dismissQueue: true,
 | ||
| 											layout: 'topRight',
 | ||
| 											theme: 'defaultTheme',
 | ||
| 											timeout: 1500,
 | ||
| 										});
 | ||
| 									} else {
 | ||
| 										noty({
 | ||
| 											text: data.message,
 | ||
| 											type: 'error',
 | ||
| 											dismissQueue: true,
 | ||
| 											layout: 'topRight',
 | ||
| 											theme: 'defaultTheme',
 | ||
| 											timeout: 3500,
 | ||
| 										});
 | ||
| 									}
 | ||
| 								},
 | ||
| 								'json'
 | ||
| 							);
 | ||
| 						}
 | ||
| 					}
 | ||
| 				});
 | ||
| 			});
 | ||
| 		});
 | ||
| 		";
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function printLockButton($document, $msglock, $msgunlock, $return=false) { /* {{{ */
 | ||
| 		$accessobject = $this->params['accessobject'];
 | ||
| 		$docid = $document->getID();
 | ||
| 		if($document->isLocked()) {
 | ||
| 			if(!$accessobject->check_controller_access('UnlockDocument'))
 | ||
| 				return '';
 | ||
| 			$icon = 'unlock';
 | ||
| 			$msg = $msgunlock;
 | ||
| 			$title = 'unlock_document';
 | ||
| 		} else {
 | ||
| 			if(!$accessobject->check_controller_access('LockDocument'))
 | ||
| 				return '';
 | ||
| 			$icon = 'lock';
 | ||
| 			$msg = $msglock;
 | ||
| 			$title = 'lock_document';
 | ||
| 		}
 | ||
| 		$content = '';
 | ||
| 		$content .= '<a class="lock-document-btn" rel="'.$docid.'" msg="'.getMLText($msg).'" title="'.getMLText($title).'" data-formtoken="'.createFormKey('tooglelockdocument').'"><i class="fa fa-'.$icon.'"></i></a>';
 | ||
| 		if($return)
 | ||
| 			return $content;
 | ||
| 		else
 | ||
| 			echo $content;
 | ||
| 		return '';
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function printAccessButton($object, $return=false) { /* {{{ */
 | ||
| 		$accessobject = $this->params['accessobject'];
 | ||
| 		$content = '';
 | ||
| 		$objid = $object->getId();
 | ||
| 		if($object->isType('document')) {
 | ||
| 			if($accessobject->check_view_access('DocumentAccess'))
 | ||
| 				$content .= '<a class="access-document-btn" href="'.$this->params['settings']->_httpRoot.'out/out.DocumentAccess.php?documentid='.$objid.'" title="'.getMLText('edit_document_access').'"><i class="fa fa-bolt"></i></a>';
 | ||
| 		} elseif($object->isType('folder')) {
 | ||
| 			if($accessobject->check_view_access('FolderAccess'))
 | ||
| 				$content .= '<a class="access-folder-btn" href="'.$this->params['settings']->_httpRoot.'out/out.FolderAccess.php?folderid='.$objid.'" title="'.getMLText('edit_folder_access').'"><i class="fa fa-bolt"></i></a>';
 | ||
| 		}
 | ||
| 		if($return)
 | ||
| 			return $content;
 | ||
| 		else
 | ||
| 			echo $content;
 | ||
| 		return '';
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Output left-arrow with link which takes over a number of ids into
 | ||
| 	 * a select box.
 | ||
| 	 *
 | ||
| 	 * Clicking in the button will preset the comma seperated list of ids
 | ||
| 	 * in data-ref as options in the select box with name $name
 | ||
| 	 *
 | ||
| 	 * @param string $name id of select box
 | ||
| 	 * @param array $ids list of option values
 | ||
| 	 */
 | ||
| 	function getSelectPresetButtonHtml($name, $ids) { /* {{{ */
 | ||
| 		return '<span id="'.$name.'_btn" class="selectpreset_btn" style="cursor: pointer;" title="'.getMLText("takeOver".$name).'" data-ref="'.$name.'" data-ids="'.implode(",", $ids).'"><i class="fa fa-arrow-left"></i></span>';
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Output left-arrow with link which takes over a number of ids into
 | ||
| 	 * a select box.
 | ||
| 	 *
 | ||
| 	 * Clicking in the button will preset the comma seperated list of ids
 | ||
| 	 * in data-ref as options in the select box with name $name
 | ||
| 	 *
 | ||
| 	 * @param string $name id of select box
 | ||
| 	 * @param array $ids list of option values
 | ||
| 	 */
 | ||
| 	function printSelectPresetButtonHtml($name, $ids) { /* {{{ */
 | ||
| 		echo self::getSelectPresetButtonHtml($name, $ids);
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Javascript code for select preset button
 | ||
| 	 */
 | ||
| 	function printSelectPresetButtonJs() { /* {{{ */
 | ||
| ?>
 | ||
| $(document).ready( function() {
 | ||
| 	$('.selectpreset_btn').click(function(ev){
 | ||
| 		ev.preventDefault();
 | ||
| 		if (typeof $(ev.currentTarget).data('ids') != 'undefined') {
 | ||
| 			target = $(ev.currentTarget).data('ref');
 | ||
| 			// Use attr() instead of data() because data() converts to int which cannot be split
 | ||
| 			items = $(ev.currentTarget).attr('data-ids');
 | ||
| 			arr = items.split(",");
 | ||
| 			for(var i in arr) {
 | ||
| 				$("#"+target+" option[value='"+arr[i]+"']").attr("selected", "selected");
 | ||
| 			}
 | ||
| //			$("#"+target).trigger("chosen:updated");
 | ||
| 			$("#"+target).trigger("change");
 | ||
| 		}
 | ||
| 	});
 | ||
| });
 | ||
| <?php
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Get HTML for left-arrow with link which takes over a string into
 | ||
| 	 * a input field.
 | ||
| 	 *
 | ||
| 	 * Clicking on the button will preset the string
 | ||
| 	 * in data-ref the value of the input field with name $name
 | ||
| 	 *
 | ||
| 	 * @param string $name id of select box
 | ||
| 	 * @param string $text text
 | ||
| 	 */
 | ||
| 	function getInputPresetButtonHtml($name, $text, $sep='') { /* {{{ */
 | ||
| 		return '<span id="'.$name.'_btn" class="inputpreset_btn" style="cursor: pointer;" title="'.getMLText("takeOverAttributeValue").'" data-ref="'.$name.'" data-text="'.(is_array($text) ? implode($sep, $text) : htmlspecialchars($text)).'"'.($sep ? " data-sep=\"".$sep."\"" : "").'><i class="fa fa-arrow-left"></i></span>';
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Output left-arrow with link which takes over a string into
 | ||
| 	 * a input field.
 | ||
| 	 *
 | ||
| 	 * Clicking on the button will preset the string
 | ||
| 	 * in data-ref the value of the input field with name $name
 | ||
| 	 *
 | ||
| 	 * @param string $name id of select box
 | ||
| 	 * @param string $text text
 | ||
| 	 */
 | ||
| 	function printInputPresetButtonHtml($name, $text, $sep='') { /* {{{ */
 | ||
| 		echo self::getInputPresetButtonHtml($name, $text, $sep);
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Javascript code for input preset button
 | ||
| 	 * This code workѕ for input fields and single select fields
 | ||
| 	 */
 | ||
| 	function printInputPresetButtonJs() { /* {{{ */
 | ||
| ?>
 | ||
| $(document).ready( function() {
 | ||
| 	$('.inputpreset_btn').click(function(ev){
 | ||
| 		ev.preventDefault();
 | ||
| 		if (typeof $(ev.currentTarget).data('text') != 'undefined') {
 | ||
| 			target = $(ev.currentTarget).data('ref');
 | ||
| 			value = $(ev.currentTarget).data('text');
 | ||
| 			sep = $(ev.currentTarget).data('sep');
 | ||
| 			if(sep) {
 | ||
| 				// Use attr() instead of data() because data() converts to int which cannot be split
 | ||
| 				arr = value.split(sep);
 | ||
| 				for(var i in arr) {
 | ||
| 					$("#"+target+" option[value='"+arr[i]+"']").attr("selected", "selected");
 | ||
| 				}
 | ||
| 			} else {
 | ||
| 				$("#"+target).val(value);
 | ||
| 			}
 | ||
| 		}
 | ||
| 	});
 | ||
| });
 | ||
| <?php
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Get HTML for left-arrow with link which takes over a boolean value
 | ||
| 	 * into a checkbox field.
 | ||
| 	 *
 | ||
| 	 * Clicking on the button will preset the checkbox
 | ||
| 	 * in data-ref the value of the input field with name $name
 | ||
| 	 *
 | ||
| 	 * @param string $name id of select box
 | ||
| 	 * @param string $text text
 | ||
| 	 */
 | ||
| 	function getCheckboxPresetButtonHtml($name, $text) { /* {{{ */
 | ||
| ?>
 | ||
| 		return '<span id="'.$name.'_btn" class="checkboxpreset_btn" style="cursor: pointer;" title="'.getMLText("takeOverAttributeValue").'" data-ref="'.$name.'" data-text="'.(is_array($text) ? implode($sep, $text) : htmlspecialchars($text)).'"'.($sep ? " data-sep=\"".$sep."\"" : "").'><i class="fa fa-arrow-left"></i></span>';
 | ||
| <?php
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Output left-arrow with link which takes over a boolean value
 | ||
| 	 * into a checkbox field.
 | ||
| 	 *
 | ||
| 	 * Clicking on the button will preset the checkbox
 | ||
| 	 * in data-ref the value of the input field with name $name
 | ||
| 	 *
 | ||
| 	 * @param string $name id of select box
 | ||
| 	 * @param string $text text
 | ||
| 	 */
 | ||
| 	function printCheckboxPresetButtonHtml($name, $text) { /* {{{ */
 | ||
| 		self::getCheckboxPresetButtonHtml($name, $text);
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Javascript code for checkboxt preset button
 | ||
| 	 * This code workѕ for checkboxes
 | ||
| 	 */
 | ||
| 	function printCheckboxPresetButtonJs() { /* {{{ */
 | ||
| ?>
 | ||
| $(document).ready( function() {
 | ||
| 	$('.checkboxpreset_btn').click(function(ev){
 | ||
| 		ev.preventDefault();
 | ||
| 		if (typeof $(ev.currentTarget).data('text') != 'undefined') {
 | ||
| 			target = $(ev.currentTarget).data('ref');
 | ||
| 			value = $(ev.currentTarget).data('text');
 | ||
| 			if(value) {
 | ||
| 				$("#"+target).attr('checked', '');
 | ||
| 			} else {
 | ||
| 				$("#"+target).removeAttribute('checked');
 | ||
| 			}
 | ||
| 		}
 | ||
| 	});
 | ||
| });
 | ||
| <?php
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Print button with link for deleting an attribute value
 | ||
| 	 *
 | ||
| 	 * This button is used in document listings (e.g. on the ViewFolder page)
 | ||
| 	 * for deleting a document. In seeddms version < 4.3.9 this was just a
 | ||
| 	 * link to the out/out.RemoveDocument.php page which asks for confirmation
 | ||
| 	 * an than calls op/op.RemoveDocument.php. Starting with version 4.3.9
 | ||
| 	 * the button just opens a small popup asking for confirmation and than
 | ||
| 	 * calls the ajax command 'deletedocument'. The ajax call is called
 | ||
| 	 * in the click function of 'button.removedocument'. That button needs
 | ||
| 	 * to have two attributes: 'rel' for the id of the document, and 'msg'
 | ||
| 	 * for the message shown by notify if the document could be deleted.
 | ||
| 	 *
 | ||
| 	 * @param object $document document to be deleted
 | ||
| 	 * @param string $msg message shown in case of successful deletion
 | ||
| 	 * @param boolean $return return html instead of printing it
 | ||
| 	 * @return string html content if $return is true, otherwise an empty string
 | ||
| 	 */
 | ||
| 	function printDeleteAttributeValueButton($attrdef, $value, $msg, $return=false){ /* {{{ */
 | ||
| 		$content = '';
 | ||
| 		$content .= '<a class="delete-attribute-value-btn" rel="'.$attrdef->getID().'" msg="'.getMLText($msg).'" attrvalue="'.htmlspecialchars($value, ENT_QUOTES).'" confirmmsg="'.htmlspecialchars(getMLText("confirm_rm_attr_value", array ("attrdefname" => $attrdef->getName())), ENT_QUOTES).'"><i class="fa fa-remove"></i></a>';
 | ||
| 		if($return)
 | ||
| 			return $content;
 | ||
| 		else
 | ||
| 			echo $content;
 | ||
| 		return '';
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function printDeleteAttributeValueButtonJs(){ /* {{{ */
 | ||
| 		echo "
 | ||
| 		$(document).ready(function () {
 | ||
| //			$('.delete-attribute-value-btn').click(function(ev) {
 | ||
| 			$('body').on('click', 'a.delete-attribute-value-btn', function(ev){
 | ||
| 				id = $(ev.currentTarget).attr('rel');
 | ||
| 				confirmmsg = $(ev.currentTarget).attr('confirmmsg');
 | ||
| 				attrvalue = $(ev.currentTarget).attr('attrvalue');
 | ||
| 				msg = $(ev.currentTarget).attr('msg');
 | ||
| 				formtoken = '".createFormKey('removeattrvalue')."';
 | ||
| 				bootbox.confirm({
 | ||
| 					\"message\": confirmmsg,
 | ||
| 					\"buttons\": {
 | ||
| 						\"confirm\": {
 | ||
| 							\"label\" : \"<i class='fa fa-remove'></i> ".getMLText("rm_attr_value")."\",
 | ||
| 							\"className\" : \"btn-danger\",
 | ||
| 						},
 | ||
| 						\"cancel\": {
 | ||
| 							\"label\" : \"".getMLText("cancel")."\",
 | ||
| 							\"className\" : \"btn-secondary\",
 | ||
| 						}
 | ||
| 					},
 | ||
| 					\"callback\": function(result) {
 | ||
| 						if(result) {
 | ||
| 							$.post('".$this->params['settings']->_httpRoot."op/op.AttributeMgr.php',
 | ||
| 								{ action: 'removeattrvalue', attrdefid: id, attrvalue: attrvalue, formtoken: formtoken },
 | ||
| 								function(data) {
 | ||
| 									if(data.success) {
 | ||
| 										$('#table-row-attrvalue-'+id).hide('slow');
 | ||
| 										noty({
 | ||
| 											text: msg,
 | ||
| 											type: 'success',
 | ||
| 											dismissQueue: true,
 | ||
| 											layout: 'topRight',
 | ||
| 											theme: 'defaultTheme',
 | ||
| 											timeout: 1500,
 | ||
| 										});
 | ||
| 									} else {
 | ||
| 										noty({
 | ||
| 											text: data.message,
 | ||
| 											type: 'error',
 | ||
| 											dismissQueue: true,
 | ||
| 											layout: 'topRight',
 | ||
| 											theme: 'defaultTheme',
 | ||
| 											timeout: 3500,
 | ||
| 										});
 | ||
| 									}
 | ||
| 								},
 | ||
| 								'json'
 | ||
| 							);
 | ||
| 						}
 | ||
| 					}
 | ||
| 				});
 | ||
| 			});
 | ||
| 		});
 | ||
| 		";
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function printClickDocumentJs() { /* {{{ */
 | ||
| 		$onepage = $this->params['onepage'];
 | ||
| 		if($onepage) {
 | ||
| ?>
 | ||
| /* catch click on a document row in the list folders and documents */
 | ||
| $('body').on('click', '[id^=\"table-row-document\"] td:nth-child(2)', function(ev) {
 | ||
| 	if(ev.shiftKey) {
 | ||
| 		$(ev.currentTarget).parent().toggleClass('selected');
 | ||
| 	} else {
 | ||
| 		attr_id = $(ev.currentTarget).parent().attr('id').split('-')[3];
 | ||
| 		window.location = '<?= $this->params['settings']->_httpRoot ?>out/out.ViewDocument.php?documentid=' + attr_id;
 | ||
| 	}
 | ||
| });
 | ||
| <?php
 | ||
| 		}
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Print js code which catches clicks on folder rows
 | ||
| 	 *
 | ||
| 	 * This method will catch a click on a folder row and changes the
 | ||
| 	 * window.location to the out.ViewFolder.php page
 | ||
| 	 * This code is not needed on the out.ViewFolder.php page itself, because
 | ||
| 	 * a click will just reload the list of folders and documents.
 | ||
| 	 */
 | ||
| 	function printClickFolderJs() { /* {{{ */
 | ||
| 		$onepage = $this->params['onepage'];
 | ||
| 		if($onepage) {
 | ||
| ?>
 | ||
| /* catch click on a document row in the list folders and documents */
 | ||
| $('body').on('click', '[id^=\"table-row-folder\"] td:nth-child(2)', function(ev) {
 | ||
| 	if(ev.shiftKey) {
 | ||
| 		$(ev.currentTarget).parent().toggleClass('selected');
 | ||
| 	} else {
 | ||
| 		attr_id = $(ev.currentTarget).parent().data('target-id');
 | ||
| 		if(typeof attr_id == 'undefined')
 | ||
| 			attr_id = $(ev.currentTarget).parent().attr('id').split('-')[3];
 | ||
| 		window.location = '<?= $this->params['settings']->_httpRoot ?>out/out.ViewFolder.php?folderid=' + attr_id;
 | ||
| 	}
 | ||
| });
 | ||
| <?php
 | ||
| 		}
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Return HTML containing the path of a document or folder
 | ||
| 	 *
 | ||
| 	 * This is used for showing the path of a document/folder below the title
 | ||
| 	 * in document/folder lists like on the search page.
 | ||
| 	 *
 | ||
| 	 * @param object $object
 | ||
| 	 * @return string
 | ||
| 	 */
 | ||
| 	function getListRowPath($object) { /* {{{ */
 | ||
| 		if(!$object)
 | ||
| 			return '';
 | ||
| 		$belowtitle = '';
 | ||
| 		$folder = $object->getParent();
 | ||
| 		if($folder) {
 | ||
| 			$belowtitle .= "<br /><span style=\"font-size: 85%;\">".getMLText('in_folder').": /";
 | ||
| 			$path = $folder->getPath();
 | ||
| 			for ($i = 1; $i  < count($path); $i++) {
 | ||
| 				$belowtitle .= htmlspecialchars($path[$i]->getName())."/";
 | ||
| 			}
 | ||
| 			$belowtitle .= "</span>";
 | ||
| 		}
 | ||
| 		return $belowtitle;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	public function folderListHeaderImage() { /* {{{ */
 | ||
| 		$folder = $this->getParam('folder');
 | ||
| 		$onepage = $this->params['onepage'];
 | ||
| 		$parent = ($folder && $onepage) ? $folder->getParent() : null;
 | ||
| 		$headcol = ($parent ? '<button class="btn btn-mini btn-secondary btn-sm" id="goto-parent" data-parentid="'.$parent->getID().'"><i class="fa fa-arrow-up"></i></button>' : '')."</th>\n";	
 | ||
| 		return $headcol;	
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	public function folderListHeaderName() { /* {{{ */
 | ||
| 		$folder = $this->getParam('folder');
 | ||
| 		$headcol = getMLText("name");
 | ||
| 		if($folder) {
 | ||
| 			$folderid = $folder->getId();
 | ||
| 			$orderby = $this->params['orderby'];
 | ||
| 			$orderdir = (isset($orderby[1]) ? ($orderby[1] == 'd' ? 'desc' : 'asc') : 'asc');
 | ||
| 			$headcol .= " <a class=\"order-btn\" href=\"".$this->params['settings']->_httpRoot."out/out.ViewFolder.php?folderid=". $folderid .($orderby=="n"||$orderby=="na"?"&orderby=nd":"&orderby=n")."\" data-orderby=\"".($orderby=="n"||$orderby=="na"?"nd":"n")."\"title=\"".getMLText("sort_by_name")."\">".($orderby=="n"||$orderby=="na"?' <i class="fa fa-sort-alpha-asc selected"></i>':($orderby=="nd"?' <i class="fa fa-sort-alpha-desc selected"></i>':' <i class="fa fa-sort-alpha-asc"></i>'))."</a>";
 | ||
| 			$headcol .= " <a class=\"order-btn\" href=\"".$this->params['settings']->_httpRoot."out/out.ViewFolder.php?folderid=". $folderid .($orderby=="s"||$orderby=="sa"?"&orderby=sd":"&orderby=s")."\" data-orderby=\"".($orderby=="s"||$orderby=="sa"?"sd":"s")."\" title=\"".getMLText("sort_by_sequence")."\">".($orderby=="s"||$orderby=="sa"?' <i class="fa fa-sort-numeric-asc selected"></i>':($orderby=="sd"?' <i class="fa fa-sort-numeric-desc selected"></i>':' <i class="fa fa-sort-numeric-asc"></i>'))."</a>";
 | ||
| 			$headcol .= " <a class=\"order-btn\" href=\"".$this->params['settings']->_httpRoot."out/out.ViewFolder.php?folderid=". $folderid .($orderby=="d"||$orderby=="da"?"&orderby=dd":"&orderby=d")."\" data-orderby=\"".($orderby=="d"||$orderby=="da"?"dd":"d")."\" title=\"".getMLText("sort_by_date")."\">".($orderby=="d"||$orderby=="da"?' <i class="fa fa-sort-amount-asc selected"></i>':($orderby=="dd"?' <i class="fa fa-sort-amount-desc selected"></i>':' <i class="fa fa-sort-amount-asc"></i>'))."</a>";
 | ||
| 		}
 | ||
| 		return $headcol;	
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	public function folderListHeader() { /* {{{ */
 | ||
| 		$content = "<table id=\"viewfolder-table\" class=\"table table-condensed table-sm table-hover\">";
 | ||
| 		$content .= "<thead>\n<tr>\n";
 | ||
| 		$headcols = array();
 | ||
| 		$headcols['image'] = $this->folderListHeaderImage();	
 | ||
| 		$headcols['name'] = $this->folderListHeaderName();
 | ||
| 		if($ec = $this->callHook('folderListHeaderExtraColumns'))
 | ||
| 				$headcols = array_merge($headcols, $ec);
 | ||
| 		$headcols['status'] = getMLText("status");
 | ||
| 		$headcols['action'] = getMLText("action");
 | ||
| 		foreach($headcols as $headcol)
 | ||
| 			$content .= "<th>".$headcol."</th>\n";
 | ||
| 		$content .= "</tr>\n</thead>\n";
 | ||
| 		return $content;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Start the row for a folder in list of documents and folders
 | ||
| 	 *
 | ||
| 	 * For a detailed description see
 | ||
| 	 * {@link SeedDMS_Bootstrap_Style::folderListRowStart()}
 | ||
| 	 */
 | ||
| 	function documentListRowStart($document, $class='') { /* {{{ */
 | ||
| 		if($class) {
 | ||
| 			if($class == 'error')
 | ||
| 				$class = 'table-danger';
 | ||
| 			else
 | ||
| 				$class = 'table-'.$class;
 | ||
| 		}
 | ||
| 		$docID = $document->getID();
 | ||
| 		return "<tr id=\"table-row-document-".$docID."\" data-target-id=\"".$docID."\" class=\"table-row-document droptarget ".($class ? ' '.$class : '')."\" data-droptarget=\"document_".$docID."\" rel=\"document_".$docID."\" formtoken=\"".createFormKey('')."\" data-uploadformtoken=\"".createFormKey('')."\" draggable=\"true\" data-name=\"".htmlspecialchars($document->getName(), ENT_QUOTES)."\">";
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function documentListRowEnd($document) { /* {{{ */
 | ||
| 			return "</tr>\n";
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function documentListRowStatus($latestContent) { /* {{{ */
 | ||
| 		$user = $this->params['user'];
 | ||
| 		$workflowmode = $this->params['workflowmode'];
 | ||
| 		$document = $latestContent->getDocument();
 | ||
| 
 | ||
| 		$status = $latestContent->getStatus();
 | ||
| 		$attentionstr = '';
 | ||
| 		if ( $document->isLocked() ) {
 | ||
| 			$attentionstr .= "<i class=\"fa fa-lock\" title=\"". getMLText("locked_by").": ".htmlspecialchars($document->getLockingUser()->getFullName())."\"></i> ";
 | ||
| 		}
 | ||
| 		if($workflowmode == 'advanced') {
 | ||
| 			$workflow = $latestContent->getWorkflow();
 | ||
| 			if($workflow && $latestContent->needsWorkflowAction($user)) {
 | ||
| 				$attentionstr .= "<i class=\"fa fa-exclamation-triangle\" title=\"". getMLText("workflow").": ".htmlspecialchars($workflow->getName())."\"></i> ";
 | ||
| 			}
 | ||
| 		}
 | ||
| 		$content = '';
 | ||
| 		if($attentionstr)
 | ||
| 			$content .= $attentionstr."<br />";
 | ||
| 
 | ||
| 		/* Retrieve attacheѕ files */
 | ||
| 		$files = $document->getDocumentFiles($latestContent->getVersion());
 | ||
| 		$files = SeedDMS_Core_DMS::filterDocumentFiles($user, $files);
 | ||
| 
 | ||
| 		/* Retrieve linked documents */
 | ||
| 		$links = $document->getDocumentLinks();
 | ||
| 		$links = SeedDMS_Core_DMS::filterDocumentLinks($user, $links);
 | ||
| 
 | ||
| 		/* Retrieve reverse linked documents */
 | ||
| 		$revlinks = $document->getReverseDocumentLinks();
 | ||
| 		$revlinks = SeedDMS_Core_DMS::filterDocumentLinks($user, $revlinks);
 | ||
| 
 | ||
| 		$content .= "<div style=\"font-size: 85%;\">";
 | ||
| 		if(count($files))
 | ||
| 			$content .= '<i class="fa fa-paperclip" title="'.getMLText("linked_files").'"></i> '.count($files)."<br />";
 | ||
| 		if(count($links) || count($revlinks))
 | ||
| 			$content .= '<i class="fa fa-link" title="'.getMLText("linked_documents").'"></i> '.count($links)."/".count($revlinks)."<br />";
 | ||
| 		if($status["status"] == S_IN_WORKFLOW && $workflowmode == 'advanced') {
 | ||
| 			if($workflowstate = $latestContent->getWorkflowState())
 | ||
| 				$content .= '<span title="'.getOverallStatusText($status["status"]).': '.($workflow ? htmlspecialchars($workflow->getName()) : '').'">'.($workflowstate ? htmlspecialchars($workflowstate->getName()) : '').'</span>';
 | ||
| 		} else {
 | ||
| 			$content .= $this->getOverallStatusIcon($status['status']);
 | ||
| 		}
 | ||
| 		$content .= "</div>";
 | ||
| 		return $content;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function documentListRowAction($document, $previewer, $skipcont=false, $version=0, $extracontent=array()) { /* {{{ */
 | ||
| 		$user = $this->params['user'];
 | ||
| 		$enableClipboard = $this->params['enableclipboard'];
 | ||
| 		$accessop = $this->params['accessobject'];
 | ||
| 		$onepage = $this->params['onepage'];
 | ||
| 
 | ||
| 		$content = '';
 | ||
| 		$content .= "<div class=\"list-action\">";
 | ||
| 		$actions = array();
 | ||
| 		if(!empty($extracontent['begin_action_list']))
 | ||
| 			$content .= $extracontent['begin_action_list'];
 | ||
| 		if($accessop->check_view_access('RemoveDocument')) {
 | ||
| 			if($document->getAccessMode($user, 'removeDocument') >= M_ALL) {
 | ||
| 				$actions['remove_document'] = $this->printDeleteDocumentButton($document, 'splash_rm_document', true);
 | ||
| 			} else {
 | ||
| 				$actions['remove_document'] = '<span style="padding: 2px; color: #CCC;"><i class="fa fa-remove"></i></span>';
 | ||
| 			}
 | ||
| 		}
 | ||
| 		$docID = $document->getID();
 | ||
| 		if($document->getAccessMode($user) >= M_READWRITE) {
 | ||
| 			$actions['edit_document'] = '<a href="'.$this->params['settings']->_httpRoot.'out/out.EditDocument.php?documentid='.$docID.'" title="'.getMLText("edit_document_props").'"><i class="fa fa-edit"></i></a>';
 | ||
| 		} else {
 | ||
| 			$actions['edit_document'] = '<span style="padding: 2px; color: #CCC;"><i class="fa fa-edit"></i></span>';
 | ||
| 		}
 | ||
| 		if($document->getAccessMode($user) >= M_READWRITE) {
 | ||
| 			$actions['lock_document'] = $this->printLockButton($document, 'splash_document_locked', 'splash_document_unlocked', true);
 | ||
| 		}
 | ||
| 		if($document->getAccessMode($user) >= M_READWRITE) {
 | ||
| 			$actions['document_access'] = $this->printAccessButton($document, true);
 | ||
| 		}
 | ||
| 		if($enableClipboard) {
 | ||
| 			$actions['add_to_clipboard'] = '<a class="addtoclipboard" rel="D'.$docID.'" msg="'.getMLText('splash_added_to_clipboard').'" title="'.getMLText("add_to_clipboard").'"><i class="fa fa-copy"></i></a>';
 | ||
| 		}
 | ||
| 		if($onepage)
 | ||
| 			$actions['view_document'] = '<a href="'.$this->params['settings']->_httpRoot.'out/out.ViewDocument.php?documentid='.$docID.'" title="'.getMLText("view_document").'"><i class="fa fa-eye"></i></a>';
 | ||
| 
 | ||
| 		/* Do not use $this->callHook() because $menuitems must be returned by the the
 | ||
| 		 * first hook and passed to next hook. $this->callHook() will just pass
 | ||
| 		 * the menuitems to each single hook. Hence, the last hook will win.
 | ||
| 		 */
 | ||
| 		$hookObjs = $this->getHookObjects();
 | ||
| 		foreach($hookObjs as $hookObj) {
 | ||
| 			if (method_exists($hookObj, 'documentRowAction')) {
 | ||
| 	      $actions = $hookObj->documentRowAction($this, $document, $actions);
 | ||
| 			}
 | ||
| 		}
 | ||
| 
 | ||
| 		foreach($actions as $action) {
 | ||
| 			if(is_string($action))
 | ||
| 				$content .= $action;
 | ||
| 		}
 | ||
| 		if(!empty($extracontent['end_action_list']))
 | ||
| 			$content .= $extracontent['end_action_list'];
 | ||
| 		$content .= "</div>";
 | ||
| 		return $content;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Return HTML of a single row in the document list table
 | ||
| 	 *
 | ||
| 	 * @param object $document
 | ||
| 	 * @param object $previewer
 | ||
| 	 * @param boolean $skipcont set to true if embrasing tr shall be skipped
 | ||
| 	 */
 | ||
| 	function documentListRow($document, $previewer, $skipcont=false, $version=0, $extracontent=array()) { /* {{{ */
 | ||
| 		$dms = $this->params['dms'];
 | ||
| 		$user = $this->params['user'];
 | ||
| 		$showtree = $this->params['showtree'];
 | ||
| 		$workflowmode = $this->params['workflowmode'];
 | ||
| 		$previewwidth = $this->params['previewWidthList'];
 | ||
| 		$enableClipboard = $this->params['enableclipboard'];
 | ||
| 		$accessop = $this->params['accessobject'];
 | ||
| 		$onepage = $this->params['onepage'];
 | ||
| 
 | ||
| 		$content = '';
 | ||
| 
 | ||
| 		$owner = $document->getOwner();
 | ||
| 		$comment = $document->getComment();
 | ||
| 		if (strlen($comment) > 150) $comment = substr($comment, 0, 147) . "...";
 | ||
| 		$docID = $document->getID();
 | ||
| 
 | ||
| 		if($version) {
 | ||
| 			$latestContent = $this->callHook('documentContent', $document, $version);
 | ||
| 			if($latestContent === null)
 | ||
| 				$latestContent = $document->getContentByVersion($version);
 | ||
| 		} else {
 | ||
| 			$latestContent = $this->callHook('documentLatestContent', $document);
 | ||
| 			if($latestContent === null)
 | ||
| 				$latestContent = $document->getLatestContent();
 | ||
| 		}
 | ||
| 
 | ||
| 		if($latestContent) {
 | ||
| 			if(!$skipcont)
 | ||
| 				$content .= $this->documentListRowStart($document);
 | ||
| 
 | ||
| 			if($previewer) $previewer->createPreview($latestContent);
 | ||
| 			$version = $latestContent->getVersion();
 | ||
| 			
 | ||
| 			if($ec = $this->callHook('documentListRowExtraContent', $document, $latestContent))
 | ||
| 				$extracontent = array_merge($extracontent, $ec);
 | ||
| 
 | ||
| 			$content .= "<td>";
 | ||
| 			if (file_exists($dms->contentDir . $latestContent->getPath())) {
 | ||
| 				$previewhtml = $this->callHook('documentListPreview', $previewer, $document, $latestContent);
 | ||
| 				if(is_string($previewhtml))
 | ||
| 					$content .= $previewhtml;
 | ||
| 				else {
 | ||
| 					if($accessop->check_controller_access('Download', array('action'=>'version')))
 | ||
| 						$content .= "<a draggable=\"false\" href=\"".$this->params['settings']->_httpRoot."op/op.Download.php?documentid=".$docID."&version=".$version."\">";
 | ||
| 					if($previewer && $previewer->hasPreview($latestContent)) {
 | ||
| 						$content .= "<img draggable=\"false\" class=\"mimeicon\" width=\"".$previewwidth."\" src=\"".$this->params['settings']->_httpRoot."op/op.Preview.php?documentid=".$document->getID()."&version=".$latestContent->getVersion()."&width=".$previewwidth."\" title=\"".htmlspecialchars($latestContent->getMimeType())."\">";
 | ||
| 					} else {
 | ||
| 						$content .= "<img draggable=\"false\" class=\"mimeicon\" width=\"".$previewwidth."\" src=\"".$this->getMimeIcon($latestContent->getFileType())."\" ".($previewwidth ? "width=\"".$previewwidth."\"" : "")."\" title=\"".htmlspecialchars($latestContent->getMimeType())."\">";
 | ||
| 					}
 | ||
| 					if($accessop->check_controller_access('Download', array('action'=>'version')))
 | ||
| 						$content .= "</a>";
 | ||
| 				}
 | ||
| 			} else
 | ||
| 				$content .= "<img draggable=\"false\" class=\"mimeicon\" width=\"".$previewwidth."\" src=\"".$this->getMimeIcon($latestContent->getFileType())."\" title=\"".htmlspecialchars($latestContent->getMimeType())."\">";
 | ||
| 			$content .= "</td>";
 | ||
| 
 | ||
| 			$content .= "<td class=\"wordbreak\"".($onepage ? ' style="cursor: pointer;"' : '').">";
 | ||
| 			if($onepage)
 | ||
| 				$content .= "<b".($onepage ? ' title="Id:'.$document->getId().'"' : '').">".htmlspecialchars($document->getName()) . "</b>";
 | ||
| 			else
 | ||
| 				$content .= "<a draggable=\"false\" href=\"".$this->params['settings']->_httpRoot."out/out.ViewDocument.php?documentid=".$docID."&showtree=".$showtree."\">" . htmlspecialchars($document->getName()) . "</a>";
 | ||
| 			if(isset($extracontent['below_title']))
 | ||
| 				$content .= $extracontent['below_title'];
 | ||
| 			$content .= "<br />";
 | ||
| 			if($belowtitle = $this->callHook('documentListRowBelowTitle', $document, $latestContent))
 | ||
| 				$content .= $belowtitle;
 | ||
| 			else
 | ||
| 				$content .= "<span style=\"font-size: 85%; font-style: italic; color: #666; \">".getMLText('owner').": <b>".htmlspecialchars($owner->getFullName())."</b>, ".getMLText('creation_date').": <b>".getReadableDate($document->getDate())."</b>, ".getMLText('version')." <b>".$version."</b> - <b>".getReadableDate($latestContent->getDate())."</b>".($document->expires() ? ", ".getMLText('expires').": <b>".getReadableDate($document->getExpires())."</b>" : "")."</span>";
 | ||
| 			if($comment) {
 | ||
| 				$content .= "<br /><span style=\"font-size: 85%;\">".htmlspecialchars($comment)."</span>";
 | ||
| 			}
 | ||
| 			if($categories = $document->getCategories()) {
 | ||
| 				$content .= "<br />";
 | ||
| 				foreach($categories as $category) {
 | ||
| 					$color = substr(md5($category->getName()), 0, 6);
 | ||
| 					$content .= "<span class=\"badge\" style=\"background-color: #".$color."; color: #".self::getContrastColor($color).";\">".$category->getName()."</span> ";
 | ||
| 				}
 | ||
| 			}
 | ||
| 			if(!empty($extracontent['bottom_title']))
 | ||
| 				$content .= $extracontent['bottom_title'];
 | ||
| 			$content .= "</td>\n";
 | ||
| 
 | ||
| 			if(!empty($extracontent['columns'])) {
 | ||
| 				foreach($extracontent['columns'] as $col)
 | ||
| 					$content .= '<td>'.$col.'</td>';
 | ||
| 			}
 | ||
| 
 | ||
| 			$content .= "<td nowrap>";
 | ||
| 			$content .= $this->documentListRowStatus($latestContent);
 | ||
| 			$content .= "</td>";
 | ||
| 			$content .= "<td>";
 | ||
| 			$content .= $this->documentListRowAction($document, $previewer, $skipcont, $version, $extracontent);
 | ||
| 			$content .= "</td>";
 | ||
| 			if(!empty($extracontent['columns_last'])) {
 | ||
| 				foreach($extracontent['columns_last'] as $col)
 | ||
| 					$content .= '<td>'.$col.'</td>';
 | ||
| 			}
 | ||
| 
 | ||
| 			if(!$skipcont)
 | ||
| 				$content .= $this->documentListRowEnd($document);
 | ||
| 		}
 | ||
| 		return $content;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Start the row for a folder in list of documents and folders
 | ||
| 	 *
 | ||
| 	 * This method creates the starting tr tag for a new table row containing
 | ||
| 	 * a folder list entry. The tr tag contains various attributes which are
 | ||
| 	 * used for removing the table line and to make drap&drop work.
 | ||
| 	 *
 | ||
| 	 * id=table-row-folder-<id> : used for identifying the row when removing the table
 | ||
| 	 *   row after deletion of the folder by clicking on the delete button in that table
 | ||
| 	 *   row.
 | ||
| 	 * data-droptarget=folder_<id> : identifies the folder represented by this row
 | ||
| 	 *   when it used as a target of the drag&drop operation.
 | ||
| 	 *   If an element (either a file or a dragged item) is dropped on this row, the
 | ||
| 	 *   data-droptarget will be evaluated to identify the underlying dms object.
 | ||
| 	 *   Dropping a file on a folder will upload that file into the folder. Droping
 | ||
| 	 *   an item (which is currently either a document or a folder) from the page will
 | ||
| 	 *   move that item into the folder.
 | ||
| 	 * rel=folder_<id> : This data is put into drag data when a drag starts. When the
 | ||
| 	 *   item is dropped on some other item this data will identify the source object.
 | ||
| 	 *   The attributes data-droptarget and rel are usually equal. At least there is
 | ||
| 	 *   currently no scenario where they are different.
 | ||
| 	 * formtoken=<token> : token made of key 'movefolder'
 | ||
| 	 *   formtoken is also placed in the drag data just like the value of attibute 'rel'.
 | ||
| 	 *   This is always set to a value made of 'movefolder'.
 | ||
| 	 * data-uploadformtoken=<token> : token made of key 'adddocument'
 | ||
| 	 * class=table-row-folder : The class must have a class named 'table-row-folder' in
 | ||
| 	 *   order to be draggable and to extract the drag data from the attributes 'rel' and
 | ||
| 	 *   'formtoken'
 | ||
| 	 *
 | ||
| 	 * @param object $folder
 | ||
| 	 * @return string starting tr tag for a table
 | ||
| 	 */
 | ||
| 	function folderListRowStart($folder, $class='') { /* {{{ */
 | ||
| 		if($class) {
 | ||
| 			if($class == 'error')
 | ||
| 				$class = 'table-danger';
 | ||
| 			else
 | ||
| 				$class = 'table-'.$class;
 | ||
| 		}
 | ||
| 		return "<tr id=\"table-row-folder-".$folder->getID()."\" draggable=\"true\" data-droptarget=\"folder_".$folder->getID()."\" rel=\"folder_".$folder->getID()."\" class=\"folder table-row-folder droptarget".($class ? ' '.$class : '')."\" data-uploadformtoken=\"".createFormKey('')."\" formtoken=\"".createFormKey('')."\" data-name=\"".htmlspecialchars($folder->getName(), ENT_QUOTES)."\">";
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function folderListRowEnd($folder) { /* {{{ */
 | ||
| 			return "</tr>\n";
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function folderListRowStatus($subFolder) { /* {{{ */
 | ||
| 		$dms = $this->params['dms'];
 | ||
| 		$user = $this->params['user'];
 | ||
| 		$showtree = $this->params['showtree'];
 | ||
| 		$enableRecursiveCount = $this->params['enableRecursiveCount'];
 | ||
| 		$maxRecursiveCount = $this->params['maxRecursiveCount'];
 | ||
| 
 | ||
| 		$content = "<div style=\"font-size: 85%;\">";
 | ||
| 		if($enableRecursiveCount) {
 | ||
| 			if($user->isAdmin()) {
 | ||
| 				/* No need to check for access rights in countChildren() for
 | ||
| 				 * admin. So pass 0 as the limit.
 | ||
| 				 */
 | ||
| 				$cc = $subFolder->countChildren($user, 0);
 | ||
| 				if($cc['folder_count'])
 | ||
| 					$content .= '<i class="fa fa-folder" title="'.getMLText("folders").'"></i> '.$cc['folder_count']."<br />";
 | ||
| 				if($cc['document_count'])
 | ||
| 					$content .= '<i class="fa fa-file" title="'.getMLText("documents").'"></i> '.$cc['document_count'];
 | ||
| 			} else {
 | ||
| 				$cc = $subFolder->countChildren($user, $maxRecursiveCount);
 | ||
| 				if($maxRecursiveCount > 5000)
 | ||
| 					$rr = 100.0;
 | ||
| 				else
 | ||
| 					$rr = 10.0;
 | ||
| 				if($cc['folder_count'])
 | ||
| 					$content .= '<i class="fa fa-folder" title="'.getMLText("folders").'"></i> '.(!$cc['folder_precise'] ? '~'.(round($cc['folder_count']/$rr)*$rr) : $cc['folder_count'])."<br />";
 | ||
| 				if($cc['document_count'])
 | ||
| 					$content .= '<i class="fa fa-file" title="'.getMLText("documents").'"></i> '.(!$cc['document_precise'] ? '~'.(round($cc['document_count']/$rr)*$rr) : $cc['document_count']);
 | ||
| 			}
 | ||
| 		} else {
 | ||
| 			/* FIXME: the following is very inefficient for just getting the number of
 | ||
| 			 * subfolders and documents. Making it more efficient is difficult, because
 | ||
| 			 * the access rights need to be checked.
 | ||
| 			 */
 | ||
| 			$subsub = $subFolder->getSubFolders();
 | ||
| 			$subsub = SeedDMS_Core_DMS::filterAccess($subsub, $user, M_READ);
 | ||
| 			$subdoc = $subFolder->getDocuments();
 | ||
| 			$subdoc = SeedDMS_Core_DMS::filterAccess($subdoc, $user, M_READ);
 | ||
| 			if(count($subsub))
 | ||
| 				$content .= '<i class="fa fa-folder" title="'.getMLText("folders").'"></i> '.count($subsub)."<br />";
 | ||
| 			if(count($subdoc))
 | ||
| 				$content .= '<i class="fa fa-file" title="'.getMLText("documents").'"></i> '.count($subdoc);
 | ||
| 		}
 | ||
| 		$content .= "</div>";
 | ||
| 		return $content;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function folderListRowAction($subFolder, $skipcont=false, $extracontent=array()) { /* {{{ */
 | ||
| 		$dms = $this->params['dms'];
 | ||
| 		$user = $this->params['user'];
 | ||
| //		$folder = $this->params['folder'];
 | ||
| 		$showtree = $this->params['showtree'];
 | ||
| 		$enableRecursiveCount = $this->params['enableRecursiveCount'];
 | ||
| 		$maxRecursiveCount = $this->params['maxRecursiveCount'];
 | ||
| 		$enableClipboard = $this->params['enableclipboard'];
 | ||
| 		$accessop = $this->params['accessobject'];
 | ||
| 		$onepage = $this->params['onepage'];
 | ||
| 
 | ||
| 		$content = '';
 | ||
| 		$content .= "<div class=\"list-action\">";
 | ||
| 		$actions = array();
 | ||
| 		if(!empty($extracontent['begin_action_list']))
 | ||
| 			$content .= $extracontent['begin_action_list'];
 | ||
| 		$subFolderAccessMode = $subFolder->getAccessMode($user);
 | ||
| 		if ($accessop->check_view_access('RemoveFolder')) {
 | ||
| 			if($subFolderAccessMode >= M_ALL) {
 | ||
| 				$actions['remove_folder'] = $this->printDeleteFolderButton($subFolder, 'splash_rm_folder', true);
 | ||
| 			} else {
 | ||
| 				$actions['remove_folder'] = '<span style="padding: 2px; color: #CCC;"><i class="fa fa-remove"></i></span>';
 | ||
| 			}
 | ||
| 		}
 | ||
| 		if($subFolderAccessMode >= M_READWRITE) {
 | ||
| 			$actions['edit_folder'] = '<a class_="btn btn-mini" href="'.$this->params['settings']->_httpRoot.'out/out.EditFolder.php?folderid='.$subFolder->getID().'" title="'.getMLText("edit_folder_props").'"><i class="fa fa-edit"></i></a>';
 | ||
| 		} else {
 | ||
| 			$content .= '<span style="padding: 2px; color: #CCC;"><i class="fa fa-edit"></i></span>';
 | ||
| 		}
 | ||
| 		if($subFolderAccessMode >= M_READWRITE) {
 | ||
| 			$actions['folder_access'] = $this->printAccessButton($subFolder, true);
 | ||
| 		}
 | ||
| 		if($enableClipboard) {
 | ||
| 			$actions['add_to_clipboard'] = '<a class="addtoclipboard" rel="F'.$subFolder->getID().'" msg="'.getMLText('splash_added_to_clipboard').'" title="'.getMLText("add_to_clipboard").'"><i class="fa fa-copy"></i></a>';
 | ||
| 		}
 | ||
| 		if($onepage)
 | ||
| 			$actions['view_folder'] = '<a href="'.$this->params['settings']->_httpRoot.'out/out.ViewFolder.php?folderid='.$subFolder->getID().'" title="'.getMLText("view_folder").'"><i class="fa fa-eye"></i></a>';
 | ||
| 
 | ||
| 		/* Do not use $this->callHook() because $menuitems must be returned by the the
 | ||
| 		 * first hook and passed to next hook. $this->callHook() will just pass
 | ||
| 		 * the menuitems to each single hook. Hence, the last hook will win.
 | ||
| 		 */
 | ||
| 		$hookObjs = $this->getHookObjects();
 | ||
| 		foreach($hookObjs as $hookObj) {
 | ||
| 			if (method_exists($hookObj, 'folderRowAction')) {
 | ||
| 	      $actions = $hookObj->folderRowAction($this, $folder, $actions);
 | ||
| 			}
 | ||
| 		}
 | ||
| 
 | ||
| 		foreach($actions as $action) {
 | ||
| 			if(is_string($action))
 | ||
| 				$content .= $action;
 | ||
| 		}
 | ||
| 
 | ||
| 		if(!empty($extracontent['end_action_list']))
 | ||
| 			$content .= $extracontent['end_action_list'];
 | ||
| 		$content .= "</div>";
 | ||
| 		return $content;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function folderListRow($subFolder, $skipcont=false, $extracontent=array()) { /* {{{ */
 | ||
| 		$dms = $this->params['dms'];
 | ||
| 		$user = $this->params['user'];
 | ||
| //		$folder = $this->params['folder'];
 | ||
| 		$showtree = $this->params['showtree'];
 | ||
| 		$enableRecursiveCount = $this->params['enableRecursiveCount'];
 | ||
| 		$maxRecursiveCount = $this->params['maxRecursiveCount'];
 | ||
| 		$enableClipboard = $this->params['enableclipboard'];
 | ||
| 		$accessop = $this->params['accessobject'];
 | ||
| 		$onepage = $this->params['onepage'];
 | ||
| 
 | ||
| 		if(!$subFolder)
 | ||
| 			return '';
 | ||
| 
 | ||
| 		$owner = $subFolder->getOwner();
 | ||
| 		$comment = $subFolder->getComment();
 | ||
| 		if (strlen($comment) > 150) $comment = substr($comment, 0, 147) . "...";
 | ||
| 
 | ||
| 		if($ec = $this->callHook('folderListRowExtraContent', $subFolder))
 | ||
| 			$extracontent = array_merge($extracontent, $ec);
 | ||
| 
 | ||
| 		$content = '';
 | ||
| 		if(!$skipcont)
 | ||
| 			$content .= $this->folderListRowStart($subFolder);
 | ||
| 		$content .= "<td><a draggable=\"false\" href=\"".$this->params['settings']->_httpRoot."out/out.ViewFolder.php?folderid=".$subFolder->getID()."&showtree=".$showtree."\"><img draggable=\"false\" src=\"".$this->getMimeIcon(".folder")."\" width=\"24\" height=\"24\" border=0></a></td>\n";
 | ||
| 		if($onepage)
 | ||
| 			$content .= "<td class=\"wordbreak\" style=\"cursor: pointer;\">" . "<b title=\"Id:".$subFolder->getId()."\">".htmlspecialchars($subFolder->getName())."</b>";
 | ||
| 		else
 | ||
| 			$content .= "<td class=\"wordbreak\"><a draggable=\"false\" href=\"".$this->params['settings']->_httpRoot."out/out.ViewFolder.php?folderid=".$subFolder->getID()."&showtree=".$showtree."\">" . htmlspecialchars($subFolder->getName()) . "</a>";
 | ||
| 		if(isset($extracontent['below_title']))
 | ||
| 			$content .= $extracontent['below_title'];
 | ||
| 		$content .= "<br /><span style=\"font-size: 85%; font-style: italic; color: #666;\">".getMLText('owner').": <b>".htmlspecialchars($owner->getFullName())."</b>, ".getMLText('creation_date').": <b>".getReadableDate($subFolder->getDate())."</b></span>";
 | ||
| 		if($comment) {
 | ||
| 			$content .= "<br /><span style=\"font-size: 85%;\">".htmlspecialchars($comment)."</span>";
 | ||
| 		}
 | ||
| 		if(isset($extracontent['bottom_title']))
 | ||
| 			$content .= $extracontent['bottom_title'];
 | ||
| 		$content .= "</td>\n";
 | ||
| //		$content .= "<td>".htmlspecialchars($owner->getFullName())."</td>";
 | ||
| 		$content .= "<td colspan=\"1\" nowrap>";
 | ||
| 		$content .= $this->folderListRowStatus($subFolder);
 | ||
| 		$content .= "</td>";
 | ||
| 		$content .= "<td>";
 | ||
| 		$content .= $this->folderListRowAction($subFolder, $skipcont, $extracontent);
 | ||
| 		$content .= "</td>";
 | ||
| 		if(!$skipcont)
 | ||
| 			$content .= $this->folderListRowEnd($subFolder);
 | ||
| 		return $content;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function show(){ /* {{{ */
 | ||
| 		parent::show();
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	function error(){ /* {{{ */
 | ||
| 		parent::error();
 | ||
| 		$dms = $this->params['dms'];
 | ||
| 		$user = $this->params['user'];
 | ||
| 		$pagetitle = $this->params['pagetitle'];
 | ||
| 		$errormsg = $this->params['errormsg'];
 | ||
| 		$plain = $this->params['plain'];
 | ||
| 		$noexit = $this->params['noexit'];
 | ||
| 
 | ||
| 		if(!$plain) {	
 | ||
| 			$this->htmlStartPage($pagetitle);
 | ||
| 			$this->globalNavigation();
 | ||
| 			$this->contentStart();
 | ||
| 		}
 | ||
| 
 | ||
| 		$html = '';
 | ||
| 		$html .= "<h4>".getMLText('error')."!</h4>";
 | ||
| 		$html .= htmlspecialchars($errormsg);
 | ||
| 		$this->errorMsg($html);
 | ||
| 		print "<div><button class=\"btn history-back\">".getMLText('back')."</button></div>";
 | ||
| 		
 | ||
| 		$this->contentEnd();
 | ||
| 		$this->htmlEndPage();
 | ||
| 		
 | ||
| 		add_log_line(" UI::exitError error=".$errormsg." pagetitle=".$pagetitle, PEAR_LOG_ERR);
 | ||
| 
 | ||
| 		if($noexit)
 | ||
| 			return;
 | ||
| 
 | ||
| 		exit;	
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Return HTML Template for jumploader
 | ||
| 	 *
 | ||
| 	 * @param string $uploadurl URL where post data is send
 | ||
| 	 * @param integer $folderid id of folder where document is saved
 | ||
| 	 * @param integer $maxfiles maximum number of files allowed to upload
 | ||
| 	 * @param array $fields list of post fields
 | ||
| 	 */
 | ||
| 	function getFineUploaderTemplate() { /* {{{ */
 | ||
| 		return '
 | ||
| <script type="text/template" id="qq-template">
 | ||
| <div class="qq-uploader-selector qq-uploader" qq-drop-area-text="'.getMLText('drop_files_here').'">
 | ||
| 	<div class="qq-total-progress-bar-container-selector qq-total-progress-bar-container">
 | ||
| 		<div role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" class="qq-total-progress-bar-selector qq-progress-bar qq-total-progress-bar"></div>
 | ||
| 		</div>
 | ||
| 	<div class="input-group">
 | ||
| 	<div class="form-control qq-upload-drop-area-selector qq-upload-drop-area" _qq-hide-dropzone>
 | ||
| 		<span class="qq-upload-drop-area-text-selector"></span>
 | ||
| 	</div>
 | ||
| 	<div class="input-group-append">
 | ||
| 	<span class="btn btn-secondary qq-upload-button-selector qq-upload-button">'.getMLText('choose_target_file').'…</span>
 | ||
| 	</div>
 | ||
| 	</div>
 | ||
| 	<span class="qq-drop-processing-selector qq-drop-processing">
 | ||
| 		<span class="qq-drop-processing-spinner-selector qq-drop-processing-spinner"></span>
 | ||
| 	</span>
 | ||
| 	<ul class="qq-upload-list-selector qq-upload-list unstyled" aria-live="polite" aria-relevant="additions removals">
 | ||
| 		<li>
 | ||
| 			<div class="progress qq-progress-bar-container-selector">
 | ||
| 				<div class="bar qq-progress-bar-selector qq-progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
 | ||
| 			</div>
 | ||
| 			<span class="qq-upload-spinner-selector qq-upload-spinner"></span>
 | ||
| 			<img class="qq-thumbnail-selector" qq-max-size="100" qq-server-scale>
 | ||
| 			<span class="qq-upload-file-selector qq-upload-file"></span>
 | ||
| 			<span class="qq-upload-size-selector qq-upload-size"></span>
 | ||
| 			<button class="btn btn-sm btn-danger qq-btn qq-upload-cancel-selector qq-upload-cancel">Cancel</button>
 | ||
| 			<span role="status" class="qq-upload-status-text-selector qq-upload-status-text"></span>
 | ||
| 		</li>
 | ||
| 	</ul>
 | ||
| 	<dialog class="qq-alert-dialog-selector">
 | ||
| 		<div class="qq-dialog-message-selector"></div>
 | ||
| 		<div class="qq-dialog-buttons">
 | ||
| 			<button class="btn btn-sm btn-secondary qq-cancel-button-selector">Cancel</button>
 | ||
| 		</div>
 | ||
| 	</dialog>
 | ||
| 
 | ||
| 	<dialog class="qq-confirm-dialog-selector">
 | ||
| 		<div class="qq-dialog-message-selector"></div>
 | ||
| 		<div class="qq-dialog-buttons">
 | ||
| 			<button class="btn btn-sm btn-secondary qq-cancel-button-selector">Cancel</button>
 | ||
| 			<button class="btn btn-sm btn-primary qq-ok-button-selector">Ok</button>
 | ||
| 		</div>
 | ||
| 	</dialog>
 | ||
| 
 | ||
| 	<dialog class="qq-prompt-dialog-selector">
 | ||
| 		<div class="qq-dialog-message-selector"></div>
 | ||
| 		<input type="text">
 | ||
| 		<div class="qq-dialog-buttons">
 | ||
| 			<button class="btn qq-cancel-button-selector">Cancel</button>
 | ||
| 			<button class="btn qq-ok-button-selector">Ok</button>
 | ||
| 		</div>
 | ||
| 	</dialog>
 | ||
| </div>
 | ||
| </script>
 | ||
| ';
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Output HTML Code for Fine Uploader
 | ||
| 	 *
 | ||
| 	 * @param string $uploadurl URL where post data is send
 | ||
| 	 * @param integer $folderid id of folder where document is saved
 | ||
| 	 * @param integer $maxfiles maximum number of files allowed to upload
 | ||
| 	 * @param array $fields list of post fields
 | ||
| 	 */
 | ||
| 	function printFineUploaderHtml($prefix='userfile') { /* {{{ */
 | ||
| 		echo self::getFineUploaderHtml($prefix);
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Get HTML Code for Fine Uploader
 | ||
| 	 *
 | ||
| 	 * @param string $uploadurl URL where post data is send
 | ||
| 	 * @param integer $folderid id of folder where document is saved
 | ||
| 	 * @param integer $maxfiles maximum number of files allowed to upload
 | ||
| 	 * @param array $fields list of post fields
 | ||
| 	 */
 | ||
| 	function getFineUploaderHtml($prefix='userfile') { /* {{{ */
 | ||
| 		$html = '<div id="'.$prefix.'-fine-uploader"></div>
 | ||
| 		<input type="hidden" '.($prefix=='userfile' ? 'class="do_validate" ' : '').'id="'.$prefix.'-fine-uploader-uuids" name="'.$prefix.'-fine-uploader-uuids" value="" />
 | ||
| 		<input type="hidden" id="'.$prefix.'-fine-uploader-names" name="'.$prefix.'-fine-uploader-names" value="" />';
 | ||
| 		return $html;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Output Javascript Code for fine uploader
 | ||
| 	 *
 | ||
| 	 * @param string $uploadurl URL where post data is send
 | ||
| 	 * @param integer $folderid id of folder where document is saved
 | ||
| 	 * @param integer $maxfiles maximum number of files allowed to upload
 | ||
| 	 * @param array $fields list of post fields
 | ||
| 	 */
 | ||
| 	function printFineUploaderJs($uploadurl, $partsize=0, $maxuploadsize=0, $multiple=true, $prefix='userfile', $formname='form1') { /* {{{ */
 | ||
| ?>
 | ||
| $(document).ready(function() {
 | ||
| 	<?php echo $prefix; ?>uploader = new qq.FineUploader({
 | ||
| 		debug: false,
 | ||
| 		autoUpload: false,
 | ||
| 		multiple: <?php echo ($multiple ? 'true' : 'false'); ?>,
 | ||
| 		element: $('#<?php echo $prefix; ?>-fine-uploader')[0],
 | ||
| 		template: 'qq-template',
 | ||
| 		request: {
 | ||
| 			endpoint: '<?php echo $uploadurl."?formkey=".md5($this->params['settings']->_encryptionKey.'uploadchunks'); ?>'
 | ||
| 		},
 | ||
| <?php echo ($maxuploadsize > 0 ? '
 | ||
| 		validation: {
 | ||
| 			sizeLimit: '.$maxuploadsize.'
 | ||
| 		},
 | ||
| ' : ''); ?>
 | ||
| 		chunking: {
 | ||
| 			enabled: true,
 | ||
| 			<?php echo $partsize ? 'partSize: '.(int)$partsize.",\n" : ''; ?>
 | ||
| 			mandatory: true
 | ||
| 		},
 | ||
| 		messages: {
 | ||
| 			sizeError: '{file} is too large, maximum file size is {sizeLimit}.'
 | ||
| 		},
 | ||
| 		callbacks: {
 | ||
| 			onComplete: function(id, name, json, xhr) {
 | ||
| 			},
 | ||
| 			onAllComplete: function(succeeded, failed) {
 | ||
| 				var uuids = Array();
 | ||
| 				var names = Array();
 | ||
| 				for (var i = 0; i < succeeded.length; i++) {
 | ||
| 					uuids.push(this.getUuid(succeeded[i]))
 | ||
| 					names.push(this.getName(succeeded[i]))
 | ||
| 				}
 | ||
| 				$('#<?php echo $prefix; ?>-fine-uploader-uuids').val(uuids.join(';'));
 | ||
| 				$('#<?php echo $prefix; ?>-fine-uploader-names').val(names.join(';'));
 | ||
| 				/* Run upload only if all files could be uploaded */
 | ||
| 				if(succeeded.length > 0 && failed.length == 0)
 | ||
| 					document.getElementById('<?= $formname ?>').submit();
 | ||
| 			},
 | ||
| 			onError: function(id, name, reason, xhr) {
 | ||
| 				noty({
 | ||
| 					text: reason,
 | ||
| 					type: 'error',
 | ||
| 					dismissQueue: true,
 | ||
| 					layout: 'topRight',
 | ||
| 					theme: 'defaultTheme',
 | ||
| 					timeout: 3500,
 | ||
| 				});
 | ||
| 			}
 | ||
| 		}
 | ||
| 	});
 | ||
| });
 | ||
| <?php
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Output a protocol
 | ||
| 	 *
 | ||
| 	 * @param object $attribute attribute
 | ||
| 	 */
 | ||
| 	protected function printProtocol($latestContent, $type="") { /* {{{ */
 | ||
| 		$dms = $this->params['dms'];
 | ||
| 		$document = $latestContent->getDocument();
 | ||
| 		$accessop = $this->params['accessobject'];
 | ||
| ?>
 | ||
| 		<legend><?php printMLText($type.'_log'); ?></legend>
 | ||
| 		<table class="table table-sm">
 | ||
| 			<tr><th><?php printMLText('name'); ?></th><th><?php printMLText('last_update'); ?>, <?php printMLText('comment'); ?></th><th><?php printMLText('status'); ?></th></tr>
 | ||
| <?php
 | ||
| 		switch($type) {
 | ||
| 		case "review":
 | ||
| 			$statusList = $latestContent->getReviewStatus(10);
 | ||
| 			break;
 | ||
| 		case "approval":
 | ||
| 			$statusList = $latestContent->getApprovalStatus(10);
 | ||
| 			break;
 | ||
| 		default:
 | ||
| 			$statusList = array();
 | ||
| 		}
 | ||
| 		foreach($statusList as $rec) {
 | ||
| 			echo "<tr>";
 | ||
| 			echo "<td>";
 | ||
| 			switch ($rec["type"]) {
 | ||
| 				case 0: // individual.
 | ||
| 					$required = $dms->getUser($rec["required"]);
 | ||
| 					if (!is_object($required)) {
 | ||
| 						$reqName = getMLText("unknown_user")." '".$rec["required"]."'";
 | ||
| 					} else {
 | ||
| 						$reqName = htmlspecialchars($required->getFullName()." (".$required->getLogin().")");
 | ||
| 					}
 | ||
| 					break;
 | ||
| 				case 1: // Approver is a group.
 | ||
| 					$required = $dms->getGroup($rec["required"]);
 | ||
| 					if (!is_object($required)) {
 | ||
| 						$reqName = getMLText("unknown_group")." '".$rec["required"]."'";
 | ||
| 					}
 | ||
| 					else {
 | ||
| 						$reqName = "<i>".htmlspecialchars($required->getName())."</i>";
 | ||
| 					}
 | ||
| 					break;
 | ||
| 			}
 | ||
| 			echo $reqName;
 | ||
| 			echo "</td>";
 | ||
| 			echo "<td>";
 | ||
| 			echo "<i style=\"font-size: 80%;\">".getLongReadableDate($rec['date'])." - ";
 | ||
| 			$updateuser = $dms->getUser($rec["userID"]);
 | ||
| 			if(!is_object($updateuser))
 | ||
| 				echo getMLText("unknown_user");
 | ||
| 			else
 | ||
| 				echo htmlspecialchars($updateuser->getFullName()." (".$updateuser->getLogin().")");
 | ||
| 			echo "</i>";
 | ||
| 			if($rec['comment'])
 | ||
| 				echo "<br />".htmlspecialchars($rec['comment']);
 | ||
| 			switch($type) {
 | ||
| 			case "review":
 | ||
| 				if($accessop->check_controller_access('Download', array('action'=>'review')))
 | ||
| 					if($rec['file']) {
 | ||
| 						echo "<br />";
 | ||
| 						echo "<a href=\"".$this->params['settings']->_httpRoot."op/op.Download.php?documentid=".$document->getID()."&reviewlogid=".$rec['reviewLogID']."\" class=\"btn btn-mini\"><i class=\"fa fa-download\"></i> ".getMLText('download')."</a>";
 | ||
| 					}
 | ||
| 				break;
 | ||
| 			case "approval":
 | ||
| 				if($accessop->check_controller_access('Download', array('action'=>'approval')))
 | ||
| 					if($rec['file']) {
 | ||
| 						echo "<br />";
 | ||
| 						echo "<a href=\"".$this->params['settings']->_httpRoot."op/op.Download.php?documentid=".$document->getID()."&approvelogid=".$rec['approveLogID']."\" class=\"btn btn-mini\"><i class=\"fa fa-download\"></i> ".getMLText('download')."</a>";
 | ||
| 					}
 | ||
| 				break;
 | ||
| 			}
 | ||
| 			echo "</td>";
 | ||
| 			echo "<td>";
 | ||
| 			switch($type) {
 | ||
| 			case "review":
 | ||
| 				echo getReviewStatusText($rec["status"]);
 | ||
| 				break;
 | ||
| 			case "approval":
 | ||
| 				echo getApprovalStatusText($rec["status"]);
 | ||
| 				break;
 | ||
| 			default:
 | ||
| 			}
 | ||
| 			echo "</td>";
 | ||
| 			echo "</tr>";
 | ||
| 		}
 | ||
| ?>
 | ||
| 				</table>
 | ||
| <?php
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	protected function printWorkflowLog($wkflogs) { /* {{{ */
 | ||
| 		echo "<table class=\"table table-condensed table-sm\"><thead>";
 | ||
| 		echo "<th>".getMLText('workflow')."</th><th>".getMLText('date')."</th><th>".getMLText('action')."</th><th>".getMLText('user')."</th><th>".getMLText('comment')."</th></tr>\n";
 | ||
| 		echo "</thead><tbody>";
 | ||
| 		foreach($wkflogs as $wkflog) {
 | ||
| 			echo "<tr>";
 | ||
| 			echo "<td>".htmlspecialchars($wkflog->getWorkflow()->getName())."</td>";
 | ||
| 			echo "<td>".getLongReadableDate($wkflog->getDate())."</td>";
 | ||
| 		echo "<td>".htmlspecialchars(getMLText('action_'.strtolower($wkflog->getTransition()->getAction()->getName()), array(), $wkflog->getTransition()->getAction()->getName()))."</td>";
 | ||
| 			$loguser = $wkflog->getUser();
 | ||
| 			echo "<td>".htmlspecialchars($loguser->getFullName())."</td>";
 | ||
| 			echo "<td>".htmlspecialchars($wkflog->getComment())."</td>";
 | ||
| 			echo "</tr>";
 | ||
| 		}
 | ||
| 		print "</tbody>\n</table>\n";
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Show progressbar
 | ||
| 	 *
 | ||
| 	 * @param double $value value
 | ||
| 	 * @param double $max 100% value
 | ||
| 	 */
 | ||
| 	protected function getProgressBar($value, $max=100.0) { /* {{{ */
 | ||
| 		if($max > $value) {
 | ||
| 			$used = (int) ($value/$max*100.0+0.5);
 | ||
| 			$free = 100-$used;
 | ||
| 		} else {
 | ||
| 			$free = 0;
 | ||
| 			$used = 100;
 | ||
| 		}
 | ||
| 		$html = '
 | ||
| 		<div class="progress">
 | ||
| 			<div class="bar bar-danger bg-danger" style="width: '.$used.'%;"></div>
 | ||
| 		  <div class="bar bar-success bg-success" style="width: '.$free.'%;"></div>
 | ||
| 		</div>';
 | ||
| 		return $html;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Output a timeline for a document
 | ||
| 	 *
 | ||
| 	 * @param object $document document
 | ||
| 	 */
 | ||
| 	protected function printTimelineJs($timelineurl, $height=300, $start='', $end='', $skip=array(), $onselect="") { /* {{{ */
 | ||
| 		if(!$timelineurl)
 | ||
| 			return;
 | ||
| ?>
 | ||
| 		var timeline;
 | ||
| 		var data;
 | ||
| 
 | ||
| 		// specify options
 | ||
| 		var options = {
 | ||
| 			'width':  '100%',
 | ||
| 			'height': '100%',
 | ||
| <?php
 | ||
| 		if($start) {
 | ||
| 			$tmp = explode('-', $start);
 | ||
| 			echo "\t\t\t'min': new Date(".$tmp[0].", ".($tmp[1]-1).", ".$tmp[2]."),\n";
 | ||
| 		}
 | ||
| 		if($end) {
 | ||
| 			$tmp = explode('-', $end);
 | ||
| 			echo "'\t\t\tmax': new Date(".$tmp[0].", ".($tmp[1]-1).", ".$tmp[2]."),\n";
 | ||
| 		}
 | ||
| ?>
 | ||
| 			'editable': false,
 | ||
| 			'selectable': true,
 | ||
| 			'style': 'box',
 | ||
| 			'locale': '<?php echo $this->params['session']->getLanguage() ?>'
 | ||
| 		};
 | ||
| 
 | ||
| 		$(document).ready(function () {
 | ||
| 		// Instantiate our timeline object.
 | ||
| 		timeline = new links.Timeline(document.getElementById('timeline'), options);
 | ||
| <?php
 | ||
| 		if($onselect):
 | ||
| ?>
 | ||
| 		links.events.addListener(timeline, 'select', <?= $onselect ?>);
 | ||
| <?php
 | ||
| 		endif;
 | ||
| ?>
 | ||
| 		$.getJSON(
 | ||
| 			'<?php echo $timelineurl ?>', 
 | ||
| 			function(data) {
 | ||
| 				$.each( data, function( key, val ) {
 | ||
| 					val.start = new Date(val.start);
 | ||
| 				});
 | ||
| 				timeline.draw(data);
 | ||
| 			}
 | ||
| 		);
 | ||
| 		});
 | ||
| <?php
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	protected function printTimelineHtml($height) { /* {{{ */
 | ||
| ?>
 | ||
| 	<div id="timeline" style="height: <?php echo $height ?>px;"></div>
 | ||
| <?php
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	protected function printTimeline($timelineurl, $height=300, $start='', $end='', $skip=array()) { /* {{{ */
 | ||
| 		echo "<script type=\"text/javascript\">\n";
 | ||
| 		$this->printTimelineJs($timelineurl, $height, $start, $end, $skip);
 | ||
| 		echo "</script>";
 | ||
| 		$this->printTimelineHtml($height);
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	public function printPopupBox($title, $content, $ret=false) { /* {{{ */
 | ||
| 		$id = md5(uniqid());
 | ||
| 		/*
 | ||
| 		$this->addFooterJS('
 | ||
| $("body").on("click", "span.openpopupbox", function(e) {
 | ||
| 	$(""+$(e.target).data("href")).toggle();
 | ||
| //	$("div.popupbox").toggle();
 | ||
| });
 | ||
| ');
 | ||
| 		 */
 | ||
| 		$html = '
 | ||
| 		<span class="openpopupbox" data-href="#'.$id.'">'.$title.'</span>
 | ||
| 		<div id="'.$id.'" class="popupbox" style="display: none;">'.$content.'<span class="closepopupbox"><i class="fa fa-remove"></i></span>
 | ||
| 		</div>';
 | ||
| 		if($ret)
 | ||
| 			return $html;
 | ||
| 		else
 | ||
| 			echo $html;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	public function printAccordion($title, $content, $open=false) { /* {{{ */
 | ||
| 		$id = substr(md5(uniqid()), 0, 4);
 | ||
| ?>
 | ||
| 		<div class="accordion mb-4" id="accordion<?php echo $id; ?>">
 | ||
| 			<div class="card">
 | ||
| 				<div class="card-header" id="accordionheader<?php echo $id; ?>">
 | ||
| 				<a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion<?php echo $id; ?>" data-target="#collapse<?php echo $id; ?>"<?= $open ? ' aria-expanded="true"' : '' ?>>
 | ||
| 						<?php echo $title; ?>
 | ||
| 					</a>
 | ||
| 				</div>
 | ||
| 				<div id="collapse<?php echo $id; ?>" class="collapse<?= $open ? ' show' : '' ?>" data-parent="accordion<?php echo $id; ?>">
 | ||
| 					<div class="card-body">
 | ||
| <?php
 | ||
| 		echo $content;
 | ||
| ?>
 | ||
| 					</div>
 | ||
| 				</div>
 | ||
| 			</div>
 | ||
| 		</div>
 | ||
| <?php
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	public function printAccordion2($title, $content) { /* {{{ */
 | ||
| 		$id = substr(md5(uniqid()), 0, 4);
 | ||
| ?>
 | ||
| 		<div class="accordion2" id="accordion<?php echo $id; ?>">
 | ||
| 			<a class="accordion2-toggle" data-toggle="collapse" data-parent="#accordion<?php echo $id; ?>" data-target="#collapse<?php echo $id; ?>">
 | ||
| <?php
 | ||
| 			$this->contentHeading($title);
 | ||
| ?>
 | ||
| 			</a>
 | ||
| 			<div id="collapse<?php echo $id; ?>" class="collapse" data-parent="accordion<?php echo $id; ?>">
 | ||
| <?php
 | ||
| 		echo $content;
 | ||
| ?>
 | ||
| 			</div>
 | ||
| 		</div>
 | ||
| <?php
 | ||
| 	} /* }}} */
 | ||
| }
 | ||
| 
 | ||
| class_alias('SeedDMS_Theme_Style', 'SeedDMS_Bootstrap_Style');
 | 
