Beispiel #1
0
 public ValidateSlugResult(ValidateSlugResult copyFrom)
 {
     _source      = copyFrom.Source;
     EntityName   = _source?.GetEntityName();
     Slug         = copyFrom.Slug;
     Found        = copyFrom.Found;
     FoundIsSelf  = copyFrom.FoundIsSelf;
     LanguageId   = copyFrom.LanguageId;
     WasValidated = copyFrom.WasValidated;
 }
Beispiel #2
0
        /// <summary>
        /// Applies a slug without sanitization or uniqueness check. This method
        /// throws if the given slug already exists in the database. The recommended
        /// way to apply a slug is to call <see cref="IUrlService.ValidateSlugAsync{T}(T, string, bool, int?)"/>
        /// first, then to call <see cref="IUrlService.ApplySlugAsync(ValidateSlugResult, bool)"/> by passing
        /// the return value from first call.
        /// </summary>
        /// <typeparam name="T">Type of slug supporting entity</typeparam>
        /// <param name="entity">Entity instance</param>
        /// <param name="slug">Slug to apply</param>
        /// <param name="languageId">Language ID</param>
        /// <param name="save"><c>true</c> will commit result to database.</param>
        /// <returns>
        /// The affected <see cref="UrlRecord"/> instance, either new or existing as tracked entity.
        /// </returns>
        public static Task <UrlRecord> ApplySlugAsync <T>(this IUrlService service, T entity, string slug, int languageId, bool save = false)
            where T : ISlugSupported
        {
            Guard.NotNull(entity, nameof(entity));

            var input = new ValidateSlugResult
            {
                Source     = entity,
                Slug       = slug,
                LanguageId = languageId
            };

            return(service.ApplySlugAsync(input, save));
        }
Beispiel #3
0
        protected internal virtual async Task <UrlRecord> ApplySlugAsync(ValidateSlugResult result, UrlRecordCollection prefetchedCollection, bool save = false)
        {
            if (!result.WasValidated)
            {
                throw new ArgumentException("Unvalidated slugs cannot be applied. Consider obtaining 'ValidateSlugResult' from 'ValidateSlugAsync()' method.", nameof(result));
            }

            if (string.IsNullOrWhiteSpace(result.Slug))
            {
                return(null);
            }

            var dirty      = false;
            var entry      = result.Found;
            var languageId = result.LanguageId ?? 0;

            if (entry != null && result.FoundIsSelf)
            {
                // Found record refers to requested entity
                if (entry.IsActive)
                {
                    // ...and is active. Do nothing, 'cause nothing changed.
                }
                else
                {
                    // ...and is inactive. Make it active
                    entry.IsActive = true;
                    dirty          = true;

                    // ...and make the current active one(s) inactive.
                    var currentActive = await GetActiveEntryFromStoreAsync();

                    if (currentActive != null)
                    {
                        currentActive.IsActive = false;
                    }
                }
            }

            if (entry == null || !result.FoundIsSelf)
            {
                // Create new entry because no entry was found or found one refers to another entity.
                // Because unvalidated slugs cannot be passed to this method we assume slug uniqueness.
                entry = new UrlRecord
                {
                    EntityId   = result.Source.Id,
                    EntityName = result.EntityName,
                    Slug       = result.Slug,
                    LanguageId = languageId,
                    IsActive   = true,
                };
            }

            if (entry != null && entry.IsTransientRecord())
            {
                // It's a freshly created record, add to set.
                _db.UrlRecords.Add(entry);

                // When we gonna save deferred, adding the new entry to our extra lookup
                // will ensure that subsequent validation does not miss new records.
                _extraSlugLookup[entry.Slug] = entry;

                dirty = true;
            }

            if (dirty && save)
            {
                await _db.SaveChangesAsync();
            }

            return(entry);

            async Task <UrlRecord> GetActiveEntryFromStoreAsync()
            {
                if (result.Source.Id > 0)
                {
                    if (prefetchedCollection != null)
                    {
                        var record = prefetchedCollection.Find(languageId, result.Source.Id);
                        if (record != null)
                        {
                            // Transient: was requested from store, but does not exist.
                            return(record.IsTransientRecord() ? null : record);
                        }
                    }

                    return(await _db.UrlRecords
                           .ApplyEntityFilter(result.Source, languageId, true)
                           .FirstOrDefaultAsync());
                }

                return(null);
            }
        }
Beispiel #4
0
 public Task <UrlRecord> ApplySlugAsync(ValidateSlugResult result, bool save = false)
 {
     return(ApplySlugAsync(result, _prefetchedCollections.Get(result.EntityName), save));
 }