diff --git a/src/Db/Decorator/Helper/MappingHelperTrait.php b/src/Db/Decorator/Helper/MappingHelperTrait.php index 44f5fad..0627fcd 100644 --- a/src/Db/Decorator/Helper/MappingHelperTrait.php +++ b/src/Db/Decorator/Helper/MappingHelperTrait.php @@ -14,6 +14,8 @@ /** * Class MappingHelperTrait + * Strictly coupled with \Vegas\Db\MappingResolverTrait + * Manages mappings specified manually in models & calls the mapping resolving tasks. * @package Vegas\Db\Decorator */ trait MappingHelperTrait @@ -22,14 +24,14 @@ trait MappingHelperTrait * Defines field mappings in format * * - * array( + * [ * 'field_1' => 'mapper_1', - * 'field_2' => array('mapper_1', 'mapper_2') - * ) + * 'field_2' => ['mapper_1', 'mapper_2'] + * ] * * @var array */ - protected $mappings = array(); + protected $mappings = []; /** * Returns array of attributes with mapped values @@ -39,7 +41,7 @@ trait MappingHelperTrait public function toMappedArray() { $values = $this->toArray(); - $mappedValues = array(); + $mappedValues = []; foreach ($values as $key => $value) { $mappedValues[$key] = $this->readMapped($key); } @@ -50,7 +52,7 @@ public function toMappedArray() /** * Returns mapped value of attribute * - * @param $name + * @param string $name * @return mixed */ public function readMapped($name) @@ -66,27 +68,27 @@ public function readMapped($name) } /** - * @param $name + * @param string $name * @return mixed */ abstract public function hasMapping($name); /** - * @param $name - * @param $mapping + * @param string $name + * @param mixed $mappings * @return mixed */ - abstract public function addMapping($name, $mapping); + abstract public function addMapping($name, $mappings); /** - * @param $name + * @param string $name * @return mixed */ abstract public function readAttribute($name); /** - * @param $name - * @param $value + * @param string $name + * @param mixed $value * @return mixed */ abstract public function resolveMapping($name, $value); diff --git a/src/Db/Mapping/Blob.php b/src/Db/Mapping/Blob.php new file mode 100644 index 0000000..5c643e6 --- /dev/null +++ b/src/Db/Mapping/Blob.php @@ -0,0 +1,46 @@ + + * @copyright Amsterdam Standard Sp. Z o.o. + * @homepage http://vegas-cmf.github.io + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Vegas\Db\Mapping; + +use Vegas\Db\MappingInterface; + +/** + * Class Blob + * + * Simple mapper for binary fields + * + * @package Vegas\Db\Mapping + */ +class Blob implements MappingInterface +{ + /** + * {@inheritdoc} + */ + public function getName() + { + return 'blob'; + } + + /** + * {@inheritdoc} + */ + public function resolve(& $value) + { + if (is_string($value) && strlen($value) > 0) { + $decoded = base64_decode($value, true); + $decoded !== false && $value = $decoded; + } + + return $value; + } +} \ No newline at end of file diff --git a/src/Db/Mapping/Camelize.php b/src/Db/Mapping/Camelize.php new file mode 100644 index 0000000..cec5e8f --- /dev/null +++ b/src/Db/Mapping/Camelize.php @@ -0,0 +1,45 @@ + + * @copyright Amsterdam Standard Sp. Z o.o. + * @homepage http://vegas-cmf.github.io + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Vegas\Db\Mapping; + +use Vegas\Db\MappingInterface; + +/** + * Class Camelize + * + * Simple mapper for converting text to camelize style + * + * @package Vegas\Db\Mapping + */ +class Camelize implements MappingInterface +{ + /** + * {@inheritdoc} + */ + public function getName() + { + return 'camelize'; + } + + /** + * {@inheritdoc} + */ + public function resolve(& $value) + { + if (is_string($value) && strlen($value) > 0) { + $value = \Phalcon\Text::camelize($value); + } + + return $value; + } +} \ No newline at end of file diff --git a/src/Db/Mapping/Decimal.php b/src/Db/Mapping/Decimal.php new file mode 100644 index 0000000..f064c2a --- /dev/null +++ b/src/Db/Mapping/Decimal.php @@ -0,0 +1,45 @@ + + * @copyright Amsterdam Standard Sp. Z o.o. + * @homepage http://vegas-cmf.github.io + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Vegas\Db\Mapping; + +use Vegas\Db\MappingInterface; + +/** + * Class Decimal + * + * Simple mapper for number fields + * + * @package Vegas\Db\Mapping + */ +class Decimal implements MappingInterface +{ + /** + * {@inheritdoc} + */ + public function getName() + { + return 'decimal'; + } + + /** + * {@inheritdoc} + */ + public function resolve(& $value) + { + if (is_numeric($value) && strlen($value) > 0) { + $value = number_format($value, 2, '.', ''); + } + + return $value; + } +} \ No newline at end of file diff --git a/src/Db/Mapping/Lowercase.php b/src/Db/Mapping/Lowercase.php new file mode 100644 index 0000000..252f099 --- /dev/null +++ b/src/Db/Mapping/Lowercase.php @@ -0,0 +1,45 @@ + + * @copyright Amsterdam Standard Sp. Z o.o. + * @homepage http://vegas-cmf.github.io + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Vegas\Db\Mapping; + +use Vegas\Db\MappingInterface; + +/** + * Class Lowercase + * + * Simple mapper for converting text to lowercase style + * + * @package Vegas\Db\Mapping + */ +class Lowercase implements MappingInterface +{ + /** + * {@inheritdoc} + */ + public function getName() + { + return 'lowercase'; + } + + /** + * {@inheritdoc} + */ + public function resolve(& $value) + { + if (is_string($value) && strlen($value) > 0) { + $value = \Phalcon\Text::lower($value); + } + + return $value; + } +} \ No newline at end of file diff --git a/src/Db/Mapping/Serialize.php b/src/Db/Mapping/Serialize.php new file mode 100644 index 0000000..6de588a --- /dev/null +++ b/src/Db/Mapping/Serialize.php @@ -0,0 +1,48 @@ + + * @copyright Amsterdam Standard Sp. Z o.o. + * @homepage http://vegas-cmf.github.io + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Vegas\Db\Mapping; + +use Vegas\Db\MappingInterface; + +/** + * Class Serialize + * + * Simple mapper for PHP serialized fields + * + * @package Vegas\Db\Mapping + */ +class Serialize implements MappingInterface +{ + /** + * {@inheritdoc} + */ + public function getName() + { + return 'serialize'; + } + + /** + * {@inheritdoc} + */ + public function resolve(& $value) + { + if (is_string($value) && strlen($value) > 0) { + $unserialized = unserialize($value); + if ($value !== serialize(false) && $unserialized !== false) { + $value = $unserialized; + } + } + + return $value; + } +} \ No newline at end of file diff --git a/src/Db/Mapping/Uppercase.php b/src/Db/Mapping/Uppercase.php new file mode 100644 index 0000000..fa478e3 --- /dev/null +++ b/src/Db/Mapping/Uppercase.php @@ -0,0 +1,45 @@ + + * @copyright Amsterdam Standard Sp. Z o.o. + * @homepage http://vegas-cmf.github.io + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Vegas\Db\Mapping; + +use Vegas\Db\MappingInterface; + +/** + * Class Uppercase + * + * Simple mapper for converting text to uppercase style + * + * @package Vegas\Db\Mapping + */ +class Uppercase implements MappingInterface +{ + /** + * {@inheritdoc} + */ + public function getName() + { + return 'uppercase'; + } + + /** + * {@inheritdoc} + */ + public function resolve(& $value) + { + if (is_string($value) && strlen($value) > 0) { + $value = \Phalcon\Text::upper($value); + } + + return $value; + } +} \ No newline at end of file diff --git a/src/Db/MappingResolverTrait.php b/src/Db/MappingResolverTrait.php index 879ca50..2c2c83a 100644 --- a/src/Db/MappingResolverTrait.php +++ b/src/Db/MappingResolverTrait.php @@ -15,6 +15,7 @@ /** * Class MappingResolverTrait + * Handles lifecycle of mapper classes which properly read DB data. * @package Vegas\Db */ trait MappingResolverTrait @@ -25,22 +26,22 @@ trait MappingResolverTrait * @var array * @internal */ - private $mappingsContainer = array(); + private $mappingsContainer = []; /** * Adds mapping for indicated attribute * - * @param $attributeName - * @param $mappings + * @param string $attributeName + * @param mixed $mappings * @return $this */ public function addMapping($attributeName, $mappings) { if (!is_array($mappings)) { - $mappings = array($mappings); + $mappings = [$mappings]; } if (!$this->hasMapping($attributeName)) { - $this->mappingsContainer[$attributeName] = array(); + $this->mappingsContainer[$attributeName] = []; } if ($this->mappingsContainer[$attributeName] !== null) { foreach ($mappings as $mapping) { @@ -53,7 +54,7 @@ public function addMapping($attributeName, $mappings) /** * Removes mapping from indicated attribute * - * @param $attributeName + * @param string $attributeName * @return $this */ public function removeMapping($attributeName) @@ -68,7 +69,7 @@ public function removeMapping($attributeName) /** * Determines if attribute has defined mapping * - * @param $attributeName + * @param string $attributeName * @return bool */ public function hasMapping($attributeName) @@ -92,8 +93,8 @@ public function clearMappings() /** * Filter value of indicated attribute by applying defined mappings * - * @param $attributeName - * @param $value + * @param string $attributeName + * @param mixed $value * @return mixed */ public function resolveMapping($attributeName, $value) diff --git a/tests/Db/MappingTest.php b/tests/Db/MappingTest.php index 1fe8326..980ff1f 100644 --- a/tests/Db/MappingTest.php +++ b/tests/Db/MappingTest.php @@ -17,8 +17,14 @@ use Vegas\Db\Decorator\ModelAbstract; use Vegas\Db\Exception\InvalidMappingClassException; use Vegas\Db\Exception\MappingClassNotFoundException; +use Vegas\Db\Mapping\Blob; +use Vegas\Db\Mapping\Camelize; +use Vegas\Db\Mapping\DateTime as DateTimeMapping; +use Vegas\Db\Mapping\Decimal; use Vegas\Db\Mapping\Json; -use Vegas\Db\MappingInterface; +use Vegas\Db\Mapping\Lowercase; +use Vegas\Db\Mapping\Serialize; +use Vegas\Db\Mapping\Uppercase; use Vegas\Db\MappingManager; use Vegas\Util\DateTime; @@ -29,12 +35,14 @@ public function getSource() return 'fake'; } - protected $mappings = array( + protected $mappings = [ 'somedata' => 'json', 'somecamel' => 'camelize', - 'encoded' => 'decoder', - 'upperstring' => 'upperCase' - ); + 'encoded' => 'blob', + 'upperstring' => 'uppercase', + 'phpobject' => 'serialize', + 'currency' => 'decimal' + ]; } class FakeModel extends ModelAbstract @@ -44,11 +52,11 @@ public function getSource() return 'fake_table'; } - protected $mappings = array( + protected $mappings = [ 'somedata' => 'json', 'somecamel' => 'camelize', - 'encoded' => 'decoder', - ); + 'encoded' => 'blob' + ]; } class FakeDate extends CollectionAbstract @@ -63,75 +71,25 @@ public function getSource() ]; } -class UpperCase implements MappingInterface -{ - /** - * {@inheritdoc} - */ - public function getName() - { - return 'upperCase'; - } - - /** - * {@inheritdoc} - */ - public function resolve(& $value) - { - $value = strtoupper($value); - - return $value; - } -} - -class Decoder implements MappingInterface +class FakeMultiple extends CollectionAbstract { - /** - * {@inheritdoc} - */ - public function getName() + public function getSource() { - return 'decoder'; + return 'fake_multiple'; } - /** - * {@inheritdoc} - */ - public function resolve(& $value) - { - $value = base64_decode($value); - - return $value; - } + protected $mappings = [ + 'jsonlower' => ['json', 'lowercase'] + ]; } -/** - * Class Camelize - * - * Simple mapper for converting text to camelize style - * - * @package Vegas\Db\Mapping - */ -class Camelize implements MappingInterface +class FakeClass { - /** - * {@inheritdoc} - */ - public function getName() - { - return 'camelize'; - } + public $param; - /** - * {@inheritdoc} - */ - public function resolve(& $value) + public function __construct($param) { - if (is_string($value) && strlen($value) > 0) { - $value = \Phalcon\Text::camelize($value); - } - - return $value; + $this->param = $param; } } @@ -164,14 +122,14 @@ public static function tearDownAfterClass() public function testShouldAddMapperToMappingManager() { //define mappings - $mappingManager = new MappingManager(); + $mappingManager = new MappingManager; $this->assertInternalType('array', $mappingManager->getMappers()); $this->assertEmpty($mappingManager->getMappers()); - $mappingManager->add(new Json()); - $mappingManager->add(new Camelize()); - $mappingManager->add(new UpperCase()); + $mappingManager->add(new Json); + $mappingManager->add(new Camelize); + $mappingManager->add(new Uppercase); $this->assertInternalType('array', $mappingManager->getMappers()); $this->assertNotEmpty($mappingManager->getMappers()); @@ -183,7 +141,7 @@ public function testShouldAddMapperToMappingManager() $this->assertInstanceOf('\Vegas\Db\MappingInterface', MappingManager::find('camelize')); try { - $mappingManager->add(new \stdClass()); + $mappingManager->add(new \stdClass); } catch (InvalidMappingClassException $e) { $m = $e->getMessage(); } @@ -207,18 +165,18 @@ public function testShouldAddMapperToMappingManager() public function testShouldResolveCollectionMappings() { - $mappingManager = new MappingManager(); - $mappingManager->add(new Json()); - $mappingManager->add(new Camelize()); - $mappingManager->add(new Decoder()); - $mappingManager->add(new UpperCase()); + $mappingManager = new MappingManager; + $mappingManager->add(new Json); + $mappingManager->add(new Camelize); + $mappingManager->add(new Blob); + $mappingManager->add(new Uppercase); - DI::getDefault()->get('mongo')->selectCollection('fake')->remove(array()); + DI::getDefault()->get('mongo')->selectCollection('fake')->remove([]); /** CREATE RECORD */ $fake = new Fake(); - $someData = json_encode(array(1,2,3,4,5,6)); + $someData = json_encode([1,2,3,4,5,6]); $fake->somedata = $someData; $nonCamelText = 'this_is_non_camel_case_text'; @@ -251,13 +209,13 @@ public function testShouldResolveCollectionMappings() $this->assertEquals($encodedVal, $fakeDoc->readAttribute('encoded')); $this->assertEquals($lowerTxt, $fakeDoc->readAttribute('upperstring')); - $ownMappedValues = array( + $ownMappedValues = [ '_id' => $fakeDoc->readMapped('_id'), 'somedata' => $fakeDoc->readMapped('somedata'), 'somecamel' => $fakeDoc->readMapped('somecamel'), 'encoded' => $fakeDoc->readMapped('encoded'), 'upperstring' => $fakeDoc->readMapped('upperstring') - ); + ]; $mappedValues = $fakeDoc->toMappedArray(); $this->assertEquals($mappedValues['somedata'], $ownMappedValues['somedata']); @@ -279,8 +237,8 @@ public function testShouldResolveModelMappings() $mappingManager->add(new Json()); $mappingManager->add(new Camelize()); - $someData = json_encode(array(1,2,3,4,5,6)); - $fake = new FakeModel(); + $someData = json_encode([1,2,3,4,5,6]); + $fake = new FakeModel; $fake->somedata = $someData; $nonCamelText = 'this_is_non_camel_case_text'; $fake->somecamel = $nonCamelText; @@ -296,11 +254,11 @@ public function testShouldResolveModelMappings() $this->assertEquals($someData, $fakeRecord->readAttribute('somedata')); $this->assertEquals($nonCamelText, $fakeRecord->readAttribute('somecamel')); - $ownMappedValues = array( + $ownMappedValues = [ '_id' => $fakeRecord->readMapped('_id'), 'somedata' => $fakeRecord->readMapped('somedata'), 'somecamel' => $fakeRecord->readMapped('somecamel'), - ); + ]; $mappedValues = $fakeRecord->toMappedArray(); $this->assertEquals($mappedValues['somedata'], $ownMappedValues['somedata']); @@ -315,8 +273,8 @@ public function testShouldResolveModelMappings() public function testShouldResolveDateTime() { - $mappingManager = new MappingManager(); - $mappingManager->add(new \Vegas\Db\Mapping\DateTime()); + $mappingManager = new MappingManager; + $mappingManager->add(new DateTimeMapping); $now = new \DateTime('now'); @@ -337,4 +295,51 @@ public function testShouldResolveDateTime() $this->assertEquals($now->format('d/m/Y'), $fake->readMapped('createdAt')); $this->assertInternalType('string', $fake->readMapped('createdAt')); } + + public function testShouldResolveMultipleMappersForOneField() + { + $mappingManager = new MappingManager; + $mappingManager->add('\Vegas\Db\Mapping\Json'); + $mappingManager->add(new Lowercase); + + $fake = new FakeMultiple; + $fake->jsonlower = json_encode('SOME DATA'); + + $this->assertSame('some data', $fake->readMapped('jsonlower')); + $this->assertInternalType('string', $fake->readMapped('jsonlower')); + } + + public function testShouldResolveValidCopyOfPhpObject() + { + $mappingManager = new MappingManager; + $mappingManager->add(new Serialize); + + $data = new FakeClass('whatever'); + + $fake = new Fake; + $fake->phpobject = serialize($data); + + $this->assertInstanceOf('\Vegas\Tests\Db\FakeClass', $fake->readMapped('phpobject')); + $this->assertEquals('whatever', $fake->readMapped('phpobject')->param); + $this->assertEquals($data, $fake->readMapped('phpobject')); + + $this->assertNotSame($data, $fake->readMapped('phpobject')); + } + + public function testShouldPrintDecimalValue() + { + $mappingManager = new MappingManager; + $mappingManager->add(new Decimal); + + $fake = new Fake; + $fake->currency = 987654.0321; + + $this->assertInternalType('string', $fake->readMapped('currency')); + $this->assertEquals('987654.03', $fake->readMapped('currency')); + + $fake->currency = 7.1234E3; + + $this->assertInternalType('string', $fake->readMapped('currency')); + $this->assertEquals('7123.40', $fake->readMapped('currency')); + } } \ No newline at end of file