File manager - Edit - /home/premiey/www/wp-includes/images/media/vendor.tar
Back
franmastromarino/wp-orm/tests/Helpers/GetSanitizedDataTest.php 0000666 00000030560 15165400216 0020660 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Tests\Helpers; use PHPUnit\Framework\TestCase; use function QuadLayers\WP_Orm\Helpers\getSanitizedData; class GetSanitizedDataTest extends TestCase { private array $schema; public function setUp(): void { $this->schema = [ 'id' => [ 'type' => 'integer', 'default' => 0 ], 'key1' => [ 'type' => 'string', 'default' => 'key1_default_value1' ], 'key2' => [ 'type' => 'boolean', 'default' => false ], 'key3' => [ 'type' => 'object', 'default' => (object) [ 'key3_1' => 'key3_default_value1', 'key3_2' => 'key3_default_value2' ], 'properties' => [ 'key3_1' => [ 'type' => 'string', 'default' => 'key3_default_value1' ], 'key3_2' => [ 'type' => 'string', 'default' => 'key3_default_value2' ], ] ], 'key4' => [ 'type' => 'number', 'default' => 1 ], 'key5' => [ 'type' => 'number' ], 'key6' => [ 'type' => 'array', 'default' => [ 'key6_1' => 'key6_default_value1', 'key6_2' => 'key6_default_value2' ], 'properties' => [ 'key6_1' => [ 'type' => 'string', 'default' => 'key6_default_value1' ], 'key6_2' => [ 'type' => 'string', 'default' => 'key6_default_value2' ], ] ], ]; } public function testGetSanitizedDataStrict() { $data = [ 'id' => 0, 'key1' => 'value1_1', 'key2' => true, 'key3' => [ 'key3_1' => 'test', 'key3_2' => 'test' ], 'key4' => '1' ]; $result = getSanitizedData($data, $this->schema, true); $expected = [ 'id' => 0, 'key1' => 'value1_1', 'key2' => true ]; $this->assertSame($expected, $result); } public function testGetSanitizedDataNonStrictArrayToObject() { $data = [ 'id' => 0, 'key1' => 'value1_1', 'key2' => 1, 'key3' => [ 'key3_1' => 'value_3', 'key3_2' => 'value_4' ], 'key4' => '1', 'key5' => '-1' ]; $expected = [ 'id' => 0, 'key1' => 'value1_1', 'key2' => true, 'key3' => (object) [ 'key3_1' => 'value_3', 'key3_2' => 'value_4' ], 'key4' => 1, 'key5' => -1, 'key6' => [ 'key6_1' => 'key6_default_value1', 'key6_2' => 'key6_default_value2' ] ]; $result = getSanitizedData($data, $this->schema, false); $this->assertEquals($expected, $result); } public function testGetSanitizedDataNonStrictObjectToArray() { $data = [ 'id' => 0, 'key1' => 'value1_1', 'key2' => 1, 'key3' => [ 'key3_1' => 'value_3', 'key3_2' => 'value_4' ], 'key4' => '1', 'key5' => '-1', 'key6' => (object) [ 'key6_1' => 'value_3', 'key6_2' => 'value_4' ] ]; $result = getSanitizedData($data, $this->schema, false); $expected = [ 'id' => 0, 'key1' => 'value1_1', 'key2' => true, 'key3' => (object) [ 'key3_1' => 'value_3', 'key3_2' => 'value_4' ], 'key4' => 1, 'key5' => -1, 'key6' => [ 'key6_1' => 'value_3', 'key6_2' => 'value_4' ] ]; $this->assertEquals($expected, $result); } public function testGetSanitizedDataWithUnsupportedType() { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage("Unsupported type 'unsupported_type' in schema for key 'unsupported_key'"); $data = [ 'unsupported_key' => 'value', ]; $schema = [ 'unsupported_key' => [ 'type' => 'unsupported_type', 'default' => 'default' ], ]; getSanitizedData($data, $schema, false); } public function testGetSanitizedDataNonStrictWithInvalidNumber() { $data = [ 'key' => 'not a number' ]; $schema = [ 'key' => [ 'type' => 'number', 'default' => 0 ], ]; $expected = [ 'key' => 0 ]; $result = getSanitizedData($data, $schema, false); $this->assertSame($expected, $result); } public function testGetSanitizedDataStrictWithInvalidNumber() { $data = [ 'key' => 'not a number' ]; $schema = [ 'key' => [ 'type' => 'number', 'default' => 0 ], ]; $expected = []; $result = getSanitizedData($data, $schema, true); $this->assertSame($expected, $result); } public function testGetSanitizedDataNonStrictWithFloatNumber() { $data = [ 'key' => '10.5' ]; $schema = [ 'key' => [ 'type' => 'number', 'default' => 0 ], ]; $expected = [ 'key' => 10.5 ]; $result = getSanitizedData($data, $schema, false); $this->assertEquals($expected, $result); } public function testGetSanitizedDataStrictWithFloatNumber() { $data = [ 'key' => '10.5' ]; $schema = [ 'key' => [ 'type' => 'number', 'default' => 0 ], ]; $expected = []; $result = getSanitizedData($data, $schema, true); $this->assertEquals($expected, $result); } public function testGetSanitizedDataNonStrictWithInvalidBoolean() { $data = [ 'key' => 'not a boolean' ]; $schema = [ 'key' => [ 'type' => 'boolean', 'default' => false ], ]; $expected = [ 'key' => false ]; $result = getSanitizedData($data, $schema, false); $this->assertEquals($expected, $result); } public function testGetSanitizedDataStrictWithInvalidBoolean() { $data = [ 'key' => 'not a boolean' ]; $schema = [ 'key' => [ 'type' => 'boolean', 'default' => false ], ]; $expected = []; $result = getSanitizedData($data, $schema, true); $this->assertEquals($expected, $result); } public function testGetSanitizedDataStrictMissingValue() { $data = [ 'key1' => 'value1', ]; $schema = [ 'key1' => [ 'type' => 'string', 'default' => 'default1' ], 'key2' => [ 'type' => 'string', 'default' => 'default2' ], ]; $expected = [ 'key1' => 'value1', ]; $result = getSanitizedData($data, $schema, true); $this->assertEquals($expected, $result); } public function testGetSanitizedDataNonStrictMissingValue() { $data = [ 'key1' => 'value1', ]; $schema = [ 'key1' => [ 'type' => 'string', 'default' => 'default1' ], 'key2' => [ 'type' => 'string', 'default' => 'default2' ], ]; $expected = [ 'key1' => 'value1', 'key2' => 'default2' ]; $result = getSanitizedData($data, $schema, false); $this->assertEquals($expected, $result); } public function testGetSanitizedDataNonStrictInvalidType() { $data = [ 'key' => 'not a number' ]; $schema = [ 'key' => [ 'type' => 'number', 'default' => 0 ], ]; $expected = [ 'key' => 0 ]; $result = getSanitizedData($data, $schema, false); $this->assertEquals($expected, $result); } public function testNonStringValueForStringFieldNonStrict() { $data = ['key1' => 1]; $schema = ['key1' => ['type' => 'string', 'default' => 'default1']]; $expected = ['key1' => '1']; $this->assertEquals($expected, getSanitizedData($data, $schema, false)); } public function testNonStringValueForStringFieldStrict() { $data = ['key1' => 1]; $schema = ['key1' => ['type' => 'string', 'default' => 'default1']]; $expected = []; $this->assertEquals($expected, getSanitizedData($data, $schema, true)); } public function testNonObjectValueForObjectFieldNonStrict() { $data = [ 'key1' => 'string' ]; $schema = [ 'key1' => [ 'type' => 'object', 'default' => (object) [ 'key' => 'default' ] ] ]; $expected = [ 'key1' => (object) ['key' => 'default'] ]; $this->assertEquals($expected, getSanitizedData($data, $schema, false)); } public function testNonObjectValueForObjectFieldStrict() { $data = ['key1' => 'string']; $schema = ['key1' => ['type' => 'object', 'default' => (object) ['key' => 'default']]]; $expected = []; $this->assertEquals($expected, getSanitizedData($data, $schema, true)); } public function testNonIntegerValueForIntegerFieldNonStrict() { $data = ['key1' => 'string']; $schema = ['key1' => ['type' => 'integer', 'default' => 0]]; $expected = ['key1' => 0]; $this->assertEquals($expected, getSanitizedData($data, $schema, false)); } public function testNonIntegerValueForIntegerFieldStrict() { $data = ['key1' => 'string']; $schema = ['key1' => ['type' => 'integer', 'default' => 0]]; $expected = []; $this->assertEquals($expected, getSanitizedData($data, $schema, true)); } public function testStringTrueFalseForBooleanFieldNonStrict() { $data = ['key1' => 'true', 'key2' => 'false']; $schema = ['key1' => ['type' => 'boolean', 'default' => false], 'key2' => ['type' => 'boolean', 'default' => false]]; $expected = ['key1' => true, 'key2' => false]; $this->assertEquals($expected, getSanitizedData($data, $schema, false)); } public function testStringTrueFalseForBooleanFieldStrict() { $data = ['key1' => 'true', 'key2' => 'false']; $schema = ['key1' => ['type' => 'boolean', 'default' => false], 'key2' => ['type' => 'boolean', 'default' => false]]; $expected = []; $this->assertEquals($expected, getSanitizedData($data, $schema, true)); } public function testNonBooleanValueForBooleanFieldNonStrict() { $data = ['key1' => 'string']; $schema = ['key1' => ['type' => 'boolean', 'default' => false]]; $expected = ['key1' => false]; $this->assertEquals($expected, getSanitizedData($data, $schema, false)); } public function testNonBooleanValueForBooleanFieldStrict() { $data = ['key1' => 'string']; $schema = ['key1' => ['type' => 'boolean', 'default' => false]]; $expected = []; $this->assertEquals($expected, getSanitizedData($data, $schema, true)); } } franmastromarino/wp-orm/tests/Collection/CollectionRepositoryBuilderTest.php 0000666 00000010407 15165400216 0023665 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Tests\Collection; use PHPUnit\Framework\TestCase; use Brain\Monkey\Functions; use QuadLayers\WP_Orm\Builder\CollectionRepositoryBuilder; use QuadLayers\WP_Orm\Repository\CollectionRepository; class CollectionRepositoryBuilderTest extends TestCase { private string $table = 'test_table'; private CollectionRepository $repository; protected function setUp(): void { $builder = (new CollectionRepositoryBuilder()) ->setTable($this->table) ->setEntity('\QuadLayers\WP_Orm\Tests\Collection\CollectionEntityTest') ->setAutoIncrement(true); $this->repository = $builder->getRepository(); // When get_option is called, return testInput Functions\when('get_option')->justReturn([]); } public function testFindAll() { $test = [ [ 'key1' => 'test', ], [ 'key1' => 'test2', ], [ 'key1' => 'test3', ], ]; // Initialize a variable to keep track of the update_option call count $callCount = 0; Functions\when('update_option')->alias( function ($option, $value) use (&$callCount, $test) { // Check if the table is correct if ($this->table !== $option) { return false; } // // Increase the call count $callCount++; // // Check if the value matches the test values up to the current call count if (serialize(array_slice($test, 0, $callCount + 1)) !== serialize($value)) { return false; } return true; } ); foreach ($test as $index => $data) { $this->repository->create($data); } $results = $this->repository->findAll(); foreach ($results as $index => $entity) { $testEntity = array_merge( $test[$index], ['id' => $index] ); $this->assertEquals($entity->getModifiedProperties(), $testEntity); } } public function testDeleteAll() { Functions\when('delete_option')->justReturn(true); $this->repository->deleteAll(); $this->assertEquals($this->repository->findAll(), null); } public function testCreate() { Functions\when('update_option')->justReturn(true); $entity = $this->repository->create(['key1' => 'value1_2_updated']); $result = $entity->getModifiedProperties(); $this->assertEquals($result, ['id' => 0,'key1' => 'value1_2_updated']); } public function testUpdate() { Functions\when('update_option')->justReturn(true); $entity0 = $this->repository->create([]); $entity0 = $this->repository->update(0, ['key1' => 'value1_2_updated']); $result = $entity0->getModifiedProperties(); $this->assertEquals($result, ['id' => 0,'key1' => 'value1_2_updated']); } public function testDelete() { Functions\when('update_option')->justReturn(true); $entity0 = $this->repository->create([]); $entity1 = $this->repository->create([]); $entity2 = $this->repository->create([]); $result = $this->repository->delete(0); $this->assertTrue($result); $this->assertEquals(null, $this->repository->find(0)); $this->assertEquals($entity1, $this->repository->find(1)); $this->assertEquals($entity2, $this->repository->find(2)); } public function testDefaults() { $entity0 = $this->repository->create([]); $entity1 = $this->repository->create([]); $entity2 = $this->repository->create([]); $results = $this->repository->findAll(); foreach ($results as $index => $entity) { $defaults = $entity->getDefaults(); $this->assertEquals($defaults, [ 'id' => 0, 'key1' => 'default_value_1', 'key2' => 'default_value_2', 'key3' => [ 'key_3_1' => 'default_value_3', 'key_3_2' => 'default_value_4', ] ]); } } } franmastromarino/wp-orm/tests/Collection/CollectionRepositoryBuilderTestDefaultEntities.php 0000666 00000016111 15165400216 0026675 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Tests\Collection; use PHPUnit\Framework\TestCase; use Brain\Monkey\Functions; use QuadLayers\WP_Orm\Builder\CollectionRepositoryBuilder; use QuadLayers\WP_Orm\Repository\CollectionRepository; class CollectionRepositoryBuilderTestDefaultEntities extends TestCase { private string $table = 'test_table'; private CollectionRepository $repository; private array $defaultEntities; protected function setUp(): void { // Create default entities $this->defaultEntities = [ ['id' => 5, 'key1' => 'defaultEntities1'], ['id' => 6, 'key1' => 'defaultEntities2'] ]; // Set up the builder with default entities $builder = (new CollectionRepositoryBuilder()) ->setTable($this->table) ->setEntity('\QuadLayers\WP_Orm\Tests\Collection\CollectionEntityTest') ->setAutoIncrement(true) ->setDefaultEntities($this->defaultEntities); // Set default entities $this->repository = $builder->getRepository(); // When get_option is called, return testInput Functions\when('get_option')->justReturn($this->defaultEntities); } public function testFindAll() { $test = [ [ 'key1' => 'test', ], [ 'key1' => 'test2', ], [ 'key1' => 'test3', ], ]; // Initialize a variable to keep track of the update_option call count $callCount = 0; Functions\when('update_option')->alias( function ($option, $value) use (&$callCount, $test) { // Check if the table is correct if ($this->table !== $option) { return false; } // // Increase the call count $callCount++; // // Check if the value matches the test values up to the current call count if (serialize(array_slice($test, 0, $callCount + 1)) !== serialize($value)) { return false; } return true; } ); foreach ($test as $index => $data) { $this->repository->create($data); } $results = $this->repository->findAll(); $merged = array_merge($this->defaultEntities, $test); // Then proceed with count check $this->assertCount(count($merged), $results); // Check if the found entities match the default entities properties foreach ($results as $index => $entity) { // Assuming getProperties() returns an associative array of entity properties $properties = $entity->getProperties(); $expectedProperties = $merged[$index]; foreach ($expectedProperties as $key => $value) { $this->assertArrayHasKey($key, $properties, "Property $key should exist in the entity"); $this->assertEquals($value, $properties[$key], "Property $key should match the expected value"); } } } public function testDeleteAll() { Functions\when('delete_option')->justReturn(true); $this->repository->deleteAll(); $results = $this->repository->findAll(); // Then proceed with count check $this->assertCount(count($this->defaultEntities), $results); // Check if the found entities match the default entities properties foreach ($results as $index => $entity) { // Assuming getProperties() returns an associative array of entity properties $properties = $entity->getProperties(); $expectedProperties = $this->defaultEntities[$index]; foreach ($expectedProperties as $key => $value) { $this->assertArrayHasKey($key, $properties, "Property $key should exist in the entity"); $this->assertEquals($value, $properties[$key], "Property $key should match the expected value"); } } } public function testCreate() { Functions\when('update_option')->justReturn(true); $entity = $this->repository->create(['key1' => 'value1_2_updated']); $result = $entity->getModifiedProperties(); $this->assertEquals($result, ['id' => end($this->defaultEntities)['id'] + 1,'key1' => 'value1_2_updated']); } public function testUpdate() { Functions\when('update_option')->justReturn(true); $id = $this->defaultEntities[0]['id']; $entity0 = $this->repository->create([]); $entity0 = $this->repository->update($id, ['key1' => 'value1_2_updated']); $result = $entity0->getModifiedProperties(); $this->assertEquals($result, ['id' => $id,'key1' => 'value1_2_updated']); } public function testDelete() { Functions\when('update_option')->justReturn(true); $id = end($this->defaultEntities)['id']; $entity0 = $this->repository->create([]); $entity1 = $this->repository->create([]); $entity2 = $this->repository->create([]); $result = $this->repository->delete($id); $this->assertTrue($result); $this->assertEquals(null, $this->repository->find($id)); $this->assertEquals($entity1, $this->repository->find($id + 2)); $this->assertEquals($entity2, $this->repository->find($id + 3)); } public function testDefaults() { $entity0 = $this->repository->create([]); $entity1 = $this->repository->create([]); $entity2 = $this->repository->create([]); $results = $this->repository->findAll(); foreach ($results as $index => $entity) { $defaults = $entity->getDefaults(); $this->assertEquals($defaults, [ 'id' => 0, 'key1' => 'default_value_1', 'key2' => 'default_value_2', 'key3' => [ 'key_3_1' => 'default_value_3', 'key_3_2' => 'default_value_4', ] ]); } } public function testWithDefaultEntities() { // Test if the repository contains the default entities $result = $this->repository->findAll(); // Check if $result is iterable $this->assertIsIterable($result, 'The result of findAll() should be iterable'); // Then proceed with count check $this->assertCount(count($this->defaultEntities), $result); // Check if the found entities match the default entities properties foreach ($result as $index => $entity) { // Assuming getProperties() returns an associative array of entity properties $properties = $entity->getProperties(); $expectedProperties = $this->defaultEntities[$index]; foreach ($expectedProperties as $key => $value) { $this->assertArrayHasKey($key, $properties, "Property $key should exist in the entity"); $this->assertEquals($value, $properties[$key], "Property $key should match the expected value"); } } } } franmastromarino/wp-orm/tests/Collection/CollectionRepositoryTest.php 0000666 00000002166 15165400216 0022361 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Tests\Collection\Repository; use PHPUnit\Framework\TestCase; use QuadLayers\WP_Orm\Repository\CollectionRepositoryInterface; use QuadLayers\WP_Orm\Tests\Collection\CollectionEntityTest; class CollectionRepositoryTest extends TestCase { private CollectionRepositoryInterface $repository; protected function setUp(): void { $this->repository = $this->createMock(CollectionRepositoryInterface::class); } public function testSave() { $entity = new CollectionEntityTest(); $testValue = $entity->getDefaults(); $this->repository ->expects($this->once()) ->method('create') ->with($testValue) ->willReturn($entity); $this->repository->create($testValue); } public function testFind() { $entity = new CollectionEntityTest(); $this->repository ->expects($this->once()) ->method('find') ->with(); $this->repository ->expects($this->once()) ->method('find') ->willReturn($entity); $this->repository->find(0); } } franmastromarino/wp-orm/tests/Collection/CollectionEntityTest.php 0000666 00000000714 15165400216 0021453 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Tests\Collection; class CollectionEntityTest extends \QuadLayers\WP_Orm\Entity\CollectionEntity { /** * @var string */ public static $primaryKey = 'id'; public $id = 0; public $key1 = 'default_value_1'; public $key2 = 'default_value_2'; public $key3 = [ 'key_3_1' => 'default_value_3', 'key_3_2' => 'default_value_4', ]; public function __construct() { } } franmastromarino/wp-orm/tests/Collection/CollectionEntityTestPrimaryKeyString.php 0000666 00000000747 15165400216 0024665 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Tests\Collection; class CollectionEntityTestPrimaryKeyString extends \QuadLayers\WP_Orm\Entity\CollectionEntity { /** * @var string */ public static $primaryKey = 'test_id'; public $test_id = ''; public $key1 = 'default_value_1'; public $key2 = 'default_value_2'; public $key3 = [ 'key_3_1' => 'default_value_3', 'key_3_2' => 'default_value_4', ]; public function __construct() { } } franmastromarino/wp-orm/tests/Collection/CollectionRepositoryBuilderTestPrimaryKeyString.php 0000666 00000011251 15165400216 0027067 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Tests\Collection; use PHPUnit\Framework\TestCase; use Brain\Monkey\Functions; use QuadLayers\WP_Orm\Builder\CollectionRepositoryBuilder; use QuadLayers\WP_Orm\Repository\CollectionRepository; class CollectionRepositoryBuilderTestPrimaryKeyString extends TestCase { private string $table = 'test_table'; private CollectionRepository $repository; protected function setUp(): void { $builder = (new CollectionRepositoryBuilder()) ->setTable($this->table) ->setEntity('\QuadLayers\WP_Orm\Tests\Collection\CollectionEntityTestPrimaryKeyString') ->setAutoIncrement(false); $this->repository = $builder->getRepository(); // When get_option is called, return testInput Functions\when('get_option')->justReturn([]); } public function testFindAll() { $test = [ [ 'test_id' => 'test1', 'key1' => 'test', ], [ 'test_id' => 'test2', 'key1' => 'test2', ], [ 'test_id' => 'test9', 'key1' => 'test3', ], ]; // Initialize a variable to keep track of the update_option call count $callCount = 0; Functions\when('update_option')->alias( function ($option, $value) use (&$callCount, $test) { // Check if the table is correct if ($this->table !== $option) { return false; } // // Increase the call count $callCount++; // // Check if the value matches the test values up to the current call count if (serialize(array_slice($test, 0, $callCount + 1)) !== serialize($value)) { return false; } return true; } ); foreach ($test as $index => $data) { $this->repository->create($data); } $results = $this->repository->findAll(); foreach ($results as $index => $entity) { $testEntity = array_merge( $test[$index], ['test_id' => $test[$index]['test_id']] ); $this->assertEquals($entity->getModifiedProperties(), $testEntity); } } public function testDeleteAll() { Functions\when('delete_option')->justReturn(true); $this->repository->deleteAll(); $this->assertEquals($this->repository->findAll(), null); } public function testCreate() { Functions\when('update_option')->justReturn(true); $entity = $this->repository->create(['test_id' => 'test1','key1' => 'value1_2_updated']); $result = $entity->getModifiedProperties(); $this->assertEquals($result, ['test_id' => 'test1','key1' => 'value1_2_updated']); } public function testUpdate() { Functions\when('update_option')->justReturn(true); $entity0 = $this->repository->create(['test_id' => 'test1','key1' => 'value1_2_updated']); $entity0 = $this->repository->update('test1', ['key1' => 'value1_2_updated']); $result = $entity0->getModifiedProperties(); $this->assertEquals($result, ['test_id' => 'test1','key1' => 'value1_2_updated']); } public function testDelete() { Functions\when('update_option')->justReturn(true); $entity0 = $this->repository->create(['test_id' => 'test1']); $entity1 = $this->repository->create(['test_id' => 'test2']); $entity2 = $this->repository->create(['test_id' => 'test3']); $result = $this->repository->delete('test1'); $this->assertTrue($result); $this->assertEquals(null, $this->repository->find('test1')); $this->assertEquals($entity1, $this->repository->find('test2')); $this->assertEquals($entity2, $this->repository->find('test3')); } public function testDefaults() { $entity0 = $this->repository->create(['test_id' => 'test1']); $entity1 = $this->repository->create(['test_id' => 'test2']); $entity2 = $this->repository->create(['test_id' => 'test3']); $results = $this->repository->findAll(); foreach ($results as $index => $entity) { $defaults = $entity->getDefaults(); $this->assertEquals($defaults, [ 'test_id' => '', 'key1' => 'default_value_1', 'key2' => 'default_value_2', 'key3' => [ 'key_3_1' => 'default_value_3', 'key_3_2' => 'default_value_4', ] ]); } } } franmastromarino/wp-orm/tests/Collection/CollectionEntityTestPrimaryKey.php 0000666 00000000732 15165400216 0023470 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Tests\Collection; class CollectionEntityTestPrimaryKey extends \QuadLayers\WP_Orm\Entity\CollectionEntity { /** * @var string */ public static $primaryKey = 'test'; public $test = 0; public $key1 = 'default_value_1'; public $key2 = 'default_value_2'; public $key3 = [ 'key_3_1' => 'default_value_3', 'key_3_2' => 'default_value_4', ]; public function __construct() { } } franmastromarino/wp-orm/tests/Collection/CollectionMapperTest.php 0000666 00000003402 15165400216 0021420 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Tests\Collection\Mapper; use PHPUnit\Framework\TestCase; use QuadLayers\WP_Orm\Entity\CollectionEntity; use QuadLayers\WP_Orm\Entity\EntityInterface; use QuadLayers\WP_Orm\Factory\CollectionFactory; use QuadLayers\WP_Orm\Mapper\CollectionMapper; use QuadLayers\WP_Orm\Tests\Collection\CollectionEntityTest; class CollectionMapperTest extends TestCase { private array $testValue; private EntityInterface $entity; private CollectionFactory $factory; private CollectionMapper $mapper; protected function setUp(): void { $entity = new CollectionEntityTest(); $this->testValue = $entity->getDefaults(); $this->factory = new CollectionFactory('\QuadLayers\WP_Orm\Tests\Collection\CollectionEntityTest'); $this->mapper = new CollectionMapper($this->factory); $this->entity = $this->mapper->toEntity($this->testValue); } public function testToEntity() { $entity = $this->mapper->toEntity($this->testValue); $this->assertInstanceOf(CollectionEntity::class, $entity); $this->assertEquals($this->testValue['key1'], $entity->getKey1()); $this->assertEquals($this->testValue['key2'], $entity->getKey2()); } public function testToArray() { // Then we convert the entity back to an array $array = $this->mapper->toArray($this->entity); // Check if the original array and the result are the same $this->assertEquals(['id' => 0], $array); } public function testEntityHasDefaultAttributes() { $entity = $this->mapper->toEntity([]); $this->assertEquals($this->testValue['key1'], $entity->getKey1()); $this->assertEquals($this->testValue['key2'], $entity->getKey2()); } } franmastromarino/wp-orm/tests/Collection/CollectionTest.php 0000666 00000000745 15165400216 0020262 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Tests\Collection\Entity; use PHPUnit\Framework\TestCase; use QuadLayers\WP_Orm\Tests\Collection\CollectionEntityTest; class CollectionTest extends TestCase { public function testGettersAndSetters() { $entity = new CollectionEntityTest(); $testValue = $entity->getDefaults(); $this->assertEquals($testValue['key1'], $entity->getKey1()); $this->assertEquals($testValue['key2'], $entity->getKey2()); } } franmastromarino/wp-orm/tests/Collection/CollectionRepositoryBuilderTestPrimaryKey.php 0000666 00000010443 15165400216 0025702 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Tests\Collection; use PHPUnit\Framework\TestCase; use Brain\Monkey\Functions; use QuadLayers\WP_Orm\Builder\CollectionRepositoryBuilder; use QuadLayers\WP_Orm\Repository\CollectionRepository; class CollectionRepositoryBuilderTestPrimaryKey extends TestCase { private string $table = 'test_table'; private CollectionRepository $repository; protected function setUp(): void { $builder = (new CollectionRepositoryBuilder()) ->setTable($this->table) ->setEntity('\QuadLayers\WP_Orm\Tests\Collection\CollectionEntityTestPrimaryKey') ->setAutoIncrement(true); $this->repository = $builder->getRepository(); // When get_option is called, return testInput Functions\when('get_option')->justReturn([]); } public function testFindAll() { $test = [ [ 'key1' => 'test', ], [ 'key1' => 'test2', ], [ 'key1' => 'test3', ], ]; // Initialize a variable to keep track of the update_option call count $callCount = 0; Functions\when('update_option')->alias( function ($option, $value) use (&$callCount, $test) { // Check if the table is correct if ($this->table !== $option) { return false; } // // Increase the call count $callCount++; // // Check if the value matches the test values up to the current call count if (serialize(array_slice($test, 0, $callCount + 1)) !== serialize($value)) { return false; } return true; } ); foreach ($test as $index => $data) { $this->repository->create($data); } $results = $this->repository->findAll(); foreach ($results as $index => $entity) { $testEntity = array_merge( $test[$index], ['test' => $index] ); $this->assertEquals($entity->getModifiedProperties(), $testEntity); } } public function testDeleteAll() { Functions\when('delete_option')->justReturn(true); $this->repository->deleteAll(); $this->assertEquals($this->repository->findAll(), null); } public function testCreate() { Functions\when('update_option')->justReturn(true); $entity = $this->repository->create(['key1' => 'value1_2_updated']); $result = $entity->getModifiedProperties(); $this->assertEquals($result, ['test' => 0,'key1' => 'value1_2_updated']); } public function testUpdate() { Functions\when('update_option')->justReturn(true); $entity0 = $this->repository->create([]); $entity0 = $this->repository->update(0, ['key1' => 'value1_2_updated']); $result = $entity0->getModifiedProperties(); $this->assertEquals($result, ['test' => 0,'key1' => 'value1_2_updated']); } public function testDelete() { Functions\when('update_option')->justReturn(true); $entity0 = $this->repository->create([]); $entity1 = $this->repository->create([]); $entity2 = $this->repository->create([]); $result = $this->repository->delete(0); $this->assertTrue($result); $this->assertEquals(null, $this->repository->find(0)); $this->assertEquals($entity1, $this->repository->find(1)); $this->assertEquals($entity2, $this->repository->find(2)); } public function testDefaults() { $entity0 = $this->repository->create([]); $entity1 = $this->repository->create([]); $entity2 = $this->repository->create([]); $results = $this->repository->findAll(); foreach ($results as $index => $entity) { $defaults = $entity->getDefaults(); $this->assertEquals($defaults, [ 'test' => 0, 'key1' => 'default_value_1', 'key2' => 'default_value_2', 'key3' => [ 'key_3_1' => 'default_value_3', 'key_3_2' => 'default_value_4', ] ]); } } } franmastromarino/wp-orm/tests/Single/SingleMapperTest.php 0000666 00000003275 15165400216 0017704 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Tests\Single\Mapper; use PHPUnit\Framework\TestCase; use QuadLayers\WP_Orm\Entity\SingleEntity; use QuadLayers\WP_Orm\Entity\EntityInterface; use QuadLayers\WP_Orm\Factory\SingleFactory; use QuadLayers\WP_Orm\Mapper\SingleMapper; use QuadLayers\WP_Orm\Tests\Single\SingleEntityTest; class SingleMapperTest extends TestCase { private array $testValue; private EntityInterface $entity; private SingleFactory $factory; private SingleMapper $mapper; protected function setUp(): void { $entity = new SingleEntityTest(); $this->testValue = $entity->getDefaults(); $this->factory = new SingleFactory('\QuadLayers\WP_Orm\Tests\Single\SingleEntityTest'); $this->mapper = new SingleMapper($this->factory); $this->entity = $this->mapper->toEntity($this->testValue); } public function testToEntity() { $entity = $this->mapper->toEntity($this->testValue); $this->assertInstanceOf(SingleEntity::class, $entity); $this->assertEquals($this->testValue['key1'], $entity->getKey1()); $this->assertEquals($this->testValue['key2'], $entity->getKey2()); } public function testToArray() { // Then we convert the entity back to an array $array = $this->mapper->toArray($this->entity); // Check if the original array and the result are the same $this->assertEquals([], $array); } public function testEntityHasDefaultAttributes() { $entity = $this->mapper->toEntity([]); $this->assertEquals($this->testValue['key1'], $entity->getKey1()); $this->assertEquals($this->testValue['key2'], $entity->getKey2()); } } franmastromarino/wp-orm/tests/Single/SingleRepositoryBuilderTest.php 0000666 00000005573 15165400216 0022151 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Tests\Single; use PHPUnit\Framework\TestCase; use Brain\Monkey\Functions; use Brain\Monkey; use QuadLayers\WP_Orm\Builder\SingleRepositoryBuilder; use QuadLayers\WP_Orm\Repository\SingleRepository; class SingleRepositoryBuilderTest extends TestCase { private array $testValue; private array $testDefaults; private string $table; private SingleRepository $repository; protected function setUp(): void { $this->table = 'settings'; // $entity = new SingleEntity(); $this->testDefaults = [ 'key1' => 'default_value_1', 'key2' => 'default_value_2' ]; $this->testValue = [ 'key1' => 'value1', 'key2' => 'value2', ]; $builder = (new SingleRepositoryBuilder()) ->setTable($this->table) ->setEntity('\QuadLayers\WP_Orm\Tests\Single\SingleEntityTest'); $this->repository = $builder->getRepository(); Functions\when('update_option')->alias( function ($option, $value) { if (serialize($this->testValue) !== serialize($value)) { fwrite(STDOUT, "testValue => " . json_encode($this->testValue, true)); fwrite(STDOUT, "value => " . json_encode($value, true)); return false; } if ($this->table !== $option) { fwrite(STDOUT, "option => " . json_encode($option, true)); fwrite(STDOUT, "table => " . json_encode($this->table, true)); return false; } return true; } ); // When get_option is called, return existingData Functions\when('get_option')->justReturn($this->testValue); } protected function tearDown(): void { Monkey\tearDown(); parent::tearDown(); } public function testSave() { $result = $this->repository->create($this->testValue); $this->assertTrue($result); } public function testGet() { // Invoke get method $result = $this->repository->find(); // Ensure the result matches our expectations // key1 should be the same as existing data $this->assertEquals($this->testValue['key1'], $result->getKey1()); // key2 should be the default value from the schema $this->assertEquals($this->testValue['key2'], $result->getKey2()); } public function testDefaults() { $result = $this->repository->create($this->testValue); // Ensure the result matches our expectations // key1 should be the same as existing data $this->assertEquals($this->testDefaults['key1'], 'default_value_1'); // key2 should be the default value from the schema $this->assertEquals($this->testDefaults['key2'], 'default_value_2'); } } franmastromarino/wp-orm/tests/Single/SingleTest.php 0000666 00000000721 15165400216 0016530 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Tests\Single\Entity; use PHPUnit\Framework\TestCase; use QuadLayers\WP_Orm\Tests\Single\SingleEntityTest; class SingleTest extends TestCase { public function testGettersAndSetters() { $entity = new SingleEntityTest(); $testValue = $entity->getDefaults(); $this->assertEquals($testValue['key1'], $entity->getKey1()); $this->assertEquals($testValue['key2'], $entity->getKey2()); } } franmastromarino/wp-orm/tests/Single/SingleEntityTest.php 0000666 00000000326 15165400216 0017726 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Tests\Single; class SingleEntityTest extends \QuadLayers\WP_Orm\Entity\SingleEntity { public string $key1 = 'default_value_1'; public string $key2 = 'default_value_2'; } franmastromarino/wp-orm/tests/Single/SingleRepositoryTest.php 0000666 00000002116 15165400216 0020630 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Tests\Single\Repository; use PHPUnit\Framework\TestCase; use QuadLayers\WP_Orm\Repository\SingleRepositoryInterface; use QuadLayers\WP_Orm\Tests\Single\SingleEntityTest; class SingleRepositoryTest extends TestCase { private SingleRepositoryInterface $repository; protected function setUp(): void { $this->repository = $this->createMock(SingleRepositoryInterface::class); } public function testSave() { $entity = new SingleEntityTest(); $testValue = $entity->getDefaults(); $this->repository ->expects($this->once()) ->method('create') ->with($testValue) ->willReturn(true); $this->repository->create($testValue); } public function testFind() { $entity = new SingleEntityTest(); $this->repository ->expects($this->once()) ->method('find') ->with(); $this->repository ->expects($this->once()) ->method('find') ->willReturn($entity); $this->repository->find(); } } franmastromarino/wp-orm/readme.md 0000666 00000013745 15165400216 0013144 0 ustar 00 # WP ORM for WordPress Developers ## Description WP ORM is a specialized Object Relational Mapper designed for WordPress, simplifying the management of entities using the `wp_options` table. It provides an efficient way to handle single and collection entities, ideal for plugin settings and simple plugin entities, without the need for custom databases. The primary goal of WP ORM is to obviate the need for creating custom database or multiple wp_options entries reducing the complexity associated with managing such data in WordPress. This makes it an ideal solution for WordPress developers looking for a simplified and efficient way to handle data within plugins. WP ORM excels in scenarios that require simple data management. It is particularly adept at managing settings and other basic entities within WordPress plugins. For applications that require more complex data structures or advanced features, we recommend using Symlink ORM, which is better suited for handling intricate data requirements. In summary, WP ORM offers a developer-friendly, efficient, and streamlined approach to managing WordPress data, making it an excellent choice for developers looking to enhance their plugin development process without the added complexity of custom database management. ## Key Features - **Simple Entity Management**: Easily create and manage single entities. - **Collection Entity Handling**: Handle collection instances with ease. ## Installation ``` composer require franmastromarino/wp-options-orm ``` ## Usage WP ORM can be utilized to create and manage entities within WordPress. Below are examples showing its practical implementation: ### Single Entity In this example we will share a plugin settings implementation. ```php // Define the PluginSettings entity namespace YourNamespace\Entities; use QuadLayers\WP_Orm\Entity\SingleEntity; class PluginSettings extends SingleEntity { public $feature_enabled = 1; public $layout_type = 'grid'; public $max_items = 10; public $post_type = array( 'post', 'page' ); public $more = array( 'test1' => true, 'test2' => true, 'test3' => false, ); // Additional settings properties... } ``` ```php // Model for PluginSettings namespace YourNamespace\Models; use YourNamespace\Entities\PluginSettings; use QuadLayers\WP_Orm\Builder\SingleRepositoryBuilder; class PluginSettingsModel { protected $repository; public function __construct() { $builder = new SingleRepositoryBuilder(); $builder->setTable('your_plugin_settings') ->setEntity(PluginSettings::class); $this->repository = $builder->getRepository(); } public function getSettingsTable() { return $this->repository->getTable(); } public function getSettings() { $entity = $this->repository->find(); if ($entity) { return $entity->getProperties(); } else { $admin = new PluginSettings(); return $admin->getProperties(); } } public function deleteSettings() { return $this->repository->delete(); } public function saveSettings($data) { $entity = $this->repository->create($data); if ($entity) { return true; } } // Additional model methods... } ``` ### Collection Entity In this example we will share a plugin items collection implementation. ```php namespace YourNamespace\Entities; use QuadLayers\WP_Orm\Entity\CollectionEntity; class PluginItems extends CollectionEntity { public static $primaryKey = 'item_id'; public $item_id = 0; public $feature_enabled = 1; public $layout_type = 'grid'; public $max_items = 10; public $post_type = array( 'post', 'page' ); public $more = array( 'test1' => true, 'test2' => true, 'test3' => false, ); // Additional settings properties... } ``` ```php namespace YourNamespace\Models; use YourNamespace\Entities\PluginItems; use QuadLayers\WP_Orm\Builder\CollectionRepositoryBuilder; class PluginItemsModel { protected static $instance; protected $repository; private function __construct() { $builder = ( new CollectionRepositoryBuilder() ) ->setTable('your_plugin_items') ->setEntity(PluginItems::class) ->setAutoIncrement(true); $this->repository = $builder->getRepository(); } public function getItemsTable() { return $this->repository->getTable(); } public function getItemDefaults() { $entity = new PluginItems(); $defaults = $entity->getDefaults(); return $defaults; } public function getItem(int $item_id) { $entity = $this->repository->find($item_id); if ($entity) { return $entity->getProperties(); } } public function deleteItem(int $item_id) { return $this->repository->delete($item_id); } public function updateItem(int $item_id, array $item) { $entity = $this->repository->update($item_id, $item); if ($entity) { return $entity->getProperties(); } } public function createItem(array $item) { if (isset($item['item_id'])) { unset($item['item_id']); } $entity = $this->repository->create($item); if ($entity) { return $entity->getProperties(); } } public function getAllItems() { $entities = $this->repository->findAll(); if (! $entities) { return; } $actions = array(); foreach ($entities as $entity) { $actions[] = $entity->getProperties(); } return $actions; } public function deleteAllItems() { return $this->repository->deleteAll(); } public static function instance() { if (! isset(self::$instance)) { self::$instance = new self(); } return self::$instance; } } ``` franmastromarino/wp-orm/src/Factory/CollectionFactory.php 0000666 00000000141 15165400216 0017701 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Factory; class CollectionFactory extends AbstractFactory { } franmastromarino/wp-orm/src/Factory/SingleFactory.php 0000666 00000000135 15165400216 0017032 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Factory; class SingleFactory extends AbstractFactory { } franmastromarino/wp-orm/src/Factory/AbstractFactory.php 0000666 00000004005 15165400216 0017354 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Factory; use QuadLayers\WP_Orm\Entity\EntityInterface; use function QuadLayers\WP_Orm\Helpers\getObjectSchema; use function QuadLayers\WP_Orm\Helpers\getSanitizedData; abstract class AbstractFactory { /** * @var string */ private $entityClass; public function __construct(string $entityClass) { $this->entityClass = $entityClass; } public function create(array $data): EntityInterface { // Create a new instance of the entity $entity = new $this->entityClass(); // Get the default values of the entity, new static() is used to get the defaults of the child class $entityDefaults = $entity->getDefaults(); $entitySchema = getObjectSchema($entityDefaults); $sanitizedData = getSanitizedData($data, $entitySchema); // Use reflection to get the properties of the class $entityReflection = new \ReflectionClass($entity); // Get private properties of the entity $entityPrivates = $entity::PRIVATE_PROPERTIES; // Check if the entity has private properties and update them if (count($entityPrivates) > 0) { // Loop through each private property foreach ($entityPrivates as $propertyName) { if (array_key_exists($propertyName, $data)) { // Set the value of the property $entity->set($propertyName, $data[$propertyName]); } } } // Loop through each data item foreach ($sanitizedData as $property => $value) { $valueType = gettype($value); $propertyType = gettype($entity->$property); // Check if the entity has the property and if the value is of the same type if ($entityReflection->hasProperty($property) && $valueType === $propertyType) { // Set the value of the property $entity->$property = $value; } } return $entity; } } franmastromarino/wp-orm/src/Builder/CollectionRepositoryBuilder.php 0000666 00000004663 15165400216 0021754 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Builder; use QuadLayers\WP_Orm\Factory\CollectionFactory; use QuadLayers\WP_Orm\Mapper\CollectionMapper; use QuadLayers\WP_Orm\Repository\CollectionRepository; class CollectionRepositoryBuilder { /** * @var string */ private $table; /** * @var string */ private $primaryKey; /** * @var string */ private $entityClass; /** * @var array|null */ private $defaultEntities; /** * @var bool|null */ private $autoIncrement = null; public function setTable(string $table): self { $this->table = $table; return $this; } public function setEntity(string $entityClass): self { if (!class_exists($entityClass)) { throw new \InvalidArgumentException("Class '{$entityClass}' does not exist."); } $this->entityClass = $entityClass; return $this; } public function setDefaultEntities(array $defaultEntities): self { $this->defaultEntities = $defaultEntities; return $this; } public function setAutoIncrement(bool $autoIncrement): self { $this->autoIncrement = $autoIncrement; return $this; } public function setPrimaryKey(): self { // Check if the entity class has the primaryKey property if (!property_exists($this->entityClass, 'primaryKey') || !isset($this->entityClass::$primaryKey)) { throw new \InvalidArgumentException("Class '{$this->entityClass}' does not have the property 'primaryKey'."); } $primaryKey = $this->entityClass::$primaryKey; // Check if the entity class has the primaryKey property if (!property_exists($this->entityClass, $primaryKey)) { throw new \InvalidArgumentException("Class '{$this->entityClass}' does not have the property '{$primaryKey}'."); } $this->primaryKey = $primaryKey; return $this; } public function getRepository(): CollectionRepository { if (null === $this->autoIncrement) { throw new \InvalidArgumentException("Auto increment is not set."); } $this->setPrimaryKey(); $factory = new CollectionFactory($this->entityClass); $mapper = new CollectionMapper($factory); return new CollectionRepository($mapper, $this->table, $this->primaryKey, $this->autoIncrement, $this->defaultEntities); } } franmastromarino/wp-orm/src/Builder/SingleRepositoryBuilder.php 0000666 00000002067 15165400216 0021076 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Builder; use QuadLayers\WP_Orm\Factory\SingleFactory; use QuadLayers\WP_Orm\Mapper\SingleMapper; use QuadLayers\WP_Orm\Repository\SingleRepository; class SingleRepositoryBuilder { /** * @var string */ private $table; /** * @var string */ private $entityClass; public function setTable(string $table): self { $this->table = $table; return $this; } public function setGroup(string $group): self { $this->group = $group; return $this; } public function setEntity(string $entityClass): self { if (!class_exists($entityClass)) { throw new \InvalidArgumentException("Class '{$entityClass}' does not exist."); } $this->entityClass = $entityClass; return $this; } public function getRepository(): SingleRepository { $factory = new SingleFactory($this->entityClass); $mapper = new SingleMapper($factory); return new SingleRepository($mapper, $this->table); } } franmastromarino/wp-orm/src/helpers.php 0000666 00000015722 15165400216 0014324 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Helpers; function isAssociativeArray(array $array): bool { if (array() === $array) { return false; } return array_keys($array) !== range(0, count($array) - 1); } /** * PHP does not filter out private and protected properties when called from within the same class. * So, we've created this function to call get_object_vars outside class scope. */ function getObjectVars($object) { $vars = get_object_vars($object); if ($vars === false) { return []; } return $vars; } function getObjectSchema($properties): array { // Initialize the defaults array $schema = []; // Iterate over each public property foreach ($properties as $propertyName => $default) { // Get the type and default value of the property $type = gettype($default); // Add the property to the schema array $schema[$propertyName] = [ 'type' => $type, 'default' => $default ]; if ($type === 'object') { $schema[$propertyName]['properties'] = getObjectSchema((array) $default); } elseif ($type === 'array' && isAssociativeArray($default)) { $schema[$propertyName]['properties'] = getObjectSchema($default); } } // Return the schema array return $schema; } /** * Recursively compares two arrays and returns the differences between them. * * @param array $array1 The first array to compare. * @param array $array2 The second array to compare. * * @return array The differences between the two arrays. */ function arrayRecursiveDiff($array1, $array2) { $result = array(); foreach ($array2 as $key => $value) { // Condition 1: Check if the key doesn't exist in $array1 or if the values are not equal if (!array_key_exists($key, $array1) || $value !== $array1[$key]) { $result[$key] = $value; } // Condition 2: Check if the value is an array elseif (is_array($value)) { // Recursively compare arrays $recursiveDiff = arrayRecursiveDiff($array1[$key], $value); // Check if there are any differences if (count($recursiveDiff)) { $result[$key] = $recursiveDiff; } } // Condition 3: Check if the value is an object elseif (is_object($value)) { // Convert objects to arrays and recursively compare $recursiveDiff = arrayRecursiveDiff((array)$array1[$key], (array)$value); // Check if there are any differences if (count($recursiveDiff)) { $result[$key] = (object)$recursiveDiff; } } } return $result; } function getSanitizedData($data, array $schema, bool $strict = false) { if (is_object($data)) { $data = (array)$data; } if (!is_array($data)) { throw new \InvalidArgumentException('The data provided should be an array or object'); } $sanitized = []; foreach ($schema as $key => $property) { if (!isset($data[$key]) || ($strict && gettype($data[$key]) !== $property['type'])) { if (!$strict) { // Check if default is set before assigning. if (array_key_exists('default', $property)) { $sanitized[$key] = $property['default']; } } continue; } $value = $data[$key] ?? null; switch ($property['type']) { case 'NULL': $sanitized[$key] = null; break; case 'integer': case 'double': case 'number': if (gettype($value) === 'integer' || gettype($value) === 'double') { $sanitized[$key] = $value; } else { $sanitizedValue = filter_var($value, FILTER_VALIDATE_FLOAT); if ($sanitizedValue === false) { // Check if default is set before assigning. if (array_key_exists('default', $property)) { $sanitized[$key] = $property['default']; } } else { // Keep the number as an integer if it has no decimal part $sanitized[$key] = floor($sanitizedValue) == $sanitizedValue ? (int)$sanitizedValue : $sanitizedValue; } } break; case 'string': $sanitized[$key] = (string) $value; break; case 'array': if (is_array($value) || is_object($value)) { if (isset($property['properties'])) { $sanitized[$key] = (array) getSanitizedData($value, $property['properties'], $strict); } else { $sanitized[$key] = (array) $value; } } else { // Check if default is set before assigning. if (array_key_exists('default', $property)) { $sanitized[$key] = $property['default']; } } break; case 'object': if (is_object($value) || is_array($value)) { if (isset($property['properties'])) { $sanitized[$key] = (object) getSanitizedData($value, $property['properties'], $strict); } else { $sanitized[$key] = (object) $value; } } else { // Check if default is set before assigning. if (array_key_exists('default', $property)) { $sanitized[$key] = $property['default']; } } break; // break; case 'boolean': if (is_bool($value)) { $sanitized[$key] = $value; } elseif (is_string($value)) { // Convert 'true'/'false' strings to corresponding boolean values if (strtolower($value) === 'true' || strtolower($value) === '1') { $sanitized[$key] = true; } elseif (strtolower($value) === 'false' || strtolower($value) === '0') { $sanitized[$key] = false; } else { // Check if default is set before assigning. if (array_key_exists('default', $property)) { $sanitized[$key] = $property['default']; } } } else { // Cast non-string values to boolean $sanitized[$key] = (bool)$value; } break; default: throw new \InvalidArgumentException("Unsupported type '{$property['type']}' in schema for key '{$key}'"); } } return $sanitized; } franmastromarino/wp-orm/src/Mapper/CollectionMapperInterface.php 0000666 00000000374 15165400216 0021164 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Mapper; use QuadLayers\WP_Orm\Entity\EntityInterface; interface CollectionMapperInterface { public function toEntity(array $data): EntityInterface; public function toArray(EntityInterface $single): array; } franmastromarino/wp-orm/src/Mapper/SingleMapper.php 0000666 00000001130 15165400216 0016460 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Mapper; use QuadLayers\WP_Orm\Entity\EntityInterface; use QuadLayers\WP_Orm\Factory\SingleFactory; class SingleMapper implements SingleMapperInterface { /** * @var SingleFactory */ private $factory; public function __construct(SingleFactory $factory) { $this->factory = $factory; } public function toEntity(array $data): EntityInterface { return $this->factory->create($data); } public function toArray(EntityInterface $single): array { return $single->getModifiedProperties(); } } franmastromarino/wp-orm/src/Mapper/SingleMapperInterface.php 0000666 00000000370 15165400216 0020306 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Mapper; use QuadLayers\WP_Orm\Entity\EntityInterface; interface SingleMapperInterface { public function toEntity(array $data): EntityInterface; public function toArray(EntityInterface $single): array; } franmastromarino/wp-orm/src/Mapper/CollectionMapper.php 0000666 00000001155 15165400216 0017341 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Mapper; use QuadLayers\WP_Orm\Entity\EntityInterface; use QuadLayers\WP_Orm\Factory\CollectionFactory; class CollectionMapper implements CollectionMapperInterface { /** * @var CollectionFactory */ private $factory; public function __construct(CollectionFactory $factory) { $this->factory = $factory; } public function toEntity(array $data): EntityInterface { return $this->factory->create($data); } public function toArray(EntityInterface $single): array { return $single->getModifiedProperties(); } } franmastromarino/wp-orm/src/Entity/EntityInterface.php 0000666 00000000462 15165400216 0017226 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Entity; interface EntityInterface { public function __get(string $key); public function __set(string $key, $value): void; public function getProperties(): array; public function getDefaults(): array; public function getModifiedProperties(): array; } franmastromarino/wp-orm/src/Entity/CollectionEntity.php 0000666 00000002633 15165400216 0017423 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Entity; use function QuadLayers\WP_Orm\Helpers\arrayRecursiveDiff; abstract class CollectionEntity extends SingleEntity { const PRIVATE_PROPERTIES = ['primaryKey','allowDelete', 'allowUpdate']; /** * @var string */ public static $primaryKey; /** * @var bool */ private $allowDelete = true; /** * @var bool */ private $allowUpdate = true; public function get(string $key) { if (property_exists($this, $key)) { return $this->$key; } } public function set(string $key, $value): void { if (property_exists($this, $key)) { $this->$key = $value; } } public function getModifiedProperties(): array { // Get the current state of the object $defaults = $this->getDefaults(); /** * Remove the primary key from the defaults array * Always assume that the primary key is modified */ if (array_key_exists(static::$primaryKey, $defaults)) { unset($defaults[static::$primaryKey]); } $properties = $this->getProperties(); // Compare the current state with the initial state and get the modified properties $modifiedProperties = arrayRecursiveDiff($defaults, $properties); // Return the modified properties return $modifiedProperties; } } franmastromarino/wp-orm/src/Entity/SingleEntity.php 0000666 00000004705 15165400216 0016553 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Entity; use function QuadLayers\WP_Orm\Helpers\arrayRecursiveDiff; use function QuadLayers\WP_Orm\Helpers\getObjectVars; abstract class SingleEntity implements EntityInterface { const PRIVATE_PROPERTIES = []; /** * @var array|null */ private $defaults = null; public function get(string $key) { if (property_exists($this, $key)) { return $this->$key; } } public function set(string $key, $value): void { if (property_exists($this, $key)) { $this->$key = $value; } } public function __get(string $key) { if (property_exists($this, $key)) { return $this->$key; } throw new \InvalidArgumentException("Property '{$key}' does not exist."); } public function __set(string $key, $value): void { if (property_exists($this, $key)) { $this->$key = $value; } else { throw new \InvalidArgumentException("Property '{$key}' does not exist."); } } public function __call($name, $arguments) { // Get the first 3 characters of the method name $methodType = substr($name, 0, 3); // Get the property name by removing the first 3 characters from the method name $propertyName = lcfirst(substr($name, 3)); if ($methodType === 'get') { return $this->__get($propertyName); } elseif ($methodType === 'set') { return $this->__set($propertyName, $arguments[0]); } else { throw new \Exception("Method $name does not exist"); } } public function getModifiedProperties(): array { // Get the current state of the object $defaults = $this->getDefaults(); $properties = $this->getProperties(); // Compare the current state with the initial state $modifiedProperties = arrayRecursiveDiff($defaults, $properties); // Return the modified properties return $modifiedProperties; } public function getProperties(): array { return getObjectVars($this); } public function getDefaults(): array { // If defaults have not been set yet if ($this->defaults === null) { // Initialize the defaults array $this->defaults = getObjectVars(new static()); } // Return the defaults array return $this->defaults; } } franmastromarino/wp-orm/src/Repository/CollectionRepositoryInterface.php 0000666 00000001012 15165400216 0023040 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Repository; use QuadLayers\WP_Orm\Entity\EntityInterface; interface CollectionRepositoryInterface { public function findAll(): ?array; public function saveAll(array $collection): bool; public function find($primaryKeyValue): ?EntityInterface; public function update($primaryKeyValue, array $data): ?EntityInterface; public function delete($primaryKeyValue): bool; public function create(array $data): ?EntityInterface; public function getTable(): string; } franmastromarino/wp-orm/src/Repository/SingleRepository.php 0000666 00000003430 15165400216 0020353 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Repository; use QuadLayers\WP_Orm\Entity\EntityInterface; use QuadLayers\WP_Orm\Mapper\SingleMapperInterface; class SingleRepository implements SingleRepositoryInterface { /** * @var SingleMapperInterface */ private $mapper; /** * @var string */ private $table; /** * @var EntityInterface|null */ private $cache = null; public function __construct(SingleMapperInterface $mapper, string $table) { $this->mapper = $mapper; $this->table = $table; } public function find(): ?EntityInterface { if ($this->cache !== null) { return $this->cache; } $data = get_option($this->table, null); $this->cache = $data ? $this->mapper->toEntity($data) : null; return $this->cache; } public function save(EntityInterface $entity): bool { $this->cache = $entity; $data = $this->mapper->toArray($entity); return update_option($this->table, $data); } public function update(array $data): bool { $entity = $this->find(); if ($entity === null) { return false; // or throw an exception, as you prefer } // merge old and new data $updatedData = array_merge($entity->getProperties(), $data); $updatedEntity = $this->mapper->toEntity($updatedData); return $this->save($updatedEntity); } public function delete(): bool { $this->cache = null; return delete_option($this->table); } public function create(array $data): bool { $entity = $this->mapper->toEntity($data); return $this->save($entity); } public function getTable(): string { return $this->table; } } franmastromarino/wp-orm/src/Repository/CollectionRepository.php 0000666 00000016017 15165400216 0021232 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Repository; use QuadLayers\WP_Orm\Entity\EntityInterface; use QuadLayers\WP_Orm\Mapper\CollectionMapperInterface; use QuadLayers\WP_Orm\Entity\Collection; class CollectionRepository implements CollectionRepositoryInterface { /** * @var CollectionMapperInterface */ private $mapper; /** * @var string */ private $table; /** * @var string */ private $primaryKey; /** * @var bool */ private $autoIncrement; /** * @var array|null */ private $defaultEntities; /** * @var Collection[]|null */ private $cache = null; public function __construct(CollectionMapperInterface $mapper, string $table, string $primaryKey, bool $autoIncrement, array $defaultEntities = null) { $this->mapper = $mapper; $this->table = $table; $this->primaryKey = $primaryKey; $this->autoIncrement = $autoIncrement; $this->defaultEntities = $defaultEntities ? array_map( function ($data) { static $i = 0; if (!isset($data[$this->primaryKey])) { if ($this->autoIncrement) { $data[$this->primaryKey] = $i; $i++; } else { throw new \InvalidArgumentException("Primary key '{$this->primaryKey}' is required."); } } return $data; }, $defaultEntities ) : null; } private function getPrimaryKeyValue(EntityInterface $entity) { $primaryKey = $this->primaryKey; if (!property_exists($entity, $primaryKey)) { throw new \InvalidArgumentException("Primary key '{$primaryKey}' does not exist in the entity."); } return $entity->$primaryKey; } private function getAutoIncrement(): int { $collection = $this->findAll(); if (empty($collection)) { return 0; } $maxPrimaryKey = max(array_map(function ($entity) { return $entity->{$this->primaryKey}; }, $collection)); return $maxPrimaryKey + 1; } private function getEntityIndex($primaryKeyValue): ?int { $collection = $this->findAll(); if (!$collection) { return null; } foreach ($collection as $index => $entity) { if ($this->getPrimaryKeyValue($entity) === $primaryKeyValue) { return $index; } } return null; } public function findAll(): ?array { if ($this->cache !== null) { return $this->cache; } $data = get_option($this->table, null); if ($data === null && null !== $this->defaultEntities) { $data = $this->defaultEntities; } $this->cache = $data ? array_values(array_map([$this->mapper, 'toEntity'], $data)) : null; return $this->cache; } public function saveAll(array $collection): bool { $this->cache = $collection; $data = array_values(array_map([$this->mapper, 'toArray'], $collection)); return update_option($this->table, $data); } public function deleteAll(): bool { // Filter entities that do not allow deletion $collection = array_filter($this->findAll() ?? [], function ($entity) { $allowDelete = $entity->get('allowDelete'); return !$allowDelete; }); // If there are no entities that allow deletion, delete the option if (empty($collection)) { $this->cache = null; return delete_option($this->table); } // Otherwise, save the filtered collection $this->cache = null; return $this->saveAll($collection); } public function find($primaryKeyValue): ?EntityInterface { $index = $this->getEntityIndex($primaryKeyValue); if ($index === null) { return null; } $collection = $this->findAll(); if (!isset($collection[$index])) { return null; } return $collection[$index]; } public function create(array $data): ?EntityInterface { if (!isset($data[$this->primaryKey])) { if ($this->autoIncrement) { $data[$this->primaryKey] = $this->getAutoIncrement(); } else { throw new \InvalidArgumentException("Primary key '{$this->primaryKey}' is required."); } } $entity = $this->mapper->toEntity($data); $primaryKeyValue = $this->getPrimaryKeyValue($entity); $index = $this->getEntityIndex($primaryKeyValue); if ($index !== null) { throw new \InvalidArgumentException("Primary key '{$primaryKeyValue}' already exists in the collection."); } // Get the collection $collection = $this->findAll() ?? []; // Add the entity to the collection array_push($collection, $entity); if (!$this->saveAll($collection)) { return null; } // Save the updated collection return $entity; } public function update($primaryKeyValue, array $data): ?EntityInterface { $index = $this->getEntityIndex($primaryKeyValue); if ($index === null) { return null; } $collection = $this->findAll(); if (!isset($collection[$index])) { return null; } $entity = $collection[$index]; // Check if the entity allows updates, otherwise throw an exception if (isset($this->defaultEntities[$index]['allowUpdate']) && true !== $this->defaultEntities[$index]['allowUpdate']) { throw new \InvalidArgumentException("Entity does not allow updates."); } $updatedData = array_merge($entity->getProperties(), $data); $updatedEntity = $this->mapper->toEntity($updatedData); // Update the entity in the collection $collection[$index] = $updatedEntity; // Save the updated collection if (!$this->saveAll($collection)) { return null; } return $updatedEntity; } public function delete($primaryKeyValue): bool { $index = $this->getEntityIndex($primaryKeyValue); if ($index === null) { return false; } $collection = $this->findAll(); if (!isset($collection[$index])) { return false; } // Check if the entity allows updates, otherwise throw an exception if (isset($this->defaultEntities[$index]['allowDelete']) && true !== $this->defaultEntities[$index]['allowDelete']) { throw new \InvalidArgumentException("Entity does not allow deletion."); } // Remove the entity from the collection unset($collection[$index]); // Save the updated collection return $this->saveAll($collection); } public function getTable(): string { return $this->table; } } franmastromarino/wp-orm/src/Repository/SingleRepositoryInterface.php 0000666 00000000630 15165400216 0022173 0 ustar 00 <?php namespace QuadLayers\WP_Orm\Repository; use QuadLayers\WP_Orm\Entity\EntityInterface; interface SingleRepositoryInterface { public function find(): ?EntityInterface; public function save(EntityInterface $single): bool; public function update(array $data): bool; public function delete(): bool; public function create(array $data): bool; public function getTable(): string; } franmastromarino/wp-orm/phpcs.xml 0000666 00000002154 15165400216 0013214 0 ustar 00 <?xml version="1.0"?> <ruleset name="WP ORM"> <description>PHP CodeSniffer configuration for WP ORM using PSR12, PHPCompatibility, and some additional rules</description> <!-- Set the default coding standards to PSR12 and PHPCompatibility --> <rule ref="PSR12"/> <rule ref="PHPCompatibility"/> <!-- Specify the PHP version to check for compatibility --> <config name="testVersion" value="7.1-"/> <!-- Files to include --> <file>src</file> <!-- Exclude specific files/folders --> <exclude-pattern>*/tests/*</exclude-pattern> <!-- Ignore warnings, show only errors --> <arg value="n"/> <!-- Show sniff codes in all reports --> <arg value="s"/> <!-- Additional rules --> <rule ref="Generic.CodeAnalysis.UnusedFunctionParameter"> <severity>10</severity> </rule> <rule ref="Generic.CodeAnalysis.EmptyStatement"> <severity>10</severity> </rule> <rule ref="Generic.PHP.LowerCaseConstant"> <severity>10</severity> </rule> <rule ref="Generic.PHP.DeprecatedFunctions"> <severity>10</severity> </rule> </ruleset>