summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormakitso <makitso@gmail.com>2013-12-15 14:17:19 -0600
committermakitso <makitso@gmail.com>2013-12-15 14:17:19 -0600
commita3c69ea9e8ef9a3c63cb653745d9c5539928d33c (patch)
tree84ace45eb0df6fad172366e744945bd7d9071d90
parent927a0b4449f09196cab8f6530bffd384b501e1c5 (diff)
parent867edf235ac0f4ef6fb636f1691904619931e344 (diff)
downloadwebtrees-a3c69ea9e8ef9a3c63cb653745d9c5539928d33c.tar.gz
webtrees-a3c69ea9e8ef9a3c63cb653745d9c5539928d33c.tar.bz2
webtrees-a3c69ea9e8ef9a3c63cb653745d9c5539928d33c.zip
Merge branch 'master' of https://github.com/fisharebest/webtrees
-rw-r--r--admin.php422
-rw-r--r--includes/functions/functions_export.php159
-rw-r--r--includes/specialchars.php56
-rw-r--r--library/WT/I18N.php109
-rw-r--r--message.php2
-rw-r--r--modules_v3/GEDFact_assistant/CENS_ctrl.php1
-rw-r--r--themes/_administration/css-1.5.1/style.css2
7 files changed, 414 insertions, 337 deletions
diff --git a/admin.php b/admin.php
index a377706306..e17560f240 100644
--- a/admin.php
+++ b/admin.php
@@ -26,6 +26,10 @@ require WT_ROOT.'includes/functions/functions_edit.php';
$controller=new WT_Controller_Page();
$controller
->requireManagerLogin()
+ ->addInlineJavascript('jQuery("#x").accordion({active:0, icons:{ "header": "ui-icon-triangle-1-s", "headerSelected": "ui-icon-triangle-1-n" }, heightStyle: "content"});')
+ ->addInlineJavascript('jQuery("#tree_stats").accordion({icons:{ "header": "ui-icon-triangle-1-s", "headerSelected": "ui-icon-triangle-1-n" }});')
+ ->addInlineJavascript('jQuery("#changes").accordion({icons:{ "header": "ui-icon-triangle-1-s", "headerSelected": "ui-icon-triangle-1-n" }});')
+ ->addInlineJavascript('jQuery("#content_container").css("visibility", "visible");')
->setPageTitle(WT_I18N::translate('Administration'))
->pageHeader();
@@ -38,215 +42,247 @@ if (preg_match('/^[0-9.]+\|[0-9.]+\|/', $latest_version_txt)) {
$latest_version='';
}
-$stats=new WT_Stats(WT_GEDCOM);
- $totusers =0; // Total number of users
- $warnusers =0; // Users with warning
- $applusers =0; // Users who have not verified themselves
- $nverusers =0; // Users not verified by admin but verified themselves
- $adminusers=0; // Administrators
- $userlang =array(); // Array for user languages
- $gedadmin =array(); // Array for managers
-
-// Display a series of "blocks" of general information, vary according to admin or manager.
-
-echo '<div id="content_container" style="visibility:hidden">';
-
-echo '<div id="x">';// div x - manages the accordion effect
-
-echo '<h2>', WT_WEBTREES, ' ', WT_VERSION, '</h2>',
- '<div id="about">',
- '<p>', WT_I18N::translate('These pages provide access to all the configuration settings and management tools for this <b>webtrees</b> site.'), '</p>',
- '<p>', /* I18N: %s is a URL/link to the project website */ WT_I18N::translate('Support and documentation can be found at %s.', ' <a class="current" href="http://webtrees.net/">webtrees.net</a>'), '</p>';
-
-// Accordion block for UPGRADE - only shown when upgrades are available
-if (WT_USER_IS_ADMIN && $latest_version && version_compare(WT_VERSION, $latest_version)<0) {
- echo '<p>', WT_I18N::translate('A new version of webtrees is available.'), ' <a href="admin_site_upgrade.php"><span class="error">', WT_I18N::translate('Upgrade to webtrees %s', WT_Filter::escapeHtml($latest_version)), '</span></a></p>';
-}
-
-echo '</div>';
-
-// Accordion block for DELETE OLD FILES - only shown when old files are found
-$old_files_found=false;
+// Delete old files (if we can).
+$old_files = array();
foreach (old_paths() as $path) {
if (file_exists($path)) {
delete_recursively($path);
// we may not have permission to delete. Is it still there?
if (file_exists($path)) {
- $old_files_found=true;
+ $old_files[] = $path;
}
}
}
-if (WT_USER_IS_ADMIN && $old_files_found) {
- echo
- '<h2><span class="warning">', WT_I18N::translate('Old files found'), '</span></h2>',
- '<div>',
- '<p>', WT_I18N::translate('Files have been found from a previous version of webtrees. Old files can sometimes be a security risk. You should delete them.'), '</p>',
- '<ul>';
- foreach (old_paths() as $path) {
- if (file_exists($path)) {
- echo '<li>', $path, '</li>';
- }
- }
- echo
- '</ul>',
- '</div>';
-}
+// Total number of users
+$total_users = WT_DB::prepare(
+ "SELECT COUNT(*) FROM `##user` WHERE user_id>0"
+)->fetchOne();
-echo
- '<h2>', WT_I18N::translate('Users'), '</h2>',
- '<div id="users">'; //id = users
+// Total number of administrators
+$total_administrators = WT_DB::prepare(
+ "SELECT COUNT(*) FROM `##user_setting` WHERE setting_name='canadmin' AND setting_value=1"
+)->fetchOne();
- foreach(get_all_users() as $user_id=>$user_name) {
- $totusers = $totusers + 1;
- if (((date("U") - (int)get_user_setting($user_id, 'reg_timestamp')) > 604800) && !get_user_setting($user_id, 'verified')) {
- $warnusers++;
- }
- if (!get_user_setting($user_id, 'verified_by_admin') && get_user_setting($user_id, 'verified')) {
- $nverusers++;
- }
- if (!get_user_setting($user_id, 'verified')) {
- $applusers++;
- }
- if (get_user_setting($user_id, 'canadmin')) {
- $adminusers++;
- }
- foreach (WT_Tree::getAll() as $tree) {
- if ($tree->userPreference($user_id, 'canedit')=='admin') {
- if (isset($gedadmin[$tree->tree_id])) {
- $gedadmin[$tree->tree_id]["number"]++;
- } else {
- $gedadmin[$tree->tree_id]["number"] = 1;
- $gedadmin[$tree->tree_id]["ged"] = $tree->tree_name;
- $gedadmin[$tree->tree_id]["title"] = $tree->tree_title_html;
- }
- }
- }
- if ($user_lang=get_user_setting($user_id, 'language')) {
- if (isset($userlang[$user_lang]))
- $userlang[$user_lang]["number"]++;
- else {
- $userlang[$user_lang]["langname"] = Zend_Locale::getTranslation($user_lang, 'language', WT_LOCALE);
- $userlang[$user_lang]["number"] = 1;
- }
- }
- }
+// Total numbers of managers
+$total_managers = WT_DB::prepare(
+ "SELECT gs.setting_value, COUNT(*)" .
+ " FROM `##gedcom_setting` gs" .
+ " JOIN `##user_gedcom_setting` ugs USING (gedcom_id)" .
+ " WHERE ugs.setting_name = 'canedit' AND ugs.setting_value='admin'" .
+ " AND gs.setting_name ='title'" .
+ " GROUP BY gedcom_id" .
+ " ORDER BY gs.setting_value"
+)->fetchAssoc();
- echo
- '<table>',
- '<tr><td>', WT_I18N::translate('Total number of users'), '</td><td>', $totusers, '</td></tr>',
- '<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="admin_users.php?action=listusers&amp;filter=adminusers">', WT_I18N::translate('Administrators'), '</a></td><td>', $adminusers, '</td></tr>',
- '<tr><td colspan="2">', WT_I18N::translate('Managers'), '</td></tr>';
- foreach ($gedadmin as $ged_id=>$geds) {
- echo '<tr><td><div><a href="admin_users.php?action=listusers&amp;filter=gedadmin&amp;ged='.rawurlencode($geds['ged']), '" dir="auto">', $geds['title'], '</a></div></td><td>', $geds['number'], '</td></tr>';
- }
- echo '<tr><td>';
- if ($warnusers == 0) {
- echo WT_I18N::translate('Users with warnings');
- } else {
- echo '<a href="admin_users.php?action=listusers&amp;filter=warnings">', WT_I18N::translate('Users with warnings'), '</a>';
- }
- echo '</td><td>', $warnusers, '</td></tr><tr><td>';
- if ($applusers == 0) {
- echo WT_I18N::translate('Unverified by User');
- } else {
- echo '<a href="admin_users.php?action=listusers&amp;filter=usunver">', WT_I18N::translate('Unverified by User'), '</a>';
- }
- echo '</td><td>', $applusers, '</td></tr><tr><td>';
- if ($nverusers == 0) {
- echo WT_I18N::translate('Unverified by Administrator');
- } else {
- echo '<a href="admin_users.php?action=listusers&amp;filter=admunver">', WT_I18N::translate('Unverified by Administrator'), '</a>';
- }
- echo '</td><td>', $nverusers, '</td></tr>';
- echo '<tr><td colspan="2">', WT_I18N::translate('Users’ languages'), '</td></tr>';
- foreach ($userlang as $key=>$ulang) {
- echo '<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;<a href="admin_users.php?action=listusers&amp;filter=language&amp;usrlang=', $key, '">', $ulang['langname'], '</a></td><td>', $ulang['number'], '</td></tr>';
- }
- echo
- '<tr><td colspan="2">', WT_I18N::translate('Users logged in'), '</td></tr>',
- '<tr><td colspan="2"><div>', $stats->_usersLoggedIn('list'), '</div></td></tr>',
- '</table>';
-echo '</div>'; // id = users
+// Number of users who have not verified their email address
+$unverified = WT_DB::prepare(
+ "SELECT COUNT(*) FROM `##user_setting` WHERE setting_name='verified' AND setting_value=0"
+)->fetchOne();
-echo
- '<h2>', WT_I18N::translate('Family trees'), '</h2>',
- '<div id="trees">',// id=trees
- '<div id="tree_stats">';
-$n=0;
-foreach (WT_Tree::getAll() as $tree) {
- $stats = new WT_Stats($tree->tree_name);
- if ($tree->tree_id==WT_GED_ID) {
- $accordion_element=$n;
- }
- ++$n;
- echo
- '<h3>', $stats->gedcomTitle(), '</h3>',
- '<div>',
- '<table>',
- '<tr><td>&nbsp;</td><td><span>', WT_I18N::translate('Count'), '</span></td></tr>',
- '<tr><th><a href="indilist.php?ged=', $tree->tree_name_url, '">',
- WT_I18N::translate('Individuals'), '</a></th><td>', $stats->totalIndividuals(),
- '</td></tr>',
- '<tr><th><a href="famlist.php?ged=', $tree->tree_name_url, '">',
- WT_I18N::translate('Families'), '</a></th><td>', $stats->totalFamilies(),
- '</td></tr>',
- '<tr><th><a href="sourcelist.php?ged=', $tree->tree_name_url, '">',
- WT_I18N::translate('Sources'), '</a></th><td>', $stats->totalSources(),
- '</td></tr>',
- '<tr><th><a href="repolist.php?ged=', $tree->tree_name_url, '">',
- WT_I18N::translate('Repositories'), '</a></th><td>', $stats->totalRepositories(),
- '</td></tr>',
- '<tr><th><a href="medialist.php?ged=', $tree->tree_name_url, '">',
- WT_I18N::translate('Media objects'), '</a></th><td>', $stats->totalMedia(),
- '</td></tr>',
- '<tr><th><a href="notelist.php?ged=', $tree->tree_name_url, '">',
- WT_I18N::translate('Notes'), '</a></th><td>', $stats->totalNotes(),
- '</td></tr>',
- '</table>',
- '</div>';
-}
-echo
- '</div>', // id=tree_stats
- '</div>'; // id=trees
+// Number of users whose accounts are not approved by an administrator
+$unapproved = WT_DB::prepare(
+ "SELECT COUNT(*) FROM `##user_setting` WHERE setting_name='verified_by_admin' AND setting_value=0"
+)->fetchOne();
-$controller->addInlineJavascript('jQuery("#tree_stats").accordion({active:'.$accordion_element.', icons:{ "header": "ui-icon-triangle-1-s", "headerSelected": "ui-icon-triangle-1-n" }});');
+// Number of users of each language
+$user_languages = WT_DB::prepare(
+ "SELECT setting_value, COUNT(*)" .
+ " FROM `##user_setting`" .
+ " WHERE setting_name = 'language'" .
+ " GROUP BY setting_value"
+)->fetchAssoc();
-echo
- '<h2>', WT_I18N::translate('Recent changes'), '</h2>',
- '<div id="recent2">'; //id=recent
- echo
- '<div id="changes">';
-$n=0;
-foreach (WT_Tree::GetAll() as $tree) {
- if ($tree->tree_id==WT_GED_ID) {
- $accordion_element=$n;
- }
- ++$n;
- echo
- '<h3><span dir="auto">', $tree->tree_title_html, '</span></h3>',
- '<div>',
- '<table>',
- '<tr><td>&nbsp;</td><td><span>', WT_I18N::translate('Day'), '</span></td><td><span>', WT_I18N::translate('Week'), '</span></td><td><span>', WT_I18N::translate('Month'), '</span></td></tr>',
- '<tr><th>', WT_I18N::translate('Individuals'), '</th><td>', WT_Query_Admin::countIndiChangesToday($tree->tree_id), '</td><td>', WT_Query_Admin::countIndiChangesWeek($tree->tree_id), '</td><td>', WT_Query_Admin::countIndiChangesMonth($tree->tree_id), '</td></tr>',
- '<tr><th>', WT_I18N::translate('Families'), '</th><td>', WT_Query_Admin::countFamChangesToday($tree->tree_id), '</td><td>', WT_Query_Admin::countFamChangesWeek($tree->tree_id), '</td><td>', WT_Query_Admin::countFamChangesMonth($tree->tree_id), '</td></tr>',
- '<tr><th>', WT_I18N::translate('Sources'), '</th><td>', WT_Query_Admin::countSourChangesToday($tree->tree_id), '</td><td>', WT_Query_Admin::countSourChangesWeek($tree->tree_id), '</td><td>', WT_Query_Admin::countSourChangesMonth($tree->tree_id), '</td></tr>',
- '<tr><th>', WT_I18N::translate('Repositories'), '</th><td>', WT_Query_Admin::countRepoChangesToday($tree->tree_id), '</td><td>', WT_Query_Admin::countRepoChangesWeek($tree->tree_id), '</td><td>', WT_Query_Admin::countRepoChangesMonth($tree->tree_id), '</td></tr>',
- '<tr><th>', WT_I18N::translate('Media objects'), '</th><td>', WT_Query_Admin::countObjeChangesToday($tree->tree_id), '</td><td>', WT_Query_Admin::countObjeChangesWeek($tree->tree_id), '</td><td>', WT_Query_Admin::countObjeChangesMonth($tree->tree_id), '</td></tr>',
- '<tr><th>', WT_I18N::translate('Notes'), '</th><td>', WT_Query_Admin::countNoteChangesToday($tree->tree_id), '</td><td>', WT_Query_Admin::countNoteChangesWeek($tree->tree_id), '</td><td>', WT_Query_Admin::countNoteChangesMonth($tree->tree_id), '</td></tr>',
- '</table>',
- '</div>';
- }
-echo
- '</div>', // id=changes
- '</div>', // id=recent
- '</div>', //id = "x"
- '</div>'; //id = content_container
+$stats = new WT_Stats(WT_GEDCOM);
-$controller
- ->addInlineJavascript('jQuery("#changes").accordion({active:' . $accordion_element . ', icons:{ "header": "ui-icon-triangle-1-s", "headerSelected": "ui-icon-triangle-1-n" }});')
- ->addInlineJavascript('jQuery("#x").accordion({active:0, icons:{ "header": "ui-icon-triangle-1-s", "headerSelected": "ui-icon-triangle-1-n" }, heightStyle: "content"});')
- ->addInlineJavascript('jQuery("#content_container").css("visibility", "visible");');
+?>
+<div id="content_container" style="visibility:hidden">
+ <div id="x">
+ <h2><?php echo WT_WEBTREES, ' ', WT_VERSION; ?></h2>
+ <div id="about">
+ <p>
+ <?php echo WT_I18N::translate('These pages provide access to all the configuration settings and management tools for this <b>webtrees</b> site.'); ?>
+ </p>
+ <p>
+ <?php echo /* I18N: %s is a URL/link to the project website */ WT_I18N::translate('Support and documentation can be found at %s.', ' <a class="current" href="http://webtrees.net/">webtrees.net</a>'); ?>
+ </p>
+ <?php if (WT_USER_IS_ADMIN && $latest_version && version_compare(WT_VERSION, $latest_version)<0) { ?>
+ <p>
+ <?php echo WT_I18N::translate('A new version of webtrees is available.'); ?>
+ <a href="admin_site_upgrade.php" class="error">
+ <?php echo WT_I18N::translate('Upgrade to webtrees %s', WT_Filter::escapeHtml($latest_version)); ?>
+ </a>
+ </p>
+ <?php } ?>
+ </div>
+
+ <?php if (WT_USER_IS_ADMIN && $old_files) { ?>
+ <h2><span class="warning">', WT_I18N::translate('Old files found'), '</span></h2>
+ <div>
+ <p>
+ <?php echo WT_I18N::translate('Files have been found from a previous version of webtrees. Old files can sometimes be a security risk. You should delete them.'); ?>
+ </p>
+ <ul>
+ <?php foreach ($old_files as $file) { ?>
+ <li dir="ltr"><?php echo $path; ?></li>';
+ <?php } ?>
+ </ul>
+ </div>
+ <?php } ?>
+
+ <h2><?php echo WT_I18N::translate('Users'); ?></h2>
+ <div id="users">
+ <table>
+ <tbody>
+ <tr>
+ <td><?php echo WT_I18N::translate('Total number of users'); ?></td>
+ <td><?php echo $total_users; ?></td>
+ </tr>
+ <tr>
+ <td><?php echo WT_I18N::translate('Administrators'); ?></td>
+ <td><?php echo $total_administrators; ?></td>
+ </tr>
+ <tr>
+ <td colspan="2"><?php echo WT_I18N::translate('Managers'); ?></td>
+ </tr>
+ <?php foreach ($total_managers as $gedcom_title=>$n) { ?>
+ <tr>
+ <td>&nbsp;&nbsp;<?php echo WT_Filter::escapeHtml($gedcom_title); ?></td>
+ <td><?php echo $n; ?></td>
+ </tr>
+ <?php } ?>
+ <tr>
+ <td><?php echo WT_I18N::translate('Unverified by User'); ?></td>
+ <td><?php echo $unverified; ?></td>
+ </tr>
+ <tr>
+ <td><?php echo WT_I18N::translate('Unverified by Administrator'); ?></td>
+ <td><?php echo $unapproved; ?></td>
+ </tr>
+ <tr>
+ <td colspan="2"><?php echo WT_I18N::translate('Users’ languages'); ?></td>
+ </tr>
+ <?php foreach ($user_languages as $language=>$n) { ?>
+ <tr>
+ <td>&nbsp;&nbsp;<?php echo WT_I18N::languageName($language); ?></td>
+ <td><?php echo $n; ?></td>
+ </tr>
+ <?php } ?>
+ <tr>
+ <td colspan="2"><?php echo WT_I18N::translate('Users logged in'); ?></td>
+ </tr>
+ <tr>
+ <td colspan="2"><?php echo $stats->_usersLoggedIn('list'); ?></td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+
+ <h2><?php echo WT_I18N::translate('Family trees'); ?></h2>
+ <div id="trees">
+ <div id="tree_stats">
+ <?php foreach (WT_Tree::getAll() as $tree) { ?>
+ <?php $stats = new WT_Stats($tree->tree_name); ?>
+ <h3><?php echo $stats->gedcomTitle(); ?></h3>
+ <div>
+ <table>
+ <thead>
+ <tr>
+ <th><?php echo WT_I18N::translate('Records'); ?></th>
+ <th><?php echo WT_I18N::translate('Count'); ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <th><a href="indilist.php?ged=<?php echo $tree->tree_name_url; ?>"><?php echo WT_I18N::translate('Individuals'); ?></a></th>
+ <td><?php echo $stats->totalIndividuals(); ?></td>
+ </tr>
+ <tr>
+ <th><a href="famlist.php?ged=<?php echo $tree->tree_name_url; ?>"><?php echo WT_I18N::translate('Families'); ?></a></th>
+ <td><?php echo $stats->totalFamilies(); ?></td>
+ </tr>
+ <tr>
+ <th><a href="sourcelist.php?ged=<?php echo $tree->tree_name_url; ?>"><?php echo WT_I18N::translate('Sources'); ?></a></th>
+ <td><?php echo$stats->totalSources(); ?></td>
+ </tr>
+ <tr><th><a href="repolist.php?ged=<?php echo $tree->tree_name_url; ?>"><?php echo WT_I18N::translate('Repositories'); ?></a></th>
+ <td><?php echo$stats->totalRepositories(); ?></td>
+ </tr>
+ <tr><th><a href="medialist.php?ged=<?php echo $tree->tree_name_url; ?>"><?php echo WT_I18N::translate('Media objects'); ?></a></th>
+ <td><?php echo$stats->totalMedia(); ?></td>
+ </tr>
+ <tr><th><a href="notelist.php?ged=<?php echo $tree->tree_name_url; ?>"><?php echo WT_I18N::translate('Notes'); ?></a></th>
+ <td><?php echo$stats->totalNotes(); ?></td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ <?php } ?>
+ </div>
+ </div>
+
+ <h2><?php echo WT_I18N::translate('Recent changes'); ?></h2>
+ <div id="recent2">
+ <div id="changes">
+ <?php foreach (WT_Tree::GetAll() as $tree) { ?>
+ <h3><span dir="auto"><?php echo $tree->tree_title_html; ?></span></h3>
+ <div>
+ <table>
+ <thead>
+ <tr>
+ <th><?php echo WT_I18N::translate('Records'); ?></th>
+ <th><?php echo WT_I18N::translate('Day'); ?></th>
+ <th><?php echo WT_I18N::translate('Week'); ?></th>
+ <th><?php echo WT_I18N::translate('Month'); ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <th><?php echo WT_I18N::translate('Individuals'); ?></th>
+ <td><?php echo WT_Query_Admin::countIndiChangesToday($tree->tree_id); ?></td>
+ <td><?php echo WT_Query_Admin::countIndiChangesWeek($tree->tree_id); ?></td>
+ <td><?php echo WT_Query_Admin::countIndiChangesMonth($tree->tree_id); ?></td>
+ </tr>
+ <tr>
+ <th><?php echo WT_I18N::translate('Families'); ?></th>
+ <td><?php echo WT_Query_Admin::countFamChangesToday($tree->tree_id); ?></td>
+ <td><?php echo WT_Query_Admin::countFamChangesWeek($tree->tree_id); ?></td>
+ <td><?php echo WT_Query_Admin::countFamChangesMonth($tree->tree_id); ?></td>
+ </tr>
+ <tr>
+ <th><?php echo WT_I18N::translate('Sources'); ?></th>
+ <td><?php echo WT_Query_Admin::countSourChangesToday($tree->tree_id); ?></td>
+ <td><?php echo WT_Query_Admin::countSourChangesWeek($tree->tree_id); ?></td>
+ <td><?php echo WT_Query_Admin::countSourChangesMonth($tree->tree_id); ?></td>
+ </tr>
+ <tr>
+ <th><?php echo WT_I18N::translate('Repositories'); ?></th>
+ <td><?php echo WT_Query_Admin::countRepoChangesToday($tree->tree_id); ?></td>
+ <td><?php echo WT_Query_Admin::countRepoChangesWeek($tree->tree_id); ?></td>
+ <td><?php echo WT_Query_Admin::countRepoChangesMonth($tree->tree_id); ?></td>
+ </tr>
+ <tr>
+ <th><?php echo WT_I18N::translate('Media objects'); ?></th>
+ <td><?php echo WT_Query_Admin::countObjeChangesToday($tree->tree_id); ?></td>
+ <td><?php echo WT_Query_Admin::countObjeChangesWeek($tree->tree_id); ?></td>
+ <td><?php echo WT_Query_Admin::countObjeChangesMonth($tree->tree_id); ?></td>
+ </tr>
+ <tr>
+ <th><?php echo WT_I18N::translate('Notes'); ?></th>
+ <td><?php echo WT_Query_Admin::countNoteChangesToday($tree->tree_id); ?></td>
+ <td><?php echo WT_Query_Admin::countNoteChangesWeek($tree->tree_id); ?></td>
+ <td><?php echo WT_Query_Admin::countNoteChangesMonth($tree->tree_id); ?></td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ <?php } ?>
+ </div>
+ </div>
+ </div>
+</div>
+
+<?php
// This is a list of old files and directories, from earlier versions of webtrees, that can be deleted
// It was generated with the help of a command like this
diff --git a/includes/functions/functions_export.php b/includes/functions/functions_export.php
index d683f3e581..170391570d 100644
--- a/includes/functions/functions_export.php
+++ b/includes/functions/functions_export.php
@@ -173,150 +173,121 @@ function export_gedcom($gedcom, $gedout, $exportOptions) {
// Temporarily switch to the specified GEDCOM
$oldGEDCOM = $GEDCOM;
$GEDCOM = $gedcom;
- $ged_id=get_id_from_gedcom($gedcom);
+ $ged_id = get_id_from_gedcom($gedcom);
switch($exportOptions['privatize']) {
case 'gedadmin':
- $access_level=WT_PRIV_NONE;
+ $access_level = WT_PRIV_NONE;
break;
case 'user':
- $access_level=WT_PRIV_USER;
+ $access_level = WT_PRIV_USER;
break;
case 'visitor':
- $access_level=WT_PRIV_PUBLIC;
+ $access_level = WT_PRIV_PUBLIC;
break;
case 'none':
- $access_level=WT_PRIV_HIDE;
+ $access_level = WT_PRIV_HIDE;
break;
}
- $head=gedcom_header($gedcom);
- if ($exportOptions['toANSI']=="yes") {
- $head=str_replace("UTF-8", "ANSI", $head);
- $head=utf8_decode($head);
+ $head = gedcom_header($gedcom);
+ if ($exportOptions['toANSI'] == 'yes') {
+ $head = str_replace('UTF-8', 'ANSI', $head);
+ $head = utf8_decode($head);
}
+ $head = reformat_record_export($head);
+ fwrite($gedout, $head);
- // Fetch all the records first - to prevent MySQL timeouts between fetches
- $rows=WT_DB::prepare(
- "SELECT i_id AS xref, i_file AS gedcom_id, i_gedcom AS gedcom".
- " FROM `##individuals` WHERE i_file=? ORDER BY i_id"
- )->execute(array($ged_id))->fetchAll();
- $individuals = array();
- foreach ($rows as $row) {
- $individuals[] = WT_Individual::getInstance($row->xref, $row->gedcom_id, $row->gedcom);
- }
-
- $rows=WT_DB::prepare(
- "SELECT f_id AS xref, f_file AS gedcom_id, f_gedcom AS gedcom".
- " FROM `##families` WHERE f_file=? ORDER BY f_id"
+ // Buffer the output. Lots of small fwrite() calls can be very slow when writing large gedcoms.
+ $buffer = '';
+
+ // Generate the OBJE/SOUR/REPO/NOTE records first, as their privacy calcualations involve
+ // database queries, and we wish to avoid large gaps between queries due to MySQL connection timeouts.
+ $tmp_gedcom = '';
+ $rows = WT_DB::prepare(
+ "SELECT 'OBJE' AS type, m_id AS xref, m_file AS gedcom_id, m_gedcom AS gedcom".
+ " FROM `##media` WHERE m_file=? ORDER BY m_id"
)->execute(array($ged_id))->fetchAll();
- $families = array();
foreach ($rows as $row) {
- $families[] = WT_Family::getInstance($row->xref, $row->gedcom_id, $row->gedcom);
+ $rec = WT_Media::getInstance($row->xref, $row->gedcom_id, $row->gedcom)->privatizeGedcom($access_level);
+ $rec = convert_media_path($rec, $exportOptions['path']);
+ if ($exportOptions['toANSI'] == 'yes') {
+ $rec = utf8_decode($rec);
+ }
+ $tmp_gedcom .= reformat_record_export($rec);
}
- $rows=WT_DB::prepare(
+ $rows = WT_DB::prepare(
"SELECT s_id AS xref, s_file AS gedcom_id, s_gedcom AS gedcom".
" FROM `##sources` WHERE s_file=? ORDER BY s_id"
)->execute(array($ged_id))->fetchAll();
- $sources = array();
foreach ($rows as $row) {
- $sources[] = WT_Source::getInstance($row->xref, $row->gedcom_id, $row->gedcom);
- }
-
- $rows=WT_DB::prepare(
- "SELECT 'OBJE' AS type, m_id AS xref, m_file AS gedcom_id, m_gedcom AS gedcom".
- " FROM `##media` WHERE m_file=? ORDER BY m_id"
- )->execute(array($ged_id))->fetchAll();
- $medias = array();
- foreach ($rows as $row) {
- $medias[] = WT_Media::getInstance($row->xref, $row->gedcom_id, $row->gedcom);
+ $rec = WT_Source::getInstance($row->xref, $row->gedcom_id, $row->gedcom)->privatizeGedcom($access_level);
+ if ($exportOptions['toANSI'] == 'yes') {
+ $rec = utf8_decode($rec);
+ }
+ $tmp_gedcom .= reformat_record_export($rec);
}
- $rows=WT_DB::prepare(
+ $rows = WT_DB::prepare(
"SELECT o_type AS type, o_id AS xref, o_file AS gedcom_id, o_gedcom AS gedcom".
" FROM `##other` WHERE o_file=? AND o_type!='HEAD' AND o_type!='TRLR' ORDER BY o_id"
)->execute(array($ged_id))->fetchAll();
- $others = array();
foreach ($rows as $row) {
switch ($row->type) {
case 'NOTE':
- $others[] = WT_Note::getInstance($row->xref, $row->gedcom_id, $row->gedcom);
+ $record = WT_Note::getInstance($row->xref, $row->gedcom_id, $row->gedcom);
break;
case 'REPO':
- $others[] = WT_Repository::getInstance($row->xref, $row->gedcom_id, $row->gedcom);
+ $record = WT_Repository::getInstance($row->xref, $row->gedcom_id, $row->gedcom);
break;
default:
- $others[] = WT_GedcomRecord::getInstance($row->xref, $row->gedcom_id, $row->gedcom);
+ $record = WT_GedcomRecord::getInstance($row->xref, $row->gedcom_id, $row->gedcom);
break;
}
- }
-
- // Buffer the output. Lots of small fwrite() calls can be very slow when writing large gedcoms.
- $buffer=reformat_record_export($head);
-
- foreach ($individuals as $individual) {
- $rec = $individual->privatizeGedcom($access_level);
- if ($exportOptions['toANSI']=="yes") {
- $rec=utf8_decode($rec);
- }
- $buffer.=reformat_record_export($rec);
- if (strlen($buffer)>65536) {
- fwrite($gedout, $buffer);
- $buffer='';
- }
- }
-
- foreach ($families as $family) {
- $rec = $family->privatizeGedcom($access_level);
- if ($exportOptions['toANSI']=="yes") {
- $rec=utf8_decode($rec);
- }
- $buffer.=reformat_record_export($rec);
- if (strlen($buffer)>65536) {
- fwrite($gedout, $buffer);
- $buffer='';
- }
- }
- foreach ($sources as $source) {
- $rec = $source->privatizeGedcom($access_level);
- if ($exportOptions['toANSI']=="yes") {
- $rec=utf8_decode($rec);
- }
- $buffer.=reformat_record_export($rec);
- if (strlen($buffer)>65536) {
- fwrite($gedout, $buffer);
- $buffer='';
+ $rec = $record->privatizeGedcom($access_level);
+ if ($exportOptions['toANSI'] == 'yes') {
+ $rec = utf8_decode($rec);
}
+ $tmp_gedcom .= reformat_record_export($rec);
}
- foreach ($others as $other) {
- $rec = $other->privatizeGedcom($access_level);
- if ($exportOptions['toANSI']=="yes") {
- $rec=utf8_decode($rec);
+ $rows = WT_DB::prepare(
+ "SELECT i_id AS xref, i_file AS gedcom_id, i_gedcom AS gedcom".
+ " FROM `##individuals` WHERE i_file=? ORDER BY i_id"
+ )->execute(array($ged_id))->fetchAll();
+ foreach ($rows as $row) {
+ $rec = WT_Individual::getInstance($row->xref, $row->gedcom_id, $row->gedcom)->privatizeGedcom($access_level);
+ if ($exportOptions['toANSI'] == 'yes') {
+ $rec = utf8_decode($rec);
}
- $buffer.=reformat_record_export($rec);
- if (strlen($buffer)>65536) {
+ $buffer .= reformat_record_export($rec);
+ if (strlen($buffer) > 65536) {
fwrite($gedout, $buffer);
- $buffer='';
+ $buffer = '';
}
}
- foreach ($medias as $media) {
- $rec = $media->privatizeGedcom($access_level);
- $rec = convert_media_path($rec, $exportOptions['path']);
- if ($exportOptions['toANSI']=="yes") {
- $rec=utf8_decode($rec);
+ $rows = WT_DB::prepare(
+ "SELECT f_id AS xref, f_file AS gedcom_id, f_gedcom AS gedcom".
+ " FROM `##families` WHERE f_file=? ORDER BY f_id"
+ )->execute(array($ged_id))->fetchAll();
+ foreach ($rows as $row) {
+ $rec = WT_Family::getInstance($row->xref, $row->gedcom_id, $row->gedcom)->privatizeGedcom($access_level);
+ if ($exportOptions['toANSI'] == 'yes') {
+ $rec = utf8_decode($rec);
}
- $buffer.=reformat_record_export($rec);
- if (strlen($buffer)>65536) {
+ $buffer .= reformat_record_export($rec);
+ if (strlen($buffer) > 65536) {
fwrite($gedout, $buffer);
- $buffer='';
+ $buffer = '';
}
}
- fwrite($gedout, $buffer."0 TRLR".WT_EOL);
+ fwrite($gedout, $buffer);
+ fwrite($gedout, $tmp_gedcom);
+ fwrite($gedout, '0 TRLR' . WT_EOL);
$GEDCOM = $oldGEDCOM;
}
diff --git a/includes/specialchars.php b/includes/specialchars.php
index f2655444f1..1ce62b96fa 100644
--- a/includes/specialchars.php
+++ b/includes/specialchars.php
@@ -43,34 +43,34 @@ if (!defined('WT_WEBTREES')) {
}
$specialchar_languages = array(
- "af" => Zend_Locale::getTranslation('af', 'language', WT_LOCALE),
- "cs" => Zend_Locale::getTranslation('cs', 'language', WT_LOCALE),
- "sk" => Zend_Locale::getTranslation('sk', 'language', WT_LOCALE),
- "da" => Zend_Locale::getTranslation('da', 'language', WT_LOCALE),
- "de" => Zend_Locale::getTranslation('de', 'language', WT_LOCALE),
- "en_US" => Zend_Locale::getTranslation('en', 'language', WT_LOCALE),
- "es" => Zend_Locale::getTranslation('es', 'language', WT_LOCALE),
- "eu" => Zend_Locale::getTranslation('eu', 'language', WT_LOCALE),
- "fr" => Zend_Locale::getTranslation('fr', 'language', WT_LOCALE),
- "gd" => Zend_Locale::getTranslation('gd', 'language', WT_LOCALE),
- "el" => Zend_Locale::getTranslation('el', 'language', WT_LOCALE),
- "is" => Zend_Locale::getTranslation('is', 'language', WT_LOCALE),
- "it" => Zend_Locale::getTranslation('it', 'language', WT_LOCALE),
- "hu" => Zend_Locale::getTranslation('hu', 'language', WT_LOCALE),
- "lt" => Zend_Locale::getTranslation('lt', 'language', WT_LOCALE),
- "nl" => Zend_Locale::getTranslation('nl', 'language', WT_LOCALE),
- "nn" => Zend_Locale::getTranslation('nn', 'language', WT_LOCALE),
- "haw" => Zend_Locale::getTranslation('haw', 'language', WT_LOCALE),
- "pl" => Zend_Locale::getTranslation('pl', 'language', WT_LOCALE),
- "pt" => Zend_Locale::getTranslation('pt', 'language', WT_LOCALE),
- "sl" => Zend_Locale::getTranslation('sl', 'language', WT_LOCALE),
- "fi" => Zend_Locale::getTranslation('fi', 'language', WT_LOCALE),
- "sv" => Zend_Locale::getTranslation('sv', 'language', WT_LOCALE),
- "tr" => Zend_Locale::getTranslation('tr', 'language', WT_LOCALE),
- "he" => Zend_Locale::getTranslation('he', 'language', WT_LOCALE),
- "ar" => Zend_Locale::getTranslation('ar', 'language', WT_LOCALE),
- "ru" => Zend_Locale::getTranslation('ru', 'language', WT_LOCALE),
- "vi" => Zend_Locale::getTranslation('vi', 'language', WT_LOCALE),
+ "af" => WT_I18N::languageName('af'),
+ "ar" => WT_I18N::languageName('ar'),
+ "cs" => WT_I18N::languageName('cs'),
+ "da" => WT_I18N::languageName('da'),
+ "de" => WT_I18N::languageName('de'),
+ "el" => WT_I18N::languageName('el'),
+ "en" => WT_I18N::languageName('en'),
+ "es" => WT_I18N::languageName('es'),
+ "eu" => WT_I18N::languageName('eu'),
+ "fi" => WT_I18N::languageName('fi'),
+ "fr" => WT_I18N::languageName('fr'),
+ "gd" => WT_I18N::languageName('gd'),
+ "haw" => WT_I18N::languageName('haw'),
+ "he" => WT_I18N::languageName('he'),
+ "hu" => WT_I18N::languageName('hu'),
+ "is" => WT_I18N::languageName('is'),
+ "it" => WT_I18N::languageName('it'),
+ "lt" => WT_I18N::languageName('lt'),
+ "nl" => WT_I18N::languageName('nl'),
+ "nn" => WT_I18N::languageName('nn'),
+ "pl" => WT_I18N::languageName('pl'),
+ "pt" => WT_I18N::languageName('pt'),
+ "ru" => WT_I18N::languageName('ru'),
+ "sk" => WT_I18N::languageName('sk'),
+ "sl" => WT_I18N::languageName('sl'),
+ "sv" => WT_I18N::languageName('sv'),
+ "tr" => WT_I18N::languageName('tr'),
+ "vi" => WT_I18N::languageName('vi'),
);
switch ($language_filter) {
diff --git a/library/WT/I18N.php b/library/WT/I18N.php
index ecdad491b7..4ed1c3bcc6 100644
--- a/library/WT/I18N.php
+++ b/library/WT/I18N.php
@@ -39,7 +39,7 @@ class WT_I18N {
// Initialise the translation adapter with a locale setting.
// If null is passed, work out which language is needed from the environment.
- static public function init($locale=null) {
+ public static function init($locale=null) {
global $WT_SESSION;
// The translation libraries only work with a cache.
@@ -177,25 +177,21 @@ class WT_I18N {
}
// Check which languages are installed
- static public function installed_languages() {
+ public static function installed_languages() {
$mo_files=glob(WT_ROOT.'language'.DIRECTORY_SEPARATOR.'*.mo');
$cache_key=md5(serialize($mo_files));
if (!($installed_languages=self::$cache->load($cache_key))) {
$installed_languages=array();
foreach ($mo_files as $mo_file) {
- if (preg_match('/^(([a-z][a-z][a-z]?)(_[A-Z][A-Z])?)\.mo$/', basename($mo_file), $match)) {
- // launchpad does not support language variants.
- // Until it does, we cannot support languages such as sr@latin
- // See http://zendframework.com/issues/browse/ZF-7485
-
+ if (preg_match('/^(([a-z][a-z][a-z]?)([-_][A-Z][A-Z])?([-_][A-Za-z]+)*)\.mo$/', basename($mo_file), $match)) {
// Sort by the transation of the base language, then the variant.
// e.g. English|British English, Portuguese|Brazilian Portuguese
- $tmp1=Zend_Locale::getTranslation($match[1], 'language', $match[1]);
+ $tmp1 = WT_I18N::languageName($match[1]);
if ($match[1]==$match[2]) {
$tmp2=$tmp1;
} else {
- $tmp2=Zend_Locale::getTranslation($match[2], 'language', $match[2]);
+ $tmp2 = WT_I18N::languageName($match[2]);
}
$installed_languages[$match[1]]=$tmp2.'|'.$tmp1;
}
@@ -221,7 +217,7 @@ class WT_I18N {
}
// Generate i18n markup for the <html> tag, e.g. lang="ar" dir="rtl"
- static public function html_markup() {
+ public static function html_markup() {
$localeData=Zend_Locale_Data::getList(self::$locale, 'layout');
$dir=$localeData['characters']=='right-to-left' ? 'rtl' : 'ltr';
list($lang)=explode('_', self::$locale);
@@ -232,7 +228,7 @@ class WT_I18N {
// en: 12,345.67
// fr: 12 345,67
// de: 12.345,67
- static public function number($n, $precision=0) {
+ public static function number($n, $precision=0) {
// Add "punctuation" and convert digits
$n=Zend_Locale_Format::toNumber($n, array('locale'=>WT_LOCALE, 'precision'=>$precision));
$n=self::digits($n);
@@ -240,7 +236,7 @@ class WT_I18N {
}
// Convert the digits 0-9 into the local script
// Used for years, etc., where we do not want thousands-separators, decimals, etc.
- static public function digits($n) {
+ public static function digits($n) {
if (WT_NUMBERING_SYSTEM!='latn') {
return Zend_Locale_Format::convertNumerals($n, 'latn', WT_NUMBERING_SYSTEM);
} else {
@@ -252,7 +248,7 @@ class WT_I18N {
// en: 12.3%
// fr: 12,3 %
// de: 12,3%
- static public function percentage($n, $precision=0) {
+ public static function percentage($n, $precision=0) {
return
/* I18N: This is a percentage, such as “32.5%”. “%s” is the number, “%%” is the percent symbol. Some languages require a (non-breaking) space between the two, or a different symbol. */
WT_I18N::translate('%s%%', self::number($n*100.0, $precision));
@@ -260,7 +256,7 @@ class WT_I18N {
// echo WT_I18N::translate('Hello World!');
// echo WT_I18N::translate('The %s sat on the mat', 'cat');
- static public function translate(/* var_args */) {
+ public static function translate(/* var_args */) {
$args=func_get_args();
if (WT_DEBUG_LANG) {
$args[0]=WT_Debug::pseudoTranslate($args[0]);
@@ -273,7 +269,7 @@ class WT_I18N {
// Context sensitive version of translate.
// echo WT_I18N::translate_c('NOMINATIVE', 'January');
// echo WT_I18N::translate_c('GENITIVE', 'January');
- static public function translate_c(/* var_args */) {
+ public static function translate_c(/* var_args */) {
$args=func_get_args();
if (WT_DEBUG_LANG) {
$msgtxt=WT_Debug::pseudoTranslate($args[1]);
@@ -292,14 +288,14 @@ class WT_I18N {
// Similar to translate, but do perform "no operation" on it.
// This is necessary to fetch a format string (containing % characters) without
// performing sustitution of arguments.
- static public function noop($string) {
+ public static function noop($string) {
return Zend_Registry::get('Zend_Translate')->_($string);
}
// echo self::plural('There is an error', 'There are errors', $num_errors);
// echo self::plural('There is one error', 'There are %s errors', $num_errors);
// echo self::plural('There is %1$d %2$s cat', 'There are %1$d %2$s cats', $num, $num, $colour);
- static public function plural(/* var_args */) {
+ public static function plural(/* var_args */) {
$args=func_get_args();
if (WT_DEBUG_LANG) {
if ($args[2]==1) {
@@ -318,7 +314,7 @@ class WT_I18N {
// NB: The import function will have normalised this, so we don't need
// to worry about badly formatted strings
// NOTE: this function is not yet complete - eventually it will replace get_age_at_event()
- static public function gedcom_age($string) {
+ public static function gedcom_age($string) {
switch ($string) {
case 'STILLBORN':
// I18N: Description of an individual’s age at an event. e.g. Died 14 Jan 1900 (stillborn)
@@ -372,7 +368,7 @@ class WT_I18N {
}
// Convert a number of seconds into a relative time. e.g. 630 => "10 hours, 30 minutes ago"
- static function time_ago($seconds) {
+ public static function time_ago($seconds) {
$year=365*24*60*60;
$month=30*24*60*60;
$day=24*60*60;
@@ -403,8 +399,81 @@ class WT_I18N {
}
}
+ // Return the endonym for a given language - as per http://cldr.unicode.org/
+ public static function languageName($language) {
+ switch (str_replace(array('_', '@'), '-', $language)) {
+ case 'af': return 'Afrikaans';
+ case 'ar': return 'العربية';
+ case 'bg': return 'български';
+ case 'bs': return 'bosanski';
+ case 'ca': return 'català';
+ case 'cs': return 'čeština';
+ case 'da': return 'dansk';
+ case 'de': return 'Deutsch';
+ case 'dv': return 'ދިވެހިބަސް';
+ case 'el': return 'Ελληνικά';
+ case 'en': return 'English';
+ case 'en-AU': return 'Australian English';
+ case 'en-GB': return 'British English';
+ case 'en-US': return 'U.S. English';
+ case 'es': return 'español';
+ case 'et': return 'eesti';
+ case 'fa': return 'فارسی';
+ case 'fi': return 'suomi';
+ case 'fo': return 'føroyskt';
+ case 'fr': return 'français';
+ case 'fr-CA': return 'français canadien';
+ case 'gl': return 'galego';
+ case 'haw': return 'ʻŌlelo Hawaiʻi';
+ case 'he': return 'עברית';
+ case 'hr': return 'hrvatski';
+ case 'hu': return 'magyar';
+ case 'id': return 'Bahasa Indonesia';
+ case 'is': return 'íslenska';
+ case 'it': return 'italiano';
+ case 'ja': return '日本語';
+ case 'ka': return 'ქართული';
+ case 'ko': return '한국어';
+ case 'lt': return 'lietuvių';
+ case 'lv': return 'latviešu';
+ case 'mi': return 'Māori';
+ case 'mr': return 'मराठी';
+ case 'ms': return 'Bahasa Melayu';
+ case 'nb': return 'norsk bokmål';
+ case 'ne': return 'नेपाली';
+ case 'nl': return 'Nederlands';
+ case 'nn': return 'nynorsk';
+ case 'oc': return 'occitan';
+ case 'pl': return 'polski';
+ case 'pt': return 'português';
+ case 'pt-BR': return 'português do Brasil';
+ case 'ro': return 'română';
+ case 'ru': return 'русский';
+ case 'sk': return 'slovenčina';
+ case 'sl': return 'slovenščina';
+ case 'sr': return 'Српски';
+ case 'sr-Latn': return 'srpski';
+ case 'sv': return 'svenska';
+ case 'ta': return 'தமிழ்';
+ case 'tr': return 'Türkçe';
+ case 'tt': return 'Татар';
+ case 'uk': return 'українська';
+ case 'vi': return 'Tiếng Việt';
+ case 'yi': return 'ייִדיש';
+ case 'zh': return '中文';
+ case 'zh-CN': return '简体中文'; // Simplified Chinese
+ case 'zh-TW': return '繁體中文'; // Traditional Chinese
+ default:
+ // Use the PHP/intl library, if it exists
+ if (class_exists('\\Locale')) {
+ return Locale::getDisplayName($language, $language);
+ }
+ return $language;
+ }
+ }
+
// Generate consistent I18N for datatables.js
- static function datatablesI18N(array $lengths=null) {
+ public static function datatablesI18N(array $lengths=null) {
if ($lengths===null) {
$lengths=array(10, 20, 30, 50, 100, -1);
}
diff --git a/message.php b/message.php
index 2eb7a00d3d..2b4cbb206f 100644
--- a/message.php
+++ b/message.php
@@ -122,7 +122,7 @@ case 'compose':
echo '<table>';
if ($to != 'all' && $to != 'last_6mo' && $to != 'never_logged') {
echo '<tr><td></td><td>', WT_I18N::translate('This message will be sent to %s', '<b>'.getUserFullName($to_user_id).'</b>'), '<br>';
- echo /* I18N: %s is the name of a language */ WT_I18N::translate('This user prefers to receive messages in %s', Zend_Locale::getTranslation(get_user_setting($to_user_id, 'language'), 'language', WT_LOCALE)), '</td></tr>';
+ echo /* I18N: %s is the name of a language */ WT_I18N::translate('This user prefers to receive messages in %s', WT_I18N::languageName(get_user_setting($to_user_id, 'language'))), '</td></tr>';
}
if (!WT_USER_ID) {
echo '<tr><td valign="top" width="15%" align="right">', WT_I18N::translate('Your Name:'), '</td>';
diff --git a/modules_v3/GEDFact_assistant/CENS_ctrl.php b/modules_v3/GEDFact_assistant/CENS_ctrl.php
index 2165ff7077..b103107c43 100644
--- a/modules_v3/GEDFact_assistant/CENS_ctrl.php
+++ b/modules_v3/GEDFact_assistant/CENS_ctrl.php
@@ -59,6 +59,7 @@ echo '</h3>';
<input id="pid_array" type="hidden" name="pid_array" value="none">
<input id="xref" type="hidden" name="xref" value=<?php echo $xref; ?>>
<?php
+ echo WT_Filter::getCsrf();
global $tabno, $linkToID, $SEARCH_SPIDER;
global $SHOW_AGE_DIFF, $GEDCOM;
diff --git a/themes/_administration/css-1.5.1/style.css b/themes/_administration/css-1.5.1/style.css
index 9feb7f26c2..06d368a33d 100644
--- a/themes/_administration/css-1.5.1/style.css
+++ b/themes/_administration/css-1.5.1/style.css
@@ -150,7 +150,7 @@ html[dir=rtl] #tree_stats th, html[dir=rtl] #recent th {padding:0 0 0 10px; text
html[dir=rtl] #tree_stats td, html[dir=rtl] #recent td {padding:0 0 0 10px; text-align:left;}
#tree_stats .ui-accordion-content, #recent2 .ui-accordion-content {padding:1em; min-height:140px;}
#tree_stats.ui-widget, #changes.ui-widget {font-size:100% !important;}
-#trees span, #recent2 span {text-decoration:underline;}
+#trees thead, #recent2 thead {text-decoration:underline;}
#x h2, #x h3 {padding:0 25px;}
/* SITE ACCESS */