Skip to content

Commit

Permalink
#29 base model classes implemented
Browse files Browse the repository at this point in the history
  • Loading branch information
1stthomas committed Oct 4, 2020
1 parent aec531e commit 38ac122
Show file tree
Hide file tree
Showing 9 changed files with 421 additions and 0 deletions.
32 changes: 32 additions & 0 deletions src/Models/AbstractLoadableModel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace Ht7\Base\Models;

use \Ht7\Base\Models\Loadable;
use \Ht7\Base\Utility\Traits\CanAddByPropertyName;

/**
* Base model.
*
* @author Thomas Pluess
* @version 0.0.1
* @since 0.0.1
*/
abstract class AbstractLoadableModel implements Loadable
{

use CanAddByPropertyName;

public function __construct(array $data = [])
{
$this->load($data);
}

public function load(array $data)
{
foreach ($data as $name => $value) {
$this->addByPropertyName($name, $value);
}
}

}
52 changes: 52 additions & 0 deletions src/Models/AbstractTransLoadableModel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

namespace Ht7\Base\Models;

use \Ht7\Base\Models\TransLoadable;
use \Ht7\Base\Utility\Traits\CanAddByPropertyName;

/**
* Base model.
*
* @author Thomas Pluess
* @version 0.0.1
* @since 0.0.1
*/
abstract class AbstractTransLoadableModel implements TransLoadable
{

use CanAddByPropertyName;

protected $transformations;

public function __construct(array $data = [], array $transformations = [])
{
$this->setTransformations($transformations);

$this->load($data);
}

public function getTransformations()
{
return $this->transformations;
}

public function load(array $data)
{
$transformations = $this->getTransformations();

foreach ($data as $name => $value) {
if (array_key_exists($name, $transformations)) {
$name = $transformations[$name];
}

$this->addByPropertyName($name, $value);
}
}

public function setTransformations(array $transformations)
{
$this->transformations = $transformations;
}

}
36 changes: 36 additions & 0 deletions src/Models/Loadable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace Ht7\Base\Models;

/**
* This interface describes a model, which is loadable with an array of property
* name/property value pairs.
*
* @author Thomas Pluess
* @version 0.0.1
* @since 0.0.1
*/
interface Loadable
{

/**
* Add a property to the present model by the property name.
*
* This method makes the first letter upper case and adds "set" to the
* beginning. Then the method is called by the composed method name, submitting
* the value as parameter.
*
* @param string $name The property name.
* @param mixed $value The new value of the property.
*/
public function addByPropertyName(string $name, $value);

/**
* Load an array of properties into the present model.
*
* @param array $data Assoc array of property names as array keys
* and the related property values as array
* values.
*/
public function load(array $data);
}
37 changes: 37 additions & 0 deletions src/Models/TransLoadable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

namespace Ht7\Base\Models;

use \Ht7\Base\Models\Loadable;

/**
* This interface describes a model, which is loadable with an array of property
* name/property value pairs.
*
* Additionally this model lets you define transformations, where e.g. short forms
* of property names can be transformed into the original ones.
*
* @author Thomas Pluess
* @version 0.0.1
* @since 0.0.1
*/
interface TransLoadable extends Loadable
{

/**
* Get the transformations.
*
* @return array Assoc array with the name to transform
* as key and the name to use as values.
*/
public function getTransformations();

/**
* Set the transformations.
*
* @param array $transformations Assoc array with the name to transform
* as key and the name to use as values.
* @return void
*/
public function setTransformations(array $transformations);
}
25 changes: 25 additions & 0 deletions src/Utility/Traits/CanAddByPropertyName.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace Ht7\Base\Utility\Traits;

/**
* Implementors of this trait are able to load their variables generic. This
* requires set methods for every property.
*
* @author Thomas Pluess
*/
trait CanAddByPropertyName
{

public function addByPropertyName($name, $value)
{
$method = 'set' . ucfirst($name);

if (is_callable([$this, $method])) {
$this->$method($value);
} else {
throw new \InvalidArgumentException('Unkown property: ' . $name);
}
}

}
46 changes: 46 additions & 0 deletions tests/Unit/Models/AbstractLoadableModelTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

namespace Ht7\Base\Tests\Models;

use \Ht7\Base\Models\AbstractLoadableModel;
use \PHPUnit\Framework\TestCase;

class AbstractLoadableModelTest extends TestCase
{

public function testConstruct()
{
$className = AbstractLoadableModel::class;

$items = [1, 2, 5];

$mock = $this->getMockBuilder($className)
->setMethods(['load'])
->getMockForAbstractClass();

$mock->expects($this->once())
->method('load')
->with($this->equalTo($items));

$reflectedClass = new \ReflectionClass($className);
$constructor = $reflectedClass->getConstructor();
$constructor->invoke($mock, $items);
}

public function testLoad()
{
$className = AbstractLoadableModel::class;

$items = [1, 2, 5];

$mock = $this->getMockBuilder($className)
->setMethods(['addByPropertyName'])
->getMockForAbstractClass();
$mock->expects($this->exactly(3))
->method('addByPropertyName')
->withConsecutive([0, 1], [1, 2], [2, 5]);

$mock->load($items);
}

}
96 changes: 96 additions & 0 deletions tests/Unit/Models/AbstractTransLoadableModelTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php

namespace Ht7\Base\Tests\Models;

use \Ht7\Base\Models\AbstractTransLoadableModel;
use \PHPUnit\Framework\TestCase;

class AbstractTransLoadableModelTest extends TestCase
{

public function testConstruct()
{
$className = AbstractTransLoadableModel::class;

$items = [1, 2, 5];
$transformations = [
'test1' => 'testProperty1',
'test2' => 'testProperty2',
];

$mock = $this->getMockBuilder($className)
->setMethods(['getTransformations', 'setTransformations', 'load'])
->getMockForAbstractClass();

$mock->expects($this->once())
->method('setTransformations')
->with($this->equalTo($transformations));
$mock->expects($this->once())
->method('load')
->with($this->equalTo($items));

$reflectedClass = new \ReflectionClass($className);
$constructor = $reflectedClass->getConstructor();
$constructor->invoke($mock, $items, $transformations);
}

public function testLoad()
{
$className = AbstractTransLoadableModel::class;

$items = [1, 2, 5];

/* @var $mock AbstractTransLoadableModel */
$mock = $this->getMockBuilder($className)
->setMethods(['getTransformations', 'addByPropertyName'])
->getMockForAbstractClass();

$mock->expects($this->once())
->method('getTransformations')
->willReturn([0 => 10, 1 => 100, 2 => 1000]);
$mock->expects($this->exactly(3))
->method('addByPropertyName')
->withConsecutive(
[$this->equalTo(10), $this->equalTo(1)],
[$this->equalTo(100), $this->equalTo(2)],
[$this->equalTo(1000), $this->equalTo(5)]
);

$mock->load($items);
}

public function testGetTranformations()
{
$className = AbstractTransLoadableModel::class;

$expected = [0 => 10, 5 => 20];

$mock = $this->getMockForAbstractClass($className);

$reflectedClass = new \ReflectionClass($className);
$property = $reflectedClass->getProperty('transformations');
$property->setAccessible(true);
$property->setValue($mock, $expected);

$this->assertEquals($expected, $mock->getTransformations());
}

public function testSetTranformations()
{
$className = AbstractTransLoadableModel::class;

$expected = [0 => 10, 5 => 20];

$mock = $this->getMockForAbstractClass($className);

$mock->setTransformations($expected);

$reflectedClass = new \ReflectionClass($className);
$property = $reflectedClass->getProperty('transformations');
$property->setAccessible(true);
$property->setValue($mock, $expected);

$this->assertEquals($expected, $property->getValue($mock));
}

}
30 changes: 30 additions & 0 deletions tests/Unit/Models/LoadableModelTest_.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Ht7\Base\Tests\Messages\Options;

use \Ht7\Base\Models\LoadableModel;
use \PHPUnit\Framework\TestCase;

class LoadableModelTest extends TestCase
{

public function testConstruct()
{
$className = LoadableModel::class;

$items = [1, 2, 5];

$mock = $this->getMockBuilder($className)
->setMethods(['load'])
->disableOriginalConstructor()
->getMock();
$mock->expects($this->once())
->method('load')
->with($this->equalTo($items));

$reflectedClass = new \ReflectionClass($className);
$constructor = $reflectedClass->getConstructor();
$constructor->invoke($mock, $items);
}

}
Loading

0 comments on commit 38ac122

Please sign in to comment.