Beispiel #1
0
        private async Task ProgressiveEditAsync(IEnumerable <EntityEditEntry> edits, string summary, bool isBot,
                                                bool strict, CancellationToken cancellationToken)
        {
            Debug.Assert(edits != null);
            var checkbaseRev = true;

            foreach (var prop in edits.GroupBy(e => e.PropertyName))
            {
                if (prop.Any(p => p.Value == null))
                {
                    throw new ArgumentException($"Detected null value in {prop} entries.", nameof(edits));
                }
                switch (prop.Key)
                {
                case nameof(DataType):
                    throw new NotSupportedException("Setting data type is not possible in progressive mode.");

                case nameof(Labels):
                    foreach (var p in prop)
                    {
                        var value   = (WbMonolingualText)p.Value;
                        var jresult = await Site.InvokeMediaWikiApiAsync(new MediaWikiFormRequestMessage(new
                        {
                            action = "wbsetlabel",
                            token = WikiSiteToken.Edit,
                            id = Id,
                            @new = Id == null ? FormatEntityType(Type) : null,
                            baserevid = checkbaseRev && LastRevisionId > 0 ? (int?)LastRevisionId : null,
                            bot = isBot,
                            summary = summary,
                            language = value.Language,
                            value = p.State == EntityEditEntryState.Updated ? value.Text : null,
                        }), cancellationToken);

                        LoadEntityMinimal(jresult["entity"]);
                        if (!strict)
                        {
                            checkbaseRev = false;
                        }
                    }
                    break;

                case nameof(Descriptions):
                    foreach (var p in prop)
                    {
                        var value   = (WbMonolingualText)p.Value;
                        var jresult = await Site.InvokeMediaWikiApiAsync(new MediaWikiFormRequestMessage(new
                        {
                            action = "wbsetdescription",
                            token = WikiSiteToken.Edit,
                            id = Id,
                            @new = Id == null ? FormatEntityType(Type) : null,
                            baserevid = checkbaseRev && LastRevisionId > 0 ? (int?)LastRevisionId : null,
                            bot = isBot,
                            summary = summary,
                            language = value.Language,
                            value = p.State == EntityEditEntryState.Updated ? value.Text : null,
                        }), cancellationToken);

                        LoadEntityMinimal(jresult["entity"]);
                        if (!strict)
                        {
                            checkbaseRev = false;
                        }
                    }
                    break;

                case nameof(Aliases):
                {
                    var entries = prop.GroupBy(t => ((WbMonolingualText)t.Value).Language);
                    foreach (var langGroup in entries)
                    {
                        var addExpr = MediaWikiHelper.JoinValues(langGroup
                                                                 .Where(e => e.State == EntityEditEntryState.Updated)
                                                                 .Select(e => ((WbMonolingualText)e.Value).Text));
                        var removeExpr = MediaWikiHelper.JoinValues(langGroup
                                                                    .Where(e => e.State == EntityEditEntryState.Removed)
                                                                    .Select(e => ((WbMonolingualText)e.Value).Text));
                        var jresult = await Site.InvokeMediaWikiApiAsync(new MediaWikiFormRequestMessage(new
                            {
                                action = "wbsetaliases",
                                token = WikiSiteToken.Edit,
                                id = Id,
                                @new = Id == null ? FormatEntityType(Type) : null,
                                baserevid = checkbaseRev && LastRevisionId > 0 ? (int?)LastRevisionId : null,
                                bot = isBot,
                                summary = summary,
                                language = langGroup.Key,
                                add = addExpr.Length == 0 ? null : addExpr,
                                remove = removeExpr.Length == 0 ? null : removeExpr,
                            }), cancellationToken);

                        LoadEntityMinimal(jresult["entity"]);
                        if (!strict)
                        {
                            checkbaseRev = false;
                        }
                    }
                    break;
                }

                case nameof(SiteLinks):
                {
                    var entries = prop.GroupBy(t => ((EntitySiteLink)t.Value).Site);
                    foreach (var siteGroup in entries)
                    {
                        string link = null, badges = null;
                        try
                        {
                            var item = siteGroup.Single();
                            if (item.State == EntityEditEntryState.Updated)
                            {
                                var value = (EntitySiteLink)item.Value;
                                link   = value.Title;
                                badges = MediaWikiHelper.JoinValues(value.Badges);
                            }
                        }
                        catch (InvalidOperationException)
                        {
                            throw new ArgumentException("One site can own at most one site link.", nameof(edits));
                        }
                        var jresult = await Site.InvokeMediaWikiApiAsync(new MediaWikiFormRequestMessage(new
                            {
                                action = "wbsetsitelink",
                                token = WikiSiteToken.Edit,
                                id = Id,
                                @new = Id == null ? FormatEntityType(Type) : null,
                                baserevid = checkbaseRev && LastRevisionId > 0 ? (int?)LastRevisionId : null,
                                bot = isBot,
                                summary = summary,
                                linksite = siteGroup.Key,
                                linktitle = link,
                                badges = badges,
                            }), cancellationToken);

                        LoadEntityMinimal(jresult["entity"]);
                        if (!strict)
                        {
                            checkbaseRev = false;
                        }
                    }
                    break;
                }

                case nameof(Claims):
                    foreach (var entry in prop.Where(e => e.State == EntityEditEntryState.Updated))
                    {
                        var value         = (Claim)entry.Value;
                        var claimContract = value.ToContract(false);
                        if (value.Id == null)
                        {
                            // New claim. We need to assign an ID manually.
                            // https://phabricator.wikimedia.org/T182573#3828344
                            if (Id == null)
                            {
                                // This is a new entity, so we need to create it first.
                                var jresult1 = await Site.InvokeMediaWikiApiAsync(new MediaWikiFormRequestMessage(new
                                {
                                    action = "wbeditentity",
                                    token = WikiSiteToken.Edit,
                                    @new = FormatEntityType(Type),
                                    bot = isBot,
                                    summary = (string)null,
                                    data = "{}"
                                }), cancellationToken);

                                if (!strict)
                                {
                                    checkbaseRev = false;
                                }
                                LoadEntityMinimal(jresult1["entity"]);
                            }
                            claimContract.Id = Utility.NewClaimGuid(Id);
                        }
                        var jresult = await Site.InvokeMediaWikiApiAsync(new MediaWikiFormRequestMessage(new
                        {
                            action = "wbsetclaim",
                            token = WikiSiteToken.Edit,
                            @new = Id == null ? FormatEntityType(Type) : null,
                            baserevid = checkbaseRev && LastRevisionId > 0 ? (int?)LastRevisionId : null,
                            bot = isBot,
                            summary = summary,
                            claim = Utility.WikiJsonSerializer.Serialize(claimContract),
                        }), cancellationToken);

                        // jresult["claim"] != null
                        LastRevisionId = (int)jresult["pageinfo"]["lastrevid"];
                        if (!strict)
                        {
                            checkbaseRev = false;
                        }
                    }
                    foreach (var batch in prop.Where(e => e.State == EntityEditEntryState.Removed)
                             .Select(e => ((Claim)e.Value).Id).Partition(50))
                    {
                        var jresult = await Site.InvokeMediaWikiApiAsync(new MediaWikiFormRequestMessage(new
                        {
                            action = "wbremoveclaims",
                            token = WikiSiteToken.Edit,
                            id = Id,
                            @new = Id == null ? FormatEntityType(Type) : null,
                            baserevid = checkbaseRev && LastRevisionId > 0 ? (int?)LastRevisionId : null,
                            bot = isBot,
                            summary = summary,
                            claim = MediaWikiHelper.JoinValues(batch),
                        }), cancellationToken);

                        LastRevisionId = (int)jresult["pageinfo"]["lastrevid"];
                        if (!strict)
                        {
                            checkbaseRev = false;
                        }
                    }
                    break;

                default:
                    throw new ArgumentException($"Unrecognized {nameof(Entity)} property name: {prop.Key}.");
                }
            }

            void LoadEntityMinimal(JToken jentity)
            {
                Debug.Assert(jentity != null);
                Id             = (string)jentity["id"];
                Type           = SerializableEntity.ParseEntityType((string)jentity["type"]);
                LastRevisionId = (int)jentity["lastrevid"];
            }
        }
Beispiel #2
0
        // postEditing: Is the entity param from the response of wbeditentity API call?
        internal void LoadFromContract(Contracts.Entity entity, EntityQueryOptions options, bool isPostEditing)
        {
            var extensionData = entity.ExtensionData ?? emptyExtensionData;
            var id            = entity.Id;

            Debug.Assert(id != null);
            if ((options & EntityQueryOptions.SuppressRedirects) != EntityQueryOptions.SuppressRedirects &&
                Id != null && Id != id)
            {
                // The page has been overwritten, or deleted.
                //logger.LogWarning("Detected change of page id for [[{Title}]]: {Id1} -> {Id2}.", Title, Id, id);
            }
            var serializable = extensionData.ContainsKey("missing")
                ? null
                : SerializableEntity.Load(entity);

            Id             = id;
            Exists         = serializable != null;
            Type           = EntityType.Unknown;
            PageId         = -1;
            NamespaceId    = -1;
            Title          = null;
            LastModified   = DateTime.MinValue;
            LastRevisionId = 0;
            Labels         = null;
            Aliases        = null;
            Descriptions   = null;
            SiteLinks      = null;
            QueryOptions   = options;
            if (serializable == null)
            {
                return;
            }
            serializable = SerializableEntity.Load(entity);
            Type         = serializable.Type;
            DataType     = serializable.DataType;
            if ((options & EntityQueryOptions.FetchInfo) == EntityQueryOptions.FetchInfo)
            {
                if (!isPostEditing)
                {
                    // wbeditentity response does not have these properties.
                    PageId       = (int)extensionData["pageid"];
                    NamespaceId  = (int)extensionData["ns"];
                    Title        = (string)extensionData["title"];
                    LastModified = (DateTime)extensionData["modified"];
                }
                LastRevisionId = (int)extensionData["lastrevid"];
            }
            if ((options & EntityQueryOptions.FetchLabels) == EntityQueryOptions.FetchLabels)
            {
                Labels = serializable.Labels;
                if (Labels.Count == 0)
                {
                    Labels = emptyStringDict;
                }
                else
                {
                    Labels.IsReadOnly = true;
                }
            }
            if ((options & EntityQueryOptions.FetchAliases) == EntityQueryOptions.FetchAliases)
            {
                Aliases = serializable.Aliases;
                if (Aliases.Count == 0)
                {
                    Aliases = emptyStringsDict;
                }
                else
                {
                    Aliases.IsReadOnly = true;
                }
            }
            if ((options & EntityQueryOptions.FetchDescriptions) == EntityQueryOptions.FetchDescriptions)
            {
                Descriptions = serializable.Descriptions;
                if (Descriptions.Count == 0)
                {
                    Descriptions = emptyStringDict;
                }
                else
                {
                    Descriptions.IsReadOnly = true;
                }
            }
            if ((options & EntityQueryOptions.FetchSiteLinks) == EntityQueryOptions.FetchSiteLinks)
            {
                SiteLinks = serializable.SiteLinks;
                if (SiteLinks.Count == 0)
                {
                    SiteLinks = emptySiteLinks;
                }
                else
                {
                    SiteLinks.IsReadOnly = true;
                }
            }
            if ((options & EntityQueryOptions.FetchClaims) == EntityQueryOptions.FetchClaims)
            {
                Claims = serializable.Claims;
                if (Claims.Count == 0)
                {
                    Claims = emptyClaims;
                }
                else
                {
                    Claims.IsReadOnly = true;
                }
            }
        }