/** * @throws \Exception */ protected function copyStaticFiles() { try { $this->upload_copy_move(ExtensionManagementUtility::extPath('extension_builder') . 'Resources/Private/Icons/ext_icon.gif', $this->extensionDirectory . 'ext_icon.gif'); } catch (\Exception $e) { throw new \Exception('Could not copy ext_icon.gif, error: ' . $e->getMessage()); } try { $this->mkdir_deep($this->extensionDirectory, 'Resources/Public'); $publicResourcesDirectory = $this->extensionDirectory . 'Resources/Public/'; $this->mkdir_deep($publicResourcesDirectory, 'Icons'); $this->iconsDirectory = $publicResourcesDirectory . 'Icons/'; $needsRelationIcon = false; foreach ($this->extension->getDomainObjects() as $domainObject) { if ($domainObject->hasRelations()) { $needsRelationIcon = true; } } if ($needsRelationIcon) { $this->upload_copy_move(ExtensionManagementUtility::extPath('extension_builder') . 'Resources/Private/Icons/relation.gif', $this->iconsDirectory . 'relation.gif'); } } catch (\Exception $e) { throw new \Exception('Could not create public resources folder, error: ' . $e->getMessage()); } }
/** * * @param \EBT\ExtensionBuilder\Domain\Model\Extension $extension * @param mixed $domainObject * @return boolean TRUE or FALSE */ public function render($extension, $domainObject) { $expectedDomainObject = $domainObject; $results = array(); foreach ($extension->getDomainObjects() as $domainObject) { if (!count($domainObject->getProperties())) { continue; } foreach ($domainObject->getProperties() as $property) { if ($property instanceof \EBT\ExtensionBuilder\Domain\Model\DomainObject\Relation\ZeroToManyRelation && $property->getForeignClassName() === $expectedDomainObject->getFullQualifiedClassName()) { $results[] = $property; } } } return $results; }
/** * @param \EBT\ExtensionBuilder\Domain\Model\Extension $extension * @param string $type * @throws \InvalidArgumentException */ public function prepareLabelArray($extension, $type = 'locallang') { $labelArray = array(); foreach ($extension->getDomainObjects() as $domainObject) { /* @var \EBT\ExtensionBuilder\Domain\Model\DomainObject $domainObject */ $labelArray[$domainObject->getLabelNamespace()] = $this->inflector->humanize($domainObject->getName()); foreach ($domainObject->getProperties() as $property) { $labelArray[$property->getLabelNamespace()] = $this->inflector->humanize($property->getName()); } if ($type == 'locallang_db') { $tableToMapTo = $domainObject->getMapToTable(); if (!empty($tableToMapTo)) { $labelArray[$tableToMapTo . '.tx_extbase_type.' . $domainObject->getRecordType()] = $extension->getName() . ' ' . $domainObject->getName(); } if (count($domainObject->getChildObjects()) > 0) { $labelArray[$extension->getShortExtensionKey() . '.tx_extbase_type'] = 'Record Type'; $labelArray[$extension->getShortExtensionKey() . '.tx_extbase_type.0'] = 'Default'; $labelArray[$domainObject->getLabelNamespace() . '.tx_extbase_type.' . $domainObject->getRecordType()] = $extension->getName() . ' ' . $domainObject->getName(); } } } return $labelArray; }
/** * @author Sebastian Michaelsen <*****@*****.**> * @param \EBT\ExtensionBuilder\Domain\Model\Extension $extension * @return void * @throws ExtensionException */ private function validateDomainObjects($extension) { $actionCounter = 0; foreach ($extension->getDomainObjects() as $domainObject) { $actionCounter .= count($domainObject->getActions()); // Check if domainObject name is given if (!$domainObject->getName()) { $this->validationResult['errors'][] = new ExtensionException('A Domain Object has no name', self::ERROR_DOMAINOBJECT_NO_NAME); } /** * Character test * Allowed characters are: a-z (lowercase), A-Z (uppercase) and 0-9 */ if (!preg_match('/^[a-zA-Z0-9]*$/', $domainObject->getName())) { $this->validationResult['errors'][] = new ExtensionException('Illegal domain object name "' . $domainObject->getName() . '". Please use UpperCamelCase, no spaces or underscores.', self::ERROR_DOMAINOBJECT_ILLEGAL_CHARACTER); } $objectName = $domainObject->getName(); $firstChar = $objectName[0]; if (strtolower($firstChar) == $firstChar) { $this->validationResult['errors'][] = new ExtensionException('Illegal first character of domain object name "' . $domainObject->getName() . '". Please use UpperCamelCase.', self::ERROR_DOMAINOBJECT_LOWER_FIRST_CHARACTER); } if (\EBT\ExtensionBuilder\Service\ValidationService::isReservedExtbaseWord($objectName)) { $this->validationResult['errors'][] = new ExtensionException('Domain object name "' . $domainObject->getName() . '" may not be used in extbase.', self::ERROR_PROPERTY_RESERVED_WORD); } $this->validateProperties($domainObject); $this->validateDomainObjectActions($domainObject); $this->validateMapping($domainObject); } if ($actionCounter < 1) { if (count($extension->getBackendModules()) > 0) { $this->validationResult['warnings'][] = new ExtensionException('Potential misconfiguration: No actions configured!' . LF . 'This will result in a missing default action in your backend module', self::ERROR_ACTION_MISCONFIGURATION); } if (count($extension->getPlugins()) > 0) { $this->validationResult['warnings'][] = new ExtensionException('Potential misconfiguration: No actions configured!' . LF . 'This will result in a missing default action in your plugin', self::ERROR_ACTION_MISCONFIGURATION); } } }
/** * parse existing tca and set appropriate properties * * @param \EBT\ExtensionBuilder\Domain\Model\Extension $extension * @return void */ public static function prepareExtensionForRoundtrip(&$extension) { foreach ($extension->getDomainObjects() as $domainObject) { $existingTca = self::getTcaForDomainObject($domainObject, $extension); if ($existingTca) { foreach ($domainObject->getAnyToManyRelationProperties() as $relationProperty) { if (isset($existingTca['columns'][$relationProperty->getName()]['config']['MM'])) { self::log('Relation table for Model ' . $domainObject->getName() . ' relation ' . $relationProperty->getName(), 0, $existingTca['columns'][$relationProperty->getName()]['config']); $relationProperty->setRelationTableName($existingTca['columns'][$relationProperty->getName()]['config']['MM']); } } } if (file_exists($extension->getExtensionDir() . 'Configuration/TCA/' . $domainObject->getName() . '.php')) { $extensionConfigurationJson = \EBT\ExtensionBuilder\Configuration\ConfigurationManager::getExtensionBuilderJson($extension->getExtensionKey()); if (floatval($extensionConfigurationJson['log']['extension_builder_version']) <= 6.2) { self::moveAdditionalTcaToOverrideFile($domainObject); } } } }
/** * generate all domainObject related * files like PHP class files, templates etc. * * @throws \Exception */ protected function generateDomainObjectRelatedFiles() { if (count($this->extension->getDomainObjects()) > 0) { $this->classBuilder->initialize($this, $this->extension, $this->roundTripEnabled); // Generate Domain Model try { $domainModelDirectory = 'Classes/Domain/Model/'; $this->mkdir_deep($this->extensionDirectory, $domainModelDirectory); $domainRepositoryDirectory = 'Classes/Domain/Repository/'; $this->mkdir_deep($this->extensionDirectory, $domainRepositoryDirectory); $this->mkdir_deep($this->extensionDirectory, 'Tests/Unit/Domain/Model'); $domainModelTestsDirectory = $this->extensionDirectory . 'Tests/Unit/Domain/Model/'; $this->mkdir_deep($this->extensionDirectory, 'Tests/Unit/Controller'); $crudEnabledControllerTestsDirectory = $this->extensionDirectory . 'Tests/Unit/Controller/'; foreach ($this->extension->getDomainObjects() as $domainObject) { /** * @var \EBT\ExtensionBuilder\Domain\Model\DomainObject $domainObject */ $destinationFile = $domainModelDirectory . $domainObject->getName() . '.php'; if ($this->fileShouldBeMerged($destinationFile)) { $mergeWithExistingClass = TRUE; } else { $mergeWithExistingClass = FALSE; } $fileContents = $this->generateDomainObjectCode($domainObject, $mergeWithExistingClass); $this->writeFile($this->extensionDirectory . $destinationFile, $fileContents); \TYPO3\CMS\Core\Utility\GeneralUtility::devlog('Generated ' . $domainObject->getName() . '.php', 'extension_builder', 0); $this->extension->setMD5Hash($this->extensionDirectory . $destinationFile); if ($domainObject->isAggregateRoot()) { $iconFileName = 'aggregate_root.gif'; } elseif ($domainObject->isEntity()) { $iconFileName = 'entity.gif'; } else { $iconFileName = 'value_object.gif'; } $this->upload_copy_move(ExtensionManagementUtility::extPath('extension_builder') . 'Resources/Private/Icons/' . $iconFileName, $this->iconsDirectory . $domainObject->getDatabaseTableName() . '.gif'); if ($domainObject->isAggregateRoot()) { $destinationFile = $domainRepositoryDirectory . $domainObject->getName() . 'Repository.php'; if ($this->fileShouldBeMerged($destinationFile)) { $mergeWithExistingClass = TRUE; } else { $mergeWithExistingClass = FALSE; } $fileContents = $this->generateDomainRepositoryCode($domainObject, $mergeWithExistingClass); $this->writeFile($this->extensionDirectory . $destinationFile, $fileContents); \TYPO3\CMS\Core\Utility\GeneralUtility::devlog('Generated ' . $domainObject->getName() . 'Repository.php', 'extension_builder', 0); $this->extension->setMD5Hash($this->extensionDirectory . $destinationFile); } // Generate basic UnitTests $fileContents = $this->generateDomainModelTests($domainObject); $this->writeFile($domainModelTestsDirectory . $domainObject->getName() . 'Test.php', $fileContents); } } catch (\Exception $e) { throw new \Exception('Could not generate domain model, error: ' . $e->getMessage()); } // Generate Action Controller try { $this->mkdir_deep($this->extensionDirectory, 'Classes/Controller'); $controllerDirectory = 'Classes/Controller/'; foreach ($this->extension->getDomainObjectsForWhichAControllerShouldBeBuilt() as $domainObject) { $destinationFile = $controllerDirectory . $domainObject->getName() . 'Controller.php'; if ($this->fileShouldBeMerged($destinationFile)) { $mergeWithExistingClass = TRUE; } else { $mergeWithExistingClass = FALSE; } $fileContents = $this->generateActionControllerCode($domainObject, $mergeWithExistingClass); $this->writeFile($this->extensionDirectory . $destinationFile, $fileContents); \TYPO3\CMS\Core\Utility\GeneralUtility::devlog('Generated ' . $domainObject->getName() . 'Controller.php', 'extension_builder', 0); $this->extension->setMD5Hash($this->extensionDirectory . $destinationFile); // Generate basic UnitTests $fileContents = $this->generateControllerTests($domainObject->getName() . 'Controller', $domainObject); $this->writeFile($crudEnabledControllerTestsDirectory . $domainObject->getName() . 'ControllerTest.php', $fileContents); } } catch (\Exception $e) { throw new \Exception('Could not generate action controller, error: ' . $e->getMessage()); } // Generate Domain Templates try { if ($this->extension->getPlugins()) { $this->generateTemplateFiles(); } if ($this->extension->getBackendModules()) { $this->generateTemplateFiles('Backend/'); } } catch (\Exception $e) { throw new \Exception('Could not generate domain templates, error: ' . $e->getMessage()); } try { $settings = $this->extension->getSettings(); } catch (\Exception $e) { throw new \Exception('Could not generate ext_autoload.php, error: ' . $e->getMessage()); } } else { \TYPO3\CMS\Core\Utility\GeneralUtility::devlog('No domainObjects in this extension', 'extension_builder', 3, (array) $this->extension); } }
/** * parse existing tca and set appropriate properties * * @param \EBT\ExtensionBuilder\Domain\Model\Extension $extension * @return void */ public static function prepareExtensionForRoundtrip(&$extension) { foreach ($extension->getDomainObjects() as $domainObject) { $existingTca = self::getTcaForDomainObject($domainObject, $extension); if ($existingTca) { foreach ($domainObject->getAnyToManyRelationProperties() as $relationProperty) { if (isset($existingTca['columns'][$relationProperty->getName()]['config']['MM'])) { self::log('Relation table for Model ' . $domainObject->getName() . ' relation ' . $relationProperty->getName(), 0, $existingTca['columns'][$relationProperty->getName()]['config']); $relationProperty->setRelationTableName($existingTca['columns'][$relationProperty->getName()]['config']['MM']); } } } } }