Skip to content

Commit

Permalink
Tidy
Browse files Browse the repository at this point in the history
  • Loading branch information
olvlvl committed Mar 26, 2023
1 parent d263e2b commit 29d382c
Show file tree
Hide file tree
Showing 22 changed files with 181 additions and 158 deletions.
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ insert_final_newline = true
indent_style = space
indent_size = 4

[{*.yaml,*yml,*.neon}]
[{*.yaml,*.yml,*.neon,*.json}]
indent_size = 2
13 changes: 13 additions & 0 deletions .scrutinizer.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
build:
nodes:
analysis:
tests:
override:
- php-scrutinizer-run
image: default-bionic
environment:
php:
version: "8.1"
filter:
excluded_paths:
- 'tests/*'
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ vendor:
test-dependencies: vendor

.PHONY: test
test: test-dependencies test-cleanup
test: test-dependencies
@$(PHPUNIT) $(ARGS)

.PHONY: test-coverage
Expand All @@ -33,7 +33,7 @@ test-coveralls: test-dependencies

.PHONY: test-cleanup
test-cleanup:
rm -rf tests/sandbox/*
@rm -rf tests/sandbox/*

.PHONY: test-container
test-container: test-container-81
Expand Down
65 changes: 28 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -432,54 +432,45 @@ and the primary key of the parent is used to link records together. When the mod
tables are joined. When values are inserted or updated, they are split to update the various
tables. Also, the connection of the parent model is inherited.

The `EXTENDING` attribute specifies the model to extend.

```php
<?php

namespace App;

use ICanBoogie\ActiveRecord\ConfigBuilder;
use ICanBoogie\ActiveRecord\Model;
use ICanBoogie\ActiveRecord\ModelCollection;
use ICanBoogie\DateTime;
use ICanBoogie\ActiveRecord\ModelDefinition;
use ICanBoogie\ActiveRecord\SchemaBuilder;use ICanBoogie\DateTime;

/* @var $connections \ICanBoogie\ActiveRecord\ConnectionCollection */
/* @var ConfigBuilder $config */

$models = new ModelCollection($connections, [

'nodes' => [

Model::SCHEMA => [

'nid' => 'serial',
'title' => 'varchar'

]
],

'contents' => [

Model::EXTENDING => 'nodes',
Model::SCHEMA => [

'body' => 'text',
'date' => 'date'

]
],

'news' => [

Model::EXTENDING => 'contents'

]
]);
$config
->add_model(
id: 'nodes',
schema_builder: fn(SchemaBuilder $b) => $b
->add_serial('nid', primary: true)
->add_varchar('title'),
activerecord_class: Node::class
)
->add_model(
id: 'articles',
schema_builder: fn(SchemaBuilder $b) => $b
->add_varchar('body')
->add_date('date'),
activerecord_class: Article::class,
extends: 'nodes'
);

$models['news']->save([
// …

'title' => "Testing!",
'body' => "Testing...",
$article = Article::from([
'title' => "My Article",
'body' => "Testing",
'date' => DateTime::now()

]);

$article->save();
```

Contrary to tables, models are not required to define a schema if they extend another model, but
Expand Down
112 changes: 54 additions & 58 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,60 +1,56 @@
{
"name": "icanboogie/activerecord",
"type": "library",
"description": "ActiveRecord Object-relational mapping",
"keywords": [
"orm",
"database",
"activerecord"
],
"homepage": "https://icanboogie.org/",
"license": "BSD-3-Clause",
"authors": [
{
"name": "Olivier Laviale",
"email": "olivier.laviale@gmail.com",
"homepage": "https://olvlvl.com/",
"role": "Developer"
}
],
"support": {
"issues": "https://github.com/ICanBoogie/ActiveRecord/issues",
"source": "https://github.com/ICanBoogie/ActiveRecord"
},
"config": {
"sort-packages": true
},
"minimum-stability": "dev",
"prefer-stable": true,
"prefer-dist": true,
"require": {
"php": ">=8.1",
"ext-pdo": "*",
"icanboogie/datetime": "^6.0",
"icanboogie/inflector": "^2.0",
"icanboogie/prototype": "^6.0",
"icanboogie/validate": "^6.0"
},
"require-dev": {
"ext-pdo_mysql": "*",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^10.0"
},
"suggest": {
"icanboogie/bind-activerecord": "Binds icanboogie/artiverecord to ICanBoogie"
},
"autoload": {
"psr-4": {
"ICanBoogie\\": "lib",
"ICanBoogie\\ActiveRecord\\": "lib/ActiveRecord"
},
"files": [
"helpers.php"
]
},
"autoload-dev": {
"psr-4": {
"Test\\ICanBoogie\\": "tests"
}
}
"name": "icanboogie/activerecord",
"type": "library",
"description": "ActiveRecord Object-relational mapping",
"keywords": [
"orm",
"database",
"activerecord"
],
"homepage": "https://icanboogie.org/",
"license": "BSD-3-Clause",
"authors": [
{
"name": "Olivier Laviale",
"email": "olivier.laviale@gmail.com",
"homepage": "https://olvlvl.com/",
"role": "Developer"
}
],
"support": {
"issues": "https://github.com/ICanBoogie/ActiveRecord/issues",
"source": "https://github.com/ICanBoogie/ActiveRecord"
},
"config": {
"sort-packages": true
},
"minimum-stability": "dev",
"prefer-stable": true,
"require": {
"php": ">=8.1",
"ext-pdo": "*",
"icanboogie/datetime": "^6.0",
"icanboogie/inflector": "^2.0",
"icanboogie/prototype": "^6.0",
"icanboogie/validate": "^6.0"
},
"require-dev": {
"ext-pdo_mysql": "*",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^10.0"
},
"autoload": {
"psr-4": {
"ICanBoogie\\": "lib",
"ICanBoogie\\ActiveRecord\\": "lib/ActiveRecord"
},
"files": [
"helpers.php"
]
},
"autoload-dev": {
"psr-4": {
"Test\\ICanBoogie\\": "tests"
}
}
}
4 changes: 2 additions & 2 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ services:
build:
context: .
args:
PHP_VERSION: 8.1
PHP_VERSION: "8.1"
environment:
PHP_IDE_CONFIG: 'serverName=icanboogie-activerecord'
volumes:
Expand All @@ -16,7 +16,7 @@ services:
build:
context: .
args:
PHP_VERSION: 8.2
PHP_VERSION: "8.2"
environment:
PHP_IDE_CONFIG: 'serverName=icanboogie-activerecord'
volumes:
Expand Down
47 changes: 32 additions & 15 deletions lib/ActiveRecord.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@
use ICanBoogie\ActiveRecord\StaticModelResolver;
use ICanBoogie\Validate\ValidationErrors;
use LogicException;
use ReflectionException;
use Throwable;

use function array_keys;
use function is_array;
use function is_numeric;

/**
Expand All @@ -27,18 +31,28 @@
* @method ValidationErrors validate() Validate the active record, returns an array of errors.
*
* @property-read Model $model The model managing the active record.
* @uses self::get_model()
* @property-read string $model_id The identifier of the model managing the active record.
* @uses self::get_model_id()
* @property-read bool $is_new Whether the record is new or not.
* @uses self::get_is_new()
*
* @template TKey of int|string|string[]
*/
abstract class ActiveRecord extends Prototyped
{
public const SAVE_SKIP_VALIDATION = 'skip_validation';

/**
* Model managing the active record.
*
* @var Model<TKey, static>
*/
private Model $model;

/**
* @return Model<TKey, static>
*/
protected function get_model(): Model
{
return $this->model
Expand All @@ -60,12 +74,9 @@ protected function get_model_id(): string
}

/**
* @param ?Model $model The model managing the active record. A {@link Model}
* instance can be specified as well as a model identifier. If `$model` is empty, the model
* will be resolved with {@link StaticModelResolver} when required.
*
* @throws \InvalidArgumentException if $model is neither a model identifier nor a
* {@link Model} instance.
* @param ?Model<TKey,static> $model
* The model managing the active record. A {@link Model} instance can be specified as well as a model
* identifier. If `$model` is null, the model will be resolved with {@link StaticModelResolver} when required.
*/
public function __construct(Model $model = null)
{
Expand All @@ -80,15 +91,21 @@ public function __construct(Model $model = null)
*
* Properties whose value are instances of the {@link ActiveRecord} class are removed from the
* exported properties.
*
* @return array<string, mixed>
*
* @throws ReflectionException
*/
public function __sleep(): array
public function __sleep() // @phpstan-ignore-line
{
$properties = parent::__sleep();

/** @phpstan-ignore-next-line */
unset($properties['model']);
/** @phpstan-ignore-next-line */
unset($properties['model_id']);

foreach (\array_keys($properties) as $property) {
foreach (array_keys($properties) as $property) {
if ($this->$property instanceof self) {
unset($properties[$property]);
}
Expand All @@ -101,9 +118,9 @@ public function __sleep(): array
* Removes `model` from the output, since `model_id` is good enough to figure which model
* is used.
*
* @return array
* @return array<string, mixed>
*/
public function __debugInfo()
public function __debugInfo(): array
{
$array = (array)$this;

Expand All @@ -114,14 +131,12 @@ public function __debugInfo()

/**
* Whether the record is new or not.
*
* @return bool
*/
protected function get_is_new(): bool
{
$primary = $this->get_model()->primary;

if (\is_array($primary)) {
if (is_array($primary)) {
foreach ($primary as $property) {
if (empty($this->$property)) {
return true;
Expand All @@ -141,8 +156,10 @@ protected function get_is_new(): bool
*
* @return bool|int Primary key value of the active record, or a boolean if the primary key
* is not a serial.
*
* @throws Throwable
*/
public function save(array $options = [])
public function save(array $options = []): int|bool
{
if (empty($options[self::SAVE_SKIP_VALIDATION])) {
$this->assert_is_valid();
Expand All @@ -158,7 +175,7 @@ public function save(array $options = [])

$primary = $model->primary;

if (\is_array($primary)) {
if (is_array($primary)) {
return $model->insert($properties, [ 'on duplicate' => true ]);
}

Expand Down
2 changes: 2 additions & 0 deletions lib/ActiveRecord/HasManyRelation.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ private function build_through_query(ActiveRecord $record, string $through_id):
// Because of the select, we need to set the mode otherwise an array would be
// fetched instead of an object.
$q->mode(PDO::FETCH_CLASS, $related->activerecord_class);
//phpcs:disable Generic.Files.LineLength.TooLong
$q->join(expression: "INNER JOIN `$through->name` ON `$through->name`.{$r2->local_key} = `$r2_model->alias`.{$related->primary}");
//phpcs:disable Generic.Files.LineLength.TooLong
$q->join(expression: "INNER JOIN `$owner->name` `$owner->alias` ON `$through->name`.{$r1->local_key} = `$owner->alias`.{$owner->primary}");
$q->where("`$owner->alias`.{$owner->primary} = ?", $record->{$this->local_key});

Expand Down
Loading

0 comments on commit 29d382c

Please sign in to comment.