public void OnMetadataCreated(ModelMetadata metadata)
        {
            var extendedMetadata = metadata as ExtendedMetadata;

            if (extendedMetadata == null)
            {
                return;
            }

            var suffix = this.TypesFormatSuffix ?? (extendedMetadata.AdditionalValues.ContainsKey("TypesFormatSuffix") ?
                                                    extendedMetadata.AdditionalValues["TypesFormatSuffix"] as string :
                                                    null);

            var allowedTypes    = this.AllowedTypes.Select(a => a.FullName.ToLowerInvariant()).ToList();
            var restrictedTypes = this.RestrictedTypes.Select(r => r.FullName.ToLowerInvariant()).ToList();

            var injectedAllowedTypesAttribute = InjectedAllowedTypes.GetInjectedAllowedTypesAttribute(extendedMetadata.ContainerType, extendedMetadata.PropertyName);

            if (injectedAllowedTypesAttribute != null)
            {
                allowedTypes =
                    allowedTypes.Concat(
                        injectedAllowedTypesAttribute.AllowedTypes.Select(x => x.FullName.ToLowerInvariant()))
                    .Distinct()
                    .ToList();

                restrictedTypes =
                    restrictedTypes.Concat(
                        injectedAllowedTypesAttribute.RestrictedTypes.Select(x => x.FullName.ToLowerInvariant()))
                    .Distinct()
                    .ToList();
            }


            if (!string.IsNullOrEmpty(suffix))
            {
                allowedTypes    = allowedTypes.ToArray().Select(a => a + "." + suffix).ToList();
                restrictedTypes = restrictedTypes.ToArray().Select(a => a + "." + suffix).ToList();
            }

            var allowedTypesArray    = allowedTypes.ToArray();
            var restrictedTypesArray = restrictedTypes.ToArray();

            extendedMetadata.EditorConfiguration["AllowedTypes"]        = allowedTypesArray;
            extendedMetadata.EditorConfiguration["RestrictedTypes"]     = restrictedTypesArray;
            extendedMetadata.EditorConfiguration["AllowedDndTypes"]     = allowedTypesArray;
            extendedMetadata.EditorConfiguration["RestrictedDndTypes"]  = restrictedTypesArray;
            extendedMetadata.OverlayConfiguration["AllowedDndTypes"]    = allowedTypesArray;
            extendedMetadata.OverlayConfiguration["RestrictedDndTypes"] = restrictedTypesArray;
        }
Ejemplo n.º 2
0
        public void Initialize(InitializationEngine context)
        {
            InjectedAvailableModelSettings.RegisterCustomAvailableModelSettings(new Dictionary <Type, ContentTypeAvailableModelSetting>
            {
                //{
                //    typeof(MediaPage) , new ContentTypeAvailableModelSetting
                //                        {
                //                            Availability = Availability.Specific,
                //                            Included = new HashSet<Type> {typeof(CoolPage) }
                //                        }
                //}
            });

            InjectedAllowedTypes.RegisterInjectedAllowedTypesAttributes(new Dictionary <string, InjectedAllowedTypesAttribute>
            {
                //{
                //    string.Format("{0}.{1}",typeof(MediaPage).Name, nameof(MediaPage.ContentArea)), new InjectedAllowedTypesAttribute
                //    {
                //        AllowedTypes = new [] {typeof(MusicBlock)}
                //    }
                //}
            });
        }
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (value == null)
            {
                return(null);
            }

            var validationMessage = string.Empty;
            var stringBuilder     = new StringBuilder();
            var allowedTypes      = this.AllowedTypes;
            var restrictedTypes   = this.RestrictedTypes;
            var contentReferences = new List <ContentReference>();

            if (value is ContentArea)
            {
                var contentArea = value as ContentArea;
                contentReferences = contentArea.Items.Select(x => x.ContentLink).ToList();
            }
            else if (value is IEnumerable <ContentReference> )
            {
                var references = value as IEnumerable <ContentReference>;
                contentReferences = references.ToList();
            }
            else if (value is ContentReference)
            {
                var contentReference = value as ContentReference;
                contentReferences.Add(contentReference);
            }

            foreach (var contentReference in contentReferences)
            {
                var content    = _contentLoader.Get <IContent>(contentReference);
                var type       = content.GetOriginalType();
                var interfaces = type.GetInterfaces();

                var injectedAllowedTypesAttribute = InjectedAllowedTypes.GetInjectedAllowedTypesAttribute(validationContext.ObjectInstance.GetOriginalType(),
                                                                                                          validationContext.MemberName);

                if (injectedAllowedTypesAttribute != null)
                {
                    allowedTypes =
                        allowedTypes.Concat(injectedAllowedTypesAttribute.AllowedTypes).Distinct().ToArray();
                    restrictedTypes =
                        restrictedTypes.Concat(injectedAllowedTypesAttribute.RestrictedTypes).Distinct().ToArray();
                }

                if (restrictedTypes.Contains(type) || restrictedTypes.Any(x => interfaces.Any(i => i == x)))
                {
                    var message =
                        string.Format(
                            LocalizationService.Current.GetString("/injectedallowedtypes/errormessages/notallowed"), type.Name, validationContext.MemberName);
                    validationMessage = stringBuilder.Append(message).AppendLine(".").ToString();
                }

                if (!allowedTypes.Contains(type) && !allowedTypes.Any(x => interfaces.Any(i => i == x)))
                {
                    var message =
                        string.Format(
                            LocalizationService.Current.GetString("/injectedallowedtypes/errormessages/notallowed"), type.Name, validationContext.MemberName);
                    validationMessage = stringBuilder.Append(message).AppendLine(".").ToString();
                }
            }

            if (string.IsNullOrEmpty(validationMessage))
            {
                return(null);
            }

            var validationResult = new ValidationResult(validationMessage);

            return(validationResult);
        }
        /// <summary>
        /// Almost exact implementation of the AssignValuesToPropertyDefinition in the ContentDataAttributeScanningAssigner
        /// the only thing that differs is the added call to CustomAllowedTypes.GetMergedAllowedTypesAttribute.
        /// That call allows us to add more types to the Allowed/RestricedTypes without using the AllowedTypes attribute.
        /// </summary>
        /// <param name="propertyDefinitionModel"></param>
        /// <param name="property"></param>
        /// <param name="parentModel"></param>
        public override void AssignValuesToPropertyDefinition(PropertyDefinitionModel propertyDefinitionModel, PropertyInfo property, ContentTypeModel parentModel)
        {
            if (property.IsAutoGenerated() && !property.IsAutoVirtualPublic())
            {
                var exceptionMessage = string.Format(CultureInfo.InvariantCulture,
                                                     "The property '{0}' on the content type '{1}' is autogenerated but not virtual declared.",
                                                     property.Name, property.DeclaringType.Name);
                throw new InvalidOperationException(exceptionMessage);
            }

            //This is our added logic to merge a predefined AllowedTypes attribute with our own AllowedTypes specified in code.
            #region ModularAllowedTypes
            var customAttributes = Attribute.GetCustomAttributes(property, true).ToList();
            var injectedAllowedTypesAttribute = InjectedAllowedTypes.GetInjectedAllowedTypesAttribute(parentModel.ModelType,
                                                                                                      property.Name);
            var specifiedAllowedTypesAttribute = property.GetCustomAttribute <InjectedAllowedTypesAttribute>();

            //We DO NOT include an existing AllowedTypesAttribute in the merge, because if the AllowedTypesAttribute is used, EPiServer will ONLY
            //look at the AllowedTypesAttribute thus making the validation fail. We can't hook into that method as far as I know so you will need
            //to use the InjectedAllowedTypesAttribute instead of the AllowedTypesAttribute.
            if (customAttributes.Any(x => x is AllowedTypesAttribute))
            {
                var existingAllowedTypesAttribute =
                    customAttributes.FirstOrDefault(x => x is AllowedTypesAttribute) as AllowedTypesAttribute;

                if (injectedAllowedTypesAttribute != null)
                {
                    var mergedAllowedTypesAttribute = InjectedAllowedTypes.MergeAttributes(injectedAllowedTypesAttribute, specifiedAllowedTypesAttribute);
                    customAttributes.Remove(existingAllowedTypesAttribute);
                    customAttributes.Add(mergedAllowedTypesAttribute);
                }
            }
            else
            {
                var mergedAllowedTypesAttribute = InjectedAllowedTypes.MergeAttributes(injectedAllowedTypesAttribute, specifiedAllowedTypesAttribute);

                if (mergedAllowedTypesAttribute != null)
                {
                    customAttributes.Add(mergedAllowedTypesAttribute);
                }
            }
            #endregion

            foreach (var attribute in customAttributes)
            {
                if (attribute is BackingTypeAttribute)
                {
                    var backingTypeAttribute = attribute as BackingTypeAttribute;

                    if (backingTypeAttribute.BackingType != null)
                    {
                        if (!typeof(PropertyData).IsAssignableFrom(backingTypeAttribute.BackingType))
                        {
                            var exceptionMessage = string.Format(CultureInfo.InvariantCulture,
                                                                 "The backing type '{0}' attributed to the property '{1}' on '{2}' does not inherit PropertyData.",
                                                                 backingTypeAttribute.BackingType.FullName, property.Name, property.DeclaringType.Name);
                            throw new TypeMismatchException(exceptionMessage);
                        }

                        if (property.IsAutoVirtualPublic())
                        {
                            ValidateTypeCompability(property, backingTypeAttribute.BackingType);
                        }
                    }
                    propertyDefinitionModel.BackingType = backingTypeAttribute.BackingType;
                }
                else if (attribute is AllowedTypesAttribute)
                {
                    var allowedTypesAttribute = attribute as AllowedTypesAttribute;
                    VerifyAllowedTypesAttribute(allowedTypesAttribute, property);
                }
                else if (attribute is DisplayAttribute)
                {
                    var displayAttribute = attribute as DisplayAttribute;
                    propertyDefinitionModel.DisplayName = displayAttribute.GetName();
                    propertyDefinitionModel.Description = displayAttribute.GetDescription();
                    propertyDefinitionModel.Order       = displayAttribute.GetOrder();
                    propertyDefinitionModel.TabName     = displayAttribute.GetGroupName();
                }
                else if (attribute is ScaffoldColumnAttribute)
                {
                    var scaffoldColumnAttribute = attribute as ScaffoldColumnAttribute;
                    propertyDefinitionModel.AvailableInEditMode = scaffoldColumnAttribute.Scaffold;
                }
                else if (attribute is CultureSpecificAttribute)
                {
                    var specificAttribute = attribute as CultureSpecificAttribute;
                    ThrowIfBlockProperty(specificAttribute, property);
                    propertyDefinitionModel.CultureSpecific = specificAttribute.IsCultureSpecific;
                }
                else if (attribute is RequiredAttribute)
                {
                    var requiredAttribute = attribute as RequiredAttribute;
                    ThrowIfBlockProperty(requiredAttribute, property);
                    propertyDefinitionModel.Required = true;
                }
                else if (attribute is SearchableAttribute)
                {
                    var searchableAttribute = attribute as SearchableAttribute;
                    ThrowIfBlockProperty(searchableAttribute, property);
                    propertyDefinitionModel.Searchable = searchableAttribute.IsSearchable;
                }
                else if (attribute is UIHintAttribute)
                {
                    var uiHintAttribute = attribute as UIHintAttribute;
                    if (!string.IsNullOrEmpty(uiHintAttribute.UIHint))
                    {
                        if (string.Equals(uiHintAttribute.PresentationLayer, "website"))
                        {
                            propertyDefinitionModel.TemplateHint = uiHintAttribute.UIHint;
                        }
                        else if (string.IsNullOrEmpty(uiHintAttribute.PresentationLayer) &&
                                 string.IsNullOrEmpty(propertyDefinitionModel.TemplateHint))
                        {
                            propertyDefinitionModel.TemplateHint = uiHintAttribute.UIHint;
                        }
                    }
                }

                propertyDefinitionModel.Attributes.AddAttribute(attribute);
            }
        }