public function getStatusMessage() { $statusMessage = ''; $this->checkForDbUpdate($this->extension->getExtensionKey(), $this->extension->getExtensionDir() . 'ext_tables.sql'); if ($this->dbUpdateNeeded) { $statusMessage .= '<p>Database has to be updated!</p>'; $typeInfo = array('add' => 'Add fields', 'change' => 'Change fields', 'create_table' => 'Create tables'); $statusMessage .= '<div id="dbUpdateStatementsWrapper"><table>'; foreach ($this->updateStatements as $type => $statements) { $statusMessage .= '<tr><td></td><td style="text-align:left;padding-left:15px">' . $typeInfo[$type] . ':</td></tr>'; foreach ($statements as $key => $statement) { if ($type == 'add') { $statusMessage .= '<tr><td><input type="checkbox" name="dbUpdateStatements[]" value="' . $key . '" checked="checked" /></td><td style="text-align:left;padding-left:15px">' . $statement . '</td></tr>'; } elseif ($type === 'change') { $statusMessage .= '<tr><td><input type="checkbox" name="dbUpdateStatements[]" value="' . $key . '" checked="checked" /></td><td style="text-align:left;padding-left:15px">' . $statement . '</td></tr>'; $statusMessage .= '<tr><td></td><td style="text-align:left;padding-left:15px">Current value: ' . $this->updateStatements['change_currentValue'][$key] . '</td></tr>'; } elseif ($type === 'create_table') { $statusMessage .= '<tr><td><input type="checkbox" name="dbUpdateStatements[]" value="' . $key . '" checked="checked" /></td><td style="text-align:left;padding-left:15px;">' . nl2br($statement) . '</td></tr>'; } } } $statusMessage .= '</table></div>'; } if (!\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded($this->extension->getExtensionKey())) { $statusMessage .= '<p>Your Extension is not installed yet.</p>'; } return $statusMessage; }
protected function tearDown() { if (!empty($this->extension) && $this->extension->getExtensionKey() != null) { GeneralUtility::rmdir($this->extension->getExtensionDir(), true); } parent::tearDown(); }
/** * @test */ public function changeVendorNameResultsInUpdatedTagsInModelClass() { $this->fixtureExtension->setOriginalVendorName('FIXTURE'); $this->fixtureExtension->setVendorName('VENDOR'); $modelClassFile = $this->roundTripService->getDomainModelClassFile($this->fixtureExtension->getDomainObjectByName('Main')); $modelClassObject = $modelClassFile->getFirstClass(); $properties = $modelClassObject->getProperties(); self::assertEquals('\\VENDOR\\TestExtension\\Domain\\Model\\Child1', $properties['child1']->getTagValue('var')); self::assertEquals('\\TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage<\\VENDOR\\TestExtension\\Domain\\Model\\Child2>', $properties['children2']->getTagValue('var')); self::assertEquals('\\TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage<\\VENDOR\\TestExtension\\Domain\\Model\\Child4>', $properties['children4']->getTagValue('var')); }
/** * @param \EBT\ExtensionBuilder\Domain\Model\Extension $extension */ public function saveExtensionConfiguration(\EBT\ExtensionBuilder\Domain\Model\Extension $extension) { $extensionBuildConfiguration = $this->configurationManager->getConfigurationFromModeler(); $extensionBuildConfiguration['log'] = array('last_modified' => date('Y-m-d h:i'), 'extension_builder_version' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getExtensionVersion('extension_builder'), 'be_user' => $GLOBALS['BE_USER']->user['realName'] . ' (' . $GLOBALS['BE_USER']->user['uid'] . ')'); $encodeOptions = 0; // option JSON_PRETTY_PRINT is available since PHP 5.4.0 if (defined('JSON_PRETTY_PRINT')) { $encodeOptions |= JSON_PRETTY_PRINT; } \TYPO3\CMS\Core\Utility\GeneralUtility::writeFile($extension->getExtensionDir() . \EBT\ExtensionBuilder\Configuration\ConfigurationManager::EXTENSION_BUILDER_SETTINGS_FILE, json_encode($extensionBuildConfiguration, $encodeOptions)); }
/** * This method generates the repository class object, * which is passed to the template * it keeps all methods and properties including * user modified method bodies and comments * needed to create a repository class file * * @param \EBT\ExtensionBuilder\Domain\Model\DomainObject $domainObject * @param \EBT\ExtensionBuilder\Domain\Model\File $existingClassFileObject * * @return \EBT\ExtensionBuilder\Domain\Model\File */ public function generateRepositoryClassFileObject($domainObject, $repositoryTemplateClassPath, $existingClassFileObject = null) { $this->classObject = null; $className = $domainObject->getName() . 'Repository'; $this->templateFileObject = $this->parserService->parseFile($repositoryTemplateClassPath); $this->templateClassObject = $this->templateFileObject->getFirstClass(); if ($existingClassFileObject) { $this->classFileObject = $existingClassFileObject; $this->classObject = $existingClassFileObject->getFirstClass(); if ($this->classFileObject->getNamespace() === false) { $nameSpace = new \EBT\ExtensionBuilder\Domain\Model\NamespaceObject('dummy'); $this->classFileObject->addNamespace($nameSpace); } } if ($this->classObject == null) { $this->classFileObject = clone $this->templateFileObject; $this->classObject = clone $this->templateClassObject; $this->classObject->resetAll(); $this->classObject->setName($className); $this->classObject->setDescription('The repository for ' . Inflector::pluralize($domainObject->getName())); if (isset($this->settings['Repository']['parentClass'])) { $parentClass = $this->settings['Repository']['parentClass']; } else { $parentClass = '\\TYPO3\\CMS\\Extbase\\Persistence\\Repository'; } $this->classObject->setParentClassName($parentClass); } if ($domainObject->getSorting() && is_null($this->classObject->getProperty('defaultOrderings'))) { $defaultOrderings = $this->templateClassObject->getProperty('defaultOrderings'); $this->classObject->addProperty($defaultOrderings); } $this->classFileObject->getNamespace()->setName($this->extension->getNamespaceName() . '\\Domain\\Repository')->setClasses(array($this->classObject)); return $this->classFileObject; }
protected function removeInitialModelClassFile($modelName) { if (@file_exists($this->extension->getExtensionDir() . $this->modelClassDir . $modelName . '.php')) { unlink($this->extension->getExtensionDir() . $this->modelClassDir . $modelName . '.php'); } $this->assertFalse(file_exists($this->extension->getExtensionDir() . $this->modelClassDir . $modelName . '.php'), 'Dummy files could not be removed:' . $this->extension->getExtensionDir() . $this->modelClassDir . $modelName . '.php'); }
/** * * @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; }
/** * @test */ public function testAddPerson() { self::assertEquals($this->extension->getPersons(), array(), 'Extensions Persons are not empty.'); $this->extension->addPerson($this->persons[0]); $this->extension->addPerson($this->persons[1]); $this->extension->addPerson($this->persons[2]); self::assertEquals(count($this->extension->getPersons()), 3, 'To many Persons in Extension.'); $persons = $this->extension->getPersons(); self::assertEquals($persons[0]->getName(), '0', 'Wrong ordering of Persons in Extension.'); self::assertEquals($persons[1]->getName(), '1', 'Wrong ordering of Persons in Extension.'); self::assertEquals($persons[2]->getName(), '2', 'Wrong ordering of Persons in Extension.'); }
/** * generate a docComment for class files. Add a license haeder if none found * @param \EBT\ExtensionBuilder\Domain\Model\ClassObject\ClassObject $classObject * * @return void; */ protected function addLicenseHeader($classObject) { $comments = $classObject->getComments(); $needsLicenseHeader = true; foreach ($comments as $comment) { if (strpos($comment, 'GNU General Public License') !== false) { $needsLicenseHeader = false; } } if ($needsLicenseHeader) { $licenseHeader = $this->renderTemplate('Partials/Classes/licenseHeader.phpt', array('persons' => $this->extension->getPersons())); $classObject->addComment($licenseHeader); } }
/** * generate a docComment for class files. Add a license header if none found * @param \EBT\ExtensionBuilder\Domain\Model\ClassObject\ClassObject $classObject * * @return void; */ protected function addLicenseHeader($classObject) { $comments = $classObject->getComments(); $needsLicenseHeader = true; foreach ($comments as $comment) { if (strpos($comment, 'license information') !== false) { $needsLicenseHeader = false; } } $extensionSettings = $this->extension->getSettings(); if ($needsLicenseHeader && empty($extensionSettings['skipDocComment'])) { $licenseHeader = $this->renderTemplate('Partials/Classes/licenseHeader.phpt', array('extension' => $this->extension)); $classObject->addComment($licenseHeader); } }
/** * @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; }
public function tearDown() { if (!empty($this->extension) && $this->extension->getExtensionKey() != NULL) { GeneralUtility::rmdir($this->extension->getExtensionDir(), TRUE); } }
/** * @return string */ public function getRecordType() { $recordType = 'Tx_' . $this->extension->getExtensionName() . '_' . $this->getName(); return $recordType; }
/** * @param \EBT\ExtensionBuilder\Domain\Model\Extension $extension * @param string $codeTemplateRootPath * @return void */ public function createInitialSettingsFile($extension, $codeTemplateRootPath) { GeneralUtility::mkdir_deep($extension->getExtensionDir(), self::SETTINGS_DIR); $settings = file_get_contents($codeTemplateRootPath . 'Configuration/ExtensionBuilder/settings.yamlt'); $settings = str_replace('{extension.extensionKey}', $extension->getExtensionKey(), $settings); $settings = str_replace('{f:format.date(format:\'Y-m-d\\TH:i:s\\Z\',date:\'now\')}', date('Y-m-d\\TH:i:s\\Z'), $settings); GeneralUtility::writeFile($extension->getExtensionDir() . self::SETTINGS_DIR . 'settings.yaml', $settings); }
/** * @return string */ public function getRecordType() { $recordType = 'Tx_' . GeneralUtility::underscoredToUpperCamelCase($this->extension->getExtensionKey()) . '_' . $this->getName(); return $recordType; }
/** * * @param \EBT\ExtensionBuilder\Domain\Model\Extension $extension * @param string $backupDir * * @return void */ static function backupExtension(Model\Extension $extension, $backupDir) { if (empty($backupDir)) { throw new \Exception('Please define a backup directory in extension configuration!'); } elseif (!GeneralUtility::validPathStr($backupDir)) { throw new \Exception('Backup directory is not a valid path: ' . $backupDir); } elseif (GeneralUtility::isAbsPath($backupDir)) { if (!GeneralUtility::isAllowedAbsPath($backupDir)) { throw new \Exception('Backup directory is not an allowed absolute path: ' . $backupDir); } } else { $backupDir = PATH_site . $backupDir; } if (strrpos($backupDir, '/') < strlen($backupDir) - 1) { $backupDir .= '/'; } if (!is_dir($backupDir)) { throw new \Exception('Backup directory does not exist: ' . $backupDir); } elseif (!is_writable($backupDir)) { throw new \Exception('Backup directory is not writable: ' . $backupDir); } $backupDir .= $extension->getExtensionKey(); // create a subdirectory for this extension if (!is_dir($backupDir)) { GeneralUtility::mkdir($backupDir); } if (strrpos($backupDir, '/') < strlen($backupDir) - 1) { $backupDir .= '/'; } $backupDir .= date('Y-m-d-') . time(); if (!is_dir($backupDir)) { GeneralUtility::mkdir($backupDir); } $extensionDir = substr($extension->getExtensionDir(), 0, strlen($extension->getExtensionDir()) - 1); try { self::recurse_copy($extensionDir, $backupDir); } catch (\Exception $e) { throw new \Exception('Code generation aborted:' . $e->getMessage()); } self::log('Backup created in ' . $backupDir); }
/** * @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); } } }
/** * @param \EBT\ExtensionBuilder\Domain\Model\Extension $extension * @param array $propertyConfiguration * @return void */ protected function setExtensionProperties(&$extension, $propertyConfiguration) { // name $extension->setName(trim($propertyConfiguration['name'])); // description $extension->setDescription($propertyConfiguration['description']); // extensionKey $extension->setExtensionKey(trim($propertyConfiguration['extensionKey'])); // vendorName $extension->setVendorName(trim($propertyConfiguration['vendorName'])); if (!empty($propertyConfiguration['emConf']['sourceLanguage'])) { $extension->setSourceLanguage($propertyConfiguration['emConf']['sourceLanguage']); } if ($propertyConfiguration['emConf']['disableVersioning']) { $extension->setSupportVersioning(false); } if ($propertyConfiguration['emConf']['disableLocalization']) { $extension->setSupportLocalization(false); } if (!empty($propertyConfiguration['emConf']['skipGenerateDocumentationTemplate'])) { $extension->setGenerateDocumentationTemplate(false); } // various extension properties $extension->setVersion($propertyConfiguration['emConf']['version']); if (!empty($propertyConfiguration['emConf']['dependsOn'])) { $dependencies = array(); $lines = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(LF, $propertyConfiguration['emConf']['dependsOn']); foreach ($lines as $line) { if (strpos($line, '=>')) { list($extensionKey, $version) = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode('=>', $line); $dependencies[$extensionKey] = $version; } } $extension->setDependencies($dependencies); } if (!empty($propertyConfiguration['emConf']['targetVersion'])) { $extension->setTargetVersion(floatval($propertyConfiguration['emConf']['targetVersion'])); } if (!empty($propertyConfiguration['emConf']['custom_category'])) { $category = $propertyConfiguration['emConf']['custom_category']; } else { $category = $propertyConfiguration['emConf']['category']; } $extension->setCategory($category); // state $state = 0; switch ($propertyConfiguration['emConf']['state']) { case 'alpha': $state = \EBT\ExtensionBuilder\Domain\Model\Extension::STATE_ALPHA; break; case 'beta': $state = \EBT\ExtensionBuilder\Domain\Model\Extension::STATE_BETA; break; case 'stable': $state = \EBT\ExtensionBuilder\Domain\Model\Extension::STATE_STABLE; break; case 'experimental': $state = \EBT\ExtensionBuilder\Domain\Model\Extension::STATE_EXPERIMENTAL; break; case 'test': $state = \EBT\ExtensionBuilder\Domain\Model\Extension::STATE_TEST; break; } $extension->setState($state); if (!empty($propertyConfiguration['originalExtensionKey'])) { // handle renaming of extensions // original extensionKey $extension->setOriginalExtensionKey($propertyConfiguration['originalExtensionKey']); \TYPO3\CMS\Core\Utility\GeneralUtility::devLog('Extension setOriginalExtensionKey:' . $extension->getOriginalExtensionKey(), 'extbase', 0, $propertyConfiguration); } if (!empty($propertyConfiguration['originalExtensionKey']) && $extension->getOriginalExtensionKey() != $extension->getExtensionKey()) { $settings = $this->configurationManager->getExtensionSettings($extension->getOriginalExtensionKey()); // if an extension was renamed, a new extension dir is created and we // have to copy the old settings file to the new extension dir copy($this->configurationManager->getSettingsFile($extension->getOriginalExtensionKey()), $this->configurationManager->getSettingsFile($extension->getExtensionKey())); } else { $settings = $this->configurationManager->getExtensionSettings($extension->getExtensionKey()); } if (!empty($settings)) { $extension->setSettings($settings); \TYPO3\CMS\Core\Utility\GeneralUtility::devLog('Extension settings:' . $extension->getExtensionKey(), 'extbase', 0, $extension->getSettings()); } }
/** * This method generates the repository class object, * which is passed to the template * it keeps all methods and properties including * user modified method bodies and comments * needed to create a repository class file * * @param \EBT\ExtensionBuilder\Domain\Model\DomainObject $domainObject * @param boolean $mergeWithExistingClass * * @return \EBT\ExtensionBuilder\Domain\Model\File */ public function generateRepositoryClassFileObject($domainObject, $repositoryTemplateClassPath, $mergeWithExistingClass) { $this->classObject = NULL; $className = $domainObject->getName() . 'Repository'; $this->templateFileObject = $this->parserService->parseFile($repositoryTemplateClassPath); $this->templateClassObject = $this->templateFileObject->getFirstClass(); if ($mergeWithExistingClass) { try { $this->classFileObject = $this->roundTripService->getRepositoryClassFile($domainObject); if ($this->classFileObject instanceof Model\File) { $this->classObject = $this->classFileObject->getFirstClass(); } } catch (\Exception $e) { \TYPO3\CMS\Core\Utility\GeneralUtility::devLog('Class ' . $className . ' could not be imported: ' . $e->getMessage(), 'extension_builder'); } } if ($this->classObject == NULL) { $this->classFileObject = clone $this->templateFileObject; $this->classObject = clone $this->templateClassObject; $this->classObject->resetAll(); $this->classObject->setName($className); $this->classObject->setNamespaceName($this->extension->getNamespaceName() . '\\Domain\\Repository'); $this->classObject->setDescription('The repository for ' . Inflector::pluralize($domainObject->getName())); if (isset($this->settings['Repository']['parentClass'])) { $parentClass = $this->settings['Repository']['parentClass']; } else { $parentClass = '\\TYPO3\\CMS\\Extbase\\Persistence\\Repository'; } $this->classObject->setParentClassName($parentClass); } $this->classFileObject->getNamespace()->setName($this->extension->getNamespaceName() . '\\Domain\\Repository')->setClasses(array($this->classObject)); return $this->classFileObject; }