/// <summary>
        /// Updates settings for a store.
        /// </summary>
        /// <param name="settings">Settings class instance.</param>
        /// <param name="form">Form value collection.</param>
        /// <param name="storeId">Store identifier.</param>
        /// <param name="settingService">Setting service.</param>
        /// <param name="propertyNameMapper">Function to map property names. Return <c>null</c> to skip a property.</param>
        public async Task UpdateSettingsAsync(
            object settings,
            IFormCollection form,
            int storeId,
            Func <string, string> propertyNameMapper = null)
        {
            var settingType       = settings.GetType();
            var settingName       = settingType.Name;
            var settingProperties = FastProperty.GetProperties(settingType).Values;

            foreach (var prop in settingProperties)
            {
                var name = propertyNameMapper?.Invoke(prop.Name) ?? prop.Name;

                if (!name.HasValue())
                {
                    continue;
                }

                var key = string.Concat(settingName, ".", name);

                if (storeId == 0 || IsOverrideChecked(key, form))
                {
                    dynamic value = prop.GetValue(settings);
                    await _settingService.ApplySettingAsync(key, value ?? string.Empty, storeId);
                }
                else if (storeId > 0)
                {
                    await _settingService.RemoveSettingAsync(key, storeId);
                }
            }

            await _db.SaveChangesAsync();
        }
		private IEnumerable<TreeNode<ModelTreeMember>> BuildModelTreePartForClass(object instance)
		{
			var type = instance?.GetType();

			if (type == null)
			{
				yield break;
			}

			foreach (var prop in FastProperty.GetProperties(type).Values)
			{
				var pi = prop.Property;

				if (pi.PropertyType.IsPredefinedType())
				{
					yield return new TreeNode<ModelTreeMember>(new ModelTreeMember { Name = prop.Name, Kind = ModelTreeMemberKind.Primitive });
				}
				else if (typeof(IDictionary<string, object>).IsAssignableFrom(pi.PropertyType))
				{
					yield return BuildModelTreePart(prop.Name, prop.GetValue(instance));
				}
				else if (pi.PropertyType.IsSequenceType())
				{
					yield return new TreeNode<ModelTreeMember>(new ModelTreeMember { Name = prop.Name, Kind = ModelTreeMemberKind.Collection });
				}
				else
				{
					var node = new TreeNode<ModelTreeMember>(new ModelTreeMember { Name = prop.Name, Kind = ModelTreeMemberKind.Complex });
					node.AppendRange(BuildModelTreePartForClass(prop.GetValue(instance)));
					yield return node;
				}
			}
		}
        /// <summary>
        /// Updates settings for a store.
        /// </summary>
        /// <param name="settings">Settings class instance.</param>
        /// <param name="form">Form value collection.</param>
        /// <param name="storeId">Store identifier.</param>
        /// <param name="settingService">Setting service.</param>
        /// <param name="propertyNameMapper">Function to map property names. Return <c>null</c> to skip a property.</param>
        public void UpdateSettings(
            object settings,
            FormCollection form,
            int storeId,
            ISettingService settingService,
            Func <string, string> propertyNameMapper = null)
        {
            var settingType       = settings.GetType();
            var settingName       = settingType.Name;
            var settingProperties = FastProperty.GetProperties(settingType).Values;

            foreach (var prop in settingProperties)
            {
                var name = propertyNameMapper?.Invoke(prop.Name) ?? prop.Name;

                if (string.IsNullOrWhiteSpace(name))
                {
                    continue;
                }

                var key = string.Concat(settingName, ".", name);

                if (storeId == 0 || IsOverrideChecked(key, form))
                {
                    dynamic value = prop.GetValue(settings);
                    settingService.SetSetting(key, value ?? string.Empty, storeId, false);
                }
                else if (storeId > 0)
                {
                    settingService.DeleteSetting(key, storeId);
                }
            }
        }
Exemple #4
0
        private static void MapObject(IDataReader reader, object instance, params string[] fieldsToSkip)
        {
            var fastProperties = FastProperty.GetProperties(instance);

            if (fastProperties.Count == 0)
            {
                return;
            }

            for (int i = 0; i < reader.FieldCount; i++)
            {
                string name = reader.GetName(i);
                if (fastProperties.ContainsKey(name))
                {
                    var fastProp = fastProperties[name];

                    if (fieldsToSkip.Contains(name))
                    {
                        continue;
                    }

                    if ((fastProp != null) && fastProp.Property.CanWrite)
                    {
                        var dbValue = reader.GetValue(i);
                        fastProp.SetValue(instance, (dbValue == DBNull.Value) ? null : dbValue);
                    }
                }
            }
        }
Exemple #5
0
        protected virtual void SaveSettingCore(ISettings settings, int storeId = 0)
        {
            Guard.NotNull(settings, nameof(settings));

            using (BeginScope())
            {
                var settingType = settings.GetType();
                var prefix      = settingType.Name;

                /* We do not clear cache after each setting update.
                 * This behavior can increase performance because cached settings will not be cleared
                 * and loaded from database after each update */
                foreach (var prop in FastProperty.GetProperties(settingType).Values)
                {
                    // get properties we can read and write to
                    if (!prop.IsPublicSettable)
                    {
                        continue;
                    }

                    var converter = TypeConverterFactory.GetConverter(prop.Property.PropertyType);
                    if (converter == null || !converter.CanConvertFrom(typeof(string)))
                    {
                        continue;
                    }

                    string key = prefix + "." + prop.Name;
                    // Duck typing is not supported in C#. That's why we're using dynamic type
                    dynamic value = prop.GetValue(settings);

                    SetSetting(key, value ?? "", storeId, false);
                }
            }
        }
Exemple #6
0
        /// <summary>
        /// Save settings object
        /// </summary>
        /// <typeparam name="T">Type</typeparam>
        /// <param name="settings">Setting instance</param>
        /// <param name="storeId">Store identifier</param>
        public virtual void SaveSetting <T>(T settings, int storeId = 0) where T : ISettings, new()
        {
            if (typeof(T).HasAttribute <JsonPersistAttribute>(true))
            {
                SaveSettingsJson <T>(settings);
                return;
            }

            /* We do not clear cache after each setting update.
             * This behavior can increase performance because cached settings will not be cleared
             * and loaded from database after each update */
            foreach (var prop in FastProperty.GetProperties(typeof(T)).Values)
            {
                // get properties we can read and write to
                if (!prop.IsPublicSettable)
                {
                    continue;
                }

                var converter = TypeConverterFactory.GetConverter(prop.Property.PropertyType);
                if (converter == null || !converter.CanConvertFrom(typeof(string)))
                {
                    continue;
                }

                string key = typeof(T).Name + "." + prop.Name;
                // Duck typing is not supported in C#. That's why we're using dynamic type
                dynamic value = prop.GetValue(settings);

                SetSetting(key, value ?? "", storeId, false);
            }

            //and now clear cache
            ClearCache();
        }
Exemple #7
0
        protected virtual ISettings LoadSettingCore(Type settingType)
        {
            var settings = (ISettings)Activator.CreateInstance(settingType);

            var prefix = settingType.Name;

            foreach (var fastProp in FastProperty.GetProperties(settingType).Values)
            {
                var prop = fastProp.Property;

                // get properties we can read and write to
                if (!prop.CanWrite)
                {
                    continue;
                }

                var key = prefix + "." + prop.Name;
                // load by store
                string setting = GetSetting <string>(key, loadSharedValueIfNotFound: true);

                if (setting == null)
                {
                    if (fastProp.IsSequenceType)
                    {
                        if ((fastProp.GetValue(settings) as IEnumerable) != null)
                        {
                            // Instance of IEnumerable<> was already created, most likely in the constructor of the settings concrete class.
                            // In this case we shouldn't let the EnumerableConverter create a new instance but keep this one.
                            continue;
                        }
                    }
                    else
                    {
                        continue;
                    }
                }

                var converter = TypeConverterFactory.GetConverter(prop.PropertyType);

                if (converter == null || !converter.CanConvertFrom(typeof(string)))
                {
                    continue;
                }

                try
                {
                    object value = converter.ConvertFrom(setting);

                    // Set property
                    fastProp.SetValue(settings, value);
                }
                catch (Exception)
                {
                    "Could not convert setting '{0}' to type '{1}'".FormatInvariant(key, prop.PropertyType.Name);
                }
            }

            return(settings);
        }
        public static void Populate(IDictionary <string, object> source, object target, out ICollection <ConvertProblem> problems, params object[] populated)
        {
            Guard.NotNull(source, nameof(source));
            Guard.NotNull(target, nameof(target));

            problems = new List <ConvertProblem>();

            if (populated.Any(x => x == target))
            {
                return;
            }

            Type t = target.GetType();

            if (source != null)
            {
                foreach (var fastProp in FastProperty.GetProperties(t).Values)
                {
                    object value;
                    var    pi = fastProp.Property;

                    if (!pi.PropertyType.IsPredefinedSimpleType() && source.TryGetValue(pi.Name, out value) && value is IDictionary <string, object> )
                    {
                        var nestedValue = fastProp.GetValue(target);
                        ICollection <ConvertProblem> nestedProblems;

                        populated = populated.Concat(new object[] { target }).ToArray();
                        Populate((IDictionary <string, object>)value, nestedValue, out nestedProblems, populated);

                        if (nestedProblems != null && nestedProblems.Any())
                        {
                            problems.AddRange(nestedProblems);
                        }
                        WriteToProperty(target, fastProp, nestedValue, problems);
                    }
                    else if (pi.PropertyType.IsArray && !source.ContainsKey(pi.Name))
                    {
                        WriteToProperty(target, fastProp, RetrieveArrayValues(pi, source, problems), problems);
                    }
                    else
                    {
                        if (source.TryGetValue(pi.Name, out value))
                        {
                            WriteToProperty(target, fastProp, value, problems);
                        }
                    }
                }
            }
        }
Exemple #9
0
        private RenderParameters CreateParameters(object data, IFormatProvider formatProvider)
        {
            var p = new RenderParameters(formatProvider);

            Hash hash = null;

            if (data is ISafeObject so)
            {
                if (so.GetWrappedObject() is IDictionary <string, object> soDict)
                {
                    hash = Hash.FromDictionary(soDict);
                }
                else
                {
                    data = so.GetWrappedObject();
                }
            }

            if (hash == null)
            {
                hash = new Hash();

                if (data is IDictionary <string, object> dict)
                {
                    foreach (var kvp in dict)
                    {
                        hash[kvp.Key] = LiquidUtil.CreateSafeObject(kvp.Value);
                    }
                }
                else
                {
                    var props = FastProperty.GetProperties(data.GetType());
                    foreach (var prop in props)
                    {
                        hash[prop.Key] = LiquidUtil.CreateSafeObject(prop.Value.GetValue(data));
                    }
                }
            }

            p.LocalVariables   = hash;
            p.ErrorsOutputMode = HostingEnvironment.IsHosted ? ErrorsOutputMode.Display : ErrorsOutputMode.Rethrow;

            return(p);
        }
        internal int DetachInternal(BaseEntity obj, ISet <BaseEntity> objSet, bool deep)
        {
            if (obj == null)
            {
                return(0);
            }

            int numDetached = 0;

            if (deep)
            {
                // This is to prevent an infinite recursion when the child object has a navigation property
                // that points back to the parent
                if (objSet != null && !objSet.Add(obj))
                {
                    return(0);
                }

                // Recursively detach all navigation properties
                foreach (var prop in FastProperty.GetProperties(obj.GetUnproxiedType()).Values)
                {
                    if (typeof(BaseEntity).IsAssignableFrom(prop.Property.PropertyType))
                    {
                        numDetached += DetachInternal(prop.GetValue(obj) as BaseEntity, objSet, deep);
                    }
                    else if (typeof(IEnumerable <BaseEntity>).IsAssignableFrom(prop.Property.PropertyType))
                    {
                        var val = prop.GetValue(obj);
                        if (val is IEnumerable <BaseEntity> list)
                        {
                            foreach (var item in list.ToList())
                            {
                                numDetached += DetachInternal(item, objSet, deep);
                            }
                        }
                    }
                }
            }

            base.Entry(obj).State = EfState.Detached;
            numDetached++;

            return(numDetached);
        }
        /// <summary>
        /// Copies common validation rules from <typeparamref name="TEntity"/> type over to corresponding <typeparamref name="TModel"/> type.
        /// Common rules are: Required and MaxLength rules on string properties (either fluently mapped or annotated).
        /// </summary>
        /// <typeparam name="TEntity">The type of source entity.</typeparam>
        /// <param name="db">The data context instance to which <typeparamref name="TEntity"/> belongs.</param>
        /// <param name="ignoreProperties">An optional list of property names to ignore.</param>
        protected virtual void CopyFromEntityRules <TEntity>(DbContext db, params string[] ignoreProperties) where TEntity : BaseEntity, new()
        {
            Guard.NotNull(db, nameof(db));

            var entityType = db.Model.GetEntityTypes(typeof(TEntity)).FirstOrDefault();

            if (entityType != null)
            {
                // Get all model properties
                var modelProps = FastProperty.GetProperties(typeof(TModel), PropertyCachingStrategy.EagerCached);

                // Get all entity properties not in exclusion list
                var entityProps = entityType.GetProperties()
                                  .Where(x => x.ClrType == typeof(string) && !ignoreProperties.Contains(x.Name))
                                  .OfType <IMutableProperty>();

                // Loop thru all entity string properties
                foreach (var entityProp in entityProps)
                {
                    // Check if target model contains property (must be of same name and type)
                    if (modelProps.TryGetValue(entityProp.Name, out var modelProp) && modelProp.Property.PropertyType == typeof(string))
                    {
                        var isNullable = entityProp.IsNullable;
                        var maxLength  = entityProp.GetMaxLength();

                        if (!isNullable || maxLength.HasValue)
                        {
                            var expression = DynamicExpressionParser.ParseLambda <TModel, string>(null, false, "@" + modelProp.Name);

                            if (!isNullable)
                            {
                                RuleFor(expression).NotEmpty();
                            }

                            if (maxLength.HasValue)
                            {
                                RuleFor(expression).Length(0, maxLength.Value);
                            }
                        }
                    }
                }
            }
        }
        // REVIEW: Dieser Code ist redundant mit DefaultModelBinder u.Ä. Entweder ablösen oder eliminieren (vielleicht ist es ja in diesem Kontext notwendig!??!)
        private static object RetrieveArrayValues(PropertyInfo arrayProp, IDictionary <string, object> source, ICollection <ConvertProblem> problems)
        {
            Type elemType       = arrayProp.PropertyType.GetElementType();
            bool anyValuesFound = true;
            int  idx            = 0;
            var  elements       = (IList)Activator.CreateInstance(typeof(List <>).MakeGenericType(elemType));

            var properties = FastProperty.GetProperties(elemType);

            while (anyValuesFound)
            {
                object curElement = null;
                anyValuesFound = false; // false until proven otherwise

                foreach (var prop in properties.Values)
                {
                    //var key = string.Format("_{0}{1}_{2}", idx, arrayProp.Name, pd.Name);
                    var    key = string.Format("{0}[{1}].{2}", arrayProp.Name, idx, prop.Name);
                    object value;

                    if (source.TryGetValue(key, out value))
                    {
                        anyValuesFound = true;

                        if (curElement == null)
                        {
                            curElement = Activator.CreateInstance(elemType);
                            elements.Add(curElement);
                        }

                        SetPropFromValue(value, curElement, prop, problems);
                    }
                }

                idx++;
            }

            var elementArray = Array.CreateInstance(elemType, elements.Count);

            elements.CopyTo(elementArray, 0);

            return(elementArray);
        }
        private static T MapReaderToObject <T>(DbDataReader reader)
        {
            var fastProps = FastProperty.GetProperties(typeof(T));
            var obj       = Activator.CreateInstance <T>();

            for (int i = 0; i < reader.FieldCount; i++)
            {
                if (!reader.IsDBNull(i))
                {
                    string columnName = reader.GetName(i);

                    if (fastProps.TryGetValue(columnName, out var prop))
                    {
                        prop.SetValue(obj, reader.GetValue(i));
                    }
                }
            }

            return(obj);
        }
        public bool SaveSetting <T>(T settings, int storeId = 0) where T : ISettings, new()
        {
            Guard.NotNull(settings, nameof(settings));

            using (BeginScope(clearCache: true))
            {
                var hasChanges         = false;
                var modifiedProperties = new Dictionary <string, object>(StringComparer.OrdinalIgnoreCase);
                var settingType        = typeof(T);
                var prefix             = settingType.Name;

                /* We do not clear cache after each setting update.
                 * This behavior can increase performance because cached settings will not be cleared
                 * and loaded from database after each update */
                foreach (var prop in FastProperty.GetProperties(settingType).Values)
                {
                    // get properties we can read and write to
                    if (!prop.IsPublicSettable)
                    {
                        continue;
                    }

                    var converter = TypeConverterFactory.GetConverter(prop.Property.PropertyType);
                    if (converter == null || !converter.CanConvertFrom(typeof(string)))
                    {
                        continue;
                    }

                    string key = prefix + "." + prop.Name;
                    // Duck typing is not supported in C#. That's why we're using dynamic type
                    dynamic currentValue = prop.GetValue(settings);

                    if (SetSetting(key, currentValue ?? "", storeId, false) > SaveSettingResult.Unchanged)
                    {
                        hasChanges = true;
                    }
                }

                return(hasChanges);
            }
        }
        public void UpdateSettings(object settings, FormCollection form, int storeId, ISettingService settingService, ILocalizedModelLocal localized = null)
        {
            var settingName = settings.GetType().Name;
            var properties  = FastProperty.GetProperties(localized == null ? settings.GetType() : localized.GetType()).Values;

            foreach (var prop in properties)
            {
                var name = prop.Name;
                var key  = settingName + "." + name;

                if (storeId == 0 || IsOverrideChecked(key, form))
                {
                    dynamic value = prop.GetValue(localized == null ? settings : localized);
                    settingService.SetSetting(key, value == null ? "" : value, storeId, false);
                }
                else if (storeId > 0)
                {
                    settingService.DeleteSetting(key, storeId);
                }
            }
        }
        /// <summary>
        /// Updates settings for a store.
        /// </summary>
        /// <param name="settings">Settings class instance.</param>
        /// <param name="form">Form value collection.</param>
        /// <param name="storeId">Store identifier.</param>
        /// <param name="settingService">Setting service.</param>
        /// <param name="localized">Localized model.</param>
        /// <param name="propertyNameMapper">Function to map property names. Return <c>null</c> to skip a property.</param>
        public void UpdateSettings(
            object settings,
            FormCollection form,
            int storeId,
            ISettingService settingService,
            ILocalizedModelLocal localized           = null,
            Func <string, string> propertyNameMapper = null)
        {
            var settingName = settings.GetType().Name;
            var properties  = FastProperty.GetProperties(localized == null ? settings.GetType() : localized.GetType()).Values;

            foreach (var prop in properties)
            {
                var name = prop.Name;

                if (propertyNameMapper != null)
                {
                    name = propertyNameMapper(name);
                }

                if (string.IsNullOrWhiteSpace(name))
                {
                    continue;
                }

                var key = string.Concat(settingName, ".", name);

                if (storeId == 0 || IsOverrideChecked(key, form))
                {
                    dynamic value = prop.GetValue(localized == null ? settings : localized);
                    settingService.SetSetting(key, value == null ? "" : value, storeId, false);
                }
                else if (storeId > 0)
                {
                    settingService.DeleteSetting(key, storeId);
                }
            }
        }
        /// <inheritdoc/>
        public async Task <int> SaveSettingsAsync <T>(T settings, int storeId = 0) where T : ISettings, new()
        {
            Guard.NotNull(settings, nameof(settings));

            // INFO: Let SettingService's hook handler handle cache invalidation

            var settingsType = typeof(T);
            var prefix       = settingsType.Name;
            var hasChanges   = false;

            using var db = _dbContextFactory.CreateDbContext();
            var rawSettings = await GetRawSettingsAsync(db, settingsType, storeId, false, true);

            foreach (var prop in FastProperty.GetProperties(settingsType).Values)
            {
                // Get only properties we can read and write to
                if (!prop.IsPublicSettable)
                {
                    continue;
                }

                var converter = TypeConverterFactory.GetConverter(prop.Property.PropertyType);
                if (converter == null || !converter.CanConvertFrom(typeof(string)))
                {
                    continue;
                }

                string key          = prefix + "." + prop.Name;
                string currentValue = prop.GetValue(settings).Convert <string>();

                if (rawSettings.TryGetValue(key, out var setting))
                {
                    if (setting.Value != currentValue)
                    {
                        // Update
                        setting.Value = currentValue;
                        hasChanges    = true;
                    }
                }
                else
                {
                    // Insert
                    setting = new Setting
                    {
                        Name    = key.ToLowerInvariant(),
                        Value   = currentValue,
                        StoreId = storeId
                    };

                    hasChanges = true;
                    db.Settings.Add(setting);
                }
            }

            var numSaved = hasChanges ? await db.SaveChangesAsync() : 0;

            if (numSaved > 0)
            {
                // Prevent reloading from DB on next hit
                await _cache.PutAsync(
                    SettingService.BuildCacheKeyForClassAccess(settingsType, storeId),
                    settings,
                    new CacheEntryOptions().ExpiresIn(SettingService.DefaultExpiry));
            }

            return(numSaved);
        }
Exemple #18
0
        /// Load settings
        /// </summary>
        /// <typeparam name="T">Type</typeparam>
        public virtual T LoadSetting <T>() where T : ISettings, new()
        {
            if (typeof(T).HasAttribute <JsonPersistAttribute>(true))
            {
                return(LoadSettingsJson <T>());
            }

            var settings = Activator.CreateInstance <T>();

            foreach (var fastProp in FastProperty.GetProperties(typeof(T)).Values)
            {
                var prop = fastProp.Property;

                // get properties we can read and write to
                if (!prop.CanWrite)
                {
                    continue;
                }

                var key = typeof(T).Name + "." + prop.Name;

                string setting = GetSettingByKey <string>(key);

                if (setting == null && !fastProp.IsSequenceType)
                {
                    #region Obsolete ('EnumerableConverter' can handle this case now)
                    //if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(List<>))
                    //{
                    //	// convenience: don't return null for simple list types
                    //	var listArg = prop.PropertyType.GetGenericArguments()[0];
                    //	object list = null;

                    //	if (listArg == typeof(int))
                    //		list = new List<int>();
                    //	else if (listArg == typeof(decimal))
                    //		list = new List<decimal>();
                    //	else if (listArg == typeof(string))
                    //		list = new List<string>();

                    //	if (list != null)
                    //	{
                    //		fastProp.SetValue(settings, list);
                    //	}
                    //}
                    #endregion

                    continue;
                }

                var converter = TypeConverterFactory.GetConverter(prop.PropertyType);

                if (converter == null || !converter.CanConvertFrom(typeof(string)))
                {
                    continue;
                }

                object value = converter.ConvertFrom(setting);

                //set property
                fastProp.SetValue(settings, value);
            }

            return(settings);
        }
Exemple #19
0
        public virtual async Task <Product> CloneProductAsync(
            Product product,
            string cloneName,
            bool isPublished,
            bool copyAssociatedProducts = true)
        {
            Guard.NotNull(product, nameof(product));
            Guard.NotEmpty(cloneName, nameof(cloneName));

            var localizedKeySelectors = new List <Expression <Func <Product, string> > >
            {
                x => x.Name,
                x => x.ShortDescription,
                x => x.FullDescription,
                x => x.MetaKeywords,
                x => x.MetaDescription,
                x => x.MetaTitle,
                x => x.BundleTitleText
            };

            var clone     = new Product();
            var utcNow    = DateTime.UtcNow;
            var languages = await _languageService.GetAllLanguagesAsync(true);

            int?sampleDownloadId = null;

            // Enable hooks for slugs cache invalidation.
            using (_chronometer.Step("Clone product " + product.Id))
                using (var scope = new DbContextScope(_db, autoDetectChanges: false, hooksEnabled: true, deferCommit: true, forceNoTracking: true))
                {
                    if (product.HasSampleDownload && product.SampleDownload != null)
                    {
                        var sampleDownloadClone = product.SampleDownload.Clone();
                        _db.Downloads.Add(sampleDownloadClone);

                        await scope.CommitAsync();

                        sampleDownloadId = sampleDownloadClone.Id;
                    }

                    var props = FastProperty.GetProperties(typeof(Product), PropertyCachingStrategy.EagerCached);

                    foreach (var prop in props.Values)
                    {
                        if (prop.IsComplexType)
                        {
                            continue;
                        }

                        if (!prop.IsPublicSettable)
                        {
                            continue;
                        }

                        prop.SetValue(clone, prop.GetValue(product));
                    }

                    clone.Id               = 0;
                    clone.Name             = cloneName;
                    clone.SampleDownloadId = sampleDownloadId;
                    clone.Published        = isPublished;
                    clone.CreatedOnUtc     = utcNow;
                    clone.UpdatedOnUtc     = utcNow;

                    // Category mappings.
                    clone.ProductCategories.AddRange(product.ProductCategories.Select(x => new ProductCategory
                    {
                        CategoryId        = x.CategoryId,
                        IsFeaturedProduct = x.IsFeaturedProduct,
                        DisplayOrder      = x.DisplayOrder
                    }));

                    // Manufacturer mappings.
                    clone.ProductManufacturers.AddRange(product.ProductManufacturers.Select(x => new ProductManufacturer
                    {
                        ManufacturerId    = x.ManufacturerId,
                        IsFeaturedProduct = x.IsFeaturedProduct,
                        DisplayOrder      = x.DisplayOrder
                    }));

                    // Media file mappings.
                    clone.ProductPictures.AddRange(product.ProductPictures.Select(x => new ProductMediaFile
                    {
                        MediaFileId  = x.MediaFileId,
                        DisplayOrder = x.DisplayOrder
                    }));
                    if (clone.MainPictureId == null)
                    {
                        clone.MainPictureId = product.ProductPictures.FirstOrDefault()?.MediaFileId;
                    }

                    // Product specification attributes.
                    clone.ProductSpecificationAttributes.AddRange(product.ProductSpecificationAttributes.Select(x => new ProductSpecificationAttribute
                    {
                        SpecificationAttributeOptionId = x.SpecificationAttributeOptionId,
                        AllowFiltering    = x.AllowFiltering,
                        ShowOnProductPage = x.ShowOnProductPage,
                        DisplayOrder      = x.DisplayOrder
                    }));

                    // Tier prices.
                    clone.TierPrices.AddRange(product.TierPrices.Select(x => new TierPrice
                    {
                        StoreId           = x.StoreId,
                        CustomerRoleId    = x.CustomerRoleId,
                        Quantity          = x.Quantity,
                        Price             = x.Price,
                        CalculationMethod = x.CalculationMethod
                    }));
                    clone.HasTierPrices = clone.TierPrices.Any();

                    // Discount mappings.
                    foreach (var discount in product.AppliedDiscounts)
                    {
                        clone.AppliedDiscounts.Add(discount);
                        clone.HasDiscountsApplied = true;
                    }

                    // Tags.
                    foreach (var tag in product.ProductTags)
                    {
                        clone.ProductTags.Add(tag);
                    }

                    // >>>>>>> Put clone to db (from here on we need the product clone's ID).
                    _db.Products.Add(clone);
                    await scope.CommitAsync();

                    // Store mappings.
                    var selectedStoreIds = await _storeMappingService.GetAuthorizedStoreIdsAsync(product);

                    selectedStoreIds.Each(id => _storeMappingService.AddStoreMapping(clone, id));

                    await ProcessPromotions(product, clone);

                    await ProcessSlugs(product, clone, languages);

                    await ProcessLocalizations(product, clone, localizedKeySelectors, languages);

                    await ProcessDownloads(product, clone);

                    // >>>>>>> Put to db.
                    await scope.CommitAsync();

                    await ProcessBundleItems(scope, product, clone, languages);

                    // Attributes and attribute combinations.
                    await ProcessAttributes(scope, product, clone, languages);

                    // Update computed properties.
                    clone.LowestAttributeCombinationPrice = await _db.ProductVariantAttributeCombinations
                                                            .ApplyLowestPriceFilter(clone.Id)
                                                            .Select(x => x.Price)
                                                            .FirstOrDefaultAsync();

                    // Associated products.
                    if (copyAssociatedProducts && product.ProductType != ProductType.BundledProduct)
                    {
                        await ProcessAssociatedProducts(product, clone, isPublished);
                    }

                    // >>>>>>> Our final commit.
                    await scope.CommitAsync();
                }

            return(clone);
        }
        private ISettings MaterializeSettings(Type settingsType, IDictionary <string, Setting> rawSettings)
        {
            Guard.NotNull(settingsType, nameof(settingsType));
            Guard.NotNull(rawSettings, nameof(rawSettings));

            var instance = (ISettings)Activator.CreateInstance(settingsType);
            var prefix   = settingsType.Name;

            foreach (var fastProp in FastProperty.GetProperties(settingsType).Values)
            {
                var prop = fastProp.Property;

                // Get properties we can read and write to
                if (!prop.CanWrite)
                {
                    continue;
                }

                string key = prefix + "." + prop.Name;
                rawSettings.TryGetValue(key, out var rawSetting);

                string setting = rawSetting?.Value;

                if (setting == null)
                {
                    if (fastProp.IsSequenceType)
                    {
                        if ((fastProp.GetValue(instance) as System.Collections.IEnumerable) != null)
                        {
                            // Instance of IEnumerable<> was already created, most likely in the constructor of the settings concrete class.
                            // In this case we shouldn't let the EnumerableConverter create a new instance but keep this one.
                            continue;
                        }
                    }
                    else
                    {
                        continue;
                    }
                }

                var converter = TypeConverterFactory.GetConverter(prop.PropertyType);

                if (converter == null || !converter.CanConvertFrom(typeof(string)))
                {
                    continue;
                }

                try
                {
                    object value = converter.ConvertFrom(setting);

                    // Set property
                    fastProp.SetValue(instance, value);
                }
                catch (Exception ex)
                {
                    var msg = "Could not convert setting '{0}' to type '{1}'".FormatInvariant(key, prop.PropertyType.Name);
                    Logger.Error(ex, msg);
                }
            }

            return(instance);
        }
Exemple #21
0
        /// Load settings
        /// </summary>
        /// <typeparam name="T">Type</typeparam>
        /// <param name="storeId">Store identifier for which settigns should be loaded</param>
        public virtual T LoadSetting <T>(int storeId = 0) where T : ISettings, new()
        {
            if (typeof(T).HasAttribute <JsonPersistAttribute>(true))
            {
                return(LoadSettingsJson <T>(storeId));
            }

            var settings = Activator.CreateInstance <T>();

            foreach (var fastProp in FastProperty.GetProperties(typeof(T)).Values)
            {
                var prop = fastProp.Property;

                // get properties we can read and write to
                if (!prop.CanWrite)
                {
                    continue;
                }

                var key = typeof(T).Name + "." + prop.Name;
                // load by store
                string setting = GetSettingByKey <string>(key, storeId: storeId, loadSharedValueIfNotFound: true);

                if (setting == null)
                {
                    if (fastProp.IsSequenceType)
                    {
                        if ((fastProp.GetValue(settings) as IEnumerable) != null)
                        {
                            // Instance of IEnumerable<> was already created, most likely in the constructor of the settings concrete class.
                            // In this case we shouldn't let the EnumerableConverter create a new instance but keep this one.
                            continue;
                        }
                    }
                    else
                    {
                        #region Obsolete ('EnumerableConverter' can handle this case now)
                        //if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(List<>))
                        //{
                        //	// convenience: don't return null for simple list types
                        //	var listArg = prop.PropertyType.GetGenericArguments()[0];
                        //	object list = null;

                        //	if (listArg == typeof(int))
                        //		list = new List<int>();
                        //	else if (listArg == typeof(decimal))
                        //		list = new List<decimal>();
                        //	else if (listArg == typeof(string))
                        //		list = new List<string>();

                        //	if (list != null)
                        //	{
                        //		fastProp.SetValue(settings, list);
                        //	}
                        //}
                        #endregion

                        continue;
                    }
                }

                var converter = TypeConverterFactory.GetConverter(prop.PropertyType);

                if (converter == null || !converter.CanConvertFrom(typeof(string)))
                {
                    continue;
                }

                object value = converter.ConvertFrom(setting);

                //set property
                fastProp.SetValue(settings, value);
            }

            return(settings);
        }
Exemple #22
0
        protected virtual ISettings LoadSettingCore(Type settingType, int storeId = 0)
        {
            if (settingType.HasAttribute <JsonPersistAttribute>(true))
            {
                return(LoadSettingsJson(settingType, storeId));
            }

            var settings = (ISettings)Activator.CreateInstance(settingType);

            var prefix = settingType.Name;

            foreach (var fastProp in FastProperty.GetProperties(settingType).Values)
            {
                var prop = fastProp.Property;

                // get properties we can read and write to
                if (!prop.CanWrite)
                {
                    continue;
                }

                var key = prefix + "." + prop.Name;
                // load by store
                string setting = GetSettingByKey <string>(key, storeId: storeId, loadSharedValueIfNotFound: true);

                if (setting == null)
                {
                    if (fastProp.IsSequenceType)
                    {
                        if ((fastProp.GetValue(settings) as IEnumerable) != null)
                        {
                            // Instance of IEnumerable<> was already created, most likely in the constructor of the settings concrete class.
                            // In this case we shouldn't let the EnumerableConverter create a new instance but keep this one.
                            continue;
                        }
                    }
                    else
                    {
                        #region Obsolete ('EnumerableConverter' can handle this case now)
                        //if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(List<>))
                        //{
                        //	// convenience: don't return null for simple list types
                        //	var listArg = prop.PropertyType.GetGenericArguments()[0];
                        //	object list = null;

                        //	if (listArg == typeof(int))
                        //		list = new List<int>();
                        //	else if (listArg == typeof(decimal))
                        //		list = new List<decimal>();
                        //	else if (listArg == typeof(string))
                        //		list = new List<string>();

                        //	if (list != null)
                        //	{
                        //		fastProp.SetValue(settings, list);
                        //	}
                        //}
                        #endregion

                        continue;
                    }
                }

                var converter = TypeConverterFactory.GetConverter(prop.PropertyType);

                if (converter == null || !converter.CanConvertFrom(typeof(string)))
                {
                    continue;
                }

                try
                {
                    object value = converter.ConvertFrom(setting);

                    // Set property
                    fastProp.SetValue(settings, value);
                }
                catch (Exception ex)
                {
                    var msg = "Could not convert setting '{0}' to type '{1}'".FormatInvariant(key, prop.PropertyType.Name);
                    Logger.Error(ex, msg);
                }
            }

            return(settings);
        }
Exemple #23
0
        protected virtual ISettings LoadSettingCore(Type settingType, int storeId = 0)
        {
            var allSettings = GetAllCachedSettings();
            var instance    = (ISettings)Activator.CreateInstance(settingType);
            var prefix      = settingType.Name;

            foreach (var fastProp in FastProperty.GetProperties(settingType).Values)
            {
                var prop = fastProp.Property;

                // Get properties we can read and write to
                if (!prop.CanWrite)
                {
                    continue;
                }

                string key = prefix + "." + prop.Name;

                if (!allSettings.TryGetValue(CreateCacheKey(key, storeId), out var cachedSetting) && storeId > 0)
                {
                    // Fallback to shared (storeId = 0)
                    allSettings.TryGetValue(CreateCacheKey(key, 0), out cachedSetting);
                }

                string setting = cachedSetting?.Value;

                if (setting == null)
                {
                    if (fastProp.IsSequenceType)
                    {
                        if ((fastProp.GetValue(instance) as IEnumerable) != null)
                        {
                            // Instance of IEnumerable<> was already created, most likely in the constructor of the settings concrete class.
                            // In this case we shouldn't let the EnumerableConverter create a new instance but keep this one.
                            continue;
                        }
                    }
                    else
                    {
                        continue;
                    }
                }

                var converter = TypeConverterFactory.GetConverter(prop.PropertyType);

                if (converter == null || !converter.CanConvertFrom(typeof(string)))
                {
                    continue;
                }

                try
                {
                    object value = converter.ConvertFrom(setting);

                    // Set property
                    fastProp.SetValue(instance, value);
                }
                catch (Exception ex)
                {
                    var msg = "Could not convert setting '{0}' to type '{1}'".FormatInvariant(key, prop.PropertyType.Name);
                    Logger.Error(ex, msg);
                }
            }

            return(instance);
        }