Skip to content

Commit 4bed61c

Browse files
committed
v2.14.0
1 parent 7a4b815 commit 4bed61c

File tree

7 files changed

+358
-1
lines changed

7 files changed

+358
-1
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file.
44

55
The format is based on [Keep a Changelog][keepachangelog] and this project adheres to [Semantic Versioning][semver].
66

7+
## v2.14.0
8+
9+
### Added
10+
11+
- Add new global function `class_basename`. Get the class "basename" of the given object / class.
12+
- Add new global function `trait_uses_recursive`. Returns all traits used by a trait and its traits.
13+
- Add new global function `class_uses_recursive`. Returns all traits used by a class, its parent classes and trait of their traits.
14+
- Add trait `TraitBooter`. Helps to boot trait's static `boot-function`.
15+
- Add trait `TraitInitializer`. Helps to init trait's `initialize-function`.
16+
717
## v2.13.0
818

919
### Added

readme.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,13 @@ composer require efureev/support "^2.10"
6262
- encodeSafe
6363
- Global functions
6464
+ classNamespace
65+
+ class_basename
66+
+ class_uses_recursive
67+
+ instance
6568
+ isTrue
69+
+ trait_uses_recursive
6670
+ value
6771
+ when
68-
+ instance
6972
- Exceptions
7073
+ ConfigException
7174
+ Exception
@@ -97,6 +100,8 @@ composer require efureev/support "^2.10"
97100
+ ReadOnlyProperties
98101
+ Singleton
99102
+ Thrower
103+
+ TraitBooter
104+
+ TraitInitializer
100105
+ Whener
101106
- Types
102107
+ GeoPoint

src/Global/base.php

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,62 @@ function instance($instance, ...$params)
8888
return null;
8989
}
9090
}
91+
92+
if (! function_exists('class_basename')) {
93+
/**
94+
* Get the class "basename" of the given object / class.
95+
*
96+
* @param string|object $class
97+
* @return string
98+
*/
99+
function class_basename($class)
100+
{
101+
$class = is_object($class) ? get_class($class) : $class;
102+
103+
return basename(str_replace('\\', '/', $class));
104+
}
105+
}
106+
107+
if (!function_exists('trait_uses_recursive')) {
108+
/**
109+
* Returns all traits used by a trait and its traits.
110+
*
111+
* @param string $trait
112+
*
113+
* @return array
114+
*/
115+
function trait_uses_recursive(string $trait): array
116+
{
117+
$traits = class_uses($trait);
118+
119+
foreach ($traits as $trait) {
120+
$traits += trait_uses_recursive($trait);
121+
}
122+
123+
return $traits;
124+
}
125+
}
126+
127+
if (!function_exists('class_uses_recursive')) {
128+
/**
129+
* Returns all traits used by a class, its parent classes and trait of their traits.
130+
*
131+
* @param object|string $class
132+
*
133+
* @return array
134+
*/
135+
function class_uses_recursive($class): array
136+
{
137+
if (is_object($class)) {
138+
$class = get_class($class);
139+
}
140+
141+
$results = [];
142+
143+
foreach (array_reverse(class_parents($class)) + [$class => $class] as $class) {
144+
$results += trait_uses_recursive($class);
145+
}
146+
147+
return array_unique($results);
148+
}
149+
}

src/Traits/TraitBooter.php

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Php\Support\Traits;
6+
7+
trait TraitBooter
8+
{
9+
/**
10+
* The array of booted classes.
11+
*
12+
* @var array
13+
*/
14+
protected static $booted = [];
15+
16+
/**
17+
* The array of trait initializers that will be called on each new instance.
18+
*
19+
* @var array
20+
*/
21+
// protected static $traitInitializers = [];
22+
23+
/**
24+
* The array of trait initializers that will be called on each new instance.
25+
*
26+
* @return array
27+
*/
28+
protected static function bootTraits(): array
29+
{
30+
$class = static::class;
31+
32+
$booted = [];
33+
34+
foreach ($traits = class_uses_recursive($class) as $trait) {
35+
$method = 'boot' . class_basename($trait);
36+
37+
if (!isset($booted[$method]) && method_exists($class, $method)) {
38+
forward_static_call([$class, $method]);
39+
40+
$booted[$method] = true;
41+
}
42+
}
43+
44+
return $traits;
45+
}
46+
47+
protected function bootIfNotBooted()
48+
{
49+
if (!isset(static::$booted[static::class])) {
50+
static::$booted[static::class] = true;
51+
52+
static::booting();
53+
static::boot();
54+
static::booted();
55+
}
56+
}
57+
58+
/**
59+
* Perform any actions required before the instance boots.
60+
*
61+
* @return void
62+
*/
63+
protected static function booting(): void
64+
{
65+
//
66+
}
67+
68+
/**
69+
* Bootstrap the instance and its traits.
70+
*
71+
* @return void
72+
*/
73+
protected static function boot(): void
74+
{
75+
static::bootTraits();
76+
}
77+
78+
/**
79+
* Perform any actions required after the instance boots.
80+
*
81+
* @return void
82+
*/
83+
protected static function booted(): void
84+
{
85+
//
86+
}
87+
88+
/**
89+
* Clear the list of booted models so they will be re-booted.
90+
*
91+
* @return void
92+
*/
93+
public static function clearBooted()
94+
{
95+
static::$booted = [];
96+
}
97+
}

src/Traits/TraitInitializer.php

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Php\Support\Traits;
6+
7+
trait TraitInitializer
8+
{
9+
use TraitBooter {
10+
bootTraits as parentBootTraits;
11+
bootIfNotBooted as parentBootIfNotBooted;
12+
}
13+
14+
/**
15+
* The array of trait initializers that will be called on each new instance.
16+
*
17+
* @var array
18+
*/
19+
protected static $traitInitializers = [];
20+
21+
protected static function bootTraits(): array
22+
{
23+
$class = static::class;
24+
25+
static::$traitInitializers[$class] = [];
26+
27+
$traits = static::parentBootTraits();
28+
29+
30+
foreach ($traits as $trait) {
31+
if (method_exists($class, $method = 'initialize' . class_basename($trait))) {
32+
static::$traitInitializers[$class][] = $method;
33+
34+
static::$traitInitializers[$class] = \array_unique(
35+
static::$traitInitializers[$class]
36+
);
37+
}
38+
}
39+
40+
return $traits;
41+
}
42+
43+
/**
44+
* Initialize any initializable traits on the model.
45+
*
46+
* @return void
47+
*/
48+
protected function initializeTraits(): void
49+
{
50+
foreach (static::$traitInitializers[static::class] as $method) {
51+
$this->{$method}();
52+
}
53+
}
54+
55+
protected function bootIfNotBooted()
56+
{
57+
$this->parentBootIfNotBooted();
58+
59+
$this->initializeTraits();
60+
}
61+
}

tests/Global/BaseTest.php

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,4 +149,60 @@ public function testInstance(): void
149149
static::assertNull(instance($val));
150150
}
151151
}
152+
153+
154+
public function testTraitUsesRecursive(): void
155+
{
156+
$traits = trait_uses_recursive(TraitUsesRecursiveClass::class);
157+
158+
static::assertEquals(
159+
[
160+
\Php\Support\Traits\Singleton::class => \Php\Support\Traits\Singleton::class,
161+
\Php\Support\Traits\ArrayStorageConfigurableTrait::class => \Php\Support\Traits\ArrayStorageConfigurableTrait::class,
162+
\Php\Support\Traits\ArrayStorage::class => \Php\Support\Traits\ArrayStorage::class,
163+
\Php\Support\Traits\ConfigurableTrait::class => \Php\Support\Traits\ConfigurableTrait::class,
164+
],
165+
$traits
166+
);
167+
}
168+
169+
public function testClassUsesRecursive(): void
170+
{
171+
$traits = class_uses_recursive(RecursiveClass::class);
172+
173+
static::assertEquals(
174+
[
175+
\Php\Support\Traits\Singleton::class => \Php\Support\Traits\Singleton::class,
176+
\Php\Support\Traits\ArrayStorageConfigurableTrait::class => \Php\Support\Traits\ArrayStorageConfigurableTrait::class,
177+
\Php\Support\Traits\ArrayStorage::class => \Php\Support\Traits\ArrayStorage::class,
178+
\Php\Support\Traits\ConfigurableTrait::class => \Php\Support\Traits\ConfigurableTrait::class,
179+
\Php\Support\Traits\Maker::class => \Php\Support\Traits\Maker::class,
180+
],
181+
$traits
182+
);
183+
}
184+
185+
public function testClassBasename(): void
186+
{
187+
$name = class_basename(RecursiveClass::class);
188+
static::assertEquals('RecursiveClass', $name);
189+
$name = class_basename(new \stdClass());
190+
static::assertEquals('stdClass', $name);
191+
}
192+
193+
}
194+
195+
196+
class TraitUsesRecursiveClass
197+
{
198+
199+
protected $username;
200+
201+
use \Php\Support\Traits\Singleton;
202+
use \Php\Support\Traits\ArrayStorageConfigurableTrait;
203+
}
204+
205+
class RecursiveClass extends TraitUsesRecursiveClass
206+
{
207+
use \Php\Support\Traits\Maker;
152208
}

tests/traits/TraitBooterTest.php

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Php\Support\Tests;
6+
7+
use Php\Support\Traits\TraitBooter;
8+
use Php\Support\Traits\TraitInitializer;
9+
use PHPUnit\Framework\TestCase;
10+
11+
final class TraitBooterTest extends TestCase
12+
{
13+
public function testBootTrait(): void
14+
{
15+
self::assertEquals('class', BootClass::$type);
16+
$class = new BootClass();
17+
self::assertEquals('trait', $class::$type);
18+
}
19+
20+
public function testInitTrait(): void
21+
{
22+
$class = new InitClass();
23+
self::assertEquals('load initialize from InitTrait', $class->title);
24+
}
25+
}
26+
27+
class BootClass
28+
{
29+
use TraitBooter;
30+
use BootTrait;
31+
32+
public static $type = 'class';
33+
34+
public function __construct()
35+
{
36+
$this->bootIfNotBooted();
37+
// $this->initializeTraits();
38+
39+
}
40+
}
41+
42+
class InitClass
43+
{
44+
use TraitInitializer;
45+
use InitTrait;
46+
47+
public $title = '';
48+
49+
public function __construct()
50+
{
51+
$this->bootIfNotBooted();
52+
}
53+
}
54+
55+
trait BootTrait
56+
{
57+
public static function bootBootTrait()
58+
{
59+
static::$type = 'trait';
60+
}
61+
}
62+
63+
trait InitTrait
64+
{
65+
public function initializeInitTrait()
66+
{
67+
$this->title = 'load initialize from InitTrait';
68+
}
69+
}

0 commit comments

Comments
 (0)