Skip to content

Commit 8c4b696

Browse files
authored
Added the database module storage adapter. (#9)
* Added the database module storage adapter. * Added covers annotations.
1 parent 6d475f1 commit 8c4b696

6 files changed

Lines changed: 450 additions & 2 deletions

File tree

.github/workflows/phpunit.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ jobs:
6262
repository: WordPress/wordpress-develop
6363
path: wordpress-develop
6464

65+
- name: Checkout database-module
66+
uses: actions/checkout@v6
67+
with:
68+
repository: TangibleInc/database-module
69+
path: database-module
70+
6571
- name: Setup WordPress test config
6672
run: |
6773
cp wordpress-develop/wp-tests-config-sample.php wordpress-develop/wp-tests-config.php
@@ -73,4 +79,5 @@ jobs:
7379
- name: Run PHPUnit
7480
env:
7581
WORDPRESS_DEVELOP_DIR: ${{ github.workspace }}/wordpress-develop
82+
DATABASE_MODULE_DIR: ${{ github.workspace }}/database-module
7683
run: ./vendor/bin/phpunit

Makefile

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
.PHONY: install test test-all setup-integrations clean help
2+
3+
# Default WordPress develop location
4+
WORDPRESS_DEVELOP_DIR ?= $(HOME)/workspace/wordpress-develop
5+
DATABASE_MODULE_DIR ?= $(shell dirname $(CURDIR))/database-module
6+
7+
help:
8+
@echo "Available targets:"
9+
@echo " make install - Install composer dependencies"
10+
@echo " make test - Run tests (skips integration tests if deps missing)"
11+
@echo " make test-all - Run all tests (requires setup-integrations first)"
12+
@echo " make setup-integrations - Clone optional integration dependencies"
13+
@echo " make setup-wp - Clone WordPress develop for testing"
14+
@echo " make clean - Remove cloned dependencies"
15+
16+
install:
17+
composer install
18+
19+
test:
20+
WORDPRESS_DEVELOP_DIR=$(WORDPRESS_DEVELOP_DIR) ./vendor/bin/phpunit
21+
22+
test-all: setup-integrations
23+
WORDPRESS_DEVELOP_DIR=$(WORDPRESS_DEVELOP_DIR) \
24+
DATABASE_MODULE_DIR=$(DATABASE_MODULE_DIR) \
25+
./vendor/bin/phpunit
26+
27+
setup-integrations: setup-database-module
28+
29+
setup-database-module:
30+
@if [ ! -d "$(DATABASE_MODULE_DIR)" ]; then \
31+
echo "Cloning database-module to $(DATABASE_MODULE_DIR)..."; \
32+
git clone https://github.com/tangibleinc/database-module.git $(DATABASE_MODULE_DIR); \
33+
else \
34+
echo "database-module already exists at $(DATABASE_MODULE_DIR)"; \
35+
fi
36+
37+
setup-wp:
38+
@if [ ! -d "$(WORDPRESS_DEVELOP_DIR)" ]; then \
39+
echo "Cloning wordpress-develop to $(WORDPRESS_DEVELOP_DIR)..."; \
40+
git clone --depth=1 https://github.com/WordPress/wordpress-develop.git $(WORDPRESS_DEVELOP_DIR); \
41+
cp $(WORDPRESS_DEVELOP_DIR)/wp-tests-config-sample.php $(WORDPRESS_DEVELOP_DIR)/wp-tests-config.php; \
42+
echo "NOTE: Edit $(WORDPRESS_DEVELOP_DIR)/wp-tests-config.php with your database credentials"; \
43+
else \
44+
echo "wordpress-develop already exists at $(WORDPRESS_DEVELOP_DIR)"; \
45+
fi
46+
47+
clean:
48+
@echo "This will remove cloned integration dependencies. Are you sure? [y/N]" && read ans && [ $${ans:-N} = y ]
49+
rm -rf $(DATABASE_MODULE_DIR)

composer.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@
1717
"Tangible\\Object\\Tests\\": "./tests/phpunit/"
1818
}
1919
},
20+
"scripts": {
21+
"test": "phpunit",
22+
"setup:integrations": [
23+
"@setup:database-module"
24+
],
25+
"setup:database-module": "[ -d ../database-module ] || git clone https://github.com/tangibleinc/database-module.git ../database-module"
26+
},
2027
"minimum-stability": "dev",
2128
"prefer-stable": true,
2229
"license": "GPL-2.0-only"
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
<?php declare( strict_types=1 );
2+
3+
namespace Tangible\DataObject\Storage;
4+
5+
use Tangible\DataObject\PluralStorage;
6+
use TDB_Table;
7+
8+
/**
9+
* Storage adapter for the Tangible Database Module library.
10+
*
11+
* This adapter implements the PluralStorage interface using the database-module
12+
* library (TDB) instead of WordPress custom post types, providing direct database
13+
* table storage for entities.
14+
*
15+
* @see https://bitbucket.org/tangibleinc/tangible-database-module
16+
*/
17+
class DatabaseModuleStorage implements PluralStorage {
18+
19+
protected string $slug;
20+
21+
protected ?TDB_Table $table = null;
22+
23+
public function __construct( string $slug ) {
24+
$this->slug = $slug;
25+
}
26+
27+
/**
28+
* Register a database table using the database-module library.
29+
*
30+
* @param string $slug The table name/slug.
31+
* @param array $settings Settings array, should include 'schema' for field definitions.
32+
*/
33+
public function register( string $slug, array $settings ): void {
34+
if ( ! function_exists( 'tdb_register_table' ) ) {
35+
return;
36+
}
37+
38+
$defaults = [
39+
'show_ui' => false,
40+
'show_in_rest' => false,
41+
'version' => 1,
42+
];
43+
44+
$settings = array_merge( $defaults, $settings );
45+
46+
$this->table = tdb_register_table( $slug, $settings );
47+
48+
// Ensure table is created (normally happens on admin_init)
49+
if ( $this->table && $this->table->db ) {
50+
$this->table->db->maybe_upgrade();
51+
}
52+
}
53+
54+
/**
55+
* Get the underlying TDB_Table instance.
56+
*/
57+
public function get_table(): ?TDB_Table {
58+
return $this->table;
59+
}
60+
61+
public function insert( array $data ): int {
62+
if ( ! $this->table ) {
63+
return 0;
64+
}
65+
66+
$id = $this->table->db->insert( $data );
67+
68+
return $id ? (int) $id : 0;
69+
}
70+
71+
public function update( int $id, array $data ): void {
72+
if ( ! $this->table ) {
73+
return;
74+
}
75+
76+
$primary_key = $this->table->db->primary_key;
77+
78+
$this->table->db->update( $data, [ $primary_key => $id ] );
79+
}
80+
81+
public function delete( int $id ): void {
82+
if ( ! $this->table ) {
83+
return;
84+
}
85+
86+
$this->table->db->delete( $id );
87+
}
88+
89+
public function find( int $id ): ?array {
90+
if ( ! $this->table ) {
91+
return null;
92+
}
93+
94+
$row = $this->table->db->get( $id );
95+
96+
if ( ! $row ) {
97+
return null;
98+
}
99+
100+
return (array) $row;
101+
}
102+
103+
public function all(): array {
104+
if ( ! $this->table ) {
105+
return [];
106+
}
107+
108+
$rows = $this->table->db->query();
109+
110+
if ( ! $rows ) {
111+
return [];
112+
}
113+
114+
$results = [];
115+
$primary_key = $this->table->db->primary_key;
116+
117+
foreach ( $rows as $row ) {
118+
$data = (array) $row;
119+
if ( isset( $data[ $primary_key ] ) ) {
120+
$data['id'] = (int) $data[ $primary_key ];
121+
}
122+
$results[] = $data;
123+
}
124+
125+
return $results;
126+
}
127+
}

tests/bootstrap.php

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22

33
/**
44
* Tests: References
5-
*
5+
*
66
* - [PHPUnit](https://github.com/sebastianbergmann/phpunit)
77
* - [PHPUnit Polyfills](https://github.com/Yoast/PHPUnit-Polyfills)
88
* - [WP_UnitTestCase](https://github.com/WordPress/wordpress-develop/blob/trunk/tests/phpunit/includes/abstract-testcase.php)
99
* - [Assertions](https://docs.phpunit.de/en/10.2/assertions.html)
1010
*/
1111

12-
if ( ! $_WORDPRESS_DEVELOP_DIR = getenv( 'WORDPRESS_DEVELOP_DIR' ) ) {
12+
if ( ! $_WORDPRESS_DEVELOP_DIR = getenv( 'WORDPRESS_DEVELOP_DIR' ) ) {
1313
$_WORDPRESS_DEVELOP_DIR = __DIR__ . '/../wordpress-develop';
1414
}
1515

@@ -22,4 +22,23 @@
2222
$_WORDPRESS_TESTS_DIR = $_WORDPRESS_DEVELOP_DIR . '/tests/phpunit';
2323
}
2424

25+
/**
26+
* Optional: Load the database-module library for DatabaseModuleStorage tests.
27+
* Set DATABASE_MODULE_DIR environment variable to override the default path.
28+
*/
29+
if ( ! $_DATABASE_MODULE_DIR = getenv( 'DATABASE_MODULE_DIR' ) ) {
30+
$_DATABASE_MODULE_DIR = __DIR__ . '/../../database-module';
31+
}
32+
33+
// Load WP test functions first (provides tests_add_filter)
34+
require_once $_WORDPRESS_TESTS_DIR . '/includes/functions.php';
35+
36+
// Load database-module if available
37+
if ( file_exists( $_DATABASE_MODULE_DIR . '/index.php' ) ) {
38+
tests_add_filter( 'muplugins_loaded', function() use ( $_DATABASE_MODULE_DIR ) {
39+
require_once $_DATABASE_MODULE_DIR . '/index.php';
40+
});
41+
}
42+
43+
// Now load the rest of WordPress
2544
require $_WORDPRESS_TESTS_DIR . '/includes/bootstrap.php';

0 commit comments

Comments
 (0)