2010-09-10 16:45:26 +00:00
< ? php
/**
* $Id :
*
* KnowledgeTree Community Edition
* Document Management Made Simple
* Copyright ( C ) 2008 , 2009 KnowledgeTree Inc .
*
*
* This program is free software ; you can redistribute it and / or modify it under
* the terms of the GNU General Public License version 3 as published by the
* Free Software Foundation .
*
* 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 , see < http :// www . gnu . org / licenses />.
*
* You can contact KnowledgeTree Inc . , PO Box 7775 #87847, San Francisco,
* California 94120 - 7775 , or email info @ knowledgetree . com .
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices , as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7 ( b ) of the GNU General Public License version 3 ,
* these Appropriate Legal Notices must retain the display of the " Powered by
* KnowledgeTree " logo and retain the original copyright notice. If the display of the
* logo is not reasonably feasible for technical reasons , the Appropriate Legal Notices
* must display the words " Powered by KnowledgeTree " and retain the original
* copyright notice .
* Contributor ( s ) : ______________________________________
*
*/
require_once ( 'File/Archive.php' );
require_once ( KT_LIB_DIR . '/util/ktpclzip.inc.php' );
/**
* Class to create and download a zip file
*/
class ZipFolder {
var $sTmpPath = '' ;
var $sZipFileName = '' ;
var $sZipFile = '' ;
var $sPattern = '' ;
var $sFolderPattern = '' ;
var $aPaths = array ();
var $aReplaceKeys = array ();
var $aReplaceValues = array ();
var $sOutputEncoding = 'UTF-8' ;
var $extension = 'zip' ;
var $exportCode = null ;
/**
* Constructor
*
* @ param string $sZipFileName The name of the zip file - gets ignored at the moment .
* @ param string $exportCode The code to use if a zip file has already been created .
*/
function ZipFolder ( $sZipFileName = null , $exportCode = null , $extension = 'zip' ) {
$this -> oKTConfig =& KTConfig :: getSingleton ();
$this -> oStorage =& KTStorageManagerUtil :: getSingleton ();
$this -> sOutputEncoding = $this -> oKTConfig -> get ( 'export/encoding' , 'UTF-8' );
$this -> extension = $extension ;
$this -> sPattern = " [ \ *| \ %| \\ \ | \ /| \ <| \ >| \ +| \ :| \ ?| \ || \ '| \" ] " ;
$this -> sFolderPattern = " [ \ *| \ %| \ <| \ >| \ +| \ :| \ ?| \ || \ '| \" ] " ;
if ( ! empty ( $exportCode )){
$this -> exportCode = $exportCode ;
} else {
$this -> exportCode = KTUtil :: randomString ();
}
// Check if the temp directory has been created and stored in session
$aData = KTUtil :: arrayGet ( $_SESSION [ 'zipcompression' ], $exportCode );
if ( ! empty ( $aData ) && isset ( $aData [ 'dir' ])){
$sTmpPath = $aData [ 'dir' ];
} else {
$sBasedir = $this -> oKTConfig -> get ( " urls/tmpDirectory " );
$sTmpPath = tempnam ( $sBasedir , 'kt_compress_zip' );
unlink ( $sTmpPath );
mkdir ( $sTmpPath , 0755 );
}
// Hard coding the zip file name.
// It normally uses the folder name but if there are special characters in the name then it doesn't download properly.
$sZipFileName = 'kt_zip' ;
$this -> sTmpPath = $sTmpPath ;
$this -> sZipFileName = $sZipFileName ;
$this -> aPaths = array ();
$aReplace = array (
" [ " => " [[] " ,
" " => " [ ] " ,
" * " => " [*] " ,
" ? " => " [?] " ,
);
$this -> aReplaceKeys = array_keys ( $aReplace );
$this -> aReplaceValues = array_values ( $aReplace );
}
static public function get ( $exportCode )
{
static $zipFolder = null ;
if ( is_null ( $zipFolder )){
$zipFolder = new ZipFolder ( '' , $exportCode );
}
return $zipFolder ;
}
/**
* Return the full path
*
* @ param mixed $oFolderOrDocument May be a Folder or Document
*/
function getFullFolderPath ( $oFolder )
{
static $sRootFolder = null ;
if ( is_null ( $sRootFolder ))
{
$oRootFolder = Folder :: get ( 1 );
$sRootFolder = $oRootFolder -> getName ();
}
$sFullPath = $sRootFolder . '/' ;
$sFullPath .= $oFolder -> getFullPath ();
if ( substr ( $sFullPath , - 1 ) == '/' ) $sFullPath = substr ( $sFullPath , 0 , - 1 );
return $sFullPath ;
}
/**
* Add a document to the zip file
*/
function addDocumentToZip ( $oDocument , $oFolder = null ) {
if ( empty ( $oFolder )){
$oFolder = Folder :: get ( $oDocument -> getFolderID ());
}
$sDocPath = $this -> getFullFolderPath ( $oFolder );
$sDocPath = preg_replace ( $this -> sFolderPattern , '-' , $sDocPath );
$sDocPath = $this -> _convertEncoding ( $sDocPath , true );
$sDocName = $oDocument -> getFileName ();
$sDocName = preg_replace ( $this -> sPattern , '-' , $sDocName );
$sDocName = $this -> _convertEncoding ( $sDocName , true );
$sParentFolder = $this -> sTmpPath . '/' . $sDocPath ;
$newDir = $this -> sTmpPath ;
$aFullPath = split ( '/' , $sDocPath );
foreach ( $aFullPath as $dirPart ) {
$newDir = sprintf ( " %s/%s " , $newDir , $dirPart );
if ( ! file_exists ( $newDir )) {
mkdir ( $newDir , 0700 );
}
}
$sOrigFile = $this -> oStorage -> temporaryFile ( $oDocument );
$sFilename = $sParentFolder . '/' . $sDocName ;
@ copy ( $sOrigFile , $sFilename );
$this -> aPaths [] = $sDocPath . '/' . $sDocName ;
return true ;
}
/**
* Add a folder to the zip file
*/
function addFolderToZip ( $oFolder ) {
$sFolderPath = $this -> getFullFolderPath ( $oFolder ) . '/' ;
$sFolderPath = preg_replace ( $this -> sFolderPattern , '-' , $sFolderPath );
$sFolderPath = $this -> _convertEncoding ( $sFolderPath , true );
$newDir = $this -> sTmpPath ;
$aFullPath = split ( '/' , $sFolderPath );
foreach ( $aFullPath as $dirPart ) {
$newDir = sprintf ( " %s/%s " , $newDir , $dirPart );
if ( ! file_exists ( $newDir )) {
mkdir ( $newDir , 0700 );
}
}
$this -> aPaths [] = $sFolderPath ;
return true ;
}
/**
* Zip the temp folder
*/
function createZipFile ( $bEchoStatus = FALSE ) {
if ( empty ( $this -> aPaths )){
return PEAR :: raiseError ( _kt ( " No folders or documents found to compress " ));
}
2010-09-10 17:22:23 +00:00
/* $sZipFile = sprintf ( " %s/%s. " . $this -> extension , $this -> sTmpPath , $this -> sZipFileName );
2010-09-10 16:45:26 +00:00
$sZipFile = str_replace ( '<' , '' , str_replace ( '</' , '' , str_replace ( '>' , '' , $sZipFile )));
$archive = new KTPclZip ( $sZipFile );
2010-09-10 17:22:23 +00:00
$archive -> createZipFile ( $this -> sTmpPath . '/Root Folder' ); */
2010-09-10 16:45:26 +00:00
2010-09-10 17:22:23 +00:00
2010-09-10 16:45:26 +00:00
$config = KTConfig :: getSingleton ();
$useBinary = true ; //$config->get('export/useBinary', false);
// Set environment language to output character encoding
$loc = $this -> sOutputEncoding ;
putenv ( " LANG= $loc " );
putenv ( " LANGUAGE= $loc " );
$loc = setlocale ( LC_ALL , $loc );
if ( $useBinary ){
$sManifest = sprintf ( " %s/%s " , $this -> sTmpPath , " MANIFEST " );
file_put_contents ( $sManifest , join ( " \n " , $this -> aPaths ));
}
$sZipFile = sprintf ( " %s/%s. " . $this -> extension , $this -> sTmpPath , $this -> sZipFileName );
$sZipFile = str_replace ( '<' , '' , str_replace ( '</' , '' , str_replace ( '>' , '' , $sZipFile )));
if ( $useBinary ){
$sZipCommand = KTUtil :: findCommand ( " export/zip " , " zip " );
$aCmd = array ( $sZipCommand , " -r " , $sZipFile , " . " , " -i@MANIFEST " );
$sOldPath = getcwd ();
chdir ( $this -> sTmpPath );
// Note that the popen means that pexec will return a file descriptor
$aOptions = array ( 'popen' => 'r' );
$fh = KTUtil :: pexec ( $aCmd , $aOptions );
if ( $bEchoStatus ){
$last_beat = time ();
while ( ! feof ( $fh )) {
if ( $i % 1000 == 0 ) {
$this_beat = time ();
if ( $last_beat + 1 < $this_beat ) {
$last_beat = $this_beat ;
print " " ;
}
}
$contents = fread ( $fh , 4096 );
if ( $contents ) {
print nl2br ( $this -> _convertEncoding ( $contents , false ));
}
$i ++ ;
}
}
pclose ( $fh );
} else {
// Create the zip archive using the PEAR File_Archive
File_Archive :: extract (
File_Archive :: read ( $this -> sTmpPath . '/Root Folder' ),
File_Archive :: toArchive ( $this -> sZipFileName . '.' . $this -> extension , File_Archive :: toFiles ( $this -> sTmpPath ), $this -> extension )
);
}
2010-09-10 17:22:23 +00:00
2010-09-10 16:45:26 +00:00
// Save the zip file and path into session
$_SESSION [ 'zipcompression' ] = KTUtil :: arrayGet ( $_SESSION , 'zipcompression' , array ());
$sExportCode = $this -> exportCode ;
$_SESSION [ 'zipcompression' ][ $sExportCode ] = array (
'file' => $sZipFile ,
'dir' => $this -> sTmpPath ,
);
$_SESSION [ 'zipcompression' ][ 'exportcode' ] = $sExportCode ;
$this -> sZipFile = $sZipFile ;
return $sExportCode ;
}
/**
* Download the zip file
*/
function downloadZipFile ( $exportCode = NULL ) {
if ( ! ( isset ( $exportCode ) && ! empty ( $exportCode ))) {
$exportCode = KTUtil :: arrayGet ( $_SESSION [ 'zipcompression' ], 'exportcode' );
}
$aData = KTUtil :: arrayGet ( $_SESSION [ 'zipcompression' ], $exportCode );
if ( ! empty ( $aData )){
$sZipFile = $aData [ 'file' ];
$sTmpPath = $aData [ 'dir' ];
} else {
$sZipFile = $this -> sZipFile ;
$sTmpPath = $this -> sTmpPath ;
}
if ( ! file_exists ( $sZipFile )) {
return PEAR :: raiseError ( _kt ( ' The zip file has not been created , if you are downloading a large number of documents
or a large document then it may take a few minutes to finish . ' ));
}
$mimeType = 'application/zip; charset=utf-8;' ;
$fileSize = filesize ( $sZipFile );
$fileName = $this -> sZipFileName . '.' . $this -> extension ;
KTUtil :: download ( $sZipFile , $mimeType , $fileSize , $fileName );
KTUtil :: deleteDirectory ( $sTmpPath );
return true ;
}
function checkArchiveExists ( $exportCode = null )
{
if ( ! ( isset ( $exportCode ) && ! empty ( $exportCode ))) {
$exportCode = KTUtil :: arrayGet ( $_SESSION [ 'zipcompression' ], 'exportcode' );
}
$aData = KTUtil :: arrayGet ( $_SESSION [ 'zipcompression' ], $exportCode );
if ( ! empty ( $aData )){
$sZipFile = $aData [ 'file' ];
$sTmpPath = $aData [ 'dir' ];
} else {
$sZipFile = $this -> sZipFile ;
$sTmpPath = $this -> sTmpPath ;
}
if ( ! file_exists ( $sZipFile )) {
return false ;
}
return true ;
}
/**
* Check that iconv exists and that the selected encoding is supported .
*/
function checkConvertEncoding () {
if ( ! function_exists ( " iconv " )) {
return PEAR :: raiseError ( _kt ( 'IConv PHP extension not installed. The zip file compression could not handle output filename encoding conversion !' ));
}
$oKTConfig = $this -> oKTConfig ;
$this -> sOutputEncoding = $oKTConfig -> get ( 'export/encoding' , 'UTF-8' );
// Test the specified encoding
if ( iconv ( " UTF-8 " , $this -> sOutputEncoding , " " ) === FALSE ) {
return PEAR :: raiseError ( _kt ( 'Specified output encoding for the zip files compression does not exists !' ));
}
return true ;
}
function _convertEncoding ( $sMystring , $bEncode ) {
2010-09-10 17:22:23 +00:00
/* if ( strcasecmp ( $this -> sOutputEncoding , " UTF-8 " ) === 0 ) {
2010-09-10 16:45:26 +00:00
return $sMystring ;
2010-09-10 17:22:23 +00:00
} */
2010-09-10 16:45:26 +00:00
if ( $bEncode ) {
return iconv ( " UTF-8 " , $this -> sOutputEncoding , $sMystring );
} else {
return iconv ( $this -> sOutputEncoding , " UTF-8 " , $sMystring );
}
}
static public function checkDownloadSize ( $object )
{
return true ;
if ( $object instanceof Document || $object instanceof DocumentProxy ){
}
if ( $object instanceof Folder || $object instanceof FolderProxy ){
$id = $object -> iId ;
// If we're working with the root folder
if ( $id = 1 ){
$sql = 'SELECT count(*) as cnt FROM documents where folder_id = 1' ;
} else {
$sql [] = " SELECT count(*) as cnt FROM documents where parent_folder_ids like '%,?' OR parent_folder_ids like '%,?,%' OR folder_id = ? " ;
$sql [] = array ( $id , $id , $id );
}
/*
SELECT count ( * ) FROM documents d
INNER JOIN document_metadata_version m ON d . metadata_version_id = m . id
INNER JOIN document_content_version c ON m . content_version_id = c . id
where ( d . parent_folder_ids like '%,12' OR d . parent_folder_ids like '%,12,%' OR d . folder_id = 12 ) AND d . status_id < 3 AND size > 100000
*/
$result = DBUtil :: getOneResult ( $sql );
if ( $result [ 'cnt' ] > 10 ){
return true ;
}
}
return false ;
}
}
/**
* Class to manage the queue of bulk downloads
*
*/
class DownloadQueue
{
private $bNoisy ;
private $bNotifications ;
private $errors ;
private $lockFile ;
/**
* Construct download queue object
*
* @ return DownloadQueue
*/
public function __construct ()
{
$config = KTConfig :: getSingleton ();
$this -> bNoisy = $config -> get ( 'tweaks/noisyBulkOperations' , false );
$this -> bNotifications = ( $config -> get ( 'export/enablenotifications' , 'on' ) == 'on' ) ? true : false ;
$this -> lockFile = $config -> get ( 'cache/cacheDirectory' ) . '/download_queue_lock.lock' ;
}
/**
* Add an item to the download queue
*
* @ param string $code The identification string for the download
* @ param string $id The object id
* @ param string $type The type of object Folder | Document
*/
static public function addItem ( $code , $folderId , $id , $type )
{
$fields = array ();
$fields [ 'code' ] = $code ;
$fields [ 'folder_id' ] = $folderId ;
$fields [ 'object_id' ] = $id ;
$fields [ 'object_type' ] = $type ;
$fields [ 'user_id' ] = $_SESSION [ 'userID' ];
$fields [ 'date_added' ] = date ( 'Y-m-d H:i:s' );
$res = DBUtil :: autoInsert ( 'download_queue' , $fields );
}
/**
* Remove an item from the download queue
*
* @ param string $code Identification string for the download item
* @ return boolean | PEAR_Error
*/
public function removeItem ( $code )
{
$where = array ( 'code' => $code );
$res = DBUtil :: whereDelete ( 'download_queue' , $where );
return $res ;
}
/**
* Get all download items in the queue
*
* @ return Queue array | PEAR_Error
*/
public function getQueue ()
{
$sql = 'SELECT * FROM download_queue d WHERE status = 0 ORDER BY date_added, code' ;
$rows = DBUtil :: getResultArray ( $sql );
if ( PEAR :: isError ( $rows )){
return $rows ;
}
$queue = array ();
foreach ( $rows as $item ){
$queue [ $item [ 'code' ]][] = $item ;
}
return $queue ;
}
/**
* Get the status of an item in the queue
* 0 = new item ; 1 = in progress ; 2 = completed ; 3 = error ;
*
* @ param string $code
* @ return Queue array
*/
public function getItemStatus ( $code )
{
$sql = array ();
$sql [] = 'SELECT status, errors FROM download_queue WHERE code = ?' ;
$sql [] = $code ;
$result = DBUtil :: getResultArray ( $sql );
return $result ;
}
/**
* Set the status of an item and any errors that may have occurred while trying to archive it .
*
* @ param string $code The identification string
* @ param integer $status The new status of the item
* @ param string $error Optional . The error ' s generated during the archive
* @ return boolean
*/
public function setItemStatus ( $code , $status = 1 , $error = null )
{
$fields = array ();
$fields [ 'status' ] = $status ;
$fields [ 'errors' ] = ! empty ( $error ) ? json_encode ( $error ) : null ;
$where = array ( 'code' => $code );
$res = DBUtil :: whereUpdate ( 'download_queue' , $fields , $where );
return $res ;
}
/**
* Loop through the queue and archive the items .
*
* @ return unknown
*/
public function processQueue ()
{
global $default ;
// get items from queue
$queue = $this -> getQueue ();
if ( PEAR :: isError ( $queue )){
$default -> log -> debug ( 'Download Queue: error on fetching queue - ' . $queue -> getMessage ());
return false ;
}
// Set queue as locked
touch ( $this -> lockFile );
// Loop through items and create downloads
foreach ( $queue as $code => $download ){
// reset the error messages
$this -> errors = null ;
// if the user_id is not set then skip
if ( ! isset ( $download [ 0 ][ 'user_id' ]) || empty ( $download [ 0 ][ 'user_id' ])){
$default -> log -> debug ( 'Download Queue: no user id set for download code ' . $code );
$error = array ( _kt ( 'No user id has been set, the archive cannot be created.' ));
$result = $this -> setItemStatus ( $code , 3 , $error );
continue ;
}
// Force a session for the user
$_SESSION [ 'userID' ] = $download [ 0 ][ 'user_id' ];
$baseFolderId = $download [ 0 ][ 'folder_id' ];
// Create a new instance of the archival class
$zip = new ZipFolder ( '' , $code );
$res = $zip -> checkConvertEncoding ();
if ( PEAR :: isError ( $res )){
$default -> log -> error ( 'Download Queue: Archive class check convert encoding error - ' . $res -> getMessage ());
$error = array ( _kt ( 'The archive cannot be created. An error occurred in the encoding.' ));
$result = $this -> setItemStatus ( $code , 3 , $error );
continue ;
}
$result = $this -> setItemStatus ( $code , 1 );
if ( PEAR :: isError ( $result )){
$default -> log -> error ( 'Download Queue: item status could not be set for user: ' . $_SESSION [ 'userID' ] . ', code: ' . $code . ', error: ' . $result -> getMessage ());
}
$default -> log -> debug ( 'Download Queue: Creating download for user: ' . $_SESSION [ 'userID' ] . ', code: ' . $code );
DBUtil :: startTransaction ();
// Add the individual files and folders into the archive
foreach ( $download as $item ){
if ( $item [ 'object_type' ] == 'document' ){
$docId = $item [ 'object_id' ];
$this -> addDocument ( $zip , $docId );
}
if ( $item [ 'object_type' ] == 'folder' ){
$folderId = $item [ 'object_id' ];
$this -> addFolder ( $zip , $folderId );
}
}
$res = $zip -> createZipFile ();
if ( PEAR :: isError ( $res )){
$default -> log -> debug ( 'Download Queue: Archive could not be created. Exiting transaction. ' . $res -> getMessage ());
DBUtil :: rollback ();
$error = array ( _kt ( 'The archive could not be created.' ));
$result = $this -> setItemStatus ( $code , 3 , $error );
continue ;
}
$default -> log -> debug ( 'Download Queue: Archival successful' );
$oTransaction = KTFolderTransaction :: createFromArray ( array (
'folderid' => $baseFolderId ,
'comment' => " Bulk export " ,
'transactionNS' => 'ktstandard.transactions.bulk_export' ,
'userid' => $_SESSION [ 'userID' ],
'ip' => Session :: getClientIP (),
));
if ( PEAR :: isError ( $oTransaction )){
$default -> log -> debug ( 'Download Queue: transaction could not be logged. ' . $oTransaction -> getMessage ());
}
DBUtil :: commit ();
// Set status for the download
$this -> errors [ 'archive' ] = $_SESSION [ 'zipcompression' ];
$result = $this -> setItemStatus ( $code , 2 , $this -> errors );
if ( PEAR :: isError ( $result )){
$default -> log -> error ( 'Download Queue: item status could not be set for user: ' . $_SESSION [ 'userID' ] . ', code: ' . $code . ', error: ' . $result -> getMessage ());
}
// reset the error messages
$this -> errors = null ;
$_SESSION [ 'zipcompression' ] = null ;
}
// Remove lock file
@ unlink ( $this -> lockFile );
}
/**
* Add a document to the archive
*
* @ param unknown_type $zip
* @ param unknown_type $docId
* @ return unknown
*/
public function addDocument ( & $zip , $docId )
{
$oDocument = Document :: get ( $docId );
if ( PEAR :: isError ( $oDocument )){
$this -> errors [] = _kt ( 'Document cannot be exported, an error occurred: ' ) . $oDocument -> getMessage ();
return $oDocument ;
}
if ( $this -> bNoisy ) {
$oDocumentTransaction = new DocumentTransaction ( $oDocument , " Document part of bulk export " , 'ktstandard.transactions.bulk_export' , array ());
$oDocumentTransaction -> create ();
}
// fire subscription alerts for the downloaded document - if global config is set
if ( $this -> bNotifications ){
$oSubscriptionEvent = new SubscriptionEvent ();
$oFolder = Folder :: get ( $oDocument -> getFolderID ());
$oSubscriptionEvent -> DownloadDocument ( $oDocument , $oFolder );
}
return $zip -> addDocumentToZip ( $oDocument );
}
/**
* Add a folder to the archive
*
* @ param unknown_type $zip
* @ param unknown_type $folderId
* @ return unknown
*/
public function addFolder ( & $zip , $folderId )
{
$oFolder = Folder :: get ( $folderId );
if ( PEAR :: isError ( $oFolder )){
$this -> errors [] = _kt ( 'Folder cannot be exported, an error occurred: ' ) . $oFolder -> getMessage ();
return $oFolder ;
}
$sFolderDocs = $oFolder -> getDocumentIDs ( $folderId );
if ( PEAR :: isError ( $sFolderDocs )){
$default -> log -> error ( 'Download Queue: get document ids for folder caused an error: ' . $sFolderDocs -> getMessage ());
$sFolderDocs = '' ;
}
// Add folder to zip
$zip -> addFolderToZip ( $oFolder );
$aDocuments = array ();
if ( ! empty ( $sFolderDocs )){
$aDocuments = explode ( ',' , $sFolderDocs );
}
// Get all the folders within the current folder
$sWhereClause = " parent_folder_ids like '%, { $folderId } '
OR parent_folder_ids like '%,{$folderId},%'
OR parent_folder_ids like '{$folderId},%'
OR parent_id = { $folderId } " ;
$aFolderList = $oFolder -> getList ( $sWhereClause );
$aLinkingFolders = $this -> getLinkingEntities ( $aFolderList );
$aFolderList = array_merge ( $aFolderList , $aLinkingFolders );
$aFolderObjects = array ();
$aFolderObjects [ $folderId ] = $oFolder ;
// Export the folder structure to ensure the export of empty directories
if ( ! empty ( $aFolderList )){
foreach ( $aFolderList as $k => $oFolderItem ){
if ( $oFolderItem -> isSymbolicLink ()){
$oFolderItem = $oFolderItem -> getLinkedFolder ();
}
if ( Permission :: userHasFolderReadPermission ( $oFolderItem )){
// Get documents for each folder
$sFolderItemId = $oFolderItem -> getID ();
$sFolderItemDocs = $oFolderItem -> getDocumentIDs ( $sFolderItemId );
if ( ! empty ( $sFolderItemDocs )){
$aFolderDocs = explode ( ',' , $sFolderItemDocs );
$aDocuments = array_merge ( $aDocuments , $aFolderDocs );
}
$zip -> addFolderToZip ( $oFolderItem );
$aFolderObjects [ $oFolderItem -> getId ()] = $oFolderItem ;
}
}
}
// Add all documents to the export
if ( ! empty ( $aDocuments )){
foreach ( $aDocuments as $sDocumentId ){
$oDocument = Document :: get ( $sDocumentId );
if ( $oDocument -> isSymbolicLink ()){
$oDocument -> switchToLinkedCore ();
}
if ( Permission :: userHasDocumentReadPermission ( $oDocument )){
if ( ! KTWorkflowUtil :: actionEnabledForDocument ( $oDocument , 'ktcore.actions.document.view' )){
$this -> errors [] = $oDocument -> getName () . ': ' . _kt ( 'Document cannot be exported as it is restricted by the workflow.' );
continue ;
}
$sDocFolderId = $oDocument -> getFolderID ();
$oFolder = isset ( $aFolderObjects [ $sDocFolderId ]) ? $aFolderObjects [ $sDocFolderId ] : Folder :: get ( $sDocFolderId );
if ( $this -> bNoisy ) {
$oDocumentTransaction = new DocumentTransaction ( $oDocument , " Document part of bulk export " , 'ktstandard.transactions.bulk_export' , array ());
$oDocumentTransaction -> create ();
}
// fire subscription alerts for the downloaded document
if ( $this -> bNotifications ){
$oSubscriptionEvent = new SubscriptionEvent ();
$oSubscriptionEvent -> DownloadDocument ( $oDocument , $oFolder );
}
$zip -> addDocumentToZip ( $oDocument , $oFolder );
}
}
}
}
/**
* Fetch any linked folders
*
* @ param Folder array $aFolderList
* @ return unknown
*/
function getLinkingEntities ( $aFolderList ){
$aSearchFolders = array ();
if ( ! empty ( $aFolderList )){
foreach ( $aFolderList as $oFolderItem ){
if ( Permission :: userHasFolderReadPermission ( $oFolderItem )){
// If it is a shortcut, we should do some more searching
if ( $oFolderItem -> isSymbolicLink ()){
$oFolderItem = $oFolderItem -> getLinkedFolder ();
$aSearchFolders [] = $oFolderItem -> getID ();
}
}
}
}
$aLinkingFolders = array ();
$aSearchCompletedFolders = array ();
$count = 0 ;
while ( count ( $aSearchFolders ) > 0 ){
$count ++ ;
$oFolder = Folder :: get ( array_pop ( $aSearchFolders ));
$folderId = $oFolder -> getId ();
// Get all the folders within the current folder
$sWhereClause = " parent_folder_ids = ' { $folderId } ' OR
parent_folder_ids LIKE '{$folderId},%' OR
parent_folder_ids LIKE '%,{$folderId},%' OR
parent_folder_ids LIKE '%,{$folderId}' " ;
$aFolderList = $this -> oFolder -> getList ( $sWhereClause );
foreach ( $aFolderList as $oFolderItem ){
if ( $oFolderItem -> isSymbolicLink ()){
$oFolderItem = $oFolderItem -> getLinkedFolder ();
}
if ( Permission :: userHasFolderReadPermission ( $oFolderItem )){
if ( $aSearchCompletedFolders [ $oFolderItem -> getID ()] != true ){
$aSearchFolders [] = $oFolderItem -> getID ();
$aSearchCompletedFolders [ $oFolderItem -> getID ()] = true ;
}
}
}
if ( ! isset ( $aLinkingFolders [ $oFolder -> getId ()])){
$aLinkingFolders [ $oFolder -> getId ()] = $oFolder ;
}
}
return $aLinkingFolders ;
}
/**
* Check if the archive has been created and is ready for download
*
* @ param string $code
* @ return boolean
*/
public function isDownloadAvailable ( $code )
{
$check = $this -> getItemStatus ( $code );
$status = $check [ 0 ][ 'status' ];
if ( $status < 2 ){
return false ;
}
$message = $check [ 0 ][ 'errors' ];
$message = json_decode ( $message , true );
if ( $status > 2 ){
return $message ;
}
// Create the archive session variables
$_SESSION [ 'zipcompression' ] = $message [ 'archive' ];
unset ( $message [ 'archive' ]);
// Check that the archive has been created
$zip = new ZipFolder ( '' , $code );
if ( $zip -> checkArchiveExists ( $code )){
// Clean up the download queue and return errors
$this -> removeItem ( $code );
return $message ;
}
return false ;
}
/**
* Check if the queue is locked and busy processing
*
* @ return boolean
*/
public function isLocked ()
{
return file_exists ( $this -> lockFile );
}
}
?>