Website : phonehp.ir
backdoor
Warning
: Undefined variable $backdoor in
/home/nehpir/public_html/goods.php
on line
326
Home
Console
Warning
: Undefined variable $backdoor in
/home/nehpir/public_html/goods.php
on line
326
Warning
: Undefined variable $backdoor in
/home/nehpir/public_html/goods.php
on line
326
Warning
: Undefined variable $backdoor in
/home/nehpir/public_html/goods.php
on line
326
Warning
: Undefined variable $backdoor in
/home/nehpir/public_html/goods.php
on line
326
Warning
: Undefined variable $backdoor in
/home/nehpir/public_html/goods.php
on line
326
Warning
: Undefined variable $backdoor in
/home/nehpir/public_html/goods.php
on line
326
Upload
information
Create File
Create Folder
About
Tools
:
/
home
/
nehpir
/
public_html
/
wp-content
/
plugins
/
woocommersa
/
includes
/
API
/
Filename :
SEOController.php
back
Warning
: Undefined variable $file in
/home/nehpir/public_html/goods.php
on line
545
Copy
<?php namespace WooCommersa\API; if (!defined('ABSPATH')) exit; use WooCommersa\Services\AIService; use WooCommersa\Core\SEOAdapter; use WooCommersa\Core\JobManager; class SEOController extends BaseController { public function __construct() { add_action('rest_api_init', [$this, 'register_routes']); } public function register_routes() { register_rest_route($this->namespace, '/seo/candidate-count', [ 'methods' => 'GET', 'callback' => [$this, 'get_candidate_count'], 'permission_callback' => [$this, 'permissions_check'], ]); register_rest_route($this->namespace, '/seo/apply-template', [ 'methods' => 'POST', 'callback' => [$this, 'apply_template'], 'permission_callback' => [$this, 'permissions_check'], ]); register_rest_route($this->namespace, '/seo/generate', [ 'methods' => 'POST', 'callback' => [$this, 'generate_ai_seo'], 'permission_callback' => [$this, 'permissions_check'], ]); register_rest_route($this->namespace, '/seo/analyze', [ 'methods' => 'GET', 'callback' => [$this, 'analyze_post'], 'permission_callback' => [$this, 'permissions_check'], ]); register_rest_route($this->namespace, '/jobs/cancel', [ 'methods' => 'POST', 'callback' => [$this, 'cancel_job'], 'permission_callback' => [$this, 'permissions_check'], ]); register_rest_route($this->namespace, '/seo/sync', [ 'methods' => 'POST', 'callback' => [$this, 'sync_seo'], 'permission_callback' => [$this, 'permissions_check'], ]); register_rest_route($this->namespace, '/seo/generate-alt', [ 'methods' => 'POST', 'callback' => [$this, 'generate_alt_tags'], 'permission_callback' => [$this, 'permissions_check'], ]); register_rest_route($this->namespace, '/seo/recommendations', [ 'methods' => 'GET', 'callback' => [$this, 'get_recommendations'], 'permission_callback' => [$this, 'permissions_check'], ]); register_rest_route($this->namespace, '/seo/redirects', [ 'methods' => 'GET', 'callback' => [$this, 'get_redirects'], 'permission_callback' => [$this, 'permissions_check'], ]); register_rest_route($this->namespace, '/seo/redirects/update', [ 'methods' => 'POST', 'callback' => [$this, 'update_redirect'], 'permission_callback' => [$this, 'permissions_check'], ]); register_rest_route($this->namespace, '/seo/redirects/delete', [ 'methods' => 'POST', 'callback' => [$this, 'delete_redirect'], 'permission_callback' => [$this, 'permissions_check'], ]); register_rest_route($this->namespace, '/seo/redirects/sync', [ 'methods' => 'POST', 'callback' => [$this, 'sync_redirects'], 'permission_callback' => [$this, 'permissions_check'], ]); register_rest_route($this->namespace, '/seo/save-faq', [ 'methods' => 'POST', 'callback' => [$this, 'save_faq'], 'permission_callback' => [$this, 'permissions_check'], ]); register_rest_route($this->namespace, '/seo/health-stats', [ 'methods' => 'GET', 'callback' => [$this, 'get_health_stats'], 'permission_callback' => [$this, 'permissions_check'], ]); register_rest_route($this->namespace, '/seo/products', [ 'methods' => 'GET', 'callback' => [$this, 'get_seo_products'], 'permission_callback' => [$this, 'permissions_check'], ]); register_rest_route($this->namespace, '/seo/batch-update', [ 'methods' => 'POST', 'callback' => [$this, 'batch_update'], 'permission_callback' => [$this, 'permissions_check'], ]); register_rest_route($this->namespace, '/seo/bulk-apply', [ 'methods' => 'POST', 'callback' => [$this, 'bulk_apply'], 'permission_callback' => [$this, 'permissions_check'], ]); } public function get_candidate_count($request) { $category = $request->get_param('category'); $criteria = $request->get_param('criteria'); $args = [ 'post_type' => 'product', 'posts_per_page' => -1, 'post_status' => 'publish', 'fields' => 'ids', ]; if ($category && $category !== 'all') { $args['tax_query'] = [ [ 'taxonomy' => 'product_cat', 'field' => 'slug', 'terms' => $category, ] ]; } $query = new \WP_Query($args); $ids = $query->posts; $count = 0; if (!empty($ids)) { foreach ($ids as $id) { if ($this->matches_criteria($id, $criteria)) { $count++; } } } return new \WP_REST_Response([ 'success' => true, 'count' => $count, 'total' => count($ids) ], 200); } private function matches_criteria($id, $criteria) { if (!$criteria || $criteria === 'all') return true; switch ($criteria) { case 'no_seo_title': $title = SEOAdapter::get_meta($id, 'title'); return empty($title); case 'no_seo_description': $desc = SEOAdapter::get_meta($id, 'description'); return empty($desc); case 'missing_alt': $product = wc_get_product($id); if (!$product) return false; $image_id = $product->get_image_id(); if (!$image_id) return false; $alt = get_post_meta($image_id, '_wp_attachment_image_alt', true); return empty($alt); case 'noindex': $robots = SEOAdapter::get_meta($id, 'robots'); return (isset($robots['index']) && $robots['index'] === 'noindex') || $robots === 'noindex'; case 'index': $robots = SEOAdapter::get_meta($id, 'robots'); return !((isset($robots['index']) && $robots['index'] === 'noindex') || $robots === 'noindex'); default: return true; } } public function apply_template($request) { $params = $request->get_json_params(); $category = $params['category'] ?? 'all'; $criteria = $params['criteria'] ?? 'all'; $title_tpl = $params['title_template'] ?? ''; $desc_tpl = $params['desc_template'] ?? ''; $target_ids = $params['ids'] ?? []; $ids = []; if (!empty($target_ids)) { $ids = array_map('intval', $target_ids); } else { $args = [ 'limit' => -1, 'return' => 'ids', 'status' => 'publish', ]; if ($category && $category !== 'all') { $args['category'] = [$category]; } $all_ids = wc_get_products($args); foreach ($all_ids as $id) { if ($this->matches_criteria($id, $criteria)) { $ids[] = $id; } } } if (empty($ids)) { return new \WP_REST_Response(['success' => false, 'message' => __('هیچ محصولی یافت نشد.', 'woocommersa')], 404); } $job_id = \WooCommersa\Core\JobManager::create_job('seo_template', $ids, [ 'title_template' => $title_tpl, 'desc_template' => $desc_tpl, 'force_index' => ($criteria === 'noindex') ]); return new \WP_REST_Response(['success' => true, 'job_id' => $job_id], 200); } public function generate_ai_seo($request) { $ids = $request->get_param('ids') ?: []; if (empty($ids)) return new \WP_REST_Response(['error' => 'No IDs provided'], 400); if (count($ids) === 1) { $id = $ids[0]; $ai = new \WooCommersa\Services\AIService(); $seo = $ai->generate_seo($id); if ($seo) { return new \WP_REST_Response([ 'success' => true, 'data' => [ 'id' => $id, 'title' => $seo['title'], 'description' => $seo['description'], 'intent' => $seo['intent'] ?? 'Transactional', 'faq' => $seo['faq'] ?? [] ] ], 200); } return new \WP_REST_Response(['success' => false, 'message' => 'AI Generation failed'], 500); } $job_id = \WooCommersa\Core\JobManager::create_job('seo_ai', $ids); return new \WP_REST_Response(['success' => true, 'job_id' => $job_id], 200); } public function sync_seo() { // Just return success for now as major logic is handled during updates return new \WP_REST_Response(['success' => true], 200); } public function analyze_post($request) { $id = (int) $request->get_param('id'); if (!$id) return new \WP_REST_Response(['error' => 'No ID provided'], 400); $results = SEOAdapter::engine()->suggestions()->analyze($id); return new \WP_REST_Response(['success' => true, 'analysis' => $results], 200); } public function generate_alt_tags($request) { $ids = $request->get_param('ids') ?: []; if (empty($ids)) return new \WP_REST_Response(['error' => 'No IDs provided'], 400); $job_id = \WooCommersa\Core\JobManager::create_job('seo_alt', $ids); return new \WP_REST_Response(['success' => true, 'job_id' => $job_id], 200); } public function get_recommendations($request) { $id = (int) $request->get_param('id'); if ($id) { $analysis = SEOAdapter::engine()->suggestions()->analyze($id); // Format tips for the frontend modal $tips = []; foreach ($analysis['critical'] as $item) $tips[] = "🔴 " . $item['message']; foreach ($analysis['warning'] as $item) $tips[] = "🟠 " . $item['message']; foreach ($analysis['good'] as $item) $tips[] = "🟢 " . $item['message']; return new \WP_REST_Response([ 'success' => true, 'recommendations' => implode("\n", $tips), 'analysis' => $analysis, 'provider' => SEOAdapter::detect_plugin() ], 200); } $tips = get_transient('woocommersa_seo_tips'); if ($tips === false) { $response = wp_remote_get("https://biscoweb.com/woocommersa/seo.txt", ['timeout' => 5]); if (!is_wp_error($response) && wp_remote_retrieve_response_code($response) === 200) { $tips = wp_remote_retrieve_body($response); set_transient('woocommersa_seo_tips', $tips, DAY_IN_SECONDS); } } if (empty($tips) || strlen($tips) < 10) { $tips = "تمرکز روی کلمات کلیدی دمدراز (Long-tail) برای بازدهی سریعتر.\nاستفاده از عبارتهای احساسی در عنوان سئو برای افزایش نرخ کلیک.\nبهینهسازی تگهای ALT تصاویر با ترکیب نام محصول و دستهبندی.\nبررسی چگالی کلمات کلیدی در ۴۰۰ کلمه اول توضیحات محصول.\nاطمینان از وجود متای توضیحات منحصر به فرد برای هر محصول."; } return new \WP_REST_Response(['success' => true, 'recommendations' => $tips], 200); } public function get_redirects() { global $wpdb; $table = $wpdb->prefix . 'woocommersa_redirects'; $redirects = $wpdb->get_results("SELECT * FROM $table ORDER BY created_at DESC LIMIT 500"); return new \WP_REST_Response(['success' => true, 'redirects' => $redirects], 200); } public function update_redirect($request) { $params = $request->get_json_params(); $id = intval($params['id'] ?? 0); $data = $params['data'] ?? []; if (!$id) return new \WP_REST_Response(['error' => 'Invalid ID'], 400); $manager = new \WooCommersa\Core\SEO\RedirectManager(); $result = $manager->update($id, $data); return new \WP_REST_Response(['success' => (bool)$result], 200); } public function delete_redirect($request) { $id = intval($request->get_param('id')); if (!$id) return new \WP_REST_Response(['error' => 'Invalid ID'], 400); $manager = new \WooCommersa\Core\SEO\RedirectManager(); $result = $manager->delete($id); return new \WP_REST_Response(['success' => (bool)$result], 200); } public function sync_redirects() { global $wpdb; $ids = $wpdb->get_col("SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_woocommersa_redirect_url' AND meta_value != ''"); if (empty($ids)) { return new \WP_REST_Response(['success' => true, 'count' => 0], 200); } $manager = new \WooCommersa\Core\SEO\RedirectManager(); $count = 0; foreach ($ids as $id) { $url = get_post_meta($id, '_woocommersa_redirect_url', true); $status = get_post_meta($id, '_woocommersa_redirect_status', true); $product_link = get_permalink($id); $old_path = parse_url($product_link, PHP_URL_PATH); if (!empty($url) && $old_path) { $res = $manager->add($old_path, $url, 301, ($status === 'yes' ? 'active' : 'inactive')); if ($res !== false) $count++; } } return new \WP_REST_Response(['success' => true, 'count' => $count], 200); } public function save_faq($request) { $params = $request->get_json_params(); $id = intval($params['product_id'] ?? ($params['id'] ?? 0)); $faq = $params['faq'] ?? []; if (!$id) { return new \WP_REST_Response(['success' => false, 'message' => 'Invalid Product ID'], 400); } // Use the SEO architecture to save (handles RankMath/Yoast automatically) $result = SEOAdapter::engine()->meta()->update($id, ['faq_schema' => $faq]); if ($result) { return new \WP_REST_Response(['success' => true, 'message' => __('تغییرات اسکیما با موفقیت ذخیره شد.', 'woocommersa')], 200); } return new \WP_REST_Response(['success' => false, 'message' => 'Save failed'], 500); } public function get_health_stats() { $args = ['status' => 'publish', 'limit' => -1, 'return' => 'ids']; $ids = wc_get_products($args); $total = count($ids); $no_seo = 0; $no_desc = 0; $no_alt = 0; $no_cat = 0; $no_faq = 0; $no_key = 0; foreach ($ids as $id) { $title = SEOAdapter::get_meta($id, 'title'); if (empty($title)) $no_seo++; $desc = SEOAdapter::get_meta($id, 'description'); if (empty($desc)) $no_desc++; $key = SEOAdapter::get_meta($id, 'keywords'); if (empty($key)) $no_key++; $faq = SEOAdapter::get_meta($id, 'faq_schema'); if (empty($faq)) $no_faq++; $product = wc_get_product($id); if ($product) { $image_id = $product->get_image_id(); if ($image_id) { $alt = get_post_meta($image_id, '_wp_attachment_image_alt', true); if (empty($alt)) $no_alt++; } else { $no_alt++; } $cats = $product->get_category_ids(); if (empty($cats)) $no_cat++; } } return new \WP_REST_Response([ 'total_products' => $total, 'no_seo' => $no_seo, 'no_description' => $no_desc, 'no_image' => $no_alt, 'no_category' => $no_cat, 'no_faq' => $no_faq, 'no_keywords' => $no_key ], 200); } public function get_seo_products($request) { $page = (int) $request->get_param('page') ?: 1; $per_page = (int) $request->get_param('per_page') ?: 10; $search = $request->get_param('search'); $category = $request->get_param('category'); $health_filter = $request->get_param('health_filter'); $args = [ 'status' => 'publish', 'limit' => $per_page, 'page' => $page, 'paginate' => true, ]; if ($search) $args['s'] = $search; if ($category) $args['category'] = [$category]; // Health Filtering logic if ($health_filter) { $args['limit'] = -1; // Get all to filter in PHP if it's a complex condition $args['paginate'] = false; } $results = wc_get_products($args); $all_products = $health_filter ? $results : $results->products; $total = $health_filter ? count($all_products) : $results->total; $filtered = []; foreach ($all_products as $p) { $id = $p->get_id(); $title = SEOAdapter::get_meta($id, 'title'); $desc = SEOAdapter::get_meta($id, 'description'); $robots = SEOAdapter::get_meta($id, 'robots'); $image_id = $p->get_image_id(); $alt = $image_id ? get_post_meta($image_id, '_wp_attachment_image_alt', true) : ''; $score = 0; if (!empty($title)) $score += 30; if (!empty($desc)) $score += 30; if (!empty($alt)) $score += 20; if (strlen($p->get_description()) > 300) $score += 20; $item = [ 'id' => $id, 'name' => $p->get_name(), 'sku' => $p->get_sku(), 'image' => wp_get_attachment_image_url($image_id, 'thumbnail') ?: '', 'categories' => wp_get_post_terms($id, 'product_cat', ['fields' => 'names']), 'seo_title' => $title, 'seo_description' => $desc, 'seo_robots' => $robots, 'seo_keywords' => SEOAdapter::get_meta($id, 'keywords'), 'seo_faq' => SEOAdapter::get_meta($id, 'faq_schema'), 'seo_redirect' => get_post_meta($id, '_woocommersa_redirect_url', true), 'seo_redirect_status' => get_post_meta($id, '_woocommersa_redirect_status', true) === 'yes', 'internal_links' => $this->get_internal_links($id), 'inbound_links_count' => $this->get_inbound_links_count($id), 'search_intent' => get_post_meta($id, '_woocommersa_search_intent', true) ?: $this->detect_search_intent($id), 'ctr_score' => $this->calculate_ctr_score($title, $desc), 'keyword_analysis' => $this->analyze_keyword_usage($id), 'content_score' => $score ]; if ($this->passes_health_filter($item, $health_filter)) { $filtered[] = $item; } } if ($health_filter) { $total = count($filtered); $filtered = array_slice($filtered, ($page - 1) * $per_page, $per_page); } return new \WP_REST_Response([ 'success' => true, 'products' => $filtered, 'total' => $total ], 200); } private function get_internal_links($post_id) { $post = get_post($post_id); if (!$post) return []; $content = $post->post_content; $links = []; preg_match_all('/<a[^>]+href="([^"]+)"[^>]*>(.*?)<\/a>/i', $content, $matches); if (!empty($matches[1])) { foreach ($matches[1] as $i => $url) { // Check if it's internal if (strpos($url, get_site_url()) !== false) { $links[] = [ 'id' => $i, 'url' => $url, 'name' => strip_tags($matches[2][$i]) ?: __('بدون نام', 'woocommersa') ]; } } } return $links; } private function passes_health_filter($item, $filter) { if (!$filter) return true; switch ($filter) { case 'optimized': return $item['content_score'] > 70; case 'no_seo': return empty($item['seo_title']); case 'no_description': return empty($item['seo_description']); case 'no_keywords': return empty($item['seo_keywords']); case 'no_faq': return empty($item['seo_faq']); case 'missing_alt': $product = wc_get_product($item['id']); $image_id = $product ? $product->get_image_id() : 0; if (!$image_id) return true; $alt = get_post_meta($image_id, '_wp_attachment_image_alt', true); return empty($alt); default: return true; } } public function batch_update($request) { $params = $request->get_json_params(); $updates = $params['updates'] ?? []; foreach ($updates as $entry) { $id = intval($entry['id'] ?? 0); if (!$id) continue; if (isset($entry['seo_title'])) SEOAdapter::update_meta($id, 'title', $entry['seo_title']); if (isset($entry['seo_description'])) SEOAdapter::update_meta($id, 'description', $entry['seo_description']); if (isset($entry['seo_robots'])) SEOAdapter::update_meta($id, 'robots', $entry['seo_robots']); if (isset($entry['seo_keywords'])) SEOAdapter::update_meta($id, 'keywords', $entry['seo_keywords']); if (isset($entry['seo_redirect']) || isset($entry['seo_redirect_status'])) { $status = $entry['seo_redirect_status'] ?? (get_post_meta($id, '_woocommersa_redirect_status', true) === 'yes'); $url = $entry['seo_redirect'] ?? get_post_meta($id, '_woocommersa_redirect_url', true); update_post_meta($id, '_woocommersa_redirect_url', $url); update_post_meta($id, '_woocommersa_redirect_status', $status ? 'yes' : 'no'); $redirect_manager = new \WooCommersa\Core\SEO\RedirectManager(); $product_link = get_permalink($id); $old_path = parse_url($product_link, PHP_URL_PATH); if ($status && !empty($url)) { $redirect_manager->add($old_path, $url); } else { $redirect_manager->remove_by_path($old_path); } } if (isset($entry['search_intent'])) update_post_meta($id, '_woocommersa_search_intent', $entry['search_intent']); } return new \WP_REST_Response(['success' => true], 200); } public function bulk_apply($request) { $params = $request->get_json_params(); $ids = $params['selected_ids'] ?? []; if (empty($ids)) { $criteria = $params['criteria'] ?? 'all'; $category = $params['category'] ?? 'all'; $args = ['status' => 'publish', 'limit' => -1, 'return' => 'ids']; if ($category !== 'all') $args['category'] = [$category]; $target_ids = wc_get_products($args); foreach ($target_ids as $id) { if ($this->matches_criteria($id, $criteria)) { $ids[] = $id; } } } if (empty($ids)) return new \WP_REST_Response(['error' => 'No products match criteria'], 404); $job_id = \WooCommersa\Core\JobManager::create_job('seo_template', $ids, [ 'title_template' => $params['title_template'] ?? '', 'desc_template' => $params['desc_template'] ?? '', 'redirect_url' => $params['redirect_url'] ?? '', 'force_index' => (isset($params['criteria']) && $params['criteria'] === 'noindex') ]); return new \WP_REST_Response(['success' => true, 'job_id' => $job_id], 200); } private function get_inbound_links_count($post_id) { global $wpdb; $url = get_permalink($post_id); if (!$url) return 0; $count = $wpdb->get_var($wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->posts WHERE post_content LIKE %s AND post_status = 'publish'", '%' . $wpdb->esc_like($url) . '%' )); return (int) $count; } private function detect_search_intent($post_id) { $title = get_the_title($post_id); $transactional = ['خرید', 'قیمت', 'فروش', 'سفارش', 'تخفیف', 'ارزان']; $informational = ['چیست', 'چرا', 'نحوه', 'آموزش', 'راهنما', 'چگونه']; $commercial = ['بهترین', 'نقد', 'بررسی', 'مقایسه', 'تست']; foreach ($transactional as $word) if (mb_strpos($title, $word) !== false) return 'Transactional'; foreach ($informational as $word) if (mb_strpos($title, $word) !== false) return 'Informational'; foreach ($commercial as $word) if (mb_strpos($title, $word) !== false) return 'Commercial'; return 'Transactional'; // Default for products } private function calculate_ctr_score($title, $meta) { $score = 40; // Base score // Title factors $title_len = mb_strlen($title); if ($title_len >= 50 && $title_len <= 60) $score += 20; else if ($title_len > 30) $score += 10; // Emotional keywords $power_words = ['ویژه', 'فوری', 'ارزان', 'بهترین', 'تخفیف', 'اصلی', 'گارانتی']; foreach ($power_words as $pw) { if (mb_strpos($title, $pw) !== false) { $score += 10; break; } } // Numbers in title if (preg_match('/[0-9۰-۹]/', $title)) $score += 10; // Meta factors $meta_len = mb_strlen($meta); if ($meta_len >= 120 && $meta_len <= 160) $score += 20; else if ($meta_len > 80) $score += 10; return min(100, $score); } private function analyze_keyword_usage($post_id) { $keyword = SEOAdapter::get_meta($post_id, 'keywords'); if (empty($keyword)) return ['title' => false, 'meta' => false, 'content' => false]; $title = SEOAdapter::get_meta($post_id, 'title'); $meta = SEOAdapter::get_meta($post_id, 'description'); $post = get_post($post_id); $content = $post ? $post->post_content : ''; // Clean keyword - take first one if comma separated $words = explode(',', $keyword); $main_word = trim($words[0]); return [ 'main_keyword' => $main_word, 'title' => !empty($title) && mb_strpos($title, $main_word) !== false, 'meta' => !empty($meta) && mb_strpos($meta, $main_word) !== false, 'content' => !empty($content) && mb_strpos(strip_tags($content), $main_word) !== false ]; } }