diff --git a/CustomFields/CustomFieldChoice.php b/CustomFields/CustomFieldChoice.php index a34968db3..bc8c89d78 100644 --- a/CustomFields/CustomFieldChoice.php +++ b/CustomFields/CustomFieldChoice.php @@ -167,8 +167,96 @@ class CustomFieldChoice extends AbstractCustomField public function deserialize($serialized, CustomField $customField) { + // we always have to adapt to what the current data should be + $options = $customField->getOptions(); + + if ($options[self::MULTIPLE]) { + return $this->deserializeToMultiple($serialized, $options[self::ALLOW_OTHER]); + } else { + return $this->deserializeToUnique($serialized, $options[self::ALLOW_OTHER]); + } return $serialized; } + + private function deserializeToUnique($serialized, $allowOther) + { + $value = $this->guessValue($serialized); + + // set in a single value. We must have a single string + $fixedValue = is_array($value) ? + // check if the array has an element, if not replace by empty string + count($value) > 0 ? end($value) : '' + : + $value; + + if ($allowOther) { + return $this->deserializeWithAllowOther($serialized, $fixedValue); + } else { + return $fixedValue; + } + } + + /** + * deserialized the data from the database to a multiple + * field + * + * @param mixed $serialized + * @param boolean $allowOther + */ + private function deserializeToMultiple($serialized, $allowOther) + { + $value = $this->guessValue($serialized); + + // set in an array : we want a multiple + $fixedValue = is_array($value) ? $value : array($value); + + if ($allowOther) { + return $this->deserializeWithAllowOther($serialized, $fixedValue); + } else { + return $fixedValue; + } + } + + private function deserializeWithAllowOther($serialized, $value) + { + $existingOther = isset($serialized['_other']) ? $serialized['_other'] : ''; + + return array( + '_other' => $existingOther, + '_choices' => $value + ); + } + + /** + * Guess the value from the representation of it. + * + * If the value had an 'allow_other' = true option, the returned value + * **is not** the content of the _other field, but the `_other` string. + * + * @param array|string $value + * @return mixed + * @throws \LogicException if the case is not covered by this + */ + private function guessValue($value) + { + if ($value === NULL) { + return NULL; + } + + if (!is_array($value)) { + return $value; + } else { + // we have a field with "allow other" + if (isset($value['_choices'])) { + return $value['_choices']; + } else { + // we have a field with "multiple" + return $value; + } + } + + throw \LogicException("This case is not expected."); + } public function getName() { diff --git a/Tests/CustomFields/CustomFieldsChoiceTest.php b/Tests/CustomFields/CustomFieldsChoiceTest.php new file mode 100644 index 000000000..f01a283ee --- /dev/null +++ b/Tests/CustomFields/CustomFieldsChoiceTest.php @@ -0,0 +1,365 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +namespace Chill\CustomFieldsBundle\Tests; + +use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; +use Chill\CustomFieldsBundle\Entity\CustomField; +use Chill\CustomFieldsBundle\CustomFields\CustomFieldChoice; + +/** + * This class cover the test of CustomFieldChoice. + * + * Function currently covered: + * + * - deserialize + * + * @author Julien Fastré + */ +class CustomFieldsChoiceTest extends KernelTestCase +{ + + /** + * + * @var \Chill\CustomFieldsBundle\Service\CustomFieldProvider + */ + private $cfProvider; + + /** + * + * @var \Chill\CustomFieldsBundle\CustomFields\CustomFieldChoice + */ + private $cfChoice; + + public function setUp() + { + static::bootKernel(); + + $this->cfProvider = static::$kernel->getContainer() + ->get('chill.custom_field.provider'); + $this->cfChoice = $this->cfProvider->getCustomFieldByType('choice'); + } + + public function tearDown() + { + parent::tearDown(); + } + + /** + * + * @param array $options + * @return CustomField + */ + private function generateCustomField($options) + { + return (new CustomField()) + ->setActive(true) + ->setSlug('slug') + ->setOptions($options) + ->setType('choice') + ; + } + + ///////////////////////////////////////// + // + // test function deserialize + // + //////////////////////////////////////// + + /** + * Test if the representation of the data is deserialized to a single text. + * + * If the value is in _other, the _other value should not be returned. + * + * @param type $data + * @dataProvider serializedRepresentationDataProvider + */ + public function testDeserializeSingleChoiceWithoutOther($data) + { + $customField = $this->generateCustomField(array( + CustomFieldChoice::ALLOW_OTHER => false, + CustomFieldChoice::MULTIPLE => false + )); + + $deserialized = $this->cfChoice->deserialize($data, $customField); + + $this->assertSame('my-value', $deserialized); + } + + + public function testDeserializeSingleChoiceWithoutOtherDataIsNull() + { + $customField = $this->generateCustomField(array( + CustomFieldChoice::ALLOW_OTHER => false, + CustomFieldChoice::MULTIPLE => false + )); + + $deserialized = $this->cfChoice->deserialize(null, $customField); + + $this->assertSame(null, $deserialized); + + $deserialized = $this->cfChoice->deserialize('', $customField); + + $this->assertSame('', $deserialized); + } + + /** + * Test if the representation of the data is deserialized to a single text + * with an "allow_other" field. + * + * If the value is in _other, the _other value should be in the _other field. + * + * @param type $data + * @dataProvider serializedRepresentationDataProvider + */ + public function testDeserializeSingleChoiceWithOther($data) + { + $customField = $this->generateCustomField(array( + CustomFieldChoice::ALLOW_OTHER => true, + CustomFieldChoice::MULTIPLE => false + )); + + $deserialized = $this->cfChoice->deserialize($data, $customField); + + $this->assertSame(array('_other' => '', '_choices' => 'my-value'), $deserialized); + } + + /** + * Other cases : + * + * - Test if the selected value is '_other + * - Test with null data + * + * @param type $data + */ + public function testDeserializeSingleChoiceWithOtherOtherCases() + { + $customField = $this->generateCustomField(array( + CustomFieldChoice::ALLOW_OTHER => true, + CustomFieldChoice::MULTIPLE => false + )); + + // from a single to a single + $data = array('_other' => 'something', '_choices' => '_other'); + $deserialized = $this->cfChoice->deserialize($data, $customField); + + $this->assertSame(array('_other' => 'something', '_choices' => '_other'), $deserialized); + + + // from a multiple to a single + $data = array('_other' => 'something', '_choices' => array('some', '_other')); + $deserialized = $this->cfChoice->deserialize($data, $customField); + + $this->assertSame(array('_other' => 'something', '_choices' => '_other'), $deserialized); + + //test with null data + //from a single to a single : + $data = array('_other' => 'something', '_choices' => null); + $deserialized = $this->cfChoice->deserialize($data, $customField); + + $this->assertSame(array('_other' => 'something', '_choices' => null), $deserialized); + + $data = array('_other' => 'something', '_choices' => ''); + $deserialized = $this->cfChoice->deserialize($data, $customField); + + $this->assertSame(array('_other' => 'something', '_choices' => ''), $deserialized); + + // from a multiple to a signle + $data = array('_other' => 'something', '_choices' => array()); + $deserialized = $this->cfChoice->deserialize($data, $customField); + + $this->assertSame(array('_other' => 'something', '_choices' => ''), $deserialized); + + $data = array('_other' => 'something', '_choices' => array('')); + $deserialized = $this->cfChoice->deserialize($data, $customField); + + $this->assertSame(array('_other' => 'something', '_choices' => ''), $deserialized); + + } + + /** + * Test if the representation of the data is deserialized to an array text + * with an "allow_other" field. + * + * This test does not covers the case when the selected value is `_other` + * + * @param type $data + * @dataProvider serializedRepresentationDataProvider + */ + public function testDeserializeMultipleChoiceWithOther($data) + { + $customField = $this->generateCustomField(array( + CustomFieldChoice::ALLOW_OTHER => true, + CustomFieldChoice::MULTIPLE => true + )); + + $deserialized = $this->cfChoice->deserialize($data, $customField); + + $this->assertSame(array('_other' => '', '_choices' => array('my-value')), + $deserialized); + } + + /** + * Test if the representation of the data is deserialized to an array text + * with an "allow_other" field. + * + * This test covers : + * - the case when the selected value is `_other` + * - result is null + * + * @param type $data + */ + public function testDeserializeMultipleChoiceWithOtherOtherCases() + { + $customField = $this->generateCustomField(array( + CustomFieldChoice::ALLOW_OTHER => true, + CustomFieldChoice::MULTIPLE => true + )); + + // selected value is _other + // from single to multiple + $data = array('_other' => 'something', '_choices' => '_other'); + $deserialized = $this->cfChoice->deserialize($data, $customField); + + $this->assertSame(array('_other' => 'something', '_choices' => array('_other')), + $deserialized); + + // from multiple to multiple + $data = array('_other' => 'something', '_choices' => array('_other', 'something')); + $deserialized = $this->cfChoice->deserialize($data, $customField); + + $this->assertSame(array('_other' => 'something', '_choices' => array('_other', 'something')), + $deserialized); + + // test with null value + // from single to multiple + $data = array('_other' => '', '_choices' => ''); + $deserialized = $this->cfChoice->deserialize($data, $customField); + + $this->assertSame(array('_other' => '', '_choices' => array('')), + $deserialized); + + // from multiple to multiple + $data = array('_other' => '', '_choices' => array()); + $deserialized = $this->cfChoice->deserialize($data, $customField); + + $this->assertSame(array('_other' => '', '_choices' => array()), + $deserialized); + } + + /** + * Test if the representation of the data is deserialized to an array text + * **without** an "allow_other" field. + * + * + * @param type $data + * @dataProvider serializedRepresentationDataProvider + */ + public function testDeserializeMultipleChoiceWithoutOther($data) + { + $customField = $this->generateCustomField(array( + CustomFieldChoice::ALLOW_OTHER => false, + CustomFieldChoice::MULTIPLE => true + )); + + $deserialized = $this->cfChoice->deserialize($data, $customField); + + $this->assertSame(array('my-value'), $deserialized); + } + + /** + * Test if the representation of the data is deserialized to an array text + * **without** an "allow_other" field. + * + * Covered cases : + * - NULL values + * + * + * @param type $data + */ + public function testDeserializeMultipleChoiceWithoutOtherOtherCases() + { + $customField = $this->generateCustomField(array( + CustomFieldChoice::ALLOW_OTHER => false, + CustomFieldChoice::MULTIPLE => true + )); + + // from single to multiple + $data = 'my-value'; + $deserialized = $this->cfChoice->deserialize($data, $customField); + + $this->assertSame(array('my-value'), $deserialized); + + // from multiple to multiple + $data = array('my-value'); + $deserialized = $this->cfChoice->deserialize($data, $customField); + + $this->assertSame(array('my-value'), $deserialized); + } + + public function serializedRepresentationDataProvider() + { + return array( + array( + // multiple => false, allow_other => false + 'my-value' + ), + array( + // multiple => true, allow_ther => false + array('my-value') + ), + array( + // multiple => false, allow_other => true, current value not in other + array('_other' => '', '_choices' => 'my-value') + ), + array( + // multiple => true, allow_other => true, current value not in other + array('_other' => '', '_choices'=> array('my-value')) + ), + ); + } + + + + ///////////////////////////////////////// + // + // test function isEmptyValue + // + //////////////////////////////////////// + + /** + * + * @param mixed $data + * @dataProvider serializedRepresentationDataProvider + */ + public function testIsEmptyValueNotEmpty($data) + { + $this->markTestSkipped("We have to improve the isEmptyFunction"); + $customField = $this->generateCustomField(array( + CustomFieldChoice::ALLOW_OTHER => false, + CustomFieldChoice::MULTIPLE => true + )); + + $deserialized = $this->cfChoice->deserialize($data, $customField); + $isEmpty = $this->cfChoice->isEmptyValue($deserialized, $customField); + + $this->assertFalse($isEmpty); + } + +}