Exemplo n.º 1
0
        private async Task InternalCopyFileData(MediaFile file, MediaFile copy)
        {
            await _storageProvider.SaveAsync(copy, MediaStorageItem.FromStream(await _storageProvider.OpenReadAsync(file)));

            await _imageCache.DeleteAsync(copy);

            // Tags.
            await _db.LoadCollectionAsync(file, (MediaFile x) => x.Tags);

            var existingTagsIds = copy.Tags.Select(x => x.Id).ToList();

            foreach (var tag in file.Tags)
            {
                if (!existingTagsIds.Contains(tag.Id))
                {
                    copy.Tags.Add(tag);
                    existingTagsIds.Add(tag.Id);
                }
            }

            // Localized values.
            var languages = _languageService.GetAllLanguages(true);

            foreach (var language in languages)
            {
                var title = file.GetLocalized(x => x.Title, language.Id, false, false).Value;
                if (title.HasValue())
                {
                    await _localizedEntityService.ApplyLocalizedValueAsync(copy, x => x.Title, title, language.Id);
                }

                var alt = file.GetLocalized(x => x.Alt, language.Id, false, false).Value;
                if (alt.HasValue())
                {
                    await _localizedEntityService.ApplyLocalizedValueAsync(copy, x => x.Alt, alt, language.Id);
                }
            }

            await _db.SaveChangesAsync();

            _db.DetachEntities <MediaTag>();
        }
Exemplo n.º 2
0
        protected virtual async Task TrackManyCoreAsync(IEnumerable <MediaTrack> tracks, string albumName)
        {
            Guard.NotNull(tracks, nameof(tracks));

            if (!tracks.Any())
            {
                return;
            }

            using (var scope = new DbContextScope(_db, minHookImportance: HookImportance.Important, autoDetectChanges: false))
            {
                // Get the album (necessary later to set FolderId)...
                MediaFolderNode albumNode = albumName.HasValue()
                    ? _folderService.GetNodeByPath(albumName)?.Value
                    : null;

                // Get distinct ids of all detected files...
                var mediaFileIds = tracks.Select(x => x.MediaFileId).Distinct().ToArray();

                // fetch these files from database...
                var query = _db.MediaFiles
                            .Include(x => x.Tracks)
                            .Where(x => mediaFileIds.Contains(x.Id));

                var isInstallation = !EngineContext.Current.Application.IsInstalled;
                if (isInstallation)
                {
                    query = query.Where(x => x.Version == 1);
                }

                var files = await query.ToDictionaryAsync(x => x.Id);

                // for each media file relation to an entity...
                foreach (var track in tracks)
                {
                    // fetch the file from local dictionary by its id...
                    if (files.TryGetValue(track.MediaFileId, out var file))
                    {
                        if (isInstallation)
                        {
                            // set album id as folder id (during installation there are no sub-folders)
                            file.FolderId = albumNode?.Id;

                            // remember that we processed tracks for this file already
                            file.Version = 2;
                        }

                        if (track.Album.IsEmpty())
                        {
                            if (albumNode != null)
                            {
                                // Overwrite track album if scope album was passed.
                                track.Album = albumNode.Name;
                            }
                            else if (file.FolderId.HasValue)
                            {
                                // Determine album from file
                                albumNode   = _folderService.FindAlbum(file)?.Value;
                                track.Album = albumNode?.Name;
                            }
                        }

                        if (track.Album.IsEmpty())
                        {
                            continue; // cannot track without album
                        }
                        if ((albumNode ?? _folderService.FindAlbum(file)?.Value)?.CanDetectTracks == false)
                        {
                            continue; // should not track in albums that do not support track detection
                        }
                        // add or remove the track from file
                        if (track.Operation == MediaTrackOperation.Track)
                        {
                            file.Tracks.Add(track);
                        }
                        else
                        {
                            var dbTrack = file.Tracks.FirstOrDefault(x => x == track);
                            if (dbTrack != null)
                            {
                                file.Tracks.Remove(track);
                                _db.TryChangeState(dbTrack, EfState.Deleted);
                            }
                        }

                        if (file.Tracks.Count > 0)
                        {
                            // A file with tracks can NEVER be transient
                            file.IsTransient = false;
                        }
                        else if (_makeFilesTransientWhenOrphaned)
                        {
                            // But an untracked file can OPTIONALLY be transient
                            file.IsTransient = true;
                        }
                    }
                }

                // Save whole batch to database
                int num = await _db.SaveChangesAsync();

                if (num > 0)
                {
                    // Breathe
                    _db.DetachEntities <MediaFile>(deep: true);
                }
            }
        }
        public async Task MigrateAsync(IEnumerable <LocaleResourceEntry> entries, bool updateTouchedResources = false)
        {
            Guard.NotNull(entries, nameof(entries));

            if (!entries.Any() || !_languages.Any())
            {
                return;
            }

            using (var scope = new DbContextScope(_db, autoDetectChanges: false, minHookImportance: HookImportance.Essential))
            {
                var langMap = (await _languages
                               .ToListAsync())
                              .ToDictionarySafe(x => x.LanguageCulture.EmptyNull().ToLower());

                var toDelete = new List <LocaleStringResource>();
                var toUpdate = new List <LocaleStringResource>();
                var toAdd    = new List <LocaleStringResource>();

                bool IsEntryValid(LocaleResourceEntry entry, Language targetLang)
                {
                    if (entry.Lang == null)
                    {
                        return(true);
                    }

                    var sourceLangCode = entry.Lang.ToLower();

                    if (targetLang != null)
                    {
                        var culture = targetLang.LanguageCulture;
                        if (culture == sourceLangCode || culture.StartsWith(sourceLangCode + "-"))
                        {
                            return(true);
                        }
                    }
                    else
                    {
                        if (langMap.ContainsKey(sourceLangCode))
                        {
                            return(true);
                        }

                        if (langMap.Keys.Any(k => k.StartsWith(sourceLangCode + "-", StringComparison.OrdinalIgnoreCase)))
                        {
                            return(true);
                        }
                    }

                    return(false);
                }

                // Remove all entries with invalid lang identifier
                var invalidEntries = entries.Where(x => !IsEntryValid(x, null));
                if (invalidEntries.Any())
                {
                    entries = entries.Except(invalidEntries).ToArray();
                }

                foreach (var lang in langMap)
                {
                    var validEntries = entries.Where(x => IsEntryValid(x, lang.Value)).ToArray();
                    foreach (var entry in validEntries)
                    {
                        var dbRes = GetResource(entry.Key, lang.Value.Id, toAdd, out bool isLocal);

                        if (dbRes == null && entry.Value.HasValue() && !entry.UpdateOnly)
                        {
                            // ADD action
                            toAdd.Add(new LocaleStringResource {
                                LanguageId = lang.Value.Id, ResourceName = entry.Key, ResourceValue = entry.Value
                            });
                        }

                        if (dbRes == null)
                        {
                            continue;
                        }

                        if (entry.Value == null)
                        {
                            // DELETE action
                            if (isLocal)
                            {
                                toAdd.Remove(dbRes);
                            }
                            else
                            {
                                toDelete.Add(dbRes);
                            }
                        }
                        else
                        {
                            if (isLocal)
                            {
                                dbRes.ResourceValue = entry.Value;
                                continue;
                            }

                            // UPDATE action
                            if (updateTouchedResources || !dbRes.IsTouched.GetValueOrDefault())
                            {
                                dbRes.ResourceValue = entry.Value;
                                toUpdate.Add(dbRes);
                                if (toDelete.Contains(dbRes))
                                {
                                    toDelete.Remove(dbRes);
                                }
                            }
                        }
                    }
                }

                if (toAdd.Any() || toDelete.Any())
                {
                    // add new resources to context
                    _resources.AddRange(toAdd);

                    // remove deleted resources
                    _resources.RemoveRange(toDelete);

                    // save now
                    int affectedRows = await _db.SaveChangesAsync();

                    _db.DetachEntities <Language>();
                    _db.DetachEntities <LocaleStringResource>();
                }
            }
        }