Skip to content

Commit 42cef12

Browse files
committed
Added new version for PHP >= 8.0
1 parent 12d01fb commit 42cef12

File tree

8 files changed

+173
-139
lines changed

8 files changed

+173
-139
lines changed

README.md

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ composer require lawondyss/config
1111
```php
1212
class DbConfig extend Lawondyss\Config
1313
{
14-
public $driver;
15-
public $host;
16-
public $database;
17-
public $username;
18-
public $password;
19-
public $charset;
14+
public string $driver;
15+
public string $host;
16+
public string $database;
17+
public string $username;
18+
public string $password;
19+
public string $charset;
2020
}
2121

2222
$dbConfig = DbConfig::fromArray([
@@ -29,7 +29,7 @@ $dbConfig = DbConfig::fromArray([
2929
]);
3030
```
3131

32-
Simple call individual option.
32+
Simple get and set individual option.
3333
```php
3434
$charset = $dbConfig->charset;
3535
$dbConfig->charset = 'latin1';
@@ -45,12 +45,12 @@ If you want default values, then defined in class.
4545
```php
4646
class DbConfig extend Lawondyss\Config
4747
{
48-
public $driver = 'mysqli';
49-
public $host = 'localhost';
50-
public $database;
51-
public $username;
52-
public $password;
53-
public $charset = 'utf8';
48+
public string $driver = 'mysqli';
49+
public string $host = 'localhost';
50+
public string $database;
51+
public string $username;
52+
public string $password;
53+
public string $charset = 'utf8';
5454
}
5555

5656
$defaultConfig = new DbConfig;

composer.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,24 @@
33
"description": "Base class for creating own class of configuration. Better than a associative array :-)",
44
"type": "library",
55
"license": "MIT",
6+
"version": "2.0.0",
67
"authors": [
78
{
89
"name": "Ladislav Vondráček",
910
"email": "lad.von@gmail.com"
1011
}
1112
],
1213
"require": {
13-
"php": ">=7.1"
14+
"php": ">=8.0"
1415
},
1516
"require-dev": {
16-
"nette/tester": "^2.3",
17-
"tracy/tracy": "^2.7"
17+
"nette/tester": "^2.5",
18+
"tracy/tracy": "^2.10"
1819
},
1920
"autoload": {
2021
"psr-4": {
2122
"Lawondyss\\Config\\": "src/Config"
22-
},
23-
"files": ["src/Config/exceptions.php"]
23+
}
2424
},
2525
"scripts": {
2626
"tests": "tester tests/"

src/Config/Config.php

Lines changed: 33 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,18 @@
55

66
namespace Lawondyss\Config;
77

8-
abstract class Config implements \ArrayAccess, \Countable, \IteratorAggregate
8+
use ArrayAccess;
9+
use Countable;
10+
use IteratorAggregate;
11+
use RecursiveArrayIterator;
12+
use ReflectionObject;
13+
use ReflectionProperty;
14+
use function array_map;
15+
use function count;
16+
use function is_array;
17+
use function property_exists;
18+
19+
abstract class Config implements ArrayAccess, Countable, IteratorAggregate
920
{
1021
/**
1122
* @param array<string, mixed> $options
@@ -30,17 +41,14 @@ public function toArray(): array
3041
{
3142
$arr = [];
3243
$properties = $this->getProperties();
44+
3345
foreach ($properties as $name) {
3446
$value = $this->$name;
3547

3648
if ($value instanceof self) {
3749
$value = $value->toArray();
38-
} elseif (is_array($value) && count($value) === count(array_filter($value, function($item) {
39-
return $item instanceof self;
40-
}))) {
41-
$value = array_map(function(Config $item) {
42-
return $item->toArray();
43-
}, $value);
50+
} elseif (is_array($value)) {
51+
$value = array_map(fn(mixed $val) => $val instanceof Config ? $val->toArray() : $val, $value);
4452
}
4553

4654
$arr[$name] = $value;
@@ -57,67 +65,60 @@ public function toArray(): array
5765
public function withOptions(array $options): Config
5866
{
5967
$dolly = clone $this;
60-
foreach ($options as $option => $value) {
61-
$dolly->$option = $value;
68+
69+
foreach ($options as $name => $value) {
70+
$dolly->$name = $value;
6271
}
6372

6473
return $dolly;
6574
}
6675

6776

68-
public function offsetExists($offset)
77+
public function offsetExists($offset): bool
6978
{
70-
return property_exists(static::class, $offset) && $this->$offset !== null;
79+
return property_exists($this::class, $offset) && $this->$offset !== null;
7180
}
7281

7382

74-
public function offsetGet($offset)
83+
public function offsetGet($offset): mixed
7584
{
7685
return $this->$offset;
7786
}
7887

7988

80-
public function offsetSet($offset, $value)
89+
public function offsetSet($offset, $value): void
8190
{
8291
$this->$offset = $value;
8392
}
8493

8594

86-
public function offsetUnset($offset)
95+
public function offsetUnset($offset): void
8796
{
8897
$this->$offset = null;
8998
}
9099

91100

92-
public function count()
101+
public function count(): int
93102
{
94103
return count($this->getProperties());
95104
}
96105

97106

98-
public function getIterator()
107+
public function getIterator(): RecursiveArrayIterator
99108
{
100-
return new \RecursiveArrayIterator($this->toArray());
109+
return new RecursiveArrayIterator($this->toArray());
101110
}
102111

103112

104113
public function __get($name)
105114
{
106-
$this->assertOptionDefined($name);
115+
throw UndefinedOption::create($this::class, $name, $this->getProperties());
107116
}
108117

109118

110119
public function __set($name, $value)
111120
{
112-
$this->assertOptionDefined($name);
113-
}
114-
115-
116-
private function assertOptionDefined(string $optionName): void
117-
{
118-
if (!property_exists(static::class, $optionName)) {
119-
throw UndefinedOption::create(static::class, $optionName);
120-
}
121+
throw UndefinedOption::create($this::class, $name, $this->getProperties());
121122
}
122123

123124

@@ -126,17 +127,11 @@ private function assertOptionDefined(string $optionName): void
126127
*/
127128
private function getProperties(): array
128129
{
129-
static $cachedProperties = null;
130-
131-
if (!isset($cachedProperties)) {
132-
$cachedProperties = [];
133-
134-
$rf = new \ReflectionObject($this);
135-
foreach ($rf->getProperties() as $property) {
136-
$cachedProperties[] = $property->name;
137-
}
138-
}
130+
static $cachedProperties = [];
139131

140-
return $cachedProperties;
132+
return $cachedProperties[$this::class] ??= (fn(): array => array_map(
133+
fn(ReflectionProperty $rp): string => $rp->name,
134+
(new ReflectionObject($this))->getProperties(~ReflectionProperty::IS_STATIC)
135+
))();
141136
}
142137
}

src/Config/UndefinedOption.php

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
/**
3+
* @author Ladislav Vondráček <lad.von@gmail.com>
4+
*/
5+
6+
namespace Lawondyss\Config;
7+
8+
use InvalidArgumentException;
9+
use function levenshtein;
10+
use function sprintf;
11+
use function strlen;
12+
13+
class UndefinedOption extends InvalidArgumentException
14+
{
15+
/**
16+
* @param string[] $possibilities
17+
*/
18+
public static function create(string $configuratorName, string $optionName, array $possibilities): self
19+
{
20+
$message = sprintf('Option %s::$%s is not defined', $configuratorName, $optionName);
21+
$suggestion = self::getSuggestion($possibilities, $optionName);
22+
23+
if (isset($suggestion)) {
24+
$message .= sprintf(', do you mean "%s"?', $suggestion);
25+
}
26+
27+
return new self($message);
28+
}
29+
30+
31+
private static function getSuggestion(array $possibilities, string $name): ?string
32+
{
33+
$best = null;
34+
$min = (strlen($name) / 4 + 1) * 10 + .1;
35+
36+
foreach ($possibilities as $item) {
37+
$len = levenshtein($item, $name, 10, 11, 10);
38+
39+
if ($len > 0 && $len < $min) {
40+
$min = $len;
41+
$best = $item;
42+
}
43+
}
44+
45+
return $best;
46+
}
47+
}

src/Config/exceptions.php

Lines changed: 0 additions & 19 deletions
This file was deleted.

tests/Config.phpt

Lines changed: 0 additions & 58 deletions
This file was deleted.

0 commit comments

Comments
 (0)