Skip to content

Commit ef3c628

Browse files
committedMay 31, 2024··
feat: Added classes subpackage
0 parents  commit ef3c628

10 files changed

+700
-0
lines changed
 

‎.gitattributes

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/.github export-ignore
2+
/.gitattributes export-ignore
3+
/.gitignore export-ignore
4+
/.releaserc export-ignore
5+
/composer.lock export-ignore

‎.github/renovate.json

Whitespace-only changes.

‎.github/workflows/release.yml

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: CI
2+
on:
3+
push:
4+
branches:
5+
- master
6+
- develop
7+
- alpha
8+
- beta
9+
10+
jobs:
11+
release:
12+
name: Release
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Checkout
16+
uses: actions/checkout@v4
17+
with:
18+
fetch-depth: 0
19+
token: ${{ secrets.OBLAKBOT_PAT }}
20+
- name: Import GPG key
21+
uses: crazy-max/ghaction-import-gpg@v6
22+
id: gpg
23+
with:
24+
gpg_private_key: ${{ secrets.OBLAKBOT_GPG_KEY }}
25+
passphrase: ${{ secrets.OBLAKBOT_GPG_PASS }}
26+
git_config_global: true
27+
git_user_signingkey: true
28+
git_commit_gpgsign: true
29+
- name: Semantic Release
30+
uses: cycjimmy/semantic-release-action@v4
31+
with:
32+
extra_plugins: |
33+
@semantic-release/github
34+
@semantic-release/exec
35+
env:
36+
GIT_AUTHOR_NAME: ${{ steps.gpg.outputs.name}}
37+
GIT_AUTHOR_EMAIL: ${{ steps.gpg.outputs.email}}
38+
GIT_COMMITTER_NAME: ${{ steps.gpg.outputs.name}}
39+
GIT_COMMITTER_EMAIL: ${{ steps.gpg.outputs.email}}
40+
GITHUB_TOKEN: ${{ secrets.OBLAKBOT_PAT }}

‎.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
composer.lock
2+
vendor

‎.releaserc

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"branches": [
3+
"master"
4+
],
5+
"plugins": [
6+
"@semantic-release/commit-analyzer",
7+
"@semantic-release/release-notes-generator",
8+
[
9+
"@semantic-release/exec",
10+
{
11+
"prepareCmd": "zip -r '/tmp/release.zip' *.php README.md"
12+
}
13+
],
14+
[
15+
"@semantic-release/github",
16+
{
17+
"assets": [
18+
{
19+
"path": "/tmp/release.zip",
20+
"name": "xwp-helper-classes-${nextRelease.version}.zip",
21+
"label": "xWP Helper Classes v${nextRelease.version}"
22+
}
23+
]
24+
}
25+
]
26+
]
27+
}

‎LICENSE

+339
Large diffs are not rendered by default.

‎README.md

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
eXtended WordPress Abstract Components
2+
=================================
3+
4+
A set of abstractions extracted out of xWP components.
5+
6+
Can be used to build and expand on semantics and definitions used by xWP ecosystem.
7+
8+
See the main [readme](https://github.com/xwp/helpers) for more information.

‎Reflection.php

+221
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
<?php
2+
/**
3+
* Reflection class file.
4+
*
5+
* @package eXtended WordPress
6+
*/
7+
8+
namespace XWP\Helper\Classes;
9+
10+
use ReflectionAttribute;
11+
use ReflectionClass;
12+
use ReflectionFunction;
13+
use ReflectionMethod;
14+
use Reflector;
15+
16+
/**
17+
* Reflection utilities.
18+
*/
19+
class Reflection {
20+
/**
21+
* Get a reflector for the target.
22+
*
23+
* @param mixed $target The target to get a reflector for.
24+
* @return ReflectionClass|ReflectionMethod|ReflectionFunction
25+
*
26+
* @throws \InvalidArgumentException If the target is invalid.
27+
*/
28+
public static function get_reflector( mixed $target ): Reflector {
29+
return match ( true ) {
30+
$target instanceof Reflector => $target,
31+
static::is_valid_class( $target ) => new ReflectionClass( $target ),
32+
static::is_valid_method( $target ) => new ReflectionMethod( ...$target ),
33+
static::is_valid_function( $target ) => new ReflectionFunction( $target ),
34+
default => throw new \InvalidArgumentException( 'Invalid target' ),
35+
};
36+
}
37+
38+
/**
39+
* Is the target callable.
40+
*
41+
* @param mixed $target The target to check.
42+
* @return bool
43+
*/
44+
public static function is_callable( mixed $target ): bool {
45+
return static::is_valid_method( $target ) || static::is_valid_function( $target );
46+
}
47+
48+
/**
49+
* Is the target a valid class.
50+
*
51+
* @param mixed $target The target to check.
52+
* @return bool
53+
*/
54+
public static function is_valid_class( mixed $target ): bool {
55+
return \is_object( $target ) || \class_exists( $target );
56+
}
57+
58+
/**
59+
* Is the target a valid method.
60+
*
61+
* @param mixed $target The target to check.
62+
* @return bool
63+
*/
64+
public static function is_valid_method( mixed $target ): bool {
65+
return \is_array( $target ) && \is_callable( $target );
66+
}
67+
68+
/**
69+
* Is the target a valid function.
70+
*
71+
* @param mixed $target The target to check.
72+
* @return bool
73+
*/
74+
public static function is_valid_function( mixed $target ): bool {
75+
return \is_string( $target ) && ( \function_exists( $target ) || \is_callable( $target ) );
76+
}
77+
78+
/**
79+
* Check if a class implements an interface.
80+
*
81+
* @param string|object $thing The class to check.
82+
* @param string $iname The interface to check for.
83+
* @param bool $autoload Whether to allow this function to load the class automatically through the __autoload() magic method.
84+
* @return bool
85+
*/
86+
public static function class_implements( string|object $thing, string $iname, bool $autoload = true ): bool {
87+
$cname = \is_object( $thing ) ? $thing::class : $thing;
88+
89+
return \class_exists( $cname ) && \in_array( $iname, \class_implements( $thing, $autoload ), true );
90+
}
91+
92+
/**
93+
* Get decorators for a target
94+
*
95+
* @template T
96+
* @param Reflector|mixed $target The target to get decorators for.
97+
* @param class-string<T> $decorator The decorator to get.
98+
* @param int|null $flags Flags to pass to getAttributes.
99+
* @return array<T>
100+
*/
101+
public static function get_attributes(
102+
mixed $target,
103+
string $decorator,
104+
?int $flags = ReflectionAttribute::IS_INSTANCEOF,
105+
): array {
106+
return static::get_reflector( $target )
107+
->getAttributes( $decorator, $flags );
108+
}
109+
110+
/**
111+
* Get decorators for a target
112+
*
113+
* @template T
114+
* @param Reflector|mixed $target The target to get decorators for.
115+
* @param class-string<T> $decorator The decorator to get.
116+
* @param int|null $flags Flags to pass to getAttributes.
117+
* @return array<T>
118+
*/
119+
public static function get_decorators(
120+
mixed $target,
121+
string $decorator,
122+
?int $flags = ReflectionAttribute::IS_INSTANCEOF,
123+
): array {
124+
return \array_map(
125+
static fn( $att ) => $att->newInstance(),
126+
static::get_attributes( $target, $decorator, $flags ),
127+
);
128+
}
129+
130+
/**
131+
* Get decorators for a target class, and its parent classes.
132+
*
133+
* @template T
134+
* @param Reflector|mixed $target The target to get decorators for.
135+
* @param class-string<T> $decorator The decorator to get.
136+
* @param int|null $flags Flags to pass to getAttributes.
137+
* @return array<T>
138+
*/
139+
public static function get_decorators_deep(
140+
mixed $target,
141+
string $decorator,
142+
?int $flags = ReflectionAttribute::IS_INSTANCEOF,
143+
): array {
144+
$decorators = array();
145+
146+
while ( $target ) {
147+
$decorators = \array_merge(
148+
$decorators,
149+
static::get_decorators( $target, $decorator, $flags ),
150+
);
151+
152+
$target = $target instanceof ReflectionClass
153+
? $target->getParentClass()
154+
: \get_parent_class( $target );
155+
}
156+
157+
return $decorators;
158+
}
159+
160+
/**
161+
* Get a **SINGLE** attribute for a target
162+
*
163+
* @template T
164+
* @param Reflector|mixed $target The target to get decorators for.
165+
* @param class-string<T> $decorator The decorator to get.
166+
* @param int|null $flags Flags to pass to getAttributes.
167+
* @param int $index The index of the decorator to get.
168+
* @return T|null
169+
*/
170+
public static function get_attribute(
171+
mixed $target,
172+
string $decorator,
173+
?int $flags = ReflectionAttribute::IS_INSTANCEOF,
174+
int $index = 0,
175+
): ?ReflectionAttribute {
176+
return static::get_attributes( $target, $decorator, $flags )[ $index ] ?? null;
177+
}
178+
179+
/**
180+
* Get a **SINGLE** decorator for a target
181+
*
182+
* @template T
183+
* @param Reflector|mixed $target The target to get decorators for.
184+
* @param class-string<T> $decorator The decorator to get.
185+
* @param int|null $flags Flags to pass to getAttributes.
186+
* @param int $index The index of the decorator to get.
187+
* @return T|null
188+
*/
189+
public static function get_decorator(
190+
mixed $target,
191+
string $decorator,
192+
?int $flags = ReflectionAttribute::IS_INSTANCEOF,
193+
int $index = 0,
194+
): ?object {
195+
return static::get_attribute( $target, $decorator, $flags, $index )
196+
?->newInstance()
197+
?? null;
198+
}
199+
200+
/**
201+
* Get all the traits used by a class.
202+
*
203+
* @param string|object $target Class or object to get the traits for.
204+
* @param bool $autoload Whether to allow this function to load the class automatically through the __autoload() magic method.
205+
* @return array Array of traits.
206+
*/
207+
public static function class_uses_deep( string|object $target, bool $autoload = true ) {
208+
$traits = array();
209+
210+
do {
211+
$traits = \array_merge( \class_uses( $target, $autoload ), $traits );
212+
$target = \get_parent_class( $target );
213+
} while ( $target );
214+
215+
foreach ( $traits as $trait ) {
216+
$traits = \array_merge( \class_uses( $trait, $autoload ), $traits );
217+
}
218+
219+
return \array_values( \array_unique( $traits ) );
220+
}
221+
}

‎Simple_Array_Object.php

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
/**
3+
* Simple_Array_Object class file.
4+
*
5+
* @package eXtended WordPress
6+
* @subpackage Helper\Classes
7+
*/
8+
9+
namespace XWP\Helper\Classes;
10+
11+
use XWP\Helper\Traits\Array_Access;
12+
13+
/**
14+
* Allows a class to be accessed as an array.
15+
*
16+
* @template TKey
17+
* @template TValue
18+
* @template-covariant TValue
19+
* @template-implements \ArrayAccess<TKey, TValue>, \Iterator<TKey, TValue>, \Countable, \JsonSerializable
20+
*/
21+
class Simple_Array_Object implements \ArrayAccess, \Iterator, \Countable, \JsonSerializable {
22+
use Array_Access;
23+
}

‎composer.json

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"name": "x-wp/helper-classes",
3+
"description": "Generic abstraction related to xWP packages",
4+
"license": "GPL-2.0-only",
5+
"type": "library",
6+
"keywords": [
7+
"abstractions",
8+
"contracts",
9+
"decoupling",
10+
"interfaces",
11+
"interoperability",
12+
"standards",
13+
"extended-wp"
14+
],
15+
"authors": [
16+
{
17+
"name": "Sibin Grasic",
18+
"email": "sibin.grasic@oblak.studio"
19+
}
20+
],
21+
"require": {
22+
"php": ">=8.0",
23+
"x-wp/helper-traits": "^1"
24+
},
25+
"suggest": {
26+
"automattic/jetpack-autoloader": "Allow for better interoperability with other plugins that use this package."
27+
},
28+
"minimum-stability": "alpha",
29+
"prefer-stable": true,
30+
"autoload": {
31+
"psr-4": {
32+
"XWP\\Helper\\Classes\\": ""
33+
}
34+
}
35+
}

0 commit comments

Comments
 (0)
Please sign in to comment.