test: AI CI injection 20260215153619 #3

Closed
feibisi wants to merge 0 commits from qa/ai-ci-20260215153619 into main
17 changed files with 459 additions and 1026 deletions

View file

@ -1,3 +0,0 @@
2026年 05月 04日 星期一 19:22:57 CST
2026年 05月 04日 星期一 19:28:08 CST
2026年 05月 04日 星期一 19:29:46 CST

View file

@ -1,17 +0,0 @@
name: Auto Label

on:
schedule:
- cron: '30 5 * * 1' # 每周一凌晨 5:30stale-cleanup 之后)
workflow_dispatch:

jobs:
auto-label:
runs-on: linux-arm64
steps:
- uses: actions/checkout@v4

- name: 自动给 PR 打标签
env:
FORGEJO_TOKEN: ${{ secrets.FORGEJO_TOKEN }}
run: python3 scripts/auto-label.py

View file

@ -1,31 +0,0 @@
name: gitleaks 密钥泄露扫描

on:
push:
branches: ['*']
pull_request:
branches: ['*']

jobs:
gitleaks:
runs-on: linux-arm64
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Run gitleaks
run: |
if [ "$GITHUB_EVENT_NAME" = "push" ]; then
gitleaks detect --source=. --log-opts="$GITHUB_SHA~1..$GITHUB_SHA" --verbose --exit-code 1 || {
echo "::error::gitleaks 发现了潜在的密钥泄露!请检查上方输出并移除敏感信息。"
exit 1
}
else
gitleaks detect --source=. --verbose --exit-code 1 || {
echo "::error::gitleaks 发现了潜在的密钥泄露!请检查上方输出并移除敏感信息。"
exit 1
}
fi
echo "gitleaks 扫描通过,未发现密钥泄露。"

View file

@ -1,7 +1,6 @@
# 文派统一插件发布 CI Workflow # 文派统一插件发布 CI Workflow
# 触发push tag v* # 触发push tag v*
# 运行环境forgejo-ci-php:latest (Alpine + php-cli + git + rsync + zip + node) # 运行环境forgejo-ci-php:latest (Alpine + php-cli + git + rsync + zip + node)
# 基于 ci-workflows/wp-release.yml 2026-02-18 版本
name: Release Plugin name: Release Plugin


on: on:
@ -18,18 +17,17 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
fetch-depth: 0


- name: Verify tools - name: Verify tools
shell: bash shell: bash
run: | run: |
php -v | head -1 || true set -euo pipefail
php -v | head -1
git --version git --version
rsync --version | head -1 || true rsync --version | head -1
zip --version | head -2 || true zip --version | head -2
jq --version jq --version
curl --version | head -1 || true curl --version | head -1


- name: Extract version from tag - name: Extract version from tag
id: version id: version
@ -76,58 +74,6 @@ jobs:
fi fi
echo "Version consistency check passed: $VERSION" echo "Version consistency check passed: $VERSION"


- name: Generate Changelog
shell: bash
run: |
set -euo pipefail
TAG="${GITHUB_REF#refs/tags/}"

PREV_TAG=$(git tag --sort=-version:refname | grep -E '^v' | grep -v "^${TAG}$" | head -1)

if [ -n "$PREV_TAG" ]; then
echo "Changelog: ${PREV_TAG}..${TAG}"
COMMITS=$(git log "${PREV_TAG}..${TAG}" --no-merges --pretty=format:"%s (%h)" 2>/dev/null || true)
else
echo "Changelog: first release, using all commits"
COMMITS=$(git log --no-merges --pretty=format:"%s (%h)" 2>/dev/null || true)
fi

if [ -z "$COMMITS" ]; then
: > /tmp/changelog.md
echo "No commits found for changelog"
exit 0
fi

FEAT="" FIX="" OTHER=""
while IFS= read -r line; do
case "$line" in
feat:*|feat\(*) FEAT="${FEAT}\n- ${line}" ;;
fix:*|fix\(*) FIX="${FIX}\n- ${line}" ;;
*) OTHER="${OTHER}\n- ${line}" ;;
esac
done <<< "$COMMITS"

CHANGELOG=""
HAS_CATEGORIES=false
if [ -n "$FEAT" ]; then
CHANGELOG="${CHANGELOG}#### New Features${FEAT}\n\n"
HAS_CATEGORIES=true
fi
if [ -n "$FIX" ]; then
CHANGELOG="${CHANGELOG}#### Bug Fixes${FIX}\n\n"
HAS_CATEGORIES=true
fi
if [ -n "$OTHER" ]; then
if [ "$HAS_CATEGORIES" = true ]; then
CHANGELOG="${CHANGELOG}#### Other Changes${OTHER}\n\n"
else
CHANGELOG="${OTHER#\\n}\n\n"
fi
fi

printf '%b' "$CHANGELOG" > /tmp/changelog.md
echo "Changelog generated ($(echo "$COMMITS" | wc -l) commits)"

- name: PHP Lint - name: PHP Lint
shell: bash shell: bash
run: | run: |
@ -167,13 +113,8 @@ jobs:
--exclude=".gitattributes" \ --exclude=".gitattributes" \
--exclude=".editorconfig" \ --exclude=".editorconfig" \
--exclude=".env*" \ --exclude=".env*" \
--exclude=".agent" \
--exclude=".vscode" \
--exclude="node_modules" \ --exclude="node_modules" \
--exclude="vendor" \
--exclude="tests" \ --exclude="tests" \
--exclude="docs" \
--exclude="lib" \
--exclude="phpunit.xml*" \ --exclude="phpunit.xml*" \
--exclude="phpcs.xml*" \ --exclude="phpcs.xml*" \
--exclude="phpstan.neon*" \ --exclude="phpstan.neon*" \
@ -186,6 +127,7 @@ jobs:
--exclude="*.md" \ --exclude="*.md" \
--exclude="LICENSE" \ --exclude="LICENSE" \
--exclude="Makefile" \ --exclude="Makefile" \
--exclude="lib" \
./ "$BUILD_DIR/" ./ "$BUILD_DIR/"


( (
@ -232,23 +174,7 @@ jobs:
SHA256="${{ steps.checksum.outputs.sha256 }}" SHA256="${{ steps.checksum.outputs.sha256 }}"
API_URL="${GITHUB_SERVER_URL%/}/api/v1/repos/${GITHUB_REPOSITORY}" API_URL="${GITHUB_SERVER_URL%/}/api/v1/repos/${GITHUB_REPOSITORY}"
AUTH_HEADER="Authorization: token ${AUTH_TOKEN}" AUTH_HEADER="Authorization: token ${AUTH_TOKEN}"

printf -v RELEASE_NOTES '## %s %s\n\n### Checksums\n\n| File | SHA-256 |\n|------|---------|\n| %s | %s |\n' "$SLUG" "$TAG" "$ZIP_NAME" "$SHA256"
{
echo "## ${SLUG} ${TAG}"
echo ""
CHANGELOG_FILE="/tmp/changelog.md"
if [ -f "$CHANGELOG_FILE" ] && [ -s "$CHANGELOG_FILE" ]; then
echo "### What's Changed"
echo ""
cat "$CHANGELOG_FILE"
fi
echo "### Checksums"
echo ""
echo "| File | SHA-256 |"
echo "|------|---------|"
echo "| ${ZIP_NAME} | ${SHA256} |"
} > /tmp/release-notes.md
RELEASE_NOTES=$(cat /tmp/release-notes.md)


echo ">>> Resolving release ${TAG}" echo ">>> Resolving release ${TAG}"
STATUS=$(curl -sS -o /tmp/release.json -w "%{http_code}" \ STATUS=$(curl -sS -o /tmp/release.json -w "%{http_code}" \
@ -354,6 +280,7 @@ jobs:
chmod 600 "$KEY_PATH" chmod 600 "$KEY_PATH"
ssh-keyscan -t rsa,ecdsa,ed25519 -p "$DEPLOY_PORT" -H "$DEPLOY_HOST" >> "$HOME/.ssh/known_hosts" 2>/dev/null || true ssh-keyscan -t rsa,ecdsa,ed25519 -p "$DEPLOY_PORT" -H "$DEPLOY_HOST" >> "$HOME/.ssh/known_hosts" 2>/dev/null || true


# Run only for this plugin to reduce release-time impact.
if [[ "$DEPLOY_COMMAND_MODE" == "runner" ]]; then if [[ "$DEPLOY_COMMAND_MODE" == "runner" ]]; then
DEPLOY_COMPOSER_SCRIPT="${DEPLOY_COMPOSER_SCRIPT:-/usr/local/sbin/wp-post-release-composer-runner}" DEPLOY_COMPOSER_SCRIPT="${DEPLOY_COMPOSER_SCRIPT:-/usr/local/sbin/wp-post-release-composer-runner}"
ssh -i "$KEY_PATH" -p "$DEPLOY_PORT" -o BatchMode=yes -o StrictHostKeyChecking=yes "${DEPLOY_USER}@${DEPLOY_HOST}" \ ssh -i "$KEY_PATH" -p "$DEPLOY_PORT" -o BatchMode=yes -o StrictHostKeyChecking=yes "${DEPLOY_USER}@${DEPLOY_HOST}" \
@ -434,3 +361,39 @@ jobs:
fi fi


echo "Update API verification passed" echo "Update API verification passed"

- name: Notify AI CI assistant on failure (optional)
if: ${{ failure() && secrets.AI_WEBHOOK_ENDPOINT != '' }}
continue-on-error: true
shell: bash
env:
AI_WEBHOOK_ENDPOINT: ${{ secrets.AI_WEBHOOK_ENDPOINT }}
AI_WEBHOOK_TOKEN: ${{ secrets.AI_WEBHOOK_TOKEN }}
run: |
set -euo pipefail

OWNER="${GITHUB_REPOSITORY%%/*}"
REPO="${GITHUB_REPOSITORY##*/}"
BRANCH="${GITHUB_REF#refs/heads/}"
RUN_URL="${GITHUB_SERVER_URL%/}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}"
FAILED_STEPS_JSON="$(printf '%s' '${{ toJson(steps) }}' | jq -c '[to_entries[] | select(.value.outcome=="failure" or .value.conclusion=="failure") | .key]')"

PAYLOAD="$(jq -cn \
--arg event "ci_failure_report" \
--arg owner "$OWNER" \
--arg repo "$REPO" \
--arg sha "${GITHUB_SHA}" \
--arg branch "$BRANCH" \
--arg workflow "${GITHUB_WORKFLOW}" \
--arg run_url "$RUN_URL" \
--arg log_excerpt "release workflow failed; inspect run_url for full logs" \
--argjson failed_steps "$FAILED_STEPS_JSON" \
'{event:$event, owner:$owner, repo:$repo, sha:$sha, branch:$branch, workflow:$workflow, run_url:$run_url, failed_steps:$failed_steps, log_excerpt:$log_excerpt}')"

CURL_HEADERS=(-H "Content-Type: application/json")
if [[ -n "${AI_WEBHOOK_TOKEN:-}" ]]; then
CURL_HEADERS+=( -H "Authorization: Bearer ${AI_WEBHOOK_TOKEN}" )
fi

curl -sS -X POST "${CURL_HEADERS[@]}" --data "$PAYLOAD" "$AI_WEBHOOK_ENDPOINT" > /dev/null
echo "AI CI assistant notified"

View file

@ -1,128 +0,0 @@
name: 安全扫描

on:
push:
branches: ['main', 'master']
paths:
- 'Dockerfile*'
- 'docker-compose*.yml'
- 'composer.json'
- 'composer.lock'
- 'package.json'
- 'package-lock.json'
- 'yarn.lock'
- 'pnpm-lock.yaml'
- 'go.mod'
- 'go.sum'
pull_request:
branches: ['main', 'master']
schedule:
- cron: '0 3 * * 1' # 每周一凌晨 3 点

jobs:
security-scan:
runs-on: linux-arm64
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Hadolint Dockerfile 检查
run: |
# 检查是否存在 Dockerfile
DOCKERFILES=$(find . -name 'Dockerfile*' -not -path './.git/*' 2>/dev/null)
if [ -z "$DOCKERFILES" ]; then
echo "未找到 Dockerfile跳过"
exit 0
fi
# 如果未安装 hadolint 则跳过
if ! command -v hadolint &> /dev/null; then
echo "hadolint 未安装,跳过 Dockerfile 检查"
exit 0
fi
FAILED=0
for df in $DOCKERFILES; do
echo "--- 检查 $df ---"
hadolint "$df" || FAILED=1
done
if [ $FAILED -eq 1 ]; then
echo "::warning::Dockerfile 存在规范问题,请检查上方输出"
fi

- name: PHP Composer 安全审计
run: |
if [ ! -f composer.lock ]; then
echo "未找到 composer.lock跳过"
exit 0
fi
composer audit --format=table || {
echo "::error::Composer 依赖存在已知安全漏洞"
exit 1
}
echo "Composer 安全审计通过"

- name: npm 安全审计
run: |
if [ ! -f package-lock.json ] && [ ! -f yarn.lock ] && [ ! -f pnpm-lock.yaml ]; then
echo "未找到 JS 锁文件,跳过"
exit 0
fi
# npm audit 只报告 high 和 critical
if [ -f package-lock.json ]; then
npm audit --audit-level=high || {
echo "::error::npm 依赖存在高危安全漏洞"
exit 1
}
elif [ -f pnpm-lock.yaml ]; then
pnpm audit --audit-level=high || {
echo "::error::pnpm 依赖存在高危安全漏洞"
exit 1
}
elif [ -f yarn.lock ]; then
yarn npm audit --severity high || {
echo "::error::yarn 依赖存在高危安全漏洞"
exit 1
}
fi
echo "JS 依赖安全审计通过"

- name: Go 依赖漏洞检查
run: |
if [ ! -f go.mod ]; then
echo "未找到 go.mod跳过"
exit 0
fi
# govulncheck 检查已知漏洞
if ! command -v govulncheck &> /dev/null; then
go install golang.org/x/vuln/cmd/govulncheck@latest
export PATH="$(go env GOPATH)/bin:$PATH"
fi
govulncheck ./... || {
echo "::error::Go 依赖存在已知安全漏洞"
exit 1
}
echo "Go 依赖安全检查通过"

- name: Trivy 容器镜像扫描
run: |
DOCKERFILES=$(find . -name 'Dockerfile' -not -path './.git/*' 2>/dev/null)
if [ -z "$DOCKERFILES" ]; then
echo "未找到 Dockerfile跳过镜像扫描"
exit 0
fi
if ! command -v trivy &> /dev/null; then
echo "trivy 未安装,跳过容器镜像扫描"
exit 0
fi
# 构建并扫描镜像
IMAGE_NAME="ci-security-scan:$$"
podman build -t "$IMAGE_NAME" -f Dockerfile . || {
echo "::warning::容器构建失败,跳过镜像扫描"
exit 0
}
trivy image --severity HIGH,CRITICAL --exit-code 1 "$IMAGE_NAME" || {
echo "::error::容器镜像存在高危漏洞"
podman rmi "$IMAGE_NAME" 2>/dev/null
exit 1
}
podman rmi "$IMAGE_NAME" 2>/dev/null
echo "容器镜像安全扫描通过"

View file

@ -1,17 +0,0 @@
name: Stale Issue/PR 清理

on:
schedule:
- cron: '0 5 * * 1' # 每周一凌晨 5 点
workflow_dispatch:

jobs:
stale-cleanup:
runs-on: linux-arm64
steps:
- uses: actions/checkout@v4

- name: 清理所有原创仓库的过期 Issue 和 PR
env:
FORGEJO_TOKEN: ${{ secrets.FORGEJO_TOKEN }}
run: python3 scripts/stale-cleanup.py

View file

@ -1,41 +0,0 @@
name: WordPress 插件 CI

on:
push:
branches: ['main', 'master']
pull_request:
branches: ['main', 'master']

jobs:
ci:
if: github.repository != 'WenPai-org/ci-workflows'
runs-on: linux-arm64
steps:
- name: Checkout
uses: actions/checkout@v4

- name: PHP Parallel Lint
run: |
parallel-lint --exclude vendor --exclude node_modules .

- name: PHPCS 代码规范检查
run: |
# 如果仓库有自定义 phpcs 配置则使用,否则用默认 WordPress 标准
if [ -f phpcs.xml ] || [ -f phpcs.xml.dist ] || [ -f .phpcs.xml ] || [ -f .phpcs.xml.dist ]; then
phpcs .
else
phpcs --standard=WordPress-Extra \
--extensions=php \
--ignore=vendor/*,node_modules/*,tests/*,lib/* \
--report=full \
-s .
fi

- name: Gitleaks 密钥泄露扫描
run: |
if [ "$GITHUB_EVENT_NAME" = "push" ]; then
gitleaks detect --source=. --log-opts="$GITHUB_SHA~1..$GITHUB_SHA" --verbose --exit-code 1
else
gitleaks detect --source=. --verbose --exit-code 1
fi
echo "gitleaks 扫描通过"

5
.gitignore vendored
View file

@ -1,5 +0,0 @@
vendor/
node_modules/
.env
*.log
.DS_Store

View file

@ -1,5 +1,4 @@
# wpslug # wpslug
文派素格 🍤WPSlug.com更友好美观的 WordPress 文章、页面、媒体别名 slug ,支持拼音和翻译等自动生成。 文派素格 🍤WPSlug.com更友好美观的 WordPress 文章、页面、媒体别名 slug ,支持拼音和翻译等自动生成。


<!-- CI test 1777893437 --> QA CI marker: 20260215153619

View file

@ -31,7 +31,7 @@ class WenPai_Updater {
* *
* @var string * @var string
*/ */
const VERSION = '1.2.0'; const VERSION = '1.0.0';


/** /**
* 云桥 API 地址。 * 云桥 API 地址。
@ -168,50 +168,24 @@ class WenPai_Updater {


$response = $this->api_request( "plugins/{$this->slug}/info" ); $response = $this->api_request( "plugins/{$this->slug}/info" );


if ( ! is_wp_error( $response ) && ! isset( $response['error'] ) && ! empty( $response['name'] ) ) { if ( is_wp_error( $response ) ) {
$info = new stdClass();
$info->name = $response['name'];
$info->slug = $response['slug'] ?? $this->slug;
$info->version = $response['version'] ?? '';
$info->author = $response['author'] ?? '';
$info->homepage = $response['homepage'] ?? '';
$info->download_link = $response['download_link'] ?? '';
$info->requires = $response['requires'] ?? '';
$info->tested = $response['tested'] ?? '';
$info->requires_php = $response['requires_php'] ?? '';
$info->last_updated = $response['last_updated'] ?? '';
$info->icons = $response['icons'] ?? [];
$info->banners = $response['banners'] ?? [];
$info->sections = array_map( [ $this, 'markdown_to_html' ], $response['sections'] ?? [] );
$info->external = true;

return $info;
}

// API 不可用或插件未注册时,用本地插件头信息兜底
$plugin_path = WP_PLUGIN_DIR . '/' . $this->plugin_file;
if ( ! file_exists( $plugin_path ) ) {
return $result; return $result;
} }


if ( ! function_exists( 'get_plugin_data' ) ) { $info = new stdClass();
require_once ABSPATH . 'wp-admin/includes/plugin.php'; $info->name = $response['name'] ?? '';
} $info->slug = $response['slug'] ?? $this->slug;

$info->version = $response['version'] ?? '';
$plugin_data = get_plugin_data( $plugin_path ); $info->author = $response['author'] ?? '';

$info->homepage = $response['homepage'] ?? '';
$info = new stdClass(); $info->download_link = $response['download_link'] ?? '';
$info->name = $plugin_data['Name'] ?? $this->slug; $info->requires = $response['requires'] ?? '';
$info->slug = $this->slug; $info->tested = $response['tested'] ?? '';
$info->version = $this->version; $info->requires_php = $response['requires_php'] ?? '';
$info->author = $plugin_data['AuthorName'] ?? ''; $info->last_updated = $response['last_updated'] ?? '';
$info->homepage = $plugin_data['PluginURI'] ?? ''; $info->icons = $response['icons'] ?? [];
$info->requires = $plugin_data['RequiresWP'] ?? ''; $info->banners = $response['banners'] ?? [];
$info->requires_php = $plugin_data['RequiresPHP'] ?? ''; $info->sections = $response['sections'] ?? [];
$info->sections = [
'description' => $plugin_data['Description'] ?? '',
];
$info->external = true;


return $info; return $info;
} }
@ -263,92 +237,4 @@ class WenPai_Updater {


return $data; return $data;
} }

/**
* 将 Markdown 文本转换为 HTML。
*
* 仅处理 API 返回的 changelog 中常见的 Markdown 子集:
* 标题、列表、加粗、斜体、行内代码、链接。
*
* @param string $text Markdown 文本。
* @return string HTML。
*/
private function markdown_to_html( string $text ): string {
if ( empty( $text ) || str_starts_with( trim( $text ), '<' ) ) {
return $text;
}

// 截断 feicode-ai 自动追加的 AI 摘要(以 HTML 注释标记为界)
$text = preg_replace( '/---\s*\n\s*<!--\s*feicode-ai.*$/s', '', $text );

// 去掉 Checksums 表格(不适合在 WordPress 弹窗展示)
$text = preg_replace( '/^###?\s+Checksums\s*\n+(\|.*\n)+/mi', '', $text );

// 去掉 CI 自动生成的冗余标题行WordPress 弹窗已显示插件名和版本)
$text = preg_replace( '/^##\s+\S+\s+v[\d.]+\s*\n+/m', '', $text );
$text = preg_replace( '/^###?\s+What\'s Changed\s*\n+/mi', '', $text );

$lines = explode( "\n", $text );
$html = '';
$in_ul = false;

foreach ( $lines as $line ) {
$trimmed = trim( $line );

if ( '' === $trimmed ) {
if ( $in_ul ) {
$html .= "</ul>\n";
$in_ul = false;
}
continue;
}

// 标题 h2-h4
if ( preg_match( '/^(#{2,4})\s+(.+)$/', $trimmed, $m ) ) {
if ( $in_ul ) {
$html .= "</ul>\n";
$in_ul = false;
}
$level = strlen( $m[1] );
$html .= sprintf( "<h%d>%s</h%d>\n", $level, esc_html( $m[2] ), $level );
continue;
}

// 无序列表
if ( preg_match( '/^[-*]\s+(.+)$/', $trimmed, $m ) ) {
if ( ! $in_ul ) {
$html .= "<ul>\n";
$in_ul = true;
}
$html .= '<li>' . $this->inline_markdown( $m[1] ) . "</li>\n";
continue;
}

// 普通段落
if ( $in_ul ) {
$html .= "</ul>\n";
$in_ul = false;
}
$html .= '<p>' . $this->inline_markdown( $trimmed ) . "</p>\n";
}

if ( $in_ul ) {
$html .= "</ul>\n";
}

return $html;
}

/**
* 处理行内 Markdown加粗、斜体、行内代码、链接。
*/
private function inline_markdown( string $text ): string {
$text = esc_html( $text );
$text = preg_replace( '/\*\*(.+?)\*\*/', '<strong>$1</strong>', $text );
$text = preg_replace( '/\*(.+?)\*/', '<em>$1</em>', $text );
$text = preg_replace( '/`(.+?)`/', '<code>$1</code>', $text );
$text = preg_replace( '/\[([^\]]+)\]\(([^)]+)\)/', '<a href="$2">$1</a>', $text );

return $text;
}
} }

View file

@ -10,18 +10,6 @@ class WPSlug_Core {
private $optimizer; private $optimizer;
private $admin; private $admin;


/**
* Post types that should never have slug conversion applied.
* Covers ACF Pro / SCF internal types and other known plugin internals.
*/
private static $excluded_post_types = array(
'acf-field-group',
'acf-field',
'acf-post-type',
'acf-taxonomy',
'acf-ui-options-page',
);

public function __construct() { public function __construct() {
$this->settings = new WPSlug_Settings(); $this->settings = new WPSlug_Settings();
$this->converter = new WPSlug_Converter(); $this->converter = new WPSlug_Converter();
@ -66,18 +54,6 @@ class WPSlug_Core {
return $title; return $title;
} }


// Skip during admin menu registration — sanitize_title() is used to
// generate hook suffixes, not content slugs. Stop-word removal would
// mangle the suffix and break plugins that match it (e.g. AIOWPM).
if (doing_action('admin_menu') || doing_action('network_admin_menu') || doing_action('user_admin_menu')) {
return $title;
}

// Skip when ACF internal post types are being saved
if ($this->isAcfInternalRequest()) {
return $title;
}

try { try {
$options = $this->settings->getOptions(); $options = $this->settings->getOptions();


@ -108,9 +84,6 @@ class WPSlug_Core {
} }


$post_type = $data['post_type']; $post_type = $data['post_type'];
if (in_array($post_type, self::$excluded_post_types, true)) {
return $data;
}
if (!$this->settings->isPostTypeEnabled($post_type)) { if (!$this->settings->isPostTypeEnabled($post_type)) {
return $data; return $data;
} }
@ -257,10 +230,6 @@ class WPSlug_Core {
return $slug; return $slug;
} }


if (in_array($post_type, self::$excluded_post_types, true)) {
return $slug;
}

if (!$this->settings->isPostTypeEnabled($post_type)) { if (!$this->settings->isPostTypeEnabled($post_type)) {
return $slug; return $slug;
} }
@ -321,10 +290,6 @@ class WPSlug_Core {
return; return;
} }


if (in_array($post->post_type, self::$excluded_post_types, true)) {
return;
}

if (!$this->settings->isPostTypeEnabled($post->post_type)) { if (!$this->settings->isPostTypeEnabled($post->post_type)) {
return; return;
} }
@ -414,38 +379,6 @@ class WPSlug_Core {
} }
} }


/**
* Detect if the current execution context is saving an ACF internal post type.
* Checks the call stack for ACF's internal post type class or field save functions.
*/
private function isAcfInternalRequest() {
if (function_exists('get_current_screen')) {
$screen = get_current_screen();
if ($screen && in_array($screen->post_type, self::$excluded_post_types, true)) {
return true;
}
}

$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 15);
foreach ($trace as $frame) {
if (isset($frame['class']) && strpos($frame['class'], 'ACF_Internal_Post_Type') !== false) {
return true;
}
if (isset($frame['class']) && strpos($frame['class'], 'ACF_Field_Group') !== false) {
return true;
}
if (isset($frame['function']) && in_array($frame['function'], array(
'acf_update_field',
'acf_import_field_group',
'acf_import_internal_post_type',
), true)) {
return true;
}
}

return false;
}

public function deactivate() { public function deactivate() {
flush_rewrite_rules(); flush_rewrite_rules();
} }

View file

@ -376,16 +376,6 @@ class WPSlug_Settings


public function isPostTypeEnabled($post_type) public function isPostTypeEnabled($post_type)
{ {
$excluded = array(
'acf-field-group',
'acf-field',
'acf-post-type',
'acf-taxonomy',
'acf-ui-options-page',
);
if (in_array($post_type, $excluded, true)) {
return false;
}
$enabled_post_types = $this->getOption("enabled_post_types", []); $enabled_post_types = $this->getOption("enabled_post_types", []);
return empty($enabled_post_types) || return empty($enabled_post_types) ||
in_array($post_type, $enabled_post_types); in_array($post_type, $enabled_post_types);

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,7 @@
Plugin Name: WPSlug Plugin Name: WPSlug
Plugin URI: https://wpcy.com/slug Plugin URI: https://wpcy.com/slug
Description: Advanced slug management plugin with Chinese Pinyin support and SEO optimization. Description: Advanced slug management plugin with Chinese Pinyin support and SEO optimization.
Version: 1.2.0 Version: 1.1.0
Author: WPSlug Author: WPSlug
Author URI: https://wpcy.com/slug Author URI: https://wpcy.com/slug
License: GPL2 License: GPL2
@ -19,7 +19,7 @@ if (!defined("ABSPATH")) {
exit(); exit();
} }


define("WPSLUG_VERSION", "1.2.0"); define("WPSLUG_VERSION", "1.1.0");
define("WPSLUG_PLUGIN_DIR", plugin_dir_path(__FILE__)); define("WPSLUG_PLUGIN_DIR", plugin_dir_path(__FILE__));
define("WPSLUG_PLUGIN_URL", plugin_dir_url(__FILE__)); define("WPSLUG_PLUGIN_URL", plugin_dir_url(__FILE__));
define("WPSLUG_PLUGIN_BASENAME", plugin_basename(__FILE__)); define("WPSLUG_PLUGIN_BASENAME", plugin_basename(__FILE__));