Module:Chapters

Documentation for this module may be created at Module:Chapters/doc

local p = {}

function p.getChaptersByAuthor(frame)
    local mw = mw
    local currentTitle = mw.title.getCurrentTitle()
    local entityId = mw.wikibase.getEntityIdForTitle(currentTitle.fullText)
    if not entityId then
        return "[[Category:Author pages incorrectly using Module:Chapters]]"
    end

    local entity = mw.wikibase.getEntity(entityId)
    if not entity or not entity.claims then
        return "[[Category:Author pages incorrectly using Module:Chapters]]"
    end

    local chapters = {}
    local index = 0  -- Initialize index for insertion order

    -- Get the list of works authored (P11)
    local authoredClaims = entity.claims['P11']
    if not authoredClaims then
        return "[[Category:Author pages incorrectly using Module:Chapters]]"
    end

    -- The sitelink prefix
    local sitelinkPrefix = 'works'

    for _, claim in ipairs(authoredClaims) do
        local workId = claim.mainsnak and claim.mainsnak.datavalue and claim.mainsnak.datavalue.value and claim.mainsnak.datavalue.value.id
        if workId then
            local workEntity = mw.wikibase.getEntity(workId)
            if workEntity and workEntity.claims then
                -- Check if the work is a chapter in a book by checking for P9 (part of publication)
                if workEntity.claims['P9'] then
                    local bookClaim = workEntity.claims['P9'][1]
                    local bookId = bookClaim.mainsnak and bookClaim.mainsnak.datavalue and bookClaim.mainsnak.datavalue.value and bookClaim.mainsnak.datavalue.value.id
                    if bookId then
                        -- Get labels and sitelinks for the chapter and the book
                        local chapterTitle = mw.wikibase.getLabel(workId) or "Unknown Chapter"
                        local bookTitle = mw.wikibase.getLabel(bookId) or "Unknown Book"

                        local chapterSitelink = mw.wikibase.getSitelink(workId, sitelinkPrefix) or nil
                        local bookSitelink = mw.wikibase.getSitelink(bookId, sitelinkPrefix) or nil

                        -- Build the links or use plain text if no sitelink is available
                        local chapterLink = chapterSitelink and string.format("[[%s|%s]]", chapterSitelink, chapterTitle) or chapterTitle
                        local bookLink = bookSitelink and string.format("[[%s|%s]]", bookSitelink, bookTitle) or bookTitle

                        -- Retrieve publication date (P29) from the book item
                        local bookEntity = mw.wikibase.getEntity(bookId)
                        local publicationDateYear = 0 -- default

                        if bookEntity and bookEntity.claims and bookEntity.claims['P29'] and bookEntity.claims['P29'][1] then
                            local publicationDateClaim = bookEntity.claims['P29'][1]
                            local pubDateSnak = publicationDateClaim.mainsnak
                            if pubDateSnak and pubDateSnak.datavalue and pubDateSnak.datavalue.value and pubDateSnak.datavalue.value.time then
                                local publicationDate = pubDateSnak.datavalue.value.time
                                -- Remove the '+' at the beginning
                                publicationDate = string.sub(publicationDate, 2)
                                -- Extract the year
                                publicationDateYear = tonumber(string.sub(publicationDate, 1, 4)) or 0
                            end
                        end

                        -- Prepare the book display title including the publication date
                        local bookDisplayTitle = bookLink
                        if publicationDateYear > 0 then
                            bookDisplayTitle = string.format("%s (%d)", bookLink, publicationDateYear)
                        end

                        -- Retrieve pages (P6) from the chapter item
                        local pages = ""
                        local pagesClaim = workEntity.claims['P6']
                        if pagesClaim and pagesClaim[1] then
                            pages = pagesClaim[1].mainsnak and pagesClaim[1].mainsnak.datavalue and pagesClaim[1].mainsnak.datavalue.value or ""
                        end

                        -- Prepare the pages text
                        local pagesText = ""
                        if pages ~= "" then
                            pagesText = ", pp. " .. pages
                        end

                        -- Prepare the formatted entry without parentheses and with publication date
                        local formattedEntry = string.format("* %s\n*: Appears in ''%s''%s", chapterLink, bookDisplayTitle, pagesText)

                        -- Insert the formatted entry into the chapters table with sort keys
                        index = index + 1  -- Increment index for insertion order
                        table.insert(chapters, {
                            formattedEntry = formattedEntry,
                            sortKey = publicationDateYear > 0 and publicationDateYear or 9999,
                            secondarySortKey = index
                        })
                    end
                end
            end
        end
    end

    if #chapters == 0 then
        return "[[Category:Author pages incorrectly using Module:Chapters]]"
    end

    -- Sort the chapters chronologically by publication date, oldest first
    -- If publication dates are the same, sort by insertion order
    table.sort(chapters, function(a, b)
        if a.sortKey == b.sortKey then
            return a.secondarySortKey < b.secondarySortKey
        else
            return a.sortKey < b.sortKey
        end
    end)

    -- Concatenate the formatted entries into a string to display
    local result = {}
    for _, chapter in ipairs(chapters) do
        table.insert(result, chapter.formattedEntry)
    end
    return table.concat(result, "\n")
end

return p