PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 1.0.1
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v1.0.1
2.7.0 2.6.0 2.5.0 2.4.0 2.3.0 2.2.0 2.1.1 2.1.0 2.0.2 2.0.1 2.0.0 1.32.0 1.31.0 1.30.0 1.29.0 1.28.0 1.27.0 1.26.0 1.25.0 trunk 1.0.0 1.0.1 1.0.2 1.1.0 1.10.0 All 48 releases
thinkrank / includes / class-autoloader.php

class-autoloader.php in ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO 1.0.1, at includes/class-autoloader.php

197 lines 5.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Autoloader Class
4 *
5 * PSR-4 compliant autoloader for ThinkRank plugin
6 *
7 * @package ThinkRank\Core
8 * @since 1.0.0
9 */
10
11 declare(strict_types=1);
12
13 namespace ThinkRank\Core;
14
15 // Prevent direct access
16 if (!defined('ABSPATH')) {
17 exit;
18 }
19
20 /**
21 * Autoloader Class
22 *
23 * Handles automatic loading of plugin classes following PSR-4 standard
24 * Single Responsibility: Only handles class loading
25 *
26 * @since 1.0.0
27 */
28 class Autoloader {
29
30 /**
31 * Namespace prefix
32 *
33 * @var string
34 */
35 private const NAMESPACE_PREFIX = 'ThinkRank\\';
36
37 /**
38 * Base directory for the namespace prefix
39 *
40 * @var string
41 */
42 private string $base_dir;
43
44 /**
45 * Class map for faster loading
46 *
47 * @var array
48 */
49 private static array $class_map = [];
50
51 /**
52 * Constructor
53 */
54 public function __construct() {
55 $this->base_dir = THINKRANK_PLUGIN_DIR . 'includes/';
56 }
57
58 /**
59 * Register autoloader
60 *
61 * @return void
62 */
63 public static function register(): void {
64 $autoloader = new self();
65 spl_autoload_register([$autoloader, 'load_class']);
66 }
67
68 /**
69 * Load class file
70 *
71 * @param string $class_name Fully qualified class name
72 * @return bool True if file was loaded, false otherwise
73 */
74 public function load_class(string $class_name): bool {
75 // Check if class uses our namespace
76 if (strpos($class_name, self::NAMESPACE_PREFIX) !== 0) {
77 return false;
78 }
79
80 // Check class map first for performance
81 if (isset(self::$class_map[$class_name])) {
82 $file = self::$class_map[$class_name];
83 if (file_exists($file)) {
84 require_once $file;
85 return true;
86 }
87 }
88
89 // Get relative class name
90 $relative_class = substr($class_name, strlen(self::NAMESPACE_PREFIX));
91
92 // Convert namespace to file path
93 $file_path = $this->get_file_path($relative_class);
94
95 // Load file if it exists
96 if (file_exists($file_path)) {
97 require_once $file_path;
98
99 // Cache successful loads
100 self::$class_map[$class_name] = $file_path;
101
102 return true;
103 }
104
105 return false;
106 }
107
108 /**
109 * Convert class name to file path
110 *
111 * @param string $relative_class Relative class name
112 * @return string File path
113 */
114 private function get_file_path(string $relative_class): string {
115 // Replace namespace separators with directory separators
116 $file_path = str_replace('\\', DIRECTORY_SEPARATOR, $relative_class);
117
118 // Convert to lowercase and add class- prefix for WordPress convention
119 $parts = explode(DIRECTORY_SEPARATOR, $file_path);
120 $class_name = array_pop($parts);
121
122 // Handle special cases for known acronyms/brands
123 $special_cases = [
124 'OpenAI_Client' => 'openai-client',
125 'Claude_Client' => 'claude-client',
126 'Gemini_Client' => 'gemini-client',
127 'Analytics_Endpoint' => 'analytics-endpoint',
128 'SEO_Manager' => 'seo-manager',
129 'SEO_Plugin_Detector' => 'seo-plugin-detector',
130 'SEO_Notice' => 'seo-notice',
131 'LLMs_Txt_Endpoint' => 'llms-txt-endpoint',
132 'LLMs_Txt_Manager' => 'llms-txt-manager',
133 'Prompt_Builder' => 'prompt-builder',
134 'SEO_Prompts' => 'prompts/seo-prompts',
135 'Site_Identity_Prompts' => 'prompts/site-identity-prompts',
136 'Homepage_Prompts' => 'prompts/homepage-prompts',
137 'LLMs_Txt_Prompts' => 'prompts/llms-txt-prompts',
138 'Content_Brief_Prompts' => 'prompts/content-brief-prompts',
139 ];
140
141 if (isset($special_cases[$class_name])) {
142 $class_file = 'class-' . $special_cases[$class_name] . '.php';
143 } else {
144 // Convert CamelCase to kebab-case for proper WordPress naming
145 // Handle consecutive uppercase letters (like SEO) properly
146 $class_name = preg_replace('/([A-Z]+)([A-Z][a-z])/', '$1-$2', $class_name);
147 $class_name = preg_replace('/([a-z])([A-Z])/', '$1-$2', $class_name);
148 $class_file = 'class-' . strtolower(str_replace('_', '-', $class_name)) . '.php';
149 }
150
151 // Build full path
152 $directory = !empty($parts) ? strtolower(implode(DIRECTORY_SEPARATOR, $parts)) . DIRECTORY_SEPARATOR : '';
153
154 return $this->base_dir . $directory . $class_file;
155 }
156
157 /**
158 * Preload critical classes for performance
159 *
160 * @return void
161 */
162 public static function preload_critical_classes(): void {
163 $critical_classes = [
164 'ThinkRank\\Core\\Database',
165 'ThinkRank\\Core\\Settings',
166 'ThinkRank\\Core\\Cache',
167 'ThinkRank\\API\\Manager',
168 'ThinkRank\\Admin\\Manager',
169 ];
170
171 foreach ($critical_classes as $class) {
172 if (!class_exists($class)) {
173 $autoloader = new self();
174 $autoloader->load_class($class);
175 }
176 }
177 }
178
179 /**
180 * Get loaded classes count for debugging
181 *
182 * @return int
183 */
184 public static function get_loaded_classes_count(): int {
185 return count(self::$class_map);
186 }
187
188 /**
189 * Get class map for debugging
190 *
191 * @return array
192 */
193 public static function get_class_map(): array {
194 return self::$class_map;
195 }
196 }
197