Commit 8ba6b67ecf09bc33523c1353d245aaa0d3550ef8

Authored by Megan Watson
1 parent 82c4f1a1

KTS-2390

"Need a way to download or checkout multiple files at the same time"
Refactored the code to zip files into a class. Updated the Bulk Export with the new class. Added the bulk check out action.

Committed by: Megan Watson
Reviewed by: Conrad Vermeulen



git-svn-id: https://kt-dms.svn.sourceforge.net/svnroot/kt-dms/trunk@7301 c91229c3-7414-0410-bfa2-8a42b809f60b
lib/foldermanagement/compressionArchiveUtil.inc.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * $Id:
  4 + *
  5 + * The contents of this file are subject to the KnowledgeTree Public
  6 + * License Version 1.1.2 ("License"); You may not use this file except in
  7 + * compliance with the License. You may obtain a copy of the License at
  8 + * http://www.knowledgetree.com/KPL
  9 + *
  10 + * Software distributed under the License is distributed on an "AS IS"
  11 + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
  12 + * See the License for the specific language governing rights and
  13 + * limitations under the License.
  14 + *
  15 + * All copies of the Covered Code must include on each user interface screen:
  16 + * (i) the "Powered by KnowledgeTree" logo and
  17 + * (ii) the KnowledgeTree copyright notice
  18 + * in the same form as they appear in the distribution. See the License for
  19 + * requirements.
  20 + *
  21 + * The Original Code is: KnowledgeTree Open Source
  22 + *
  23 + * The Initial Developer of the Original Code is The Jam Warehouse Software
  24 + * (Pty) Ltd, trading as KnowledgeTree.
  25 + * Portions created by The Jam Warehouse Software (Pty) Ltd are Copyright
  26 + * (C) 2007 The Jam Warehouse Software (Pty) Ltd;
  27 + * All Rights Reserved.
  28 + * Contributor( s): ______________________________________
  29 + *
  30 + */
  31 +
  32 +/**
  33 +* Class to create and download a zip file
  34 +*/
  35 +class ZipFolder {
  36 +
  37 + var $sTmpPath = '';
  38 + var $sZipFileName = '';
  39 + var $sZipFile = '';
  40 + var $aPaths = array();
  41 + var $aReplaceKeys = array();
  42 + var $aReplaceValues = array();
  43 + var $sOutputEncoding = 'UTF-8';
  44 +
  45 + /**
  46 + * Constructor
  47 + */
  48 + function ZipFolder($sZipFileName) {
  49 + $this->oKTConfig =& KTConfig::getSingleton();
  50 + $this->oStorage =& KTStorageManagerUtil::getSingleton();
  51 +
  52 + $sBasedir = $this->oKTConfig->get("urls/tmpDirectory");
  53 + $sTmpPath = tempnam($sBasedir, 'kt_compress_zip');
  54 +
  55 + unlink($sTmpPath);
  56 + mkdir($sTmpPath, 0700);
  57 +
  58 + $this->sTmpPath = $sTmpPath;
  59 + $this->sZipFileName = $sZipFileName;
  60 + $this->aPaths = array();
  61 +
  62 + $aReplace = array(
  63 + "[" => "[[]",
  64 + " " => "[ ]",
  65 + "*" => "[*]",
  66 + "?" => "[?]",
  67 + );
  68 +
  69 + $this->aReplaceKeys = array_keys($aReplace);
  70 + $this->aReplaceValues = array_values($aReplace);
  71 + }
  72 +
  73 + /**
  74 + * Add a document to the zip file
  75 + */
  76 + function addDocumentToZip($oDocument) {
  77 + $sParentFolder = str_replace('<', '', str_replace('</', '', str_replace('>', '', sprintf('%s/%s', $this->sTmpPath, $oDocument->getFullPath()))));
  78 + $newDir = $this->sTmpPath;
  79 + $sFullPath = str_replace('<', '', str_replace('</', '', str_replace('>', '', $this->_convertEncoding($oDocument->getFullPath(), true))));
  80 + foreach (split('/', $sFullPath) as $dirPart) {
  81 + $newDir = sprintf("%s/%s", $newDir, $dirPart);
  82 + if (!file_exists($newDir)) {
  83 + mkdir($newDir, 0700);
  84 + }
  85 + }
  86 +
  87 + $sOrigFile = str_replace('<', '', str_replace('</', '', str_replace('>', '', $this->oStorage->temporaryFile($oDocument))));
  88 + $sFilename = sprintf("%s/%s", $sParentFolder, str_replace('<', '', str_replace('</', '', str_replace('>', '', $oDocument->getFileName()))));
  89 + $sFilename = $this->_convertEncoding($sFilename, true);
  90 + copy($sOrigFile, $sFilename);
  91 +
  92 + $sPath = str_replace('<', '', str_replace('</', '', str_replace('>', '', sprintf("%s/%s", $oDocument->getFullPath(), $oDocument->getFileName()))));
  93 + $sPath = str_replace($this->aReplaceKeys, $this->aReplaceValues, $sPath);
  94 + $sPath = $this->_convertEncoding($sPath, true);
  95 +
  96 + $this->aPaths[] = $sPath;
  97 + return true;
  98 + }
  99 +
  100 + /**
  101 + * Add a folder to the zip file
  102 + */
  103 + function addFolderToZip($oFolder) {
  104 + $sFolderPath = $oFolder->getFullPath().'/'.$oFolder->getName().'/';
  105 + $sParentFolder = str_replace('<', '', str_replace('</', '', str_replace('>', '', sprintf('%s/%s', $this->sTmpPath, $sFolderPath))));
  106 + $newDir = $this->sTmpPath;
  107 + $sFullPath = str_replace('<', '', str_replace('</', '', str_replace('>', '', $this->_convertEncoding($sFolderPath, true))));
  108 + foreach (split('/', $sFullPath) as $dirPart) {
  109 + $newDir = sprintf("%s/%s", $newDir, $dirPart);
  110 + if (!file_exists($newDir)) {
  111 + mkdir($newDir, 0700);
  112 + }
  113 + }
  114 +
  115 + $sPath = str_replace('<', '', str_replace('</', '', str_replace('>', '', sprintf("%s", $sFolderPath))));
  116 + $sPath = str_replace($this->aReplaceKeys, $this->aReplaceValues, $sPath);
  117 + $sPath = $this->_convertEncoding($sPath, true);
  118 +
  119 + $this->aPaths[] = $sPath;
  120 + return true;
  121 + }
  122 +
  123 + /**
  124 + * Zip the temp folder
  125 + */
  126 + function createZipFile($bEchoStatus = FALSE) {
  127 + if(empty($this->aPaths)){
  128 + return PEAR::raiseError(_kt("No folders or documents found to compress"));
  129 + //$this->addErrorMessage(_kt("No folders or documents found to compress"));
  130 + //return false;
  131 + }
  132 +
  133 + $sManifest = sprintf("%s/%s", $this->sTmpPath, "MANIFEST");
  134 + file_put_contents($sManifest, join("\n", $this->aPaths));
  135 + $sZipFile = sprintf("%s/%s.zip", $this->sTmpPath, $this->sZipFileName);
  136 + $sZipFile = str_replace('<', '', str_replace('</', '', str_replace('>', '', $sZipFile)));
  137 + $sZipCommand = KTUtil::findCommand("export/zip", "zip");
  138 + $aCmd = array($sZipCommand, "-r", $sZipFile, ".", "-i@MANIFEST");
  139 + $sOldPath = getcwd();
  140 + chdir($this->sTmpPath);
  141 + // Note that the popen means that pexec will return a file descriptor
  142 + $aOptions = array('popen' => 'r');
  143 + $fh = KTUtil::pexec($aCmd, $aOptions);
  144 +
  145 + if($bEchoStatus){
  146 + $last_beat = time();
  147 + while(!feof($fh)) {
  148 + if ($i % 1000 == 0) {
  149 + $this_beat = time();
  150 + if ($last_beat + 1 < $this_beat) {
  151 + $last_beat = $this_beat;
  152 + print "&nbsp;";
  153 + }
  154 + }
  155 + $contents = fread($fh, 4096);
  156 + if ($contents) {
  157 + print nl2br($this->_convertEncoding($contents, false));
  158 + }
  159 + $i++;
  160 + }
  161 + }
  162 + pclose($fh);
  163 +
  164 + // Save the zip file and path into session
  165 + $_SESSION['zipcompression'] = KTUtil::arrayGet($_SESSION, 'zipcompression', array());
  166 + $sExportCode = KTUtil::randomString();
  167 + $_SESSION['zipcompression'][$sExportCode] = array(
  168 + 'file' => $sZipFile,
  169 + 'dir' => $this->oZip->sTmpPath,
  170 + );
  171 + $_SESSION['zipcompression']['exportcode'] = $sExportCode;
  172 +
  173 + $this->sZipFile = $sZipFile;
  174 + return $sExportCode;
  175 + }
  176 +
  177 + /**
  178 + * Download the zip file
  179 + */
  180 + function downloadZipFile($exportCode = NULL) {
  181 + if(!(isset($exportCode) && !empty($exportCode))) {
  182 + $exportCode = KTUtil::arrayGet($_SESSION['zipcompression'], 'exportcode');
  183 + }
  184 + $aData = KTUtil::arrayGet($_SESSION['zipcompression'], $exportCode);
  185 +
  186 + if(!empty($aData)){
  187 + $sZipFile = $aData['file'];
  188 + $sTmpPath = $aData['dir'];
  189 + }else{
  190 + $sZipFile = $this->sZipFile;
  191 + $sTmpPath = $this->sTmpPath;
  192 + }
  193 +
  194 + if (!file_exists($sZipFile)) {
  195 + return PEAR::raiseError(_kt('The ZIP file can only be downloaded once - if you cancel the download, you will need to reload the page.'));
  196 + }
  197 +
  198 + header("Content-Type: application/zip");
  199 + header("Content-Length: ". filesize($sZipFile));
  200 + header("Content-Disposition: attachment; filename=\"" . $this->sZipFileName . ".zip" . "\"");
  201 + header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
  202 + header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
  203 + header("Cache-Control: must-revalidate");
  204 + readfile($sZipFile);
  205 + $sTmpDir = $sTmpPath;
  206 + KTUtil::deleteDirectory($sTmpDir);
  207 + return true;
  208 + }
  209 +
  210 + /**
  211 + * Check that iconv exists and that the selected encoding is supported.
  212 + */
  213 + function checkConvertEncoding() {
  214 + if(!function_exists("iconv")) {
  215 + return PEAR::raiseError(_kt('IConv PHP extension not installed. The zip file compression could not handle output filename encoding conversion !'));
  216 + }
  217 + $oKTConfig = $this->oKTConfig;
  218 + $this->sOutputEncoding = $oKTConfig->get('export/encoding', 'UTF-8');
  219 +
  220 + // Test the specified encoding
  221 + if(iconv("UTF-8", $this->sOutputEncoding, "") === FALSE) {
  222 + return PEAR::raiseError(_kt('Specified output encoding for the zip files compression does not exists !'));
  223 + }
  224 + return true;
  225 + }
  226 +
  227 + function _convertEncoding($sMystring, $bEncode) {
  228 + if (strcasecmp($this->sOutputEncoding, "UTF-8") === 0) {
  229 + return $sMystring;
  230 + }
  231 + if ($bEncode) {
  232 + return iconv("UTF-8", $this->sOutputEncoding, $sMystring);
  233 + } else {
  234 + return iconv($this->sOutputEncoding, "UTF-8", $sMystring);
  235 + }
  236 + }
  237 +}
  238 +?>
0 \ No newline at end of file 239 \ No newline at end of file
plugins/ktcore/KTBulkActions.php
@@ -31,6 +31,7 @@ @@ -31,6 +31,7 @@
31 31
32 require_once(KT_LIB_DIR . '/actions/bulkaction.php'); 32 require_once(KT_LIB_DIR . '/actions/bulkaction.php');
33 require_once(KT_LIB_DIR . '/widgets/forms.inc.php'); 33 require_once(KT_LIB_DIR . '/widgets/forms.inc.php');
  34 +require_once(KT_LIB_DIR . '/foldermanagement/compressionArchiveUtil.inc.php');
34 35
35 36
36 class KTBulkDeleteAction extends KTBulkAction { 37 class KTBulkDeleteAction extends KTBulkAction {
@@ -486,33 +487,33 @@ class KTBulkArchiveAction extends KTBulkAction { @@ -486,33 +487,33 @@ class KTBulkArchiveAction extends KTBulkAction {
486 DBUtil::rollback(); 487 DBUtil::rollback();
487 return false; 488 return false;
488 } 489 }
489 - 490 +
490 $oDocumentTransaction = & new DocumentTransaction($document, sprintf(_kt('Document archived: %s'), $this->sReason), 'ktcore.transactions.update'); 491 $oDocumentTransaction = & new DocumentTransaction($document, sprintf(_kt('Document archived: %s'), $this->sReason), 'ktcore.transactions.update');
491 $oDocumentTransaction->create(); 492 $oDocumentTransaction->create();
492 - 493 +
493 DBUtil::commit(); 494 DBUtil::commit();
494 return true; 495 return true;
495 }else if(is_a($oEntity, 'Folder')) { 496 }else if(is_a($oEntity, 'Folder')) {
496 DBUtil::startTransaction(); 497 DBUtil::startTransaction();
497 - 498 +
498 $aDocuments = array(); 499 $aDocuments = array();
499 $aChildFolders = array(); 500 $aChildFolders = array();
500 $oFolder = $oEntity; 501 $oFolder = $oEntity;
501 - 502 +
502 // Get folder id 503 // Get folder id
503 $sFolderId = $oFolder->getID(); 504 $sFolderId = $oFolder->getID();
504 - 505 +
505 // Get documents in folder 506 // Get documents in folder
506 $sDocuments = $oFolder->getDocumentIDs($sFolderId); 507 $sDocuments = $oFolder->getDocumentIDs($sFolderId);
507 $aDocuments = explode(',', $sDocuments); 508 $aDocuments = explode(',', $sDocuments);
508 - 509 +
509 // Get all the folders within the folder 510 // Get all the folders within the folder
510 $sWhereClause = "parent_folder_ids = '{$sFolderId}' OR 511 $sWhereClause = "parent_folder_ids = '{$sFolderId}' OR
511 parent_folder_ids LIKE '{$sFolderId},%' OR 512 parent_folder_ids LIKE '{$sFolderId},%' OR
512 parent_folder_ids LIKE '%,{$sFolderId},%' OR 513 parent_folder_ids LIKE '%,{$sFolderId},%' OR
513 parent_folder_ids LIKE '%,{$sFolderId}'"; 514 parent_folder_ids LIKE '%,{$sFolderId}'";
514 $aChildFolders = $this->oFolder->getList($sWhereClause); 515 $aChildFolders = $this->oFolder->getList($sWhereClause);
515 - 516 +
516 // Loop through folders and get documents 517 // Loop through folders and get documents
517 if(!empty($aChildFolders)){ 518 if(!empty($aChildFolders)){
518 foreach($aChildFolders as $oChild){ 519 foreach($aChildFolders as $oChild){
@@ -522,26 +523,26 @@ class KTBulkArchiveAction extends KTBulkAction { @@ -522,26 +523,26 @@ class KTBulkArchiveAction extends KTBulkAction {
522 DBUtil::rollback(); 523 DBUtil::rollback();
523 return false; 524 return false;
524 } 525 }
525 - 526 +
526 if(!empty($sChildDocs)){ 527 if(!empty($sChildDocs)){
527 $aChildDocs = explode(',', $sChildDocs); 528 $aChildDocs = explode(',', $sChildDocs);
528 $aDocuments = array_merge($aDocuments, $aChildDocs); 529 $aDocuments = array_merge($aDocuments, $aChildDocs);
529 } 530 }
530 } 531 }
531 } 532 }
532 - 533 +
533 // Archive all documents 534 // Archive all documents
534 if(!empty($aDocuments)){ 535 if(!empty($aDocuments)){
535 foreach($aDocuments as $sDocumentId){ 536 foreach($aDocuments as $sDocumentId){
536 $oDocument = Document::get($sDocumentId); 537 $oDocument = Document::get($sDocumentId);
537 - 538 +
538 $oDocument->setStatusID(ARCHIVED); 539 $oDocument->setStatusID(ARCHIVED);
539 $res = $oDocument->update(); 540 $res = $oDocument->update();
540 if (($res === false) || PEAR::isError($res)) { 541 if (($res === false) || PEAR::isError($res)) {
541 DBUtil::rollback(); 542 DBUtil::rollback();
542 return false; 543 return false;
543 } 544 }
544 - 545 +
545 $oDocumentTransaction = & new DocumentTransaction($oDocument, sprintf(_kt('Document archived: %s'), $this->sReason), 'ktcore.transactions.update'); 546 $oDocumentTransaction = & new DocumentTransaction($oDocument, sprintf(_kt('Document archived: %s'), $this->sReason), 'ktcore.transactions.update');
546 $oDocumentTransaction->create(); 547 $oDocumentTransaction->create();
547 } 548 }
@@ -573,47 +574,29 @@ class KTBrowseBulkExportAction extends KTBulkAction { @@ -573,47 +574,29 @@ class KTBrowseBulkExportAction extends KTBulkAction {
573 574
574 function do_performaction() { 575 function do_performaction() {
575 576
576 - $oKTConfig =& KTConfig::getSingleton();  
577 - $sBasedir = $oKTConfig->get("urls/tmpDirectory");  
578 - $this->sTmpPath= $sTmpPath = tempnam($sBasedir, 'kt_export'); 577 + $folderName = $this->oFolder->getName();
  578 + $this->oZip = new ZipFolder($folderName);
  579 + $res = $this->oZip->checkConvertEncoding();
579 580
580 - $this->oStorage =& KTStorageManagerUtil::getSingleton(); 581 + $folderurl = KTBrowseUtil::getUrlForFolder($this->oFolder);
  582 + $sReturn = sprintf('<p>' . _kt('Return to the original <a href="%s">folder</a>') . "</p>\n", $folderurl);
581 583
582 - unlink($sTmpPath);  
583 - mkdir($sTmpPath, 0700); 584 + if(PEAR::isError($res)){
  585 + $this->addErrorMessage($res->getMessage());
  586 + return $sReturn;
  587 + }
584 588
585 $this->startTransaction(); 589 $this->startTransaction();
  590 + $oKTConfig =& KTConfig::getSingleton();
586 $this->bNoisy = $oKTConfig->get("tweaks/noisyBulkOperations"); 591 $this->bNoisy = $oKTConfig->get("tweaks/noisyBulkOperations");
587 592
588 - $this->sTmpPath = $sTmpPath;  
589 - $this->aPaths = array();  
590 -  
591 $result = parent::do_performaction(); 593 $result = parent::do_performaction();
  594 + $sExportCode = $this->oZip->createZipFile();
592 595
593 -  
594 - $sManifest = sprintf("%s/%s", $this->sTmpPath, "MANIFEST");  
595 - file_put_contents($sManifest, join("\n", $this->aPaths));  
596 - $sZipFile = sprintf("%s/%s.zip", $this->sTmpPath, $this->oFolder->getName());  
597 - $sZipFile = str_replace('<', '', str_replace('</', '', str_replace('>', '', $sZipFile)));  
598 - $_SESSION['bulkexport'] = KTUtil::arrayGet($_SESSION, 'bulkexport', array());  
599 - $sExportCode = KTUtil::randomString();  
600 - $_SESSION['bulkexport'][$sExportCode] = array(  
601 - 'file' => $sZipFile,  
602 - 'dir' => $this->sTmpPath,  
603 - );  
604 - $sZipCommand = KTUtil::findCommand("export/zip", "zip");  
605 - $aCmd = array(  
606 - $sZipCommand,  
607 - "-r",  
608 - $sZipFile,  
609 - ".",  
610 - "-i@MANIFEST",  
611 - );  
612 - $sOldPath = getcwd();  
613 - chdir($this->sTmpPath);  
614 - // Note that the popen means that pexec will return a file descriptor  
615 -  
616 - $fh = KTUtil::pexec($aCmd); 596 + if(PEAR::isError($sExportCode)){
  597 + $this->addErrorMessage($sExportCode->getMessage());
  598 + return $sReturn;
  599 + }
617 600
618 $oTransaction = KTFolderTransaction::createFromArray(array( 601 $oTransaction = KTFolderTransaction::createFromArray(array(
619 'folderid' => $this->oFolder->getId(), 602 'folderid' => $this->oFolder->getId(),
@@ -624,32 +607,25 @@ class KTBrowseBulkExportAction extends KTBulkAction { @@ -624,32 +607,25 @@ class KTBrowseBulkExportAction extends KTBulkAction {
624 )); 607 ));
625 608
626 $this->commitTransaction(); 609 $this->commitTransaction();
627 -  
628 -  
629 - header("Content-Type: application/zip");  
630 - header("Content-Length: ". filesize($sZipFile));  
631 - header("Content-Disposition: attachment; filename=\"" . $this->oFolder->getName() . ".zip" . "\"");  
632 - header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");  
633 - header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");  
634 - header("Cache-Control: must-revalidate");  
635 - readfile($sZipFile);  
636 - $sTmpDir = $aData['dir'];  
637 - KTUtil::deleteDirectory($sTmpDir);  
638 -  
639 - return $result; 610 +
  611 + $url = KTUtil::addQueryStringSelf(sprintf('action=downloadZipFile&fFolderId=%d&exportcode=%s', $this->oFolder->getId(), $sExportCode));
  612 + $str = sprintf('<p>' . _kt('Go <a href="%s">here</a> to download the zip file if you are not automatically redirected there') . "</p>\n", $url);
  613 + $folderurl = KTBrowseUtil::getUrlForFolder($this->oFolder);
  614 + $str .= sprintf('<p>' . _kt('Once downloaded, return to the original <a href="%s">folder</a>') . "</p>\n", $folderurl);
  615 + //$str .= sprintf("</div></div></body></html>\n");
  616 + $str .= sprintf('<script language="JavaScript">
  617 + function kt_bulkexport_redirect() {
  618 + document.location.href = "%s";
  619 + }
  620 + callLater(1, kt_bulkexport_redirect);
  621 +
  622 + </script>', $url);
  623 +
  624 + return $str;
640 } 625 }
641 626
642 function perform_action($oEntity) { 627 function perform_action($oEntity) {
643 - $aReplace = array(  
644 - "[" => "[[]",  
645 - " " => "[ ]",  
646 - "*" => "[*]",  
647 - "?" => "[?]",  
648 - );  
649 -  
650 - $aReplaceKeys = array_keys($aReplace);  
651 - $aReplaceValues = array_values($aReplace);  
652 - 628 +
653 if(is_a($oEntity, 'Document')) { 629 if(is_a($oEntity, 'Document')) {
654 630
655 $oDocument = $oEntity; 631 $oDocument = $oEntity;
@@ -658,113 +634,316 @@ class KTBrowseBulkExportAction extends KTBulkAction { @@ -658,113 +634,316 @@ class KTBrowseBulkExportAction extends KTBulkAction {
658 $oDocumentTransaction = new DocumentTransaction($oDocument, "Document part of bulk export", 'ktstandard.transactions.bulk_export', array()); 634 $oDocumentTransaction = new DocumentTransaction($oDocument, "Document part of bulk export", 'ktstandard.transactions.bulk_export', array());
659 $oDocumentTransaction->create(); 635 $oDocumentTransaction->create();
660 } 636 }
661 -  
662 - $sParentFolder = str_replace('<', '', str_replace('</', '', str_replace('>', '', sprintf('%s/%s', $this->sTmpPath, $oDocument->getFullPath()))));  
663 - $newDir = $this->sTmpPath;  
664 - $sFullPath = str_replace('<', '', str_replace('</', '', str_replace('>', '', $this->_convertEncoding($oDocument->getFullPath(), true))));  
665 - foreach (split('/', $sFullPath) as $dirPart) {  
666 - $newDir = sprintf("%s/%s", $newDir, $dirPart);  
667 - if (!file_exists($newDir)) {  
668 - mkdir($newDir, 0700);  
669 - }  
670 - }  
671 - $sOrigFile = str_replace('<', '', str_replace('</', '', str_replace('>', '', $this->oStorage->temporaryFile($oDocument))));  
672 - $sFilename = sprintf("%s/%s", $sParentFolder, str_replace('<', '', str_replace('</', '', str_replace('>', '', $oDocument->getFileName()))));  
673 - $sFilename = $this->_convertEncoding($sFilename, true);  
674 - copy($sOrigFile, $sFilename);  
675 - $sPath = str_replace('<', '', str_replace('</', '', str_replace('>', '', sprintf("%s/%s", $oDocument->getFullPath(), $oDocument->getFileName()))));  
676 - $sPath = str_replace($aReplaceKeys, $aReplaceValues, $sPath);  
677 - $sPath = $this->_convertEncoding($sPath, true);  
678 - $this->aPaths[] = $sPath;  
679 - 637 + $this->oZip->addDocumentToZip($oDocument);
680 638
681 }else if(is_a($oEntity, 'Folder')) { 639 }else if(is_a($oEntity, 'Folder')) {
682 $aDocuments = array(); 640 $aDocuments = array();
683 $oFolder = $oEntity; 641 $oFolder = $oEntity;
684 $sFolderId = $oFolder->getId(); 642 $sFolderId = $oFolder->getId();
685 $sFolderDocs = $oFolder->getDocumentIDs($sFolderId); 643 $sFolderDocs = $oFolder->getDocumentIDs($sFolderId);
686 - 644 +
687 if(!empty($sFolderDocs)){ 645 if(!empty($sFolderDocs)){
688 $aDocuments = explode(',', $sFolderDocs); 646 $aDocuments = explode(',', $sFolderDocs);
689 } 647 }
690 - 648 +
691 // Get all the folders within the current folder 649 // Get all the folders within the current folder
692 $sWhereClause = "parent_folder_ids = '{$sFolderId}' OR 650 $sWhereClause = "parent_folder_ids = '{$sFolderId}' OR
693 parent_folder_ids LIKE '{$sFolderId},%' OR 651 parent_folder_ids LIKE '{$sFolderId},%' OR
694 parent_folder_ids LIKE '%,{$sFolderId},%' OR 652 parent_folder_ids LIKE '%,{$sFolderId},%' OR
695 parent_folder_ids LIKE '%,{$sFolderId}'"; 653 parent_folder_ids LIKE '%,{$sFolderId}'";
696 $aFolderList = $this->oFolder->getList($sWhereClause); 654 $aFolderList = $this->oFolder->getList($sWhereClause);
697 - 655 +
698 // Export the folder structure to ensure the export of empty directories 656 // Export the folder structure to ensure the export of empty directories
699 - foreach($aFolderList as $k => $oFolderItem){  
700 - // Get documents for each folder  
701 - $sFolderItemId = $oFolderItem->getID();  
702 - $sFolderItemDocs = $oFolderItem->getDocumentIDs($sFolderItemId);  
703 -  
704 - if(!empty($sFolderItemDocs)){  
705 - $aFolderDocs = explode(',', $sFolderItemDocs);  
706 - $aDocuments = array_merge($aDocuments, $aFolderDocs);  
707 - }  
708 -  
709 - $sFolderPath = $oFolderItem->getFullPath().'/'.$oFolderItem->getName().'/';  
710 - $sParentFolder = str_replace('<', '', str_replace('</', '', str_replace('>', '', sprintf('%s/%s', $this->sTmpPath, $sFolderPath))));  
711 - $newDir = $this->sTmpPath;  
712 - $sFullPath = str_replace('<', '', str_replace('</', '', str_replace('>', '', $this->_convertEncoding($sFolderPath, true))));  
713 - foreach (split('/', $sFullPath) as $dirPart) {  
714 - $newDir = sprintf("%s/%s", $newDir, $dirPart);  
715 - if (!file_exists($newDir)) {  
716 - mkdir($newDir, 0700); 657 + if(!empty($aFolderList)){
  658 + foreach($aFolderList as $k => $oFolderItem){
  659 + // Get documents for each folder
  660 + $sFolderItemId = $oFolderItem->getID();
  661 + $sFolderItemDocs = $oFolderItem->getDocumentIDs($sFolderItemId);
  662 +
  663 + if(!empty($sFolderItemDocs)){
  664 + $aFolderDocs = explode(',', $sFolderItemDocs);
  665 + $aDocuments = array_merge($aDocuments, $aFolderDocs);
717 } 666 }
  667 + $this->oZip->addFolderToZip($oFolderItem);
718 } 668 }
719 - $sPath = str_replace('<', '', str_replace('</', '', str_replace('>', '', sprintf("%s", $sFolderPath))));  
720 - $sPath = str_replace($aReplaceKeys, $aReplaceValues, $sPath);  
721 - $sPath = $this->_convertEncoding($sPath, true);  
722 - $this->aPaths[] = $sPath;  
723 } 669 }
724 - 670 +
725 // Add all documents to the export 671 // Add all documents to the export
726 if(!empty($aDocuments)){ 672 if(!empty($aDocuments)){
727 foreach($aDocuments as $sDocumentId){ 673 foreach($aDocuments as $sDocumentId){
728 $oDocument = Document::get($sDocumentId); 674 $oDocument = Document::get($sDocumentId);
729 - 675 +
730 if ($this->bNoisy) { 676 if ($this->bNoisy) {
731 $oDocumentTransaction = new DocumentTransaction($oDocument, "Document part of bulk export", 'ktstandard.transactions.bulk_export', array()); 677 $oDocumentTransaction = new DocumentTransaction($oDocument, "Document part of bulk export", 'ktstandard.transactions.bulk_export', array());
732 $oDocumentTransaction->create(); 678 $oDocumentTransaction->create();
733 } 679 }
  680 + $this->oZip->addDocumentToZip($oDocument);
  681 + }
  682 + }
  683 + }
  684 + return true;
  685 + }
  686 +
  687 + function do_downloadZipFile() {
  688 + $sCode = $this->oValidator->validateString($_REQUEST['exportcode']);
  689 +
  690 + $folderName = $this->oFolder->getName();
  691 + $this->oZip = new ZipFolder($folderName);
734 692
735 - $sParentFolder = str_replace('<', '', str_replace('</', '', str_replace('>', '', sprintf('%s/%s', $this->sTmpPath, $oDocument->getFullPath()))));  
736 - $newDir = $this->sTmpPath;  
737 - $sFullPath = str_replace('<', '', str_replace('</', '', str_replace('>', '', $this->_convertEncoding($oDocument->getFullPath(), true))));  
738 - foreach (split('/', $sFullPath) as $dirPart) {  
739 - $newDir = sprintf("%s/%s", $newDir, $dirPart);  
740 - if (!file_exists($newDir)) {  
741 - mkdir($newDir, 0700); 693 + $res = $this->oZip->downloadZipFile($sCode);
  694 +
  695 + if(PEAR::isError($res)){
  696 + $this->addErrorMessage($res->getMessage());
  697 + redirect(generateControllerUrl("browse", "fBrowseType=folder&fFolderId=" . $this->oFolder->getId()));
  698 + }
  699 + exit(0);
  700 + }
  701 +}
  702 +
  703 +class KTBrowseBulkCheckoutAction extends KTBulkAction {
  704 + var $sName = 'ktcore.actions.bulk.checkout';
  705 + var $_sPermission = 'ktcore.permissions.write';
  706 + var $_bMutator = true;
  707 +
  708 + function getDisplayName() {
  709 + return _kt('Checkout');
  710 + }
  711 +
  712 + function check_entity($oEntity) {
  713 + if(is_a($oEntity, 'Document')) {
  714 + if ($oEntity->getIsCheckedOut()) {
  715 + return PEAR::raiseError(_kt('Document is already checked out'));
  716 + }
  717 + }else if(!is_a($oEntity, 'Folder')) {
  718 + return PEAR::raiseError(_kt('Document cannot be checked out'));
  719 + }
  720 + return parent::check_entity($oEntity);
  721 + }
  722 +
  723 + function form_collectinfo() {
  724 + $oForm = new KTForm;
  725 + $oForm->setOptions(array(
  726 + 'identifier' => 'ktcore.actions.bulk.checkout.form',
  727 + 'label' => _kt('Checkout Items'),
  728 + 'submit_label' => _kt('Checkout'),
  729 + 'action' => 'performaction',
  730 + 'fail_action' => 'collectinfo',
  731 + 'cancel_action' => 'main',
  732 + 'context' => $this,
  733 + ));
  734 +
  735 + $oForm-> setWidgets(array(
  736 + array('ktcore.widgets.reason',array(
  737 + 'name' => 'reason',
  738 + 'label' => _kt('Reason'),
  739 + 'description' => _kt('Please specify why you are checking out these documents. It will assist other users in understanding why you have locked these files.'),
  740 + 'value' => null,
  741 + 'required' => true,
  742 + )),
  743 + array('ktcore.widgets.boolean', array(
  744 + 'label' => _kt('Download Files'),
  745 + 'description' => _kt('Indicate whether you would like to download these file as part of the checkout.'),
  746 + 'name' => 'download_file',
  747 + 'value' => true,
  748 + )),
  749 + ));
  750 +
  751 + $oForm->setValidators(array(
  752 + array('ktcore.validators.string', array(
  753 + 'test' => 'reason',
  754 + 'max_length' => 250,
  755 + 'output' => 'reason',
  756 + )),
  757 + array('ktcore.validators.boolean', array(
  758 + 'test' => 'download_file',
  759 + 'output' => 'download_file',
  760 + )),
  761 + ));
  762 +
  763 + return $oForm;
  764 + }
  765 +
  766 + // info collection step
  767 + function do_collectinfo() {
  768 + $this->store_lists();
  769 + $this->get_lists();
  770 + $oTemplating =& KTTemplating::getSingleton();
  771 + $oTemplate = $oTemplating->loadTemplate('ktcore/bulk_action_info');
  772 + return $oTemplate->render(array('context' => $this,
  773 + 'form' => $this->form_collectinfo()));
  774 + }
  775 +
  776 + function do_performaction() {
  777 + // Get reason for checkout & check if docs must be downloaded
  778 + $this->store_lists();
  779 + $this->get_lists();
  780 +
  781 + $oForm = $this->form_collectinfo();
  782 + $res = $oForm->validate();
  783 + if (!empty($res['errors'])) {
  784 + $oForm->handleError();
  785 + }
  786 +
  787 + $this->sReason = $_REQUEST['data']['reason'];
  788 + $this->bDownload = $_REQUEST['data']['download_file'];
  789 +
  790 + $oKTConfig =& KTConfig::getSingleton();
  791 + $this->bNoisy = $oKTConfig->get("tweaks/noisyBulkOperations");
  792 +
  793 + $folderurl = KTBrowseUtil::getUrlForFolder($this->oFolder);
  794 + $sReturn = sprintf('<p>' . _kt('Return to the original <a href="%s">folder</a>') . "</p>\n", $folderurl);
  795 +
  796 + $this->startTransaction();
  797 +
  798 + // if files are to be downloaded - create the temp directory for the bulk export
  799 + if($this->bDownload){
  800 + $folderName = $this->oFolder->getName();
  801 + $this->oZip = new ZipFolder($folderName);
  802 + $res = $this->oZip->checkConvertEncoding();
  803 +
  804 + if(PEAR::isError($res)){
  805 + $this->addErrorMessage($res->getMessage());
  806 + return $sReturn;
  807 + }
  808 + }
  809 +
  810 +
  811 + $result = parent::do_performaction();
  812 +
  813 + if(PEAR::isError($result)){
  814 + $this->addErrorMessage($result->getMessage());
  815 + return $sReturn;
  816 + }
  817 +
  818 + if($this->bDownload){
  819 + $sExportCode = $this->oZip->createZipFile();
  820 +
  821 + if(PEAR::isError($sExportCode)){
  822 + $this->addErrorMessage($sExportCode->getMessage());
  823 + return $sReturn;
  824 + }
  825 + }
  826 +
  827 + $this->commitTransaction();
  828 +
  829 + if($this->bDownload){
  830 +
  831 + $url = KTUtil::addQueryStringSelf(sprintf('action=downloadZipFile&fFolderId=%d&exportcode=%s', $this->oFolder->getId(), $sExportCode));
  832 + $str = sprintf('<p>' . _kt('Go <a href="%s">here</a> to download the zip file if you are not automatically redirected there') . "</p>\n", $url);
  833 + $folderurl = KTBrowseUtil::getUrlForFolder($this->oFolder);
  834 + $str .= sprintf('<p>' . _kt('Once downloaded, return to the original <a href="%s">folder</a>') . "</p>\n", $folderurl);
  835 + $str .= sprintf("</div></div></body></html>\n");
  836 + $str .= sprintf('<script language="JavaScript">
  837 + function kt_bulkexport_redirect() {
  838 + document.location.href = "%s";
  839 + }
  840 + callLater(1, kt_bulkexport_redirect);
  841 +
  842 + </script>', $url);
  843 +
  844 + return $str;
  845 + }
  846 + return $result;
  847 + }
  848 +
  849 + function perform_action($oEntity) {
  850 + // checkout document
  851 + $sReason = $this->sReason;
  852 +
  853 + if(is_a($oEntity, 'Document')) {
  854 + $res = KTDocumentUtil::checkout($oEntity, $sReason, $this->oUser);
  855 +
  856 + if(PEAR::isError($res)) {
  857 + return PEAR::raiseError($oEntity->getName().': '.$res->getMessage());
  858 + }
  859 + if($this->bDownload){
  860 + if ($this->bNoisy) {
  861 + $oDocumentTransaction = new DocumentTransaction($oEntity, "Document part of bulk checkout", 'ktstandard.transactions.check_out', array());
  862 + $oDocumentTransaction->create();
  863 + }
  864 + $this->oZip->addDocumentToZip($oEntity);
  865 + }
  866 +
  867 + }else if(is_a($oEntity, 'Folder')) {
  868 + // get documents and subfolders
  869 + $aDocuments = array();
  870 + $oFolder = $oEntity;
  871 +
  872 + $sFolderId = $oFolder->getId();
  873 + $sFolderDocs = $oFolder->getDocumentIDs($sFolderId);
  874 +
  875 + // get documents directly in the folder
  876 + if(!empty($sFolderDocs)){
  877 + $aDocuments = explode(',', $sFolderDocs);
  878 + }
  879 +
  880 + // Get all the folders within the current folder
  881 + $sWhereClause = "parent_folder_ids = '{$sFolderId}' OR
  882 + parent_folder_ids LIKE '{$sFolderId},%' OR
  883 + parent_folder_ids LIKE '%,{$sFolderId},%' OR
  884 + parent_folder_ids LIKE '%,{$sFolderId}'";
  885 + $aFolderList = $this->oFolder->getList($sWhereClause);
  886 +
  887 + // Get the documents within the folder
  888 + if(!empty($aFolderList)){
  889 + foreach($aFolderList as $k => $oFolderItem){
  890 + // Get documents for each folder
  891 + $sFolderItemId = $oFolderItem->getID();
  892 + $sFolderItemDocs = $oFolderItem->getDocumentIDs($sFolderItemId);
  893 +
  894 + if(!empty($sFolderItemDocs)){
  895 + $aFolderDocs = explode(',', $sFolderItemDocs);
  896 + $aDocuments = array_merge($aDocuments, $aFolderDocs);
  897 + }
  898 +
  899 + // Add the folder to the zip file
  900 + if($this->bDownload){
  901 + $this->oZip->addFolderToZip($oFolderItem);
  902 + }
  903 + }
  904 + }
  905 +
  906 + // Checkout each document within the folder structure
  907 + if(!empty($aDocuments)){
  908 + foreach($aDocuments as $sDocId){
  909 + $oDocument = Document::get($sDocId);
  910 + if(PEAR::isError($oDocument)) {
  911 + return PEAR::raiseError(_kt('Folder documents cannot be checked out'));
  912 + }
  913 +
  914 + $res = KTDocumentUtil::checkout($oDocument, $sReason, $this->oUser);
  915 + if(PEAR::isError($res)) {
  916 + return PEAR::raiseError($oDocument->getName().': '.$res->getMessage());
  917 + }
  918 +
  919 + // Add document to the zip file
  920 + if($this->bDownload){
  921 + if ($this->bNoisy) {
  922 + $oDocumentTransaction = new DocumentTransaction($oDocument, "Document part of bulk checkout", 'ktstandard.transactions.check_out', array());
  923 + $oDocumentTransaction->create();
742 } 924 }
  925 + $this->oZip->addDocumentToZip($oDocument);
743 } 926 }
744 - $sOrigFile = str_replace('<', '', str_replace('</', '', str_replace('>', '', $this->oStorage->temporaryFile($oDocument))));  
745 - $sFilename = sprintf("%s/%s", $sParentFolder, str_replace('<', '', str_replace('</', '', str_replace('>', '', $oDocument->getFileName()))));  
746 - $sFilename = $this->_convertEncoding($sFilename, true);  
747 - copy($sOrigFile, $sFilename);  
748 - $sPath = str_replace('<', '', str_replace('</', '', str_replace('>', '', sprintf("%s/%s", $oDocument->getFullPath(), $oDocument->getFileName()))));  
749 - $sPath = str_replace($aReplaceKeys, $aReplaceValues, $sPath);  
750 - $sPath = $this->_convertEncoding($sPath, true);  
751 - $this->aPaths[] = $sPath;  
752 } 927 }
753 - } 928 + }
754 } 929 }
755 return true; 930 return true;
756 } 931 }
757 -  
758 - function _convertEncoding($sMystring, $bEncode) {  
759 - if (strcasecmp($this->sOutputEncoding, "UTF-8") === 0) {  
760 - return $sMystring;  
761 - }  
762 - if ($bEncode) {  
763 - return iconv("UTF-8", $this->sOutputEncoding, $sMystring);  
764 - } else {  
765 - return iconv($this->sOutputEncoding, "UTF-8", $sMystring);  
766 - } 932 +
  933 + function do_downloadZipFile() {
  934 + $sCode = $this->oValidator->validateString($_REQUEST['exportcode']);
  935 +
  936 + $folderName = $this->oFolder->getName();
  937 + $this->oZip = new ZipFolder($folderName);
  938 +
  939 + $res = $this->oZip->downloadZipFile($sCode);
  940 +
  941 + if(PEAR::isError($res)){
  942 + $this->addErrorMessage($res->getMessage());
  943 + redirect(generateControllerUrl("browse", "fBrowseType=folder&fFolderId=" . $this->oFolder->getId()));
  944 + }
  945 + exit(0);
767 } 946 }
768 -  
769 } 947 }
  948 +
770 ?> 949 ?>
771 \ No newline at end of file 950 \ No newline at end of file
plugins/ktcore/KTCorePlugin.php
@@ -91,6 +91,7 @@ class KTCorePlugin extends KTPlugin { @@ -91,6 +91,7 @@ class KTCorePlugin extends KTPlugin {
91 $this->registerAction('bulkaction', 'KTBulkCopyAction', 'ktcore.actions.bulk.copy', 'KTBulkActions.php'); 91 $this->registerAction('bulkaction', 'KTBulkCopyAction', 'ktcore.actions.bulk.copy', 'KTBulkActions.php');
92 $this->registerAction('bulkaction', 'KTBulkArchiveAction', 'ktcore.actions.bulk.archive', 'KTBulkActions.php'); 92 $this->registerAction('bulkaction', 'KTBulkArchiveAction', 'ktcore.actions.bulk.archive', 'KTBulkActions.php');
93 $this->registerAction('bulkaction', 'KTBrowseBulkExportAction', 'ktcore.actions.bulk.export', 'KTBulkActions.php'); 93 $this->registerAction('bulkaction', 'KTBrowseBulkExportAction', 'ktcore.actions.bulk.export', 'KTBulkActions.php');
  94 + $this->registerAction('bulkaction', 'KTBrowseBulkCheckoutAction', 'ktcore.actions.bulk.checkout', 'KTBulkActions.php');
94 95
95 // Dashlets 96 // Dashlets
96 $this->registerDashlet('KTInfoDashlet', 'ktcore.dashlet.info', 'KTDashlets.php'); 97 $this->registerDashlet('KTInfoDashlet', 'ktcore.dashlet.info', 'KTDashlets.php');
plugins/ktstandard/KTBulkExportPlugin.php
@@ -34,6 +34,7 @@ require_once(KT_LIB_DIR . &#39;/plugins/pluginregistry.inc.php&#39;); @@ -34,6 +34,7 @@ require_once(KT_LIB_DIR . &#39;/plugins/pluginregistry.inc.php&#39;);
34 require_once(KT_LIB_DIR . '/browse/browseutil.inc.php'); 34 require_once(KT_LIB_DIR . '/browse/browseutil.inc.php');
35 35
36 require_once(KT_LIB_DIR . '/config/config.inc.php'); 36 require_once(KT_LIB_DIR . '/config/config.inc.php');
  37 +require_once(KT_LIB_DIR . '/foldermanagement/compressionArchiveUtil.inc.php');
37 38
38 class KTBulkExportPlugin extends KTPlugin { 39 class KTBulkExportPlugin extends KTPlugin {
39 var $sNamespace = "ktstandard.bulkexport.plugin"; 40 var $sNamespace = "ktstandard.bulkexport.plugin";
@@ -55,48 +56,16 @@ class KTBulkExportAction extends KTFolderAction { @@ -55,48 +56,16 @@ class KTBulkExportAction extends KTFolderAction {
55 var $sName = 'ktstandard.bulkexport.action'; 56 var $sName = 'ktstandard.bulkexport.action';
56 var $sPermissionName = "ktcore.permissions.read"; 57 var $sPermissionName = "ktcore.permissions.read";
57 var $_sShowPermission = "ktcore.permissions.read"; 58 var $_sShowPermission = "ktcore.permissions.read";
58 - var $sOutputEncoding = 'UTF-8';  
59 -  
60 - function _checkConvertEncoding() {  
61 - if(!function_exists("iconv")) {  
62 - $this->addErrorMessage(_kt('IConv PHP extension not installed. Bulk export could not handle output filename encoding conversion !'));  
63 - return false;  
64 - }  
65 - $oKTConfig = KTConfig::getSingleton();  
66 - $this->sOutputEncoding = $oKTConfig->get('export/encoding', 'UTF-8');  
67 -  
68 - // Test the specified encoding  
69 - if(iconv("UTF-8", $this->sOutputEncoding, "") === FALSE) {  
70 - $this->addErrorMessage(_kt('Specified output encoding for bulk export does not exists !'));  
71 - return false;  
72 - }  
73 - return true;  
74 - }  
75 -  
76 - /**  
77 - * Convert encoding to defined character encoding  
78 - *  
79 - * @param string the string to convert  
80 - * @param boolean encode(true) or decode(false) string  
81 - * @return string the encoded string  
82 - */  
83 - function _convertEncoding($sMystring, $bEncode) {  
84 - if (strcasecmp($this->sOutputEncoding, "UTF-8") === 0) {  
85 - return $sMystring;  
86 - }  
87 - if ($bEncode) {  
88 - return iconv("UTF-8", $this->sOutputEncoding, $sMystring);  
89 - } else {  
90 - return iconv($this->sOutputEncoding, "UTF-8", $sMystring);  
91 - }  
92 - }  
93 59
94 function getDisplayName() { 60 function getDisplayName() {
95 return _kt('Bulk Export'); 61 return _kt('Bulk Export');
96 } 62 }
97 63
98 function do_main() { 64 function do_main() {
99 - if(!$this->_checkConvertEncoding()) { 65 + $folderName = $this->oFolder->getName();
  66 + $this->oZip = new ZipFolder($folderName);
  67 +
  68 + if(!$this->oZip->checkConvertEncoding()) {
100 redirect(KTBrowseUtil::getUrlForFolder($oFolder)); 69 redirect(KTBrowseUtil::getUrlForFolder($oFolder));
101 exit(0); 70 exit(0);
102 } 71 }
@@ -105,7 +74,7 @@ class KTBulkExportAction extends KTFolderAction { @@ -105,7 +74,7 @@ class KTBulkExportAction extends KTFolderAction {
105 $aQuery = $this->buildQuery(); 74 $aQuery = $this->buildQuery();
106 $this->oValidator->notError($aQuery); 75 $this->oValidator->notError($aQuery);
107 $aDocumentIds = DBUtil::getResultArrayKey($aQuery, 'id'); 76 $aDocumentIds = DBUtil::getResultArrayKey($aQuery, 'id');
108 - 77 +
109 /* Modified 07/09/2007 by megan_w */ 78 /* Modified 07/09/2007 by megan_w */
110 // Get all the folders within the current folder 79 // Get all the folders within the current folder
111 $sCurrentFolderId = $this->oFolder->getId(); 80 $sCurrentFolderId = $this->oFolder->getId();
@@ -116,11 +85,10 @@ class KTBulkExportAction extends KTFolderAction { @@ -116,11 +85,10 @@ class KTBulkExportAction extends KTFolderAction {
116 85
117 $aFolderList = $this->oFolder->getList($sWhereClause); 86 $aFolderList = $this->oFolder->getList($sWhereClause);
118 /* End modified */ 87 /* End modified */
119 - 88 +
120 $this->startTransaction(); 89 $this->startTransaction();
121 90
122 $oKTConfig =& KTConfig::getSingleton(); 91 $oKTConfig =& KTConfig::getSingleton();
123 - $sBasedir = $oKTConfig->get("urls/tmpDirectory");  
124 $bNoisy = $oKTConfig->get("tweaks/noisyBulkOperations"); 92 $bNoisy = $oKTConfig->get("tweaks/noisyBulkOperations");
125 93
126 // Redirect if there are no documents and no folders to export 94 // Redirect if there are no documents and no folders to export
@@ -129,114 +97,31 @@ class KTBulkExportAction extends KTFolderAction { @@ -129,114 +97,31 @@ class KTBulkExportAction extends KTFolderAction {
129 redirect(KTBrowseUtil::getUrlForFolder($oFolder)); 97 redirect(KTBrowseUtil::getUrlForFolder($oFolder));
130 exit(0); 98 exit(0);
131 } 99 }
132 - 100 +
133 $this->oPage->requireJSResource('thirdpartyjs/MochiKit/Base.js'); 101 $this->oPage->requireJSResource('thirdpartyjs/MochiKit/Base.js');
134 $this->oPage->requireJSResource('thirdpartyjs/MochiKit/Async.js'); 102 $this->oPage->requireJSResource('thirdpartyjs/MochiKit/Async.js');
135 $this->oPage->template = "kt3/minimal_page"; 103 $this->oPage->template = "kt3/minimal_page";
136 $this->handleOutput(""); 104 $this->handleOutput("");
137 105
138 - $sTmpPath = tempnam($sBasedir, 'kt_export');  
139 - unlink($sTmpPath);  
140 - mkdir($sTmpPath, 0700);  
141 - $this->sTmpPath = $sTmpPath;  
142 - $aPaths = array();  
143 - $aReplace = array(  
144 - "[" => "[[]",  
145 - " " => "[ ]",  
146 - "*" => "[*]",  
147 - "?" => "[?]",  
148 - );  
149 - $aReplaceKeys = array_keys($aReplace);  
150 - $aReplaceValues = array_values($aReplace);  
151 if(!empty($aDocumentIds)){ 106 if(!empty($aDocumentIds)){
152 foreach ($aDocumentIds as $iId) { 107 foreach ($aDocumentIds as $iId) {
153 $oDocument = Document::get($iId); 108 $oDocument = Document::get($iId);
154 - 109 +
155 if ($bNoisy) { 110 if ($bNoisy) {
156 $oDocumentTransaction = & new DocumentTransaction($oDocument, "Document part of bulk export", 'ktstandard.transactions.bulk_export', array()); 111 $oDocumentTransaction = & new DocumentTransaction($oDocument, "Document part of bulk export", 'ktstandard.transactions.bulk_export', array());
157 $oDocumentTransaction->create(); 112 $oDocumentTransaction->create();
158 } 113 }
159 -  
160 - $sParentFolder = str_replace('<', '', str_replace('</', '', str_replace('>', '', sprintf('%s/%s', $sTmpPath, $oDocument->getFullPath()))));  
161 - $newDir = $this->sTmpPath;  
162 - $sFullPath = str_replace('<', '', str_replace('</', '', str_replace('>', '', $this->_convertEncoding($oDocument->getFullPath(), true))));  
163 - foreach (split('/', $sFullPath) as $dirPart) {  
164 - $newDir = sprintf("%s/%s", $newDir, $dirPart);  
165 - if (!file_exists($newDir)) {  
166 - mkdir($newDir, 0700);  
167 - }  
168 - }  
169 - $sOrigFile = str_replace('<', '', str_replace('</', '', str_replace('>', '', $oStorage->temporaryFile($oDocument))));  
170 - $sFilename = sprintf("%s/%s", $sParentFolder, str_replace('<', '', str_replace('</', '', str_replace('>', '', $oDocument->getFileName()))));  
171 - $sFilename = $this->_convertEncoding($sFilename, true);  
172 - copy($sOrigFile, $sFilename);  
173 - $sPath = str_replace('<', '', str_replace('</', '', str_replace('>', '', sprintf("%s/%s", $oDocument->getFullPath(), $oDocument->getFileName()))));  
174 - $sPath = str_replace($aReplaceKeys, $aReplaceValues, $sPath);  
175 - $sPath = $this->_convertEncoding($sPath, true);  
176 - $aPaths[] = $sPath; 114 +
  115 + $this->oZip->addDocumentToZip($oDocument);
177 } 116 }
178 } 117 }
179 -  
180 - /* Modified 07/09/2007 by megan_w */ 118 +
181 // Export the folder structure to ensure the export of empty directories 119 // Export the folder structure to ensure the export of empty directories
182 foreach($aFolderList as $k => $oFolderItem){ 120 foreach($aFolderList as $k => $oFolderItem){
183 - $sFolderPath = $oFolderItem->getFullPath().'/'.$oFolderItem->getName().'/';  
184 - $sParentFolder = str_replace('<', '', str_replace('</', '', str_replace('>', '', sprintf('%s/%s', $sTmpPath, $sFolderPath))));  
185 - $newDir = $this->sTmpPath;  
186 - $sFullPath = str_replace('<', '', str_replace('</', '', str_replace('>', '', $this->_convertEncoding($sFolderPath, true))));  
187 - foreach (split('/', $sFullPath) as $dirPart) {  
188 - $newDir = sprintf("%s/%s", $newDir, $dirPart);  
189 - if (!file_exists($newDir)) {  
190 - mkdir($newDir, 0700);  
191 - }  
192 - }  
193 - $sPath = str_replace('<', '', str_replace('</', '', str_replace('>', '', sprintf("%s", $sFolderPath))));  
194 - $sPath = str_replace($aReplaceKeys, $aReplaceValues, $sPath);  
195 - $sPath = $this->_convertEncoding($sPath, true);  
196 - $aPaths[] = $sPath; 121 + $this->oZip->addFolderToZip($oFolderItem);
197 } 122 }
198 - /* End modified */  
199 -  
200 - $sManifest = sprintf("%s/%s", $this->sTmpPath, "MANIFEST");  
201 - file_put_contents($sManifest, join("\n", $aPaths));  
202 - $sZipFile = sprintf("%s/%s.zip", $this->sTmpPath, $this->oFolder->getName());  
203 - $sZipFile = str_replace('<', '', str_replace('</', '', str_replace('>', '', $sZipFile)));  
204 - $_SESSION['bulkexport'] = KTUtil::arrayGet($_SESSION, 'bulkexport', array());  
205 - $sExportCode = KTUtil::randomString();  
206 - $_SESSION['bulkexport'][$sExportCode] = array(  
207 - 'file' => $sZipFile,  
208 - 'dir' => $this->sTmpPath,  
209 - );  
210 - $sZipCommand = KTUtil::findCommand("export/zip", "zip");  
211 - $aCmd = array(  
212 - $sZipCommand,  
213 - "-r",  
214 - $sZipFile,  
215 - ".",  
216 - "-i@MANIFEST",  
217 - );  
218 - $sOldPath = getcwd();  
219 - chdir($this->sTmpPath);  
220 - // Note that the popen means that pexec will return a file descriptor  
221 - $aOptions = array('popen' => 'r');  
222 - $fh = KTUtil::pexec($aCmd, $aOptions);  
223 -  
224 - $last_beat = time();  
225 - while(!feof($fh)) {  
226 - if ($i % 1000 == 0) {  
227 - $this_beat = time();  
228 - if ($last_beat + 1 < $this_beat) {  
229 - $last_beat = $this_beat;  
230 - print "&nbsp;";  
231 - }  
232 - }  
233 - $contents = fread($fh, 4096);  
234 - if ($contents) {  
235 - print nl2br($this->_convertEncoding($contents, false));  
236 - }  
237 - $i++;  
238 - }  
239 - pclose($fh); 123 +
  124 + $sExportCode = $this->oZip->createZipFile(TRUE);
240 125
241 $oTransaction = KTFolderTransaction::createFromArray(array( 126 $oTransaction = KTFolderTransaction::createFromArray(array(
242 'folderid' => $this->oFolder->getId(), 127 'folderid' => $this->oFolder->getId(),
@@ -311,29 +196,17 @@ class KTBulkExportAction extends KTFolderAction { @@ -311,29 +196,17 @@ class KTBulkExportAction extends KTFolderAction {
311 196
312 function do_downloadZipFile() { 197 function do_downloadZipFile() {
313 $sCode = $this->oValidator->validateString($_REQUEST['exportcode']); 198 $sCode = $this->oValidator->validateString($_REQUEST['exportcode']);
314 - $aData = KTUtil::arrayGet($_SESSION['bulkexport'], $sCode);  
315 - $this->oValidator->notEmpty($aData);  
316 - $sZipFile = $aData['file'];  
317 199
318 - if (!file_exists($sZipFile)) {  
319 - $this->addErrorMessage(_kt('The ZIP can only be downloaded once - if you cancel the download, you will need to reload the Bulk Export page.')); 200 + $folderName = $this->oFolder->getName();
  201 + $this->oZip = new ZipFolder($folderName);
  202 +
  203 + if(!$this->oZip->downloadZipFile($sCode)){
320 redirect(generateControllerUrl("browse", "fBrowseType=folder&fFolderId=" . $this->oFolder->getId())); 204 redirect(generateControllerUrl("browse", "fBrowseType=folder&fFolderId=" . $this->oFolder->getId()));
321 - exit(0);  
322 } 205 }
323 -  
324 - header("Content-Type: application/zip");  
325 - header("Content-Length: ". filesize($sZipFile));  
326 - header("Content-Disposition: attachment; filename=\"" . $this->oFolder->getName() . ".zip" . "\"");  
327 - header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");  
328 - header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");  
329 - header("Cache-Control: must-revalidate");  
330 - readfile($sZipFile);  
331 - $sTmpDir = $aData['dir'];  
332 - KTUtil::deleteDirectory($sTmpDir);  
333 exit(0); 206 exit(0);
334 } 207 }
335 } 208 }
336 $oPluginRegistry =& KTPluginRegistry::getSingleton(); 209 $oPluginRegistry =& KTPluginRegistry::getSingleton();
337 $oPluginRegistry->registerPlugin('KTBulkExportPlugin', 'ktstandard.bulkexport.plugin', __FILE__); 210 $oPluginRegistry->registerPlugin('KTBulkExportPlugin', 'ktstandard.bulkexport.plugin', __FILE__);
338 211
339 -?> 212 -?>
  213 +?>
340 \ No newline at end of file 214 \ No newline at end of file