From 5b0018edcae483e460514559346c86334229b681 Mon Sep 17 00:00:00 2001 From: Marc Neuhaus Date: Thu, 1 Feb 2018 15:56:44 +0100 Subject: [PATCH] DimensionMapping --- .../FourallportalCommandController.php | 1 + Classes/Domain/Model/Dimension.php | 88 ++++++++++++++ Classes/Domain/Model/DimensionMapping.php | 100 ++++++++++++++++ Classes/Domain/Model/Server.php | 25 ++++ .../DynamicModel/DynamicModelGenerator.php | 28 +++-- Classes/Mapping/AbstractMapping.php | 110 +++++++++++++++--- ...x_fourallportal_domain_model_dimension.php | 54 +++++++++ ...llportal_domain_model_dimensionmapping.php | 57 +++++++++ .../tx_fourallportal_domain_model_server.php | 24 +++- ...lportal_domain_model_dimension_mapping.xlf | 26 +++++ Resources/Private/Language/locallang_db.xlf | 30 ++++- ext_tables.sql | 45 +++++++ 12 files changed, 554 insertions(+), 34 deletions(-) create mode 100644 Classes/Domain/Model/Dimension.php create mode 100644 Classes/Domain/Model/DimensionMapping.php create mode 100644 Configuration/TCA/tx_fourallportal_domain_model_dimension.php create mode 100644 Configuration/TCA/tx_fourallportal_domain_model_dimensionmapping.php create mode 100644 Resources/Private/Language/locallang_csh_tx_fourallportal_domain_model_dimension_mapping.xlf diff --git a/Classes/Command/FourallportalCommandController.php b/Classes/Command/FourallportalCommandController.php index 1ec6471..6e53a59 100644 --- a/Classes/Command/FourallportalCommandController.php +++ b/Classes/Command/FourallportalCommandController.php @@ -820,6 +820,7 @@ public function processEvent($event, $updateEventId = true) } catch(\Exception $exception) { $event->setStatus('failed'); $event->setMessage($exception->getMessage() . ' (code: ' . $exception->getCode() . ')' . $exception->getFile() . ':' . $exception->getLine()); + $this->response->appendContent($exception->getMessage() . ' (code: ' . $exception->getCode() . ')' . $exception->getFile() . ':' . $exception->getLine() . PHP_EOL); if ($updateEventId) { $event->getModule()->setLastEventId(max($event->getEventId(), $event->getModule()->getLastEventId())); } diff --git a/Classes/Domain/Model/Dimension.php b/Classes/Domain/Model/Dimension.php new file mode 100644 index 0000000..6323fb6 --- /dev/null +++ b/Classes/Domain/Model/Dimension.php @@ -0,0 +1,88 @@ +, MIA3 GmbH & Co. KG + * + ***/ +use Crossmedia\Fourallportal\Domain\Repository\ModuleRepository; +use Crossmedia\Fourallportal\Mapping\MappingInterface; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Object\ObjectManager; + +/** + * Module + */ +class Dimension extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity +{ + /** + * @var string + */ + protected $name = ''; + + /** + * @var string + */ + protected $value = ''; + + /** + * server + * + * @var \Crossmedia\Fourallportal\Domain\Model\DimensionMapping + */ + protected $mapping = null; + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * @param string $name + */ + public function setName($name) + { + $this->name = $name; + } + + /** + * @return string + */ + public function getValue() + { + return $this->value; + } + + /** + * @param string $value + */ + public function setValue($value) + { + $this->value = $value; + } + + /** + * @return DimensionMapping + */ + public function getMapping() + { + return $this->mapping; + } + + /** + * @param DimensionMapping $mapping + */ + public function setMapping($mapping) + { + $this->mapping = $mapping; + } +} diff --git a/Classes/Domain/Model/DimensionMapping.php b/Classes/Domain/Model/DimensionMapping.php new file mode 100644 index 0000000..83b5cbe --- /dev/null +++ b/Classes/Domain/Model/DimensionMapping.php @@ -0,0 +1,100 @@ +, MIA3 GmbH & Co. KG + * + ***/ +use Crossmedia\Fourallportal\Domain\Repository\ModuleRepository; +use Crossmedia\Fourallportal\Mapping\MappingInterface; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Object\ObjectManager; + +/** + * Module + */ +class DimensionMapping extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity +{ + /** + * @var int + */ + protected $language = ''; + + /** + * server + * + * @var \Crossmedia\Fourallportal\Domain\Model\Server + */ + protected $server = null; + + /** + * modules + * + * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\Crossmedia\Fourallportal\Domain\Model\Dimension> + * @cascade remove + */ + protected $dimensions = null; + + /** + * @return int + */ + public function getLanguage() + { + return $this->language; + } + + /** + * @param int $language + */ + public function setLanguage($language) + { + $this->language = $language; + } + + /** + * @return Server + */ + public function getServer() + { + return $this->server; + } + + /** + * @param Server $server + */ + public function setServer($server) + { + $this->server = $server; + } + + /** + * @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage + */ + public function getDimensions() + { + return $this->dimensions; + } + + /** + * @param \TYPO3\CMS\Extbase\Persistence\ObjectStorage $dimensions + */ + public function setDimensions($dimensions) + { + $this->dimensions = $dimensions; + } + + public function matches($dimensions) { + foreach ($this->dimensions as $dimension) { + if ($dimensions[$dimension->getName()] != $dimension->getValue()) { + return false; + } + } + return true; + } +} diff --git a/Classes/Domain/Model/Server.php b/Classes/Domain/Model/Server.php index c745023..a8e49fd 100644 --- a/Classes/Domain/Model/Server.php +++ b/Classes/Domain/Model/Server.php @@ -64,6 +64,14 @@ class Server extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity */ protected $modules = null; + /** + * modules + * + * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\Crossmedia\Fourallportal\Domain\Model\DimensionMapping> + * @cascade remove + */ + protected $dimensionMappings = null; + /** * __construct */ @@ -283,4 +291,21 @@ public function getClient() $client->login(); return $client; } + + /** + * @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage + */ + public function getDimensionMappings() + { + return $this->dimensionMappings; + } + + /** + * @param \TYPO3\CMS\Extbase\Persistence\ObjectStorage $dimensionMappings + */ + public function setDimensionMappings($dimensionMappings) + { + $this->dimensionMappings = $dimensionMappings; + } + } diff --git a/Classes/DynamicModel/DynamicModelGenerator.php b/Classes/DynamicModel/DynamicModelGenerator.php index 80cd2a2..33e4966 100644 --- a/Classes/DynamicModel/DynamicModelGenerator.php +++ b/Classes/DynamicModel/DynamicModelGenerator.php @@ -320,6 +320,25 @@ public function generateAbstractModelForModule(Module $module, $strict = false, // PHP/SQL representations, either errors will be raised or the remaining safe properties // will be written - depending on the context of the TYPO3 site (Development = errors thrown) $propertyConfiguration = $this->getPropertyConfigurationFromConnector($module); + + $propertyConfiguration['remoteId'] = [ + "column"=> "remote_id", + "type"=> "string", + "schema" => "varchar(255) default ''", + "config" => [ + "type"=> "input", + "size" => 255 + ] + ]; + $propertyConfiguration['l10nParent'] = [ + "column"=> 'l10n_parent', + "type"=> '\\' . $entityClassName, + "schema" => "INT(11) DEFAULT '0' NOT NULL", + "config" => [ + "type"=> "passthrough" + ] + ]; + $sourceCode = $this->generateCachedClassFile($abstractModelClassName, AbstractEntity::class, $propertyConfiguration, $strict); } return $sourceCode; @@ -1019,15 +1038,6 @@ public function set%s(%s%s) $functionsAndProperties = ''; $objectStorageInitializations = ''; - $propertyConfiguration['remoteId'] = [ - "column"=> "remote_id", - "type"=> "string", - "schema" => "varchar(255) default ''", - "config" => [ - "type"=> "input", - "size" => 255 - ] - ]; foreach ($propertyConfiguration as $propertyName => $property) { $variableType = $property['type']; diff --git a/Classes/Mapping/AbstractMapping.php b/Classes/Mapping/AbstractMapping.php index 8e03d10..ce880c7 100644 --- a/Classes/Mapping/AbstractMapping.php +++ b/Classes/Mapping/AbstractMapping.php @@ -1,6 +1,7 @@ getEntityClassName(); - $object = new $class(); - ObjectAccess::setProperty($object, 'remoteId', $objectId); - } - $object->setPid($event->getModule()->getStoragePid()); - if ($object->getUid()) { - $repository->update($object); - } else { - $repository->add($object); - GeneralUtility::makeInstance(ObjectManager::class)->get(PersistenceManager::class)->persistAll(); - } - $this->mapPropertiesFromDataToObject($data, $object, $event->getModule()); - $repository->update($object); + $this->importObjectWithDimensionMappings($data, $object, $event); break; default: throw new \RuntimeException('Unknown event type: ' . $event->getEventType()); @@ -80,8 +69,9 @@ public function import(array $data, Event $event) * @param array $data * @param AbstractEntity $object * @param Module $module + * @param DimensionMapping|null $dimensionMapping */ - protected function mapPropertiesFromDataToObject(array $data, $object, Module $module) + protected function mapPropertiesFromDataToObject(array $data, $object, Module $module, DimensionMapping $dimensionMapping = null) { if (!$data['result']) { return; @@ -89,6 +79,18 @@ protected function mapPropertiesFromDataToObject(array $data, $object, Module $m $map = MappingRegister::resolvePropertyMapForMapper(static::class); $properties = $data['result'][0]['properties']; $properties = $this->addMissingNullProperties($properties, $module); + if ($dimensionMapping !== null) { + foreach ($properties as $propertyName => $value) { + if (is_array($value) && isset($value[0]['dimensions'])) { + foreach ($value as $dimensionValue) { + if ($dimensionMapping->matches($dimensionValue['dimensions'])) { + $properties[$propertyName] = $dimensionValue['value']; + } + } + } + } + } + $properties = $this->addMissingNullProperties($properties, $module); foreach ($properties as $importedName => $propertyValue) { if (($map[$importedName] ?? null) === false) { continue; @@ -379,7 +381,7 @@ protected function addMissingNullProperties($properties, Module $module) default: break; } - dump($field['name'] . ':' . $field['type'], $value); +// dump($field['name'] . ':' . $field['type'], $value); } $properties[$field['name']] = $value; } @@ -387,4 +389,80 @@ protected function addMissingNullProperties($properties, Module $module) return $properties; } + + /** + * @param Event $event + * @param null $existingRow + * @return mixed + */ + protected function createObject(Event $event, $existingRow = null) + { + $class = $this->getEntityClassName(); + $object = new $class(); + ObjectAccess::setProperty($object, 'remoteId', $event->getObjectId()); + ObjectAccess::setProperty($object, 'pid', $event->getModule()->getStoragePid()); + if (isset($existingRow['uid'])) { + ObjectAccess::setProperty($object, 'uid', $existingRow['uid']); + } + $this->getObjectRepository()->add($object); + GeneralUtility::makeInstance(ObjectManager::class)->get(PersistenceManager::class)->persistAll(); + return $object; + } + + public function getTableName() { + + $dataMapper = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper::class); + return $dataMapper->getDataMap($this->getEntityClassName())->getTableName(); + } + + /** + * @param array $data + * @param $object + * @param Event $event + * @throws \Exception + */ + protected function importObjectWithDimensionMappings(array $data, $object, Event $event) + { + $dimensionMappings = $event->getModule()->getServer()->getDimensionMappings(); + + $sysLanguageUids = []; + $defaultDimensionMapping = null; + $translationDimensionMappings = []; + foreach ($dimensionMappings as $dimensionMapping) { + if ($dimensionMapping->getLanguage() === 0) { + $defaultDimensionMapping = $dimensionMapping; + } else { + $sysLanguageUids[] = $dimensionMapping->getLanguage(); + $translationDimensionMappings[] = $dimensionMapping; + } + } + + if ($defaultDimensionMapping === null) { + throw new \Exception('No DimensionMapping found for Default Language!'); + } + + if (!$object) { + $object = $this->createObject($event); + } + + $this->mapPropertiesFromDataToObject($data, $object, $event->getModule(), $defaultDimensionMapping); + $this->getObjectRepository()->update($object); + + $dataMapper = GeneralUtility::makeInstance(DataMapper::class); + foreach ($translationDimensionMappings as $translationDimensionMapping) { + $existingRow = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('*', $this->getTableName(), 'sys_language_uid = ' . $translationDimensionMapping->getLanguage() . ' AND l10n_parent = ' . $object->getUid()); + if (is_array($existingRow)) { + $translationObjects = $dataMapper->map($this->getEntityClassName(), [$existingRow]); + $translationObject = current($translationObjects); + } else { + $translationObject = $this->createObject($event, $existingRow); + } + $translationObject->_setProperty('_languageUid', $translationDimensionMapping->getLanguage()); + $translationObject->setL10nParent($object); + $this->mapPropertiesFromDataToObject($data, $translationObject, $event->getModule(), $translationDimensionMapping); + $this->getObjectRepository()->update($translationObject); + } + + $GLOBALS['TYPO3_DB']->exec_DELETEquery($this->getTableName(), 'sys_language_uid NOT IN (' . implode(', ', $sysLanguageUids) . ') AND l10n_parent = ' . $object->getUid()); + } } diff --git a/Configuration/TCA/tx_fourallportal_domain_model_dimension.php b/Configuration/TCA/tx_fourallportal_domain_model_dimension.php new file mode 100644 index 0000000..ad5e3f3 --- /dev/null +++ b/Configuration/TCA/tx_fourallportal_domain_model_dimension.php @@ -0,0 +1,54 @@ + [ + 'title' => 'LLL:EXT:fourallportal/Resources/Private/Language/locallang_db.xlf:tx_fourallportal_domain_model_dimension', + 'label' => 'name', + 'tstamp' => 'tstamp', + 'crdate' => 'crdate', + 'cruser_id' => 'cruser_id', + //'delete' => 'deleted', + 'rootLevel' => 1, + 'enablecolumns' => [ + //'disabled' => 'hidden', + //'starttime' => 'starttime', + //'endtime' => 'endtime', + ], + 'iconfile' => 'EXT:fourallportal/Resources/Public/Icons/tx_fourallportal_domain_model_dimension.gif' + ], + 'interface' => [ + 'showRecordFieldList' => ';;1, dimension', + ], + 'types' => [ + '1' => ['showitem' => ';;1, dimension'], + ], + 'palettes' => [ + '1' => [ + 'showitem' => 'name, value', + ], + ], + 'columns' => [ + 'name' => [ + 'exclude' => true, + 'label' => 'LLL:EXT:fourallportal/Resources/Private/Language/locallang_db.xlf:tx_fourallportal_domain_model_dimension.name', + 'config' => [ + 'type' => 'input', + 'size' => 300, + 'eval' => 'trim' + ], + ], + 'value' => [ + 'exclude' => true, + 'label' => 'LLL:EXT:fourallportal/Resources/Private/Language/locallang_db.xlf:tx_fourallportal_domain_model_dimension.value', + 'config' => [ + 'type' => 'input', + 'size' => 300, + 'eval' => 'trim' + ], + ], + 'dimension_mapping' => [ + 'config' => [ + 'type' => 'passthrough', + ], + ], + ], +]; diff --git a/Configuration/TCA/tx_fourallportal_domain_model_dimensionmapping.php b/Configuration/TCA/tx_fourallportal_domain_model_dimensionmapping.php new file mode 100644 index 0000000..bcd5da5 --- /dev/null +++ b/Configuration/TCA/tx_fourallportal_domain_model_dimensionmapping.php @@ -0,0 +1,57 @@ + [ + 'title' => 'LLL:EXT:fourallportal/Resources/Private/Language/locallang_db.xlf:tx_fourallportal_domain_model_dimensionmapping', + 'label' => 'language', + 'tstamp' => 'tstamp', + 'crdate' => 'crdate', + 'cruser_id' => 'cruser_id', + //'delete' => 'deleted', + 'rootLevel' => 1, + 'enablecolumns' => [ + //'disabled' => 'hidden', + //'starttime' => 'starttime', + //'endtime' => 'endtime', + ], + 'iconfile' => 'EXT:fourallportal/Resources/Public/Icons/tx_fourallportal_domain_model_dimensionmapping.gif' + ], + 'interface' => [ + 'showRecordFieldList' => 'language, dimensions, server', + ], + 'types' => [ + '1' => ['showitem' => 'language, dimensions, server'], + ], + 'columns' => [ + 'language' => [ + 'exclude' => true, + 'label' => 'LLL:EXT:fourallportal/Resources/Private/Language/locallang_db.xlf:tx_fourallportal_domain_model_dimensionmapping.language', + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectSingle', + 'special' => 'languages', + 'default' => 0, + ] + ], + 'server' => [ + 'config' => [ + 'type' => 'passthrough', + ], + ], + 'dimensions' => [ + 'exclude' => true, + 'label' => 'LLL:EXT:fourallportal/Resources/Private/Language/locallang_db.xlf:tx_fourallportal_domain_model_dimensionmapping.dimensions', + 'config' => [ + 'type' => 'inline', + 'foreign_table' => 'tx_fourallportal_domain_model_dimension', + 'foreign_field' => 'dimension_mapping', + 'minitems' => 1, + 'maxitems' => 9999, + 'appearance' => [ + 'collapseAll' => 1, + 'levelLinksPosition' => 'top' + ], + ], + + ], + ], +]; diff --git a/Configuration/TCA/tx_fourallportal_domain_model_server.php b/Configuration/TCA/tx_fourallportal_domain_model_server.php index 66937b5..2140915 100644 --- a/Configuration/TCA/tx_fourallportal_domain_model_server.php +++ b/Configuration/TCA/tx_fourallportal_domain_model_server.php @@ -15,10 +15,10 @@ 'iconfile' => 'EXT:fourallportal/Resources/Public/Icons/tx_fourallportal_domain_model_server.gif' ], 'interface' => [ - 'showRecordFieldList' => 'domain, customer_name, username, password, active, modules', + 'showRecordFieldList' => 'domain, customer_name, username, password, active, modules, dimension_mappings', ], 'types' => [ - '1' => ['showitem' => 'active, domain, customer_name, username, password, modules'], + '1' => ['showitem' => 'active, domain, customer_name, username, password, modules, dimension_mappings'], ], 'columns' => [ 'domain' => [ @@ -79,7 +79,25 @@ 'foreign_field' => 'server', 'maxitems' => 9999, 'appearance' => [ - 'collapseAll' => 0, + 'collapseAll' => 1, + 'levelLinksPosition' => 'top', + 'showSynchronizationLink' => 1, + 'showPossibleLocalizationRecords' => 1, + 'showAllLocalizationLink' => 1 + ], + ], + + ], + 'dimension_mappings' => [ + 'exclude' => true, + 'label' => 'LLL:EXT:fourallportal/Resources/Private/Language/locallang_db.xlf:tx_fourallportal_domain_model_server.dimensionmappings', + 'config' => [ + 'type' => 'inline', + 'foreign_table' => 'tx_fourallportal_domain_model_dimensionmapping', + 'foreign_field' => 'server', + 'maxitems' => 9999, + 'appearance' => [ + 'collapseAll' => 1, 'levelLinksPosition' => 'top', 'showSynchronizationLink' => 1, 'showPossibleLocalizationRecords' => 1, diff --git a/Resources/Private/Language/locallang_csh_tx_fourallportal_domain_model_dimension_mapping.xlf b/Resources/Private/Language/locallang_csh_tx_fourallportal_domain_model_dimension_mapping.xlf new file mode 100644 index 0000000..82e5bd0 --- /dev/null +++ b/Resources/Private/Language/locallang_csh_tx_fourallportal_domain_model_dimension_mapping.xlf @@ -0,0 +1,26 @@ + + + +
+ + + domain + + + customerName + + + username + + + password + + + active + + + modules + + + + \ No newline at end of file diff --git a/Resources/Private/Language/locallang_db.xlf b/Resources/Private/Language/locallang_db.xlf index 970ec7b..ca3e292 100644 --- a/Resources/Private/Language/locallang_db.xlf +++ b/Resources/Private/Language/locallang_db.xlf @@ -21,9 +21,12 @@ Active - - Modules - + + Modules + + + Dimension Mappings + Module @@ -132,9 +135,24 @@ PHP data type this value gets cast to - - Parent object - + + Parent object + + + Language + + + Dimensions + + + Name + + + Value + + + Server + diff --git a/ext_tables.sql b/ext_tables.sql index 894f13f..b0169e8 100644 --- a/ext_tables.sql +++ b/ext_tables.sql @@ -12,6 +12,7 @@ CREATE TABLE tx_fourallportal_domain_model_server ( password varchar(255) DEFAULT '' NOT NULL, active smallint(5) unsigned DEFAULT '0' NOT NULL, modules int(11) unsigned DEFAULT '0' NOT NULL, + dimension_mappings int(11) unsigned DEFAULT '0' NOT NULL, tstamp int(11) unsigned DEFAULT '0' NOT NULL, crdate int(11) unsigned DEFAULT '0' NOT NULL, @@ -134,3 +135,47 @@ CREATE TABLE sys_file ( remote_id varchar(255) DEFAULT '' NOT NULL, KEY remote_id (remote_id) ); + +# +# Table structure for table 'tx_fourallportal_domain_model_dimension_mapping' +# +CREATE TABLE tx_fourallportal_domain_model_dimensionmapping ( + + uid int(11) NOT NULL auto_increment, + pid int(11) DEFAULT '0' NOT NULL, + + server int(11) unsigned DEFAULT '0' NOT NULL, + dimensions int(11) unsigned DEFAULT '0' NOT NULL, + + language varchar(255) DEFAULT '' NOT NULL, + + tstamp int(11) unsigned DEFAULT '0' NOT NULL, + crdate int(11) unsigned DEFAULT '0' NOT NULL, + cruser_id int(11) unsigned DEFAULT '0' NOT NULL, + + PRIMARY KEY (uid), + KEY parent (pid), + +); + +# +# Table structure for table 'tx_fourallportal_domain_model_dimension' +# +CREATE TABLE tx_fourallportal_domain_model_dimension ( + + uid int(11) NOT NULL auto_increment, + pid int(11) DEFAULT '0' NOT NULL, + + dimension_mapping int(11) unsigned DEFAULT '0' NOT NULL, + + name varchar(255) DEFAULT '' NOT NULL, + value varchar(255) DEFAULT '' NOT NULL, + + tstamp int(11) unsigned DEFAULT '0' NOT NULL, + crdate int(11) unsigned DEFAULT '0' NOT NULL, + cruser_id int(11) unsigned DEFAULT '0' NOT NULL, + + PRIMARY KEY (uid), + KEY parent (pid), + +);