Changeset 3470610
- Timestamp:
- 02/26/2026 06:08:35 PM (4 weeks ago)
- Location:
- greek-multi-tool
- Files:
-
- 25 edited
-
assets/screenshot-1.png (modified) (previous)
-
assets/screenshot-10.png (modified) (previous)
-
assets/screenshot-13.png (modified) (previous)
-
assets/screenshot-2.png (modified) (previous)
-
assets/screenshot-3.png (modified) (previous)
-
assets/screenshot-4.png (modified) (previous)
-
assets/screenshot-5.png (modified) (previous)
-
assets/screenshot-6.png (modified) (previous)
-
assets/screenshot-7.png (modified) (previous)
-
assets/screenshot-8.png (modified) (previous)
-
assets/screenshot-9.png (modified) (previous)
-
trunk/admin/class-grmlt-plugin-admin.php (modified) (1 diff)
-
trunk/admin/functions/function.js (modified) (1 diff)
-
trunk/admin/functions/greek-excerpts.php (modified) (5 diffs)
-
trunk/admin/functions/oldtranslator.php (modified) (2 diffs)
-
trunk/admin/functions/text-analysis.php (modified) (5 diffs)
-
trunk/admin/functions/translator-diphthongs.php (modified) (3 diffs)
-
trunk/admin/functions/translator.php (modified) (2 diffs)
-
trunk/admin/partials/settings-page/convert-old-permalinks.php (modified) (1 diff)
-
trunk/admin/partials/settings-page/grmlt-plugin-admin-main-settings-page.php (modified) (1 diff)
-
trunk/admin/partials/settings-page/permalinks-settings.php (modified) (2 diffs)
-
trunk/grmlt-plugin.php (modified) (3 diffs)
-
trunk/includes/class-grmlt-plugin-activator.php (modified) (1 diff)
-
trunk/readme.txt (modified) (11 diffs)
-
trunk/uninstall.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
greek-multi-tool/trunk/admin/class-grmlt-plugin-admin.php
r3463358 r3470610 202 202 public static function register_grmlt_option_triggers() { 203 203 204 // Check if grmlt_text is set to on ( The Greeklish Permalinks Switch in settings page ). 205 if (get_option( 'grmlt_text' ) == 'on'){ 206 207 // Check if grmlt_diphthongs is set to `Enabled` ( The Greeklish Permalinks Convert Diphthongs Switch in settings page ). 208 if (get_option( 'grmlt_diphthongs' ) == 'simple'){ 209 require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/functions/translator-diphthongs.php'; 210 add_filter('sanitize_title', 'grmlt_title_sanitizer_diphthongs_simple', 1); 204 $permalinks_on = ( get_option( 'grmlt_text' ) === 'on' ); 205 $media_on = ( get_option( 'grmlt_media_file_name' ) === 'on' ); 206 207 // Load translator files if either permalinks or media conversion is enabled 208 if ( $permalinks_on || $media_on ) { 209 require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/functions/translator-diphthongs.php'; 210 require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/functions/translator.php'; 211 } 212 213 // Register sanitize_title filters for permalink conversion. 214 // Now passes 3 accepted args so callbacks receive $raw_title and $context 215 // for ACF compatibility (skips transliteration on ACF internal post types). 216 if ( $permalinks_on ) { 217 218 if ( get_option( 'grmlt_diphthongs' ) === 'simple' ) { 219 add_filter( 'sanitize_title', 'grmlt_title_sanitizer_diphthongs_simple', 1, 3 ); 211 220 } else { 212 require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/functions/translator-diphthongs.php'; 213 add_filter('sanitize_title', 'grmlt_title_sanitizer_diphthongs_advanced', 1); 221 add_filter( 'sanitize_title', 'grmlt_title_sanitizer_diphthongs_advanced', 1, 3 ); 214 222 } 215 223 216 // Call and add_filter for title sanitization when text sanitize option is 'enabled'. 217 require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/functions/translator.php'; 218 add_filter('sanitize_title', 'grmlt_title_sanitizer', 1); 224 add_filter( 'sanitize_title', 'grmlt_title_sanitizer', 1, 3 ); 225 } 226 227 // Register sanitize_file_name filter for Greek media file name conversion on upload. 228 if ( $media_on ) { 229 add_filter( 'sanitize_file_name', 'grmlt_file_name_sanitizer', 1 ); 219 230 } 220 231 -
greek-multi-tool/trunk/admin/functions/function.js
r2812381 r3470610 84 84 85 85 jQuery( document ).ready(function($) { 86 $( ":uppercase:not(input[type!=submit], textarea, .no-remove-accents)" ).removeAcc(); 87 $( ":smallcaps:not(input[type!=submit], textarea, .no-remove-accents)" ).removeAcc(); 88 $( ".remove-accents, .remove-accents > *:not(input[type!=submit], textarea, .no-remove-accents)" ).removeAcc(); 86 /** 87 * Apply accent removal to all matching elements. 88 * Scoped to an optional root element for performance with MutationObserver. 89 */ 90 function grmltApplyAccentRemoval( root ) { 91 var $scope = root ? $( root ) : $( document ); 92 $scope.find( ":uppercase:not(input[type!=submit], textarea, .no-remove-accents)" ).removeAcc(); 93 $scope.find( ":smallcaps:not(input[type!=submit], textarea, .no-remove-accents)" ).removeAcc(); 94 $scope.find( ".remove-accents, .remove-accents > *:not(input[type!=submit], textarea, .no-remove-accents)" ).removeAcc(); 95 // Also apply to root itself if it matches 96 if ( root ) { 97 $( root ).filter( ":uppercase:not(input[type!=submit], textarea, .no-remove-accents)" ).removeAcc(); 98 $( root ).filter( ":smallcaps:not(input[type!=submit], textarea, .no-remove-accents)" ).removeAcc(); 99 } 100 } 101 102 // Initial application on page load 103 grmltApplyAccentRemoval(); 104 105 // Re-apply after any AJAX request (covers classic WP AJAX, WP Bakery AJAX loading, etc.) 89 106 $( document ).ajaxComplete(function( event, request, settings ) { 90 $( ":uppercase:not(input[type!=submit], textarea, .no-remove-accents)" ).removeAcc(); 91 $( ":smallcaps:not(input[type!=submit], textarea, .no-remove-accents)" ).removeAcc(); 92 $( ".remove-accents, .remove-accents > *:not(input[type!=submit], textarea, .no-remove-accents)" ).removeAcc(); 107 grmltApplyAccentRemoval(); 108 }); 109 110 /** 111 * MutationObserver for dynamic content loaded by page builders. 112 * 113 * WP Bakery (frontend editor), Elementor, and other page builders insert 114 * content dynamically into the DOM. The MutationObserver watches for new 115 * nodes and applies accent removal to them automatically. 116 */ 117 if ( typeof MutationObserver !== 'undefined' ) { 118 var grmltDebounceTimer = null; 119 var grmltObserver = new MutationObserver(function( mutations ) { 120 // Debounce to avoid running on every tiny DOM change 121 if ( grmltDebounceTimer ) { 122 clearTimeout( grmltDebounceTimer ); 123 } 124 grmltDebounceTimer = setTimeout(function() { 125 var hasNewContent = false; 126 for ( var i = 0; i < mutations.length; i++ ) { 127 if ( mutations[ i ].addedNodes && mutations[ i ].addedNodes.length > 0 ) { 128 for ( var j = 0; j < mutations[ i ].addedNodes.length; j++ ) { 129 var node = mutations[ i ].addedNodes[ j ]; 130 if ( node.nodeType === 1 ) { // Element nodes only 131 grmltApplyAccentRemoval( node ); 132 hasNewContent = true; 133 } 134 } 135 } 136 } 137 // Full re-scan if many nodes changed (page builder re-render) 138 if ( hasNewContent ) { 139 grmltApplyAccentRemoval(); 140 } 141 }, 100 ); 142 }); 143 144 grmltObserver.observe( document.body, { 145 childList: true, 146 subtree: true 147 }); 148 149 // Elementor frontend: also observe the preview iframe if present 150 $( window ).on( 'elementor/frontend/init', function() { 151 setTimeout(function() { 152 grmltApplyAccentRemoval(); 153 }, 500 ); 154 }); 155 } 156 157 // WP Bakery frontend editor: listen for vc-shortcode-render events 158 $( document ).on( 'vc-full-width-row vc-shortcodes-rendered', function() { 159 grmltApplyAccentRemoval(); 160 }); 161 162 // Elementor: listen for its frontend initialization events 163 $( window ).on( 'elementor/frontend/init', function() { 164 if ( typeof elementorFrontend !== 'undefined' && elementorFrontend.hooks ) { 165 elementorFrontend.hooks.addAction( 'frontend/element_ready/global', function( $element ) { 166 grmltApplyAccentRemoval( $element[0] ); 167 }); 168 } 93 169 }); 94 170 }); -
greek-multi-tool/trunk/admin/functions/greek-excerpts.php
r3255049 r3470610 144 144 * Create a Greek-friendly excerpt 145 145 * 146 * Supports content from all major page builders including WP Bakery, 147 * Elementor, Gutenberg Blocks, Divi, Beaver Builder, and Avada. 148 * 146 149 * @param string $text Text to create excerpt from 147 150 * @param int $length Optional. Length of excerpt in words. Default 55. … … 153 156 $length = get_option('grmlt_excerpt_length', 55); 154 157 } 155 158 156 159 if ($more === null) { 157 160 $more = get_option('grmlt_excerpt_more', '…'); 158 161 } 159 160 // Remove shortcodes161 $text = strip_shortcodes($text);162 163 // Remove page builder specific shortcodes164 $text = preg_replace('/\[\/?vc_.*?\]/', '', $text); // WP Bakery shortcodes165 $text = preg_replace('/\[\/?et_.*?\]/', '', $text); // Divi Builder shortcodes166 $text = preg_replace('/\[\/?fl_.*?\]/', '', $text); // Beaver Builder shortcodes167 $text = preg_replace('/\[\/?fusion_.*?\]/', '', $text); // Fusion Builder (Avada) shortcodes168 $text = preg_replace('/\[\/?elementor_.*?\]/', '', $text); // Elementor shortcodes169 170 // Remove Gutenberg blocks171 $text = excerpt_remove_blocks($text);172 173 // Remove HTML tags174 $text = wp_strip_all_tags($text);175 176 // Remove excessive whitespace177 $text = preg_replace('/\s+/', ' ',$text);178 $text = trim($text);162 163 // Use the page builder compatibility layer for clean text extraction 164 if (function_exists('grmlt_extract_clean_text')) { 165 $text = grmlt_extract_clean_text($text); 166 } else { 167 // Fallback if compat layer isn't loaded yet 168 $text = strip_shortcodes($text); 169 $text = preg_replace('/\[\/?vc_[^\]]*\]/s', '', $text); 170 $text = preg_replace('/\[\/?et_[^\]]*\]/s', '', $text); 171 $text = preg_replace('/\[\/?fl_[^\]]*\]/s', '', $text); 172 $text = preg_replace('/\[\/?fusion_[^\]]*\]/s', '', $text); 173 $text = preg_replace('/\[\/?elementor[^\]]*\]/s', '', $text); 174 $text = preg_replace('/\[\/?[^\]]+\]/', '', $text); 175 if (function_exists('excerpt_remove_blocks')) { 176 $text = excerpt_remove_blocks($text); 177 } 178 $text = wp_strip_all_tags($text); 179 $text = preg_replace('/\s+/', ' ', $text); 180 $text = trim($text); 181 } 179 182 180 183 // Detect if text contains Greek characters … … 212 215 * Override the default get_the_excerpt function with Greek-friendly version 213 216 * 217 * Supports all major page builders (WP Bakery, Elementor, Gutenberg, etc.) 218 * by using the page builder compatibility layer for content extraction. 219 * 214 220 * @param string $post_excerpt The post excerpt 215 221 * @param WP_Post $post The post object … … 221 227 return $post_excerpt; 222 228 } 223 229 224 230 // If an explicit excerpt is set, return it unchanged 225 231 if (!empty($post_excerpt)) { 226 232 return $post_excerpt; 227 233 } 228 229 // Otherwise, generate a proper Greek-friendly excerpt 234 235 // Use the page builder compat layer for best content extraction 236 if (function_exists('grmlt_get_post_clean_text') && !empty($post->ID)) { 237 $clean_text = grmlt_get_post_clean_text($post->ID); 238 if (!empty($clean_text)) { 239 // Apply excerpt length and "more" text to the clean content 240 $length = get_option('grmlt_excerpt_length', 55); 241 $more = get_option('grmlt_excerpt_more', '…'); 242 $words = preg_split('/\s+/u', $clean_text, -1, PREG_SPLIT_NO_EMPTY); 243 if (count($words) > $length) { 244 return implode(' ', array_slice($words, 0, $length)) . $more; 245 } 246 return $clean_text; 247 } 248 } 249 250 // Fallback to standard excerpt generation 230 251 return grmlt_greek_excerpt($post->post_content); 231 252 } … … 422 443 // Get post content 423 444 $post = get_post($post_id); 424 445 425 446 if (!$post) { 426 447 wp_send_json_error(__('Post not found', 'greek-multi-tool')); 427 448 } 428 429 // Generate excerpt 449 450 // Use page builder compat layer for best content extraction 451 if (function_exists('grmlt_get_post_clean_text')) { 452 $clean_text = grmlt_get_post_clean_text($post_id); 453 if (!empty($clean_text)) { 454 $more = get_option('grmlt_excerpt_more', '…'); 455 $words = preg_split('/\s+/u', $clean_text, -1, PREG_SPLIT_NO_EMPTY); 456 $actual_length = ($length !== null) ? $length : get_option('grmlt_excerpt_length', 55); 457 if (count($words) > $actual_length) { 458 $excerpt = implode(' ', array_slice($words, 0, $actual_length)) . $more; 459 } else { 460 $excerpt = $clean_text; 461 } 462 wp_send_json_success($excerpt); 463 return; 464 } 465 } 466 467 // Fallback: Generate excerpt from raw post_content 430 468 $excerpt = grmlt_greek_excerpt($post->post_content, $length); 431 469 -
greek-multi-tool/trunk/admin/functions/oldtranslator.php
r3463358 r3470610 70 70 global $wpdb; 71 71 72 // Get posts with non-Latin characters in post_name 73 $posts = $wpdb->get_results("SELECT ID, post_name, post_title FROM {$wpdb->posts} WHERE post_name REGEXP('[^A-Za-z0-9\-]+') AND post_status IN ('publish', 'future', 'private')");74 72 // Get posts with non-Latin characters in post_name (includes attachments via 'inherit' status) 73 $posts = $wpdb->get_results("SELECT ID, post_name, post_title, post_type FROM {$wpdb->posts} WHERE post_name REGEXP('[^A-Za-z0-9\-]+') AND post_status IN ('publish', 'future', 'private', 'inherit')"); 74 75 75 foreach ((array) $posts as $post) { 76 76 $sanitized_name_var = grmlt_old_sanitizer($post->post_title); 77 77 $sanitized_name = preg_replace("/[^A-Za-z0-9-]+/", "", $sanitized_name_var); 78 78 79 79 if ($post->post_name != $sanitized_name) { 80 80 // Sanitize the post data before database operation 81 81 $wpdb->update( 82 $wpdb->posts, 83 array('post_name' => $sanitized_name), 82 $wpdb->posts, 83 array('post_name' => $sanitized_name), 84 84 array('ID' => absint($post->ID)) 85 85 ); 86 86 clean_post_cache(absint($post->ID)); 87 87 88 // Check if redirect option is ON/OFF. 88 // Create 301 redirect for non-attachment post types only. 89 // Attachment URLs are served from /wp-content/uploads/ and don't use slugs in the same way. 89 90 $red_option = get_option('grmlt_redirect'); 90 if ($red_option == 1 ) {91 if ($red_option == 1 && $post->post_type !== 'attachment') { 91 92 // Prepare old permalink - sanitize 92 93 $old_permalink = $post->post_title; … … 97 98 $old_permalink = esc_url_raw(get_site_url() . "/" . $old_permalink . "/"); 98 99 $new_permalink = esc_url_raw(get_site_url() . "/" . $sanitized_name . "/"); 99 100 100 101 // Insert into database with proper sanitization 101 102 $wpdb->insert( 102 $wpdb->prefix . 'grmlt', 103 $wpdb->prefix . 'grmlt', 103 104 array( 104 105 'post_id' => absint($post->ID), -
greek-multi-tool/trunk/admin/functions/text-analysis.php
r3463358 r3470610 387 387 <script> 388 388 jQuery(document).ready(function($) { 389 /** 390 * Extract content from the current editor, supporting: 391 * - WordPress Gutenberg (Block Editor) 392 * - Classic Editor (TinyMCE / textarea) 393 * - WP Bakery Page Builder (backend & frontend) 394 * - Elementor Page Builder 395 */ 396 function grmltGetEditorContent() { 397 var content = ''; 398 399 // --- 1. Gutenberg Block Editor --- 400 if (typeof wp !== 'undefined' && wp.data && wp.data.select) { 401 try { 402 var editor = wp.data.select('core/editor'); 403 if (editor && typeof editor.getEditedPostContent === 'function') { 404 content = editor.getEditedPostContent(); 405 if (content && content.trim().length > 0) { 406 return content; 407 } 408 } 409 } catch(e) {} 410 411 // Try core/block-editor for newer WP versions 412 try { 413 var blockEditor = wp.data.select('core/block-editor'); 414 if (blockEditor && typeof blockEditor.getBlocks === 'function') { 415 var blocks = blockEditor.getBlocks(); 416 if (blocks && blocks.length > 0) { 417 content = wp.blocks.serialize(blocks); 418 if (content && content.trim().length > 0) { 419 return content; 420 } 421 } 422 } 423 } catch(e) {} 424 } 425 426 // --- 2. WP Bakery Page Builder --- 427 // WP Bakery backend editor: content is in the #content textarea (raw shortcodes) 428 // Also try WP Bakery's own content areas 429 if (typeof vc !== 'undefined' || $('#wpb_visual_composer').length > 0 || $('[data-vc-shortcode]').length > 0) { 430 // Try to get content from WP Bakery's internal storage 431 if (typeof vc !== 'undefined' && typeof vc.builder !== 'undefined') { 432 try { 433 content = vc.builder.getContent(); 434 if (content && content.trim().length > 0) { 435 return content; 436 } 437 } catch(e) {} 438 } 439 440 // Try the Visual Composer shortcode textarea 441 if ($('#wpb_vc_js_status').length && $('#wpb_vc_js_status').val() === 'true') { 442 // WP Bakery visual mode is active, get from hidden textarea 443 content = $('#content').val(); 444 if (content && content.trim().length > 0) { 445 return content; 446 } 447 } 448 449 // Try to scrape text from WP Bakery visual editor elements 450 var vcTexts = []; 451 $('.wpb_text_column .wpb_wrapper, .vc_element .wpb_wrapper, [data-vc-content] .wpb_wrapper').each(function() { 452 var txt = $(this).text().trim(); 453 if (txt.length > 0) { 454 vcTexts.push(txt); 455 } 456 }); 457 if (vcTexts.length > 0) { 458 content = vcTexts.join(' '); 459 if (content.trim().length > 0) { 460 return content; 461 } 462 } 463 } 464 465 // --- 3. Elementor --- 466 // When editing with Elementor, the main editor is not present; 467 // content comes from the server via post_id fallback. 468 // But try the preview iframe if available 469 if (typeof elementor !== 'undefined' || typeof elementorFrontend !== 'undefined') { 470 try { 471 var $previewFrame = $('#elementor-preview-iframe'); 472 if ($previewFrame.length) { 473 var iframeContent = $previewFrame.contents().find('.elementor-widget-container'); 474 if (iframeContent.length) { 475 var elTexts = []; 476 iframeContent.each(function() { 477 var txt = $(this).text().trim(); 478 if (txt.length > 0) { 479 elTexts.push(txt); 480 } 481 }); 482 if (elTexts.length > 0) { 483 content = elTexts.join(' '); 484 return content; 485 } 486 } 487 } 488 } catch(e) {} 489 } 490 491 // --- 4. Classic Editor (TinyMCE) --- 492 if (typeof tinyMCE !== 'undefined' && tinyMCE.activeEditor && !tinyMCE.activeEditor.isHidden()) { 493 content = tinyMCE.activeEditor.getContent(); 494 if (content && content.trim().length > 0) { 495 return content; 496 } 497 } 498 499 // --- 5. Plain textarea fallback --- 500 if ($('#content').length && $('#content').val()) { 501 content = $('#content').val(); 502 if (content && content.trim().length > 0) { 503 return content; 504 } 505 } 506 507 return content || ''; 508 } 509 510 /** 511 * Strip HTML tags and shortcodes from content client-side. 512 */ 513 function grmltStripContent(content) { 514 if (!content) return ''; 515 516 // Remove Gutenberg block comments 517 content = content.replace(/<!--\s*\/?wp:.*?-->/gs, ''); 518 519 // Remove shortcode tags but keep their inner content 520 // Matches [shortcode attr="val"]...[/shortcode] and standalone [shortcode /] 521 content = content.replace(/\[\/?[^\]]+\]/g, ' '); 522 523 // Strip HTML tags 524 var div = document.createElement('div'); 525 div.innerHTML = content; 526 content = div.textContent || div.innerText || ''; 527 528 // Normalize whitespace 529 content = content.replace(/\s+/g, ' ').trim(); 530 531 return content; 532 } 533 389 534 $('#grmlt-analyze-button').on('click', function() { 390 535 // Get content from the editor 391 let content = ''; 392 393 if (typeof wp !== 'undefined' && wp.data && wp.data.select('core/editor')) { 394 // For Gutenberg 395 content = wp.data.select('core/editor').getEditedPostContent(); 396 } else { 397 // For Classic Editor 398 if (typeof tinyMCE !== 'undefined' && tinyMCE.activeEditor && !tinyMCE.activeEditor.isHidden()) { 399 content = tinyMCE.activeEditor.getContent(); 400 } else { 401 content = $('#content').val(); 402 } 403 } 404 405 // Strip HTML tags 406 const div = document.createElement('div'); 407 div.innerHTML = content; 408 content = div.textContent || div.innerText || ''; 409 536 var rawContent = grmltGetEditorContent(); 537 var content = grmltStripContent(rawContent); 538 539 // Get post ID for server-side fallback 540 var postId = 0; 541 if ($('#post_ID').length) { 542 postId = $('#post_ID').val(); 543 } else if (typeof wp !== 'undefined' && wp.data && wp.data.select) { 544 try { 545 postId = wp.data.select('core/editor').getCurrentPostId(); 546 } catch(e) {} 547 } 548 410 549 // AJAX request to analyze text 411 550 $.ajax({ … … 415 554 action: 'grmlt_analyze_text', 416 555 content: content, 556 post_id: postId, 417 557 nonce: $('#grmlt_text_analysis_nonce').val() 418 558 }, … … 422 562 success: function(response) { 423 563 if (response.success) { 424 lethtml = '<div class="grmlt-analysis-stats">';564 var html = '<div class="grmlt-analysis-stats">'; 425 565 html += '<h4><?php _e('Text Statistics', 'greek-multi-tool'); ?></h4>'; 426 566 html += '<p><?php _e('Characters:', 'greek-multi-tool'); ?> ' + response.data.stats.total_chars + '</p>'; … … 429 569 html += ' (' + response.data.stats.percent_greek + '%)</p>'; 430 570 html += '<p><?php _e('Accented characters:', 'greek-multi-tool'); ?> ' + response.data.stats.accented_chars + '</p>'; 431 571 432 572 if (response.data.issues.length > 0) { 433 573 html += '<h4><?php _e('Accent Rule Issues', 'greek-multi-tool'); ?></h4>'; 434 574 html += '<ul class="grmlt-issues-list">'; 435 575 436 576 $.each(response.data.issues, function(index, issue) { 437 html += '<li>' + issue+ '</li>';577 html += '<li>' + $('<span>').text(issue).html() + '</li>'; 438 578 }); 439 579 440 580 html += '</ul>'; 441 581 } else { 442 582 html += '<p class="grmlt-no-issues"><?php _e('No accent rule issues found!', 'greek-multi-tool'); ?></p>'; 443 583 } 444 584 445 585 html += '</div>'; 446 586 $('#grmlt-analysis-results').html(html); 447 587 } else { 448 $('#grmlt-analysis-results').html('<p class="grmlt-error">' + response.data+ '</p>');588 $('#grmlt-analysis-results').html('<p class="grmlt-error">' + $('<span>').text(response.data).html() + '</p>'); 449 589 } 450 590 }, … … 461 601 /** 462 602 * AJAX handler for text analysis 603 * 604 * Accepts content from the client-side editor, but also supports a post_id 605 * fallback for page builders (WP Bakery, Elementor, etc.) where client-side 606 * content extraction may not capture the full text. 463 607 */ 464 608 function grmlt_ajax_analyze_text() { 465 609 // Check nonce for security 466 610 check_ajax_referer('grmlt_text_analysis_nonce', 'nonce'); 467 611 468 612 // Check if user has permission 469 613 if (!current_user_can('edit_posts')) { 470 614 wp_send_json_error(__('You do not have permission to perform this action.', 'greek-multi-tool')); 471 615 } 472 616 473 617 // Get content from request 474 618 $content = isset($_POST['content']) ? sanitize_textarea_field($_POST['content']) : ''; 475 619 $post_id = isset($_POST['post_id']) ? absint($_POST['post_id']) : 0; 620 621 // If content is empty or too short, try server-side extraction from the post 622 if ((empty($content) || mb_strlen($content) < 10) && $post_id > 0) { 623 // Load page builder compat if not already loaded 624 if (!function_exists('grmlt_get_post_clean_text')) { 625 require_once plugin_dir_path(__FILE__) . 'page-builder-compat.php'; 626 } 627 628 $server_content = grmlt_get_post_clean_text($post_id); 629 630 // Use server content if it's longer than client content 631 if (mb_strlen($server_content) > mb_strlen($content)) { 632 $content = $server_content; 633 } 634 } 635 636 // If content still contains shortcode-like patterns, clean them 637 if (!empty($content) && preg_match('/\[\w+/', $content)) { 638 if (!function_exists('grmlt_extract_clean_text')) { 639 require_once plugin_dir_path(__FILE__) . 'page-builder-compat.php'; 640 } 641 $content = grmlt_extract_clean_text($content); 642 } 643 476 644 if (empty($content)) { 477 wp_send_json_error(__('No content to analyze. ', 'greek-multi-tool'));478 } 479 645 wp_send_json_error(__('No content to analyze. If you are using a page builder, please save the post first and try again.', 'greek-multi-tool')); 646 } 647 480 648 // Analyze text 481 649 $results = grmlt_analyze_text($content); 482 650 483 651 // Send results 484 652 wp_send_json_success($results); -
greek-multi-tool/trunk/admin/functions/translator-diphthongs.php
r2812381 r3470610 1 <?php 2 function grmlt_title_sanitizer_diphthongs_simple($text) { 1 <?php 2 /** 3 * Diphthong transliteration functions for Greek Multi Tool. 4 * 5 * Contains both reusable helper functions for pure transliteration 6 * and sanitize_title callbacks with context checking. 7 * 8 * @since 1.0.0 9 * @since 3.3.0 Refactored for ACF compatibility and media support. 10 * @package Grmlt_Plugin 11 */ 12 13 /** 14 * Pure diphthong transliteration - simple mode. 15 * Reusable helper used by both sanitize_title callback and file name sanitizer. 16 * 17 * @since 3.3.0 18 * @param string $text The text to transliterate. 19 * @return string The transliterated text. 20 */ 21 function grmlt_apply_diphthongs_simple($text) { 3 22 4 23 $diphthongs = array( … … 29 48 } 30 49 31 function grmlt_title_sanitizer_diphthongs_advanced($text) { 50 /** 51 * Pure diphthong transliteration - advanced mode. 52 * Reusable helper used by both sanitize_title callback and file name sanitizer. 53 * 54 * @since 3.3.0 55 * @param string $text The text to transliterate. 56 * @return string The transliterated text. 57 */ 58 function grmlt_apply_diphthongs_advanced($text) { 32 59 33 60 $diphthongs = array( … … 56 83 57 84 } 85 86 /** 87 * sanitize_title callback - simple diphthong mode. 88 * Accepts all 3 sanitize_title arguments to check context and skip ACF operations. 89 * 90 * @since 1.0.0 91 * @since 3.3.0 Added $raw_title and $context parameters for ACF compatibility. 92 * 93 * @param string $text The sanitized title. 94 * @param string $raw_title The title prior to sanitization. 95 * @param string $context The context for which the title is being sanitized. 96 * @return string The transliterated text. 97 */ 98 function grmlt_title_sanitizer_diphthongs_simple($text, $raw_title = '', $context = 'save') { 99 100 // Only transliterate when saving slugs 101 if ( $context !== 'save' ) { 102 return $text; 103 } 104 105 // Skip transliteration for ACF internal operations 106 if ( grmlt_is_acf_context() ) { 107 return $text; 108 } 109 110 return grmlt_apply_diphthongs_simple($text); 111 112 } 113 114 /** 115 * sanitize_title callback - advanced diphthong mode. 116 * Accepts all 3 sanitize_title arguments to check context and skip ACF operations. 117 * 118 * @since 1.0.0 119 * @since 3.3.0 Added $raw_title and $context parameters for ACF compatibility. 120 * 121 * @param string $text The sanitized title. 122 * @param string $raw_title The title prior to sanitization. 123 * @param string $context The context for which the title is being sanitized. 124 * @return string The transliterated text. 125 */ 126 function grmlt_title_sanitizer_diphthongs_advanced($text, $raw_title = '', $context = 'save') { 127 128 // Only transliterate when saving slugs 129 if ( $context !== 'save' ) { 130 return $text; 131 } 132 133 // Skip transliteration for ACF internal operations 134 if ( grmlt_is_acf_context() ) { 135 return $text; 136 } 137 138 return grmlt_apply_diphthongs_advanced($text); 139 140 } -
greek-multi-tool/trunk/admin/functions/translator.php
r2812381 r3470610 1 <?php 2 function grmlt_title_sanitizer($text) { 3 $expressions = array( 4 5 '/[αάΑΆ]/u' => 'a', 6 '/[βΒ]/u' => 'v', 7 '/[γΓ]/u' => 'g', 8 '/[δΔ]/u' => 'd', 9 '/[εέΕΈ]/u' => 'e', 10 '/[ζΖ]/u' => 'z', 11 '/[ηήΗΉ]/u' => 'i', 12 '/[θΘ]/u' => 'th', 13 '/[ιίϊΙΊΪ]/u' => 'i', 14 '/[κΚ]/u' => 'k', 15 '/[λΛ]/u' => 'l', 16 '/[μΜ]/u' => 'm', 17 '/[νΝ]/u' => 'n', 18 '/[ξΞ]/u' => 'x', 19 '/[οόΟΌ]/u' => 'o', 20 '/[πΠ]/u' => 'p', 21 '/[ρΡ]/u' => 'r', 22 '/[σςΣ]/u' => 's', 23 '/[τΤ]/u' => 't', 24 '/[υύϋΥΎΫ]/u' => 'y', 25 '/[φΦ]/iu' => 'f', 26 '/[χΧ]/u' => 'ch', 27 '/[ψΨ]/u' => 'ps', 28 '/[ωώ]/iu' => 'o', 29 30 ); 1 <?php 2 /** 3 * Core transliteration functions for Greek Multi Tool. 4 * 5 * Contains the main Greek-to-Latin character mapping, ACF context detection, 6 * sanitize_title callback, and media file name sanitizer. 7 * 8 * @since 1.0.0 9 * @since 3.3.0 Added ACF compatibility, media file name support, and shared helpers. 10 * @package Grmlt_Plugin 11 */ 12 13 /** 14 * Check if the current context is an ACF (Advanced Custom Fields) internal operation. 15 * 16 * ACF stores field definitions as custom post types (acf-field, acf-field-group). 17 * When ACF generates field names from labels, it calls sanitize_title() internally. 18 * This function detects those contexts so transliteration can be skipped, preventing 19 * ACF field keys from being converted to Greeklish. 20 * 21 * @since 3.3.0 22 * @return bool True if we're inside an ACF operation, false otherwise. 23 */ 24 function grmlt_is_acf_context() { 25 26 // If ACF is not active, no need to check further 27 if ( ! class_exists( 'ACF' ) && ! function_exists( 'acf' ) ) { 28 return false; 29 } 30 31 // Check for ACF AJAX actions (field saving, field group updates, etc.) 32 if ( wp_doing_ajax() ) { 33 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- We're only reading, not processing 34 $action = isset( $_POST['action'] ) ? sanitize_text_field( wp_unslash( $_POST['action'] ) ) : ''; 35 if ( strpos( $action, 'acf/' ) === 0 || strpos( $action, 'acf_' ) === 0 ) { 36 return true; 37 } 38 } 39 40 // Check if the post being saved is an ACF internal post type 41 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- We're only reading, not processing 42 if ( isset( $_POST['post_type'] ) ) { 43 // phpcs:ignore WordPress.Security.NonceVerification.Missing 44 $post_type = sanitize_text_field( wp_unslash( $_POST['post_type'] ) ); 45 if ( strpos( $post_type, 'acf-' ) === 0 ) { 46 return true; 47 } 48 } 49 50 // Check the current admin screen for ACF post types 51 if ( is_admin() && function_exists( 'get_current_screen' ) ) { 52 $screen = get_current_screen(); 53 if ( $screen && ! empty( $screen->post_type ) && strpos( $screen->post_type, 'acf-' ) === 0 ) { 54 return true; 55 } 56 } 57 58 return false; 59 60 } 61 62 /** 63 * Get the Greek-to-Latin character expression map. 64 * 65 * @since 3.3.0 66 * @return array Associative array of regex patterns to Latin replacements. 67 */ 68 function grmlt_get_greek_expressions() { 69 70 return array( 71 72 '/[αάΑΆ]/u' => 'a', 73 '/[βΒ]/u' => 'v', 74 '/[γΓ]/u' => 'g', 75 '/[δΔ]/u' => 'd', 76 '/[εέΕΈ]/u' => 'e', 77 '/[ζΖ]/u' => 'z', 78 '/[ηήΗΉ]/u' => 'i', 79 '/[θΘ]/u' => 'th', 80 '/[ιίϊΙΊΪ]/u' => 'i', 81 '/[κΚ]/u' => 'k', 82 '/[λΛ]/u' => 'l', 83 '/[μΜ]/u' => 'm', 84 '/[νΝ]/u' => 'n', 85 '/[ξΞ]/u' => 'x', 86 '/[οόΟΌ]/u' => 'o', 87 '/[πΠ]/u' => 'p', 88 '/[ρΡ]/u' => 'r', 89 '/[σςΣ]/u' => 's', 90 '/[τΤ]/u' => 't', 91 '/[υύϋΥΎΫ]/u' => 'y', 92 '/[φΦ]/iu' => 'f', 93 '/[χΧ]/u' => 'ch', 94 '/[ψΨ]/u' => 'ps', 95 '/[ωώ]/iu' => 'o', 96 97 ); 98 99 } 100 101 /** 102 * Core transliteration function - converts Greek characters to Latin. 103 * This is a pure transliteration helper without any context/stop-word checks. 104 * Used by the file name sanitizer and can be reused by other features. 105 * 106 * @since 3.3.0 107 * @param string $text The text to transliterate. 108 * @return string The transliterated text. 109 */ 110 function grmlt_transliterate_greek($text) { 111 112 // Apply diphthongs first (based on settings) 113 $diphthong_mode = get_option( 'grmlt_diphthongs' ); 114 if ( $diphthong_mode === 'simple' ) { 115 $text = grmlt_apply_diphthongs_simple( $text ); 116 } else { 117 $text = grmlt_apply_diphthongs_advanced( $text ); 118 } 119 120 // Apply individual character transliteration 121 $expressions = grmlt_get_greek_expressions(); 122 $text = preg_replace( array_keys($expressions), array_values($expressions), $text ); 123 124 return $text; 125 126 } 127 128 /** 129 * sanitize_title callback - main Greek-to-Latin character conversion. 130 * Processes individual Greek characters after diphthongs have been handled. 131 * 132 * @since 1.0.0 133 * @since 3.3.0 Added $raw_title and $context parameters for ACF compatibility. 134 * 135 * @param string $text The sanitized title. 136 * @param string $raw_title The title prior to sanitization. 137 * @param string $context The context for which the title is being sanitized. 138 * @return string The transliterated text. 139 */ 140 function grmlt_title_sanitizer($text, $raw_title = '', $context = 'save') { 141 142 // Only transliterate when saving slugs, not for display or query contexts 143 if ( $context !== 'save' ) { 144 return $text; 145 } 146 147 // Skip transliteration for ACF internal operations 148 if ( grmlt_is_acf_context() ) { 149 return $text; 150 } 151 152 $expressions = grmlt_get_greek_expressions(); 31 153 32 154 // Stop Words functionality … … 50 172 51 173 return $text; 52 53 } 174 175 } 176 177 /** 178 * sanitize_file_name callback - converts Greek characters in uploaded media file names. 179 * Only processes the file name portion (not the extension). 180 * 181 * @since 3.3.0 182 * @param string $filename The file name to sanitize. 183 * @return string The sanitized file name with Greek characters converted to Latin. 184 */ 185 function grmlt_file_name_sanitizer($filename) { 186 187 // Separate file name and extension 188 $file_info = pathinfo( $filename ); 189 $name = isset( $file_info['filename'] ) ? $file_info['filename'] : ''; 190 $ext = isset( $file_info['extension'] ) ? '.' . $file_info['extension'] : ''; 191 192 // Only process if the name contains Greek characters 193 if ( ! preg_match( '/[\x{0370}-\x{03FF}\x{1F00}-\x{1FFF}]/u', $name ) ) { 194 return $filename; 195 } 196 197 // Apply full Greek-to-Latin transliteration (diphthongs + individual characters) 198 $name = grmlt_transliterate_greek( $name ); 199 200 return $name . $ext; 201 202 } -
greek-multi-tool/trunk/admin/partials/settings-page/convert-old-permalinks.php
r3463358 r3470610 4 4 <hr> 5 5 <strong class="mb-0"><?php esc_html_e( 'Convert All Old Permalinks', 'greek-multi-tool' ); ?></strong> 6 <p><?php esc_html_e( 'Press the button bel low to initialize the conversion of all old permalinks', 'greek-multi-tool' ); ?></p>6 <p><?php esc_html_e( 'Press the button below to initialize the conversion of all old permalinks. This includes posts, pages, custom post types, media/attachment slugs, and taxonomy terms.', 'greek-multi-tool' ); ?></p> 7 7 <div class="mt-3"> 8 8 <form method="post"> -
greek-multi-tool/trunk/admin/partials/settings-page/grmlt-plugin-admin-main-settings-page.php
r3463358 r3470610 56 56 'grmlt_settings', // settings group name 57 57 'grmlt_redirect', // option name 58 'sanitize_text_field' // sanitization function 59 ); 60 61 // It registers settings for Media File Name Conversion. 62 register_setting( 63 'grmlt_settings', // settings group name 64 'grmlt_media_file_name', // option name 58 65 'sanitize_text_field' // sanitization function 59 66 ); -
greek-multi-tool/trunk/admin/partials/settings-page/permalinks-settings.php
r2972131 r3470610 17 17 <div class="col"> 18 18 <strong class="mb-0"><?php _e('Enable Greeklish Permalinks Convert: ', 'greek-multi-tool') ?></strong> 19 <p class="text-muted mb-0"><?php _e('Automatically convert the greek characters to latin in all permalinks in posts, pages, custom post type and terms.', 'greek-multi-tool') ?></p>19 <p class="text-muted mb-0"><?php _e('Automatically convert the greek characters to latin in all permalinks in posts, pages, custom post types, media attachments and terms. Fully compatible with ACF (Advanced Custom Fields).', 'greek-multi-tool') ?></p> 20 20 </div> 21 21 <div class="col-auto"> … … 123 123 </div> 124 124 125 <!-- MEDIA FILE NAME CONVERSION --> 126 <?php 127 $grmlt_media_file_name = get_option( 'grmlt_media_file_name' ); 128 if ( $grmlt_media_file_name == 'on' ){ 129 $grmlt_media_file_name = true; 130 } 131 ?> 132 133 <hr class="my-4" /> 134 <strong class="mb-0"><?php _e('Media File Name Conversion', 'greek-multi-tool'); ?></strong> 135 <p><?php _e('Convert Greek characters in media file names to Latin during upload', 'greek-multi-tool'); ?></p> 136 <div class="list-group mb-5 shadow"> 137 <div class="list-group-item"> 138 <div class="row align-items-center"> 139 <div class="col"> 140 <strong class="mb-0"><?php _e('Enable Media File Name Conversion: ', 'greek-multi-tool'); ?></strong> 141 <p class="text-muted mb-0"><?php _e('Automatically convert Greek characters in uploaded media file names (images, documents, etc.) to clean, SEO-friendly Latin equivalents. For example "φωτογραφία.jpg" becomes "fotografia.jpg".', 'greek-multi-tool'); ?></p> 142 </div> 143 <div class="col-auto"> 144 <div class="custom-control custom-switch"> 145 <label class="switch"> 146 <input type="checkbox" class="custom-control-input" id="grmlt_media_file_name" name="grmlt_media_file_name" <?php echo checked( $grmlt_media_file_name, 1, 0 ); ?> /> 147 <span class="slider round"></span> 148 </label> 149 </div> 150 </div> 151 </div> 152 </div> 153 </div> 154 125 155 <!-- STOPWORDS START --> 126 127 <?php 156 157 <?php 128 158 $textarea_stwords = get_option( 'grmlt_stwords' ); 129 159 ?> -
greek-multi-tool/trunk/grmlt-plugin.php
r3463358 r3470610 8 8 * Plugin Name: Greek Multi Tool 9 9 * Plugin URI: https://bigdrop.gr/greek-multi-tool 10 * Description: Th is plugin provides a handful of tools and key functionalities to simplify and fix the greek language used in your webpage. For example it change the greek character urls to latin, remove the uppercase accents.11 * Version: 3. 2.010 * Description: The comprehensive WordPress plugin for Greek websites. Converts Greek URLs and media file names to SEO-friendly Latin, removes uppercase accents, enhances search, localizes dates, and much more. Fully compatible with ACF, WooCommerce, and all major plugins. 11 * Version: 3.3.0 12 12 * Author: BigDrop.gr 13 13 * Author URI: https://bigdrop.gr … … 29 29 * Currently plugin version. 30 30 */ 31 define( 'GRMLT_PLUGIN_VERSION', '3. 2.0' );31 define( 'GRMLT_PLUGIN_VERSION', '3.3.0' ); 32 32 33 33 /** … … 204 204 // Removed: add_action('wp_ajax_nopriv_grmlt_database_301_redirect_edit_handler', 'grmlt_database_301_redirect_edit_handler'); 205 205 206 // Load the Page Builder Compatibility Layer (WP Bakery, Elementor, Gutenberg, Yoast SEO) 207 require_once plugin_dir_path(__FILE__) . 'admin/functions/page-builder-compat.php'; 208 206 209 // Load the Greek Text Analysis functionality 207 210 if (is_admin()) { -
greek-multi-tool/trunk/includes/class-grmlt-plugin-activator.php
r2921021 r3470610 44 44 add_option('grmlt_redirect', 1); 45 45 46 // Media File Name Conversion Option 47 add_option('grmlt_media_file_name', 'on'); 48 46 49 // flush rewrite rules 47 50 flush_rewrite_rules(); -
greek-multi-tool/trunk/readme.txt
r3463358 r3470610 5 5 Tags: greek, greeklish, permalinks, accent remover, seo 6 6 Requires at least: 6.2 7 Stable tag: 3. 2.07 Stable tag: 3.3.0 8 8 Tested up to: 6.9.1 9 9 Requires PHP: 7.4 … … 11 11 License URI: http://www.gnu.org/licenses/gpl-2.0.html 12 12 13 The comprehensive WordPress plugin for Greek websites - fixes permalinks, handles accents, enhances search, localizes dates and more!13 The comprehensive WordPress plugin for Greek websites - fixes permalinks, converts media file names, handles accents, enhances search, localizes dates and more! Fully compatible with WP Bakery, Elementor, Gutenberg, and Yoast SEO. 14 14 15 15 == Description == 16 **Greek Multi Tool 3. 0** transforms how WordPress handles the Greek language. This all-in-one solution tackles every Greek-specific challenge your website faces - from URL structureto search functionality to content optimization.16 **Greek Multi Tool 3.3** transforms how WordPress handles the Greek language. This all-in-one solution tackles every Greek-specific challenge your website faces - from URL structure to media file names to search functionality to content optimization. 17 17 18 18 Our plugin is meticulously designed for Greek website owners who need professional-grade tools that understand the unique characteristics of the Greek language. Whether you're running a blog, business site, or e-commerce store, Greek Multi Tool solves problems other plugins can't even detect. 19 19 20 = Full Page Builder & SEO Plugin Compatibility = 21 22 Greek Multi Tool works seamlessly with the most popular WordPress page builders and SEO plugins: 23 24 * **WP Bakery Page Builder** - Full compatibility. Text analysis, excerpt generation, uppercase accent removal, and all other features work correctly with WP Bakery content blocks (vc_column_text, vc_row, etc.). Content is properly extracted from WP Bakery shortcodes for analysis and SEO. 25 * **Elementor** - Full compatibility. The plugin reads Elementor widget data directly from post meta, ensuring text analysis and excerpt generation capture all your content - including text editors, headings, tabs, accordions, and other Elementor widgets. 26 * **WordPress Gutenberg (Block Editor)** - Full compatibility. All block types are properly parsed and their content extracted for analysis, excerpt generation, and search. 27 * **WordPress Classic Editor** - Full compatibility. Works with both TinyMCE visual and text modes. 28 * **Yoast SEO** - Full compatibility. Greek Multi Tool provides clean, rendered content to Yoast's analysis engine when page builder shortcodes are detected, ensuring Yoast can properly analyze your Greek content for SEO optimization. 29 * **Rank Math & All in One SEO** - Compatible. Uses standard WordPress hooks that work alongside all major SEO plugins. 30 * **Divi Builder, Beaver Builder, Avada/Fusion Builder** - Compatible. Page builder shortcodes are properly stripped for text analysis and excerpt generation. 31 20 32 = Why Greek Multi Tool Is Essential for Your Greek Website = 21 33 22 34 * **Solve Greek URL Problems Once and For All** - Convert complicated Greek character URLs to clean, SEO-friendly Latin permalinks automatically 23 * **Enhance Greek Content SEO** - Our specialized tools ensure search engines properly understand and index your Greek content 24 * **Create Professional Greek Typography** - Remove unsightly uppercase accents and ensure consistent, beautiful Greek text display 35 * **Clean Up Greek Media File Names** - Automatically convert Greek file names during upload so your images and documents have proper Latin file names for maximum compatibility and SEO 36 * **Full ACF Compatibility** - Our smart context-aware transliteration knows when to convert and when to leave things alone, so Advanced Custom Fields and other plugins work perfectly alongside 37 * **Works With Any Page Builder** - Text analysis, excerpt generation, uppercase accent removal, and search all work perfectly whether you build pages with WP Bakery, Elementor, Gutenberg, or the Classic Editor 38 * **Enhance Greek Content SEO** - Our specialized tools ensure search engines properly understand and index your Greek content. Provides clean text to Yoast SEO for accurate analysis of page builder content 39 * **Create Professional Greek Typography** - Remove unsightly uppercase accents and ensure consistent, beautiful Greek text display, even on dynamically loaded page builder content 25 40 * **Boost Greek Search Accuracy** - Improve internal search with accent-insensitive, diphthong-aware algorithms built specifically for Greek 26 41 * **Display Proper Greek Dates** - Show dates in proper Greek format with correct month and day names 27 * **Generate Perfect Greek Excerpts** - Create proper excerpts that respect Greek word boundaries and linguistic rules 28 * **Analyze Greek Text Quality** - Check for proper accent usage and text readability with our Greek-specific analysis tools 42 * **Generate Perfect Greek Excerpts** - Create proper excerpts that respect Greek word boundaries and linguistic rules, with full support for extracting text from WP Bakery, Elementor, and Gutenberg content 43 * **Analyze Greek Text Quality** - Check for proper accent usage and text readability with our Greek-specific analysis tools that understand page builder content 29 44 30 45 Unlike generic WordPress plugins, Greek Multi Tool was built from the ground up specifically for Greek language websites, addressing peculiarities and challenges that non-specialized tools simply can't handle. … … 57 72 15. **Added Toggle Control for enabling/disabling Greek Text Analysis** - Analyze your content for proper Greek accent rules with easy on/off control. Ensure linguistic correctness with just a click. 58 73 74 = New in Version 3.3.0 = 75 16. **Greek Media File Name Conversion** - Automatically convert Greek characters in uploaded media file names (images, documents, PDFs, etc.) to clean, SEO-friendly Latin equivalents during upload. No more broken image URLs or encoding headaches - "φωτογραφία-προϊόντος.jpg" becomes "fotografia-proiontos.jpg" automatically. 76 17. **ACF (Advanced Custom Fields) Compatibility Fix** - Our transliteration engine is now context-aware. It intelligently detects when Advanced Custom Fields is generating internal field names and keys, and skips transliteration to prevent ACF field corruption. Your ACF field definitions stay exactly as they should be. 77 18. **Attachment Slug Conversion** - Media attachment slugs (URLs) are now automatically converted to Latin, just like posts and pages. This applies both on new uploads and through the bulk "Convert Old Permalinks" tool which now includes attachments and media items. 78 59 79 == Compatibility == 60 Greek Multi Tool is compatible with: 61 * WordPress core (tested up to 6.7.2) 62 * WooCommerce 63 * Major SEO plugins (Yoast SEO, Rank Math, All in One SEO) 64 * Popular page builders (Elementor, Gutenberg, WP Bakery) 65 * Most WordPress themes 80 81 = Page Builders - Full Support = 82 Greek Multi Tool provides deep, tested compatibility with all major page builders. Every feature of the plugin - text analysis, excerpt generation, uppercase accent removal, search, and permalink conversion - works correctly regardless of which page builder you use: 83 84 * **WP Bakery Page Builder (Visual Composer)** - Full support. The plugin extracts text content from all WP Bakery elements (vc_column_text, vc_row, custom text blocks, etc.) both client-side and server-side. If client-side extraction isn't possible (e.g., WP Bakery's backend editor mode), the plugin automatically falls back to server-side content extraction from the saved post. The uppercase accent remover also works on WP Bakery's dynamically rendered frontend content. 85 * **Elementor** - Full support. The plugin reads Elementor's widget data directly from post meta (_elementor_data), extracting text from all widget types including text editors, headings, tabs, accordions, testimonials, and more. Accent removal works on Elementor's frontend-rendered elements via MutationObserver. 86 * **WordPress Gutenberg (Block Editor)** - Full support. Block content is properly parsed using WordPress core functions (excerpt_remove_blocks) and the Gutenberg data API. 87 * **WordPress Classic Editor** - Full support. Works with TinyMCE visual mode and plain text mode. 88 * **Divi Builder** - Compatible. Divi shortcodes (et_*) are properly stripped for content extraction. 89 * **Beaver Builder** - Compatible. Beaver Builder shortcodes (fl_*) are properly handled. 90 * **Avada / Fusion Builder** - Compatible. Fusion shortcodes (fusion_*) are properly handled. 91 92 = SEO Plugins = 93 * **Yoast SEO** - Full support. Greek Multi Tool filters content through Yoast's analysis hooks (wpseo_pre_analysis_post_content), providing clean rendered text when page builder shortcodes are detected. This ensures Yoast can accurately analyze your Greek content for readability and SEO, even when using WP Bakery or other shortcode-based builders. 94 * **Rank Math** - Compatible. Uses standard WordPress hooks. 95 * **All in One SEO (AIOSEO)** - Compatible. Uses standard WordPress hooks. 96 97 = Other Plugins = 98 * **WordPress core** (tested up to 6.9.1) 99 * **WooCommerce** - Full support for product permalinks, search, and media 100 * **Advanced Custom Fields (ACF)** - Full compatibility since v3.3.0 with context-aware transliteration 66 101 67 102 The plugin has been extensively tested for compatibility issues and will not conflict with other well-coded plugins. … … 99 134 Absolutely! Greek Multi Tool seamlessly integrates with WooCommerce to handle Greek permalinks, accents, and all other features on your product pages. 100 135 136 = Does this plugin work with ACF (Advanced Custom Fields)? = 137 Yes! Since version 3.3.0, Greek Multi Tool is fully compatible with ACF. Our context-aware transliteration engine automatically detects ACF internal operations and skips transliteration, so your field names, keys, and definitions remain untouched. 138 139 = Does it convert media/image file names? = 140 Yes! Since version 3.3.0, the plugin can automatically convert Greek characters in media file names during upload. Enable the "Media File Name Conversion" toggle in the Permalink Settings tab. For example, "εικόνα-προϊόντος.jpg" becomes "eikona-proiontos.jpg" automatically. 141 142 = Does it convert attachment (media) slugs? = 143 Yes! Media attachment slugs are automatically converted to Latin, just like regular posts and pages. The bulk "Convert Old Permalinks" tool also includes existing media attachments. 144 101 145 = Will this plugin slow down my website? = 102 146 No. Greek Multi Tool is built with performance in mind, using efficient code that makes minimal database queries. The impact on site speed is negligible. 103 147 104 148 = How do I convert old permalinks? = 105 Simply navigate to Greek Multi Tool → Convert Old Permalinks in your WordPress dashboard and click the "CONVERT" button. The plugin handles everything automatically, including setting up proper 301 redirects.149 Simply navigate to Greek Multi Tool → Convert Old Permalinks in your WordPress dashboard and click the "CONVERT" button. The plugin handles everything automatically, including posts, pages, custom post types, media attachments, taxonomy terms, and setting up proper 301 redirects. 106 150 107 151 = Will this break my SEO? = … … 111 155 Our plugin implements specialized search algorithms that understand Greek linguistic patterns, including handling accented characters, diphthongs, and various word forms. This dramatically improves the accuracy of internal WordPress searches. 112 156 113 = Is the Text Analysis tool compatible with Gutenberg and Classic Editor? = 114 Yes, our Text Analysis tool works perfectly with both Gutenberg and Classic Editor. 157 = Does this plugin work with WP Bakery Page Builder? = 158 Yes! Greek Multi Tool is fully compatible with WP Bakery (Visual Composer). All features work correctly - text analysis extracts content from WP Bakery text blocks, excerpt generation properly handles vc_ shortcodes, and the uppercase accent remover works on WP Bakery's dynamically loaded frontend content. If you had issues with "No content to analyze" when using WP Bakery text blocks, this has been resolved with the page builder compatibility layer. 159 160 = Does this plugin work with Elementor? = 161 Yes! Full Elementor support is included. The plugin reads Elementor widget data directly from post meta to extract text content from all widget types. Text analysis, excerpt generation, and all other features work perfectly with Elementor-built pages. 162 163 = Is the Text Analysis tool compatible with page builders? = 164 Yes! The Text Analysis tool works with all major editors and page builders including WordPress Gutenberg (Block Editor), Classic Editor (TinyMCE), WP Bakery Page Builder, and Elementor. The plugin uses multiple content extraction strategies and includes a server-side fallback that reads saved post content when client-side extraction isn't possible. 165 166 = Does this plugin work with Yoast SEO? = 167 Yes! Greek Multi Tool enhances Yoast SEO compatibility by providing clean, rendered text content to Yoast's analysis engine. When your content uses page builder shortcodes (WP Bakery, Divi, etc.), Yoast may not be able to analyze the raw shortcode content properly. Greek Multi Tool intercepts Yoast's content analysis and provides the fully rendered, clean text for accurate SEO analysis of your Greek content. 115 168 116 169 = What PHP version do I need? = … … 139 192 140 193 == Changelog == 194 = 3.3.0 = 195 * **New Feature**: Greek Media File Name Conversion - Automatically convert Greek characters in uploaded media file names (images, documents, etc.) to SEO-friendly Latin equivalents during upload 196 * **New Feature**: Attachment Slug Conversion - Media attachment slugs are now converted to Latin both automatically on upload and via the bulk "Convert Old Permalinks" tool 197 * **New Feature**: Page Builder Compatibility Layer - New shared content extraction engine that properly handles content from WP Bakery, Elementor, Gutenberg, Divi, Beaver Builder, and Avada/Fusion Builder 198 * **Bug Fix**: ACF (Advanced Custom Fields) Compatibility - Transliteration engine is now context-aware and skips ACF internal operations, preventing field name/key corruption (e.g., 'acf-data-weight' no longer becomes 'acf-dedomena-varos') 199 * **Bug Fix**: Text Analysis now works with WP Bakery Page Builder - Fixed "No content to analyze" error when content is inside WP Bakery text blocks. The plugin now uses multiple content extraction strategies (WP Bakery JS API, visual editor scraping, hidden textarea) with an automatic server-side fallback 200 * **Bug Fix**: Text Analysis now works with Elementor - Content is extracted directly from Elementor's widget data stored in post meta 201 * **Improvement**: Excerpt generation now uses the page builder compatibility layer to extract clean text from any page builder content, including Elementor widget data 202 * **Improvement**: Uppercase accent remover now uses MutationObserver for dynamically loaded content from page builders (WP Bakery frontend editor, Elementor frontend rendering) 203 * **Improvement**: Uppercase accent remover listens for WP Bakery and Elementor frontend events to apply accent removal on newly rendered content 204 * **Improvement**: sanitize_title callbacks now accept all 3 WordPress filter arguments ($title, $raw_title, $context) and only run in 'save' context, preventing unintended transliteration during display and query operations 205 * **Improvement**: Bulk "Convert Old Permalinks" now includes media attachments (post_status 'inherit') alongside posts, pages, and custom post types 206 * **Improvement**: Translator functions refactored with shared helper functions (grmlt_get_greek_expressions, grmlt_transliterate_greek, grmlt_apply_diphthongs_simple/advanced) for better code reuse and maintainability 207 * **Improvement**: Smart 301 redirect creation that skips attachments (whose URLs are served from /wp-content/uploads/ and don't use slugs in the same way) 208 * **Compatibility**: Full WP Bakery Page Builder support - text analysis, excerpt generation, uppercase accent removal, and content extraction all work with WP Bakery elements 209 * **Compatibility**: Full Elementor support - reads Elementor widget data directly from post meta for comprehensive content extraction 210 * **Compatibility**: Full Gutenberg Block Editor support - proper block parsing via WordPress core functions 211 * **Compatibility**: Yoast SEO integration - provides clean rendered content to Yoast's analysis engine via wpseo_pre_analysis_post_content filter, ensuring accurate SEO analysis of page builder content 212 * **Compatibility**: Full ACF (Advanced Custom Fields) compatibility - detects ACF AJAX actions, ACF post types, and ACF admin screens 213 * **Compatibility**: Updated plugin description to reflect all current features 214 141 215 = 3.2.0 = 142 216 * **Critical Fix**: Fixed 301 redirect feature not working (redirect was hooked incorrectly to `init` inside an `init` callback and never fired) … … 199 273 * Global 301 Redirect Error on database record fixed. 200 274 201 = 2.1.6 = 275 = 2.1.6 = 202 276 * Added new list for existing 301 redirections made by the plugin where you can edit/delete them. 203 277 * Fixed where sometimes the plugin wouldn't automatically turn text transliteration on upon activation. … … 217 291 218 292 = 2.1.2 = 219 * Fixed the issue with the convertion of old URLs. 293 * Fixed the issue with the convertion of old URLs. 220 294 * If you are facing any error 404 with mass converted old URLs, please visit the Admin > Greek Multi Tool > Convert Old Permalinks and hit the Convert Button. 221 295 … … 250 324 * Minor bug fixes 251 325 252 = 1.2.1 = 326 = 1.2.1 = 253 327 * Minor bug fixes 254 328 … … 266 340 267 341 = 1.0.4 = 268 * Add the ability to choose how to save the diphthongs 342 * Add the ability to choose how to save the diphthongs 269 343 270 344 = 1.0.3 = 271 * Minor fixes on the settings page 345 * Minor fixes on the settings page 272 346 273 347 = 1.0.2 = 274 * Settings page redesign 348 * Settings page redesign 275 349 276 350 = 1.0.1 = … … 279 353 280 354 = 1.0.0 = 281 * Plugin released. 355 * Plugin released. 282 356 283 357 == Upgrade Notice == 358 = 3.3.0 = 359 New features: Automatic Greek media file name conversion on upload, attachment slug conversion, and full ACF compatibility. Full page builder support: text analysis, excerpts, and accent removal now work perfectly with WP Bakery, Elementor, and Gutenberg. Yoast SEO integration provides clean content for accurate SEO analysis. Recommended update for all Greek websites! 360 284 361 = 3.2.0 = 285 362 Critical security and bug fix release. Fixes 301 redirects not working, XSS vulnerabilities, SQL injection risks, and PHP 8.2+ compatibility issues. All users should update immediately. -
greek-multi-tool/trunk/uninstall.php
r3463358 r3470610 28 28 delete_option( 'grmlt_uar_js' ); 29 29 delete_option( 'grmlt_redirect' ); 30 delete_option( 'grmlt_media_file_name' ); 30 31 delete_option( 'grmlt_enhance_search' ); 31 32 delete_option( 'grmlt_accent_insensitive_search' );
Note: See TracChangeset
for help on using the changeset viewer.