'com_name', 'comcomname' => 'com_com_name', 'version' => 'com_version', 'lang_admin' => 'dir_lang_admin', 'lang_site' => 'dir_lang_site', 'installxml'=>'installxml', 'description' => 'description', 'ebc_author' => 'author', 'authoremail' => 'authoremail', 'authorurl' => 'authorurl', 'license' => 'license', 'copyright' => 'copyright' , 'creationdate' => 'creationDate' ); private $_credit_vars = array(); private $_langs = array(); private $_copys = array(); private $_menu = array(); private $_submenu = array(); private $_scope = ''; private $_entryFile = ''; private $_f_date = ''; private $_download_link = ''; private $downloadLinks = array(); private $_steps = array(); private $_log = array(); private $_buildopts = array(); private $_profiler = null; private $logger = null; private $project; public $_errors = array(); /** * Constructor * * @access public * @return void */ public function __construct() { jimport('joomla.filesystem.file'); }// function /** * Create the package * * @param unknown_type $project * * @return bool true on success */ public function create($project) { $this->project = $project; $this->base = JPATH_SITE; $this->build_dir = substr(JPATH_COMPONENT, strlen(JPATH_SITE) + 1 ).DS.'builds'; $this->setDate(date("ymd_Hi")); //--Init buildopts $buildopts = JRequest::getVar('buildopts',array()); $this->initBuildOpts($buildopts); //--Setup logging JLoader::import('helpers.logger', JPATH_COMPONENT); $logName = date('ymd_Hi').'_packing.log'; $this->logger = new easyLogger($logName, $buildopts); $this->logger->log( 'STARTING at:
'.$this->base.'
Build dir:
'.$this->build_dir); $this->setTempDir(); $this->copyCopys(); $this->copyLanguage(); $this->copyPackageElements(); //--Deleting 'old' manifest.. $this->deleteManifest(); if( ! $this->_createManifest($project) ) { $this->_errors[] = 'unable to create manifest'; return false; } $this->createZip(); $this->removeBuildDir(); $this->logger->log('FINISHED'); $this->logger->writeLog(); return true; }// function private function initBuildOpts( $buildopts ) { $this->_buildopts['verbose'] =( in_array('verbose', $buildopts) ) ? true : false; $this->_buildopts['files'] =( in_array('files', $buildopts) ) ? true : false; $this->_buildopts['archive_zip'] =( in_array('archive_zip', $buildopts) ) ? true : false; $this->_buildopts['archive_tgz'] =( in_array('archive_tgz', $buildopts) ) ? true : false; $this->_buildopts['archive_bz'] =( in_array('archive_bz', $buildopts) ) ? true : false; //--Init profiler $this->_buildopts['profiling'] = false; if( in_array('profile', $buildopts) ) { jimport('joomla.error.profiler'); $this->_profiler =& JProfiler::getInstance( 'EasyZipper' ); $this->_buildopts['profiling'] = true; } }//function /** * Tries to find the package manifest file * * @access private * @return boolean True on success, False on error * @since 1.0 */ function deleteManifest() { // Get an array of all the xml files from teh installation directory $xmlfiles = JFolder::files($this->_temp_dir, '.xml$', 1, true); // If at least one xml file exists if (!empty($xmlfiles)) { foreach ($xmlfiles as $file) { // Is it a valid joomla installation manifest file? $manifest = $this->_isManifest($file); if (!is_null($manifest)) { ###JFile::move($file, $file.'.backup'); if( JFile::delete($file)) { $this->logger->log( 'File deleted '.$file); return true; } else { $this->logger->log( 'Unable to delete file '.$file, 'ERROR'); return false; } } }//foreach // None of the xml files found were valid install files # JError::raiseWarning(1, 'JInstaller::install: '.JText::_('ERRORNOTFINDJOOMLAXMLSETUPFILE')); return false; } else { // No xml files were found in the install folder # JError::raiseWarning(1, 'JInstaller::install: '.JText::_('ERRORXMLSETUP')); return false; } }//function /** * Is the xml file a valid Joomla installation manifest file * * @access private * @param string $file An xmlfile path to check * @return mixed A JSimpleXML document, or null if the file failed to parse * @since 1.5 */ function &_isManifest($file) { // Initialize variables $null = null; $xml =& JFactory::getXMLParser('Simple'); // If we cannot load the xml file return null if (!$xml->loadFile($file)) { // Free up xml parser memory and return null unset ($xml); return $null; } /* * Check for a valid XML root tag. */ $root =& $xml->document; if (!is_object($root) || ($root->name() != 'install')) { // Free up xml parser memory and return null unset ($xml); return $null; } // Valid manifest file return the object return $xml; } private function _createManifest( $project ) { //--Get manifest class JLoader::import('helpers.manifest', JPATH_COMPONENT); $manifest = new Manifest(); $project->basepath = $this->_temp_dir; $project->creationDate = date("d-M-Y"); $this->logger->log('Starting manifest'); if( $manifest->create($project)) { $this->logger->logFileWrite('', $project->basepath.DS.$project->installxml, $manifest->getNormalizedString()); } else { $this->logger->log('Error creating manifest file: '.$manifest->getError(),'Error creating manifest file'); //TODO ABORT return false; } return true; }// function /** * Set the temp directory */ private function setTempDir() { $config =& JFactory::getConfig(); $this->_temp_dir = $config->getValue('config.tmp_path'); $this->_temp_dir .= DS.uniqid($this->project->com_name); if( JFolder::create($this->_temp_dir) ) { $this->logger->log('TempDir created
'.$this->_temp_dir); return true; } else { $this->logger->log('ERROR creating TempDir
'.$this->_temp_dir, 'ERROR'); return false; } }// function /** * parse the config file */ function _parseConfig() { foreach( $this->_configfile as $line ) { //TODO separator char is a space.. switch to '=' ? $args = explode( ' ', $line ); $command = strtolower( trim($args[0]) ); if( ! $command ) continue; foreach( $this->_build_vars as $k => $v ) { if( $command == $k ) { $value = trim( substr( $line, strlen( $command ))); $this->_credit_vars[$v] = $value; $this->logger->log('ADD _credit_var: '. $v.' : '.$value.'
'); continue 2; } }//foreach switch( $command ) { case 'langs': $this->_langs = explode(',', trim($args[1])); foreach( $this->_langs as $k=>$v ) { $this->logger->log('Found Lang: '.$k.') '.$v.'
'); } break; case 'ecopy': $i =( count($this->_copys) ) ? count($this->_copys) : 0; $this->_copys[$i]['source'] = JPath::clean( trim($args[1]) ); $this->_copys[$i]['dest'] =(isset($args[2])) ? JPath::clean( trim($args[2]) ): ''; $this->logger->log( '$copy['.$i.']source: '.$this->_copys[$i]['source'].'
'); $this->logger->log( '$copy['.$i.']dest: '.$this->_copys[$i]['dest'].'
'); break; case 'menu': $this->_menu['img'] = trim($args[1]); $this->_menu['link'] = trim($args[2]); //--menu['text'] can contain spaces, so asume all other args to be ['text'].. //--for that text must be in last place ! $this->_menu['text'] = trim(substr($line, strpos($line, $args[3]) )); $this->logger->log( 'menu entry found: '.$line); break; case 'submenu': $i =( count($this->_submenu) ) ? count($this->_submenu) : 0; $this->_submenu[$i]['img'] = trim($args[1]); $this->_submenu[$i]['link'] = trim($args[2]); //--menu['text'] can contain spaces, so asume all other args to be ['text'].. //--for that text must be in last place ! $this->_submenu[$i]['text'] = trim(substr($line, strpos($line, $args[3]) )); $this->logger->log( 'submenu entry found: '.$line); break; case 'comscope': $this->_scope = trim($args[1]); $this->logger->log( 'scope entry found: '.$line); break; case 'comtype': $this->_com_type = trim($args[1]); $this->logger->log( 'com_type entry found: '.$line); break; case 'entryfile': $this->_entryFile = trim($args[1]); $this->logger->log( 'entryfile entry found: '.$line); break; default: if( $command ) { $this->logger->log( 'UNKNOWN '.$args[0]); } break; }//switch }//foreach return true; }// function function getParsedConfig( $configfile ) { if( ! $configfile ) { echo 'no config..'; return false; } return $this->_parseEEConfig( $configfile ); }// function function _parseEEConfig( $configfile ) { $parsed = array(); $parsed['copys'] = array(); $parsed['menu'] = array(); $parsed['submenu'] = array(); foreach( $configfile as $line ) { $args = explode(' ', $line); $command = strtolower( trim($args[0]) ); if( ! $command ) { continue; } foreach( $this->_build_vars as $k=>$v ) { if( $command == $k ) { $parsed['buildvars'][$v] = trim($args[1]); continue 2; } }//foreach switch( $command ) { case 'langs': $parsed ['langs'] = explode(',', trim($args[1])); break; case 'ecopy': $i =( count($parsed ['copys']) ) ? count($parsed ['copys']) : 0; $parsed ['copys'][$i]['source'] = trim($args[1]); $parsed ['copys'][$i]['dest'] =(isset($args[2])) ? trim($args[2]) : ''; break; case 'menu': $parsed ['menu']['img'] = trim($args[1]); $parsed ['menu']['link'] = trim($args[2]); $parsed ['menu']['text'] = trim($args[3]); break; case 'submenu': $i =( count($parsed ['submenu']) ) ? count($parsed ['submenu']) : 0; $parsed ['submenu'][$i]['img'] = trim($args[1]); $parsed ['submenu'][$i]['link'] = trim($args[2]); $parsed ['submenu'][$i]['text'] = trim($args[3]); break; default: if( trim($args[0])) { $parsed['unknown'][] = $args[0]; } break; }//switch }//foreach if( defined('ECR_DEBUG') ) { //echo '
';
//print_r($parsed);
//echo '
'; } return $parsed; }// function /** * Copy files and folders */ private function copyCopys( ) { foreach( $this->project->copys as $copy ) { $copy['source'] = str_replace('/', DS, $copy['source']); $copy['dest'] = str_replace('/', DS, $copy['dest']); $tmp_dest = $this->_temp_dir.DS.$copy['dest']; JFolder::create($tmp_dest); if( is_dir( $this->base.DS.$copy['source'] )) { //--source is a directory //--copy with force overwrite.. if( JFolder::copy( $this->base.DS.$copy['source'], $tmp_dest, '', true )) { $this->logger->log('COPY DIR
SRC: '.$copy['source'].'
DST: '.$tmp_dest); if( $this->project->com_com_name == com_EASY_APP_ELKUKU_1 ) { if( JFile::exists($this->_temp_dir.DS.'admin'.DS.'builds'.DS.'scripts'.DS.'com_easycreator.ebc')) { if(JFile::delete($this->_temp_dir.DS.'admin'.DS.'builds'.DS.'scripts'.DS.'com_easycreator.ebc')) { $this->logger->log('EasyCreator ebc file deleted'); } else { $this->logger->log('EasyCreator ebc file not found :(
'.$this->_temp_dir.DS.'admin'.DS.'builds'.DS.'scripts'.DS.'com_easycreator.ebc', 'ERROR'); } } } } else { $this->logger->log('SRC: '.$copy['source'].'
DST: '.$tmp_dest, 'COPY DIR FAILED'); } } elseif( file_exists($this->base.DS.$copy['source'] )) { //--source is a file if( JFile::copy($this->base.DS.$copy['source'], $tmp_dest.DS.JFile::getName($copy['source']))) { $this->logger->log('COPY FILE
SRC: '.$copy['source'].'
DST: '.$tmp_dest); } else { $this->logger->log('COPY FILE FAILED
SRC: '.$copy['source'].'
DST: '.$tmp_dest,'ERROR copy file'); } } else { //--source does not exist - ABORT - TODO: rollback $this->logger->log( '
NOT FOUND :
>'.$this->base.DS.$copy['source'].'
', 'not found'); # return false; } }//foreach return true; }//function private function copyPackageElements() { JLoader::import('helpers.project', JPATH_COMPONENT); $easyProject = new easyProject(); /* * Modules */ foreach ($this->project->modules as $module) { $clientPath =( $module['client'] == 'administrator' ) ? 'administrator'.DS.'modules' : 'modules'; if( JFolder::copy( JPATH_ROOT.DS.$clientPath.DS.$module['name'], $this->_temp_dir.DS.$module['name'], '', true )) { $this->logger->log('COPY DIR
SRC: '.JPATH_ROOT.DS.$clientPath.DS.$module['name'].'
DST: '.$this->_temp_dir); } else { $this->logger->log('COPY DIR FAILED
SRC: '.JPATH_ROOT.DS.$clientPath.DS.$module['name'].'
DST: '.$this->_temp_dir,'ERROR copy dir'); return false; } //--Get the project if( ! $modProject = $easyProject->getProject($module['name']) ) { //--Something went wrong.. JError::raiseWarning(100, JText::sprintf('Unable to load the project %s', $module['module'])); return false; } if( ! is_array( $modProject->langs)) { continue; } $clientPath =( $module['client'] == 'administrator' ) ? 'administrator'.DS.'language' : 'language'; foreach( $modProject->langs as $language ) { $this->logger->log( 'Processing module language '.$language.''); $tmp_src = $clientPath.DS.$language; $tmp_dest = $this->_temp_dir.DS.$module['name'].DS.'language'.DS.$language; JFolder::create( $tmp_dest ); $tmp_fname = $language.'.'.$module['name'].'.ini'; if( file_exists($this->base.DS.$tmp_src.DS.$tmp_fname)) { JFile::copy( $this->base.DS.$tmp_src.DS.$tmp_fname, $tmp_dest.DS.$tmp_fname); $this->logger->log( 'copy: '.$tmp_src.DS.$tmp_fname); } else { $this->logger->log( 'NOT FOUND: '.$tmp_src.DS.$tmp_fname, 'copy langfile'); } }//foreach }//foreach /* * Plugins */ foreach ($this->project->plugins as $plugin) { //--Get the project if( ! $plgProject = $easyProject->getProject($plugin['name']) ) { //--Something went wrong.. JError::raiseWarning(100, JText::sprintf('Unable to load the project %s', $plugin['module'])); $this->logger->log('Unable to load the project '.$plugin['module'], 'ERROR'); continue; } $plgFolderName = 'plg_'.$plugin['name']; if( JFolder::create($this->_temp_dir.DS.$plgFolderName)) { $this->logger->log('Plugin folder created: '.$this->_temp_dir.DS.$plgFolderName); } else { $this->logger->log('ERROR creating folder'.$this->_temp_dir.DS.$plgFolderName, 'ERROR'); } foreach ($plgProject->copys as $copy) { $fName = JPATH_ROOT.DS.$copy['source']; if( JFolder::exists($fName)) { $tName = str_replace('plugins'.DS.$plugin['client'].DS, '', $copy['source']); if( JFolder::copy($fName, $this->_temp_dir.DS.$plgFolderName.DS.$tName)) { $this->logger->log('COPY folder
SRC: '.$fName.'
DST: '.$this->_temp_dir.DS.$plgFolderName.DS.$tName); } else { $this->logger->log('COPY FOLDER FAILED
SRC: '.$fName.'
DST: '.$this->_temp_dir.DS.$plgFolderName.DS.$tName,'ERROR copy folder'); } } else if( JFile::exists($fName) ) { $tName = JFile::getName($fName); if( JFile::copy($fName, $this->_temp_dir.DS.$plgFolderName.DS.$tName)) { $this->logger->log('COPY file
SRC: '.$fName.'
DST: '.$this->_temp_dir.DS.$plgFolderName.DS.$tName); } else { $this->logger->log('COPY FILE FAILED
SRC: '.$fName.'
DST: '.$this->_temp_dir.DS.$plgFolderName.DS.$tName,'ERROR copy file'); } } else { $this->logger->log('Not found
SRC: '.$fName,'FILE NOT FOUND'); } }//foreach if( ! is_array( $plgProject->langs)) { continue; } foreach( $plgProject->langs as $language ) { $this->logger->log( 'Processing plugin language '.$language.''); $tmp_src = 'administrator'.DS.'language'.DS.$language; $tmp_dest = $this->_temp_dir.DS.$plgFolderName.DS.'language'.DS.$language; JFolder::create( $tmp_dest ); $tmp_fname = $language.'.plg_'.$plugin['client'].'_'.$plugin['name'].'.ini'; if( file_exists($this->base.DS.$tmp_src.DS.$tmp_fname)) { JFile::copy( $this->base.DS.$tmp_src.DS.$tmp_fname, $tmp_dest.DS.$tmp_fname); $this->logger->logFileWrite($tmp_src.DS.$tmp_fname, $tmp_dest.DS.$tmp_fname); } else { $this->logger->log( 'NOT FOUND: '.$tmp_src.DS.$tmp_fname, 'copy langfile'); } }//foreach }//foreach }//function /** * copy language files */ private function copyLanguage() { if( ! is_array( $this->project->langs)) { return; } foreach( $this->project->langs as $language ) { $this->logger->log( 'Processing language '.$language.''); //--Copy admin language if( isset($this->project->dir_lang_admin) && $this->project->dir_lang_admin) { $tmp_src = 'administrator'.DS.'language'.DS.$language; $tmp_dest = $this->_temp_dir.DS.$this->project->dir_lang_admin.DS.$language; JFolder::create( $tmp_dest ); $tmp_fname = $language.'.'.$this->project->com_com_name.'.ini'; if(file_exists($this->base.DS.$tmp_src.DS.$tmp_fname)) { JFile::copy( $this->base.DS.$tmp_src.DS.$tmp_fname, $tmp_dest.DS.$tmp_fname); $this->logger->log( 'copy: '.$this->project->dir_lang_admin.DS.$tmp_fname); } else { $this->logger->log( 'copy FAILED: '.$this->project->dir_lang_admin.DS.$tmp_fname, 'copy langfile'); } //--Copy admin menu language $tmp_fname = $language.'.'.$this->project->com_com_name.'.menu.ini'; if( file_exists($this->base.DS.$tmp_src.DS.$tmp_fname)) { JFile::copy( $this->base.DS.$tmp_src.DS.$tmp_fname, $tmp_dest.DS.$tmp_fname); $this->logger->log( 'copy: '.$this->project->dir_lang_admin.$tmp_fname); } } //--Copy site language if( isset($this->project->dir_lang_site) && $this->project->dir_lang_site) { $tmp_src = 'language'.DS.$language; $tmp_dest = $this->_temp_dir.DS.$this->project->dir_lang_site.DS.$language; JFolder::create( $tmp_dest ); if($this->project->comtype == 'plugin') { //--Plugin language files come from admin and go to site.. $tmp_src = 'administrator'.DS.'language'.DS.$language; $tmp_fname = $language.'.plg_'.$this->project->comscope.'_'.$this->project->com_com_name.'.ini'; } else { $tmp_fname = $language.'.'.$this->project->com_com_name.'.ini'; } if( file_exists($this->base.DS.$tmp_src.DS.$tmp_fname)) { JFile::copy($this->base.DS.$tmp_src.DS.$tmp_fname, $tmp_dest.DS.$tmp_fname); $this->logger->log( 'copy: '.$this->project->dir_lang_site.DS.$tmp_fname); } } }//foreach return true; }// function /** * Create the zip file */ private function createZip() { $zipTypes = array( 'zip' => 'zip' , 'tgz' => 'tar.gz' , 'bz' => 'bz2' ); $this->logger->log('Start adding files'); $workDir = $this->_temp_dir; $zipDir = $this->base.DS.$this->build_dir.DS.'zips'.DS.$this->project->com_com_name.DS.$this->project->com_version; $fileList = array(); //--Change current working directory, so that the zip file gets created in the temp dir chdir($this->_temp_dir); //--Build the file list $files = JFolder::files( $this->_temp_dir, '.', true, true); foreach( $files as $file ) { $fileList[] = substr( $file, strlen( $this->_temp_dir )+1 ); } $this->logger->log( 'TOTAL: '.count($fileList). ' files'); if( ! is_dir($zipDir) ) { JFolder::create($zipDir); } $buildResult = array(); foreach ($zipTypes as $zipType => $ext) { if( $this->_buildopts['archive_'.$zipType] ) { $this->logger->log('creating '.$zipType); $buildResult[$zipType] = $this->createArchive($fileList, $ext); } }//foreach $href = JURI::Root().'administrator/components/'.com_EASY_APP_ELKUKU_1.'/builds/zips/'.$this->project->com_com_name.'/'.$this->project->com_version.'/'.$this->project->com_com_name.'_'. $this->project->com_version.'_'.$this->_f_date; $fileName = $this->project->com_com_name.'_'. $this->project->com_version.'_'.$this->_f_date; # $msg = ''; # $msg .= '
'; # $msg .= '

DONE !

'; foreach ($zipTypes as $zipType => $ext) { if( $this->_buildopts['archive_'.$zipType] && $buildResult[$zipType] ) { # $msg .= '

Download: '.$fileName.'.'.$ext.'

'; $this->downloadLinks[] = $href.'.'.$ext; } }//foreach # $msg .= '
'; # $this->logger->log($msg, 'finished creating zip'); $this->_download_link = $href; return true; }// function private function createArchive($files, $type) { $FileName = $this->project->com_com_name.'_'. $this->project->com_version.'_'.$this->_f_date; $zipDir = $this->base.DS.$this->build_dir.DS.'zips'.DS.$this->project->com_com_name.DS.$this->project->com_version; switch ($type) { case 'zip': $FileName .= '.'.$type; //--Get PEAR::Zip JLoader::import('helpers.Zip', JPATH_COMPONENT); $archive = new Archive_Zip($FileName); if($archive->create($files)) { if(JFile::move($this->_temp_dir.DS.$FileName, $zipDir.DS.$FileName)) { $this->logger->log('Packing routine for '.$type.' finished'); return true; } else { $this->logger->log('ERROR Packing routine for '.$type, 'ERROR packing routine'); return false; } } else { $this->logger->log('ERROR moving file
'.$this->_temp_dir.DS.$FileName.'
'.$zipDir.DS.$FileName, 'ERROR moving file'); return false; } break; case 'tar.gz': case 'bz2': $FileName .= '.'.$type; jimport('joomla.filesystem.archive'); $compression =( $type == 'tar.gz' ) ? 'gz' : 'bz2'; $result = $archive = JArchive::create($FileName, $files, $compression, '', '', false, false); if( $result->_file === 0 ) { //--This means OK if( JFile::move($this->_temp_dir.DS.$FileName, $zipDir.DS.$FileName) ) { $this->logger->log('Packing routine for '.$type.' finished'); return true; } else { JError::raiseWarning(100, JText::_('Unable to move file')); JError::raiseWarning(100, JText::_('From').': '.$this->_temp_dir.DS.$FileName); JError::raiseWarning(100, JText::_('To').': '.$zipDir.DS.$FileName); return false; } } else { JError::raiseWarning(100, JText::sprintf('Packing routine for %s finished with errors', $type)); return false; } break; default: JError::raiseWarning(100, 'undefined packing type '.$type); return false; break; }//switch }//function /** * Remove the build directory */ private function removeBuildDir() { //--Delete the build folder $folderName = $this->_temp_dir; if( ! JFolder::delete( $folderName ) ) { $this->logger->log('Unable to delete
'.$folderName, 'cannot delete'); return false; } else { $this->logger->log('The build folder
'.$folderName.'
has been sucessfully deleted.'); } return true; }// function private function _addLog( $string, $title='', $css_class='' ) { if( $this->_buildopts['verbose'] ) { $spacing = 60; $spacing =( strlen($title) > $spacing ) ? 0 : $spacing - strlen($title); if( $this->_buildopts['profiling'] ){$this->_profiler->mark(str_repeat(' ', $spacing).$title);} $this->_log[] = $string; } }// function public function getLog() { if( is_array( $this->_log )) { return $this->_log; } else { return array('NO LOG SO FAR...'); } }// function public function printLog() { $this->logger->printLog(); return; if( count( $this->_log )) { echo '

LOG:

'; echo ''; if( $this->_buildopts['profiling'] ) { echo '

Profiler:

'; echo '
';
				print_r($this->_profiler->getBuffer());
				echo '
'; } } return true; }// function public function displayDownloadLink() { if( count($this->downloadLinks) ) { echo '
'; echo '

'.JText::_('Download').' :

'; foreach ($this->downloadLinks as $link) { echo '

'.JFile::getName( JPath::clean($link) ).'

'; }//foreach echo '
'; } else { echo '

'.JText::_('No download available').'

'; } }// function public function getErrorLog() { return $this->_errors; }// function public function setDate( $date ) { $this->_f_date = $date; }// function }//class