Модуль:Новый персонаж

Материал из Кадровый состав НКВД 1935-1939
Версия от 14:37, 17 апреля 2021; StasR (обсуждение | вклад)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Для документации этого модуля может быть создана страница Модуль:Новый персонаж/doc

local p = {}
tools = require 'Module:Tools'
global = mw.ext.luaglobal;
local cq = mw.ext.cargo.query
local collect = require 'Module:Collect'

local function pageInCargo( name )
	local query = cq( 'designations_journal',
			'_pageName',
			{ where = 'person = "' .. name .. '"' }
		)
	for i, v in ipairs( query ) do
		query[i] = v._pageName
	end
	local query1 = cq( 'ranks_journal',
			'_pageName',
			{ where = 'person = "' .. name .. '"' }
		)
	for _, v in ipairs( query1 ) do
		query[#query+1] = v._pageName
	end
	local query1 = cq( 'prizes_journal',
			'_pageName',
			{ where = 'person = "' .. name .. '"' }
		)
	for _, v in ipairs( query1 ) do
		query[#query+1] = v._pageName
	end
	local query1 = cq( 'mention_journal',
			'_pageName',
			{ where = 'person = "' .. name .. '"' }
		)
	for _, v in ipairs( query1 ) do
		query[#query+1] = v._pageName
	end

	table.sort( query )
	local i, v = 1, nil
	while i <= #query do
		if query[i] == v then
			table.remove( query, i )
		else
			v = query[i]
			i = i + 1
		end
	end
	return query
end

-- Побочный эффект :-)
local refErr = {}
local fpart, iopart, index, fioPattern
local hasMinus, isPattern, hasIndex, hasEndPoint

function p.anal( original )
	local name = original
	local out = {}
	if string.sub( name, -4, -1 ) == ' (-)' then
		hasMinus = true
		name = string.sub( name, 1, -5 )
	else
		index = mw.ustring.match( name, ' (%([IVX]+%))$' )
		if index then
			name = string.sub( name, 1, -2 - string.len( index ) )
			hasIndex = true
		end
	end
	name = mw.ustring.gsub( name, '%.%.%.([^%.])', '#\1' )
	name = mw.ustring.gsub( name, '%.%.%.$', '#' )
	if string.match( name .. ' ', '[,#%.][^ ]' ) then
		refErr[#refErr+1] = '<p class="error">После запятой, точки и многоточия пробелы обязательны!</p>'
		name = mw.ustring.gsub( name, '([,#%.])([^ ])', '%1 %2' )
	end
	if string.sub( name, -1, -1) == '?' then
		hasEndPoint = true
		name = string.sub( name, 1, -2 )
	end
	fpart, iopart = string.match( name, '^([^,]+), (.+)$' )
	if not fpart then
		fpart = name
		iopart = '#'
		isPattern = true
	elseif string.match( name, '[#%.]' ) then
		isPattern = true
	end

	fioPattern = fpart .. ', ' .. string.gsub( iopart, '[#%.]', '%%' )

--[[
	if not string.match( name, ',' ) then
		isPattern = true
		pattern = name .. ', %'
	elseif string.match( name, '%.' ) then
		isPattern = true
		pattern = mw.ustring.gsub( name, '%.', '%%' )
	else
		pattern = name
	end
	if string.sub( pattern, -1, -1 ) ~= '%' then
		pattern = pattern .. ' %'
	end
--]]
end

function p.existsPage( name, index )
	return mw.title.new( name .. ' ' .. (index or ''), 0 ).exists
end

function p.searchFio( name, index, isPattern )
	if index then
		index = ' AND disambig="' .. index .. '"'
	else
		index = ''
	end
	if isPattern then
		name = 'name LIKE "' .. name .. '"'
	else
		name = 'name="' .. name .. '"'
	end
	local query = cq( 'names', '_pageName, name, disambig',
		{ where = name .. index, limit = 11, orderBy = 'name, disambig' } )
	return query
end

--[==[
Упрощенный аналог Collect.dbtable для работы с таблицей names_table
Пока не выкидываем лишее — например, перебор gFio
--]==]

local function collectNames( gFio )
	local where = {}
	local tmp
	for _, fio in ipairs( gFio ) do
		tmp = 'lastN="' .. fio.l .. '"'
		if fio.f  ~= '' then
			tmp = tmp .. ' AND (firstN IS NULL OR firstN LIKE "' .. mw.ustring.sub( fio.f, 1, 1 ) .. '%")'
		end
		if fio.m ~= '' then
			tmp = tmp .. ' AND (middleN IS NULL OR middleN LIKE "' .. mw.ustring.sub( fio.m, 1, 1 ) .. '%")'
		end
		if fio.d and fio.d ~= '(*)' then -- для (*) все соответствуют
			tmp = tmp .. ' AND (disambig IS NULL OR disambig="' .. fio.d .. '")'
		end
		where[#where+1] = tmp
	end
	where = table.concat( where, ' OR ' )

	local query = cq( 'names_table', '_pageName, lastN, firstN, middleN, disambig', { where = where, limit = 1001 } )
--	do return query end
	local flen, mlen, fcmp, mcmp
	local fdb, mdb
	local eqCount = 0

	for _, row in ipairs( query ) do
		fdb, mdb = row.firstN or '', row.middleN or ''
		flen, mlen = string.len( fdb ), string.len( mdb )
		for _, fio in ipairs( gFio ) do
			if ( row.disambig == ( fio.d or '' ) or fio.d == '(*)' ) and fio.f == fdb and fio.m == mdb then
				row['#eq'] = true
			elseif row.disambig~='' and fio.d and row.disambig ~= fio.d then
				-- не подходит
			else
				fcmp, mcmp = math.min( flen, string.len( fio.f ) ), math.min( mlen, string.len( fio.m ) )
				if string.sub( fio.f, 1, fcmp ) == string.sub( fdb, 1, fcmp )
						and string.sub( fio.m, 1, mcmp ) == string.sub( mdb, 1, mcmp ) then
					row['#ap'] = true
				end
			end
		end
		if row['#eq'] or row['#ap'] then
			eqCount = eqCount + 1
		end

	end
	-- итого у нас в query готовая выборка, где у некоторых строк стоят флаги #eq и #ap
	return query, eqCount
end

local function namesDisplay( namesQuery, namesCount )
	if namesCount == 0 then
		return '<p class="nkvd-no-names">Отсутствуют соответствующие условиям персоналии.</p>'
	end
	local out = {}
	for _, row in ipairs( namesQuery ) do
		if row['#eq'] or row['#ap'] then
			local person, i, o = row.lastN, row.firstN, row.middleN
			if  i ~= '' or o  ~= '' then
				person = person .. ', '
				if i == '' then
					i = '...'
				elseif mw.ustring.len( i ) == 1 then
					i = i .. '.'
				end
				person = person .. i
				if o ~= '' then
					if mw.ustring.len( o ) == 1 then
						o = o .. '.'
					end
					person = person .. ' ' .. o
				end
			end
			if row.disambig ~= '' then
				person = person .. ' <span class="nkvd-idx">' .. row.disambig .. '</span>'
			end
			out[#out+1] = row._pageName .. '|' .. person
		end
	end
	return '[[' .. table.concat( out, ']] &bull; [[' ) .. ']]'
end


p[''] = function ( frame )
	local args = frame.args
	local redlink, creatype = args[1], args [2]
	local page = mw.title.getCurrentTitle()
	local original = page.text
--		frame:callParserFunction{ name = 'DISPLAYTITLE', args = original .. ' ntcn' }
	local out = {}
	local fio_l, fio_f, fio_m, fio_d, fio_warn, fio_base = tools.splitName( original, true )
	if not fio_l then
		return '<div class=nkvd-error><p><big><b>Не удалось разобрать заголовок страницы.</b></big></p>' .. fio_f .. '</div>'
	end
	local tmp, errorpage
	for _, warn in ipairs( fio_warn ) do
		errorpage = tmp or string.sub( warn, 1, 1 ) ~= ' '
		out[#out+1] = '<p class=error>' .. warn .. '</p>'
	end
	if errorpage then
		out[#out+1] = '<div class=nkvd-error>Для продолжения работы исправьте ссылку и вновь вызовите эту страницу.</div>'
	elseif #fio_warn ~= 0 then
		out[#out+1] = '<p>При необходимости исправьте ссылку и вновь вызовите эту страницу.</p>'
	end

	local nsQuery, namesakes, ns0disambig = {}, {}
	if not errorpage then
		local where = 'lastN="' .. fio_l .. '"'
		if fio_f == '' then
			where = where .. ' AND firstN IS NULL'
		else
			where = where .. ' AND firstN="' .. fio_f ..'"'
		end
		if fio_m == '' then
			where = where .. ' AND middleN IS NULL'
		else
			where = where .. ' AND middleN="' .. fio_m ..'"'
		end
		nsQuery = cq( 'names_table', '_pageName, lastN, firstN, middleN, disambig', { where = where } )
		for _, row in ipairs( nsQuery ) do
			namesakes[row.disambig] = row
		end
		if not namesakes['']  then
			tmp = mw.title.new( fio_base ):getContent()
			ns0disambig = mw.ustring.match( tmp or '', '%{%{%s*[Нн]еоднозначность' )
--			out[#out+1] = '\n\n\n«««' .. (tmp or '—') .. '»»»\n\n\n'
		end
	end

	if fio_d == '(*)' then
		out[#out+1] = '<div class=nkvd-error><b>Ссылки, созданные шаблоном «[[Шаблон:Персона*|персона*]]»'
			.. ' («[[Шаблон:Упоминание*|упоминание*]]»), не должны использоваться для создания страниц.</b><br>'
		if not errorpage then
			if #nsQuery == 0 and not ns0disambig then
				out[#out+1] = 'Страницы-тезки отсутствуют в базе, для создания страницы достаточно'
					.. ' убрать «*» из названия шаблона и вновь вызвать данную страницу'
			elseif ns0disambig then
				out[#out+1] = 'Уже существует [[' .. fio_base .. '|страница разрешения неоднозначности]]'
					.. ' по этому имени, для создания страницы персоналии нужно убрать «*» из названия шаблона'
					.. ' и добавить к имени персоналии первый свободный (или нужный из имеющихся) номер тезки'
			elseif namesakes[''] then
				if #nsQuery > 1 then
					out[#out+1] = '<big>Существующий набор страниц тезок находится в непредусмотренном состоянии.'
						.. ' Требуется компетентное вмешательство!</big>'
				else
					out[#out+1] = 'Сейчас существует единственная персоналия с таким именем,'
						.. ' и создание тезки потребует усилий. Прежде всего потребуется убрать «*»'
						.. ' из названия шаблона, вслед за именем персоналии поставить через пробел «(II)»'
						.. ' и вновь перейти по ссылке сюда'
				end
			end
		end
		out[#out+1] = '</div>'
		errorpage = true
	end


	local prizesQuery, prizesCount = collect.dbtable( { { l=fio_l, f=fio_f, m=fio_m, d=fio_d } },
		'prizes_table',
		'cDate, cDate__precision, _pageName, reference, prize, prizeNumber, origin, alias, podvig, nLast, nFirst, nMiddle, nDisambig, nPrecision',
		nil )
	local ranksQuery, ranksCount = collect.dbtable( { { l=fio_l, f=fio_f, m=fio_m, d=fio_d } },
		'ranks_table',
		'cDate, cDate__precision, _pageName, reference, rank, origin, alias, nLast, nFirst, nMiddle, nDisambig, nPrecision',
		nil )
	local designationsQuery, designationsCount  = collect.dbtable( { { l=fio_l, f=fio_f, m=fio_m, d=fio_d } },
		'designations_table',
		'cDate, cDate__precision, _pageName, reference, unit, position, segment, origin, article, dismissal_type, formula, alias, nLast, nFirst, nMiddle, nDisambig, nPrecision',
		nil )
	local mentionsQuery, mentionsCount = collect.dbtable( { { l=fio_l, f=fio_f, m=fio_m, d=fio_d } },
		'mentions_table',
		'cDate, cDate__precision, _pageName, reference, comment, nLast, nFirst, nMiddle, nDisambig, nPrecision',
		nil )
	local namesQuery, namesCount = collectNames( { { l=fio_l, f=fio_f, m=fio_m, d=fio_d } } )
	if redlink then
		out[#out+1] = '<div style="width: 100%; box-sizing: border-box; border:1px dotted black; background-color: #f8f4ff; padding: 0.5em; margin-bottom: 0.5em;">'
	else
		out[#out+1] = '__NOTOC__\n<h2>Справочная информация</h2><div>'
	end
	out[#out+1] = '<table style="width: 100%;"><tr>'
	if namesCount == 0 then
		out[#out+1] = '<td style="width: 20%; border:4px solid #ccc; padding: 4px; text-align: center">Нет страниц персоналий с таким именем</td>'
	else
		out[#out+1] = '<td  class="mw-customtoggle-names" style="font-weight:bold; background-color:#e0e0F8; width: 20%; border:4px solid #ccf; padding: 4px; text-align: center; color: rgb(6, 69, 173); ">Список персоналий</td>'
	end
	if designationsCount == 0 then
		out[#out+1] = '<td style="width: 20%; border:4px solid #ccc; padding: 4px; text-align: center">Нет записей о службе</td>'
	else
		out[#out+1] = '<td  class="mw-customtoggle-designations" style="font-weight:bold; background-color:#e0e0F8; width: 20%; border:4px solid #ccf; padding: 4px; text-align: center; color: rgb(6, 69, 173); ">Записи о службе</td>'
	end
	if ranksCount == 0 then
		out[#out+1] = '<td style="width: 20%; border:4px solid #ccc; padding: 4px; text-align: center">Нет записей о званиях</td>'
	else
		out[#out+1] = '<td class="mw-customtoggle-ranks" style="font-weight:bold; background-color:#e0e0F8; width: 20%; border:4px solid #ccf; padding: 4px; text-align: center; color: rgb(6, 69, 173); ">Записи о званиях</td>'
	end
	if prizesCount == 0 then
		out[#out+1] = '<td style="width: 20%; border:4px solid #ccc; padding: 4px; text-align: center">Нет записей о награждениях</td>'
	else
		out[#out+1] = '<td class="mw-customtoggle-prizes" style="font-weight:bold; background-color:#e0e0F8; width: 20%; border:4px solid #ccf; padding: 4px; text-align: center; color: rgb(6, 69, 173); ">Записи о награждениях</td>'
	end
	if mentionsCount == 0 then
		out[#out+1] = '<td style="width: 20%; border:4px solid #ccc; padding: 4px; text-align: center">Нет иных упоминаний</td>'
	else
		out[#out+1] = '<td class="mw-customtoggle-mentions" style="font-weight:bold; background-color:#e0e0F8; width: 20%; border:4px solid #ccf; padding: 4px; text-align: center; color: rgb(6, 69, 173); ">Иные упоминания</td>'
	end
	out[#out+1] = '</tr></table>'
	if namesCount ~= 0 then
		out[#out+1] = '<div id="mw-customcollapsible-names" class="mw-collapsible" style="border:1px solid #ccc; box-sizing: border-box; padding: 3px; margin-bottom: 0.5em;">'
		out[#out+1] = '<div class="mw-customtoggle-names" style="float: right; margin: 0 0.5em; font-size: 120%; font-weight: bold; cursor:pointer; ">&times;</div>'
		out[#out+1] = '<h3>Страницы персоналий</h3>'
		out[#out+1] = namesDisplay( namesQuery, namesCount )
		out[#out+1] = mw.getCurrentFrame():extensionTag( 'references' )
		out[#out+1] = '</div>'
	end
	if designationsCount ~= 0 then
		out[#out+1] = '<div id="mw-customcollapsible-designations" class="mw-collapsible mw-collapsed" style="display: none; border:1px solid #ccc; box-sizing: border-box; padding: 3px; margin-bottom: 0.5em;">'
		out[#out+1] = '<div class="mw-customtoggle-designations" style="float: right; margin: 0 0.5em; font-size: 120%; font-weight: bold; cursor:pointer; ">&times;</div>'
		out[#out+1] = '<h3>Записи о прохождении службы</h3>'
		out[#out+1] = require ('Модуль:Отображение назначений').display( designationsQuery, designationsCount, true )
		out[#out+1] = mw.getCurrentFrame():extensionTag( 'references' )
		out[#out+1] = '</div>'
	end
	if ranksCount ~= 0 then
--		do return (mw.dumpObject(ranksQuery )) end
		out[#out+1] = '<div id="mw-customcollapsible-ranks" class="mw-collapsible mw-collapsed" style="display: none; border:1px solid #ccc; box-sizing: border-box; padding: 3px; margin-bottom: 0.5em;">'
		out[#out+1] = '<div class="mw-customtoggle-ranks" style="float: right; margin: 0 0.5em; font-size: 120%; font-weight: bold; cursor:pointer; ">&times;</div>'
		out[#out+1] = '<h3>Записи о званиях</h3>'
		out[#out+1] = require ('Модуль:Отображение званий').display( ranksQuery, ranksCount, true )
		out[#out+1] = mw.getCurrentFrame():extensionTag( 'references' )
		out[#out+1] = '</div>'
	end
	if prizesCount ~= 0 then
		out[#out+1] = '<div id="mw-customcollapsible-prizes" class="mw-collapsible mw-collapsed" style="display: none; border:1px solid #ccc; box-sizing: border-box; padding: 3px; margin-bottom: 0.5em;">'
		out[#out+1] = '<div class="mw-customtoggle-prizes" style="float: right; margin: 0 0.5em; font-size: 120%; font-weight: bold; cursor:pointer; ">&times;</div>'
		out[#out+1] = '<h3>Записи о награждениях</h3>'
		out[#out+1] = require ('Модуль:Отображение наград').display( prizesQuery, prizesCount, true )
		out[#out+1] = mw.getCurrentFrame():extensionTag( 'references' )
		out[#out+1] = '</div>'
	end
	if mentionsCount ~= 0 then
		out[#out+1] = '<div id="mw-customcollapsible-mentions" class="mw-collapsible mw-collapsed" style="display: none; border:1px solid #ccc; box-sizing: border-box; padding: 3px; margin-bottom: 0.5em;">'
		out[#out+1] = '<div class="mw-customtoggle-mentions" style="float: right; margin: 0 0.5em; font-size: 120%; font-weight: bold; cursor:pointer; ">&times;</div>'
		out[#out+1] = '<h3>Иные упоминания</h3>'
		out[#out+1] = require ('Модуль:Отображение упоминаний').display( mentionsQuery, mentionsCount, true )
		out[#out+1] = mw.getCurrentFrame():extensionTag( 'references' )
		out[#out+1] = '</div>'
	end

--[==[
fio_d = '' / '(*)' / '(N)'
db[''] = нет / есть
page[''] = нет / неодн. / страница




--]==]


	out[#out+1] = require( 'Module:Toolbar' )( fio_l, fio_f, fio_m )
	do
		out[#out+1] = '</div>'
		return table.concat( out, '\n' )
	end




	p.anal( original )




	-- простая красная ссылка
	if not (hasIndex or hasMinus or isPattern or hasEndPoint) then
		-- на всякий случай проверяем отсутствие страницы с индексом «(I)»
		local children = p.searchFio( name )
		if #children ~= 0 or p.existsPage( name, '(I)' ) then
			refErr[#refErr+1] = '<p class="error">Эта страница должна быть страницей разрешения неоднозначностей.</p>'
		end

	end
	if index == '(II)' then -- предполагаем создание первого тезки
		-- Предлагаемые шаги.
		-- 1) измените все существующие ссылки c root на root-1
		-- 2) переименуйте root в root-1
		-- 3) измените содержимое root
	end
	return frame.args[1]
end



while false do
	local u = mw.text.split( name, ' ' )
	local idx = u[#u]
	if  not string.match( idx, '^%([IVX]+%)$' ) then   --false and
		return tools.errorMsg( 'Новый тезка',
			'В заголовке страницы отсутствует номер тезки',
			'Этот шаблон помогает создавать страницы для тезок существующих в справочнике'
				.. ' персонажей. Названия создаваемых для тезок страниц имеют вид'
				.. ' «Фамилия, Имя Отчество (N)», где N — записанный римскими цифрами'
				.. ' порядковый номер тезки. Если для нужного вам имени уже существует'
				.. ' более одного тезки (то есть уже существуют страницы с номерами в'
				.. ' названии), то вам не требуется ничего специального, достаточно'
				.. ' завести страницу с очередным номером. Если же в справочнике'
				.. ' есть единственный тезка вашего персонажа, то создайте страницу'
				.. ' с названием «Фамилия, Имя Отчество (II)» и для получения подсказок'
				.. ' поместите там текст «{{ новый тезка }}»'
		)

	end
	local out = {}
	if idx ~= '(II)' then
		out[#out+1] = 'Обычно шаблон {{ новый тезка }} требуется применяется для'
			.. ' создания страницы с индексом (II). <b>Вы уверены,'
			.. ' что хотите создать страницу с индексом ' .. u[#u] .. '?</b>\n'
	end





	u[#u] = nil
--	u = { 'Берия, Лаврентий Павлович' }
	local rootPage = mw.title.new( table.concat( u, ' ' ), 0 )
	local root = rootPage.fullText
	local alterPage = mw.title.new( root .. ' (I)', 0 )
	-- Предлагаемые шаги.
	-- 1) измените все существующие ссылки c root на root-1
	-- 2) переименуйте root в root-1
	-- 3) измените содержимое root

	-- обзираем ситуацию. Убеждаемся, что  root — это пока нормальная страница,
	-- а root-1 не существует
	local rootIsDisambig, rootExists, alterExists
	rootExists = rootPage.exists
	local oldContent = rootPage:getContent()
	rootIsDisambig = mw.ustring.match( oldContent, '%{%{%s*неоднозначность' )
	alterExists = alterPage.exists

	query = pageInCargo( root )

	if #query ~= 0 then
		out[#out+1] = 'Ссылка на существующую страницу «[[' .. root .. ']]» используется в шаблонах на следующих страницах:<ul>'
		for _, v in ipairs( query ) do
			out[#out+1] = '<li>[[' .. v .. ']] [' .. tostring( mw.uri.fullUrl( v, { action = 'edit'} ) ) .. ' <i class="fa fa-pencil"></i>]</li>'
		end
		out[#out+1] = '</ul>\n'
	end
	out[#out+1] = require( 'Модуль:Отображение назначений').display( 'person="' .. root ..'"', true )
	return table.concat( out, '\n' )
--	local root = mw.title.new( table.concat( u, ' ' ), 0 )
--	local here = mw.text.unstripNoWiki( frame:preprocess( '{{Special:WhatLinksHere/' .. root.fullText ) )
--	return string.len(here) .. '---' .. mw.ustring.len(here) .. '---\n' .. here
end

return p