* @copyright 2007-2011 PrestaShop SA * @version Release: $Revision: 7560 $ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) * International Registered Trademark & Property of PrestaShop SA */ include_once(PS_ADMIN_DIR.'/../tools/tar/Archive_Tar.php'); class AdminModules extends AdminTab { /** @var array map with $_GET keywords and their callback */ private $map = array( 'install' => 'install', 'uninstall' => 'uninstall', 'configure' => 'getContent', 'delete' => 'delete' ); private $listTabModules; private $listPartnerModules = array(); private $listNativeModules = array(); private $_moduleCacheFile; static private $MAX_DISP_AUTHOR = 20; // maximum length to display function __construct() { parent::__construct (); $this->_moduleCacheFile = _PS_ROOT_DIR_.'/config/modules_list.xml'; //refresh modules_list.xml every week if (!$this->isFresh()) $this->refresh(); $this->listTabModules = array('administration' => $this->l('Administration'), 'advertising_marketing' => $this->l('Advertising & Marketing'), 'analytics_stats' => $this->l('Analytics & Stats'), 'billing_invoicing' => $this->l('Billing & Invoicing'), 'checkout' => $this->l('Checkout'), 'content_management' => $this->l('Content Management'), 'export' => $this->l('Export'), 'front_office_features' => $this->l('Front Office Features'), 'i18n_localization' => $this->l('I18n & Localization'), 'merchandizing' => $this->l('Merchandizing'), 'migration_tools' => $this->l('Migration Tools'), 'payments_gateways' => $this->l('Payments & Gateways'), 'payment_security' => $this->l('Payment Security'), 'pricing_promotion' => $this->l('Pricing & Promotion'), 'quick_bulk_update' => $this->l('Quick / Bulk update'), 'search_filter' => $this->l('Search & Filter'), 'seo' => $this->l('SEO'), 'shipping_logistics' => $this->l('Shipping & Logistics'), 'slideshows' => $this->l('Slideshows'), 'smart_shopping' => $this->l('Smart Shopping'), 'market_place' => $this->l('Market Place'), 'social_networks' => $this->l('Social Networks'), 'others'=> $this->l('Other Modules')); $xmlModules = @simplexml_load_file($this->_moduleCacheFile); foreach($xmlModules->children() as $xmlModule) if ($xmlModule->attributes() == 'native') foreach($xmlModule->children() as $module) foreach($module->attributes() as $key => $value) if ($key == 'name') $this->listNativeModules[] = (string)$value; if ($xmlModule->attributes() == 'partner') foreach($xmlModule->children() as $module) foreach($module->attributes() as $key => $value) if ($key == 'name') $this->listPartnerModules[] = (string)$value; } public function postProcess() { global $currentIndex, $cookie; $id_employee = (int)($cookie->id_employee); $filter_conf = Configuration::getMultiple(array( 'PS_SHOW_TYPE_MODULES_'.$id_employee, 'PS_SHOW_COUNTRY_MODULES_'.$id_employee, 'PS_SHOW_INSTALLED_MODULES_'.$id_employee, 'PS_SHOW_ENABLED_MODULES_'.$id_employee )); //reset filtre if (Tools::isSubmit('desactive') && isset($filter_conf['PS_SHOW_ENABLED_MODULES_'.$id_employee]) && $filter_conf['PS_SHOW_ENABLED_MODULES_'.$id_employee] != 'enabledDisabled') $this->setFilterModules($filter_conf['PS_SHOW_TYPE_MODULES_'.$id_employee], $filter_conf['PS_SHOW_COUNTRY_MODULES_'.$id_employee], $filter_conf['PS_SHOW_INSTALLED_MODULES_'.$id_employee], 'disabled'); if (Tools::isSubmit('active') && isset($filter_conf['PS_SHOW_ENABLED_MODULES_'.$id_employee]) && $filter_conf['PS_SHOW_ENABLED_MODULES_'.$id_employee] != 'enabledDisabled') $this->setFilterModules($filter_conf['PS_SHOW_TYPE_MODULES_'.$id_employee], $filter_conf['PS_SHOW_COUNTRY_MODULES_'.$id_employee], $filter_conf['PS_SHOW_INSTALLED_MODULES_'.$id_employee], 'enabled'); if (Tools::isSubmit('uninstall') && isset($filter_conf['PS_SHOW_INSTALLED_MODULES_'.$id_employee]) && $filter_conf['PS_SHOW_INSTALLED_MODULES_'.$id_employee] != 'installedUninstalled') $this->setFilterModules($filter_conf['PS_SHOW_TYPE_MODULES_'.$id_employee], $filter_conf['PS_SHOW_COUNTRY_MODULES_'.$id_employee], 'unistalled', $filter_conf['PS_SHOW_ENABLED_MODULES_'.$id_employee]); if (Tools::isSubmit('install') && isset($filter_conf['PS_SHOW_INSTALLED_MODULES_'.$id_employee]) && $filter_conf['PS_SHOW_INSTALLED_MODULES_'.$id_employee] != 'installedUninstalled') $this->setFilterModules($filter_conf['PS_SHOW_TYPE_MODULES_'.$id_employee], $filter_conf['PS_SHOW_COUNTRY_MODULES_'.$id_employee], 'installed', $filter_conf['PS_SHOW_ENABLED_MODULES_'.$id_employee]); if (Tools::isSubmit('filterModules')) { $this->setFilterModules(Tools::getValue('module_type'), Tools::getValue('country_module_value'), Tools::getValue('module_install'), Tools::getValue('module_status')); Tools::redirectAdmin($currentIndex.'&token='.$this->token); } elseif (Tools::isSubmit('resetFilterModules')) { $this->resetFilterModules(); Tools::redirectAdmin($currentIndex.'&token='.$this->token); } if (Tools::isSubmit('active')) { if ($this->tabAccess['edit'] === '1') { $module = Module::getInstanceByName(Tools::getValue('module_name')); if (Validate::isLoadedObject($module)) { $module->enable(); Tools::redirectAdmin($currentIndex.'&conf=5'.'&token='.$this->token.'&tab_module='.$module->tab.'&module_name='.$module->name); } else $this->_errors[] = Tools::displayError('Cannot load module object'); } else $this->_errors[] = Tools::displayError('You do not have permission to add here.'); } elseif (Tools::isSubmit('desactive')) { if ($this->tabAccess['edit'] === '1') { $module = Module::getInstanceByName(Tools::getValue('module_name')); if (Validate::isLoadedObject($module)) { $module->disable(); Tools::redirectAdmin($currentIndex.'&conf=5'.'&token='.$this->token.'&tab_module='.$module->tab.'&module_name='.$module->name); } else $this->_errors[] = Tools::displayError('Cannot load module object'); } else $this->_errors[] = Tools::displayError('You do not have permission to add here.'); } elseif (Tools::isSubmit('reset')) { if ($this->tabAccess['edit'] === '1') { $module = Module::getInstanceByName(Tools::getValue('module_name')); if (Validate::isLoadedObject($module)) { if ($module->uninstall()) if ($module->install()) Tools::redirectAdmin($currentIndex.'&conf=21'.'&token='.$this->token.'&tab_module='.$module->tab.'&module_name='.$module->name); else $this->_errors[] = Tools::displayError('Cannot install module'); else $this->_errors[] = Tools::displayError('Cannot uninstall module'); } else $this->_errors[] = Tools::displayError('Cannot load module object'); } else $this->_errors[] = Tools::displayError('You do not have permission to add here.'); } /* Automatically copy a module from external URL and unarchive it in the appropriated directory */ if (Tools::isSubmit('submitDownload')) { if ($this->tabAccess['add'] === '1') { if (Validate::isModuleUrl($url = Tools::getValue('url'), $this->_errors)) { if (!@copy($url, _PS_MODULE_DIR_.basename($url))) $this->_errors[] = Tools::displayError('404 Module not found'); else $this->extractArchive(_PS_MODULE_DIR_.basename($url)); } } else $this->_errors[] = Tools::displayError('You do not have permission to add here.'); } if (Tools::isSubmit('submitDownload2')) { if ($this->tabAccess['add'] === '1') { if (!isset($_FILES['file']['tmp_name']) OR empty($_FILES['file']['tmp_name'])) $this->_errors[] = $this->l('no file selected'); elseif (substr($_FILES['file']['name'], -4) != '.tar' AND substr($_FILES['file']['name'], -4) != '.zip' AND substr($_FILES['file']['name'], -4) != '.tgz' AND substr($_FILES['file']['name'], -7) != '.tar.gz') $this->_errors[] = Tools::displayError('Unknown archive type'); elseif (!@copy($_FILES['file']['tmp_name'], _PS_MODULE_DIR_.$_FILES['file']['name'])) $this->_errors[] = Tools::displayError('An error occurred while copying archive to module directory.'); else $this->extractArchive(_PS_MODULE_DIR_.$_FILES['file']['name']); } else $this->_errors[] = Tools::displayError('You do not have permission to add here.'); } if (Tools::isSubmit('deleteModule')) { if ($this->tabAccess['delete'] === '1') { if (Tools::getValue('module_name') != '') { $moduleDir = _PS_MODULE_DIR_.str_replace(array('.', '/', '\\'), array('', '', ''), Tools::getValue('module_name')); $this->recursiveDeleteOnDisk($moduleDir); Tools::redirectAdmin($currentIndex.'&conf=22&token='.$this->token.'&tab_module='.Tools::getValue('tab_module')); } Tools::redirectAdmin($currentIndex.'&token='.$this->token); } else $this->_errors[] = Tools::displayError('You do not have permission to delete here.'); } /* Call appropriate module callback */ else { $return = false; foreach ($this->map as $key => $method) { $modules = Tools::getValue($key); if (strpos($modules, '|')) $modules = explode('|', $modules); else $modules = empty($modules) ? false : array($modules); $module_errors = array(); if ($modules) foreach ($modules AS $name) { if (!($module = Module::getInstanceByName(urldecode($name)))) $this->_errors[] = $this->l('module not found'); elseif ($key == 'install' AND $this->tabAccess['add'] !== '1') $this->_errors[] = Tools::displayError('You do not have permission to add here.'); elseif ($key == 'uninstall' AND $this->tabAccess['delete'] !== '1') $this->_errors[] = Tools::displayError('You do not have permission to delete here.'); elseif ($key == 'configure' AND $this->tabAccess['edit'] !== '1') $this->_errors[] = Tools::displayError('You do not have permission to edit here.'); elseif ($key == 'install' AND Module::isInstalled($module->name)) $this->_errors[] = Tools::displayError('This module is already installed : ').$module->name; elseif ($key == 'uninstall' AND !Module::isInstalled($module->name)) $this->_errors[] = Tools::displayError('This module is already uninstalled : ').$module->name; elseif (($echo = $module->{$method}()) AND ($key == 'configure') AND Module::isInstalled($module->name)) { $backlink = $currentIndex.'&token='.$this->token.'&tab_module='.$module->tab.'&module_name='.$module->name; $hooklink = 'index.php?tab=AdminModulesPositions&token='.Tools::getAdminTokenLite('AdminModulesPositions').'&show_modules='.(int)$module->id; $tradlink = 'index.php?tab=AdminTranslations&token='.Tools::getAdminTokenLite('AdminTranslations').'&type=modules&lang='; $toolbar = '
'.$this->l('Module').' '.$module->name.' '.$this->l('Back').' '.$this->l('Manage hooks').' '.$this->l('Manage translations:').' '; foreach (Language::getLanguages(false) AS $language) $toolbar .= ''.$language['iso_code'].''; $toolbar .= '
'; echo $toolbar.'
 
'.$echo.'
 
'.$toolbar; } elseif ($echo) $return = ($method == 'install' ? 12 : 13); elseif ($echo === false) $module_errors[] = $name; if ($key != 'configure' AND isset($_GET['bpay'])) Tools::redirectAdmin('index.php?tab=AdminPayment&token='.Tools::getAdminToken('AdminPayment'.(int)(Tab::getIdFromClassName('AdminPayment')).(int)($cookie->id_employee))); } if (sizeof($module_errors)) { $htmlError = ''; foreach ($module_errors AS $module_error) $htmlError .= '
  • '.$module_error.'
  • '; $htmlError .= ''; $this->_errors[] = Tools::displayError('The following module(s) were not installed successfully:'.$htmlError); } } if ($return) Tools::redirectAdmin($currentIndex.'&conf='.$return.'&token='.$this->token.'&tab_module='.$module->tab.'&module_name='.$module->name); } } function extractArchive($file) { global $currentIndex; $success = false; if (substr($file, -4) == '.zip') { if (!Tools::ZipExtract($file, _PS_MODULE_DIR_)) $this->_errors[] = Tools::displayError('Error while extracting module (file may be corrupted).'); } else { $archive = new Archive_Tar($file); if ($archive->extract(_PS_MODULE_DIR_)) $success = true; else $this->_errors[] = Tools::displayError('Error while extracting module (file may be corrupted).'); } @unlink($file); if ($success) Tools::redirectAdmin($currentIndex.'&conf=8'.'&token='.$this->token); } public function display() { if (!isset($_GET['configure']) AND !isset($_GET['delete']) OR sizeof($this->_errors) ) $this->displayList(); } public function displayJavascript() { global $currentIndex; echo ' '; } public static function sortModule($a, $b) { if (sizeof($a) == sizeof($b)) { return 0; } return (sizeof($a) < sizeof($b)) ? -1 : 1; } /** * Used for retreiving author name from submited field authorModules[name] * @param String $value value to be clean * * @return String cleant value: name */ private function _getSubmitedModuleAuthor($value) { $value = str_replace('authorModules[', '', $value); $value = str_replace("\'", "'", $value); $value = substr($value, 0, -1); return $value; } /** * Used for building option group * @param Array $authors contains modules authors * @param String $fieldName name of optiongroup * @return String built comp */ private function _buildModuleAuthorsOptGroup($authors, $fieldName = "UNDEFINED") { $out = ''; foreach($authors as $author_item => $status) { $author_item = Tools::htmlentitiesUTF8($author_item); $disp_author = $this->_getDispAuthor($author_item); $out .= ''; } $out .= ''; return $out; } /** * Used for truncating author name to display it nicely * @param String $author original author * @return String truncated author name */ private function _getDispAuthor($author) { return ((strlen($author) > self::$MAX_DISP_AUTHOR) ? substr($author, 0, self::$MAX_DISP_AUTHOR).'...' : $author); } public function displayList() { global $currentIndex, $cookie; $modulesAuthors = array(); $autocompleteList = 'var moduleList = ['; $showTypeModules = Configuration::get('PS_SHOW_TYPE_MODULES_'.(int)($cookie->id_employee)); $showInstalledModules = Configuration::get('PS_SHOW_INSTALLED_MODULES_'.(int)($cookie->id_employee)); $showEnabledModules = Configuration::get('PS_SHOW_ENABLED_MODULES_'.(int)($cookie->id_employee)); $showCountryModules = Configuration::get('PS_SHOW_COUNTRY_MODULES_'.(int)($cookie->id_employee)); $nameCountryDefault = Country::getNameById($cookie->id_lang, Configuration::get('PS_COUNTRY_DEFAULT')); $isoCountryDefault = Country::getIsoById(Configuration::get('PS_COUNTRY_DEFAULT')); $serialModules = ''; $modules = Module::getModulesOnDisk(true); foreach ($modules AS $module) { if (!in_array($module->name, $this->listNativeModules)) $serialModules .= $module->name.' '.$module->version.'-'.($module->active ? 'a' : 'i')."\n"; $moduleAuthor = $module->author; if (!empty($moduleAuthor)&& ($moduleAuthor != "")) $modulesAuthors[(string)$moduleAuthor] = true; } $serialModules = urlencode($serialModules); $filterName = Tools::getValue('filtername'); if (!empty($filterName)) { echo ' '; } //filter module list foreach($modules as $key => $module) { switch ($showTypeModules) { case 'nativeModules': if (!in_array($module->name, $this->listNativeModules)) unset($modules[$key]); break; case 'partnerModules': if (!in_array($module->name, $this->listPartnerModules)) unset($modules[$key]); break; case 'otherModules': if (in_array($module->name, $this->listPartnerModules) OR in_array($module->name, $this->listNativeModules)) unset($modules[$key]); break; default: if (strpos($showTypeModules, 'authorModules[') !== false) { $author_selected = $this->_getSubmitedModuleAuthor($showTypeModules); $modulesAuthors[$author_selected] = 'selected'; // setting selected author in authors set if (empty($module->author) || $module->author != $author_selected) unset($modules[$key]); } break; } switch ($showInstalledModules) { case 'installed': if (!$module->id) unset($modules[$key]); break; case 'unistalled': if ($module->id) unset($modules[$key]); break; } switch ($showEnabledModules) { case 'enabled': if (!$module->active) unset($modules[$key]); break; case 'disabled': if ($module->active) unset($modules[$key]); break; } if ($showCountryModules) if (isset($module->limited_countries) AND !empty($module->limited_countries) AND ((is_array($module->limited_countries) AND sizeof($module->limited_countries) AND !in_array(strtolower($isoCountryDefault), $module->limited_countries)) OR (!is_array($module->limited_countries) AND strtolower($isoCountryDefault) != strval($module->limited_countries)))) unset($modules[$key]); if (!empty($filterName)) if (stristr($module->name, $filterName) === false AND stristr($module->displayName, $filterName) === false AND stristr($module->description, $filterName) === false) unset($modules[$key]); } foreach($modules as $module) $autocompleteList .= Tools::jsonEncode(array( 'displayName' => (string)$module->displayName, 'desc' => (string)$module->description, 'name' => (string)$module->name, 'author' => (string)$module->author )).', '; $autocompleteList = rtrim($autocompleteList, ' ,').'];'; // Display CSS Fancy Box echo ''; echo ''; $this->displayJavascript(); echo ' '.$this->l('Add a new module').' '.$this->l('Add a module from my computer').'  | '; if (@fsockopen('www.prestashop.com', 80)) echo ' Add '.$this->l('Add a module from PrestaShop Addons').' '; echo '
     
    '.$this->l('Add a new module').' '.$this->l('Add a new module').'

    '.$this->l('The module must be either a zip file or a tarball.').'


    '.$this->l('Upload the module from your computer.').'

    '.$this->l('Download the module directly from a website.').'


    '; if (Configuration::get('PRESTASTORE_LIVE')) echo ' '; /* Scan modules directories and load modules classes */ $warnings = array(); $orderModule = array(); $irow = 0; foreach ($modules AS $module) $orderModule[(isset($module->tab) AND !empty($module->tab) AND array_key_exists(strval($module->tab), $this->listTabModules)) ? strval($module->tab) : 'others' ][] = $module; uasort($orderModule,array('AdminModules', 'sortModule')); $concatWarning = array(); foreach ($orderModule AS $tabModule) foreach ($tabModule AS $module) if ($module->active AND $module->warning) $warnings[] =''.$module->displayName.' - '.stripslashes(pSQL($module->warning)); $this->displayWarning($warnings); echo '
    '.$this->l('Open all tabs').'      
    '; echo $this->displaySelectedFilter(); if ($tab_module = Tools::getValue('tab_module')) if (array_key_exists($tab_module, $this->listTabModules)) $goto = $tab_module; else $goto = 'others'; else $goto = false; echo ' '; if (!empty($orderModule)) { /* Browse modules by tab type */ foreach ($orderModule AS $tab => $tabModule) { echo '
    '.sizeof($tabModule).' '.((sizeof($tabModule) > 1) ? $this->l('modules') : $this->l('module')).' '.$this->listTabModules[$tab].'
    '; } echo '

    '.$this->l('Icon legend').' :   '.$this->l('Module installed and enabled').'   '.$this->l('Module installed but disabled').'   '.$this->l('Module installed but with warnings').'   '.$this->l('Module not installed').'
     
    '; } else echo '
    '.$this->l('No module found').'
    '; } public function recursiveDeleteOnDisk($dir) { if (strpos(realpath($dir), realpath(_PS_MODULE_DIR_)) === false) return ; if (is_dir($dir)) { $objects = scandir($dir); foreach ($objects as $object) if ($object != "." && $object != "..") { if (filetype($dir."/".$object) == "dir") $this->recursiveDeleteOnDisk($dir."/".$object); else unlink($dir."/".$object); } reset($objects); rmdir($dir); } } public function displayOptions($module) { global $currentIndex; $return = ''; $href = $currentIndex.'&token='.$this->token.'&module_name='. urlencode($module->name).'&tab_module='.$module->tab; $hrefDelete = $currentIndex.'&deleteModule='.urlencode($module->name).'&token='.$this->token.'&tab_module='.$module->tab.'&module_name='.urlencode($module->name); $return .= ''.$this->l('Delete').'  '; if ((int)($module->id)) $return .= 'active && method_exists($module, 'onclickOption')? 'onclick="'.$module->onclickOption('desactive', $href).'"' : '').' href="'.$currentIndex.'&token='.$this->token.'&module_name='.urlencode($module->name).'&'.($module->active ? 'desactive' : 'active').'&tab_module='.$module->tab.'&module_name='.urlencode($module->name).'">'.($module->active ? $this->l('Disable') : $this->l('Enable')).'  '; if ((int)($module->id) AND $module->active) $return .= ''.$this->l('Reset').'  '; if ((int)($module->id) AND (method_exists($module, 'getContent') OR (isset($module->is_configurable) AND (int)$module->is_configurable))) $return .= ''.$this->l('Configure').'  '; return $return; } public function isFresh($timeout = 604800000) { if (file_exists($this->_moduleCacheFile)) return ((time() - filemtime($this->_moduleCacheFile)) < $timeout); else return false; } public function refresh() { return file_put_contents($this->_moduleCacheFile, Tools::file_get_contents('http://www.prestashop.com/xml/modules_list.xml')); } public function displaySelectedFilter() { global $cookie; $selected_filter = ''; $id_employee = (int)($cookie->id_employee); $showTypeModules = Configuration::get('PS_SHOW_TYPE_MODULES_'.(int)($cookie->id_employee)); $showInstalledModules = Configuration::get('PS_SHOW_INSTALLED_MODULES_'.(int)($cookie->id_employee)); $showEnabledModules = Configuration::get('PS_SHOW_ENABLED_MODULES_'.(int)($cookie->id_employee)); $showCountryModules = Configuration::get('PS_SHOW_COUNTRY_MODULES_'.(int)($cookie->id_employee)); $selected_filter .= ($showTypeModules == 'allModules' ? $this->l('All Modules').' - ' : ''). ($showTypeModules == 'nativeModules' ? $this->l('Native Modules').' - ' : ''). ($showTypeModules == 'partnerModules' ? $this->l('Partners Modules').' - ' : ''). ($showTypeModules == 'otherModules' ? $this->l('Others Modules').' - ' : ''). ($showInstalledModules == 'installedUninstalled' ? $this->l('Installed & Uninstalled').' - ' : ''). ($showInstalledModules == 'installed' ? $this->l('Installed Modules').' - ' : ''). ($showInstalledModules == 'unistalled' ? $this->l('Uninstalled Modules').' - ' : ''). ($showEnabledModules == 'enabledDisabled' ? $this->l('Enabled & Disabled').' - ' : ''). ($showEnabledModules == 'enabled' ? $this->l('Enabled Modules').' - ' : ''). ($showEnabledModules == 'disabled' ? $this->l('Disabled Modules').' - ' : ''). ($showCountryModules === 1 ? $this->l('Current country:').' '.$nameCountryDefault.' - ' : ''). ($showCountryModules === 0 ? $this->l('All countries').' - ' : ''); if (strlen($selected_filter) != 0) $selected_filter = '
    '.$this->l('Selected filters').' : '.rtrim($selected_filter, ' - ').'
    '; return $selected_filter; } private function setFilterModules($module_type, $country_module_value, $module_install, $module_status) { global $cookie; Configuration::updateValue('PS_SHOW_TYPE_MODULES_'.(int)($cookie->id_employee), $module_type); Configuration::updateValue('PS_SHOW_COUNTRY_MODULES_'.(int)($cookie->id_employee), $country_module_value); Configuration::updateValue('PS_SHOW_INSTALLED_MODULES_'.(int)($cookie->id_employee), $module_install); Configuration::updateValue('PS_SHOW_ENABLED_MODULES_'.(int)($cookie->id_employee), $module_status); } private function resetFilterModules() { global $cookie; Configuration::updateValue('PS_SHOW_TYPE_MODULES_'.(int)($cookie->id_employee), 'allModules'); Configuration::updateValue('PS_SHOW_COUNTRY_MODULES_'.(int)($cookie->id_employee), 0); Configuration::updateValue('PS_SHOW_INSTALLED_MODULES_'.(int)($cookie->id_employee), 'installedUninstalled'); Configuration::updateValue('PS_SHOW_ENABLED_MODULES_'.(int)($cookie->id_employee), 'enabledDisabled'); } }