first commit
This commit is contained in:
113
var/Widget/Plugins/Config.php
Executable file
113
var/Widget/Plugins/Config.php
Executable file
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
namespace Widget\Plugins;
|
||||
|
||||
use Typecho\Plugin;
|
||||
use Typecho\Widget\Exception;
|
||||
use Typecho\Widget\Helper\Form;
|
||||
use Widget\Base\Options;
|
||||
|
||||
if (!defined('__TYPECHO_ROOT_DIR__')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* 插件配置组件
|
||||
*
|
||||
* @author qining
|
||||
* @category typecho
|
||||
* @package Widget
|
||||
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
|
||||
* @license GNU General Public License 2.0
|
||||
*/
|
||||
class Config extends Options
|
||||
{
|
||||
/**
|
||||
* 获取插件信息
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public array $info;
|
||||
|
||||
/**
|
||||
* 插件文件路径
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private string $pluginFileName;
|
||||
|
||||
/**
|
||||
* 插件类
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private string $className;
|
||||
|
||||
/**
|
||||
* 绑定动作
|
||||
*
|
||||
* @throws Plugin\Exception
|
||||
* @throws Exception|\Typecho\Db\Exception
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
$this->user->pass('administrator');
|
||||
$config = $this->request->filter('slug')->get('config');
|
||||
if (empty($config)) {
|
||||
throw new Exception(_t('插件不存在'), 404);
|
||||
}
|
||||
|
||||
/** 获取插件入口 */
|
||||
[$this->pluginFileName, $this->className] = Plugin::portal($config, $this->options->pluginDir);
|
||||
$this->info = Plugin::parseInfo($this->pluginFileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取菜单标题
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMenuTitle(): string
|
||||
{
|
||||
return _t('设置插件 %s', $this->info['title']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置插件
|
||||
*
|
||||
* @return Form
|
||||
* @throws Exception|Plugin\Exception
|
||||
*/
|
||||
public function config(): Form
|
||||
{
|
||||
/** 获取插件名称 */
|
||||
$pluginName = $this->request->filter('slug')->get('config');
|
||||
|
||||
/** 获取已启用插件 */
|
||||
$plugins = Plugin::export();
|
||||
$activatedPlugins = $plugins['activated'];
|
||||
|
||||
/** 判断实例化是否成功 */
|
||||
if (!$this->info['config'] || !isset($activatedPlugins[$pluginName])) {
|
||||
throw new Exception(_t('无法配置插件'), 500);
|
||||
}
|
||||
|
||||
/** 载入插件 */
|
||||
require_once $this->pluginFileName;
|
||||
$form = new Form($this->security->getIndex('/action/plugins-edit?config=' . $pluginName), Form::POST_METHOD);
|
||||
call_user_func([$this->className, 'config'], $form);
|
||||
|
||||
$options = $this->options->plugin($pluginName);
|
||||
|
||||
if (!empty($options)) {
|
||||
foreach ($options as $key => $val) {
|
||||
$form->getInput($key)->value($val);
|
||||
}
|
||||
}
|
||||
|
||||
$submit = new Form\Element\Submit(null, null, _t('保存设置'));
|
||||
$submit->input->setAttribute('class', 'btn primary');
|
||||
$form->addItem($submit);
|
||||
return $form;
|
||||
}
|
||||
}
|
||||
318
var/Widget/Plugins/Edit.php
Executable file
318
var/Widget/Plugins/Edit.php
Executable file
@@ -0,0 +1,318 @@
|
||||
<?php
|
||||
|
||||
namespace Widget\Plugins;
|
||||
|
||||
use Typecho\Common;
|
||||
use Typecho\Db;
|
||||
use Typecho\Plugin;
|
||||
use Typecho\Widget\Exception;
|
||||
use Typecho\Widget\Helper\Form;
|
||||
use Widget\ActionInterface;
|
||||
use Widget\Base\Options;
|
||||
use Widget\Notice;
|
||||
|
||||
if (!defined('__TYPECHO_ROOT_DIR__')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* 插件管理组件
|
||||
*
|
||||
* @author qining
|
||||
* @category typecho
|
||||
* @package Widget
|
||||
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
|
||||
* @license GNU General Public License 2.0
|
||||
*/
|
||||
class Edit extends Options implements ActionInterface
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private bool $configNoticed = false;
|
||||
|
||||
/**
|
||||
* 启用插件
|
||||
*
|
||||
* @param $pluginName
|
||||
* @throws Exception|Db\Exception|Plugin\Exception
|
||||
*/
|
||||
public function activate($pluginName)
|
||||
{
|
||||
/** 获取插件入口 */
|
||||
[$pluginFileName, $className] = Plugin::portal($pluginName, $this->options->pluginDir);
|
||||
$info = Plugin::parseInfo($pluginFileName);
|
||||
|
||||
/** 检测依赖信息 */
|
||||
if (Plugin::checkDependence($info['since'])) {
|
||||
|
||||
/** 获取已启用插件 */
|
||||
$plugins = Plugin::export();
|
||||
$activatedPlugins = $plugins['activated'];
|
||||
|
||||
/** 载入插件 */
|
||||
require_once $pluginFileName;
|
||||
|
||||
/** 判断实例化是否成功 */
|
||||
if (
|
||||
isset($activatedPlugins[$pluginName]) || !class_exists($className)
|
||||
|| !method_exists($className, 'activate')
|
||||
) {
|
||||
throw new Exception(_t('无法启用插件'), 500);
|
||||
}
|
||||
|
||||
try {
|
||||
$result = call_user_func([$className, 'activate']);
|
||||
Plugin::activate($pluginName);
|
||||
$this->update(
|
||||
['value' => json_encode(Plugin::export())],
|
||||
$this->db->sql()->where('name = ?', 'plugins')
|
||||
);
|
||||
} catch (Plugin\Exception $e) {
|
||||
/** 截获异常 */
|
||||
Notice::alloc()->set($e->getMessage(), 'error');
|
||||
$this->response->goBack();
|
||||
}
|
||||
|
||||
$form = new Form();
|
||||
call_user_func([$className, 'config'], $form);
|
||||
|
||||
$personalForm = new Form();
|
||||
call_user_func([$className, 'personalConfig'], $personalForm);
|
||||
|
||||
$options = $form->getValues();
|
||||
$personalOptions = $personalForm->getValues();
|
||||
|
||||
if ($options && !$this->configHandle($pluginName, $options, true)) {
|
||||
self::configPlugin($pluginName, $options);
|
||||
}
|
||||
|
||||
if ($personalOptions && !$this->personalConfigHandle($className, $personalOptions)) {
|
||||
self::configPlugin($pluginName, $personalOptions, true);
|
||||
}
|
||||
} else {
|
||||
$result = _t('<a href="%s">%s</a> 无法在此版本的typecho下正常工作', $info['homepage'], $info['title']);
|
||||
}
|
||||
|
||||
/** 设置高亮 */
|
||||
Notice::alloc()->highlight('plugin-' . $pluginName);
|
||||
|
||||
if (isset($result) && is_string($result)) {
|
||||
Notice::alloc()->set($result, 'notice');
|
||||
} else {
|
||||
Notice::alloc()->set(_t('插件已经被启用'), 'success');
|
||||
}
|
||||
$this->response->goBack();
|
||||
}
|
||||
|
||||
/**
|
||||
* 用自有函数处理配置信息
|
||||
*
|
||||
* @access public
|
||||
* @param string $pluginName 插件名称
|
||||
* @param array $settings 配置值
|
||||
* @param boolean $isInit 是否为初始化
|
||||
* @return boolean
|
||||
* @throws Plugin\Exception
|
||||
*/
|
||||
public function configHandle(string $pluginName, array $settings, bool $isInit): bool
|
||||
{
|
||||
/** 获取插件入口 */
|
||||
[$pluginFileName, $className] = Plugin::portal($pluginName, $this->options->pluginDir);
|
||||
|
||||
if (!$isInit && method_exists($className, 'configCheck')) {
|
||||
$result = call_user_func([$className, 'configCheck'], $settings);
|
||||
|
||||
if (!empty($result) && is_string($result)) {
|
||||
Notice::alloc()->set($result);
|
||||
$this->configNoticed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (method_exists($className, 'configHandle')) {
|
||||
call_user_func([$className, 'configHandle'], $settings, $isInit);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 手动配置插件变量
|
||||
*
|
||||
* @param string $pluginName 插件名称
|
||||
* @param array $settings 变量键值对
|
||||
* @param bool $isPersonal 是否为私人变量
|
||||
* @throws Db\Exception
|
||||
*/
|
||||
public static function configPlugin(string $pluginName, array $settings, bool $isPersonal = false)
|
||||
{
|
||||
$db = Db::get();
|
||||
$pluginName = ($isPersonal ? '_' : '') . 'plugin:' . $pluginName;
|
||||
|
||||
$select = $db->select()->from('table.options')
|
||||
->where('name = ?', $pluginName);
|
||||
|
||||
$options = $db->fetchAll($select);
|
||||
|
||||
if (empty($settings)) {
|
||||
if (!empty($options)) {
|
||||
$db->query($db->delete('table.options')->where('name = ?', $pluginName));
|
||||
}
|
||||
} else {
|
||||
if (empty($options)) {
|
||||
$db->query($db->insert('table.options')
|
||||
->rows([
|
||||
'name' => $pluginName,
|
||||
'value' => json_encode($settings),
|
||||
'user' => 0
|
||||
]));
|
||||
} else {
|
||||
foreach ($options as $option) {
|
||||
$value = json_decode($option['value'], true);
|
||||
$value = array_merge($value, $settings);
|
||||
|
||||
$db->query($db->update('table.options')
|
||||
->rows(['value' => json_encode($value)])
|
||||
->where('name = ?', $pluginName)
|
||||
->where('user = ?', $option['user']));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用自有函数处理自定义配置信息
|
||||
*
|
||||
* @param string $className 类名
|
||||
* @param array $settings 配置值
|
||||
* @return boolean
|
||||
*/
|
||||
public function personalConfigHandle(string $className, array $settings): bool
|
||||
{
|
||||
if (method_exists($className, 'personalConfigHandle')) {
|
||||
call_user_func([$className, 'personalConfigHandle'], $settings, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 禁用插件
|
||||
*
|
||||
* @param string $pluginName
|
||||
* @throws Db\Exception
|
||||
* @throws Exception
|
||||
* @throws Plugin\Exception
|
||||
*/
|
||||
public function deactivate(string $pluginName)
|
||||
{
|
||||
/** 获取已启用插件 */
|
||||
$plugins = Plugin::export();
|
||||
$activatedPlugins = $plugins['activated'];
|
||||
$pluginFileExist = true;
|
||||
|
||||
try {
|
||||
/** 获取插件入口 */
|
||||
[$pluginFileName, $className] = Plugin::portal($pluginName, $this->options->pluginDir);
|
||||
} catch (Plugin\Exception $e) {
|
||||
$pluginFileExist = false;
|
||||
|
||||
if (!isset($activatedPlugins[$pluginName])) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/** 判断实例化是否成功 */
|
||||
if (!isset($activatedPlugins[$pluginName])) {
|
||||
throw new Exception(_t('无法禁用插件'), 500);
|
||||
}
|
||||
|
||||
if ($pluginFileExist) {
|
||||
|
||||
/** 载入插件 */
|
||||
require_once $pluginFileName;
|
||||
|
||||
/** 判断实例化是否成功 */
|
||||
if (
|
||||
!isset($activatedPlugins[$pluginName]) || !class_exists($className)
|
||||
|| !method_exists($className, 'deactivate')
|
||||
) {
|
||||
throw new Exception(_t('无法禁用插件'), 500);
|
||||
}
|
||||
|
||||
try {
|
||||
$result = call_user_func([$className, 'deactivate']);
|
||||
} catch (Plugin\Exception $e) {
|
||||
/** 截获异常 */
|
||||
Notice::alloc()->set($e->getMessage(), 'error');
|
||||
$this->response->goBack();
|
||||
}
|
||||
|
||||
/** 设置高亮 */
|
||||
Notice::alloc()->highlight('plugin-' . $pluginName);
|
||||
}
|
||||
|
||||
Plugin::deactivate($pluginName);
|
||||
$this->update(['value' => json_encode(Plugin::export())], $this->db->sql()->where('name = ?', 'plugins'));
|
||||
|
||||
$this->delete($this->db->sql()->where('name = ?', 'plugin:' . $pluginName));
|
||||
$this->delete($this->db->sql()->where('name = ?', '_plugin:' . $pluginName));
|
||||
|
||||
if (isset($result) && is_string($result)) {
|
||||
Notice::alloc()->set($result);
|
||||
} else {
|
||||
Notice::alloc()->set(_t('插件已经被禁用'), 'success');
|
||||
}
|
||||
$this->response->goBack();
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置插件
|
||||
*
|
||||
* @param string $pluginName
|
||||
* @throws Db\Exception
|
||||
* @throws Exception
|
||||
* @throws Plugin\Exception
|
||||
*/
|
||||
public function config(string $pluginName)
|
||||
{
|
||||
$form = Config::alloc()->config();
|
||||
|
||||
/** 验证表单 */
|
||||
if ($form->validate()) {
|
||||
$this->response->goBack();
|
||||
}
|
||||
|
||||
$settings = $form->getAllRequest();
|
||||
|
||||
if (!$this->configHandle($pluginName, $settings, false)) {
|
||||
self::configPlugin($pluginName, $settings);
|
||||
}
|
||||
|
||||
/** 设置高亮 */
|
||||
Notice::alloc()->highlight('plugin-' . $pluginName);
|
||||
|
||||
if (!$this->configNoticed) {
|
||||
/** 提示信息 */
|
||||
Notice::alloc()->set(_t("插件设置已经保存"), 'success');
|
||||
}
|
||||
|
||||
/** 转向原页 */
|
||||
$this->response->redirect(Common::url('plugins.php', $this->options->adminUrl));
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定动作
|
||||
*/
|
||||
public function action()
|
||||
{
|
||||
$this->user->pass('administrator');
|
||||
$this->security->protect();
|
||||
$this->on($this->request->is('activate'))->activate($this->request->filter('slug')->get('activate'));
|
||||
$this->on($this->request->is('deactivate'))->deactivate($this->request->filter('slug')->get('deactivate'));
|
||||
$this->on($this->request->is('config'))->config($this->request->filter('slug')->get('config'));
|
||||
$this->response->redirect($this->options->adminUrl);
|
||||
}
|
||||
}
|
||||
115
var/Widget/Plugins/Rows.php
Executable file
115
var/Widget/Plugins/Rows.php
Executable file
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
namespace Widget\Plugins;
|
||||
|
||||
use Typecho\Plugin;
|
||||
use Typecho\Widget;
|
||||
|
||||
if (!defined('__TYPECHO_ROOT_DIR__')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* 插件列表组件
|
||||
*
|
||||
* @author qining
|
||||
* @category typecho
|
||||
* @package Widget
|
||||
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
|
||||
* @license GNU General Public License 2.0
|
||||
*/
|
||||
class Rows extends Widget
|
||||
{
|
||||
/**
|
||||
* 已启用插件
|
||||
*
|
||||
* @access public
|
||||
* @var array
|
||||
*/
|
||||
public array $activatedPlugins = [];
|
||||
|
||||
/**
|
||||
* 执行函数
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
/** 列出插件目录 */
|
||||
$pluginDirs = $this->getPlugins();
|
||||
$this->parameter->setDefault(['activated' => null]);
|
||||
|
||||
/** 获取已启用插件 */
|
||||
$plugins = Plugin::export();
|
||||
$this->activatedPlugins = $plugins['activated'];
|
||||
|
||||
if (!empty($pluginDirs)) {
|
||||
foreach ($pluginDirs as $key => $pluginDir) {
|
||||
$parts = $this->getPlugin($pluginDir, $key);
|
||||
if (empty($parts)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
[$pluginName, $pluginFileName] = $parts;
|
||||
|
||||
if (file_exists($pluginFileName)) {
|
||||
$info = Plugin::parseInfo($pluginFileName);
|
||||
$info['name'] = $pluginName;
|
||||
|
||||
$info['dependence'] = Plugin::checkDependence($info['since']);
|
||||
|
||||
/** 默认即插即用 */
|
||||
$info['activated'] = true;
|
||||
|
||||
if ($info['activate'] || $info['deactivate'] || $info['config'] || $info['personalConfig']) {
|
||||
$info['activated'] = isset($this->activatedPlugins[$pluginName]);
|
||||
|
||||
if (isset($this->activatedPlugins[$pluginName])) {
|
||||
unset($this->activatedPlugins[$pluginName]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($info['activated'] == $this->parameter->activated) {
|
||||
$this->push($info);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function getPlugins(): array
|
||||
{
|
||||
return glob(__TYPECHO_ROOT_DIR__ . '/' . __TYPECHO_PLUGIN_DIR__ . '/*');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $plugin
|
||||
* @return array|null
|
||||
*/
|
||||
protected function getPlugin(string $plugin): ?array
|
||||
{
|
||||
if (is_dir($plugin)) {
|
||||
/** 获取插件名称 */
|
||||
$pluginName = basename($plugin);
|
||||
|
||||
/** 获取插件主文件 */
|
||||
$pluginFileName = $plugin . '/Plugin.php';
|
||||
} elseif (file_exists($plugin) && 'index.php' != basename($plugin)) {
|
||||
$pluginFileName = $plugin;
|
||||
$part = explode('.', basename($plugin));
|
||||
if (2 == count($part) && 'php' == $part[1]) {
|
||||
$pluginName = $part[0];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
return [$pluginName, $pluginFileName];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user