Phiên bản: 1.0 Ngày tạo: 2025 Tác giả: Development Team
Rake WordPress Adapter là bridge giữa Rake Core Framework và WordPress, cung cấp:
┌─────────────────────────────────────────────────────────────┐
│ RAKE WORDPRESS ADAPTER │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────┐ │
│ │ DATABASE │ │ HOOKS │ │ ADMIN │ │
│ │ ADAPTER │ │ INTEGRATION │ │ INTEGRATION │ │
│ │ │ │ │ │ │ │
│ │ • WP Database │ │ • add_action │ │ • Menu │ │
│ │ • Query Builder │ │ • add_filter │ │ • Pages │ │
│ │ • Prefix Handle │ │ • do_action │ │ • Scripts │ │
│ │ • wpdb Wrapper │ │ • apply_filters │ │ • Styles │ │
│ └─────────────────┘ └─────────────────┘ └─────────────┘ │
│ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────┐ │
│ │ SECURITY │ │ CACHE │ │ CONFIG │ │
│ │ LAYER │ │ INTEGRATION │ │ INTEGRATION │ │
│ │ │ │ │ │ │ │
│ │ • Nonce Check │ │ • WP Cache │ │ • WP Config │ │
│ │ • Capability │ │ • Transients │ │ • Options │ │
│ │ • Sanitization │ │ • Object Cache │ │ • Settings │ │
│ │ • Validation │ │ • Query Cache │ │ • Constants │ │
│ └─────────────────┘ └─────────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
rake-wordpress-adapter/
├── src/
│ ├── Database/ # WordPress Database Integration
│ │ ├── WordPressDatabaseAdapter.php
│ │ ├── WordPressQueryBuilder.php
│ │ └── WordPressPrefixHandler.php
│ ├── Hooks/ # WordPress Hooks Integration
│ │ ├── WordPressHooksAdapter.php
│ │ └── WordPressHooksInterface.php
│ ├── Admin/ # WordPress Admin Integration
│ │ ├── WordPressAdminAdapter.php
│ │ ├── WordPressMenuBuilder.php
│ │ └── WordPressScriptManager.php
│ ├── Security/ # WordPress Security Layer
│ │ ├── WordPressSecurityAdapter.php
│ │ ├── WordPressNonceHandler.php
│ │ └── WordPressCapabilityChecker.php
│ ├── Cache/ # WordPress Cache Integration
│ │ ├── WordPressCacheAdapter.php
│ │ ├── WordPressTransientHandler.php
│ │ └── WordPressObjectCache.php
│ └── Config/ # WordPress Config Integration
│ ├── WordPressConfigAdapter.php
│ └── WordPressOptionsHandler.php
├── composer.json
└── README.md
{
"name": "puleeno/rake-wordpress-adapter",
"require": {
"php": ">=8.1",
"ramphor/rake": "^2.0"
},
"autoload": {
"psr-4": {
"Rake\\WordPress\\": "src/"
}
}
}
class WordPressDatabaseAdapter implements DatabaseAdapterInterface
{
private \wpdb $wpdb;
private string $prefix;
public function __construct()
{
global $wpdb;
$this->wpdb = $wpdb;
$this->prefix = $wpdb->prefix;
}
public function query(string $sql): bool
{
return $this->wpdb->query($sql) !== false;
}
public function getResults(string $sql): array
{
return $this->wpdb->get_results($sql, ARRAY_A);
}
public function getRow(string $sql): ?array
{
$result = $this->wpdb->get_row($sql, ARRAY_A);
return $result ?: null;
}
public function getVar(string $sql): mixed
{
return $this->wpdb->get_var($sql);
}
public function insert(string $table, array $data): int
{
$table = $this->addPrefix($table);
$result = $this->wpdb->insert($table, $data);
if ($result === false) {
throw new DatabaseException('Insert failed: ' . $this->wpdb->last_error);
}
return $this->wpdb->insert_id;
}
public function update(string $table, array $data, array $where): int
{
$table = $this->addPrefix($table);
$result = $this->wpdb->update($table, $data, $where);
if ($result === false) {
throw new DatabaseException('Update failed: ' . $this->wpdb->last_error);
}
return $result;
}
public function delete(string $table, array $where): int
{
$table = $this->addPrefix($table);
$result = $this->wpdb->delete($table, $where);
if ($result === false) {
throw new DatabaseException('Delete failed: ' . $this->wpdb->last_error);
}
return $result;
}
public function getPrefix(): string
{
return $this->prefix;
}
public function escape(string $value): string
{
return $this->wpdb->_real_escape($value);
}
private function addPrefix(string $table): string
{
if (strpos($table, $this->prefix) === 0) {
return $table;
}
return $this->prefix . $table;
}
public function tableExists(string $table): bool
{
$sql = "SHOW TABLES LIKE '{$this->addPrefix($table)}'";
$result = $this->getRow($sql);
return $result !== null;
}
public function getTables(): array
{
$sql = "SHOW TABLES LIKE '{$this->prefix}%'";
$results = $this->getResults($sql);
$tables = [];
foreach ($results as $result) {
$tables[] = array_values($result)[0];
}
return $tables;
}
}
class WordPressQueryBuilder
{
private WordPressDatabaseAdapter $adapter;
private array $select = [];
private array $from = [];
private array $where = [];
private array $orderBy = [];
private array $groupBy = [];
private ?int $limit = null;
private ?int $offset = null;
public function __construct(WordPressDatabaseAdapter $adapter)
{
$this->adapter = $adapter;
}
public function select(array $columns): self
{
$this->select = $columns;
return $this;
}
public function from(string $table): self
{
$this->from[] = $table;
return $this;
}
public function where(string $column, string $operator, $value): self
{
$this->where[] = [
'column' => $column,
'operator' => $operator,
'value' => $value,
];
return $this;
}
public function orderBy(string $column, string $direction = 'ASC'): self
{
$this->orderBy[] = [
'column' => $column,
'direction' => strtoupper($direction),
];
return $this;
}
public function limit(int $limit): self
{
$this->limit = $limit;
return $this;
}
public function offset(int $offset): self
{
$this->offset = $offset;
return $this;
}
public function get(): array
{
$sql = $this->buildSelectQuery();
return $this->adapter->getResults($sql);
}
public function first(): ?array
{
$this->limit(1);
$sql = $this->buildSelectQuery();
return $this->adapter->getRow($sql);
}
private function buildSelectQuery(): string
{
$sql = "SELECT " . implode(', ', $this->select ?: ['*']);
$sql .= " FROM " . implode(', ', $this->from);
if (!empty($this->where)) {
$sql .= " WHERE " . $this->buildWhereClause();
}
if (!empty($this->groupBy)) {
$sql .= " GROUP BY " . implode(', ', $this->groupBy);
}
if (!empty($this->orderBy)) {
$sql .= " ORDER BY " . $this->buildOrderByClause();
}
if ($this->limit !== null) {
$sql .= " LIMIT {$this->limit}";
}
if ($this->offset !== null) {
$sql .= " OFFSET {$this->offset}";
}
return $sql;
}
private function buildWhereClause(): string
{
$conditions = [];
foreach ($this->where as $condition) {
$value = $this->adapter->escape($condition['value']);
$conditions[] = "{$condition['column']} {$condition['operator']} '{$value}'";
}
return implode(' AND ', $conditions);
}
private function buildOrderByClause(): string
{
$orders = [];
foreach ($this->orderBy as $order) {
$orders[] = "{$order['column']} {$order['direction']}";
}
return implode(', ', $orders);
}
}
class WordPressHooksAdapter implements WordPressHooksInterface
{
public function addAction(string $hook, callable $callback, int $priority = 10, int $acceptedArgs = 1): void
{
\add_action($hook, $callback, $priority, $acceptedArgs);
}
public function addFilter(string $hook, callable $callback, int $priority = 10, int $acceptedArgs = 1): void
{
\add_filter($hook, $callback, $priority, $acceptedArgs);
}
public function doAction(string $hook, ...$args): void
{
\do_action($hook, ...$args);
}
public function applyFilters(string $hook, $value, ...$args)
{
return \apply_filters($hook, $value, ...$args);
}
public function removeAction(string $hook, callable $callback, int $priority = 10): void
{
\remove_action($hook, $callback, $priority);
}
public function removeFilter(string $hook, callable $callback, int $priority = 10): void
{
\remove_filter($hook, $callback, $priority);
}
public function hasAction(string $hook): bool
{
return \has_action($hook);
}
public function hasFilter(string $hook): bool
{
return \has_filter($hook);
}
public function currentFilter(): string
{
return \current_filter();
}
public function doingAction(string $hook): bool
{
return \doing_action($hook);
}
public function doingFilter(string $hook): bool
{
return \doing_filter($hook);
}
}
interface WordPressHooksInterface
{
public function addAction(string $hook, callable $callback, int $priority = 10, int $acceptedArgs = 1): void;
public function addFilter(string $hook, callable $callback, int $priority = 10, int $acceptedArgs = 1): void;
public function doAction(string $hook, ...$args): void;
public function applyFilters(string $hook, $value, ...$args);
public function removeAction(string $hook, callable $callback, int $priority = 10): void;
public function removeFilter(string $hook, callable $callback, int $priority = 10): void;
public function hasAction(string $hook): bool;
public function hasFilter(string $hook): bool;
public function currentFilter(): string;
public function doingAction(string $hook): bool;
public function doingFilter(string $hook): bool;
}
class WordPressAdminAdapter
{
public function addMenuPage(string $pageTitle, string $menuTitle, string $capability, string $menuSlug, callable $callback): void
{
\add_menu_page($pageTitle, $menuTitle, $capability, $menuSlug, $callback);
}
public function addSubmenuPage(string $parentSlug, string $pageTitle, string $menuTitle, string $capability, string $menuSlug, callable $callback): void
{
\add_submenu_page($parentSlug, $pageTitle, $menuTitle, $capability, $menuSlug, $callback);
}
public function enqueueScript(string $handle, string $src, array $deps = [], $version = false, bool $inFooter = false): void
{
\wp_enqueue_script($handle, $src, $deps, $version, $inFooter);
}
public function enqueueStyle(string $handle, string $src, array $deps = [], $version = false): void
{
\wp_enqueue_style($handle, $src, $deps, $version);
}
public function localizeScript(string $handle, string $objectName, array $data): void
{
\wp_localize_script($handle, $objectName, $data);
}
public function addAdminNotice(string $message, string $type = 'info'): void
{
\add_action('admin_notices', function() use ($message, $type) {
$class = 'notice notice-' . $type;
echo "<div class='{$class}'><p>{$message}</p></div>";
});
}
public function getCurrentScreen(): ?object
{
return \get_current_screen();
}
public function getAdminUrl(string $path = '', array $args = []): string
{
return \admin_url($path, $args);
}
public function getPluginUrl(string $path = ''): string
{
return \plugin_dir_url(__FILE__) . $path;
}
public function getPluginPath(string $path = ''): string
{
return \plugin_dir_path(__FILE__) . $path;
}
}
class WordPressMenuBuilder
{
private WordPressAdminAdapter $adminAdapter;
public function __construct(WordPressAdminAdapter $adminAdapter)
{
$this->adminAdapter = $adminAdapter;
}
public function addMainMenu(string $pageTitle, string $menuTitle, string $capability, string $menuSlug, callable $callback, string $icon = '', int $position = null): void
{
\add_menu_page($pageTitle, $menuTitle, $capability, $menuSlug, $callback, $icon, $position);
}
public function addSubMenu(string $parentSlug, string $pageTitle, string $menuTitle, string $capability, string $menuSlug, callable $callback): void
{
\add_submenu_page($parentSlug, $pageTitle, $menuTitle, $capability, $menuSlug, $callback);
}
public function removeSubMenu(string $parentSlug, string $menuSlug): void
{
\remove_submenu_page($parentSlug, $menuSlug);
}
public function addAdminBarNode(string $id, string $title, string $href = '', string $parent = '', array $meta = []): void
{
\add_action('admin_bar_menu', function($wp_admin_bar) use ($id, $title, $href, $parent, $meta) {
$wp_admin_bar->add_node([
'id' => $id,
'title' => $title,
'href' => $href,
'parent' => $parent,
'meta' => $meta,
]);
}, 999);
}
}
class WordPressScriptManager
{
private WordPressAdminAdapter $adminAdapter;
public function __construct(WordPressAdminAdapter $adminAdapter)
{
$this->adminAdapter = $adminAdapter;
}
public function enqueueAdminScript(string $handle, string $src, array $deps = [], $version = false): void
{
\add_action('admin_enqueue_scripts', function() use ($handle, $src, $deps, $version) {
$this->adminAdapter->enqueueScript($handle, $src, $deps, $version);
});
}
public function enqueueAdminStyle(string $handle, string $src, array $deps = [], $version = false): void
{
\add_action('admin_enqueue_scripts', function() use ($handle, $src, $deps, $version) {
$this->adminAdapter->enqueueStyle($handle, $src, $deps, $version);
});
}
public function enqueueFrontendScript(string $handle, string $src, array $deps = [], $version = false): void
{
\add_action('wp_enqueue_scripts', function() use ($handle, $src, $deps, $version) {
$this->adminAdapter->enqueueScript($handle, $src, $deps, $version);
});
}
public function enqueueFrontendStyle(string $handle, string $src, array $deps = [], $version = false): void
{
\add_action('wp_enqueue_scripts', function() use ($handle, $src, $deps, $version) {
$this->adminAdapter->enqueueStyle($handle, $src, $deps, $version);
});
}
public function localizeScript(string $handle, string $objectName, array $data): void
{
\add_action('admin_enqueue_scripts', function() use ($handle, $objectName, $data) {
$this->adminAdapter->localizeScript($handle, $objectName, $data);
});
}
}
class WordPressSecurityAdapter
{
public function verifyNonce(string $nonce, string $action): bool
{
return \wp_verify_nonce($nonce, $action);
}
public function createNonce(string $action): string
{
return \wp_create_nonce($action);
}
public function checkAjaxReferer(string $action, string $queryArg = '_wpnonce', bool $die = true): bool
{
return \check_ajax_referer($action, $queryArg, $die);
}
public function currentUserCan(string $capability): bool
{
return \current_user_can($capability);
}
public function sanitizeTextField(string $text): string
{
return \sanitize_text_field($text);
}
public function sanitizeTextareaField(string $text): string
{
return \sanitize_textarea_field($text);
}
public function sanitizeEmail(string $email): string
{
return \sanitize_email($email);
}
public function sanitizeUrl(string $url): string
{
return \esc_url_raw($url);
}
public function wpDie(string $message = '', string $title = '', array $args = []): void
{
\wp_die($message, $title, $args);
}
public function isAjax(): bool
{
return \wp_doing_ajax();
}
public function isAdmin(): bool
{
return \is_admin();
}
}
class WordPressNonceHandler
{
private WordPressSecurityAdapter $securityAdapter;
public function __construct(WordPressSecurityAdapter $securityAdapter)
{
$this->securityAdapter = $securityAdapter;
}
public function createNonce(string $action): string
{
return $this->securityAdapter->createNonce($action);
}
public function verifyNonce(string $nonce, string $action): bool
{
return $this->securityAdapter->verifyNonce($nonce, $action);
}
public function createNonceField(string $action, string $name = '_wpnonce', bool $referer = true): string
{
return \wp_nonce_field($action, $name, $referer, false);
}
public function createNonceUrl(string $actionUrl, string $action, string $name = '_wpnonce'): string
{
return \wp_nonce_url($actionUrl, $action, $name);
}
public function checkAjaxReferer(string $action, string $queryArg = '_wpnonce', bool $die = true): bool
{
return $this->securityAdapter->checkAjaxReferer($action, $queryArg, $die);
}
}
class WordPressCapabilityChecker
{
private WordPressSecurityAdapter $securityAdapter;
public function __construct(WordPressSecurityAdapter $securityAdapter)
{
$this->securityAdapter = $securityAdapter;
}
public function canManageOptions(): bool
{
return $this->securityAdapter->currentUserCan('manage_options');
}
public function canEditPosts(): bool
{
return $this->securityAdapter->currentUserCan('edit_posts');
}
public function canEditPages(): bool
{
return $this->securityAdapter->currentUserCan('edit_pages');
}
public function canPublishPosts(): bool
{
return $this->securityAdapter->currentUserCan('publish_posts');
}
public function canUploadFiles(): bool
{
return $this->securityAdapter->currentUserCan('upload_files');
}
public function canActivatePlugins(): bool
{
return $this->securityAdapter->currentUserCan('activate_plugins');
}
public function canInstallPlugins(): bool
{
return $this->securityAdapter->currentUserCan('install_plugins');
}
public function canUpdateCore(): bool
{
return $this->securityAdapter->currentUserCan('update_core');
}
public function requireCapability(string $capability): void
{
if (!$this->securityAdapter->currentUserCan($capability)) {
$this->securityAdapter->wpDie('Insufficient permissions');
}
}
}
class WordPressCacheAdapter
{
public function get(string $key, $default = null)
{
$value = \wp_cache_get($key);
return $value !== false ? $value : $default;
}
public function set(string $key, $value, int $expiration = 0): bool
{
return \wp_cache_set($key, $value, '', $expiration);
}
public function delete(string $key): bool
{
return \wp_cache_delete($key);
}
public function flush(): bool
{
return \wp_cache_flush();
}
public function add(string $key, $value, int $expiration = 0): bool
{
return \wp_cache_add($key, $value, '', $expiration);
}
public function replace(string $key, $value, int $expiration = 0): bool
{
return \wp_cache_replace($key, $value, '', $expiration);
}
public function increment(string $key, int $offset = 1): int
{
return \wp_cache_incr($key, $offset);
}
public function decrement(string $key, int $offset = 1): int
{
return \wp_cache_decr($key, $offset);
}
}
class WordPressTransientHandler
{
public function get(string $key, $default = null)
{
$value = \get_transient($key);
return $value !== false ? $value : $default;
}
public function set(string $key, $value, int $expiration = 0): bool
{
return \set_transient($key, $value, $expiration);
}
public function delete(string $key): bool
{
return \delete_transient($key);
}
public function getSiteTransient(string $key, $default = null)
{
$value = \get_site_transient($key);
return $value !== false ? $value : $default;
}
public function setSiteTransient(string $key, $value, int $expiration = 0): bool
{
return \set_site_transient($key, $value, $expiration);
}
public function deleteSiteTransient(string $key): bool
{
return \delete_site_transient($key);
}
}
class WordPressObjectCache
{
private WordPressCacheAdapter $cacheAdapter;
public function __construct(WordPressCacheAdapter $cacheAdapter)
{
$this->cacheAdapter = $cacheAdapter;
}
public function getObject(string $key, $default = null)
{
$value = $this->cacheAdapter->get($key, $default);
return is_string($value) ? unserialize($value) : $value;
}
public function setObject(string $key, $object, int $expiration = 0): bool
{
$serialized = serialize($object);
return $this->cacheAdapter->set($key, $serialized, $expiration);
}
public function getArray(string $key, array $default = []): array
{
$value = $this->cacheAdapter->get($key, $default);
return is_array($value) ? $value : $default;
}
public function setArray(string $key, array $array, int $expiration = 0): bool
{
return $this->cacheAdapter->set($key, $array, $expiration);
}
public function getJson(string $key, $default = null)
{
$value = $this->cacheAdapter->get($key, $default);
if (is_string($value)) {
$decoded = json_decode($value, true);
return json_last_error() === JSON_ERROR_NONE ? $decoded : $default;
}
return $value;
}
public function setJson(string $key, $data, int $expiration = 0): bool
{
$json = json_encode($data);
return $this->cacheAdapter->set($key, $json, $expiration);
}
}
// Always use WordPress functions with backslash prefix
$result = \wp_verify_nonce($nonce, $action);
// Use WordPress security functions
$sanitized = \sanitize_text_field($input);
// Check capabilities before actions
if (\current_user_can('manage_options')) {
// Perform admin action
}
// Use WordPress hooks properly
\add_action('init', [$this, 'initialize']);
class WordPressIntegrationTest extends TestCase
{
public function testDatabaseAdapter(): void
{
// Arrange
$adapter = new WordPressDatabaseAdapter();
// Act
$result = $adapter->query('SELECT 1');
// Assert
$this->assertTrue($result);
}
public function testSecurityAdapter(): void
{
// Arrange
$adapter = new WordPressSecurityAdapter();
$nonce = \wp_create_nonce('test_action');
// Act
$result = $adapter->verifyNonce($nonce, 'test_action');
// Assert
$this->assertTrue($result);
}
}
class WordPressException extends Exception
{
public function __construct(string $message, array $context = [], int $code = 0, ?Throwable $previous = null)
{
parent::__construct("WordPress error: {$message}", $code, $previous);
}
}
// Usage
try {
$adapter = new WordPressDatabaseAdapter();
$result = $adapter->insert('table', $data);
} catch (WordPressException $e) {
Logger::error('WordPress operation failed: ' . $e->getMessage());
}
Rake WordPress Adapter cung cấp bridge hoàn chỉnh giữa Rake Core Framework và WordPress với:
// Initialize adapter
$adapter = new WordPressDatabaseAdapter();
$hooks = new WordPressHooksAdapter();
$admin = new WordPressAdminAdapter();
// Use database
$results = $adapter->getResults('SELECT * FROM wp_posts');
// Use hooks
$hooks->addAction('init', [$this, 'initialize']);
// Use admin
$admin->addMenuPage('My Plugin', 'My Plugin', 'manage_options', 'my-plugin', [$this, 'renderPage']);
Tài liệu này sẽ được cập nhật thường xuyên khi có thay đổi trong adapter.