| 
<?php
 require __DIR__ . '/../vendor/autoload.php';
 
 use Nette\PhpGenerator\ClassType;
 use Nette\PhpGenerator\PhpNamespace;
 
 // Configuration
 $srcDir = realpath(__DIR__ . '/../src');
 $docsDir = realpath(__DIR__ . '/../docs') . '/api';
 
 // Create docs directory if it doesn't exist
 if (!is_dir($docsDir)) {
 mkdir($docsDir, 0777, true);
 }
 
 // Function to parse PHPDoc comments
 function parseDocComment($docComment) {
 if (empty($docComment)) {
 return '';
 }
 $docComment = trim(preg_replace('/^\s*\/\*+|\s*\*+\/\s*$/s', '', $docComment));
 $docComment = preg_replace('/^\s*\* ?/m', '', $docComment);
 return $docComment;
 }
 
 // Function to generate documentation for a file
 function generateFileDoc($file, $docsDir) {
 $content = file_get_contents($file);
 $tokens = token_get_all($content);
 $namespace = '';
 $classes = [];
 $currentClass = null;
 
 foreach ($tokens as $token) {
 if (!is_array($token)) {
 continue;
 }
 
 switch ($token[0]) {
 case T_NAMESPACE:
 $namespace = '';
 $i = array_search($token, $tokens) + 2;
 while (isset($tokens[$i]) && is_array($tokens[$i])) {
 if ($tokens[$i][0] === T_STRING || $tokens[$i][0] === T_NS_SEPARATOR) {
 $namespace .= $tokens[$i][1];
 }
 $i++;
 }
 break;
 
 case T_CLASS:
 $i = array_search($token, $tokens) + 2;
 if (isset($tokens[$i]) && is_array($tokens[$i])) {
 $className = trim($tokens[$i][1]);
 if (empty($className)) {
 continue 2;
 }
 
 $currentClass = [
 'name' => $className,
 'namespace' => $namespace,
 'docComment' => '',
 'methods' => []
 ];
 
 // Look for class doc comment
 $j = array_search($token, $tokens) - 2;
 while (isset($tokens[$j]) && is_array($tokens[$j])) {
 if ($tokens[$j][0] === T_DOC_COMMENT) {
 $currentClass['docComment'] = parseDocComment($tokens[$j][1]);
 break;
 }
 $j--;
 }
 
 $classes[] = $currentClass;
 }
 break;
 
 case T_FUNCTION:
 if ($currentClass !== null) {
 $i = array_search($token, $tokens) + 2;
 if (isset($tokens[$i]) && is_array($tokens[$i])) {
 $methodName = trim($tokens[$i][1]);
 if (empty($methodName)) {
 continue 2;
 }
 
 $method = ['name' => $methodName, 'docComment' => ''];
 
 // Look for method doc comment
 $j = array_search($token, $tokens) - 2;
 while (isset($tokens[$j]) && is_array($tokens[$j])) {
 if ($tokens[$j][0] === T_DOC_COMMENT) {
 $method['docComment'] = parseDocComment($tokens[$j][1]);
 break;
 }
 $j--;
 }
 
 $classes[count($classes) - 1]['methods'][] = $method;
 }
 }
 break;
 }
 }
 
 // Generate documentation
 foreach ($classes as $class) {
 if (empty(trim($class['name']))) {
 continue;
 }
 
 $classDoc = "# {$class['name']}\n\n";
 $classDoc .= "Namespace: `{$class['namespace']}`\n\n";
 
 if (!empty($class['docComment'])) {
 $classDoc .= "{$class['docComment']}\n\n";
 }
 
 if (!empty($class['methods'])) {
 $classDoc .= "## Methods\n\n";
 foreach ($class['methods'] as $method) {
 if (empty(trim($method['name']))) {
 continue;
 }
 $classDoc .= "### {$method['name']}\n\n";
 if (!empty($method['docComment'])) {
 $classDoc .= "{$method['docComment']}\n\n";
 }
 }
 }
 
 $safeFilename = preg_replace('/[^a-zA-Z0-9_-]/', '_', $class['namespace'] . '_' . $class['name']);
 $filename = $docsDir . '/' . $safeFilename . '.md';
 file_put_contents($filename, $classDoc);
 }
 
 return $classes;
 }
 
 // Generate index file
 $indexContent = "# API Documentation\n\n";
 $indexContent .= "Welcome to the Laravel MCP SDK API documentation.\n\n";
 $indexContent .= "## Classes\n\n";
 
 // Process all PHP files in src directory
 $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($srcDir));
 $allClasses = [];
 $seenClasses = [];
 
 foreach ($iterator as $file) {
 if ($file->isFile() && $file->getExtension() === 'php') {
 $classes = generateFileDoc($file, $docsDir);
 foreach ($classes as $class) {
 if (empty(trim($class['name']))) {
 continue;
 }
 
 // Skip duplicate classes
 $classKey = $class['namespace'] . '\\' . $class['name'];
 if (isset($seenClasses[$classKey])) {
 continue;
 }
 $seenClasses[$classKey] = true;
 
 $allClasses[] = [
 'name' => $class['name'],
 'namespace' => $class['namespace'],
 'file' => preg_replace('/[^a-zA-Z0-9_-]/', '_', $class['namespace'] . '_' . $class['name']) . '.md'
 ];
 }
 }
 }
 
 // Sort classes by namespace and name
 usort($allClasses, function($a, $b) {
 $nsCompare = strcmp($a['namespace'], $b['namespace']);
 return $nsCompare !== 0 ? $nsCompare : strcmp($a['name'], $b['name']);
 });
 
 // Group classes by namespace
 $groupedClasses = [];
 foreach ($allClasses as $class) {
 if (empty(trim($class['name']))) {
 continue;
 }
 $namespace = trim($class['namespace']) ?: 'Global';
 if (!isset($groupedClasses[$namespace])) {
 $groupedClasses[$namespace] = [];
 }
 $groupedClasses[$namespace][] = $class;
 }
 
 // Generate index content
 foreach ($groupedClasses as $namespace => $classes) {
 $indexContent .= "\n### {$namespace}\n\n";
 foreach ($classes as $class) {
 if (!empty(trim($class['name']))) {
 $indexContent .= "* [{$class['name']}](api/{$class['file']})\n";
 }
 }
 }
 
 file_put_contents(dirname($docsDir) . '/index.md', $indexContent);
 
 echo "Documentation generated successfully in {$docsDir}\n";
 |