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]);
}
}
}
}