2 /*********************************************************************************
3 * SugarCRM Community Edition is a customer relationship management program developed by
4 * SugarCRM, Inc. Copyright (C) 2004-2012 SugarCRM Inc.
6 * This program is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU Affero General Public License version 3 as published by the
8 * Free Software Foundation with the addition of the following permission added
9 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
10 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
11 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
18 * You should have received a copy of the GNU Affero General Public License along with
19 * this program; if not, see http://www.gnu.org/licenses or write to the Free
20 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
24 * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
26 * The interactive user interfaces in modified source and object code versions
27 * of this program must display Appropriate Legal Notices, as required under
28 * Section 5 of the GNU Affero General Public License version 3.
30 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
31 * these Appropriate Legal Notices must retain the display of the "Powered by
32 * SugarCRM" logo. If the display of the logo is not reasonably feasible for
33 * technical reasons, the Appropriate Legal Notices must display the words
34 * "Powered by SugarCRM".
35 ********************************************************************************/
37 require_once('modules/ModuleBuilder/MB/MBModule.php');
41 var $is_uninstallable = true;
42 var $description = '';
43 var $has_images = true;
44 var $modules = array();
45 var $date_modified = '';
49 function MBPackage($name){
54 function loadModules($force=false){
55 if(!file_exists(MB_PACKAGE_PATH . '/' . $this->name .'/modules'))return;
56 $d = dir(MB_PACKAGE_PATH . '/' . $this->name .'/modules');
57 while($e = $d->read()){
58 if(substr($e, 0, 1) != '.' && is_dir(MB_PACKAGE_PATH . '/'. $this->name. '/modules/' . $e)){
59 $this->getModule($e, $force);
65 * Loads the translated module titles from the selected language into.
66 * Will override currently loaded string to reflect undeployed label changes.
69 * @param $languge String language identifyer
71 function loadModuleTitles($languge = '')
75 $language = $GLOBALS['current_language'];
77 global $app_list_strings;
78 $packLangFilePath = $this->getPackageDir() . "/language/application/" . $language . ".lang.php";
79 if (file_exists($packLangFilePath))
82 require($packLangFilePath);
86 function getModule($name, $force=true){
87 if(!$force && !empty($this->modules[$name]))return;
88 $path = $this->getPackageDir();
90 $this->modules[$name] = new MBModule($name, $path, $this->name, $this->key);
93 function deleteModule($name){
94 $this->modules[$name]->delete();
95 unset($this->modules[$name]);
98 function getManifest($version_specific = false, $for_export = false){
99 //If we are exporting the package, we must ensure a different install key
100 $pre = $for_export ? MB_EXPORTPREPEND : "";
101 $date = TimeDate::getInstance()->nowDb();
103 $this->description = to_html($this->description);
104 $is_uninstallable = ($this->is_uninstallable ? true : false);
105 if($GLOBALS['sugar_flavor'] == 'CE') {
106 $flavors = array('CE','PRO','ENT');
108 $flavors = array($GLOBALS['sugar_flavor']);
110 $version = (!empty($version_specific))?$GLOBALS['sugar_version']:'';
112 // Build an array and use var_export to build this file
114 array('acceptable_sugar_versions' => array($version)),
115 array('acceptable_sugar_flavors' => $flavors),
116 'readme' => $this->readme,
118 'author' => $this->author,
119 'description' => $this->description,
121 'is_uninstallable' => $is_uninstallable,
122 'name' => $pre.$this->name,
123 'published_date' => $date,
126 'remove_tables' => 'prompt',
131 $header = file_get_contents('modules/ModuleBuilder/MB/header.php');
133 return $header."\n// THIS CONTENT IS GENERATED BY MBPackage.php\n".'$manifest = '.var_export_helper($manifest).";\n\n";
138 'acceptable_sugar_versions' =>
142 'acceptable_sugar_flavors' =>
146 'readme'=>'$this->readme',
148 'author' => '$this->author',
149 'description' => '$this->description',
151 'is_uninstallable' => $is_uninstallable,
152 'name' => '$pre$this->name',
153 'published_date' => '$date',
155 'version' => '$time',
156 'remove_tables' => 'prompt',
162 function buildInstall($path){
163 $installdefs = array ('id' => $this->name,
165 'layoutdefs'=>array(),
166 'relationships'=>array(),
168 if($this->has_images){
169 $installdefs['image_dir'] = '<basepath>/icons';
171 foreach(array_keys($this->modules) as $module){
172 $this->modules[$module]->build($path);
173 $this->modules[$module]->addInstallDefs($installdefs);
175 $this->path = $this->getPackageDir();
176 if(file_exists($this->path . '/language')){
177 $d= dir($this->path . '/language');
178 while($e = $d->read()){
179 $lang_path = $this->path .'/language/' . $e;
180 if(substr($e, 0, 1) != '.' && is_dir($lang_path)){
181 $f = dir($lang_path);
182 while($g = $f->read()){
183 if(substr($g, 0, 1) != '.' && is_file($lang_path.'/'. $g)){
184 $lang = substr($g, 0, strpos($g, '.'));
185 $installdefs['language'][] = array(
186 'from'=> '<basepath>/SugarModules/language/'.$e . '/'. $g,
195 copy_recursive( $this->path . '/language/', $path . '/language/');
196 $icon_path = $path . '/../icons/default/images/';
197 mkdir_recursive($icon_path);
198 copy_recursive($this->path . '/icons/', $icon_path);
200 return "\n".'$installdefs = ' . var_export_helper($installdefs). ';';
204 function getPackageDir(){
205 return MB_PACKAGE_PATH . '/' . $this->name;
208 function getBuildDir(){
209 return MB_PACKAGE_BUILD . '/' . $this->name;
212 function getZipDir(){
213 return $this->getPackageDir() . '/zips';
218 $path = $this->getPackageDir();
219 if(file_exists($path .'/manifest.php')){
220 require($path . '/manifest.php');
221 if(!empty($manifest)){
222 $this->date_modified = $manifest['published_date'];
223 $this->is_uninstallable = $manifest['is_uninstallable'];
224 $this->author = $manifest['author'];
225 $this->key = $manifest['key'];
226 $this->description = $manifest['description'];
227 if(!empty($manifest['readme']))
228 $this->readme = $manifest['readme'];
231 $this->loadModules(true);
235 $path = $this->getPackageDir();
236 if(mkdir_recursive($path)){
237 $fp = sugar_fopen($path .'/manifest.php', 'w');
240 //Save all the modules when we save a package
241 $this->updateModulesMetaData(true);
242 fwrite($fp, $this->getManifest() );
251 function build($export=true, $clean = false){
252 $this->loadModules();
253 require_once('include/utils/zip_utils.php');
254 $package_path = $this->getPackageDir();
255 $path = $this->getBuildDir() . '/SugarModules';
256 if($clean && file_exists($path))rmdir_recursive($path);
257 if(mkdir_recursive($path)){
259 $manifest = $this->getManifest().$this->buildInstall($path);
260 $fp = sugar_fopen($this->getBuildDir() .'/manifest.php', 'w');
261 fwrite($fp, $manifest);
265 if(file_exists('modules/ModuleBuilder/MB/LICENSE.txt')){
266 copy('modules/ModuleBuilder/MB/LICENSE.txt', $this->getBuildDir() . '/LICENSE.txt');
267 }else if(file_exists('LICENSE.txt')){
268 copy('LICENSE.txt', $this->getBuildDir() . '/LICENSE.txt');
270 $package_dir = $this->getPackageDir();
271 $date = date('Y_m_d_His');
272 $zipDir = $this->getZipDir();
273 if(!file_exists($zipDir))mkdir_recursive($zipDir);
275 chdir($this->getBuildDir());
276 zip_dir('.',$cwd . '/'. $zipDir. '/'. $this->name. $date. '.zip');
279 header('Location:' . $zipDir. '/'. $this->name. $date. '.zip');
282 'zip'=>$zipDir. '/'. $this->name. $date. '.zip',
283 'manifest'=>$this->getBuildDir(). '/manifest.php',
284 'name'=>$this->name. $date,
290 $this->loadModules();
291 $node = array('name'=>$this->name, 'action'=>'module=ModuleBuilder&action=package&package=' . $this->name, 'children'=>array());
292 foreach(array_keys($this->modules) as $module){
293 $node['children'][] = $this->modules[$module]->getNodes();
298 function populateFromPost(){
299 $this->description = trim($_REQUEST['description']);
300 $this->author = trim($_REQUEST['author']);
301 $this->key = trim($_REQUEST['key']);
302 $this->readme = trim($_REQUEST['readme']);
305 function rename($new_name){
306 $old= $this->getPackageDir();
307 $this->name = $new_name;
308 $new = $this->getPackageDir();
309 if(file_exists($new)){
312 if(rename($old, $new)){
319 function updateModulesMetaData($save=false){
320 foreach(array_keys($this->modules) as $module){
321 $old_name = $this->modules[$module]->key_name;
322 $this->modules[$module]->key_name = $this->key . '_' . $this->modules[$module]->name;
323 $this->modules[$module]->renameMetaData($this->modules[$module]->getModuleDir(), $old_name);
324 $this->modules[$module]->renameLanguageFiles($this->modules[$module]->getModuleDir());
325 if($save)$this->modules[$module]->save();
330 function copy($new_name){
331 $old= $this->getPackageDir();
334 $this->name = $new_name;
335 $new= $this->getPackageDir();
336 while(file_exists($new)){
338 $this->name = $new_name . $count;
339 $new= $this->getPackageDir();
342 $new = $this->getPackageDir();
343 if(copy_recursive($old, $new)){
344 $this->updateModulesMetaData();
352 return rmdir_recursive($this->getPackageDir());
356 //creation of the installdefs[] array for the manifest when exporting customizations
357 function customBuildInstall($modules, $path, $extensions = array()){
358 $columns=$this->getColumnsName();
359 $installdefs = array ('id' => $this->name);
360 $include_path="$path/SugarModules/include/language";
361 if(file_exists($include_path) && is_dir($include_path)){
362 $dd= dir($include_path);
363 while($gg = $dd->read()){
364 if(substr($gg, 0, 1) != '.' && is_file($include_path . '/' . $gg)){
365 $lang = substr($gg, 0, strpos($gg, '.'));
366 $installdefs['language'][] = array(
367 'from'=> '<basepath>/SugarModules/include/language/'. $gg,
368 'to_module'=> 'application',
375 foreach($modules as $value){
376 $custom_module = $this->getCustomModules($value);
377 foreach($custom_module as $va){
378 if ($va == 'language'){
379 $this->getLanguageManifestForModule($value, $installdefs);
380 $this->getCustomFieldsManifestForModule($value, $installdefs);
382 if($va == 'metadata'){
383 $this->getCustomMetadataManifestForModule($value, $installdefs);
387 if (is_dir("$path/Extension"))
389 $this->getExtensionsManifestForPackage($path, $installdefs);
391 return "\n".'$installdefs = ' . var_export_helper($installdefs). ';';
394 private function getLanguageManifestForModule($module, &$installdefs)
396 $lang_path = 'custom/modules/' . $module . '/language';
397 foreach(scandir($lang_path) as $langFile)
399 if(substr($langFile, 0, 1) != '.' && is_file($lang_path . '/' . $langFile)){
400 $lang = substr($langFile, 0, strpos($langFile, '.'));
401 $installdefs['language'][] = array(
402 'from'=> '<basepath>/SugarModules/modules/' . $module . '/language/'. $langFile,
403 'to_module'=> $module,
410 private function getCustomFieldsManifestForModule($module, &$installdefs)
412 $db = DBManagerFactory::getInstance();
413 $result=$db->query("SELECT * FROM fields_meta_data where custom_module='$module'");
414 while($row = $db->fetchByAssoc($result)){
416 foreach($row as $col=>$res){
418 case 'custom_module':
419 $installdefs['custom_fields'][$name]['module'] = $res;
422 $installdefs['custom_fields'][$name]['require_option'] = $res;
425 $installdefs['custom_fields'][$name]['label'] = $res;
428 $installdefs['custom_fields'][$name]['require_option'] = $res;
431 $installdefs['custom_fields'][$name]['mass_update'] = $res;
434 $installdefs['custom_fields'][$name]['comments'] = $res;
437 $installdefs['custom_fields'][$name]['help'] = $res;
440 $installdefs['custom_fields'][$name]['max_size'] = $res;
443 $installdefs['custom_fields'][$name][$col] = $res;
449 private function getCustomMetadataManifestForModule($module, &$installdefs)
451 $meta_path = 'custom/modules/' . $module . '/metadata';
452 foreach(scandir($meta_path) as $meta_file)
454 if(substr($meta_file, 0, 1) != '.' && is_file($meta_path . '/' . $meta_file)){
455 if($meta_file == 'listviewdefs.php'){
456 $installdefs['copy'][] = array(
457 'from'=> '<basepath>/SugarModules/modules/'. $module . '/metadata/'. $meta_file,
458 'to'=> 'custom/modules/'. $module . '/metadata/' . $meta_file,
462 $installdefs['copy'][] = array(
463 'from'=> '<basepath>/SugarModules/modules/'. $module . '/metadata/'. $meta_file,
464 'to'=> 'custom/modules/'. $module . '/metadata/' . $meta_file,
466 $installdefs['copy'][] = array(
467 'from'=> '<basepath>/SugarModules/modules/'. $module . '/metadata/'. $meta_file,
468 'to'=> 'custom/working/modules/'. $module . '/metadata/' . $meta_file,
475 private function getExtensionsManifestForPackage($path, &$installdefs)
477 $extPath = "$path/Extension/modules";
478 foreach(scandir($extPath) as $moduleDir)
480 if(substr($moduleDir, 0, 1) != '.' && is_dir("$extPath/$moduleDir/Ext")){
481 foreach(scandir("$extPath/$moduleDir/Ext") as $type)
483 if(substr($type, 0, 1) != '.' && is_dir("$extPath/$moduleDir/Ext/$type")){
484 foreach(scandir("$extPath/$moduleDir/Ext/$type") as $file)
486 if(substr($file, 0, 1) != '.' && strtolower(substr($file, -4)) == ".php")
488 $installdefs['copy'][] = array(
489 'from'=> "<basepath>/Extension/modules/$moduleDir/Ext/$type/$file",
490 'to'=> "custom/Extension/modules/$moduleDir/Ext/$type/$file",
501 //return an array which contain the name of fields_meta_data table's columns
502 function getColumnsName(){
504 $meta = new FieldsMetaData();
506 foreach($meta->getFieldDefinitions() as $key=>$value) {
513 //creation of the custom fields ZIP file (use getmanifest() and customBuildInstall() )
514 function exportCustom($modules, $export=true, $clean = true){
515 $path=$this->getBuildDir();
516 if($clean && file_exists($path))rmdir_recursive($path);
517 //Copy the custom files to the build dir
518 foreach($modules as $mod){
519 $extensions = $this->getExtensionsList($mod);
520 $pathmod="$path/SugarModules/modules/$mod";
521 if(mkdir_recursive($pathmod)){
522 if(file_exists("custom/modules/$mod")){
523 copy_recursive("custom/modules/$mod", "$pathmod");
524 //Don't include cached extension files
525 if (is_dir("$pathmod/Ext"))
526 rmdir_recursive("$pathmod/Ext");
528 //Convert modstring files to extension compatible arrays
529 $this->convertLangFilesToExtensions("$pathmod/language");
531 $pathext="$path/Extension/modules/$mod/Ext";
532 if (!empty($extensions) && mkdir_recursive($pathext))
534 foreach($extensions as $type => $files)
536 sugar_mkdir("$pathext/$type");
537 foreach($files as $file => $filePath)
539 copy ($filePath, "$pathext/$type/$file");
545 $this->copyCustomDropdownValuesForModules($modules,$path);
546 if(file_exists($path)){
547 $manifest = $this->getManifest(true).$this->customBuildInstall($modules,$path);
548 sugar_file_put_contents($path .'/manifest.php', $manifest);;
550 if(file_exists('modules/ModuleBuilder/MB/LICENSE.txt')){
551 copy('modules/ModuleBuilder/MB/LICENSE.txt', $path . '/LICENSE.txt');
553 else if(file_exists('LICENSE.txt')){
554 copy('LICENSE.txt', $path . '/LICENSE.txt');
556 require_once('include/utils/zip_utils.php');
557 $date = date('Y_m_d_His');
558 $zipDir = $this->getZipDir();
559 if(!file_exists($zipDir))mkdir_recursive($zipDir);
561 chdir($this->getBuildDir());
562 zip_dir('.',$cwd . '/'. $zipDir. '/'. $this->name. $date. '.zip');
564 if($clean && file_exists($this->getBuildDir()))rmdir_recursive($this->getBuildDir());
566 header('Location:' . $zipDir. '/'. $this->name. $date. '.zip');
568 return $zipDir. '/'. $this->name. $date. '.zip';
571 private function convertLangFilesToExtensions($langDir)
573 if (is_dir($langDir))
575 foreach(scandir($langDir) as $langFile)
577 $mod_strings = array();
578 if (strcasecmp(substr($langFile, -4), ".php") != 0)
580 include("$langDir/$langFile");
581 $out = "<?php \n // created: " . date('Y-m-d H:i:s') . "\n";
582 foreach($mod_strings as $lbl_key => $lbl_val )
584 $out .= override_value_to_string("mod_strings", $lbl_key, $lbl_val) . "\n";
587 sugar_file_put_contents("$langDir/$langFile", $out);
591 private function copyCustomDropdownValuesForModules($modules, $path)
593 if(file_exists("custom/include/language")){
594 if(mkdir_recursive("$path/SugarModules/include")){
595 global $app_list_strings;
596 $backStrings = $app_list_strings;
597 foreach(scandir("custom/include/language") as $langFile)
599 $app_list_strings = array();
600 if (strcasecmp(substr($langFile, -4), ".php") != 0)
602 include("custom/include/language/$langFile");
604 $lang = substr($langFile, 0, -9);
605 $options = $this->getCustomDropDownStringsForModules($modules, $app_list_strings);
606 foreach($options as $name => $arr) {
607 $out .= override_value_to_string('app_list_strings', $name, $arr);
609 mkdir_recursive("$path/SugarModules/include/language/");
610 sugar_file_put_contents("$path/SugarModules/include/language/$lang.$this->name.php", $out);
612 $app_list_strings = $backStrings;
617 function getCustomDropDownStringsForModules($modules, $list_strings) {
618 global $beanList, $beanFiles;
620 foreach($modules as $module)
622 if (!empty($beanList[$module]))
624 require_once($beanFiles[$beanList[$module]]);
625 $bean = new $beanList[$module]();
626 foreach($bean->field_defs as $field => $def)
628 if (isset($def['options']) && isset($list_strings[$def['options']]))
630 $options[$def['options']] = $list_strings[$def['options']];
640 //if $module=false : return an array with custom module and there customizations.
641 //if $module=!false : return an array with the directories of custom/module/$module.
642 function getCustomModules($module=false){
644 $path='custom/modules/';
645 $extPath = 'custom/Extension/modules/';
646 if(!file_exists($path) || !is_dir($path)){
647 return array($mod_strings['LBL_EC_NOCUSTOM'] => "");
650 if ($module != false ){
651 $path=$path . $module . '/';
653 $scanlisting = scandir($path);
654 $dirlisting = array();
655 foreach ($scanlisting as $value){
656 if(is_dir($path . $value) == true && $value != '.' && $value != '..') {
657 $dirlisting[] = $value;
660 if(empty($dirlisting)){
661 return array($mod_strings['LBL_EC_NOCUSTOM'] => "");
663 if ($module == false ){
664 foreach ($dirlisting as $value){
665 if(!file_exists('modules/' . $value . '/metadata/studio.php'))
667 $custommodules[$value]=$this->getCustomModules($value);
668 foreach ($custommodules[$value] as $va){
671 $return[$value][$va] = $mod_strings['LBL_EC_CUSTOMFIELD'];
674 $return[$value][$va] = $mod_strings['LBL_EC_CUSTOMLAYOUT'];
678 $return[$value][$va] = $mod_strings['LBL_EC_CUSTOMFIELD'];
681 $return[$value . " " . $mod_strings['LBL_EC_EMPTYCUSTOM']] = "";
684 $return[$value][$va] = $mod_strings['LBL_UNDEFINED'];
696 private function getExtensionsList($module, $excludeRelationships = true)
698 require_once 'modules/ModuleBuilder/parsers/relationships/DeployedRelationships.php' ;
699 $extPath = 'custom/Extension/modules/';
700 $modExtPath = $extPath . $module . '/Ext';
701 $rels = new DeployedRelationships($module);
702 $relList = $rels->getRelationshipList ();
705 if (is_dir($modExtPath))
707 $extFolders = scandir($modExtPath);
708 foreach($extFolders as $extFolder)
710 if (!is_dir("$modExtPath/$extFolder") || substr($extFolder, 0, 1) == ".")
713 foreach( scandir("$modExtPath/$extFolder") as $extFile)
716 if (substr($extFile, 0, 1) == "." || strtolower(substr($extFile, -4)) != ".php")
718 //Exclude relattionship extension files
719 if ($excludeRelationships && (
720 (substr($extFile, 0, 6) == "custom" && isset($relList[substr($extFile, 6, strlen($extFile) - 10)])) ||
721 (substr($extFile, 6, 6) == "custom" && isset($relList[substr($extFile, 12, strlen($extFile) - 16)]))
726 if (!isset($ret[$extFolder]))
727 $ret[$extFolder] = array();
729 $ret[$extFolder][$extFile ] = "$modExtPath/$extFolder/$extFile";
737 * Returns a set of field defs for fields that will exist when this package is deployed
738 * based on the relationships in all of its modules.
740 * @param $moduleName (module must be from whithin this package)
741 * @return array Field defs
743 function getRelationshipsForModule($moduleName) {
745 if (isset($this->modules[$moduleName])) {
746 $keyName = $this->modules[$moduleName]->key_name;
747 foreach($this->modules as $mName => $module) {
748 $rels = $module->getRelationships();
749 $relList = $rels->getRelationshipList();
750 foreach($relList as $rName ) {
751 $rel = $rels->get ( $rName ) ;
752 if ($rel->lhs_module == $keyName || $rel->rhs_module == $keyName) {
763 function exportProjectInstall($package, $for_export){
764 $pre = $for_export ? MB_EXPORTPREPEND : "";
765 $installdefs = array ('id' => $pre . $this->name);
766 $installdefs['copy'][] = array(
767 'from'=> '<basepath>/' . $this->name,
768 'to'=> 'custom/modulebuilder/packages/'. $this->name,
770 return "\n".'$installdefs = ' . var_export_helper($installdefs). ';';
776 function exportProject($package, $export=true, $clean = true){
777 $tmppath="custom/modulebuilder/projectTMP/";
778 if(file_exists($this->getPackageDir())){
779 if(mkdir_recursive($tmppath)){
780 copy_recursive($this->getPackageDir(), $tmppath ."/". $this->name);
781 $manifest = $this->getManifest(true, $export).$this->exportProjectInstall($package, $export);
782 $fp = sugar_fopen($tmppath .'/manifest.php', 'w');
783 fwrite($fp, $manifest);
785 if(file_exists('modules/ModuleBuilder/MB/LICENSE.txt')){
786 copy('modules/ModuleBuilder/MB/LICENSE.txt', $tmppath . '/LICENSE.txt');
788 else if(file_exists('LICENSE.txt')){
789 copy('LICENSE.txt', $tmppath . '/LICENSE.txt');
791 $readme_contents = $this->readme;
792 $readmefp = sugar_fopen($tmppath.'/README.txt','w');
793 fwrite($readmefp, $readme_contents);
797 require_once('include/utils/zip_utils.php');
798 $date = date('Y_m_d_His');
799 $zipDir = "custom/modulebuilder/packages/ExportProjectZips";
800 if(!file_exists($zipDir))mkdir_recursive($zipDir);
803 zip_dir('.',$cwd . '/'. $zipDir. '/project_'. $this->name. $date. '.zip');
805 if($clean && file_exists($tmppath))rmdir_recursive($tmppath);
807 header('Location:' . $zipDir. '/project_'. $this->name. $date. '.zip');
809 return $zipDir. '/project_'. $this->name. $date. '.zip';