/Addon.ini * - Addon_Name (required) * - link definitions: (optional) * - should be able to have multiple links, * * * - link_name (required) * an example link: Admin_ * - labels (required) should pull the language values during installation/upgrading * - script (required) * - class / function to call once opened (optional) * * - minimum version / max version * /addons// */ class Addons extends \gp\admin\Addon\Install{ public $dataFile; public function __construct( $args ){ global $langmessage; parent::__construct($args); $this->InitRating(); $this->GetData(); $this->avail_addons = $this->GetAvailAddons(); } public function RunScript(){ $cmd = \gp\tool::GetCommand(); switch($cmd){ case 'LocalInstall': $this->LocalInstall(); break; case 'remote_install': case 'RemoteInstall': $this->RemoteInstall(); return; case 'RemoteInstallConfirmed': $this->RemoteInstallConfirmed(); break; case 'SendAddonReview': case 'ReviewAddonForm': $this->AdminAddonRating(); if( $this->ShowRatingText ){ return; } break; case 'enable': case 'disable': $this->GadgetVisibility($cmd); return; case 'uninstall': $this->Uninstall(); return; case 'confirm_uninstall': $this->Confirm_Uninstall(); break; } //single addon $request_parts = explode('/',$this->page->requested); if( count($request_parts) > 2 ){ $this->ShowAddon($request_parts[2]); return; } $this->Select(); $this->CleanAddonFolder(); } /** * Remove unused code folders created by incomplete addon installations * */ public function CleanAddonFolder(){ global $config; //get a list of all folders $folder = '/data/_addoncode'; $code_folders = $this->GetCleanFolders($folder); $folder = '/data/_addondata'; $data_folders = $this->GetCleanFolders($folder); //check against folders used by addons $addons = $config['addons']; foreach($addons as $addon_key => $info){ $addon_config = \gp\tool\Plugins::GetAddonConfig($addon_key); if( array_key_exists($addon_config['code_folder_part'],$code_folders) ){ $code_folders[$addon_config['code_folder_part']] = false; } if( array_key_exists($addon_config['data_folder_part'],$data_folders) ){ $data_folders[$addon_config['data_folder_part']] = false; } } //remove unused folders $folders = array_filter($code_folders) + array_filter($data_folders); foreach($folders as $folder => $full_path){ \gp\tool\Files::RmAll($full_path); } } /** * Get a list of folders within $dir that * */ public function GetCleanFolders($relative){ global $dataDir; $dir = $dataDir.$relative; $folders = array(); if( file_exists($dir) ){ $files = scandir($dir); foreach($files as $file){ if( $file == '.' || $file == '..' ){ continue; } $full_path = $dir.'/'.$file; if( !is_dir($full_path) ){ continue; } $mtime = filemtime($full_path); $diff = time() - $mtime; if( $diff < 3600 ){ continue; } $folders[$relative.'/'.$file] = $full_path; } } return $folders; } public function GadgetVisibility($cmd){ global $config, $langmessage; $this->page->ajaxReplace = array(); $gadget = $_GET['gadget']; if( !isset($config['gadgets']) || !is_array($config['gadgets']) || !isset($config['gadgets'][$gadget]) ){ msg($langmessage['OOPS'].' (Invalid Gadget)'); return; } $gadgetInfo =& $config['gadgets'][$gadget]; switch($cmd){ case 'enable': unset($gadgetInfo['disabled']); break; case 'disable': $gadgetInfo['disabled'] = true; break; } if( !\gp\admin\Tools::SaveConfig(true) ){ return; } $link = $this->GadgetLink($gadget); $this->page->ajaxReplace[] = array('replace','.gadget_link_'.md5($gadget),$link); } public function GadgetLink($name){ global $config, $langmessage; $info =& $config['gadgets'][$name]; if( !$info ){ return ''; } if( isset($info['disabled']) ){ return \gp\tool::Link('Admin/Addons',str_replace('_',' ',$name).' ('.$langmessage['disabled'].')','cmd=enable&addon='.rawurlencode($info['addon']).'&gadget='.rawurlencode($name),'data-cmd="gpajax" class="gadget_link_'.md5($name).'"'); }else{ return \gp\tool::Link('Admin/Addons',str_replace('_',' ',$name) .' ('.$langmessage['enabled'].')','cmd=disable&addon='.rawurlencode($info['addon']).'&gadget='.rawurlencode($name),'data-cmd="gpajax" class="gadget_link_'.md5($name).'"'); } } /** * Addon Data * */ public function GetData(){ global $dataDir,$config; //new if( !isset($config['addons']) ){ $config['addons'] = array(); } if( !isset($config['admin_links']) ){ $config['admin_links'] = array(); } if( !isset($config['gadgets']) ){ $config['gadgets'] = array(); } //fix data $firstValue = current($config['addons']); if( is_string($firstValue) ){ foreach($config['addons'] as $addon => $addonName){ $config['addons'][$addon] = array(); $config['addons'][$addon]['name'] = $addonName; } } } /** * Prompt User about uninstalling an addon */ public function Uninstall(){ global $config,$langmessage; echo '
'; echo '

'.$langmessage['uninstall'].'

'; echo '
'; $addon =& $_REQUEST['addon']; if( !isset($config['addons'][$addon]) ){ echo $langmessage['OOPS']; echo '

'; echo ' '; echo '

'; }else{ echo $langmessage['confirm_uninstall']; echo '

'; echo ''; echo ''; echo ' '; echo ' '; echo '

'; } echo '
'; echo '
'; } public function Confirm_Uninstall(){ $addon =& $_POST['addon']; $installer = new \gp\admin\Addon\Installer(); $installer->Uninstall($addon); $installer->OutputMessages(); } /** * Display addon details * */ public function ShowAddon($encoded_key){ global $config, $langmessage; $addon_key = \gp\admin\Tools::decode64($encoded_key); if( !isset($config['addons'][$addon_key]) ){ msg($langmessage['OOPS'].'(Addon Not Found)'); $this->Select(); return; } $show = $this->GetDisplayInfo(); $info = $show[$addon_key]; $this->ShowHeader($info['name']); $this->UpgradeLinks($info); //about if( !empty($info['About']) ){ echo '
'; echo '
'; echo $info['About']; echo '
'; echo '

'; } echo '
'; $format = array(); $format['end'] = '
'; $format['start'] = '

%s

'; $this->AddonPanel_Special($addon_key,$format); $this->AddonPanel_Admin($addon_key,$format); $this->AddonPanel_Gadget($addon_key,$format); $this->AddonPanel_Hooks($addon_key, $format); $this->OptionLinks($addon_key, $info, $format); echo '
'; } /** * Get a list of available addons * */ public function GetAvailAddons(){ global $dataDir; $addonPath = $dataDir.'/addons'; if( !file_exists($addonPath) ){ msg('Warning: The /addons folder "'.$addonPath.'" does not exist on your server.'); return array(); } $folders = \gp\tool\Files::ReadDir($addonPath,1); $versions = array(); $avail = array(); foreach($folders as $value){ $fullPath = $addonPath .'/'.$value; $info = $this->GetAvailInstall($fullPath); if( !$info ){ continue; } $info['source_folder'] = $addonPath .'/'. $value; $info['upgrade_key'] = \gp\admin\Addon\Tools::UpgradePath($info); $avail[$value] = $info; if( isset($info['Addon_Version']) && isset($info['Addon_Unique_ID']) ){ $id = $info['Addon_Unique_ID']; if( !isset($versions[$id]) ){ $versions[$id] = $info['Addon_Version']; }elseif( version_compare($versions[$id],$info['Addon_Version'],'<') ){ $versions[$id] = $info['Addon_Version']; continue; } } } if( gp_unique_addons ){ $avail = self::FilterUnique($avail, $versions); } return $avail; } /** * Filter the list of addons so we only have a list of the most recent versions * */ protected static function FilterUnique($addons, $versions){ $temp = array(); foreach($addons as $key => $info){ if( !isset($info['Addon_Version']) || !isset($info['Addon_Unique_ID']) ){ $temp[$key] = $info; continue; } $id = $info['Addon_Unique_ID']; $version = $info['Addon_Version']; if( version_compare($versions[$id], $version,'>') ){ continue; } $temp[$key] = $info; } return $temp; } public function Instructions(){ echo '
'; echo 'Plugin Documentation'; } /** * Show installed and locally available plugins * */ public function Select(){ $this->ShowHeader(); $this->ShowInstalled(); $this->Instructions(); } /** * Show installed addons * */ public function ShowInstalled(){ $show = $this->GetDisplayInfo(); echo '
'; // sort installed addons by name $names = []; foreach($show as $key => $row){ $names[$key] = $row['name'] ?? null; } $names = array_column($show, 'name'); // array_multisort($names, SORT_ASC, $show); ::: // ExecInfo() Fatal Error: Array sizes are inconsistent foreach($show as $addon_key => $info){ $this->PluginPanelGroup($addon_key,$info); } echo '
'; return true; } /** * Get addon configuration along with upgrade info * */ public function GetDisplayInfo(){ global $config; //show installed addons $show = $config['addons']; if( !is_array($show) ){ return array(); } //set upgrade_from foreach($this->avail_addons as $folder => $info){ if( !$info['upgrade_key'] ){ continue; } $upgrade_key = $info['upgrade_key']; if( !isset($show[$upgrade_key]) ){ continue; } if( !isset($info['Addon_Version']) ){ $show[$upgrade_key]['upgrade_from'] = $folder; continue; } if( !isset($show[$upgrade_key]['upgrade_version']) || version_compare($show[$upgrade_key]['upgrade_version'], $info['Addon_Version'], '<') ){ $show[$upgrade_key]['upgrade_from'] = $folder; $show[$upgrade_key]['upgrade_version'] = $info['Addon_Version']; } } return $show; } public function PluginPanelGroup($addon_key,$info){ global $langmessage, $gpLayouts; $addon_config = \gp\tool\Plugins::GetAddonConfig($addon_key); $addon_config += $info; //merge the upgrade info echo '
'; echo '

'; echo \gp\tool::Link('Admin/Addons/'.\gp\admin\Tools::encode64($addon_key),$addon_config['name']); echo '

'; echo '
'; echo ''; $this->UpgradeLinks($addon_config); echo '
'; echo '
'; } /** * Plugin Upgrade links * */ public function UpgradeLinks($addon_config){ global $langmessage; //upgrade local if( isset($addon_config['upgrade_from']) && isset($addon_config['upgrade_version']) ){ if(version_compare($addon_config['upgrade_version'],$addon_config['version'] ,'>') ){ echo '
'; $label = $langmessage['new_version'].'   '.$addon_config['upgrade_version']; echo ''.$label.''; echo '
'; } } //upgrade cms if( isset($addon_config['id']) && isset(\gp\admin\Tools::$new_versions[$addon_config['id']]) ){ $new_version = \gp\admin\Tools::$new_versions[$addon_config['id']]; if( version_compare($new_version['version'],$addon_config['version'],'>') ){ echo ''; } } } /** * Plugin option links * */ public function OptionLinks($addon_key, $addon_config, $format = false){ global $langmessage, $gpLayouts; $list = array(); if( !isset($addon_config['is_theme']) || !$addon_config['is_theme'] ){ //editable text if( isset($addon_config['editable_text']) && \gp\admin\Tools::HasPermission('Admin_Theme_Content') ){ $list[] = \gp\tool::Link('Admin_Theme_Content/Text',$langmessage['editable_text'],'cmd=AddonTextForm&addon='.urlencode($addon_key),array('title'=>urlencode($langmessage['editable_text']),'data-cmd'=>'gpabox')); } //upgrade link if( isset($addon_config['upgrade_from']) ){ $list[] = ''.$langmessage['upgrade'].''; } //uninstall $list[] = \gp\tool::Link('Admin/Addons',$langmessage['uninstall'],'cmd=uninstall&addon='.rawurlencode($addon_key),'data-cmd="gpabox"'); //version if( !empty($addon_config['version']) ){ $list[] = ''.$langmessage['Your_version'].' '.$addon_config['version']. ''; } //rating if( isset($addon_config['id']) && is_numeric($addon_config['id']) ){ $id = $addon_config['id']; $rating = 5; if( isset($this->addonReviews[$id]) ){ $rating = $this->addonReviews[$id]['rating']; } $label = $langmessage['rate_this_addon'].' '.$this->ShowRating($id,$rating); $list[] = ''.$label. ''; } $this->FormatList($list,$langmessage['options'],$format); return; } //show list of themes using these addons foreach($gpLayouts as $layout_id => $layout_info){ if( !isset($layout_info['addon_key']) || $layout_info['addon_key'] !== $addon_key ){ continue; } $item = ' '; $item .= \gp\tool::Link('Admin_Theme_Content',$layout_info['label']); $item .= ' ( '; $item .= \gp\tool::Link('Admin_Theme_Content/Edit/'.$layout_id,$langmessage['edit']); $item .= ' )'; $list[] = $item; } $this->FormatList($list,$langmessage['layouts'],$format); } /** * Install Local Packages * */ public function LocalInstall(){ global $dataDir, $langmessage; $_REQUEST += array('source'=>''); if( !isset($this->avail_addons[$_REQUEST['source']]) ){ msg($langmessage['OOPS'].' (Invalid Request)'); return false; } $installer = new \gp\admin\Addon\Installer(); $installer->source = $this->avail_addons[$_REQUEST['source']]['source_folder']; $installer->Install(); $installer->OutputMessages(); } }