Source of file functions.publish.php
Size: 16,427 Bytes - Last Modified: 2017-07-17T16:46:02+00:00
/home/travis/build/Limych/GeniBase/src/edit/functions.publish.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416 | <?php /** * Функции автоматической формализации данных. * * @copyright Copyright © 2014–2015, Andrey Khrolenok (andrey@khrolenok.ru) */ // Direct execution forbidden for this script if (! defined('GB_VERSION') || count(get_included_files()) == 1) die('<b>ERROR:</b> Direct execution forbidden!'); /** * Функции формализации и публикации записей */ require_once (BASE_DIR . '/class.ww1-database.php'); /** * Функция нормирования дат */ function prepublish_date(&$raw, &$date_norm) { if (empty($raw['date'])) { $raw['date_from'] = MIN_DATE; $raw['date_to'] = MAX_DATE; return; } // Автоматическая корректировка «машинных» форматов дат в привычные для людей $raw['date'] = strtr($raw['date'], array( '-Jan-' => ' янв.', '-Feb-' => ' фев.', '-Mar-' => ' мар.', '-Apr-' => ' апр.', '-May-' => ' мая ', '-Jun-' => ' июн.', '-Jul-' => ' июл.', '-Aug-' => ' авг.', '-Sep-' => ' сен.', '-Oct-' => ' окт.', '-Nov-' => ' ноя.', '-Dec-' => ' дек.' )); // static $month_names_norm = array( 1 => ' янв.', 2 => ' фев.', 3 => ' мар.', 4 => ' апр.', 5 => ' мая ', 6 => ' июн.', 7 => ' июл.', 8 => ' авг.', 9 => ' сен.', 10 => ' окт.', 11 => ' ноя.', 12 => ' дек.' ); // yyyy-mm-dd $raw['date'] = preg_replace_callback('/^(\d{4})-(\d{2})-(\d{2})$/uS', function ($matches) use($month_names_norm) { if (! isset($month_names_norm[intval($matches[2])])) return $matches[0]; return $matches[3] . $month_names_norm[intval($matches[2])] . $matches[1]; }, $raw['date']); // mm/dd/yyyy $raw['date'] = preg_replace_callback('/^(\d{1,2})\/(\d{1,2})\/(\d{2,4})$/uS', function ($matches) use($month_names_norm) { if (! isset($month_names_norm[intval($matches[1])])) return $matches[0]; return $matches[2] . $month_names_norm[intval($matches[1])] . $matches[3]; }, $raw['date']); // dd.mm.yyyy $raw['date'] = preg_replace_callback('/^(\d{1,2})\.(\d{1,2})\.(\d{2,4})$/uS', function ($matches) use($month_names_norm) { if (! isset($month_names_norm[intval($matches[2])])) return $matches[0]; return $matches[1] . $month_names_norm[intval($matches[2])] . $matches[3]; }, $raw['date']); $date_norm = $raw['date']; // Переводим все буквы в строчные, обрезаем концевые пробелы и корректируем русские буквы $date_norm = fix_russian(trim(mb_strtolower($date_norm))); // Убираем префикс «с » $date_norm = preg_replace('/^съ?\s*/uS', '', $date_norm); // Заменяем частички « по » и « на » на дефис $date_norm = preg_replace('/(?<=[\d\W])\s*(?:по|на)\s*(?=[\d\W])/uS', '-', $date_norm); // Заменяем частички « и » и « или » на запятую $date_norm = preg_replace('/(?<=[\d\W])\s*и(ли)?\s*(?=[\d\W])/uS', ',', $date_norm); // Убираем окончание «г[ода][.]» $date_norm = preg_replace('/\s*г(?:ода?)?\.?\s*$/uS', '', $date_norm); // Заменяем на точки пробелы рядом со словами, остальные — убираем $date_norm = preg_replace('/(?<=[А-Яа-я])\s+|\s+(?=[А-Яа-я])/uS', '.', $date_norm); $date_norm = preg_replace('/\s+/uS', '', $date_norm); // Сокращаем несколько точек или дефисов в один $date_norm = preg_replace('/([\.\-])\\1*/uS', '\\1', $date_norm); // Шаблоны для поиска дат static $month_names = array( 'январь' => '01', 'января' => '01', 'янв' => '01', 'февраль' => '02', 'февраля' => '02', 'февр' => '02', 'фев' => '02', 'фвр' => '02', 'март' => '03', 'марта' => '03', 'мрт' => '03', 'мар' => '03', 'апрель' => '04', 'апреля' => '04', 'апр' => '04', 'май' => '05', 'мая' => '05', 'июнь' => '06', 'июня' => '06', 'июн' => '06', 'июль' => '07', 'июля' => '07', 'июл' => '07', 'август' => '08', 'августа' => '08', 'ав' => '08', 'авг' => '08', 'сентябрь' => '09', 'сентября' => '09', 'сен' => '09', 'снт' => '09', 'сент' => '09', 'октябрь' => '10', 'октября' => '10', 'окт' => '10', 'ноябрь' => '11', 'ноября' => '11', 'нбр' => '11', 'ноя' => '11', 'нояб' => '11', 'декабрь' => '12', 'декабря' => '12', 'дек' => '12', 'дкб' => '12' ); static $reg_months = ''; static $reg_date_left = ''; static $reg_date_right = ''; if (empty($reg_months)) { $reg_months = '(?:' . implode('|', array_keys($month_names)) . ')'; // дд[.мм[.[гг]гг]] или дд[.ммм[.[гг]гг]] $reg_date_left = "(\d\d?)(?:\.(?:($reg_months|\d\d?)(?:\.((?:\d\d)?\d\d)?)?)?)?"; // [[дд.]мм.]гггг или [[дд.]ммм.]гггг $reg_date_right = "(?:(?:(?:(\d\d?)?\.)?($reg_months|\d\d?))?\.)?(\d\d\d\d)"; // [дд.]ммм. $reg_date_right_short = "(?:(\d\d?)?\.)?($reg_months)\.?()"; } // Запись «1914/15» if ($date_norm == '1914/15') { $matches = array( '', '01', '08', '1914', '31', '12', '1915' ); // Простая запись дд.мм.гггг или мм.гггг или гггг } elseif (preg_match("/^$reg_date_left$/uS", $date_norm, $matches) || preg_match("/^$reg_date_right$/uS", $date_norm, $matches)) { if (empty($matches[3])) $matches[3] = ($matches[2] >= 8 ? 1914 : 1915); $matches[4] = $matches[1]; $matches[5] = $matches[2]; $matches[6] = $matches[3]; // Периодическая запись дд-дд.мм.гггг или дд.мм-дд.мм.гггг или дд.мм.гггг-дд.мм.гггг } elseif (preg_match("/^$reg_date_left-$reg_date_left$/uS", $date_norm, $matches) || preg_match("/^$reg_date_left-$reg_date_right$/uS", $date_norm, $matches) || preg_match("/^$reg_date_right-$reg_date_right$/uS", $date_norm, $matches)) { if (empty($matches[6])) $matches[6] = ($matches[5] >= 8 ? 1914 : 1915); if (empty($matches[2])) $matches[2] = $matches[5]; if (empty($matches[3])) $matches[3] = $matches[6]; // Периодическая запись дд.ммм-дд.ммм.гггг } elseif (preg_match("/^$reg_date_right_short-$reg_date_right$/uS", $date_norm, $matches)) { if (empty($matches[6])) $matches[6] = ($matches[5] >= 8 ? 1914 : 1915); if (empty($matches[2])) $matches[2] = $matches[5]; if (empty($matches[3])) $matches[3] = $matches[6]; // Списочная запись дд,дд,дд.мм.гггг } elseif (preg_match("/^(\d\d?),(?:\d\d?,)*$reg_date_left$/uS", $date_norm, $matches) || preg_match("/^(\d\d?),(?:\d\d?,)*$reg_date_right$/uS", $date_norm, $matches)) { if (empty($matches[4])) $matches[4] = ($matches[3] >= 8 ? 1914 : 1915); array_splice($matches, 2, 0, array( $matches[3], $matches[4] )); } // Нормализуем данные и формируем новые поля if (! empty($matches)) { static $last_days = array( 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ); if ($matches[3] < 100) $matches[3] += 1900; if (empty($matches[2])) $matches[2] = ($matches[3] == 1914 ? '08' : '01'); elseif (! is_numeric($matches[2])) $matches[2] = $month_names[$matches[2]]; if (empty($matches[1])) $matches[1] = '01'; $tmp = date_create(implode('-', array( $matches[3], $matches[2], $matches[1] ))); if ($tmp) $raw['date_from'] = $tmp->format('Y-m-d'); // if ($matches[6] < 100) $matches[6] += 1900; if (empty($matches[5])) $matches[5] = ($matches[5] == 1918 ? '11' : '12'); elseif (! is_numeric($matches[5])) $matches[5] = $month_names[$matches[5]]; if (empty($matches[4])) $matches[4] = (($matches[6] == 1918) && ($matches[5] == 11) ? '11' : $last_days[intval($matches[5]) - 1]); $tmp = date_create(implode('-', array( $matches[6], $matches[5], $matches[4] ))); if ($tmp) $raw['date_to'] = $tmp->format('Y-m-d'); if (($raw['date_from'] < MIN_DATE) || ($raw['date_from'] > MAX_DATE) || ($raw['date_to'] < MIN_DATE) || ($raw['date_to'] > MAX_DATE)) { unset($raw['date_from']); unset($raw['date_to']); } } // var_export($matches); // TODO: Remove this? } /** * Функция нормирования исходных данных */ function prepublish($raw, &$have_trouble, &$date_norm) { static $str_fields = array( 'surname', 'name', 'rank', 'religion', 'marital', 'uyezd', 'reason' ); foreach ($str_fields as $key) { if (! isset($raw[$key])) continue; // Убираем концевые пробелы и сокращаем множественные пробелы $raw[$key] = trim(preg_replace('/\s\s+/uS', ' ', $raw[$key])); // Конвертируем старо-русские буквы в современные $raw[$key] = fix_russian($raw[$key]); // Правим регистр букв в текстах if ($key == 'surname') { // Первые буквы каждого слова в верхний регистр $raw[$key] = preg_replace_callback('/\b\w+\b/uS', function ($matches) { return mb_ucfirst(mb_strtolower($matches[0])); }, $raw[$key]); } elseif ($key == 'name') { // Первые буквы каждого слова в верхний регистр $raw[$key] = preg_replace_callback('/\b\w+(?:-\w+)\b/uS', function ($matches) { return mb_ucfirst($matches[0]); }, $raw[$key]); } else { // Первую букву в верхний регистр $raw[$key] = mb_ucfirst($raw[$key]); } } // Расшифровываем вероисповедания if (isset($raw['religion'])) { /** * * @var int[] Array of correspondences between contractions of religion names and their IDs in the database. */ static $religion_conts = array(); // // Fetch religion names and reductions from dbase if (empty($religion_conts)) { $religion_conts[''] = 18; // Special ID for "(not set)" $result = gbdb()->get_table('SELECT `id`, `religion`, `contractions` FROM ?_dic_religions' . ' WHERE `religion` NOT LIKE "(%"'); foreach ($result as $row) { $tmp = array_merge((array) mb_strtolower($row['religion']), preg_split('/\W+/uS', mb_strtolower($row['contractions']), - 1, PREG_SPLIT_NO_EMPTY)); foreach ($tmp as $key) $religion_conts[$key] = $row['id']; } } // $tmp = trim(preg_replace('/\W+/uS', '-', mb_strtolower($raw['religion'])), '-'); if (isset($religion_conts[$tmp])) $raw['religion_id'] = $religion_conts[$tmp]; } // Расшифровываем семейные положения if (isset($raw['marital'])) { // TODO: Move to SQL-table static $maritals = array( '' => 4, // Женатые 'ж' => 1, 'жен' => 1, 'женат' => 1, // Холостые 'х' => 2, 'хол' => 2, 'холост' => 2, // Вдовые 'вд' => 3, 'вдв' => 3, 'вдов' => 3, 'вдовец' => 3 ); $tmp = trim(preg_replace('/\W+/uS', ' ', mb_strtolower($raw['marital']))); if (isset($maritals[$tmp])) $raw['marital_id'] = $maritals[$tmp]; } // Формализуем события if (isset($raw['reason'])) { // Get event/reason names and it's reductions from dbase static $reason_conts = array(); if (empty($reason_conts)) { $result = gbdb()->get_table('SELECT `reason_id`, `reason_raw` FROM ?_dic_reason2id AS rid,' . ' ?_dic_reasons AS r WHERE rid.reason_id = r.id and r.`reason` NOT LIKE "(%"'); $reason_conts[''] = 1; // Special ID for "(not set)" foreach ($result as $row) $reason_conts[trim(mb_strtolower($row['reason_raw']))] = $row['reason_id']; } $tmp = trim(mb_strtolower($raw['reason'])); // if( defined('GB_DEBUG_PUBLISH')) var_export($tmp); // TODO: Remove this? if (isset($reason_conts[$tmp])) $raw['reason_id'] = $reason_conts[$tmp]; } // Уточняем региональную привязку if (! empty($raw['uyezd'])) { $res = gbdb()->get_cell('SELECT id FROM ?_dic_regions WHERE parent_id = ?parent_id AND title LIKE ?title', array( 'parent_id' => $raw['region_id'], 'title' => $raw['uyezd'] . ' %' )); if ($res) $raw['region_id'] = $res; else { $raw['region_id'] = gbdb()->set_row('?_dic_regions', array( 'parent_id' => $raw['region_id'], 'title' => $raw['uyezd'] . ' ' ), FALSE, GB_DBase::MODE_INSERT); } } // Расшифровываем даты prepublish_date($raw, $date_norm); // Собираем данные для занесения в основную таблицу if (defined('GB_DEBUG_PUBLISH')) var_export($raw); // TODO: Remove this? return prepublish_make_data($raw, $have_trouble); } // function prepublish /** * Функция подготовки данных для занесения в систему. * * @param mixed[] $raw_norm * для нормализации. * @param bool $have_trouble * автоматически формализовать данные. * @return mixed[] версия данных. */ function prepublish_make_data($raw_norm, &$have_trouble) { $have_trouble = false; $pub = array(); foreach (explode(' ', 'id surname name rank religion_id marital_id region_id place reason_id date date_from date_to source_id source_pg') as $key) { if (! isset($raw_norm[$key]) || ((empty($raw_norm[$key]) || absint($raw_norm[$key]) != $raw_norm[$key]) && $key != 'source_id' && preg_match('/(^|_)id$/uS', $key)) || ($key == 'date_from' && ($raw_norm['date_from'] < MIN_DATE || $raw_norm['date_from'] > MAX_DATE)) || ($key == 'date_to' && ($raw_norm['date_to'] < MIN_DATE || $raw_norm['date_to'] > MAX_DATE))) $have_trouble = true; else $pub[$key] = $raw_norm[$key]; } return $pub; } |