Skip to content
Merged
8 changes: 4 additions & 4 deletions .github/workflows/tests-php.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the repository
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
fetch-depth: 1000
submodules: recursive
# ------------------------------------------------------------------------------
# Checkout slic
# ------------------------------------------------------------------------------
- name: Checkout slic
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
repository: stellarwp/slic
ref: main
Expand All @@ -30,8 +30,8 @@ jobs:
- name: Get Composer Cache Directory
id: get-composer-cache-dir
run: |
echo "::set-output name=dir::$(composer config cache-files-dir)"
- uses: actions/cache@v2
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- uses: actions/cache@v4
id: composer-cache
with:
path: ${{ steps.get-composer-cache-dir.outputs.dir }}
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class Breakfast_Model extends Model {
/**
* @inheritDoc
*/
protected $properties = [
protected static $properties = [
'id' => 'int',
'name' => 'string',
'price' => 'float',
Expand All @@ -95,7 +95,7 @@ class Breakfast_Model extends Model implements Contracts\ModelReadOnly {
/**
* @inheritDoc
*/
protected $properties = [
protected static $properties = [
'id' => 'int',
'name' => 'string',
'price' => 'float',
Expand Down Expand Up @@ -136,7 +136,7 @@ class Breakfast_Model extends Model implements Contracts\ModelCrud {
/**
* @inheritDoc
*/
protected $properties = [
protected static $properties = [
'id' => 'int',
'name' => 'string',
'price' => 'float',
Expand Down Expand Up @@ -199,7 +199,7 @@ class Breakfast_Model extends Model {
/**
* @inheritDoc
*/
protected $properties = [
protected static $properties = [
'id' => 'int',
'name' => 'string',
'price' => 'float',
Expand Down
4 changes: 4 additions & 0 deletions src/Models/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,8 @@ public static function setInvalidArgumentException( string $class ) {

static::$invalidArgumentException = $class;
}

public static function throwInvalidArgumentException( string $message ) {
throw new static::$invalidArgumentException( $message );
}
}
7 changes: 5 additions & 2 deletions src/Models/Contracts/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,14 @@ public function getOriginal( string $key = null );
/**
* Determines if the model has the given property.
*
* @since 2.0.0 changed to static
* @since 1.0.0
*
* @param string $key Property name.
*
* @return bool
*/
public function hasProperty( string $key ) : bool;
public static function hasProperty( string $key ) : bool;

/**
* Determines if a given attribute is clean.
Expand All @@ -94,18 +95,20 @@ public function isDirty( string $attribute = null ) : bool;
/**
* Validates an attribute to a PHP type.
*
* @since 2.0.0 changed to static
* @since 1.0.0
*
* @param string $key Attribute name.
* @param mixed $value Attribute value.
*
* @return bool
*/
public function isPropertyTypeValid( string $key, $value ) : bool;
public static function isPropertyTypeValid( string $key, $value ) : bool;

/**
* Returns the property keys.
*
* @since 2.0.0 changed to static
* @since 1.0.0
*
* @return int[]|string[]
Expand Down
63 changes: 35 additions & 28 deletions src/Models/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,16 @@ abstract class Model implements ModelInterface, Arrayable, JsonSerializable {
/**
* The model properties assigned to their types.
*
* @var array<string,string>
* @var array<string,string|array>
*/
protected $properties = [];
protected static $properties = [];

/**
* The model relationships assigned to their relationship types.
*
* @var array<string,string>
*/
protected $relationships = [];
protected static $relationships = [];

/**
* Relationships that have already been loaded and don't need to be loaded again.
Expand All @@ -52,7 +52,7 @@ abstract class Model implements ModelInterface, Arrayable, JsonSerializable {
* @param array<string,mixed> $attributes Attributes.
*/
public function __construct( array $attributes = [] ) {
$this->fill( array_merge( $this->getPropertyDefaults(), $attributes ) );
$this->fill( array_merge( static::getPropertyDefaults(), $attributes ) );

$this->syncOriginal();
}
Expand Down Expand Up @@ -87,7 +87,7 @@ public function fill( array $attributes ) : ModelInterface {
* @throws RuntimeException
*/
public function getAttribute( string $key, $default = null ) {
$this->validatePropertyExists( $key );
static::validatePropertyExists( $key );

return $this->attributes[ $key ] ?? $default;
}
Expand Down Expand Up @@ -133,34 +133,36 @@ public function getOriginal( string $key = null ) {
* @return boolean
*/
public function isSet( string $key ): bool {
return array_key_exists( $key, $this->attributes ) || $this->hasDefault( $key );
return array_key_exists( $key, $this->attributes ) || static::hasDefault( $key );
}

/**
* Check if there is a default value for a property.
*
* @since 2.0.0 changed to static
* @since 1.2.2
*
* @param string $key Property name.
*
* @return bool
*/
protected function hasDefault( string $key ): bool {
return is_array( $this->properties[ $key ] ) && array_key_exists( 1, $this->properties[ $key ] );
protected static function hasDefault( string $key ): bool {
return is_array( static::$properties[ $key ] ) && array_key_exists( 1, static::$properties[ $key ] );
}

/**
* Returns the default value for a property if one is provided, otherwise null.
*
* @since 2.0.0 changed to static
* @since 1.0.0
*
* @param string $key Property name.
*
* @return mixed|null
*/
protected function getPropertyDefault( string $key ) {
if ( $this->hasDefault( $key ) ) {
return $this->properties[ $key ][1];
protected static function getPropertyDefault( string $key ) {
if ( static::hasDefault( $key ) ) {
return static::$properties[ $key ][1];
}

return null;
Expand All @@ -169,15 +171,16 @@ protected function getPropertyDefault( string $key ) {
/**
* Returns the defaults for all the properties. If a default is omitted it defaults to null.
*
* @since 2.0.0 changed to static
* @since 1.0.0
*
* @return array<string,mixed>
*/
protected function getPropertyDefaults() : array {
protected static function getPropertyDefaults() : array {
$defaults = [];
foreach ( array_keys( $this->properties ) as $property ) {
if ( $this->hasDefault( $property ) ) {
$defaults[ $property ] = $this->getPropertyDefault( $property );
foreach ( array_keys( static::$properties ) as $property ) {
if ( static::hasDefault( $property ) ) {
$defaults[ $property ] = static::getPropertyDefault( $property );
}
}

Expand All @@ -194,7 +197,7 @@ protected function getPropertyDefaults() : array {
* @return string
*/
protected function getPropertyType( string $key ) : string {
$type = is_array( $this->properties[ $key ] ) ? $this->properties[ $key ][0] : $this->properties[ $key ];
$type = is_array( static::$properties[ $key ] ) ? static::$properties[ $key ][0] : static::$properties[ $key ];

return strtolower( trim( $type ) );
}
Expand All @@ -218,7 +221,7 @@ protected function getRelationship( string $key ) {
return $this->cachedRelations[ $key ];
}

$relationship = $this->relationships[ $key ];
$relationship = static::$relationships[ $key ];

switch ( $relationship ) {
case Relationship::BELONGS_TO:
Expand Down Expand Up @@ -262,14 +265,15 @@ protected function hasCachedRelationship( string $key ) : bool {
/**
* Determines if the model has the given property.
*
* @since 2.0.0 changed to static
* @since 1.0.0
*
* @param string $key Property name.
*
* @return bool
*/
public function hasProperty( string $key ) : bool {
return array_key_exists( $key, $this->properties );
public static function hasProperty( string $key ) : bool {
return array_key_exists( $key, static::$properties );
}

/**
Expand Down Expand Up @@ -305,19 +309,20 @@ public function isDirty( string $attribute = null ) : bool {
/**
* Validates an attribute to a PHP type.
*
* @since 2.0.0
* @since 1.0.0
*
* @param string $key Property name.
* @param mixed $value Property value.
*
* @return bool
*/
public function isPropertyTypeValid( string $key, $value ) : bool {
public static function isPropertyTypeValid( string $key, $value ) : bool {
if ( is_null( $value ) ) {
return true;
}

$type = $this->getPropertyType( $key );
$type = static::getPropertyType( $key );

switch ( $type ) {
case 'int':
Expand Down Expand Up @@ -357,7 +362,7 @@ public function jsonSerialize() {
* @return int[]|string[]
*/
public static function propertyKeys() : array {
return array_keys( ( new static() )->properties );
return array_keys( static::$properties );
}

/**
Expand Down Expand Up @@ -428,14 +433,15 @@ public function toArray() : array {
/**
* Validates that the given property exists
*
* @since 2.0.0 changed to static
* @since 1.0.0
*
* @param string $key Property name.
*
* @return void
*/
protected function validatePropertyExists( string $key ) {
if ( ! $this->hasProperty( $key ) ) {
protected static function validatePropertyExists( string $key ) {
if ( ! static::hasProperty( $key ) ) {
$exception = Config::getInvalidArgumentException();
throw new $exception( "Invalid property. '$key' does not exist." );
}
Expand All @@ -444,16 +450,17 @@ protected function validatePropertyExists( string $key ) {
/**
* Validates that the given value is a valid type for the given property.
*
* @since 2.0.0 changed to static
* @since 1.0.0
*
* @param string $key Property name.
* @param mixed $value Property value.
*
* @return void
*/
protected function validatePropertyType( string $key, $value ) {
if ( ! $this->isPropertyTypeValid( $key, $value ) ) {
$type = $this->getPropertyType( $key );
protected static function validatePropertyType( string $key, $value ) {
if ( ! static::isPropertyTypeValid( $key, $value ) ) {
$type = static::getPropertyType( $key );

$exception = Config::getInvalidArgumentException();
throw new $exception( "Invalid attribute assignment. '$key' should be of type: '$type'" );
Expand All @@ -470,7 +477,7 @@ protected function validatePropertyType( string $key, $value ) {
* @return mixed
*/
public function __get( string $key ) {
if ( array_key_exists( $key, $this->relationships ) ) {
if ( array_key_exists( $key, static::$relationships ) ) {
return $this->getRelationship( $key );
}

Expand Down
2 changes: 1 addition & 1 deletion tests/_support/Helper/MockModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use StellarWP\Models\Model;

class MockModel extends Model {
protected $properties = [
protected static $properties = [
'id' => 'int',
'firstName' => [ 'string', 'Michael' ],
'lastName' => 'string',
Expand Down
4 changes: 2 additions & 2 deletions tests/_support/Helper/MockModelWithRelationship.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
use StellarWP\Models\ValueObjects\Relationship;

class MockModelWithRelationship extends Model {
protected $properties = [
protected static $properties = [
'id' => 'int',
];

protected $relationships = [
protected static $relationships = [
'relatedButNotCallable' => Relationship::HAS_ONE,
'relatedAndCallableHasOne' => Relationship::HAS_ONE,
'relatedAndCallableHasMany' => Relationship::HAS_MANY,
Expand Down
6 changes: 3 additions & 3 deletions tests/wpunit/ModelFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ class MockModel extends Model
{
protected static $autoIncrementId = 1;

protected $properties = [
protected static $properties = [
'id' => 'int',
];

Expand All @@ -342,7 +342,7 @@ public static function resetAutoIncrementId() {
*/
class MockModelWithDependency extends MockModel
{
protected $properties = [
protected static $properties = [
'id' => 'int',
'nestedId' => 'int',
];
Expand All @@ -363,7 +363,7 @@ abstract public function __invoke();
*/
class MockModelWithInvokableProperty extends MockModel
{
protected $properties = [
protected static $properties = [
'invokable' => MockInvokableClass::class,
];
}
Loading