Introduction of the GameConfiguration model

This commit introduces the GameConfiguration, a model that is not an
entity. It also introduces GameConfigurationElement which is a doctrine
entity.
The two models make use of the traits introduced for CharacterProperty.
They also use the new OneToManyCollection class, which implements the
doctrine collection interface to a certain, limited extend. It mimicks
doctrine's PersisentCollection.
This commit is contained in:
Basilius Sauter
2016-04-27 22:51:16 +02:00
parent d59c08b60d
commit 7b21baee37
11 changed files with 494 additions and 1 deletions
+11
View File
@@ -0,0 +1,11 @@
<?php
declare(strict_types=1);
namespace LotGD\Core\Exceptions;
/**
* Exception if a specific, required argument is missing
*/
class ClassNotFoundException extends CoreException {
}
+11
View File
@@ -0,0 +1,11 @@
<?php
declare(strict_types=1);
namespace LotGD\Core\Exceptions;
/**
* Exception if a specific, required argument is missing
*/
class KeyNotFoundException extends CoreException {
}
@@ -0,0 +1,11 @@
<?php
declare(strict_types=1);
namespace LotGD\Core\Exceptions;
/**
* Exception if a specific, required argument is missing
*/
class NotImplementedException extends CoreException {
}
+1
View File
@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace LotGD\Core\Models;
+51
View File
@@ -0,0 +1,51 @@
<?php
declare(strict_types=1);
namespace LotGD\Core\Models;
use Doctrine\ORM\EntityManagerInterface;
use LotGD\Core\Models\GameConfigurationElement;
use LotGD\Core\Tools\OneToManyCollection;
use LotGD\Core\Tools\Model\PropertyManager;
/**
* Provides an interface to access properties
*/
class GameConfiguration
{
use PropertyManager;
/** @var ArrayCollection */
private $properties;
/**
* Constructor.
* @param EntityManagerInterface $em
*/
public function __construct(EntityManagerInterface $entityManager)
{
$this->properties = new OneToManyCollection($entityManager, GameConfigurationElement::class);
}
/**
* Returns a configuration value or the default one if the configuration name has not been set yet.
* @param string $configurationName
* @param mixed $configurationDefault
* @return mixed
*/
public function get(string $configurationName, $configurationDefault)
{
return $this->getProperty($configurationName, $configurationDefault);
}
/**
* Sets and overwrites a configuration value saved by the name
* @param string $configurationName
* @param type $configurationValue
*/
public function set(string $configurationName, $configurationValue)
{
$this->setProperty($configurationName, $configurationValue);
}
}
+16
View File
@@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
namespace LotGD\Core\Models;
use LotGD\Core\Tools\Model\Properties;
/**
* Properties for Characters
* @Entity
* @Table(name="game_configuration")
*/
class GameConfigurationElement
{
use Properties;
}
+9
View File
@@ -0,0 +1,9 @@
<?php
trait BaseSetting
{
/** @Id @Column(type="string", length=255) */
private $settingName;
/** @Column(type="text") */
private $settingValue;
}
+3 -1
View File
@@ -43,7 +43,9 @@ trait PropertyManager
else {
$className = $this->properties->getTypeClass()->name;
$property = new $className();
$property->setOwner($this);
if (method_exists($property, "setOwner")) {
$property->setOwner($this);
}
$property->setName($name);
$property->setValue($value);
+314
View File
@@ -0,0 +1,314 @@
<?php
namespace LotGD\Core\Tools;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
use LotGD\Core\Exceptions\ClassNotFoundException;
use LotGD\Core\Exceptions\KeyNotFoundException;
use LotGD\Core\Exceptions\NotImplementedException;
use LotGD\Core\Exceptions\WrongTypeException;
class OneToManyCollection implements Collection
{
/** @var string */
private $typeClass;
/** @var EntityManagerInterface */
private $entityManager = null;
/** @var array */
private $collection;
/** @var int */
private $numberOfRows;
/**
* Constructor
* @param EntityManagerInterface $entityManager
* @param string $typeClass
* @throws ClassNotFoundException
*/
public function __construct(EntityManagerInterface $entityManager, string $typeClass)
{
if(class_exists($typeClass) === false) {
throw new ClassNotFoundException(sprintf("The class %s has not been found.", $typeClass));
}
$this->entityManager = $entityManager;
$this->typeClass = $typeClass;
// Load eagerly everything.
$this->collection = $this->entityManager->getRepository($this->typeClass)->findAll();
}
/**
* returns the class this collection consists of.
* @return string
*/
public function getTypeClass(): ClassMetadata
{
return $this->entityManager->getClassMetadata($this->typeClass);
}
/**
* Counts the number of settings stored
* @return int
*/
public function count(): int
{
// If the collection has not been loaded yet, we should query the db directly
if ($this->collection === null and $this->numberOfRows === null) {
$this->numberOfRows = (int)$this->entityManager->createQueryBuilder()
->from($this->typeClass, "p")
->select("COUNT(p.propertyName)")
->getQuery()
->getSingleScalarResult();
}
if ($this->collection === null) {
return $this->numberOfRows;
}
else {
return count($this->collection);
}
}
/**
* Checks if the element matches the typeClass of this collection
* @param mixed $element
* @throws WrongTypeException
*/
private function checkElementType($element)
{
if ($element instanceof $this->typeClass === false) {
throw new WrongTypeException(sprintf('$element needs to be of type %s', $this->typeClass));
}
}
/**
* Adds an element to the collection
* @param mixed $element
*/
public function add($element)
{
$this->checkElementType($element);
if ($this->collection === null) {
$this->collection = [];
}
$this->collection[] = $element;
$this->entityManager->persist($element);
}
/**
* Clears the collection
*/
public function clear()
{
$this->entityManager->createQueryBuilder()
->delete($this->typeClass, "p")
->getQuery()
->execute();
$this->collection = [];
}
/**
* Returns true if a item is contained in this collection
* @param type $element
* @return bool
*/
public function contains($element): bool
{
$this->checkElementType($element);
return in_array($element, $this->collection);
}
/**
* Checks if this the collection is empty
* @return bool
*/
public function isEmpty(): bool
{
return empty($this->collection);
}
/**
* Removes an element from this collection by the given key
* @param int|string $key
*/
public function remove($key)
{
if (isset($this->collection[$key])) {
$element = $this->collection[$key];
$this->removeElement($element);
}
}
/**
* Removes an element from this collection
* @param type $element
*/
public function removeElement($element)
{
if ($this->contains($element)) {
$key = array_search($element, $this->collection);
$this->entityManager->remove($element);
unset($this->collection[$key]);
}
}
/**
* Checks if this collection contains a certain key
* @param int|string $key
*/
public function containsKey($key)
{
return isset($this->collection[$key]);
}
/**
* Returns the element saved at the given position
* @param int|string $key
* @return type
* @throws KeyNotFoundException
*/
public function get($key)
{
if (isset($this->collection[$key])) {
return $this->collection[$key];
}
else {
throw new KeyNotFoundException(sprintf("The key %s has not been found within the collection", $key));
}
}
/**
* Returns all collection keys
* @return array
*/
public function getKeys(): array
{
return array_keys($this->collection);
}
/**
* Returns all collection values
* @return array
*/
public function getValues(): array
{
return array_values($this->collection);
}
/**
* Sets the element at position $key to $value.
* @param int|string $key
* @param mixed $value
*/
public function set($key, $element)
{
$this->checkElementType($element);
$this->collection[$key] = $element;
}
/**
* Returns an array representation of this collection
* @return array
*/
public function toArray(): array
{
return $this->collection;
}
public function first()
{
return first($this->collection);
}
public function last()
{
return last($this->collection);
}
public function key()
{
return key($this->collection);
}
public function next()
{
return next($this->collection);
}
public function current()
{
return current($this->collection);
}
public function exists(\Closure $p): bool
{
throw new NotImplementedException();
}
public function filter(\Closure $p)
{
throw new NotImplementedException();
}
public function forAll(\Closure $p)
{
throw new NotImplementedException();
}
public function map(\Closure $p)
{
throw new NotImplementedException();
}
public function partition(\Closure $p)
{
throw new NotImplementedException();
}
/**
* Returns the index of a specific element
* @param mixed $element
* @return int|string
*/
public function indexOf($element)
{
$this->checkElementType($element);
return array_search($element, $this->collection);
}
public function slice($offset, $length = null)
{
throw new NotImplementedException();
}
/**
* Gets a Iterator over this collection
* @return \ArrayIterator
*/
public function getIterator()
{
return new \ArrayIterator($this->collection);
}
public function offsetGet($key) {
return $this->get($key);
}
public function offsetSet($key, $element) {
$this->set($key, $element);
}
public function offsetUnset($key) {
$this->remove($key);
}
public function offsetExists($key) {
return isset($this->collection[$key]);
}
}
+54
View File
@@ -0,0 +1,54 @@
<?php
declare(strict_types=1);
namespace LotGD\Core\Tests\Models;
use LotGD\Core\Models\GameConfiguration;
use LotGD\Core\Tests\ModelTestCase;
/**
* Tests the management of CharacterScenes
*/
class GameConfigurationTest extends ModelTestCase
{
/** @var string default data set */
protected $dataset = "gameConfiguration";
public function testGetConfiguration()
{
$configuration = new GameConfiguration($this->getEntityManager());
$this->assertSame("hallo", $configuration->get("default_test", "hallo"));
$this->assertSame(87897, $configuration->get("default_test_int", 87897));
$this->assertSame("Legend of the Green Dragon", $configuration->get("gameName", "Daenerys"));
$this->assertSame("1.0.5.6", $configuration->get("gameVersion", "1.0"));
$this->assertSame(30, $configuration->get("maxPlayerOnline", 100));
$this->assertSame(30.4, $configuration->get("testFloat", 100.123512));
$this->getEntityManager()->flush();
}
public function datasetSetAndGet() {
return [
["testOne", 15],
["testTwo", "256"]
];
}
/**
* Tests setting settings and fetching them back from the database
* @dataProvider datasetSetAndGet
* @param string $key
* @param mixed $value
*/
public function testSetAndGet(string $key, $value)
{
$configuration = new GameConfiguration($this->getEntityManager());
$configuration->set($key, $value);
$this->getEntityManager()->flush();
$this->getEntityManager()->clear();
$this->assertSame($value, $configuration->get($key, null));
}
}
+13
View File
@@ -0,0 +1,13 @@
game_configuration:
-
propertyName: "gameName"
propertyValue: 's:26:"Legend of the Green Dragon";'
-
propertyName: "gameVersion"
propertyValue: 's:7:"1.0.5.6";'
-
propertyName: "maxPlayerOnline"
propertyValue: 'i:30;'
-
propertyName: "testFloat"
propertyValue: 'd:30.4;'