public static string GetInterfaces( Extension extension, DataModel model ) { var dataObject = new { _foreignTable = NameHelper.GetAbsoluteModelName( extension, model ) }; return Interfaces.FormatSmart( dataObject ); }
/// <summary> /// Resolves the models of an extension from a ParsedPartial. /// </summary> /// <param name="parsedFragment">The partially parsed extension.</param> /// <returns>The models of the extension</returns> public static List<DataModel> Resolve( Fragment parsedFragment ) { IEnumerable<Fragment> modelPartials = parsedFragment.Fragments.Where( p => p.Keyword == Keywords.ExtensionDirectives.DeclareModel ); if( !modelPartials.Any() ) return null; List<DataModel> dataModels = new List<DataModel>(); foreach( Fragment modelPartial in modelPartials ) { DataModel dataModel = new DataModel {Name = modelPartial.Parameters, SourceFragment = modelPartial}; dataModels.Add( dataModel ); if( modelPartial.Fragments.Any() ) { foreach( Fragment dataMember in modelPartial.Fragments ) { if( dataMember.Keyword == Keywords.InternalType ) { dataModel.InternalType = dataMember.Parameters; } else { dataModel.Members.Add( new DataModel.DataModelMember {Name = dataMember.Keyword, Value = dataMember.Parameters} ); } } } } // Resolve any foreign key references ForeignKeyResolver.Resolve( dataModels ); return dataModels; }
private string GenerateSqlMembers( DataModel dataModel ) { StringBuilder dataMembers = new StringBuilder(); StringBuilder keys = new StringBuilder(); foreach( DataModel.DataModelMember member in dataModel.Members ) { // Is this a template request or a normal data member? if( Keywords.DataModelTemplate == member.Name ) { switch( member.Value ) { case Keywords.DataModelTemplates.T3ManagedFields: dataMembers.Append( T3ManagedFields.Content + ",\n" ); keys.Append( T3ManagedFields.Keys + ",\n" ); break; case Keywords.DataModelTemplates.T3CommonFields: dataMembers.Append( T3CommonFields.Content + ",\n" ); break; case Keywords.DataModelTemplates.T3VersioningFields: dataMembers.Append( T3VersioningFields.Content + ",\n" ); keys.Append( T3VersioningFields.Keys + ",\n" ); break; case Keywords.DataModelTemplates.T3TranslationFields: dataMembers.Append( T3TranslationFields.Content + ",\n" ); keys.Append( T3TranslationFields.Keys + ",\n" ); break; case Keywords.DataModelTemplates.T3Sortable: dataMembers.Append( T3Sortable.Content + ",\n" ); break; default: throw new GeneratorException( string.Format( "Data model template '{0}' is unknown", member.Value ), dataModel.SourceFragment.SourceDocument ); } } else { if( dataModel.ForeignModels.ContainsKey( member.Value ) ) { // For a foreign key, we just insert the default uint dataMembers.Append( string.Format( "{0} {1},\n", NameHelper.GetSqlColumnName( Subject, member.Value ), TypeTranslator.ToSQL( Keywords.Types.UnsignedInt, dataModel.SourceFragment.SourceDocument ) ) ); } else if( TypeTranslator.CanTranslate( member.Name ) ) { // If it is a POD type, just translate it dataMembers.Append( string.Format( "{0} {1},\n", NameHelper.GetSqlColumnName( Subject, member.Value ), TypeTranslator.ToSQL( member.Name, dataModel.SourceFragment.SourceDocument ) ) ); } else { throw new GeneratorException( string.Format( "Data model field type '{0}' in model '{1}' is unknown.", member.Name, dataModel.Name ), dataModel.SourceFragment.SourceDocument ); } } } String dataMembersAndKeys = string.Format( "{0},\n{1}", (dataMembers.Length >0) ? dataMembers.ToString().Substring( 0, dataMembers.Length - 2 ) : string.Empty, ( keys.Length > 0 ) ? keys.ToString().Substring( 0, keys.Length - 2 ) : string.Empty ); return dataMembersAndKeys; }
/// <summary> /// Generates an ExtBase repository for the given data model. /// This allows ExtBase controllers to retrieve data records from the database. /// </summary> /// <param name="model"></param> /// <returns></returns> /// <exception cref="GeneratorException">Implementation for repository does not exist.</exception> private string GenerateRepositoryFile( DataModel model ) { const string repositoryImplementationTemplate = "private $implementation;\n" + "private function getImplementation() {{\n" + " if( null == $this->implementation ) {{\n" + " $this->implementation = new {implClassname}($this);\n" + " }}\n" + " return $this->implementation;\n" + "}}\n"; string implementationClassname = NameHelper.GetExtbaseDomainModelRepositoryImplementationClassName( Subject, model ); string implementationFilename = NameHelper.GetExtbaseDomainModelRepositoryImplementationFileName( Subject, model ); string baseClassname = "Tx_Extbase_Persistence_Repository"; // Did the user define additional information for our repository bool isExternallyImplemented = false; Repository repositoryDefinition = Subject.Repositories.SingleOrDefault( r => r.TargetModelName == model.Name ); // If the repository type is an internal type, no need to generate anything... if( null != repositoryDefinition && !string.IsNullOrEmpty( repositoryDefinition.InternalType ) ) { // ...unless BOTH an internal type and an implementation are given if( !string.IsNullOrEmpty( repositoryDefinition.Implementation ) ) { // This would indicate that the internal type is to be extended by the implementation // A common example of this is the extension of the Tx_Extbase_Domain_Repository_FrontendUserRepository baseClassname = repositoryDefinition.InternalType; } else { return string.Empty; } } if( null != repositoryDefinition && !string.IsNullOrEmpty( repositoryDefinition.Implementation ) ) { if( !File.Exists( repositoryDefinition.Implementation ) ) { throw new GeneratorException( string.Format( "Implementation '{0}' for repository for '{1}' does not exist.", repositoryDefinition.Implementation, model.Name ), repositoryDefinition.SourceFragment.SourceDocument ); } isExternallyImplemented = true; Log.InfoFormat( "Merging implementation '{0}'...", repositoryDefinition.Implementation ); string repositoryImplementationContent = File.ReadAllText( repositoryDefinition.Implementation ); DateTime lastWriteTimeUtc = new FileInfo( repositoryDefinition.Implementation ).LastWriteTimeUtc; if( !Regex.IsMatch( repositoryImplementationContent, String.Format( "class {0} ?({{|extends|implements)", implementationClassname ) ) ) { Log.WarnFormat( "The class name of your implementation for repository for model '{1}' MUST be '{0}'!", implementationClassname, repositoryDefinition.TargetModelName ); } WriteFile( "Classes/Domain/Repository/" + implementationFilename, repositoryImplementationContent, lastWriteTimeUtc ); } // Generate methods as described in definition StringBuilder actions = new StringBuilder(); if( null != repositoryDefinition ) { const string actionTemplate = "public function {0}({1}) {{ return $this->getImplementation()->{0}({1}); }}\n"; foreach( Action action in repositoryDefinition.Methods ) { // Prefix each parameter with a $ and join them together with , in between. string parameters = action.Requirements.Aggregate( string.Empty, ( current, requirement ) => current + ( "$" + requirement + ( ( requirement != action.Requirements.Last() ) ? "," : string.Empty ) ) ); actions.Append( String.Format( actionTemplate, action.Name, parameters ) ); } } string repositoryImplementation = repositoryImplementationTemplate.FormatSmart( new { implClassname = implementationClassname, className = NameHelper.GetExtbaseDomainModelRepositoryClassName( Subject, model ) } ); // Generate final class const string template = "class {_className} extends {_baseClass} {{\n" + "{_repositoryMethods}\n" + "}}\n" + "{_requireImplementation}"; return template.FormatSmart( new { _className = NameHelper.GetExtbaseDomainModelRepositoryClassName( Subject, model ), _baseClass = baseClassname, _repositoryMethods = repositoryImplementation + actions, _requireImplementation = ( isExternallyImplemented ) ? string.Format( "require_once('{0}');\n", implementationFilename ) : string.Empty } ); }
/// <summary> /// Generate the ExtBase model file for the given data model. /// </summary> /// <param name="dataModel"></param> /// <returns></returns> private string GenerateModelFile( DataModel dataModel ) { // If this model implements an internal type, we don't need to generate anything. if( !string.IsNullOrEmpty( dataModel.InternalType ) ) { return string.Empty; } const string template = "class {className} extends Tx_Extbase_DomainObject_AbstractEntity {{\n" + "{properties}" + "{gettersSetters}" + "}}"; const string propertyTemplate = "/**\n" + "* {0}\n" + "* @var {1}\n" + "*/\n" + "protected ${0};\n"; StringBuilder dataMembers = new StringBuilder(); foreach( DataModel.DataModelMember member in dataModel.Members ) { if( member.Name == Keywords.DataModelTemplate ) continue; bool containsKey = dataModel.ForeignModels.ContainsKey( member.Value ); if( containsKey ) { DataModel foreignModel = dataModel.ForeignModels[ member.Value ]; // Make sure to use the internal type name if it is defined. string foreignModelClassName = foreignModel.InternalType ?? NameHelper.GetExtbaseDomainModelClassName( Subject, dataModel.ForeignModels[ member.Name ] ); dataMembers.Append( string.Format( propertyTemplate, member.Value, foreignModelClassName ) ); } else { dataMembers.Append( string.Format( propertyTemplate, member.Value, TypeTranslator.ToPHP( member.Name, dataModel.SourceFragment.SourceDocument ) ) ); } } const string accessor = "public function get{1}() {{" + " return $this->{0};" + "}}" + "public function set{1}( ${0} ) {{" + " $this->{0} = ${0};" + "}}\n"; StringBuilder accessors = new StringBuilder(); foreach( DataModel.DataModelMember member in dataModel.Members ) { accessors.Append( string.Format( accessor, member.Value, NameHelper.UpperCamelCase( member.Value ) ) ); } var dataObject = new { className = NameHelper.GetExtbaseDomainModelClassName( Subject, dataModel ), properties = dataMembers, gettersSetters = accessors }; return template.FormatSmart( dataObject ); }
/// <summary> /// Generates a placeholder Fluid partial that will render a given data model. /// </summary> /// <param name="dataModel"></param> /// <returns></returns> private string GenerateFluidPartial( DataModel dataModel ) { const string modelTemplate = "<div class=\"tx-{cssRoot}-item\">\n{fieldsList}</div>\n"; const string fieldTemplate = "<div>{{{fieldAccessor}}}</div>\n"; StringBuilder fieldsCollector = new StringBuilder(); foreach( DataModel.DataModelMember member in dataModel.Members ) { fieldsCollector.Append( fieldTemplate.FormatSmart( new {fieldAccessor = dataModel.Name + "." + member.Value} ) ); } string fields = fieldsCollector.ToString(); string model = modelTemplate.FormatSmart( new {fieldsList = fields, cssRoot = NameHelper.UpperCamelCase( Subject.Key ).ToLower()} ); return model; }
/// <summary> /// Generates the Extbase class name for a given data model. /// </summary> /// <param name="extension"></param> /// <param name="dataModel"></param> /// <returns></returns> public static string GetExtbaseDomainModelFileName( Extension extension, DataModel dataModel ) { return String.Format( "{0}.php", UpperCamelCase( dataModel.Name ) ); }
/// <summary> /// Generates the ExtBase domain model class name for a given data model. /// </summary> /// <param name="extension"></param> /// <param name="dataModel"></param> /// <returns></returns> public static string GetExtbaseDomainModelClassName( Extension extension, DataModel dataModel ) { return String.Format( "Tx_{0}_Domain_Model_{1}", UpperCamelCase( extension.Key ), UpperCamelCase( dataModel.Name ) ); }
/// <summary> /// Retrieves a full model name for a data model. /// </summary> /// <example> /// tx_downloads_domain_model_download /// </example> /// <param name="extension">The extension this data model belongs to.</param> /// <param name="model">The data model.</param> /// <returns></returns> public static string GetAbsoluteModelName( Extension extension, DataModel model ) { return String.Format( "tx_{0}_domain_model_{1}", extension.Key.Replace( "_", string.Empty ), model.Name.ToLower() ); }
/// <summary> /// Generates the file name for a Fluid partial. /// </summary> /// <param name="subject"></param> /// <param name="dataModel"></param> /// <returns></returns> public static string GetFluidPartialFileName( Extension subject, DataModel dataModel ) { return String.Format( "{0}.html", UpperCamelCase( dataModel.Name ) ); }
/// <summary> /// Generates the Extbase class name for a given data model repository implementation. /// </summary> /// <param name="extension"></param> /// <param name="dataModel"></param> /// <returns></returns> public static string GetExtbaseDomainModelRepositoryImplementationFileName( Extension extension, DataModel dataModel ) { return String.Format( "{0}RepositoryImplementation.php", UpperCamelCase( dataModel.Name ) ); }
/// <summary> /// Generates the ExtBase domain model repository class name for a given data model that must be used for a specific implementation. /// </summary> /// <param name="extension"></param> /// <param name="dataModel"></param> /// <returns></returns> public static string GetExtbaseDomainModelRepositoryImplementationClassName( Extension extension, DataModel dataModel ) { return String.Format( "{0}{1}RepositoryImplementation", UpperCamelCase( extension.Key ), UpperCamelCase( dataModel.Name ) ); }