Skip to content

Commit 016fcda

Browse files
authored
Branch 0.3 (#2)
## Tests Unit and integration tests have been added, they cover 100% of the current code. Sadly, we're stuck with PHPUNIT 7.5.20 because of WP’s test suite 😢. ## AbstractCRUD - `prepare_select_for_query()`: - Trim quotes. - Add backticks. - Remove empty fields. - Don't use `esc_sql()` anymore. - `get_placeholders()`: - Return only valid columns. - `cast()`: - When the placeholder is not `%d` nor `%f` and the column is not serializable, return numeric values as string. ## Basic - `get()`: - Disallowed `ARRAY_N` value for the output type, as it conflicts with `cast_row()`. ## AbstractTableDefinition - An instance of `Worker` can be injected into the constructor. ## DBUtilities / DBWorker\Worker - The static class `DBUtilities` is now the instanciable class `DBWorker\Worker` that implements `DBWorker\WorkerInterface`. Seeing how `DBUtilities` was used at this point, using a static class was not shorter. The advantage now is that the instance can be typehinted against the interface. Although, it is not typehinted directly in `AbstractTableDefinition` today, we need php 7.1 for nullable typehints (this is for a future release), but `instanceof` is used for the time being. The full instanciation is now `new Table( new MyTableDefinition( new MyWorker() ) )`. `AbstractTableDefinition` falls back to `new DBWorker\Worker()` if no custom worker is specified as argument. - Hide database errors in most methods. - `table_exists()`: - Fix returned value by comparing the query value to the unescaped name of the table. - New method `get_last_error()`, which returns the last `$wpdb` error. - `sanitize_table_name()`: - Allow `0` as a valid table name. - `quote_string()`: - Do not escape simple quotes anymore, it is done by `esc_sql()` in `prepare_values_list()`. - `can_log()`: - New filter `screenfeed_autowpdb_can_log`. ## Table - New method `get_last_error()`, which returns the last DB error. - `clone_to()`: - Allow `0` as a valid table name. ## TableUpgrader - Use `static` instead of `self`, so the class can be extended and tested. - `init()`: - Move tests from the constructor to the `init()` method. - Don't add the upgrade hook if the hook name is set to `false`. - `table_is_up_to_date()`: - Fix when downgrade is handled, it was returning the opposite of the expected value.
1 parent 07b3f9b commit 016fcda

142 files changed

Lines changed: 9569 additions & 157 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Directories
2+
/.vscode
23
/report
34
/vendor
45

.markdownlint.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"ul-indent": { "indent": 4 },
3+
"line-length": false,
4+
"no-hard-tabs": false
5+
}

README.md

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,35 @@ Requires **php 7.0** and **WordPress 4.9.6**. With php 7.1+, can be used with Wo
1818

1919
With composer:
2020

21-
```
21+
```json
2222
"require": {
2323
"screenfeed/autowpdb": "dev-master"
2424
},
2525
```
2626

2727
## How to use
2828

29-
Create 2 classes and youre ready:
29+
Create 1 or 2 classes and you're ready:
3030

3131
* One that "defines" your custom table (name, default values, value types, schema, etc) by extending *TableDefinition\AbstractTableDefinition*,
32-
* One containing your CRUD methods (optional) by extending *CRUD\Basic*.
32+
* Optionally, one containing your CRUD methods by extending *CRUD\Basic*.
33+
34+
Example:
35+
36+
```php
37+
use Screenfeed\AutoWPDB\Table;
38+
use Screenfeed\AutoWPDB\TableUpgrader;
39+
40+
add_action( 'plugins_loaded', 'my_plugin_init' );
41+
42+
function my_plugin_init() {
43+
// Your class defining your custom DB table.
44+
$table_def = new MyCustomTableDefinition();
45+
46+
// The upgrader: it will upgrade your DB table automatically if the schema changes.
47+
$upgrader = new TableUpgrader( new Table( $table_def ) );
48+
$upgrader->init();
49+
}
50+
```
3351

3452
Please take a look at [this plugin](https://github.com/Screenfeed/autowpdb-example-plugin) to see an example of use.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<?php
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
namespace Screenfeed\AutoWPDB\Tests\Fixtures\src\CRUD;
3+
4+
use Screenfeed\AutoWPDB\CRUD\AbstractCRUD;
5+
6+
class CustomCRUD extends AbstractCRUD {
7+
8+
public function insert( array $data ): int {
9+
return 0;
10+
}
11+
12+
public function replace( array $data ): int {
13+
return 0;
14+
}
15+
16+
public function get( array $select, array $where, string $output_type = OBJECT ) {
17+
return null;
18+
}
19+
20+
public function update( array $data, array $where ) {
21+
return false;
22+
}
23+
24+
public function delete( array $where ) {
25+
return false;
26+
}
27+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
namespace Screenfeed\AutoWPDB\Tests\Fixtures\src\DBWorker\Worker;
3+
4+
use Screenfeed\AutoWPDB\DBWorker\Worker;
5+
6+
/**
7+
* Allows to perform some Integration tests for Worker->create_table() and Worker->delete_table().
8+
* During the integration tests, WP only allows to create temporary tables, which won't be listed in 'SHOW TABLES'.
9+
*
10+
* @source https://wordpress.stackexchange.com/questions/220275/wordpress-unit-testing-cannot-create-tables
11+
*/
12+
class WorkerIntegration extends Worker {
13+
14+
public function table_exists( string $table_name ): bool {
15+
global $wpdb;
16+
17+
$query = "SELECT * FROM `$table_name` LIMIT 1";
18+
$wpdb->get_results( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
19+
20+
return "Table '{$wpdb->dbname}.$table_name' doesn't exist" !== $wpdb->last_error;
21+
}
22+
}
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
<?php
2+
namespace Screenfeed\AutoWPDB\Tests\Fixtures\src\Table;
3+
4+
use Screenfeed\AutoWPDB\TableDefinition\AbstractTableDefinition;
5+
6+
/**
7+
* Class that defines our custom table.
8+
*
9+
* @since 0.3
10+
*/
11+
class CustomTable extends AbstractTableDefinition {
12+
protected $table_version;
13+
protected $schema;
14+
protected $short_name;
15+
protected $table_is_global;
16+
17+
protected $default_table_version = 102;
18+
protected $default_schema = "
19+
file_id bigint(20) unsigned NOT NULL auto_increment,
20+
file_date datetime NOT NULL default '0000-00-00 00:00:00',
21+
path varchar(191) NOT NULL default '',
22+
mime_type varchar(100) NOT NULL default '',
23+
modified tinyint(1) unsigned NOT NULL default 0,
24+
width smallint(2) unsigned NOT NULL default 0,
25+
height smallint(2) unsigned NOT NULL default 0,
26+
file_size int(4) unsigned NOT NULL default 0,
27+
status varchar(20) default NULL,
28+
error varchar(255) default NULL,
29+
data longtext default NULL,
30+
PRIMARY KEY (file_id),
31+
UNIQUE KEY path (path),
32+
KEY status (status),
33+
KEY modified (modified)";
34+
protected $default_short_name = 'foobar';
35+
protected $default_table_is_global = true;
36+
37+
public function get_table_version(): int {
38+
if ( ! isset( $this->table_version ) ) {
39+
$this->table_version = $this->default_table_version;
40+
}
41+
return $this->table_version;
42+
}
43+
44+
public function get_table_short_name(): string {
45+
if ( ! isset( $this->short_name ) ) {
46+
$this->short_name = $this->default_short_name;
47+
}
48+
return $this->short_name;
49+
}
50+
51+
public function is_table_global(): bool {
52+
if ( ! isset( $this->table_is_global ) ) {
53+
$this->table_is_global = $this->default_table_is_global;
54+
}
55+
return $this->table_is_global;
56+
}
57+
58+
public function get_primary_key(): string {
59+
return 'file_id';
60+
}
61+
62+
public function get_column_placeholders(): array {
63+
return [
64+
'file_id' => '%d',
65+
'file_date' => '%s',
66+
'path' => '%s',
67+
'mime_type' => '%s',
68+
'modified' => '%d',
69+
'width' => '%d',
70+
'height' => '%d',
71+
'file_size' => '%d',
72+
'status' => '%s',
73+
'error' => '%s',
74+
'data' => '%s',
75+
];
76+
}
77+
78+
public function get_column_defaults(): array {
79+
return [
80+
'file_id' => 0,
81+
'file_date' => '0000-00-00 00:00:00',
82+
'path' => '',
83+
'mime_type' => '',
84+
'modified' => 0,
85+
'width' => 0,
86+
'height' => 0,
87+
'file_size' => 0,
88+
'status' => null,
89+
'error' => null,
90+
'data' => [],
91+
];
92+
}
93+
94+
public function get_table_schema(): string {
95+
if ( ! isset( $this->schema ) ) {
96+
$this->schema = $this->default_schema;
97+
}
98+
return $this->schema;
99+
}
100+
101+
/** ----------------------------------------------------------------------------------------- */
102+
/** SETTERS ================================================================================= */
103+
/** ----------------------------------------------------------------------------------------- */
104+
105+
public function set_table_version( $table_version ) {
106+
$this->table_version = $table_version;
107+
}
108+
109+
public function set_table_short_name( $short_name ) {
110+
$this->short_name = $short_name;
111+
}
112+
113+
public function set_table_schema( $schema ) {
114+
$this->schema = $schema;
115+
}
116+
117+
public function set_table_is_global( $table_is_global ) {
118+
$this->table_is_global = $table_is_global;
119+
}
120+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?php
2+
3+
namespace Screenfeed\AutoWPDB\Tests\Integration;
4+
5+
trait TemporaryTableTrait {
6+
protected $table_name = 'foobar';
7+
protected $target_table_name = 'targettable';
8+
protected $drop_table = false;
9+
protected $drop_target_table = false;
10+
11+
protected function init_temporary_tables() {
12+
global $wpdb;
13+
14+
$this->table_name = $wpdb->prefix . $this->table_name;
15+
$this->target_table_name = $wpdb->prefix . $this->target_table_name;
16+
}
17+
18+
protected function maybe_drop_temporary_tables() {
19+
global $wpdb;
20+
21+
if ( $this->drop_table ) {
22+
$query = "DROP TEMPORARY TABLE IF EXISTS `{$this->table_name}`";
23+
$result = $wpdb->query( $query );
24+
}
25+
26+
if ( $this->drop_target_table ) {
27+
$query = "DROP TEMPORARY TABLE IF EXISTS `{$this->target_table_name}`";
28+
$result = $wpdb->query( $query );
29+
}
30+
}
31+
32+
protected function create_table( $table_name = '' ) {
33+
global $wpdb;
34+
35+
if ( empty( $table_name ) ) {
36+
$table_name = $this->table_name;
37+
}
38+
39+
$charset_collate = $wpdb->get_charset_collate();
40+
$schema = "
41+
id bigint(20) unsigned NOT NULL auto_increment,
42+
data longtext default NULL,
43+
PRIMARY KEY (id)";
44+
45+
$wpdb->query( "CREATE TEMPORARY TABLE `$table_name` ($schema) $charset_collate" );
46+
}
47+
48+
protected function add_row( $data, $table_name = '' ) {
49+
global $wpdb;
50+
51+
if ( empty( $table_name ) ) {
52+
$table_name = $this->table_name;
53+
}
54+
55+
$wpdb->insert(
56+
$table_name,
57+
[ 'data' => $data ],
58+
[ 'data' => '%s' ]
59+
);
60+
61+
return (int) $wpdb->insert_id;
62+
}
63+
64+
protected function get_rows( $table_name = '' ) {
65+
global $wpdb;
66+
67+
if ( empty( $table_name ) ) {
68+
$table_name = $this->table_name;
69+
}
70+
71+
return $wpdb->get_results(
72+
"SELECT * FROM $table_name ORDER BY `id` ASC",
73+
ARRAY_A
74+
);
75+
}
76+
77+
protected function get_last_row( $table_name = '' ) {
78+
global $wpdb;
79+
80+
if ( empty( $table_name ) ) {
81+
$table_name = $this->table_name;
82+
}
83+
84+
return $wpdb->get_row(
85+
"SELECT * FROM {$table_name} ORDER BY `id` DESC LIMIT 1;",
86+
ARRAY_A
87+
);
88+
}
89+
}

Tests/Integration/TestCase.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
namespace Screenfeed\AutoWPDB\Tests\Integration;
4+
5+
use Brain\Monkey;
6+
use Screenfeed\AutoWPDB\Tests\TestCaseTrait;
7+
use WP_UnitTestCase;
8+
9+
abstract class TestCase extends WP_UnitTestCase {
10+
use TestCaseTrait;
11+
12+
/**
13+
* Prepares the test environment before each test.
14+
*/
15+
public function setUp() {
16+
parent::setUp();
17+
Monkey\setUp();
18+
}
19+
20+
/**
21+
* Cleans up the test environment after each test.
22+
*/
23+
public function tearDown() {
24+
Monkey\tearDown();
25+
parent::tearDown();
26+
}
27+
28+
public function return_true() {
29+
return true;
30+
}
31+
32+
public function return_false() {
33+
return false;
34+
}
35+
}

0 commit comments

Comments
 (0)