Skip to content

Commit

Permalink
feat: PHP 83
Browse files Browse the repository at this point in the history
  • Loading branch information
devhaozi committed Nov 23, 2023
1 parent f900ada commit b532064
Show file tree
Hide file tree
Showing 7 changed files with 325 additions and 6 deletions.
274 changes: 274 additions & 0 deletions app/http/controllers/plugins/php83_controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
package plugins

import (
"fmt"
"regexp"
"strings"
"time"

"github.com/goravel/framework/contracts/http"
"github.com/goravel/framework/facades"
"github.com/imroc/req/v3"

"panel/app/http/controllers"
"panel/app/models"
"panel/app/services"
"panel/pkg/tools"
)

type Php83Controller struct {
setting services.Setting
task services.Task
version string
}

func NewPhp83Controller() *Php83Controller {
return &Php83Controller{
setting: services.NewSettingImpl(),
task: services.NewTaskImpl(),
version: "83",
}
}

func (r *Php83Controller) Status(ctx http.Context) http.Response {
status, err := tools.ServiceStatus("php-fpm-" + r.version)
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
}

return controllers.Success(ctx, status)
}

func (r *Php83Controller) Reload(ctx http.Context) http.Response {
if err := tools.ServiceReload("php-fpm-" + r.version); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "重载PHP-"+r.version+"失败")
}

return controllers.Success(ctx, nil)
}

func (r *Php83Controller) Start(ctx http.Context) http.Response {
if err := tools.ServiceStart("php-fpm-" + r.version); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "启动PHP-"+r.version+"失败")
}

return controllers.Success(ctx, nil)
}

func (r *Php83Controller) Stop(ctx http.Context) http.Response {
if err := tools.ServiceStop("php-fpm-" + r.version); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "停止PHP-"+r.version+"失败")
}

return controllers.Success(ctx, nil)
}

func (r *Php83Controller) Restart(ctx http.Context) http.Response {
if err := tools.ServiceRestart("php-fpm-" + r.version); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "重启PHP-"+r.version+"失败")
}

return controllers.Success(ctx, nil)
}

func (r *Php83Controller) GetConfig(ctx http.Context) http.Response {
config, err := tools.Read("/www/server/php/" + r.version + "/etc/php.ini")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"配置失败")
}

return controllers.Success(ctx, config)
}

func (r *Php83Controller) SaveConfig(ctx http.Context) http.Response {
config := ctx.Request().Input("config")
if err := tools.Write("/www/server/php/"+r.version+"/etc/php.ini", config, 0644); err != nil {
return nil
}
return r.Reload(ctx)
}

func (r *Php83Controller) Load(ctx http.Context) http.Response {
client := req.C().SetTimeout(10 * time.Second)
resp, err := client.R().Get("http://127.0.0.1/phpfpm_status/" + r.version)
if err != nil || !resp.IsSuccessState() {
facades.Log().Info("获取PHP-" + r.version + "运行状态失败")
return controllers.Error(ctx, http.StatusInternalServerError, "[PHP-"+r.version+"] 获取运行状态失败")
}

raw := resp.String()
dataKeys := []string{"应用池", "工作模式", "启动时间", "接受连接", "监听队列", "最大监听队列", "监听队列长度", "空闲进程数量", "活动进程数量", "总进程数量", "最大活跃进程数量", "达到进程上限次数", "慢请求"}
regexKeys := []string{"pool", "process manager", "start time", "accepted conn", "listen queue", "max listen queue", "listen queue len", "idle processes", "active processes", "total processes", "max active processes", "max children reached", "slow requests"}

type Data struct {
Name string `json:"name"`
Value string `json:"value"`
}
data := make([]Data, len(dataKeys))
for i := range dataKeys {
data[i].Name = dataKeys[i]

r := regexp.MustCompile(fmt.Sprintf("%s:\\s+(.*)", regexKeys[i]))
match := r.FindStringSubmatch(raw)

if len(match) > 1 {
data[i].Value = strings.TrimSpace(match[1])
}
}

return controllers.Success(ctx, data)
}

func (r *Php83Controller) ErrorLog(ctx http.Context) http.Response {
log, err := tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/php-fpm.log")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, log)
}

return controllers.Success(ctx, log)
}

func (r *Php83Controller) SlowLog(ctx http.Context) http.Response {
log, err := tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/slow.log")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, log)
}

return controllers.Success(ctx, log)
}

func (r *Php83Controller) ClearErrorLog(ctx http.Context) http.Response {
if out, err := tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/php-fpm.log"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}

return controllers.Success(ctx, nil)
}

func (r *Php83Controller) ClearSlowLog(ctx http.Context) http.Response {
if out, err := tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/slow.log"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, nil)
}

func (r *Php83Controller) GetExtensionList(ctx http.Context) http.Response {
extensions := r.GetExtensions()
return controllers.Success(ctx, extensions)
}

func (r *Php83Controller) InstallExtension(ctx http.Context) http.Response {
slug := ctx.Request().Input("slug")
if len(slug) == 0 {
return controllers.Error(ctx, http.StatusUnprocessableEntity, "参数错误")
}

extensions := r.GetExtensions()
for _, item := range extensions {
if item.Slug == slug {
if item.Installed {
return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展已安装")
}

var task models.Task
task.Name = "安装PHP-" + r.version + "扩展-" + item.Name
task.Status = models.TaskStatusWaiting
task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' install ` + r.version + ` >> /tmp/` + item.Slug + `.log 2>&1`
task.Log = "/tmp/" + item.Slug + ".log"
if err := facades.Orm().Query().Create(&task); err != nil {
facades.Log().Info("[PHP-" + r.version + "] 创建安装拓展任务失败:" + err.Error())
return controllers.ErrorSystem(ctx)
}

r.task.Process(task.ID)

return controllers.Success(ctx, true)
}
}

return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展不存在")
}

func (r *Php83Controller) UninstallExtension(ctx http.Context) http.Response {
slug := ctx.Request().Input("slug")
if len(slug) == 0 {
return controllers.Error(ctx, http.StatusUnprocessableEntity, "参数错误")
}

extensions := r.GetExtensions()
for _, item := range extensions {
if item.Slug == slug {
if !item.Installed {
return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展未安装")
}

var task models.Task
task.Name = "卸载PHP-" + r.version + "扩展-" + item.Name
task.Status = models.TaskStatusWaiting
task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' uninstall ` + r.version + ` >> /tmp/` + item.Slug + `.log 2>&1`
task.Log = "/tmp/" + item.Slug + ".log"
if err := facades.Orm().Query().Create(&task); err != nil {
facades.Log().Info("[PHP-" + r.version + "] 创建卸载拓展任务失败:" + err.Error())
return controllers.ErrorSystem(ctx)
}

r.task.Process(task.ID)

return controllers.Success(ctx, true)
}
}

return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展不存在")
}

func (r *Php83Controller) GetExtensions() []PHPExtension {
var extensions []PHPExtension
extensions = append(extensions, PHPExtension{
Name: "OPcache",
Slug: "Zend OPcache",
Description: "OPcache 通过将 PHP 脚本预编译的字节码存储到共享内存中来提升 PHP 的性能,存储预编译字节码可以省去每次加载和解析 PHP 脚本的开销。",
Installed: false,
})
extensions = append(extensions, PHPExtension{
Name: "PhpRedis",
Slug: "redis",
Description: "PhpRedis 是一个用C语言编写的PHP模块,用来连接并操作 Redis 数据库上的数据。",
Installed: false,
})
extensions = append(extensions, PHPExtension{
Name: "ImageMagick",
Slug: "imagick",
Description: "ImageMagick 是一个免费的创建、编辑、合成图片的软件。",
Installed: false,
})
extensions = append(extensions, PHPExtension{
Name: "Exif",
Slug: "exif",
Description: "通过 exif 扩展,你可以操作图像元数据。",
Installed: false,
})
extensions = append(extensions, PHPExtension{
Name: "pdo_pgsql",
Slug: "pdo_pgsql",
Description: "(需先安装PostgreSQL)pdo_pgsql 是一个驱动程序,它实现了 PHP 数据对象(PDO)接口以启用从 PHP 到 PostgreSQL 数据库的访问。",
Installed: false,
})

raw, err := tools.Exec("/www/server/php/" + r.version + "/bin/php -m")
if err != nil {
return extensions
}

rawExtensionList := strings.Split(raw, "\n")
for _, item := range rawExtensionList {
if !strings.Contains(item, "[") && item != "" {
for i := range extensions {
if extensions[i].Slug == item {
extensions[i].Installed = true
}
}
}
}

return extensions
}
2 changes: 1 addition & 1 deletion app/plugins/php81/php81.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ var (
Name = "PHP-8.1"
Description = "PHP 是世界上最好的语言!"
Slug = "php81"
Version = "8.1.25"
Version = "8.1.26"
Requires = []string{}
Excludes = []string{}
Install = `bash /www/panel/scripts/php/install.sh 81`
Expand Down
2 changes: 1 addition & 1 deletion app/plugins/php82/php82.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ var (
Name = "PHP-8.2"
Description = "PHP 是世界上最好的语言!"
Slug = "php82"
Version = "8.2.12"
Version = "8.2.13"
Requires = []string{}
Excludes = []string{}
Install = `bash /www/panel/scripts/php/install.sh 82`
Expand Down
13 changes: 13 additions & 0 deletions app/plugins/php83/php83.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package php83

var (
Name = "PHP-8.3"
Description = "PHP 是世界上最好的语言!"
Slug = "php83"
Version = "8.3.0"
Requires = []string{}
Excludes = []string{}
Install = `bash /www/panel/scripts/php/install.sh 83`
Uninstall = `bash /www/panel/scripts/php/uninstall.sh 83`
Update = `bash /www/panel/scripts/php/install.sh 83`
)
12 changes: 12 additions & 0 deletions app/services/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"panel/app/plugins/php80"
"panel/app/plugins/php81"
"panel/app/plugins/php82"
"panel/app/plugins/php83"
"panel/app/plugins/phpmyadmin"
"panel/app/plugins/postgresql15"
"panel/app/plugins/postgresql16"
Expand Down Expand Up @@ -164,6 +165,17 @@ func (r *PluginImpl) All() []PanelPlugin {
Uninstall: php82.Uninstall,
Update: php82.Update,
})
p = append(p, PanelPlugin{
Name: php83.Name,
Description: php83.Description,
Slug: php83.Slug,
Version: php83.Version,
Requires: php83.Requires,
Excludes: php83.Excludes,
Install: php83.Install,
Uninstall: php83.Uninstall,
Update: php83.Update,
})
p = append(p, PanelPlugin{
Name: phpmyadmin.Name,
Description: phpmyadmin.Description,
Expand Down
18 changes: 18 additions & 0 deletions routes/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,24 @@ func Plugin() {
route.Post("extensions", php82Controller.InstallExtension)
route.Delete("extensions", php82Controller.UninstallExtension)
})
r.Prefix("php83").Group(func(route route.Router) {
php83Controller := plugins.NewPhp83Controller()
route.Get("status", php83Controller.Status)
route.Post("reload", php83Controller.Reload)
route.Post("start", php83Controller.Start)
route.Post("stop", php83Controller.Stop)
route.Post("restart", php83Controller.Restart)
route.Get("load", php83Controller.Load)
route.Get("config", php83Controller.GetConfig)
route.Post("config", php83Controller.SaveConfig)
route.Get("errorLog", php83Controller.ErrorLog)
route.Get("slowLog", php83Controller.SlowLog)
route.Post("clearErrorLog", php83Controller.ClearErrorLog)
route.Post("clearSlowLog", php83Controller.ClearSlowLog)
route.Get("extensions", php83Controller.GetExtensionList)
route.Post("extensions", php83Controller.InstallExtension)
route.Delete("extensions", php83Controller.UninstallExtension)
})
r.Prefix("phpmyadmin").Group(func(route route.Router) {
phpMyAdminController := plugins.NewPhpMyAdminController()
route.Get("info", phpMyAdminController.Info)
Expand Down
10 changes: 6 additions & 4 deletions scripts/php/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,11 @@ if [ "${phpVersion}" == "74" ]; then
elif [ "${phpVersion}" == "80" ]; then
phpVersionCode="8.0.30"
elif [ "${phpVersion}" == "81" ]; then
phpVersionCode="8.1.25"
phpVersionCode="8.1.26"
elif [ "${phpVersion}" == "82" ]; then
phpVersionCode="8.2.12"
phpVersionCode="8.2.13"
elif [ "${phpVersion}" == "83" ]; then
phpVersionCode="8.3.0"
else
echo -e $HR
echo "错误:PHP-${phpVersion}不支持,请检查版本号是否正确。"
Expand Down Expand Up @@ -119,8 +121,8 @@ fi

# 配置
cd src
if [ "${phpVersion}" == "81" ] || [ "${phpVersion}" == "82" ]; then
./configure --prefix=${phpPath} --with-config-file-path=${phpPath}/etc --enable-fpm --with-fpm-user=www --with-fpm-group=www --enable-mysqlnd --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --with-freetype --with-jpeg --with-zlib --with-libxml-dir=/usr --enable-xml --disable-rpath --enable-bcmath --enable-shmop --enable-sysvsem --enable-inline-optimization --with-curl --enable-mbregex --enable-mbstring --enable-intl --enable-pcntl --enable-ftp --enable-gd --with-openssl --with-mhash --enable-pcntl --enable-sockets --with-xmlrpc --enable-soap --with-gettext --enable-fileinfo --enable-opcache --with-sodium --with-webp --with-avif
if [ "${phpVersion}" == "81" ] || [ "${phpVersion}" == "82" ] || [ "${phpVersion}" == "83" ]; then
./configure --prefix=${phpPath} --with-config-file-path=${phpPath}/etc --enable-fpm --with-fpm-user=www --with-fpm-group=www --enable-mysqlnd --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --with-freetype --with-jpeg --with-zlib --enable-xml --disable-rpath --enable-bcmath --enable-shmop --enable-sysvsem --with-curl --enable-mbregex --enable-mbstring --enable-intl --enable-pcntl --enable-ftp --enable-gd --with-openssl --with-mhash --enable-pcntl --enable-sockets --enable-soap --with-gettext --enable-fileinfo --enable-opcache --with-sodium --with-webp --with-avif
else
./configure --prefix=${phpPath} --with-config-file-path=${phpPath}/etc --enable-fpm --with-fpm-user=www --with-fpm-group=www --enable-mysqlnd --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --with-freetype --with-jpeg --with-zlib --with-libxml-dir=/usr --enable-xml --disable-rpath --enable-bcmath --enable-shmop --enable-sysvsem --enable-inline-optimization --with-curl --enable-mbregex --enable-mbstring --enable-intl --enable-pcntl --enable-ftp --enable-gd --with-openssl --with-mhash --enable-pcntl --enable-sockets --with-xmlrpc --enable-soap --with-gettext --enable-fileinfo --enable-opcache --with-sodium --with-webp
fi
Expand Down

0 comments on commit b532064

Please sign in to comment.