added additional plugins
This commit is contained in:
parent
c85895d306
commit
00e60ec1b7
132 changed files with 27514 additions and 0 deletions
749
native/wordpress/maple-code-blocks/includes/class-github-api.php
Normal file
749
native/wordpress/maple-code-blocks/includes/class-github-api.php
Normal file
|
|
@ -0,0 +1,749 @@
|
|||
<?php
|
||||
/**
|
||||
* Git Platform API Handler Class
|
||||
* Handles API interactions for GitHub, GitLab, Bitbucket, and Codeberg
|
||||
*/
|
||||
|
||||
// Prevent direct access
|
||||
if (!defined('WPINC')) {
|
||||
die('Direct access not permitted.');
|
||||
}
|
||||
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
class MCB_GitHub_API {
|
||||
|
||||
private $cache_duration = 3600; // 1 hour cache
|
||||
|
||||
// Platform API configurations
|
||||
private $platforms = array(
|
||||
'github' => array(
|
||||
'name' => 'GitHub',
|
||||
'api_base' => 'https://api.github.com',
|
||||
'repo_pattern' => '/^[a-zA-Z0-9\-_]+\/[a-zA-Z0-9\-_\.]+$/',
|
||||
'web_base' => 'https://github.com'
|
||||
),
|
||||
'gitlab' => array(
|
||||
'name' => 'GitLab',
|
||||
'api_base' => 'https://gitlab.com/api/v4',
|
||||
'repo_pattern' => '/^[a-zA-Z0-9\-_]+\/[a-zA-Z0-9\-_\.]+$/',
|
||||
'web_base' => 'https://gitlab.com'
|
||||
),
|
||||
'bitbucket' => array(
|
||||
'name' => 'Bitbucket',
|
||||
'api_base' => 'https://api.bitbucket.org/2.0',
|
||||
'repo_pattern' => '/^[a-zA-Z0-9\-_]+\/[a-zA-Z0-9\-_\.]+$/',
|
||||
'web_base' => 'https://bitbucket.org'
|
||||
),
|
||||
'codeberg' => array(
|
||||
'name' => 'Codeberg',
|
||||
'api_base' => 'https://codeberg.org/api/v1',
|
||||
'repo_pattern' => '/^[a-zA-Z0-9\-_]+\/[a-zA-Z0-9\-_\.]+$/',
|
||||
'web_base' => 'https://codeberg.org'
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* Detect platform from repository string
|
||||
*/
|
||||
private function detect_platform($repo_string) {
|
||||
// Check for platform prefix (e.g., "gitlab:owner/repo")
|
||||
if (strpos($repo_string, ':') !== false) {
|
||||
list($platform, $repo) = explode(':', $repo_string, 2);
|
||||
if (isset($this->platforms[$platform])) {
|
||||
return array('platform' => $platform, 'repo' => $repo);
|
||||
}
|
||||
}
|
||||
|
||||
// Check for full URLs
|
||||
if (strpos($repo_string, 'https://') === 0 || strpos($repo_string, 'http://') === 0) {
|
||||
foreach ($this->platforms as $key => $config) {
|
||||
if (strpos($repo_string, $config['web_base']) !== false) {
|
||||
// Extract owner/repo from URL
|
||||
$parsed = parse_url($repo_string);
|
||||
$path = trim($parsed['path'], '/');
|
||||
$parts = explode('/', $path);
|
||||
if (count($parts) >= 2) {
|
||||
return array(
|
||||
'platform' => $key,
|
||||
'repo' => $parts[0] . '/' . $parts[1]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Default to GitHub for backward compatibility
|
||||
return array('platform' => 'github', 'repo' => $repo_string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get repository files list
|
||||
*/
|
||||
public function get_repository_files($repo_string, $path = '') {
|
||||
$platform_info = $this->detect_platform($repo_string);
|
||||
$platform = $platform_info['platform'];
|
||||
$repo = $platform_info['repo'];
|
||||
|
||||
// Validate repo format
|
||||
if (!preg_match($this->platforms[$platform]['repo_pattern'], $repo)) {
|
||||
return new WP_Error('invalid_repo', 'Invalid repository format. Use: owner/repository');
|
||||
}
|
||||
|
||||
// Check cache first
|
||||
$cache_key = 'mcb_repo_' . $platform . '_' . md5($repo . '_' . $path);
|
||||
$cached_data = get_transient($cache_key);
|
||||
|
||||
if ($cached_data !== false) {
|
||||
return $cached_data;
|
||||
}
|
||||
|
||||
// Get files based on platform
|
||||
switch ($platform) {
|
||||
case 'github':
|
||||
$files = $this->get_github_files($repo, $path);
|
||||
break;
|
||||
case 'gitlab':
|
||||
$files = $this->get_gitlab_files($repo, $path);
|
||||
break;
|
||||
case 'bitbucket':
|
||||
$files = $this->get_bitbucket_files($repo, $path);
|
||||
break;
|
||||
case 'codeberg':
|
||||
$files = $this->get_codeberg_files($repo, $path);
|
||||
break;
|
||||
default:
|
||||
return new WP_Error('unsupported_platform', 'Unsupported platform');
|
||||
}
|
||||
|
||||
if (!is_wp_error($files)) {
|
||||
// Cache the results
|
||||
set_transient($cache_key, $files, $this->cache_duration);
|
||||
}
|
||||
|
||||
return $files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file content from repository
|
||||
*/
|
||||
public function get_file_content($repo_string, $file_path) {
|
||||
$platform_info = $this->detect_platform($repo_string);
|
||||
$platform = $platform_info['platform'];
|
||||
$repo = $platform_info['repo'];
|
||||
|
||||
// Validate inputs
|
||||
if (!preg_match($this->platforms[$platform]['repo_pattern'], $repo)) {
|
||||
return new WP_Error('invalid_repo', 'Invalid repository format');
|
||||
}
|
||||
|
||||
// Sanitize and validate file path
|
||||
$file_path = trim($file_path, '/');
|
||||
|
||||
// Block path traversal attempts
|
||||
if (strpos($file_path, '..') !== false ||
|
||||
strpos($file_path, '//') !== false ||
|
||||
strpos($file_path, '\\') !== false ||
|
||||
preg_match('/[<>"|*?]/', $file_path)) {
|
||||
return new WP_Error('invalid_path', 'Invalid file path');
|
||||
}
|
||||
|
||||
// Check cache
|
||||
$cache_key = 'mcb_file_' . $platform . '_' . md5($repo . $file_path);
|
||||
$cached_content = get_transient($cache_key);
|
||||
|
||||
if ($cached_content !== false) {
|
||||
return $cached_content;
|
||||
}
|
||||
|
||||
// Get content based on platform
|
||||
switch ($platform) {
|
||||
case 'github':
|
||||
$content = $this->get_github_file_content($repo, $file_path);
|
||||
break;
|
||||
case 'gitlab':
|
||||
$content = $this->get_gitlab_file_content($repo, $file_path);
|
||||
break;
|
||||
case 'bitbucket':
|
||||
$content = $this->get_bitbucket_file_content($repo, $file_path);
|
||||
break;
|
||||
case 'codeberg':
|
||||
$content = $this->get_codeberg_file_content($repo, $file_path);
|
||||
break;
|
||||
default:
|
||||
return new WP_Error('unsupported_platform', 'Unsupported platform');
|
||||
}
|
||||
|
||||
if (!is_wp_error($content)) {
|
||||
// Cache the content
|
||||
set_transient($cache_key, $content, $this->cache_duration);
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* GitHub-specific file listing
|
||||
*/
|
||||
private function get_github_files($repo, $path = '') {
|
||||
$url = $this->platforms['github']['api_base'] . '/repos/' . $repo . '/contents';
|
||||
if (!empty($path)) {
|
||||
$url .= '/' . ltrim($path, '/');
|
||||
}
|
||||
|
||||
$response = $this->make_api_request($url, 'github');
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
return $this->parse_github_contents($response, $repo, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* GitLab-specific file listing
|
||||
*/
|
||||
private function get_gitlab_files($repo, $path = '') {
|
||||
// GitLab uses project ID or URL-encoded path
|
||||
$project_id = urlencode($repo);
|
||||
$url = $this->platforms['gitlab']['api_base'] . '/projects/' . $project_id . '/repository/tree?recursive=true&per_page=100';
|
||||
$response = $this->make_api_request($url, 'gitlab');
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
return $this->parse_gitlab_contents($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bitbucket-specific file listing
|
||||
*/
|
||||
private function get_bitbucket_files($repo, $path = '') {
|
||||
$url = $this->platforms['bitbucket']['api_base'] . '/repositories/' . $repo . '/src';
|
||||
$response = $this->make_api_request($url, 'bitbucket');
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
return $this->parse_bitbucket_contents($response, $repo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Codeberg-specific file listing (uses Gitea API)
|
||||
*/
|
||||
private function get_codeberg_files($repo, $path = '') {
|
||||
$url = $this->platforms['codeberg']['api_base'] . '/repos/' . $repo . '/contents';
|
||||
if (!empty($path)) {
|
||||
$url .= '/' . ltrim($path, '/');
|
||||
}
|
||||
|
||||
$response = $this->make_api_request($url, 'codeberg');
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
// Codeberg uses Gitea, similar to GitHub API
|
||||
return $this->parse_github_contents($response, $repo, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* GitHub file content retrieval
|
||||
*/
|
||||
private function get_github_file_content($repo, $file_path) {
|
||||
$url = $this->platforms['github']['api_base'] . '/repos/' . $repo . '/contents/' . $file_path;
|
||||
$response = $this->make_api_request($url, 'github');
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$data = json_decode($response, true);
|
||||
|
||||
if (!isset($data['content'])) {
|
||||
return new WP_Error('no_content', 'File content not found');
|
||||
}
|
||||
|
||||
return base64_decode($data['content']);
|
||||
}
|
||||
|
||||
/**
|
||||
* GitLab file content retrieval
|
||||
*/
|
||||
private function get_gitlab_file_content($repo, $file_path) {
|
||||
$project_id = urlencode($repo);
|
||||
$file_path_encoded = urlencode($file_path);
|
||||
$url = $this->platforms['gitlab']['api_base'] . '/projects/' . $project_id . '/repository/files/' . $file_path_encoded . '/raw?ref=main';
|
||||
|
||||
// Try main branch first, then master
|
||||
$response = $this->make_api_request($url, 'gitlab');
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
// Try master branch
|
||||
$url = $this->platforms['gitlab']['api_base'] . '/projects/' . $project_id . '/repository/files/' . $file_path_encoded . '/raw?ref=master';
|
||||
$response = $this->make_api_request($url, 'gitlab');
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bitbucket file content retrieval
|
||||
*/
|
||||
private function get_bitbucket_file_content($repo, $file_path) {
|
||||
// Get default branch first
|
||||
$repo_url = $this->platforms['bitbucket']['api_base'] . '/repositories/' . $repo;
|
||||
$repo_response = $this->make_api_request($repo_url, 'bitbucket');
|
||||
|
||||
if (is_wp_error($repo_response)) {
|
||||
return $repo_response;
|
||||
}
|
||||
|
||||
$repo_data = json_decode($repo_response, true);
|
||||
$branch = isset($repo_data['mainbranch']['name']) ? $repo_data['mainbranch']['name'] : 'master';
|
||||
|
||||
$url = $this->platforms['bitbucket']['api_base'] . '/repositories/' . $repo . '/src/' . $branch . '/' . $file_path;
|
||||
return $this->make_api_request($url, 'bitbucket');
|
||||
}
|
||||
|
||||
/**
|
||||
* Codeberg file content retrieval
|
||||
*/
|
||||
private function get_codeberg_file_content($repo, $file_path) {
|
||||
// Codeberg uses Gitea API, similar to GitHub
|
||||
$url = $this->platforms['codeberg']['api_base'] . '/repos/' . $repo . '/contents/' . $file_path;
|
||||
$response = $this->make_api_request($url, 'codeberg');
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$data = json_decode($response, true);
|
||||
|
||||
if (!isset($data['content'])) {
|
||||
return new WP_Error('no_content', 'File content not found');
|
||||
}
|
||||
|
||||
return base64_decode($data['content']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make HTTP request to Git platform API
|
||||
*/
|
||||
private function make_api_request($url, $platform) {
|
||||
// SSRF Protection - validate URL
|
||||
$parsed_url = parse_url($url);
|
||||
|
||||
// Only allow HTTPS protocol
|
||||
if ($parsed_url['scheme'] !== 'https') {
|
||||
return new WP_Error('invalid_protocol', 'Only HTTPS is allowed');
|
||||
}
|
||||
|
||||
// Only allow known platform hosts
|
||||
$allowed_hosts = array(
|
||||
'api.github.com',
|
||||
'gitlab.com',
|
||||
'api.bitbucket.org',
|
||||
'codeberg.org'
|
||||
);
|
||||
|
||||
if (!in_array($parsed_url['host'], $allowed_hosts)) {
|
||||
return new WP_Error('invalid_host', 'Invalid API host');
|
||||
}
|
||||
|
||||
// Add request throttling to prevent rate limit issues
|
||||
static $last_request_time = 0;
|
||||
$min_interval = 0.1; // Minimum 100ms between requests
|
||||
|
||||
$current_time = microtime(true);
|
||||
$time_since_last = $current_time - $last_request_time;
|
||||
|
||||
if ($time_since_last < $min_interval) {
|
||||
usleep(($min_interval - $time_since_last) * 1000000);
|
||||
}
|
||||
|
||||
$args = array(
|
||||
'timeout' => 10, // Reduced timeout to prevent hanging
|
||||
'redirection' => 3, // Limit redirects
|
||||
'headers' => $this->get_platform_headers($platform)
|
||||
);
|
||||
|
||||
// Add authentication if available
|
||||
$token = $this->get_platform_token($platform);
|
||||
if (!empty($token)) {
|
||||
$args['headers']['Authorization'] = $this->get_auth_header($platform, $token);
|
||||
}
|
||||
|
||||
$response = wp_remote_get($url, $args);
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$status_code = wp_remote_retrieve_response_code($response);
|
||||
|
||||
if ($status_code !== 200) {
|
||||
return new WP_Error('api_error', 'API returned status: ' . $status_code);
|
||||
}
|
||||
|
||||
$last_request_time = microtime(true);
|
||||
|
||||
return wp_remote_retrieve_body($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get platform-specific headers
|
||||
*/
|
||||
private function get_platform_headers($platform) {
|
||||
switch ($platform) {
|
||||
case 'github':
|
||||
return array(
|
||||
'Accept' => 'application/vnd.github.v3+json',
|
||||
'User-Agent' => 'WordPress/GitHub-Code-Viewer'
|
||||
);
|
||||
case 'gitlab':
|
||||
return array(
|
||||
'Accept' => 'application/json',
|
||||
'User-Agent' => 'WordPress/GitHub-Code-Viewer'
|
||||
);
|
||||
case 'bitbucket':
|
||||
return array(
|
||||
'Accept' => 'application/json',
|
||||
'User-Agent' => 'WordPress/GitHub-Code-Viewer'
|
||||
);
|
||||
case 'codeberg':
|
||||
return array(
|
||||
'Accept' => 'application/json',
|
||||
'User-Agent' => 'WordPress/GitHub-Code-Viewer'
|
||||
);
|
||||
default:
|
||||
return array(
|
||||
'User-Agent' => 'WordPress/GitHub-Code-Viewer'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get platform token if configured
|
||||
*/
|
||||
private function get_platform_token($platform) {
|
||||
// Use secure token manager if available
|
||||
if (class_exists('MCB_Token_Manager')) {
|
||||
return MCB_Token_Manager::get_token($platform);
|
||||
}
|
||||
// Fallback to direct option (for backwards compatibility)
|
||||
return get_option('mcb_' . $platform . '_token', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get authorization header format for platform
|
||||
*/
|
||||
private function get_auth_header($platform, $token) {
|
||||
switch ($platform) {
|
||||
case 'github':
|
||||
return 'token ' . $token;
|
||||
case 'gitlab':
|
||||
return 'Bearer ' . $token;
|
||||
case 'bitbucket':
|
||||
return 'Bearer ' . $token;
|
||||
case 'codeberg':
|
||||
return 'token ' . $token;
|
||||
default:
|
||||
return 'Bearer ' . $token;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse GitHub/Codeberg repository contents
|
||||
*/
|
||||
private function parse_github_contents($response, $repo, $current_path = '') {
|
||||
$items = json_decode($response, true);
|
||||
$files = array();
|
||||
|
||||
if (!is_array($items)) {
|
||||
return $files;
|
||||
}
|
||||
|
||||
// Add parent directory navigation if not at root
|
||||
if (!empty($current_path)) {
|
||||
$parent_path = dirname($current_path);
|
||||
if ($parent_path === '.') {
|
||||
$parent_path = '';
|
||||
}
|
||||
|
||||
$files[] = array(
|
||||
'name' => '..',
|
||||
'path' => $parent_path,
|
||||
'size' => 0,
|
||||
'type' => 'parent',
|
||||
'is_folder' => true,
|
||||
'url' => ''
|
||||
);
|
||||
}
|
||||
|
||||
$code_extensions = $this->get_code_extensions();
|
||||
|
||||
// First add all directories
|
||||
foreach ($items as $item) {
|
||||
if ($item['type'] === 'dir') {
|
||||
$files[] = array(
|
||||
'name' => $item['name'],
|
||||
'path' => $item['path'],
|
||||
'size' => 0,
|
||||
'type' => 'folder',
|
||||
'is_folder' => true,
|
||||
'url' => $item['html_url']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Then add all files
|
||||
foreach ($items as $item) {
|
||||
if ($item['type'] === 'file') {
|
||||
$extension = strtolower(pathinfo($item['name'], PATHINFO_EXTENSION));
|
||||
$name_lower = strtolower($item['name']);
|
||||
|
||||
// Include all files, not just code files, for better browsing
|
||||
$files[] = array(
|
||||
'name' => $item['name'],
|
||||
'path' => $item['path'],
|
||||
'size' => $item['size'],
|
||||
'type' => $this->get_file_type($item['name']),
|
||||
'is_folder' => false,
|
||||
'url' => $item['html_url']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse GitLab repository contents
|
||||
*/
|
||||
private function parse_gitlab_contents($response) {
|
||||
$items = json_decode($response, true);
|
||||
$files = array();
|
||||
|
||||
if (!is_array($items)) {
|
||||
return $files;
|
||||
}
|
||||
|
||||
$code_extensions = $this->get_code_extensions();
|
||||
|
||||
foreach ($items as $item) {
|
||||
if ($item['type'] === 'blob') { // GitLab uses 'blob' for files
|
||||
$extension = strtolower(pathinfo($item['name'], PATHINFO_EXTENSION));
|
||||
$name_lower = strtolower($item['name']);
|
||||
|
||||
if (in_array($extension, $code_extensions) || $this->is_code_file($name_lower)) {
|
||||
$files[] = array(
|
||||
'name' => $item['name'],
|
||||
'path' => $item['path'],
|
||||
'size' => 0, // GitLab doesn't provide size in tree API
|
||||
'type' => $this->get_file_type($item['name']),
|
||||
'url' => '' // Will need to construct if needed
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse Bitbucket repository contents
|
||||
*/
|
||||
private function parse_bitbucket_contents($response, $repo) {
|
||||
$data = json_decode($response, true);
|
||||
$files = array();
|
||||
|
||||
if (!isset($data['values']) || !is_array($data['values'])) {
|
||||
return $files;
|
||||
}
|
||||
|
||||
$code_extensions = $this->get_code_extensions();
|
||||
|
||||
foreach ($data['values'] as $item) {
|
||||
if ($item['type'] === 'commit_file') {
|
||||
$extension = strtolower(pathinfo($item['path'], PATHINFO_EXTENSION));
|
||||
$name_lower = strtolower(basename($item['path']));
|
||||
|
||||
if (in_array($extension, $code_extensions) || $this->is_code_file($name_lower)) {
|
||||
$files[] = array(
|
||||
'name' => basename($item['path']),
|
||||
'path' => $item['path'],
|
||||
'size' => isset($item['size']) ? $item['size'] : 0,
|
||||
'type' => $this->get_file_type(basename($item['path'])),
|
||||
'url' => 'https://bitbucket.org/' . $repo . '/src/master/' . $item['path']
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of code file extensions
|
||||
*/
|
||||
private function get_code_extensions() {
|
||||
return array(
|
||||
'php', 'js', 'jsx', 'ts', 'tsx', 'py', 'rb', 'java', 'c', 'cpp', 'cc', 'cxx',
|
||||
'h', 'hpp', 'cs', 'swift', 'kt', 'go', 'rs', 'scala', 'r', 'sql', 'sh', 'bash',
|
||||
'yml', 'yaml', 'json', 'xml', 'html', 'css', 'scss', 'sass', 'less',
|
||||
'md', 'markdown', 'txt', 'ini', 'conf', 'dockerfile', 'makefile',
|
||||
'vue', 'svelte', 'elm', 'clj', 'ex', 'exs', 'erl', 'hrl', 'lua', 'pl', 'pm'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if filename indicates a code file
|
||||
*/
|
||||
private function is_code_file($filename) {
|
||||
$code_files = array(
|
||||
'dockerfile', 'makefile', '.gitignore', '.env', '.htaccess',
|
||||
'gemfile', 'rakefile', 'gulpfile', 'gruntfile', 'webpack.config.js',
|
||||
'package.json', 'composer.json', 'cargo.toml', 'go.mod'
|
||||
);
|
||||
|
||||
return in_array($filename, $code_files);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file type based on extension
|
||||
*/
|
||||
private function get_file_type($filename) {
|
||||
$extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
|
||||
$name_lower = strtolower($filename);
|
||||
|
||||
$type_map = array(
|
||||
'php' => 'php',
|
||||
'js' => 'javascript',
|
||||
'jsx' => 'jsx',
|
||||
'ts' => 'typescript',
|
||||
'tsx' => 'tsx',
|
||||
'py' => 'python',
|
||||
'rb' => 'ruby',
|
||||
'java' => 'java',
|
||||
'c' => 'c',
|
||||
'cpp' => 'cpp',
|
||||
'cc' => 'cpp',
|
||||
'cxx' => 'cpp',
|
||||
'h' => 'c',
|
||||
'hpp' => 'cpp',
|
||||
'cs' => 'csharp',
|
||||
'swift' => 'swift',
|
||||
'kt' => 'kotlin',
|
||||
'go' => 'go',
|
||||
'rs' => 'rust',
|
||||
'scala' => 'scala',
|
||||
'r' => 'r',
|
||||
'sql' => 'sql',
|
||||
'sh' => 'bash',
|
||||
'bash' => 'bash',
|
||||
'yml' => 'yaml',
|
||||
'yaml' => 'yaml',
|
||||
'json' => 'json',
|
||||
'xml' => 'xml',
|
||||
'html' => 'html',
|
||||
'css' => 'css',
|
||||
'scss' => 'scss',
|
||||
'sass' => 'sass',
|
||||
'less' => 'less',
|
||||
'md' => 'markdown',
|
||||
'markdown' => 'markdown'
|
||||
);
|
||||
|
||||
// Check special file names
|
||||
if ($name_lower === 'dockerfile') {
|
||||
return 'docker';
|
||||
}
|
||||
if ($name_lower === 'makefile') {
|
||||
return 'makefile';
|
||||
}
|
||||
|
||||
return isset($type_map[$extension]) ? $type_map[$extension] : 'plain';
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate if repository exists
|
||||
*/
|
||||
public function validate_repository_exists($repo_string) {
|
||||
$platform_info = $this->detect_platform($repo_string);
|
||||
$platform = $platform_info['platform'];
|
||||
$repo = $platform_info['repo'];
|
||||
|
||||
// Validate format first
|
||||
if (!preg_match($this->platforms[$platform]['repo_pattern'], $repo)) {
|
||||
return new WP_Error('invalid_repo', 'Invalid repository format');
|
||||
}
|
||||
|
||||
// Check cache first
|
||||
$cache_key = 'mcb_repo_valid_' . $platform . '_' . md5($repo);
|
||||
$cached_result = get_transient($cache_key);
|
||||
|
||||
if ($cached_result !== false) {
|
||||
return $cached_result;
|
||||
}
|
||||
|
||||
// Check with platform API
|
||||
$exists = false;
|
||||
switch ($platform) {
|
||||
case 'github':
|
||||
$url = $this->platforms['github']['api_base'] . '/repos/' . $repo;
|
||||
break;
|
||||
case 'gitlab':
|
||||
$project_id = urlencode($repo);
|
||||
$url = $this->platforms['gitlab']['api_base'] . '/projects/' . $project_id;
|
||||
break;
|
||||
case 'bitbucket':
|
||||
$url = $this->platforms['bitbucket']['api_base'] . '/repositories/' . $repo;
|
||||
break;
|
||||
case 'codeberg':
|
||||
$url = $this->platforms['codeberg']['api_base'] . '/repos/' . $repo;
|
||||
break;
|
||||
default:
|
||||
return new WP_Error('unsupported_platform', 'Unsupported platform');
|
||||
}
|
||||
|
||||
$response = $this->make_api_request($url, $platform);
|
||||
|
||||
if (!is_wp_error($response)) {
|
||||
$data = json_decode($response, true);
|
||||
if (isset($data['id']) || isset($data['uuid']) || isset($data['name'])) {
|
||||
$exists = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($exists) {
|
||||
set_transient($cache_key, true, 3600);
|
||||
return true;
|
||||
}
|
||||
|
||||
return new WP_Error('repo_not_found', 'Repository not found or is private');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get platform display name
|
||||
*/
|
||||
public function get_platform_name($repo_string) {
|
||||
$platform_info = $this->detect_platform($repo_string);
|
||||
return $this->platforms[$platform_info['platform']]['name'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get repository web URL
|
||||
*/
|
||||
public function get_repository_url($repo_string) {
|
||||
$platform_info = $this->detect_platform($repo_string);
|
||||
$platform = $platform_info['platform'];
|
||||
$repo = $platform_info['repo'];
|
||||
|
||||
return $this->platforms[$platform]['web_base'] . '/' . $repo;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue