Typesetter/include/admin/Addons.php

661 lines
15 KiB
PHP
Raw Normal View History

2021-09-08 19:52:21 +02:00
<?php
namespace gp\admin;
defined('is_running') or die('Not an entry point...');
/**
* Admin Plugin
* /addons/<addon>/Addon.ini
* - Addon_Name (required)
* - link definitions: (optional)
* - should be able to have multiple links,
*
*
* - link_name (required)
* an example link: Admin_<linkname>
* - labels (required) should pull the language values during installation/upgrading
* - script (required)
* - class / function to call once opened (optional)
*
* - minimum version / max version
* /addons/<addon>/<php files>
*/
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 '<div class="inline_box">';
echo '<h3>'.$langmessage['uninstall'].'</h3>';
echo '<form action="'.\gp\tool::GetUrl('Admin/Addons').'" method="post">';
$addon =& $_REQUEST['addon'];
if( !isset($config['addons'][$addon]) ){
echo $langmessage['OOPS'];
echo '<p>';
echo ' <input type="submit" value="'.$langmessage['Close'].'" class="admin_box_close" /> ';
echo '</p>';
}else{
echo $langmessage['confirm_uninstall'];
echo '<p>';
echo '<input type="hidden" name="addon" value="'.htmlspecialchars($addon).'" />';
echo '<input type="hidden" name="cmd" value="confirm_uninstall" />';
echo ' <input type="submit" name="aaa" value="'.$langmessage['continue'].'" class="gpsubmit"/> ';
echo ' <input type="submit" value="'.$langmessage['cancel'].'" class="admin_box_close gpcancel" /> ';
echo '</p>';
}
echo '</form>';
echo '</div>';
}
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 '<hr/>';
echo '<div class="lead">';
echo $info['About'];
echo '</div>';
echo '<hr/><br/>';
}
echo '<div id="adminlinks2">';
$format = array();
$format['end'] = '</div></div>';
$format['start'] = '<div class="panelgroup"><h3>%s</h3><div class="panelgroup2">';
$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 '</div>';
}
/**
* Get a list of available addons
*
*/
public function GetAvailAddons(){
global $dataDir;
$addonPath = $dataDir.'/addons';
if( !file_exists($addonPath) ){
msg('Warning: The /addons folder "<em>'.$addonPath.'</em>" 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 '<hr/>';
echo '<a href="' . \CMS_DOMAIN . '/Docs/Plugins">Plugin Documentation</a>';
}
/**
* 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 '<div id="adminlinks2">';
// sort installed addons by name
$names = [];
foreach($show as $key => $row){
$names[$key] = $row['name'] ?? null;
2021-09-08 19:52:21 +02:00
}
$names = array_column($show, 'name');
// array_multisort($names, SORT_ASC, $show); ::: // ExecInfo() Fatal Error: Array sizes are inconsistent
2021-09-08 19:52:21 +02:00
foreach($show as $addon_key => $info){
$this->PluginPanelGroup($addon_key,$info);
}
echo '</div>';
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 '<div class="panelgroup" id="panelgroup_'.md5($addon_key).'">';
echo '<h3>';
echo \gp\tool::Link('Admin/Addons/'.\gp\admin\Tools::encode64($addon_key),$addon_config['name']);
echo '</h3>';
echo '<div class="panelgroup2">';
echo '<ul class="submenu">';
$this->AddonPanelGroup($addon_key);
$this->OptionLinks($addon_key, $addon_config);
echo '</ul>';
$this->UpgradeLinks($addon_config);
echo '</div>';
echo '</div>';
}
/**
* 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 '<div class="gp_notice">';
$label = $langmessage['new_version'].' &nbsp; '.$addon_config['upgrade_version'];
echo '<a href="?cmd=LocalInstall&source='.rawurlencode($addon_config['upgrade_from']).'" data-cmd="cnreq">'.$label.'</a>';
echo '</div>';
}
}
//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 '<div class="gp_notice">';
echo '<a href="'.addon_browse_path.'/Plugins?id='.$addon_config['id'].'" data-cmd="remote">';
echo $langmessage['new_version'];
echo ' &nbsp; '.$new_version['version'].' ('.CMS_READABLE_DOMAIN.')</a>';
echo '</div>';
}
}
}
/**
* 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[] = '<a href="?cmd=LocalInstall&source='.rawurlencode($addon_config['upgrade_from']).'" data-cmd="cnreq">'.$langmessage['upgrade'].'</a>';
}
//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[] = '<a>'.$langmessage['Your_version'].' '.$addon_config['version']. '</a>';
}
//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[] = '<span>'.$label. '</span>';
}
$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 = '<span><span class="layout_color_id" style="background:'.$layout_info['color'].'"></span> ';
$item .= \gp\tool::Link('Admin_Theme_Content',$layout_info['label']);
$item .= ' ( ';
$item .= \gp\tool::Link('Admin_Theme_Content/Edit/'.$layout_id,$langmessage['edit']);
$item .= ' )</span>';
$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();
}
}