source should already be set * */ public function Install(){ global $langmessage; $success = $this->InstallSteps(); if( !$this->remote_install && !is_dir($this->source) ){ $this->message($langmessage['OOPS'].' (Source not found)'); return false; } if( $success ){ $this->message( sprintf($langmessage['installed'], $this->display_name ) ); }else{ $this->Failed(); } $this->CleanInstallFolder(); return $success; } /** * Get and install addon from a remote source * @param string $type Type of addon (plugin or theme) * @param int $id Addon id * @param int $order Purchase order id * */ public function InstallRemote( $type, $id, $order = null ){ global $langmessage; // check values if( empty($type) ){ $this->message($langmessage['OOPS'].' - Invalid Request (type)'); return false; } if( empty($id) || !ctype_digit($id) ){ $this->message($langmessage['OOPS'].' - Invalid Request (id)'); return false; } $this->remote_install = true; $this->type = $type; $this->id = (int)$id; if( !is_null($order) ){ $this->order = (int)$order; } return $this->Install(); } public function OutputMessages(){ foreach($this->messages as $msg){ msg($msg); } } /** * Remove an addon from the site configuration * Delete code folders if needed * */ public function Uninstall( $addon ){ global $config, $langmessage, $gp_titles, $gp_menu, $gp_index; $this->GetAddonData(); $addon_config = \gp\tool\Plugins::GetAddonConfig($addon); if( !$addon_config ){ $this->message($langmessage['OOPS'].' (Already uninstalled)'); return; } unset($config['addons'][$addon]); //remove links $installedGadgets = $this->GetInstalledComponents($config['gadgets'],$addon); $this->RemoveFromHandlers($installedGadgets); //remove from gp_index, gp_menu $installedLinks = $this->GetInstalledComponents($gp_titles,$addon); foreach($installedLinks as $index){ if( isset($gp_menu[$index]) ){ unset($gp_menu[$index]); } $title = \gp\tool::IndexToTitle($index); if( $title ){ unset($gp_index[$title]); } } $this->RemoveFromConfig($config['gadgets'],$addon); $this->RemoveFromConfig($config['admin_links'],$addon); $this->RemoveFromConfig($gp_titles,$addon); $this->CleanHooks($addon); if( !\gp\admin\Tools::SaveAllConfig() ){ $this->message($langmessage['OOPS']); return false; } $this->RemoveFolders($addon_config); //Record the history $this->addonHistory[] = $this->UninstallHistory($addon_config); $this->SaveAddonData(); if( $addon_config['order'] ){ $img_path = \gp\tool::IdUrl('ci'); \gp\tool::IdReq($img_path); } $this->message($langmessage['SAVED']); return true; } /** * Delete the code & data folders for an addon * @param array $addon_config */ private function RemoveFolders($addon_config){ if( !$this->rm_folders ){ return; } //only delete code if remote installation if( isset($addon_config['remote_install']) && $addon_config['remote_install'] ){ $installFolder = $addon_config['code_folder_full']; if( file_exists($installFolder) ){ \gp\tool\Files::RmAll($installFolder); } } //only delete data if data_folder is not empty if( !empty($addon_config['data_folder']) ){ $dataFolder = $addon_config['data_folder_full']; if( file_exists($dataFolder) ){ \gp\tool\Files::RmAll($dataFolder); } } } /** * Prepare a history record for the addon history * @param array $addon_config */ public function UninstallHistory($addon_config){ $history = array(); $history['name'] = $addon_config['name']; $history['action'] = 'uninstalled'; $history['time'] = time(); if( isset($addon_config['id']) ){ $history['id'] = $addon_config['id']; } return $history; } /** * Run through the installation process * */ public function InstallSteps(){ global $dataDir, $langmessage; $this->GetAddonData(); // addonHistory $this->Init_PT(); // $this->config //get from remote if( $this->remote_install && !$this->GetRemote() ){ return false; } //check ini contents if( !$this->CheckIni() ){ return false; } $this->SetDestination(); $this->DataFolder(); $this->IniContents(); if( !$this->PrepConfig() ){ return false; } if( !$this->CheckFile() ){ return false; } //hooks if( !$this->Hooks() ){ return false; } //layout if( !$this->Layout() ){ return false; } //move new addon folder into place if( !$this->FinalizeFolder() ){ return false; } if( !$this->FinalizeConfig() ){ return false; } // Save if( !\gp\admin\Tools::SaveAllConfig() ){ $this->message($langmessage['OOPS'].' (Configuration not saved)'); return false; } if( !is_null($this->order) ){ $img_path = \gp\tool::IdUrl('ci'); \gp\tool::IdReq($img_path); } $this->UpdateHistory(); return true; } /** * Prepare $this->config and make sure $this->addon_folder exists * */ public function Init_PT(){ global $config, $dataDir, $gpLayouts; if( !isset($config[$this->config_index]) ){ $config[$this->config_index] = array(); } $this->config =& $config[$this->config_index]; $this->config_cache = $config; $this->layouts_cache = $gpLayouts; if( !$this->addon_folder_rel ){ if( $this->remote_install ){ $this->addon_folder_rel = '/data/'.$this->code_folder_name; }else{ $this->addon_folder_rel = '/'.basename( dirname($this->source) ); } } $this->addon_folder = $dataDir.$this->addon_folder_rel; \gp\tool\Files::CheckDir($this->addon_folder); } /** * Check the Ini contents * */ protected function CheckIni(){ $this->display_name = basename($this->source); if( !$this->GetINI($this->source,$error) ){ //local themes don't need addon.ini files if( empty($this->new_layout) ){ $this->message( $error ); return false; } } return true; } /** * Set the install destination * */ protected function SetDestination(){ $this->config_key = \gp\admin\Addon\Tools::UpgradePath($this->ini_contents,$this->config_index); $this->upgrade_key = $this->config_key; if( $this->remote_install ){ if( $this->config_key ){ $this->dest = $this->addon_folder.'/'.$this->config_key; }else{ $this->dest = $this->TempFile(); } }else{ $this->dest = $this->source; } $this->dest_name = basename($this->dest); if( !$this->config_key ){ $this->config_key = $this->dest_name; } } /** * The data folder will not always be the same as the addon folder * */ protected function DataFolder(){ global $dataDir; if( !empty($this->config[$this->config_key]['data_folder']) ){ $this->data_folder = $this->config[$this->config_key]['data_folder']; }elseif( !empty($this->upgrade_key) && file_exists( $dataDir.'/data/_addondata/'.$this->upgrade_key) ){ $this->data_folder = $this->upgrade_key; }else{ $this->data_folder = $this->dest_name; } } /** * Prepare the configuration array for installation * */ public function PrepConfig(){ if( !$this->has_hooks ){ return true; } //make sure we have an array if( !isset($this->config[$this->config_key]) ){ $this->config[$this->config_key] = array(); }elseif( !is_array($this->config[$this->config_key]) ){ $this->message('$this->config[addon] is not an array'); return false; } return true; } /** * Get the Ini contents and check values * @return bool * */ public function GetINI($ini_dir,&$error){ global $langmessage; $error = false; $ini_file = $ini_dir.'/Addon.ini'; if( !file_exists($ini_file) ){ $error = sprintf($langmessage['File_Not_Found'],' '.$ini_file.''); return false; } $this->ini_text = file_get_contents($ini_file); $this->ini_contents = \gp\tool\Ini::ParseString($this->ini_text); $this->ini_contents['source_folder'] = dirname($ini_file); if( !$this->ini_contents ){ $error = $langmessage['Ini_Error'].' '.$langmessage['Ini_Submit_Bug']; $error = preg_replace('#href="[^"]+"#','href="'.CMS_DOMAIN.'/Docs/Addon.ini"',$error); return false; } $this->HasHooks(); if( !isset($this->ini_contents['Addon_Name']) ){ $error = $langmessage['Ini_No_Name'].' '.$langmessage['Ini_Submit_Bug']; return false; } if( isset($this->ini_contents['Addon_Unique_ID']) && !is_numeric($this->ini_contents['Addon_Unique_ID']) ){ $error = 'Invalid Unique ID'; return false; } // Check Versions if( !empty($this->ini_contents['min_gpeasy_version']) && version_compare($this->ini_contents['min_gpeasy_version'], gpversion,'>') ){ $error = sprintf($langmessage['min_version'],$this->ini_contents['min_gpeasy_version']).' '.$langmessage['min_version_upgrade']; return false; } $this->display_name = $this->ini_contents['Addon_Name']; return true; } /** * Does it have addon hooks? * */ public function HasHooks(){ foreach($this->ini_contents as $key => $value){ if( is_array($value) ){ $this->has_hooks = true; return; } } } /** * Parse the ini a second time with variables * */ public function IniContents(){ global $dataDir, $dirPrefix; $folder = basename($this->dest); $variables = array( '{$addon}' => $folder, '{$plugin}' => $folder, '{$dataDir}' => $dataDir, '{$dirPrefix}' => $dirPrefix, '{$addonRelativeData}' => \gp\tool::GetDir('/data/_addondata/'.$this->data_folder), '{$addonRelativeCode}' => \gp\tool::GetDir($this->addon_folder_rel.'/'.$folder), ); $this->ini_contents = \gp\tool\Ini::ParseString($this->ini_text,$variables); } /** * Add hooks to configuration * */ public function Hooks(){ global $langmessage, $config; if( !$this->has_hooks ){ return true; } //needs to be before other gadget functions $installedGadgets = $this->GetInstalledComponents($config['gadgets'],$this->config_key); $gadgets = $this->ExtractFromInstall($this->ini_contents,'Gadget:'); $gadgets = $this->CleanGadgets($gadgets); $this->PurgeExisting($config['gadgets'],$gadgets); $this->AddToConfig($config['gadgets'],$gadgets); //remove gadgets that were installed but are no longer part of package $gadgetNames = array_keys($gadgets); $toRemove = array_diff($installedGadgets,$gadgetNames); $this->RemoveFromHandlers($toRemove); //add new gadgets to GetAllGadgets handler $toAdd = array_diff($gadgetNames,$installedGadgets); $this->AddToHandlers($toAdd); //admin links $Admin_Links = $this->ExtractFromInstall($this->ini_contents,'Admin_Link:'); $Admin_Links = $this->CleanLinks($Admin_Links,'Admin_'); $this->PurgeExisting($config['admin_links'],$Admin_Links); $this->AddToConfig($config['admin_links'],$Admin_Links); //special links $Special_Links = $this->ExtractFromInstall($this->ini_contents,'Special_Link:'); $Special_Links = $this->CleanLinks($Special_Links,'Special_','special'); $this->AddToConfig_Special($Special_Links); //generic hooks $this->AddHooks(); return true; } /** * Create a layout * */ public function Layout(){ global $gpLayouts, $langmessage, $config, $page; if( empty($this->new_layout) ){ return true; } if( $this->has_hooks ){ $this->new_layout['addon_key'] = $this->config_key; } if( isset($this->ini_contents['Addon_Unique_ID']) && is_numeric($this->ini_contents['Addon_Unique_ID']) ){ $this->new_layout['addon_id'] = $this->ini_contents['Addon_Unique_ID']; } if( isset($this->ini_contents['Addon_Version']) ){ $this->new_layout['version'] = $this->ini_contents['Addon_Version']; } if( isset($this->ini_contents['Addon_Name']) ){ $this->new_layout['name'] = $this->ini_contents['Addon_Name']; } $temp = $this->TempFile(); $layout_id = basename($temp); $gpLayouts[$layout_id] = $this->new_layout; if( $this->default_layout ){ $config['gpLayout'] = $layout_id; } return true; } /** * Rename the temp folder to the dest folder * */ public function FinalizeFolder(){ if( !$this->remote_install ){ return true; } if( file_exists($this->dest) ){ $this->trash_path = $this->TempFile(); if( !@rename($this->dest,$this->trash_path) ){ $this->message('Existing destination not renamed'); return false; } } //rename temp folder if( rename($this->source,$this->dest) ){ return true; } $this->message('Couldn\'t rename to destination'); return false; } /** * Finalize the configuration * * */ public function FinalizeConfig(){ global $langmessage, $config; if( !$this->has_hooks ){ return true; } //code folder $this->config[$this->config_key]['code_folder_part'] = $this->addon_folder_rel.'/'.$this->dest_name; $this->config[$this->config_key]['data_folder'] = $this->data_folder; //general configuration $this->UpdateConfigInfo('Addon_Name','name'); $this->UpdateConfigInfo('Addon_Version','version'); $this->UpdateConfigInfo('Addon_Unique_ID','id'); $this->UpdateConfigInfo('Namespace','Namespace'); //remote unset($this->config[$this->config_key]['remote_install']); if( $this->remote_install ){ $this->config[$this->config_key]['remote_install'] = true; } //layout if( count($this->new_layout) ){ $this->config[$this->config_key]['is_theme'] = true; } //proof of purchase if( isset($this->ini_contents['Proof of Purchase']) && isset($this->ini_contents['Proof of Purchase']['order']) ){ $this->order = $this->ini_contents['Proof of Purchase']['order']; $this->config[$this->config_key]['order'] = $this->order; } $this->UpdateConfigInfo('editable_text','editable_text'); $this->UpdateConfigInfo('About','About'); $this->UpdateConfigInfo('html_head','html_head'); return true; } /** * * */ public function UpdateHistory(){ if( !$this->has_hooks ){ return; } // History $history = array(); $history['name'] = $this->config[$this->config_key]['name']; $history['action'] = 'installed'; if( isset($this->config[$this->config_key]['id']) ){ $history['id'] = $this->config[$this->config_key]['id']; } $history['time'] = time(); $this->addonHistory[] = $history; $this->SaveAddonData(); } /** * Run the Install_Check.php file if it exists * @return bool * */ public function CheckFile(){ $check_file = $this->source.'/Install_Check.php'; if( !file_exists($check_file) ){ return true; } $success = true; ob_start(); include($check_file); if( function_exists('Install_Check') ){ $success = Install_Check(); } $msg = ob_get_clean(); if( !empty($msg) ){ $this->message($msg); } return $success; } /** * Return the path of a non-existant file * Make sure the name won't conflict with names of addons or layouts * */ public function TempFile(){ global $config, $gpLayouts, $dataDir; do{ $file = \gp\tool::RandomString(7,false); $full_dest = $this->addon_folder.'/'.$file; $data_dest = $dataDir.'/data/_addondata/'.$file; }while( is_numeric($file) || array_key_exists($file, $config['addons']) || array_key_exists($file, $config['themes']) || array_key_exists($file, $gpLayouts) || file_exists($full_dest) || file_exists($data_dest) ); return $full_dest; } /** * Recursive copy folder * */ public function CopyAddonDir($fromDir,$toDir){ if( !\gp\tool\Files::CheckDir($toDir) ){ return 'Copy failed: '.$fromDir.' to '.$toDir; } $files = scandir($fromDir); if( $files === false ){ return 'scandir failed: '.$fromDir; } foreach($files as $file){ if( strpos($file,'.') === 0){ continue; } $fullFrom = $fromDir.'/'.$file; $fullTo = $toDir.'/'.$file; //directories if( is_dir($fullFrom) ){ $result = self::CopyAddonDir($fullFrom,$fullTo); if( $result !== true ){ return $result; } continue; } //files //If the destination file already exists, it will be overwritten. if( !copy($fullFrom,$fullTo) ){ return 'Copy failed: '.$fullFrom.' to '.$fullTo.' (2)'; } } return true; } /** * Undo changes * */ public function Failed(){ global $config, $gpLayouts; if( is_array($this->config_cache) ){ $config = $this->config_cache; $gpLayouts = $this->layouts_cache; } if( isset($this->trash_path) && file_exists($this->trash_path) ){ @rename($this->trash_path,$this->dest); } } public function message($message){ $this->messages[] = $message; } /** * Get a stored order/purchase id * @param int addon id * */ public function GetOrder($id){ if( !is_numeric($id) ){ return; } foreach( $this->config as $folder => $info ){ if( !empty($info['id']) && $id == $info['id'] && !empty($info['order']) ){ return $info['order']; } } } /** * Get the remote package * */ public function GetRemote(){ global $langmessage, $dataDir; // download url $download_url = \gp\admin\Tools::RemoteUrl( $this->type ); // allowed to remote install? if( $download_url === false ){ $this->message($langmessage['OOPS'].' (Can\'t remote install '.$this->type.')'); return false; } $download_url .= '?cmd=install&id='.rawurlencode($this->id); // purchase order id if( is_null($this->order) ){ $this->order = $this->GetOrder($this->id); } if( !is_null($this->order) ){ $download_url .= '&order='.rawurlencode($this->order); } // able to remote install? if( !\gp\admin\Tools::CanRemoteInstall() ){ $this->message($langmessage['OOPS'].' (Can\'t remote install)'); return false; } // get package from remote $getter = new \gp\tool\RemoteGet(); $full_result = $getter->Get($download_url); if( (int)$full_result['response']['code'] < 200 && (int)$full_result['response']['code'] >= 300 ){ $this->message( $langmessage['download_failed'] .' (1)'); return false; } // download failed and a message was sent if( isset($full_result['headers']['x-error']) ){ $this->message( htmlspecialchars($full_result['headers']['x-error']) ); $this->message( sprintf($langmessage['download_failed_xerror'],'href="'.self::DetailUrl($_POST['type'],$_POST['id']).'" data-cmd="remote"') ); return false; } $result = $full_result['body']; $md5 =& $full_result['headers']['x-md5']; $package_md5 = md5($result); //check md5 if( $package_md5 != $md5 ){ $this->message( $langmessage['download_failed_md5'].'
(Package Checksum '.$package_md5.' != Expected Checksum '.$md5.')' ); return false; } //save contents $tempfile = $dataDir.\gp\tool\FileSystem::TempFile('/data/_temp/addon','.zip'); if( !\gp\tool\Files::Save($tempfile,$result) ){ $this->message( $langmessage['download_failed'].' (Package not saved)' ); return false; } $this->source = $this->TempFile(); $success = $this->ExtractArchive($tempfile); unlink($tempfile); return $success; } /** * Write Archive * */ private function ExtractArchive($archive_path){ global $langmessage, $dataDir; $archive = new \gp\tool\Archive($archive_path); $extract_temp = $dataDir.\gp\tool\FileSystem::TempFile('/data/_temp/addon'); if( !$archive->extractTo($extract_temp) ){ $this->message( $langmessage['download_failed'].' (Package not extracted)' ); return false; } //get archive root $archive_root = $archive->GetRoot(); if( is_null($archive_root) ){ $this->message( $langmessage['download_failed'].' (Root not found)' ); return false; } //rename to source folder $rename_from = $extract_temp.'/'.ltrim($archive_root,'/'); if( !\gp\tool\Files::Replace($rename_from, $this->source) ){ $this->message( $langmessage['download_failed'].' (Not replaced)' ); return false; } return true; } /** * Set config value based on ini setting * */ public function UpdateConfigInfo($ini_var,$config_var){ if( isset($this->ini_contents[$ini_var]) ){ $this->config[$this->config_key][$config_var] = $this->ini_contents[$ini_var]; }elseif( isset($this->config[$this->config_key][$config_var]) ){ unset($this->config[$this->config_key][$config_var]); } } /** * Add an addon's special links to the configuration * */ public function AddToConfig_Special($Special_Links){ global $gp_index, $gp_titles, $gp_menu, $langmessage; $lower_links = array_change_key_case($Special_Links,CASE_LOWER); //purge links no longer defined ... similar to PurgeExisting() foreach($gp_index as $linkName => $index){ $linkInfo = $gp_titles[$index]; if( !isset($linkInfo['addon']) ){ continue; } if( $linkInfo['addon'] !== $this->config_key ){ continue; } if( isset($lower_links[$index]) ){ continue; } unset($gp_index[$linkName]); unset($gp_titles[$index]); if( isset($gp_menu[$index]) ){ unset($gp_menu[$index]); } } //prepare a list with all titles converted to lower case $lower_titles = array_keys($gp_index); $lower_titles = array_combine($lower_titles, $lower_titles); $lower_titles = array_change_key_case($lower_titles, CASE_LOWER); //add new links ... similar to AddToConfig() foreach($Special_Links as $new_title => $linkInfo){ $index = strtolower($new_title); $title = \gp\tool::IndexToTitle($index); //if the title already exists, see if we need to update it if( $title ){ $add_link = $this->CanAddLink( $gp_titles[$index] ); if( !$add_link ){ $this->message( sprintf($langmessage['addon_key_defined'],' Special_Link: '.$new_title.'') ); continue; } //this will overwrite things like label which are at times editable by users //$AddTo[$new_title] = $linkInfo + $AddTo[$new_title]; // if it doesn't exist, just add it }else{ // we don't need the Special_ prefix, but we don't want duplicates $temp = $new_title = substr($new_title,8); $temp_lower = $new_lower = strtolower($new_title); $i = 1; while( isset($lower_titles[$new_lower]) ){ $new_lower = $temp_lower.'_'.$i; $new_title = $temp.'_'.$i; $i++; } $gp_index[$new_title] = $index; $gp_titles[$index] = $linkInfo; } $this->UpdateLinkInfo($gp_titles[$index],$linkInfo); } } public function AddHooks(){ $installed = array(); foreach($this->ini_contents as $hook => $hook_args){ if( !is_array($hook_args) ){ continue; } if( strpos($hook,'Gadget:') === 0 || strpos($hook,'Admin_Link:') === 0 || strpos($hook,'Special_Link:') === 0 ){ continue; } if( $this->AddHook($hook,$hook_args) ){ $installed[$hook] = $hook; } } $this->CleanHooks($this->config_key,$installed); } public function AddHook($hook,$hook_args){ global $config; $add = array(); $this->UpdateLinkInfo($add,$hook_args); $config['hooks'][$hook][$this->config_key] = $add; return true; } //extract the configuration type (extractArg) from $Install public function ExtractFromInstall(&$Install,$extractArg){ if( !is_array($Install) || (count($Install) <= 0) ){ return array(); } $extracted = array(); $removeLength = strlen($extractArg); foreach($Install as $InstallArg => $ArgInfo){ if( strpos($InstallArg,$extractArg) !== 0 ){ continue; } $extractName = substr($InstallArg,$removeLength); if( !$this->CheckName($extractName) ){ continue; } $extracted[$extractName] = $ArgInfo; } return $extracted; } /* * Add to $AddTo * Don't add elements already defined by the cms or other addons * */ public function AddToConfig(&$AddTo,$New_Config){ global $langmessage; if( !is_array($New_Config) || (count($New_Config) <= 0) ){ return; } $lower_add_to = array_change_key_case($AddTo,CASE_LOWER); foreach($New_Config as $Config_Key => $linkInfo){ $lower_key = strtolower($Config_Key); if( isset($lower_add_to[$lower_key]) ){ $add_link = $this->CanAddLink( $lower_add_to[$lower_key] ); if( !$add_link ){ $this->message( sprintf($langmessage['addon_key_defined'],' '.$Config_Key.'') ); continue; } //this will overwrite things like label which are at times editable by users //$AddTo[$Config_Key] = $linkInfo + $AddTo[$Config_Key]; }else{ $AddTo[$Config_Key] = $linkInfo; } $this->UpdateLinkInfo($AddTo[$Config_Key],$linkInfo); } } public function CanAddLink( $info ){ if( !isset($info['addon']) || $this->config_key === false ){ return false; } if( $info['addon'] != $this->config_key ){ return false; } return true; } public function UpdateLinkInfo(&$link_array,$new_info){ unset($link_array['script'], $link_array['data'], $link_array['class'], $link_array['method'], $link_array['value'], $link_array['class_admin']); $new_info += array('script'=>'','data'=>'','class'=>'','method'=>'','value'=>'','class_admin'=>''); $link_array['addon'] = $this->config_key; $link_array['class'] = $new_info['class']; $link_array['value'] = $new_info['value']; $link_array['class_admin'] = $new_info['class_admin']; $link_array = array_filter($link_array); //remove empty values if( !empty($new_info['script']) ){ $link_array['script'] = $this->addon_folder_rel.'/'.$this->dest_name .'/'.$new_info['script']; } if( !empty($new_info['data']) ){ $link_array['data'] = '/data/_addondata/'.$this->data_folder.'/'.$new_info['data']; } if( !empty($new_info['method']) ){ $link_array['method'] = $new_info['method']; if( strpos($link_array['method'],'::') > 0 ){ $link_array['method'] = explode('::',$link_array['method']); } } } /** * Purge Links from $purgeFrom that were once defined for $this->config_key * */ public function PurgeExisting(&$purgeFrom,$NewLinks){ if( $this->config_key === false || !is_array($purgeFrom) ){ return; } foreach($purgeFrom as $linkName => $linkInfo){ if( !isset($linkInfo['addon']) ){ continue; } if( $linkInfo['addon'] !== $this->config_key ){ continue; } if( isset($NewLinks[$linkName]) ){ continue; } unset($purgeFrom[$linkName]); } } /** * Make sure the extracted links are valid * */ public function CleanLinks($links,$prefix,$linkType=null){ if( !is_array($links) ){ return array(); } $result = array(); foreach($links as $linkName => $linkInfo){ if( !$this->ValidInfo($linkInfo) ){ continue; } if( stripos($linkName,$prefix) !== 0 ){ $linkName = $prefix.$linkName; } $result[$linkName] = $linkInfo; if( is_string($linkType) ){ $result[$linkName]['type'] = $linkType; } } return $result; } /** * similar to CleanLinks() * */ public function CleanGadgets($gadgets){ global $gpOutConf, $langmessage, $config; if( !is_array($gadgets) ){ return array(); } $result = array(); foreach($gadgets as $gadgetName => $gadgetInfo){ //check against $gpOutConf if( isset($gpOutConf[$gadgetName]) ){ $this->message( sprintf($langmessage['addon_key_defined'],' Gadget: '.$gadgetName.'') ); continue; } //check against other gadgets if( isset($config['gadgets'][$gadgetName]) && ($config['gadgets'][$gadgetName]['addon'] !== $this->config_key) ){ $this->message( sprintf($langmessage['addon_key_defined'],' Gadget: '.$gadgetName.'') ); continue; } if( !$this->ValidInfo($gadgetInfo, false) ){ continue; } $result[$gadgetName] = $gadgetInfo; } return $result; } /** * Check the info to make sure it has a label and some way of executing code * */ public function ValidInfo($info, $require_label = true ){ if( $require_label && empty($info['label']) ){ return false; } $keys = array('class','class_admin','data','method','script'); foreach($keys as $key){ if( !empty($info[$key]) ){ return true; } } return false; } /** * Add gadgets to gpLayouts * */ public function AddToHandlers($gadgets){ global $gpLayouts; if( !is_array($gpLayouts) || !is_array($gadgets) ){ return; } foreach($gpLayouts as $layout => $containers){ if( !is_array($containers) ){ continue; } if( isset($containers['handlers']['GetAllGadgets']) ){ $container =& $gpLayouts[$layout]['handlers']['GetAllGadgets']; if( !is_array($container) ){ $container = array(); } $container = array_merge($container,$gadgets); } } } public function CheckName($name){ $test = str_replace(array('.','_',' '),array(''),$name ); if( empty($test) || !ctype_alnum($test) ){ $this->message( 'Could not install '.$name.'. Link and gadget names can only contain alphanumeric characters with underscore "_", dot "." and space " " characters.'); return false; } return true; } /** * Remove unused code folders created by incomplete addon installations * */ public function CleanInstallFolder(){ if( !$this->remote_install ){ return; } if( file_exists($this->source) ){ \gp\tool\Files::RmAll($this->source); } if( file_exists($this->trash_path) ){ \gp\tool\Files::RmAll($this->trash_path); } } public function RemoveFromConfig(&$configFrom,$addon){ if( !is_array($configFrom) ){ return; } foreach($configFrom as $key => $value ){ if( !isset($value['addon']) ){ continue; } if( $value['addon'] == $addon ){ unset($configFrom[$key]); } } } }