Skip to content

Commit 9faab04

Browse files
committed
feat: adds all enums
1 parent 612294c commit 9faab04

File tree

10 files changed

+677
-0
lines changed

10 files changed

+677
-0
lines changed

src/Common/AbstractEnum.php

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace WordPress\AiClient\Common;
6+
7+
use BadMethodCallException;
8+
use InvalidArgumentException;
9+
use ReflectionClass;
10+
11+
/**
12+
* Abstract base class for enum-like behavior in PHP 7.4
13+
*
14+
* This class provides enum-like functionality for PHP versions that don't support native enums.
15+
* Child classes should define uppercase snake_case constants for enum values.
16+
*
17+
* @example
18+
* class PersonEnum extends AbstractEnum {
19+
* public const FIRST_NAME = 'first';
20+
* public const LAST_NAME = 'last';
21+
* }
22+
*
23+
* // Usage:
24+
* $enum = PersonEnum::firstName(); // Creates instance with value 'first'
25+
* $enum->isFirstName(); // Returns true
26+
* $enum->equals('first'); // Returns true
27+
* $enum->is(PersonEnum::firstName()); // Returns true
28+
*/
29+
abstract class AbstractEnum
30+
{
31+
/**
32+
* @var string|int|float The value of the enum instance
33+
*/
34+
private $value;
35+
36+
/**
37+
* @var array<string, array<string, string|int|float>> Cache for reflection data
38+
*/
39+
private static $cache = [];
40+
41+
/**
42+
* Constructor is private to ensure instances are created through static methods
43+
*
44+
* @param string|int|float $value The enum value
45+
*/
46+
private function __construct($value)
47+
{
48+
$this->value = $value;
49+
}
50+
51+
/**
52+
* Get the value of the enum instance
53+
*
54+
* @return string|int|float
55+
*/
56+
public function getValue()
57+
{
58+
return $this->value;
59+
}
60+
61+
/**
62+
* Check if this enum has the same value as the given value
63+
*
64+
* @param string|int|float|self $other The value or enum to compare
65+
* @return bool
66+
*/
67+
public function equals($other): bool
68+
{
69+
if ($other instanceof self) {
70+
return $this->is($other);
71+
}
72+
73+
return $this->value === $other;
74+
}
75+
76+
/**
77+
* Check if this enum is the same instance type and value as another enum
78+
*
79+
* @param self $other The other enum to compare
80+
* @return bool
81+
*/
82+
public function is(self $other): bool
83+
{
84+
return get_class($this) === get_class($other) && $this->value === $other->getValue();
85+
}
86+
87+
/**
88+
* Get all valid values for this enum
89+
*
90+
* @return array<string, string|int|float>
91+
*/
92+
public static function getValues(): array
93+
{
94+
return self::getConstants();
95+
}
96+
97+
/**
98+
* Check if a value is valid for this enum
99+
*
100+
* @param string|int|float $value The value to check
101+
* @return bool
102+
*/
103+
public static function isValidValue($value): bool
104+
{
105+
return in_array($value, self::getValues(), true);
106+
}
107+
108+
/**
109+
* Create an enum instance from a value
110+
*
111+
* @param string|int|float $value The enum value
112+
* @return static
113+
* @throws InvalidArgumentException If the value is not valid
114+
*/
115+
public static function fromValue($value): self
116+
{
117+
if (!self::isValidValue($value)) {
118+
throw new InvalidArgumentException(
119+
sprintf('Invalid value "%s" for enum %s', (string) $value, static::class)
120+
);
121+
}
122+
123+
$className = static::class;
124+
return new $className($value);
125+
}
126+
127+
/**
128+
* Get all constants for this enum class
129+
*
130+
* @return array<string, string|int|float>
131+
*/
132+
protected static function getConstants(): array
133+
{
134+
$className = static::class;
135+
136+
if (!isset(self::$cache[$className])) {
137+
$reflection = new ReflectionClass($className);
138+
$constants = $reflection->getConstants();
139+
140+
// Filter to only include uppercase snake_case constants
141+
$enumConstants = [];
142+
foreach ($constants as $name => $value) {
143+
if (
144+
preg_match('/^[A-Z][A-Z0-9_]*$/', $name)
145+
&& (is_string($value) || is_int($value) || is_float($value))
146+
) {
147+
$enumConstants[$name] = $value;
148+
}
149+
}
150+
151+
self::$cache[$className] = $enumConstants;
152+
}
153+
154+
return self::$cache[$className];
155+
}
156+
157+
/**
158+
* Handle dynamic method calls for enum creation and checking
159+
*
160+
* @param string $name The method name
161+
* @param array<mixed> $arguments The method arguments
162+
* @return bool
163+
* @throws BadMethodCallException If the method doesn't exist
164+
*/
165+
public function __call(string $name, array $arguments)
166+
{
167+
// Handle is* methods
168+
if (strpos($name, 'is') === 0) {
169+
$constantName = self::camelCaseToConstant(substr($name, 2));
170+
$constants = self::getConstants();
171+
172+
if (isset($constants[$constantName])) {
173+
return $this->value === $constants[$constantName];
174+
}
175+
}
176+
177+
throw new BadMethodCallException(
178+
sprintf('Method %s::%s does not exist', static::class, $name)
179+
);
180+
}
181+
182+
/**
183+
* Handle static method calls for enum creation
184+
*
185+
* @param string $name The method name
186+
* @param array<mixed> $arguments The method arguments
187+
* @return static
188+
* @throws BadMethodCallException If the method doesn't exist
189+
*/
190+
public static function __callStatic(string $name, array $arguments)
191+
{
192+
$constantName = self::camelCaseToConstant($name);
193+
$constants = self::getConstants();
194+
195+
if (isset($constants[$constantName])) {
196+
$className = static::class;
197+
return new $className($constants[$constantName]);
198+
}
199+
200+
throw new BadMethodCallException(
201+
sprintf('Method %s::%s does not exist', static::class, $name)
202+
);
203+
}
204+
205+
/**
206+
* Convert camelCase to CONSTANT_CASE
207+
*
208+
* @param string $camelCase The camelCase string
209+
* @return string The CONSTANT_CASE version
210+
*/
211+
private static function camelCaseToConstant(string $camelCase): string
212+
{
213+
$snakeCase = preg_replace('/([a-z])([A-Z])/', '$1_$2', $camelCase);
214+
if ($snakeCase === null) {
215+
return strtoupper($camelCase);
216+
}
217+
return strtoupper($snakeCase);
218+
}
219+
220+
/**
221+
* String representation of the enum
222+
*
223+
* @return string
224+
*/
225+
public function __toString(): string
226+
{
227+
return (string) $this->value;
228+
}
229+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace WordPress\AiClient\Messages\Enums;
6+
7+
use WordPress\AiClient\Common\AbstractEnum;
8+
9+
/**
10+
* Enum for message part types
11+
*
12+
* @method static self text() Create an instance for TEXT type
13+
* @method static self inlineFile() Create an instance for INLINE_FILE type
14+
* @method static self remoteFile() Create an instance for REMOTE_FILE type
15+
* @method static self functionCall() Create an instance for FUNCTION_CALL type
16+
* @method static self functionResponse() Create an instance for FUNCTION_RESPONSE type
17+
* @method bool isText() Check if the type is TEXT
18+
* @method bool isInlineFile() Check if the type is INLINE_FILE
19+
* @method bool isRemoteFile() Check if the type is REMOTE_FILE
20+
* @method bool isFunctionCall() Check if the type is FUNCTION_CALL
21+
* @method bool isFunctionResponse() Check if the type is FUNCTION_RESPONSE
22+
*/
23+
class MessagePartTypeEnum extends AbstractEnum
24+
{
25+
/**
26+
* Text content
27+
*/
28+
public const TEXT = 'text';
29+
30+
/**
31+
* Inline file content (base64 encoded)
32+
*/
33+
public const INLINE_FILE = 'inline_file';
34+
35+
/**
36+
* Remote file reference (URL)
37+
*/
38+
public const REMOTE_FILE = 'remote_file';
39+
40+
/**
41+
* Function call request
42+
*/
43+
public const FUNCTION_CALL = 'function_call';
44+
45+
/**
46+
* Function response
47+
*/
48+
public const FUNCTION_RESPONSE = 'function_response';
49+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace WordPress\AiClient\Messages\Enums;
6+
7+
use WordPress\AiClient\Common\AbstractEnum;
8+
9+
/**
10+
* Enum for message roles in AI conversations
11+
*
12+
* @method static self user() Create an instance for USER role
13+
* @method static self model() Create an instance for MODEL role
14+
* @method static self system() Create an instance for SYSTEM role
15+
* @method bool isUser() Check if the role is USER
16+
* @method bool isModel() Check if the role is MODEL
17+
* @method bool isSystem() Check if the role is SYSTEM
18+
*/
19+
class MessageRoleEnum extends AbstractEnum
20+
{
21+
/**
22+
* User role - messages from the user
23+
*/
24+
public const USER = 'user';
25+
26+
/**
27+
* Model role - messages from the AI model
28+
*/
29+
public const MODEL = 'model';
30+
31+
/**
32+
* System role - system instructions
33+
*/
34+
public const SYSTEM = 'system';
35+
}

src/Messages/Enums/ModalityEnum.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace WordPress\AiClient\Messages\Enums;
6+
7+
use WordPress\AiClient\Common\AbstractEnum;
8+
9+
/**
10+
* Enum for input/output modalities
11+
*
12+
* @method static self text() Create an instance for TEXT modality
13+
* @method static self document() Create an instance for DOCUMENT modality
14+
* @method static self image() Create an instance for IMAGE modality
15+
* @method static self audio() Create an instance for AUDIO modality
16+
* @method static self video() Create an instance for VIDEO modality
17+
* @method bool isText() Check if the modality is TEXT
18+
* @method bool isDocument() Check if the modality is DOCUMENT
19+
* @method bool isImage() Check if the modality is IMAGE
20+
* @method bool isAudio() Check if the modality is AUDIO
21+
* @method bool isVideo() Check if the modality is VIDEO
22+
*/
23+
class ModalityEnum extends AbstractEnum
24+
{
25+
/**
26+
* Text modality
27+
*/
28+
public const TEXT = 'text';
29+
30+
/**
31+
* Document modality (PDFs, Word docs, etc.)
32+
*/
33+
public const DOCUMENT = 'document';
34+
35+
/**
36+
* Image modality
37+
*/
38+
public const IMAGE = 'image';
39+
40+
/**
41+
* Audio modality
42+
*/
43+
public const AUDIO = 'audio';
44+
45+
/**
46+
* Video modality
47+
*/
48+
public const VIDEO = 'video';
49+
}

0 commit comments

Comments
 (0)