diff --git a/core/lib/Thelia/Core/FileFormat/Formatter/FormatterData.php b/core/lib/Thelia/Core/FileFormat/Formatter/FormatterData.php index 0a7ed344d..f2aaa8507 100644 --- a/core/lib/Thelia/Core/FileFormat/Formatter/FormatterData.php +++ b/core/lib/Thelia/Core/FileFormat/Formatter/FormatterData.php @@ -11,9 +11,10 @@ /*************************************************************************************/ namespace Thelia\Core\FileFormat\Formatter; +use Propel\Runtime\ActiveQuery\Criteria; use Propel\Runtime\ActiveQuery\ModelCriteria; -use Propel\Runtime\Collection\ArrayCollection; -use Propel\Runtime\Collection\ObjectCollection; +use Propel\Runtime\ActiveQuery\ModelJoin; +use Propel\Runtime\Map\TableMap; use Thelia\Core\Translation\Translator; /** @@ -26,14 +27,74 @@ class FormatterData /** @var array */ protected $data; + /** @var null|array */ + protected $aliases; + /** @var Translator */ protected $translator; - public function __construct() + /** + * @param array $aliases + * + * $aliases is a associative array where the key represents propel TYPE_PHP_NAME of column if you use + * loadModelCriteria, or your own aliases for setData, and the value + * is the alias. It can be null or empty if you don't want aliases, + * but remember to always define all the fields the you want: + * non aliases fields will be ignored. + */ + public function __construct(array $aliases = null) { $this->translator = Translator::getInstance(); + + if (!is_array($aliases)) { + $aliases = []; + } + + /** + * Lower all the values + */ + foreach ($aliases as $key => $value) { + $lowerKey = strtolower($key); + $lowerValue = strtolower($value); + if ($lowerKey !== $key) { + $aliases[$lowerKey] = $lowerValue; + unset($aliases[$key]); + } else { + $aliases[$key] = $lowerValue; + } + } + + $this->aliases = $aliases; } + /** + * @param array $data + * @return $this + * + * Sets raw data with aliases + */ + public function setData(array $data) + { + if (empty($this->aliases)) { + $this->data = $data; + return $this; + } + + $this->data = $this->applyAliases($data, $this->aliases); + + return $this; + } + + /** + * @param ModelCriteria $criteria + * @return $this|null + * + * Loads a model criteria. + * Warning: if you want to do multi table export, + * you'll have to use you own select and not the joinYourTable method. + * For more details, please see the unit test + * Thelia\Tests\FileFormat\Formatter\FormatterDataTest::testFormatSimpleMultipleTableQuery + */ public function loadModelCriteria(ModelCriteria $criteria) { $propelData = $criteria->find(); @@ -44,23 +105,62 @@ class FormatterData $asColumns = $propelData->getFormatter()->getAsColumns(); - if (empty($asColumns) && $propelData instanceof ObjectCollection) { - /** - * Full request ( without select nor join ) - */ - } elseif (empty($asColumns) && $propelData instanceof ArrayCollection) { - /** - * Request with joins, but without select - */ - } elseif (count($asColumns) > 1) { + /** + * Format it correctly + * After this pass, we MUST have a 2D array. + * The first may be keyed with integers. + */ + $formattedResult = $propelData + ->toArray(null, false, TableMap::TYPE_COLNAME); + + if (count($asColumns) > 1) { /** * Request with multiple select + * Apply propel aliases */ + $formattedResult = $this->applyAliases($formattedResult, $asColumns); } elseif (count($asColumns) === 1) { /** * Request with one select */ + $key = str_replace("\"", "", array_keys($asColumns)[0]); + $formattedResult = [[$key => $formattedResult[0]]]; } + $data = $this->applyAliases($formattedResult, $this->aliases); + + /** + * Then store it + */ + $this->data = $data; + + return $this; + } + + /** + * @param array $data + * @param array $aliases + */ + protected function applyAliases(array $data, array $aliases) + { + $formattedData = []; + + foreach ($data as $key=>$entry) { + $key = strtolower($key); + + if (is_array($entry)) { + $formattedData[$key] = $this->applyAliases($entry, $aliases); + } else { + $alias = isset($aliases[$key]) ? $aliases[$key] : $key; + $formattedData[$alias] = $entry; + } + } + + return $formattedData; + } + + public function getData() + { + return $this->data; } } diff --git a/core/lib/Thelia/Tests/FileFormat/Formatter/FormatterDataTest.php b/core/lib/Thelia/Tests/FileFormat/Formatter/FormatterDataTest.php index 369e2bc41..31949a60c 100644 --- a/core/lib/Thelia/Tests/FileFormat/Formatter/FormatterDataTest.php +++ b/core/lib/Thelia/Tests/FileFormat/Formatter/FormatterDataTest.php @@ -11,13 +11,20 @@ /*************************************************************************************/ namespace Thelia\Tests\FileFormat\Formatter; +use Propel\Generator\Builder\Om\QueryBuilder; use Propel\Runtime\ActiveQuery\Criteria; +use Propel\Runtime\DataFetcher\ArrayDataFetcher; +use Propel\Runtime\Formatter\ArrayFormatter; +use Propel\Runtime\Map\TableMap; +use Propel\Runtime\Propel; use Symfony\Component\DependencyInjection\Container; use Thelia\Core\FileFormat\Formatter\FormatterData; +use Thelia\Core\Thelia; use Thelia\Core\Translation\Translator; use Thelia\Model\Base\ProductQuery; use Thelia\Model\Base\ProductSaleElementsQuery; -use Thelia\Model\LangQuery; +use Thelia\Model\ConfigQuery; +use Thelia\Model\Map\ProductTableMap; use Thelia\Model\Product; /** @@ -28,14 +35,11 @@ use Thelia\Model\Product; class FormatterDataTest extends \PHPUnit_Framework_TestCase { - protected $data; - public function setUp() { new Translator(new Container()); - $this->data = new FormatterData(); - $query = ProductQuery::create() + /* ->filterById([3,4,5], Criteria::IN); $this->data->loadModelCriteria($query); @@ -60,11 +64,307 @@ class FormatterDataTest extends \PHPUnit_Framework_TestCase ->joinProductSaleElements() ->filterById([3,4,5], Criteria::IN); - $this->data->loadModelCriteria($query); + $this->data->loadModelCriteria($query);*/ } - public function testA() + public function testFormatSimpleQuery() { + $formatterData = new FormatterData(); + $query = ConfigQuery::create() + ->limit(1) + ; + + $formattedData = $formatterData + ->loadModelCriteria($query) + ->getData() + ; + + /** @var \Thelia\Model\Config $result */ + $result = $query->findOne(); + + $formattedResult = [ + [ + "config.id" => $result->getId(), + "config.name" => $result->getName(), + "config.value" => $result->getValue(), + "config.created_at" => $result->getCreatedAt(), + "config.updated_at" => $result->getUpdatedAt(), + "config.hidden" => $result->getHidden(), + "config.secured" => $result->getHidden(), + ], + ]; + + $this->assertEquals($formattedResult,$formattedData); } + + public function testFormatSimpleQueryWithAliases() + { + /** + * Aliases must not be case sensitive + */ + $aliases = [ + "coNfiG.iD" => "id", + "conFig.NaMe" => "name", + "CoNfIg.Value" => "value", + "config.hidden" => "hidden", + "ConFig.Secured" => "secured", + ]; + + $formatterData = new FormatterData($aliases); + + $query = ConfigQuery::create() + ->limit(1) + ; + + $formattedData = $formatterData + ->loadModelCriteria($query) + ->getData() + ; + + /** @var \Thelia\Model\Config $result */ + $result = $query->findOne(); + + $formattedResult = [ + [ + "id" => $result->getId(), + "name" => $result->getName(), + "value" => $result->getValue(), + "config.created_at" => $result->getCreatedAt(), + "config.updated_at" => $result->getUpdatedAt(), + "hidden" => $result->getHidden(), + "secured" => $result->getHidden(), + ], + ]; + + $this->assertEquals($formattedResult,$formattedData); + } + + public function testFormatSimpleMultipleTableQuery() + { + $formatterData = new FormatterData(); + + + } + + public function testFormatSimpleMultipleTableQueryWithAliases() + { + /** + * Aliases must not be case sensitive + */ + $aliases = [ + "coNfiG.iD" => "id", + "conFig.NaMe" => "name", + "CoNfIg.Value" => "value", + "config.hidden" => "hidden", + "ConFig.Secured" => "secured", + ]; + + $formatterData = new FormatterData($aliases); + + $query = ConfigQuery::create() + ->limit(1) + ; + + $formattedData = $formatterData + ->loadModelCriteria($query) + ->getData() + ; + + /** @var \Thelia\Model\Config $result */ + $result = $query->findOne(); + + $formattedResult = [ + [ + "id" => $result->getId(), + "name" => $result->getName(), + "value" => $result->getValue(), + "config.created_at" => $result->getCreatedAt(), + "config.updated_at" => $result->getUpdatedAt(), + "hidden" => $result->getHidden(), + "secured" => $result->getHidden(), + ], + ]; + + $this->assertEquals($formattedResult,$formattedData); + } + + public function testSetRawDataDepth1() { + $formatterData = new FormatterData(); + + $data = [ + "foo" => "bar", + "baz" => "foo", + ]; + + $formattedData = $formatterData + ->setData($data) + ->getData() + ; + + $this->assertEquals($data,$formattedData); + } + + public function testSetRawDataDepth1WithAliases() { + $aliases = [ + "FoO" => "orange", + "Baz" => "banana", + ]; + + $formatterData = new FormatterData($aliases); + + $data = [ + "fOo" => "bar", + "bAZ" => "foo", + ]; + + $expectedData = [ + "orange" => "bar", + "banana" => "foo", + ]; + + $formattedData = $formatterData + ->setData($data) + ->getData() + ; + + $this->assertEquals($expectedData,$formattedData); + } + + public function testSetRawDataDepth2() { + $formatterData = new FormatterData(); + + $data = [ + [ + "orange" => "banana", + "apple" => "pear", + ], + [ + "strawberry" => "raspberry", + "blackberry" => "cranberry", + ] + ]; + + $formattedData = $formatterData + ->setData($data) + ->getData() + ; + + $this->assertEquals($data,$formattedData); + } + + public function testSetRawDataDepth2WithAliases() { + $aliases = [ + "orange" => "cherry", + "blackberry" => "banana", + ]; + + $formatterData = new FormatterData($aliases); + + $data = [ + [ + "orange" => "banana", + "apple" => "pear", + ], + [ + "strawberry" => "raspberry", + "blackberry" => "cranberry", + ] + ]; + + $expectedData = [ + [ + "cherry" => "banana", + "apple" => "pear", + ], + [ + "strawberry" => "raspberry", + "banana" => "cranberry", + ] + ]; + + $formattedData = $formatterData + ->setData($data) + ->getData() + ; + + $this->assertEquals($expectedData,$formattedData); + } + + public function testSetRawDataMultipleDepth() { + $formatterData = new FormatterData(); + + $data = [ + [ + "orange" => "banana", + "apple" => "pear", + ], + [ + "strawberry" => "raspberry", + "blackberry" => "cranberry", + ] + ]; + + $formattedData = $formatterData + ->setData($data) + ->getData() + ; + + $this->assertEquals($data,$formattedData); + } + + public function testSetRawDataMultipleDepthWithAliases() { + $aliases = [ + "orange" => "cherry", + "blackberry" => "banana", + ]; + + $formatterData = new FormatterData($aliases); + + $data = [ + "orange" => "banana", + "apple" => "pear", + [ + "orange" => "tomato", + "pepper" => "pear", + ], + [ + [ + "strawberry" => "raspberry", + "blackberry" => "cranberry", + ], + [ + "cherry" => "lemon", + "mango" => "cranberry", + ] + ], + ]; + + $expectedData = [ + "cherry" => "banana", + "apple" => "pear", + [ + "cherry" => "tomato", + "pepper" => "pear", + ], + [ + [ + "strawberry" => "raspberry", + "banana" => "cranberry", + ], + [ + "cherry" => "lemon", + "mango" => "cranberry", + ] + ], + ]; + + $formattedData = $formatterData + ->setData($data) + ->getData() + ; + + $this->assertEquals($expectedData,$formattedData); + } + }