/// <summary> /// Generates an icon in the "new content element" wizard to quickly select the plugin /// </summary> /// <param name="plugin"></param> /// <param name="titleLanguageConstant">The name of the language constant in locallang_be that contains the title of the plugin.</param> private void GenerateWizard( Typo3ExtensionGenerator.Model.Plugin.Plugin plugin, string titleLanguageConstant ) { string pluginSignature = NameHelper.GetPluginSignature( Subject, plugin ); string wizIconScriptFilename = string.Format( "Resources/Private/Php/class.{0}_wizicon.php", pluginSignature ); // Class registration const string registerWizardIconTemplate = "if( TYPO3_MODE == 'BE' ) {{" + " $TBE_MODULES_EXT['xMOD_db_new_content_el']['addElClasses']['{_pluginSignature}_wizicon'] =" + " t3lib_extMgm::extPath('{_extensionKey}') . '{_wizIconFilename}';" + "}}"; string registerWizardIcon = registerWizardIconTemplate.FormatSmart( new {_pluginSignature = pluginSignature, _extensionKey = Subject.Key, _wizIconFilename = wizIconScriptFilename} ); WriteVirtual( "ext_tables.php", registerWizardIcon ); // Class generation string plusWizDescriptionConstant = String.Format( "{0}_plus_wiz_description", plugin.Name.ToLower() ); WriteVirtual( "Resources/Private/Language/locallang_be.xml", string.Format( "<label index=\"{0}\">Description for {1}</label>", plusWizDescriptionConstant, plugin.Title ) ); // Flush wizard icon string wizIconFilename = string.Format( "ce_wiz_{0}.gif", plugin.Name.ToLower() ); string wizIconFullFilename = "Resources/Public/Icons/" + wizIconFilename; ResourceHelper.FlushIcon( "wiz_icon.gif", this, wizIconFullFilename ); const string wizIconClassTemplate = "class {_pluginSignature}_wizicon {{" + " public function proc($wizardItems) {{" + " $locallang = $this->includeLocalLang();" + "" + " $wizardItems['plugins_tx_{_pluginSignature}'] = array(" + " 'icon' => t3lib_extMgm::extRelPath('{_extensionKey}') . '{_wizIconFullFilename}'," + " 'title' => $GLOBALS['LANG']->getLLL('{_languageConstant}', $locallang)," + " 'description' => $GLOBALS['LANG']->getLLL('{_plusWizDescriptionConstant}', $locallang)," + " 'params' => '&defVals[tt_content][CType]=list&defVals[tt_content][list_type]={_pluginSignature}'" + " );" + "" + " return $wizardItems;" + " }}" + " protected function includeLocalLang() {{" + " $file = t3lib_extMgm::extPath('{_extensionKey}') . 'Resources/Private/Language/locallang_be.xml';" + "" + " return {_readLLXMLfile};" + " }}" + "}}"; string wizIconClass = wizIconClassTemplate.FormatSmart( new { _pluginSignature = pluginSignature, _extensionKey = Subject.Key, _languageConstant = titleLanguageConstant, _plusWizDescriptionConstant = plusWizDescriptionConstant, _wizIconFullFilename = wizIconFullFilename, _readLLXMLfile = String.Format( Deprecated.Get( "t3lib_div::readLLXMLfile({0},{1})", GeneratorContext.TargetVersion ), "$file", "$GLOBALS['LANG']->lang" ) } ); WritePhpFile( wizIconScriptFilename, wizIconClass, DateTime.UtcNow ); }
/// <summary> /// Constructs a ConfigurationFileGenerator. /// </summary> /// <param name="context">The generator context.</param> /// <param name="extension">The extension that should be generated.</param> /// <param name="configuration">The model for the configuration that should be generated.</param> public ConfigurationFileGenerator( Context context, Extension extension, Typo3ExtensionGenerator.Model.Configuration.Configuration configuration ) : base(context, extension) { Configuration = configuration; }
private void GenerateFluidTemplate( Typo3ExtensionGenerator.Model.Plugin.Plugin plugin ) { // The default frontend layout const string defaultLayoutTemplate = "<f:render section=\"main\" />"; const string layoutFilename = "Resources/Private/Layouts/Default.html"; Log.InfoFormat( "Generating default Fluid layout '{0}'...", layoutFilename ); WriteFile( layoutFilename, String.Format( defaultLayoutTemplate, Subject.Key ), DateTime.UtcNow ); // A generic partial that will render all the fields in a model //WriteFile( "Resources/Private/Partials/Models/Download.html", string.Empty ); const string defaultTemplateTemplate = "<f:layout name=\"Default\" />" + "<f:section name=\"main\">" + " <f:flashMessages class=\"flashMessages\" />" + " <f:if condition=\"{{debug}}\">" + " <f:debug>{{debug}}</f:debug>" + " </f:if>" + " <h3>You need to create your own Fluid templates and point TYPO3 to them via TypoScript.</h3>" + " <p>This is the default template for the action '{_actionTitle}'({_actionName}) of plugin '{_pluginTitle}'({_pluginName}).</p>" + "</f:section>"; // Write Fluid templates for each action foreach( Action action in plugin.Actions ) { // The template that is used for the given action of the given controller string templateFilename = string.Format( "Resources/Private/Templates/{0}/{1}.html", NameHelper.UpperCamelCase( plugin.Name ), NameHelper.UpperCamelCase( action.Name ) ); Log.InfoFormat( "Generating Fluid template '{0}'...", templateFilename ); string template = defaultTemplateTemplate.FormatSmart( new { _actionName = action.Name, _actionTitle = action.Title, _pluginName = plugin.Name, _pluginTitle = plugin.Title } ); WriteFile( templateFilename, template, DateTime.UtcNow ); } }
/// <summary> /// Writes the default TypoScript constants and settings files for the extension. /// </summary> /// <param name="plugin"> </param> private void GenerateTypoScript( Typo3ExtensionGenerator.Model.Plugin.Plugin plugin ) { const string constantsTemplate = "plugin.{pluginName} {{\n" + "}}"; const string setupTemplate = "plugin.{pluginName} {{\n" + " settings {{\n" + " example {{\n" + " // Place your own TS here\n" + " }}\n" + " }}\n" + "}}"; // Just to be safe, we also go all lower-case here. var dataObject = new { pluginName = "tx_" + NameHelper.GetPluginSignature( Subject, plugin ), extensionKey = Subject.Key, pluginFolder = plugin.Name, pluginTitle = plugin.Title }; Log.Info( "Generating TypoScript constants..." ); string constants = constantsTemplate.FormatSmart( dataObject ); WriteFile( string.Format( "Configuration/TypoScript/{0}/constants.txt", plugin.Name ), constants, DateTime.UtcNow ); Log.Info( "Generating TypoScript setup..." ); string setup = setupTemplate.FormatSmart( dataObject ); WriteFile( string.Format( "Configuration/TypoScript/{0}/setup.txt", plugin.Name ), setup, DateTime.UtcNow ); const string typoScriptRegisterTemplate = "t3lib_extMgm::addStaticFile('{extensionKey}', 'Configuration/TypoScript/{pluginFolder}', '{pluginTitle}');"; WriteVirtual( "ext_tables.php", typoScriptRegisterTemplate.FormatSmart( dataObject ) ); }
/// <summary> /// Generates the FlexForm XML for the given plugin. /// </summary> /// <param name="plugin"></param> private void GenerateFlexForm( Typo3ExtensionGenerator.Model.Plugin.Plugin plugin ) { Log.InfoFormat( "Generating FlexForm for '{0}'...", plugin.Name ); // Collect FlexForms from interfaces StringBuilder settings = new StringBuilder(); StringBuilder actions = new StringBuilder(); // TODO: Should possibly render ALL fields in the model const string membersTemplate = "\n<settings.{0}><TCEforms>{1}</TCEforms></settings.{0}>"; foreach( Interface @interface in plugin.Interfaces ) { string members = InterfaceGenerator.Generate( this, Subject, @interface, SimpleContainer.Format.XML ); string setting = string.Format( membersTemplate, @interface.Target, members ); settings.Append( setting ); } // Generate actions const string controllerActionTemplate = "{_controllerName}->{_actionName}"; const string actionTemplate = " <numIndex index=\"{_actIndex}\">" + " <numIndex index=\"0\">{_title}</numIndex>" + " <numIndex index=\"1\">{_controllerName}->{_actionName};{_nonDefault}</numIndex>" + " </numIndex>"; // We'll generate an entry for each action in the controller. // The combination will always list the given action as the first (default) action; all other actions will be allowed in that combination as well. int actionIndex = 0; foreach( Action action in plugin.Actions ) { string nonDefault = plugin.Actions.Where( nonDefaultAction => nonDefaultAction != action ).Aggregate( string.Empty, ( current, nonDefaultAction ) => current + ( controllerActionTemplate.FormatSmart( new { _controllerName = NameHelper.UpperCamelCase( plugin.Name ), _actionName = nonDefaultAction.Name } ) + ";" ) ); if( !string.IsNullOrEmpty( nonDefault ) ) { nonDefault = nonDefault.Substring( 0, nonDefault.Length - 1 ); } var dataObject = new { _title = action.Title, _controllerName = NameHelper.UpperCamelCase( plugin.Name ), _actionName = action.Name, _actIndex = actionIndex, _nonDefault = nonDefault.ToString() }; string actionString = actionTemplate.FormatSmart( dataObject ); actions.Append( actionString ); ++actionIndex; } string allActions = actions.ToString(); string allSettings = settings.ToString(); const string actionsTemplate = "<switchableControllerActions><TCEforms><label>Action</label><config><type>select</type><items>{0}</items></config></TCEforms></switchableControllerActions>"; const string flexFormTemplate = "<T3DataStructure>" + " <meta>" + " <langDisable>1</langDisable>" + " </meta>" + " " + " <sheets>" + " <sDEF>" + " <ROOT>" + " <TCEforms>" + " <sheetTitle>General</sheetTitle>" + " </TCEforms>" + " <type>array</type>" + " <el>" + "{actions}" + "{settings}" + " </el>" + " </ROOT>" + " </sDEF>" + " </sheets>" + "</T3DataStructure>"; var dataObjectFlexForm = new {settings = allSettings, actions = string.Format( actionsTemplate, allActions )}; string flexFormsXml = flexFormTemplate.FormatSmart( dataObjectFlexForm ); // Write final result to file WriteVirtual( string.Format( "Configuration/FlexForms/flexform_{0}.xml", plugin.Name.ToLower() ), flexFormsXml ); }
/// <summary> /// Generates the ExtBase controller for the given plugin. /// </summary> /// <param name="plugin"></param> private void GenerateController( Typo3ExtensionGenerator.Model.Plugin.Plugin plugin ) { ClassProxyGenerator classGenerator = new ClassProxyGenerator( GeneratorContext, Subject ); classGenerator.GenerateClassProxy( plugin, new ControllerNamingStrategy(), "Classes/Controller/", true ); }
/// <summary> /// Write all defined language fields to the locallang_db.xml /// </summary> /// <param name="configuration"></param> private void FlushLanguageFields( Typo3ExtensionGenerator.Model.Configuration.Configuration configuration ) { string languageConstant = NameHelper.GetAbsoluteModelName( Subject, configuration.Model ); WriteVirtual( "Resources/Private/Language/locallang_db.xml", string.Format( "<label index=\"{0}\">{1}</label>", languageConstant, configuration.Title ) ); }
public static void Resolve( Fragment parsedFragment, Typo3ExtensionGenerator.Model.Configuration.Interface.Interface @interface, string displayType ) { if( Keywords.ConfigurationDirectives.InterfaceDirectives.Representations.FileReference == displayType ) { SpecializedDisplayType specializedDisplayType = new SpecializedDisplayType { Name = Keywords.ConfigurationDirectives.InterfaceDirectives.Representations.RecordGroup, SourceFragment = parsedFragment }; specializedDisplayType.Set( "internal_type", "file_reference" ); specializedDisplayType.Set( "allowed", "*" ); specializedDisplayType.Set( "disallowed", "php" ); specializedDisplayType.Set( "size", 5 ); specializedDisplayType.Set( "maxitems", 99 ); // If this field requires anything, it should have at least 1 item. if( @interface.Settings.Any( s => s.Key == Keywords.Requirement ) ) { specializedDisplayType.Set( "minitems", 1 ); } else { specializedDisplayType.Set( "minitems", 0 ); } @interface.DisplayType = specializedDisplayType; } else if( Keywords.ConfigurationDirectives.InterfaceDirectives.Representations.RecordGroup == displayType ) { RecordGroupDisplayType recordGroupDisplayType = new RecordGroupDisplayType { Name = Keywords.ConfigurationDirectives.InterfaceDirectives.Representations.RecordGroup, SourceFragment = parsedFragment }; // Show records next to select box recordGroupDisplayType.ShowThumbnails = true; // Increase list length recordGroupDisplayType.Lines = 10; // Increase list width recordGroupDisplayType.SelectedListStyle = "width:400px"; // Don't allow duplicates recordGroupDisplayType.AllowDuplicates = false; // Set item limit recordGroupDisplayType.MaxItems = 99; // If this field requires anything, it should have at least 1 item. if( @interface.Settings.Any( s => s.Key == Keywords.Requirement ) ) { recordGroupDisplayType.MinItems = 1; } else { recordGroupDisplayType.MinItems = 0; } // The model type for the suggest wizard is resolved during generation later. recordGroupDisplayType.Set( "wizards.RTE.type", "suggest" ); @interface.DisplayType = recordGroupDisplayType; } else if( Keywords.ConfigurationDirectives.InterfaceDirectives.Representations.RichTextArea == displayType ) { SpecializedDisplayType specializedDisplayType = new SpecializedDisplayType() { Name = Keywords.ConfigurationDirectives.InterfaceDirectives.Representations.TextArea, SourceFragment = parsedFragment }; specializedDisplayType.Set( "wizards.RTE.icon", "wizard_rte2.gif" ); specializedDisplayType.Set( "wizards.RTE.notNewRecords", 1 ); specializedDisplayType.Set( "wizards.RTE.RTEonly", 1 ); specializedDisplayType.Set( "wizards.RTE.script", "wizard_rte.php" ); specializedDisplayType.Set( "wizards.RTE.title", "LLL:EXT:cms/locallang_ttc.xml:bodytext.W.RTE" ); specializedDisplayType.Set( "wizards.RTE.type", "script" ); @interface.DisplayType = specializedDisplayType; // Add a new property to the interface itself, to enable rich text editing. @interface.Set( "defaultExtras", "richtext[]" ); } else { // Could not determine proper display type, use user supplied intput @interface.DisplayType = new DisplayType {Name = @interface.DisplayTypeTarget}; } }
/// <summary> /// Generates the interface. /// </summary> /// <param name="parent">The generator that uses this <see cref="InterfaceGenerator"/>.</param> /// <param name="extension">The extension that is being worked on.</param> /// <param name="subject">The model for the interface defintion.</param> /// <param name="format">The format of the interface.</param> /// <returns></returns> /// <exception cref="GeneratorException">No display type given in interface.</exception> public static string Generate( AbstractGenerator parent, Extension extension, Typo3ExtensionGenerator.Model.Configuration.Interface.Interface subject, SimpleContainer.Format format ) { string propertyTemplate = ( format == SimpleContainer.Format.PhpArray ) ? SimpleContainer.PropertyTemplatePHP : SimpleContainer.PropertyTemplateXML; StringBuilder interfaceDefinition = new StringBuilder(); // exclude interfaceDefinition.Append( string.Format( propertyTemplate, "exclude", subject.Exclude ? "1" : "0" ) ); // label string labelLanguageConstant = string.Format( "{0}.{1}", NameHelper.GetAbsoluteModelName( extension, subject.ParentModel ), NameHelper.LowerUnderscoredCase( subject.Target ) ); if( format == SimpleContainer.Format.PhpArray ) { interfaceDefinition.Append( string.Format( propertyTemplate, "label", string.Format( "'LLL:EXT:{0}/Resources/Private/Language/locallang_db.xml:{1}'", extension.Key, labelLanguageConstant ) ) ); } else { interfaceDefinition.Append( string.Format( propertyTemplate, "label", string.Format( "LLL:EXT:{0}/Resources/Private/Language/locallang_db.xml:{1}", extension.Key, labelLanguageConstant ) ) ); } parent.WriteVirtual( "Resources/Private/Language/locallang_db.xml", string.Format( "<label index=\"{0}\">{1}</label>", labelLanguageConstant, subject.Title ) ); // config string configuration = string.Empty; // Add foreign_table if( subject.ParentModel.ForeignModels.ContainsKey( subject.Target ) ) { DataModel foreignModel = subject.ParentModel.ForeignModels[ subject.Target ]; string typename = ( String.IsNullOrEmpty( foreignModel.InternalType ) ) ? NameHelper.GetAbsoluteModelName( extension, foreignModel ) : foreignModel.InternalType; subject.DisplayType.ParentModel = foreignModel; if( format == SimpleContainer.Format.PhpArray ) { configuration += String.Format( propertyTemplate, "foreign_table", "'" + typename + "'" ); configuration += String.Format( propertyTemplate, "foreign_table_where", "'AND " + typename + ".sys_language_uid=0'" ); configuration += String.Format( propertyTemplate, "allowed", "'" + typename + "'" ); } else { configuration += String.Format( propertyTemplate, "foreign_table", typename ); configuration += String.Format( propertyTemplate, "foreign_table_where", "AND " + typename + ".sys_language_uid=0" ); configuration += String.Format( propertyTemplate, "allowed", typename ); } } if( null != subject.DisplayType ) { // Add any additional properties to the configuration configuration += DisplayTypeGenerator.GeneratePropertyArray( extension, subject.DisplayType, format ); if( format == SimpleContainer.Format.PhpArray ) { configuration += String.Format( propertyTemplate, "type", "'" + subject.DisplayType.Name + "'" ); } else { configuration += String.Format( propertyTemplate, "type", subject.DisplayType.Name ); } } else { throw new GeneratorException( string.Format( "No display type given in interface for '{0}'!", subject.Target ), subject.SourceFragment.SourceDocument ); } if( null != subject.DefaultValue ) { if( format == SimpleContainer.Format.PhpArray ) { configuration += String.Format( propertyTemplate, "default", "'" + subject.DefaultValue + "'" ); } else { configuration += String.Format( propertyTemplate, "default", subject.DefaultValue ); } } // Trim trailing comma configuration = configuration.TrimEnd( new[] {','} ); // Add the 'config' array to the interface if( format == SimpleContainer.Format.PhpArray ) { interfaceDefinition.Append( string.Format( propertyTemplate, "config", "array(" + configuration + ")" ) ); } else { interfaceDefinition.Append( string.Format( propertyTemplate, "config", configuration ) ); } // Add any additional parameters set in the interface interfaceDefinition.Append( subject.GeneratePropertyArray( SimpleContainer.Format.PhpArray) ); string finalInterface = interfaceDefinition.ToString().TrimEnd( new[] {','} ); return finalInterface; }