Skip to content

Commit 13f2214

Browse files
authored
Merge pull request #6 from tattersoftware/develop
Update for release
2 parents 4a33379 + fbdde74 commit 13f2214

File tree

15 files changed

+279
-25
lines changed

15 files changed

+279
-25
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: CodeIgniter4 ModuleTests
2+
3+
on:
4+
push:
5+
branches:
6+
- develop
7+
8+
jobs:
9+
build:
10+
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- uses: actions/checkout@v1
15+
16+
- name: Setup PHP
17+
uses: shivammathur/setup-php@master
18+
with:
19+
php-version: '7.2'
20+
extension-csv: intl, json, mbstring, mysqlnd, xdebug, xml
21+
coverage: xdebug
22+
23+
- name: Validate composer.json
24+
run: composer validate
25+
26+
- name: Install dependencies
27+
run: composer install --prefer-dist --no-progress --no-suggest
28+
29+
- name: Run test suite
30+
run: composer run-script test

README.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,12 @@ in the comments. If no config file is found in **app/Config** the library will u
4242
* *Publish*: (not yet available) Modifies environments to match schema specs
4343

4444
The **Schemas** service is also available to simplify a workflow with convenient wrapper functions.
45+
At its most basic (with automation enabled), the service will draft, archive, and return
46+
a schema with one simple command:
4547

48+
$schema = service('schemas')->get();
49+
50+
You may want to control when portions of the workflow take place to optimize performance.
4651
Here is an example of one common process, mapping the default database group and storing
4752
the resulting schema to the cache:
4853

@@ -55,7 +60,7 @@ $schemas->draft('database')->archive('cache');
5560
$schema = $schemas->read('cache')->draft('model')->get();
5661
```
5762

58-
If you need to deviate from the default configuration you can inject the handlers yourself:
63+
If you need to deviate from default handler configurations you can inject the handlers yourself:
5964
```
6065
$db = db_connect('alternate_database');
6166
$databaseHandler = new \Tatter\Schemas\Drafter\Handlers\DatabaseHandler(null, $db);
@@ -72,7 +77,16 @@ Use the command to test and troubleshoot, or add it to your cron for periodic sc
7277

7378
php spark schemas -draft database,model -archive cache
7479

75-
## Autodetection
80+
## Automation
81+
82+
By default automation is turned on, but this can be configured via the `$automate` toggles
83+
in your config file. Automation will allow the service to fall back on a Reader, or even on
84+
a Drafter should it fail to have a schema already loaded. While automation makes using the
85+
library very easy, it can come at a performance cost if your application is not configured
86+
correctly, since it may draft a schema on every page load. Use automation to help but don't
87+
let it become a crutch.
88+
89+
## Structure
7690

7791
**Schemas** uses foreign keys, indexes, and naming convention to detect relationships
7892
automatically. Make sure your database is setup using the appropriate keys and

bin/Schemas.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ class Schemas extends \Tatter\Schemas\Config\Schemas
1414
{
1515
// Whether to continue instead of throwing exceptions
1616
public $silent = true;
17+
18+
// Which tasks to automate when a schema is not available from the service
19+
public $automate = [
20+
'draft' => true,
21+
'archive' => true,
22+
'read' => true,
23+
];
1724

1825
//--------------------------------------------------------------------
1926
// Drafting

src/Config/Schemas.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@ class Schemas extends BaseConfig
66
{
77
// Whether to continue instead of throwing exceptions
88
public $silent = true;
9+
10+
// Which tasks to automate when a schema is not available from the service
11+
public $automate = [
12+
'draft' => true,
13+
'archive' => true,
14+
'read' => true,
15+
];
916

1017
//--------------------------------------------------------------------
1118
// Drafting

src/Exceptions/SchemasException.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,14 @@ public static function forMethodNotImplemented($class, $method)
1919
{
2020
return new static(lang('Schemas.methodNotImplemented', [$class, $method]));
2121
}
22+
23+
public static function forNoSchema()
24+
{
25+
return new static(lang('Schemas.noSchema'));
26+
}
27+
28+
public static function forReaderNotReady()
29+
{
30+
return new static(lang('Schemas.readerNotReady'));
31+
}
2232
}

src/Language/en/Schemas.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@
66
'missingField' => '{0} is missing {1}',
77
'emptySchemaFile' => 'Could not read file contents from {0}',
88
'emptySchemaDirectory' => 'No files found in schema directory: {0}',
9+
'noSchema' => 'No schema is available and automation failed or is disabled',
10+
'readerNotReady' => 'Unable to use Reader: not ready',
911
];

src/Reader/BaseReader.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44

55
class BaseReader extends BaseHandler
66
{
7+
/**
8+
* Whether the reader is in a state to be used
9+
*
10+
* @var bool
11+
*/
12+
protected $ready = false;
13+
714
/**
815
* The currently loaded schema.
916
* Could be static but since Reader is usually called by
@@ -13,6 +20,37 @@ class BaseReader extends BaseHandler
1320
*/
1421
protected $schema;
1522

23+
/**
24+
* Indicate whether the reader is in a state to be used
25+
*
26+
* @param array|string $tables
27+
*/
28+
public function ready(): bool
29+
{
30+
return $this->ready;
31+
}
32+
33+
/**
34+
* Check that reader is ready before using its functions
35+
*
36+
* @param array|string $tables
37+
*/
38+
protected function ensureReady(): bool
39+
{
40+
if ($this->ready)
41+
{
42+
return true;
43+
}
44+
45+
if (! $this->config->silent)
46+
{
47+
throw SchemasException::forReaderNotReady();
48+
}
49+
50+
$this->errors[] = lang('Schemas.notReady');
51+
return false;
52+
}
53+
1654
/**
1755
* Dummy implementation for classes that cannot lazy load
1856
*

src/Reader/Handlers/CacheHandler.php

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,22 @@ public function __construct(BaseConfig $config = null, CacheInterface $cache = n
2828
$this->cacheInit($cache);
2929

3030
// Start $tables as the cached scaffold version
31-
$scaffold = $this->cache->get($this->cacheKey);
32-
33-
$this->tables = $scaffold->tables ?? new Mergeable();
31+
if ($scaffold = $this->cache->get($this->cacheKey))
32+
{
33+
if (isset($scaffold->tables))
34+
{
35+
$this->tables = $scaffold->tables ?? new Mergeable();
36+
$this->ready = true;
37+
}
38+
}
3439
}
3540

3641
/**
3742
* Return the current tables, fetched or not
3843
*
39-
* @return array String error messages
44+
* @return array|null
4045
*/
41-
public function getTables(): Mergeable
46+
public function getTables(): ?Mergeable
4247
{
4348
return $this->tables;
4449
}
@@ -52,6 +57,11 @@ public function getTables(): Mergeable
5257
*/
5358
public function fetch($tables)
5459
{
60+
if (! $this->ensureReady())
61+
{
62+
return $this;
63+
}
64+
5565
if (is_string($tables))
5666
{
5767
$tables = [$tables];
@@ -75,6 +85,11 @@ public function fetch($tables)
7585
*/
7686
public function fetchAll()
7787
{
88+
if (! $this->ensureReady())
89+
{
90+
return $this;
91+
}
92+
7893
foreach ($this->tables as $tableName => $value)
7994
{
8095
if ($value === true)

src/Reader/ReaderInterface.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44

55
interface ReaderInterface extends \Countable, \IteratorAggregate
66
{
7+
/**
8+
* Indicate whether the reader is in a state to be used
9+
*
10+
* @return bool
11+
*/
12+
public function ready(): bool;
13+
714
/**
815
* Fetch specified tables into the scaffold
916
*

src/Schemas.php

Lines changed: 86 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,11 @@ public function __construct(BaseConfig $config, Schema $schema = null)
3232
{
3333
$this->config = $config;
3434

35-
// Store an initial schema
36-
$this->schema = $schema ?? new Schema();
35+
// Store initial schema
36+
if (! is_null($schema))
37+
{
38+
$this->schema = $schema;
39+
}
3740
}
3841

3942
/**
@@ -49,13 +52,78 @@ public function getErrors(): array
4952
}
5053

5154
/**
52-
* Return the current schema
55+
* Reset the current schema and errors
5356
*
54-
* @return Schema The current schema object
57+
* @return $this
58+
*/
59+
public function reset()
60+
{
61+
$this->schema = null;
62+
$this->errors = [];
63+
64+
return $this;
65+
}
66+
67+
/**
68+
* Set the current schema; used mostly for testing
69+
*
70+
* @return $this
71+
*/
72+
public function setSchema(Schema $schema)
73+
{
74+
$this->schema = $schema;
75+
76+
return $this;
77+
}
78+
79+
/**
80+
* Return the current schema; if automation is enabled then read or draft a missing schema
81+
*
82+
* @return Schema|null The current schema object
5583
*/
5684
public function get(): ?Schema
5785
{
58-
return $this->schema;
86+
if (! is_null($this->schema))
87+
{
88+
return $this->schema;
89+
}
90+
91+
// No schema loaded - try the default reader
92+
if ($this->config->automate['read'])
93+
{
94+
$this->read();
95+
96+
if (! is_null($this->schema))
97+
{
98+
return $this->schema;
99+
}
100+
}
101+
102+
// Still no schema - try a default draft
103+
if ($this->config->automate['draft'])
104+
{
105+
$this->draft();
106+
107+
if (! is_null($this->schema))
108+
{
109+
// If the draft succeeded check if we should archive it
110+
if ($this->config->automate['archive'])
111+
{
112+
$this->archive();
113+
}
114+
115+
return $this->schema;
116+
}
117+
}
118+
119+
// Absolute failure
120+
if (! $this->config->silent)
121+
{
122+
throw SchemasException::forNoSchema();
123+
}
124+
125+
$this->errors[] = lang('Schemas.noSchema');
126+
return null;
59127
}
60128

61129
/**
@@ -86,7 +154,14 @@ public function draft($handlers = null)
86154
$handler = new $handler($this->config);
87155
}
88156

89-
$this->schema->merge($handler->draft());
157+
if (is_null($this->schema))
158+
{
159+
$this->schema = $handler->draft();
160+
}
161+
else
162+
{
163+
$this->schema->merge($handler->draft());
164+
}
90165

91166
$this->errors = array_merge($this->errors, $handler->getErrors());
92167
}
@@ -153,8 +228,11 @@ public function read($handler = null)
153228

154229
$this->errors = array_merge($this->errors, $handler->getErrors());
155230

156-
// Replace the current schema with a new one using the injected readHandler
157-
$this->schema = new Schema($handler);
231+
// If all went well then set the current schema to a new one using the injected reader
232+
if ($handler->ready())
233+
{
234+
$this->schema = new Schema($handler);
235+
}
158236

159237
return $this;
160238
}

0 commit comments

Comments
 (0)