@@ -35,16 +35,16 @@ discard block |
||
| 35 | 35 | |
| 36 | 36 | // The default view depends on whether we are logged in |
| 37 | 37 | if (Auth::check()) { |
| 38 | - $ctype = Filter::get('ctype', 'gedcom|user', 'user'); |
|
| 38 | + $ctype = Filter::get('ctype', 'gedcom|user', 'user'); |
|
| 39 | 39 | } else { |
| 40 | - $ctype = 'gedcom'; |
|
| 40 | + $ctype = 'gedcom'; |
|
| 41 | 41 | } |
| 42 | 42 | |
| 43 | 43 | // Get the blocks list |
| 44 | 44 | if ($ctype === 'user') { |
| 45 | - $blocks = FunctionsDb::getUserBlocks(Auth::id()); |
|
| 45 | + $blocks = FunctionsDb::getUserBlocks(Auth::id()); |
|
| 46 | 46 | } else { |
| 47 | - $blocks = FunctionsDb::getTreeBlocks($WT_TREE->getTreeId()); |
|
| 47 | + $blocks = FunctionsDb::getTreeBlocks($WT_TREE->getTreeId()); |
|
| 48 | 48 | } |
| 49 | 49 | |
| 50 | 50 | $active_blocks = Module::getActiveBlocks($WT_TREE); |
@@ -54,91 +54,91 @@ discard block |
||
| 54 | 54 | |
| 55 | 55 | // We generate individual blocks using AJAX |
| 56 | 56 | if ($action === 'ajax') { |
| 57 | - $controller = new AjaxController; |
|
| 58 | - $controller->pageHeader(); |
|
| 57 | + $controller = new AjaxController; |
|
| 58 | + $controller->pageHeader(); |
|
| 59 | 59 | |
| 60 | - // Check we’re displaying an allowable block. |
|
| 61 | - $block_id = Filter::getInteger('block_id'); |
|
| 62 | - if (array_key_exists($block_id, $blocks['main'])) { |
|
| 63 | - $module_name = $blocks['main'][$block_id]; |
|
| 64 | - } elseif (array_key_exists($block_id, $blocks['side'])) { |
|
| 65 | - $module_name = $blocks['side'][$block_id]; |
|
| 66 | - } else { |
|
| 67 | - return; |
|
| 68 | - } |
|
| 69 | - if (array_key_exists($module_name, $active_blocks)) { |
|
| 70 | - echo $active_blocks[$module_name]->getBlock($block_id); |
|
| 71 | - } |
|
| 60 | + // Check we’re displaying an allowable block. |
|
| 61 | + $block_id = Filter::getInteger('block_id'); |
|
| 62 | + if (array_key_exists($block_id, $blocks['main'])) { |
|
| 63 | + $module_name = $blocks['main'][$block_id]; |
|
| 64 | + } elseif (array_key_exists($block_id, $blocks['side'])) { |
|
| 65 | + $module_name = $blocks['side'][$block_id]; |
|
| 66 | + } else { |
|
| 67 | + return; |
|
| 68 | + } |
|
| 69 | + if (array_key_exists($module_name, $active_blocks)) { |
|
| 70 | + echo $active_blocks[$module_name]->getBlock($block_id); |
|
| 71 | + } |
|
| 72 | 72 | |
| 73 | - return; |
|
| 73 | + return; |
|
| 74 | 74 | } |
| 75 | 75 | |
| 76 | 76 | // Redirect search engines to the full URL |
| 77 | 77 | if (Filter::get('ctype') !== $ctype || Filter::get('ged') !== $WT_TREE->getName()) { |
| 78 | - header('Location: ' . WT_BASE_URL . 'index.php?ctype=' . $ctype . '&ged=' . $WT_TREE->getNameUrl()); |
|
| 78 | + header('Location: ' . WT_BASE_URL . 'index.php?ctype=' . $ctype . '&ged=' . $WT_TREE->getNameUrl()); |
|
| 79 | 79 | |
| 80 | - return; |
|
| 80 | + return; |
|
| 81 | 81 | } |
| 82 | 82 | |
| 83 | 83 | $controller = new PageController; |
| 84 | 84 | if ($ctype === 'user') { |
| 85 | - $controller->restrictAccess(Auth::check()); |
|
| 85 | + $controller->restrictAccess(Auth::check()); |
|
| 86 | 86 | } |
| 87 | 87 | $controller |
| 88 | - ->setPageTitle($ctype === 'user' ? I18N::translate('My page') : $WT_TREE->getTitle()) |
|
| 89 | - ->setMetaRobots('index,follow') |
|
| 90 | - ->pageHeader() |
|
| 91 | - // By default jQuery modifies AJAX URLs to disable caching, causing JS libraries to be loaded many times. |
|
| 92 | - ->addInlineJavascript('jQuery.ajaxSetup({cache:true});'); |
|
| 88 | + ->setPageTitle($ctype === 'user' ? I18N::translate('My page') : $WT_TREE->getTitle()) |
|
| 89 | + ->setMetaRobots('index,follow') |
|
| 90 | + ->pageHeader() |
|
| 91 | + // By default jQuery modifies AJAX URLs to disable caching, causing JS libraries to be loaded many times. |
|
| 92 | + ->addInlineJavascript('jQuery.ajaxSetup({cache:true});'); |
|
| 93 | 93 | |
| 94 | 94 | if ($ctype === 'user') { |
| 95 | - echo '<div id="my-page">'; |
|
| 96 | - echo '<h2 class="center">', I18N::translate('My page'), '</h2>'; |
|
| 95 | + echo '<div id="my-page">'; |
|
| 96 | + echo '<h2 class="center">', I18N::translate('My page'), '</h2>'; |
|
| 97 | 97 | } else { |
| 98 | - echo '<div id="home-page">'; |
|
| 98 | + echo '<div id="home-page">'; |
|
| 99 | 99 | } |
| 100 | 100 | if ($blocks['main']) { |
| 101 | - if ($blocks['side']) { |
|
| 102 | - echo '<div id="index_main_blocks">'; |
|
| 103 | - } else { |
|
| 104 | - echo '<div id="index_full_blocks">'; |
|
| 105 | - } |
|
| 106 | - foreach ($blocks['main'] as $block_id => $module_name) { |
|
| 107 | - if (array_key_exists($module_name, $active_blocks)) { |
|
| 108 | - if (Auth::isSearchEngine() || !$active_blocks[$module_name]->loadAjax()) { |
|
| 109 | - // Load the block directly |
|
| 110 | - echo $active_blocks[$module_name]->getBlock($block_id); |
|
| 111 | - } else { |
|
| 112 | - // Load the block asynchronously |
|
| 113 | - echo '<div id="block_', $block_id, '"><div class="loading-image"></div></div>'; |
|
| 114 | - $controller->addInlineJavascript( |
|
| 115 | - 'jQuery("#block_' . $block_id . '").load("index.php?ctype=' . $ctype . '&action=ajax&block_id=' . $block_id . '");' |
|
| 116 | - ); |
|
| 117 | - } |
|
| 118 | - } |
|
| 119 | - } |
|
| 120 | - echo '</div>'; |
|
| 101 | + if ($blocks['side']) { |
|
| 102 | + echo '<div id="index_main_blocks">'; |
|
| 103 | + } else { |
|
| 104 | + echo '<div id="index_full_blocks">'; |
|
| 105 | + } |
|
| 106 | + foreach ($blocks['main'] as $block_id => $module_name) { |
|
| 107 | + if (array_key_exists($module_name, $active_blocks)) { |
|
| 108 | + if (Auth::isSearchEngine() || !$active_blocks[$module_name]->loadAjax()) { |
|
| 109 | + // Load the block directly |
|
| 110 | + echo $active_blocks[$module_name]->getBlock($block_id); |
|
| 111 | + } else { |
|
| 112 | + // Load the block asynchronously |
|
| 113 | + echo '<div id="block_', $block_id, '"><div class="loading-image"></div></div>'; |
|
| 114 | + $controller->addInlineJavascript( |
|
| 115 | + 'jQuery("#block_' . $block_id . '").load("index.php?ctype=' . $ctype . '&action=ajax&block_id=' . $block_id . '");' |
|
| 116 | + ); |
|
| 117 | + } |
|
| 118 | + } |
|
| 119 | + } |
|
| 120 | + echo '</div>'; |
|
| 121 | 121 | } |
| 122 | 122 | if ($blocks['side']) { |
| 123 | - if ($blocks['main']) { |
|
| 124 | - echo '<div id="index_small_blocks">'; |
|
| 125 | - } else { |
|
| 126 | - echo '<div id="index_full_blocks">'; |
|
| 127 | - } |
|
| 128 | - foreach ($blocks['side'] as $block_id => $module_name) { |
|
| 129 | - if (array_key_exists($module_name, $active_blocks)) { |
|
| 130 | - if (Auth::isSearchEngine() || !$active_blocks[$module_name]->loadAjax()) { |
|
| 131 | - // Load the block directly |
|
| 132 | - echo $active_blocks[$module_name]->getBlock($block_id); |
|
| 133 | - } else { |
|
| 134 | - // Load the block asynchronously |
|
| 135 | - echo '<div id="block_', $block_id, '"><div class="loading-image"></div></div>'; |
|
| 136 | - $controller->addInlineJavascript( |
|
| 137 | - 'jQuery("#block_' . $block_id . '").load("index.php?ctype=' . $ctype . '&action=ajax&block_id=' . $block_id . '");' |
|
| 138 | - ); |
|
| 139 | - } |
|
| 140 | - } |
|
| 141 | - } |
|
| 142 | - echo '</div>'; |
|
| 123 | + if ($blocks['main']) { |
|
| 124 | + echo '<div id="index_small_blocks">'; |
|
| 125 | + } else { |
|
| 126 | + echo '<div id="index_full_blocks">'; |
|
| 127 | + } |
|
| 128 | + foreach ($blocks['side'] as $block_id => $module_name) { |
|
| 129 | + if (array_key_exists($module_name, $active_blocks)) { |
|
| 130 | + if (Auth::isSearchEngine() || !$active_blocks[$module_name]->loadAjax()) { |
|
| 131 | + // Load the block directly |
|
| 132 | + echo $active_blocks[$module_name]->getBlock($block_id); |
|
| 133 | + } else { |
|
| 134 | + // Load the block asynchronously |
|
| 135 | + echo '<div id="block_', $block_id, '"><div class="loading-image"></div></div>'; |
|
| 136 | + $controller->addInlineJavascript( |
|
| 137 | + 'jQuery("#block_' . $block_id . '").load("index.php?ctype=' . $ctype . '&action=ajax&block_id=' . $block_id . '");' |
|
| 138 | + ); |
|
| 139 | + } |
|
| 140 | + } |
|
| 141 | + } |
|
| 142 | + echo '</div>'; |
|
| 143 | 143 | } |
| 144 | 144 | echo '</div>'; |
@@ -32,85 +32,85 @@ |
||
| 32 | 32 | |
| 33 | 33 | $controller = new PageController; |
| 34 | 34 | $controller |
| 35 | - ->restrictAccess(Auth::isAdmin()) |
|
| 36 | - ->setPageTitle(I18N::translate('Module administration')); |
|
| 35 | + ->restrictAccess(Auth::isAdmin()) |
|
| 36 | + ->setPageTitle(I18N::translate('Module administration')); |
|
| 37 | 37 | |
| 38 | 38 | $modules = Module::getInstalledModules('disabled'); |
| 39 | 39 | $module_status = Database::prepare("SELECT module_name, status FROM `##module`")->fetchAssoc(); |
| 40 | 40 | |
| 41 | 41 | uasort($modules, function (AbstractModule $x, AbstractModule $y) { |
| 42 | - return I18N::strcasecmp($x->getTitle(), $y->getTitle()); |
|
| 42 | + return I18N::strcasecmp($x->getTitle(), $y->getTitle()); |
|
| 43 | 43 | }); |
| 44 | 44 | |
| 45 | 45 | if (Filter::post('action') === 'update_mods' && Filter::checkCsrf()) { |
| 46 | - foreach ($modules as $module) { |
|
| 47 | - $new_status = Filter::post('status-' . $module->getName(), '[01]'); |
|
| 48 | - if ($new_status !== null) { |
|
| 49 | - $new_status = $new_status ? 'enabled' : 'disabled'; |
|
| 50 | - $old_status = $module_status[$module->getName()]; |
|
| 51 | - if ($new_status !== $old_status) { |
|
| 52 | - Database::prepare("UPDATE `##module` SET status=? WHERE module_name=?")->execute(array($new_status, $module->getName())); |
|
| 53 | - if ($new_status === 'disabled') { |
|
| 54 | - FlashMessages::addMessage(I18N::translate('The module “%s” has been disabled.', $module->getTitle()), 'success'); |
|
| 55 | - } else { |
|
| 56 | - FlashMessages::addMessage(I18N::translate('The module “%s” has been enabled.', $module->getTitle()), 'success'); |
|
| 57 | - } |
|
| 58 | - } |
|
| 59 | - } |
|
| 60 | - } |
|
| 46 | + foreach ($modules as $module) { |
|
| 47 | + $new_status = Filter::post('status-' . $module->getName(), '[01]'); |
|
| 48 | + if ($new_status !== null) { |
|
| 49 | + $new_status = $new_status ? 'enabled' : 'disabled'; |
|
| 50 | + $old_status = $module_status[$module->getName()]; |
|
| 51 | + if ($new_status !== $old_status) { |
|
| 52 | + Database::prepare("UPDATE `##module` SET status=? WHERE module_name=?")->execute(array($new_status, $module->getName())); |
|
| 53 | + if ($new_status === 'disabled') { |
|
| 54 | + FlashMessages::addMessage(I18N::translate('The module “%s” has been disabled.', $module->getTitle()), 'success'); |
|
| 55 | + } else { |
|
| 56 | + FlashMessages::addMessage(I18N::translate('The module “%s” has been enabled.', $module->getTitle()), 'success'); |
|
| 57 | + } |
|
| 58 | + } |
|
| 59 | + } |
|
| 60 | + } |
|
| 61 | 61 | |
| 62 | - header('Location: ' . WT_BASE_URL . 'admin_modules.php'); |
|
| 62 | + header('Location: ' . WT_BASE_URL . 'admin_modules.php'); |
|
| 63 | 63 | |
| 64 | - return; |
|
| 64 | + return; |
|
| 65 | 65 | } |
| 66 | 66 | |
| 67 | 67 | if (Filter::post('action') === 'delete' && Filter::checkCsrf()) { |
| 68 | - $module_name = Filter::post('module_name'); |
|
| 69 | - Database::prepare( |
|
| 70 | - "DELETE `##block_setting`" . |
|
| 71 | - " FROM `##block_setting`" . |
|
| 72 | - " JOIN `##block` USING (block_id)" . |
|
| 73 | - " JOIN `##module` USING (module_name)" . |
|
| 74 | - " WHERE module_name=?" |
|
| 75 | - )->execute(array($module_name)); |
|
| 76 | - Database::prepare( |
|
| 77 | - "DELETE `##block`" . |
|
| 78 | - " FROM `##block`" . |
|
| 79 | - " JOIN `##module` USING (module_name)" . |
|
| 80 | - " WHERE module_name=?" |
|
| 81 | - )->execute(array($module_name)); |
|
| 82 | - Database::prepare("DELETE FROM `##module_setting` WHERE module_name=?")->execute(array($module_name)); |
|
| 83 | - Database::prepare("DELETE FROM `##module_privacy` WHERE module_name=?")->execute(array($module_name)); |
|
| 84 | - Database::prepare("DELETE FROM `##module` WHERE module_name=?")->execute(array($module_name)); |
|
| 68 | + $module_name = Filter::post('module_name'); |
|
| 69 | + Database::prepare( |
|
| 70 | + "DELETE `##block_setting`" . |
|
| 71 | + " FROM `##block_setting`" . |
|
| 72 | + " JOIN `##block` USING (block_id)" . |
|
| 73 | + " JOIN `##module` USING (module_name)" . |
|
| 74 | + " WHERE module_name=?" |
|
| 75 | + )->execute(array($module_name)); |
|
| 76 | + Database::prepare( |
|
| 77 | + "DELETE `##block`" . |
|
| 78 | + " FROM `##block`" . |
|
| 79 | + " JOIN `##module` USING (module_name)" . |
|
| 80 | + " WHERE module_name=?" |
|
| 81 | + )->execute(array($module_name)); |
|
| 82 | + Database::prepare("DELETE FROM `##module_setting` WHERE module_name=?")->execute(array($module_name)); |
|
| 83 | + Database::prepare("DELETE FROM `##module_privacy` WHERE module_name=?")->execute(array($module_name)); |
|
| 84 | + Database::prepare("DELETE FROM `##module` WHERE module_name=?")->execute(array($module_name)); |
|
| 85 | 85 | |
| 86 | - FlashMessages::addMessage(I18N::translate('The preferences for the module “%s” have been deleted.', $module_name), 'success'); |
|
| 86 | + FlashMessages::addMessage(I18N::translate('The preferences for the module “%s” have been deleted.', $module_name), 'success'); |
|
| 87 | 87 | |
| 88 | - header('Location: ' . WT_BASE_URL . 'admin_modules.php'); |
|
| 88 | + header('Location: ' . WT_BASE_URL . 'admin_modules.php'); |
|
| 89 | 89 | |
| 90 | - return; |
|
| 90 | + return; |
|
| 91 | 91 | } |
| 92 | 92 | |
| 93 | 93 | // The module can’t be found on disk? |
| 94 | 94 | // Don't delete it automatically. It may be temporarily missing, after a re-installation, etc. |
| 95 | 95 | foreach ($module_status as $module_name => $status) { |
| 96 | - if (!array_key_exists($module_name, $modules)) { |
|
| 97 | - $html = |
|
| 98 | - I18N::translate('Preferences exist for the module “%s”, but this module no longer exists.', '<span dir="ltr">' . $module_name . '</span>') . |
|
| 99 | - '<form method="post" class="form-inline">' . |
|
| 100 | - Filter::getCsrf() . |
|
| 101 | - '<input type="hidden" name="action" value="delete">' . |
|
| 102 | - '<input type="hidden" name="module_name" value="' . $module_name . '">' . |
|
| 103 | - '<button type="submit" class="btn btn-link">' . I18N::translate('Delete the preferences for this module.') . '</button>' . |
|
| 104 | - '</form>'; |
|
| 105 | - FlashMessages::addMessage($html, 'warning'); |
|
| 106 | - } |
|
| 96 | + if (!array_key_exists($module_name, $modules)) { |
|
| 97 | + $html = |
|
| 98 | + I18N::translate('Preferences exist for the module “%s”, but this module no longer exists.', '<span dir="ltr">' . $module_name . '</span>') . |
|
| 99 | + '<form method="post" class="form-inline">' . |
|
| 100 | + Filter::getCsrf() . |
|
| 101 | + '<input type="hidden" name="action" value="delete">' . |
|
| 102 | + '<input type="hidden" name="module_name" value="' . $module_name . '">' . |
|
| 103 | + '<button type="submit" class="btn btn-link">' . I18N::translate('Delete the preferences for this module.') . '</button>' . |
|
| 104 | + '</form>'; |
|
| 105 | + FlashMessages::addMessage($html, 'warning'); |
|
| 106 | + } |
|
| 107 | 107 | } |
| 108 | 108 | |
| 109 | 109 | $controller |
| 110 | - ->pageHeader() |
|
| 111 | - ->addExternalJavascript(WT_JQUERY_DATATABLES_JS_URL) |
|
| 112 | - ->addExternalJavascript(WT_DATATABLES_BOOTSTRAP_JS_URL) |
|
| 113 | - ->addInlineJavascript(' |
|
| 110 | + ->pageHeader() |
|
| 111 | + ->addExternalJavascript(WT_JQUERY_DATATABLES_JS_URL) |
|
| 112 | + ->addExternalJavascript(WT_DATATABLES_BOOTSTRAP_JS_URL) |
|
| 113 | + ->addInlineJavascript(' |
|
| 114 | 114 | function reindexMods(id) { |
| 115 | 115 | jQuery("#" + id + " input").each( |
| 116 | 116 | function (index, value) { |
@@ -176,9 +176,12 @@ discard block |
||
| 176 | 176 | <a href="<?php echo $module->getConfigLink() ?>"> |
| 177 | 177 | <?php echo $module->getTitle() ?> <i class="fa fa-cogs"></i> |
| 178 | 178 | </a> |
| 179 | - <?php else: ?> |
|
| 179 | + <?php else { |
|
| 180 | + : ?> |
|
| 180 | 181 | <?php echo $module->getTitle() ?> |
| 181 | - <?php endif; ?> |
|
| 182 | + <?php endif; |
|
| 183 | +} |
|
| 184 | +?> |
|
| 182 | 185 | <?php if (!in_array($module->getName(), Module::getCoreModuleNames())): ?> |
| 183 | 186 | <br> |
| 184 | 187 | <?php endif; ?> |
@@ -202,23 +205,32 @@ discard block |
||
| 202 | 205 | <td class="text-center text-muted hidden-xs"> |
| 203 | 206 | <?php if ($module instanceof ModuleMenuInterface): ?> |
| 204 | 207 | <i class="fa fa-list-ul" title="<?php echo I18N::translate('Menu') ?>"></i> |
| 205 | - <?php else: ?> |
|
| 208 | + <?php else { |
|
| 209 | + : ?> |
|
| 206 | 210 | - |
| 207 | - <?php endif; ?> |
|
| 211 | + <?php endif; |
|
| 212 | +} |
|
| 213 | +?> |
|
| 208 | 214 | </td> |
| 209 | 215 | <td class="text-center text-muted hidden-xs"> |
| 210 | 216 | <?php if ($module instanceof ModuleTabInterface): ?> |
| 211 | 217 | <i class="fa fa-folder" title="<?php echo I18N::translate('Tab') ?>"></i> |
| 212 | - <?php else: ?> |
|
| 218 | + <?php else { |
|
| 219 | + : ?> |
|
| 213 | 220 | - |
| 214 | - <?php endif; ?> |
|
| 221 | + <?php endif; |
|
| 222 | +} |
|
| 223 | +?> |
|
| 215 | 224 | </td> |
| 216 | 225 | <td class="text-center text-muted hidden-xs"> |
| 217 | 226 | <?php if ($module instanceof ModuleSidebarInterface): ?> |
| 218 | 227 | <i class="fa fa-th-large" title="<?php echo I18N::translate('Sidebar') ?>"></i> |
| 219 | - <?php else: ?> |
|
| 228 | + <?php else { |
|
| 229 | + : ?> |
|
| 220 | 230 | - |
| 221 | - <?php endif; ?> |
|
| 231 | + <?php endif; |
|
| 232 | +} |
|
| 233 | +?> |
|
| 222 | 234 | </td> |
| 223 | 235 | <td class="text-center text-muted hidden-xs"> |
| 224 | 236 | <?php if ($module instanceof ModuleBlockInterface): ?> |
@@ -228,30 +240,42 @@ discard block |
||
| 228 | 240 | <?php if ($module->isUserBlock()): ?> |
| 229 | 241 | <i class="fa fa-tree" title="<?php echo I18N::translate('Home page') ?>"></i> |
| 230 | 242 | <?php endif; ?> |
| 231 | - <?php else: ?> |
|
| 243 | + <?php else { |
|
| 244 | + : ?> |
|
| 232 | 245 | - |
| 233 | - <?php endif; ?> |
|
| 246 | + <?php endif; |
|
| 247 | +} |
|
| 248 | +?> |
|
| 234 | 249 | </td> |
| 235 | 250 | <td class="text-center text-muted hidden-xs"> |
| 236 | 251 | <?php if ($module instanceof ModuleChartInterface): ?> |
| 237 | 252 | <i class="fa fa-share-alt" title="<?php echo I18N::translate('Chart') ?>"></i> |
| 238 | - <?php else: ?> |
|
| 253 | + <?php else { |
|
| 254 | + : ?> |
|
| 239 | 255 | - |
| 240 | - <?php endif; ?> |
|
| 256 | + <?php endif; |
|
| 257 | +} |
|
| 258 | +?> |
|
| 241 | 259 | </td> |
| 242 | 260 | <td class="text-center text-muted hidden-xs"> |
| 243 | 261 | <?php if ($module instanceof ModuleReportInterface): ?> |
| 244 | 262 | <i class="fa fa-file" title="<?php echo I18N::translate('Report') ?>"></i> |
| 245 | - <?php else: ?> |
|
| 263 | + <?php else { |
|
| 264 | + : ?> |
|
| 246 | 265 | - |
| 247 | - <?php endif; ?> |
|
| 266 | + <?php endif; |
|
| 267 | +} |
|
| 268 | +?> |
|
| 248 | 269 | </td> |
| 249 | 270 | <td class="text-center text-muted hidden"> |
| 250 | 271 | <?php if ($module instanceof ModuleThemeInterface): ?> |
| 251 | 272 | <i class="fa fa-check" title="<?php echo I18N::translate('Theme') ?>"></i> |
| 252 | - <?php else: ?> |
|
| 273 | + <?php else { |
|
| 274 | + : ?> |
|
| 253 | 275 | - |
| 254 | - <?php endif; ?> |
|
| 276 | + <?php endif; |
|
| 277 | +} |
|
| 278 | +?> |
|
| 255 | 279 | </td> |
| 256 | 280 | </tr> |
| 257 | 281 | <?php endforeach; ?> |
@@ -23,45 +23,45 @@ discard block |
||
| 23 | 23 | |
| 24 | 24 | $to_delete = Filter::postArray('to_delete'); |
| 25 | 25 | if ($to_delete && Filter::checkCsrf()) { |
| 26 | - foreach ($to_delete as $path) { |
|
| 27 | - $is_dir = is_dir(WT_DATA_DIR . $path); |
|
| 28 | - if (File::delete(WT_DATA_DIR . $path)) { |
|
| 29 | - if ($is_dir) { |
|
| 30 | - FlashMessages::addMessage(I18N::translate('The folder %s has been deleted.', Filter::escapeHtml($path)), 'success'); |
|
| 31 | - } else { |
|
| 32 | - FlashMessages::addMessage(I18N::translate('The file %s has been deleted.', Filter::escapeHtml($path)), 'success'); |
|
| 33 | - } |
|
| 34 | - } else { |
|
| 35 | - if ($is_dir) { |
|
| 36 | - FlashMessages::addMessage(I18N::translate('The folder %s could not be deleted.', Filter::escapeHtml($path)), 'danger'); |
|
| 37 | - } else { |
|
| 38 | - FlashMessages::addMessage(I18N::translate('The file %s could not be deleted.', Filter::escapeHtml($path)), 'danger'); |
|
| 39 | - } |
|
| 40 | - } |
|
| 41 | - } |
|
| 42 | - |
|
| 43 | - header('Location: ' . WT_BASE_URL . WT_SCRIPT_NAME); |
|
| 44 | - |
|
| 45 | - return; |
|
| 26 | + foreach ($to_delete as $path) { |
|
| 27 | + $is_dir = is_dir(WT_DATA_DIR . $path); |
|
| 28 | + if (File::delete(WT_DATA_DIR . $path)) { |
|
| 29 | + if ($is_dir) { |
|
| 30 | + FlashMessages::addMessage(I18N::translate('The folder %s has been deleted.', Filter::escapeHtml($path)), 'success'); |
|
| 31 | + } else { |
|
| 32 | + FlashMessages::addMessage(I18N::translate('The file %s has been deleted.', Filter::escapeHtml($path)), 'success'); |
|
| 33 | + } |
|
| 34 | + } else { |
|
| 35 | + if ($is_dir) { |
|
| 36 | + FlashMessages::addMessage(I18N::translate('The folder %s could not be deleted.', Filter::escapeHtml($path)), 'danger'); |
|
| 37 | + } else { |
|
| 38 | + FlashMessages::addMessage(I18N::translate('The file %s could not be deleted.', Filter::escapeHtml($path)), 'danger'); |
|
| 39 | + } |
|
| 40 | + } |
|
| 41 | + } |
|
| 42 | + |
|
| 43 | + header('Location: ' . WT_BASE_URL . WT_SCRIPT_NAME); |
|
| 44 | + |
|
| 45 | + return; |
|
| 46 | 46 | } |
| 47 | 47 | |
| 48 | 48 | $controller = new PageController; |
| 49 | 49 | $controller |
| 50 | - ->restrictAccess(Auth::isAdmin()) |
|
| 51 | - ->setPageTitle(/* I18N: The “Data folder” is a configuration setting */ I18N::translate('Clean up data folder')) |
|
| 52 | - ->pageHeader(); |
|
| 50 | + ->restrictAccess(Auth::isAdmin()) |
|
| 51 | + ->setPageTitle(/* I18N: The “Data folder” is a configuration setting */ I18N::translate('Clean up data folder')) |
|
| 52 | + ->pageHeader(); |
|
| 53 | 53 | |
| 54 | 54 | $do_not_delete = array('index.php', 'config.ini.php', 'language'); |
| 55 | 55 | |
| 56 | 56 | // If we are storing the media in the data folder (this is the default), then don’t delete it. |
| 57 | 57 | foreach (Tree::getAll() as $tree) { |
| 58 | - $MEDIA_DIRECTORY = $tree->getPreference('MEDIA_DIRECTORY'); |
|
| 58 | + $MEDIA_DIRECTORY = $tree->getPreference('MEDIA_DIRECTORY'); |
|
| 59 | 59 | |
| 60 | - if (substr($MEDIA_DIRECTORY, 0, 3) != '../') { |
|
| 61 | - // Just need to add the first part of the path |
|
| 62 | - $tmp = explode('/', $MEDIA_DIRECTORY); |
|
| 63 | - $do_not_delete[] = $tmp[0]; |
|
| 64 | - } |
|
| 60 | + if (substr($MEDIA_DIRECTORY, 0, 3) != '../') { |
|
| 61 | + // Just need to add the first part of the path |
|
| 62 | + $tmp = explode('/', $MEDIA_DIRECTORY); |
|
| 63 | + $do_not_delete[] = $tmp[0]; |
|
| 64 | + } |
|
| 65 | 65 | } |
| 66 | 66 | |
| 67 | 67 | $locked_icon = '<i class="fa fa-ban text-danger"></i>'; |
@@ -69,9 +69,9 @@ discard block |
||
| 69 | 69 | $dir = dir(WT_DATA_DIR); |
| 70 | 70 | $entries = array(); |
| 71 | 71 | while (false !== ($entry = $dir->read())) { |
| 72 | - if ($entry[0] != '.') { |
|
| 73 | - $entries[] = $entry; |
|
| 74 | - } |
|
| 72 | + if ($entry[0] != '.') { |
|
| 73 | + $entries[] = $entry; |
|
| 74 | + } |
|
| 75 | 75 | } |
| 76 | 76 | |
| 77 | 77 | sort($entries); |
@@ -94,20 +94,20 @@ discard block |
||
| 94 | 94 | <legend class="sr-only"><?php echo $controller->getPageTitle(); ?></legend> |
| 95 | 95 | <ul class="fa-ul"> |
| 96 | 96 | <?php |
| 97 | - foreach ($entries as $entry) { |
|
| 98 | - if (in_array($entry, $do_not_delete)) { |
|
| 99 | - echo '<li><i class="fa-li fa fa-ban text-danger"></i>', Filter::escapeHtml($entry), '</li>'; |
|
| 100 | - } else { |
|
| 101 | - $id = 'input-' . Uuid::uuid4(); |
|
| 102 | - echo '<li><i class="fa-li fa fa-trash-o"></i>'; |
|
| 103 | - echo '<label for="', $id, '">'; |
|
| 104 | - echo '<input type="checkbox" id="', $id, '" name="to_delete[]" value="', Filter::escapeHtml($entry), '"> '; |
|
| 105 | - echo Filter::escapeHtml($entry); |
|
| 106 | - echo '</label></li>'; |
|
| 107 | - } |
|
| 108 | - } |
|
| 109 | - $dir->close(); |
|
| 110 | - ?> |
|
| 97 | + foreach ($entries as $entry) { |
|
| 98 | + if (in_array($entry, $do_not_delete)) { |
|
| 99 | + echo '<li><i class="fa-li fa fa-ban text-danger"></i>', Filter::escapeHtml($entry), '</li>'; |
|
| 100 | + } else { |
|
| 101 | + $id = 'input-' . Uuid::uuid4(); |
|
| 102 | + echo '<li><i class="fa-li fa fa-trash-o"></i>'; |
|
| 103 | + echo '<label for="', $id, '">'; |
|
| 104 | + echo '<input type="checkbox" id="', $id, '" name="to_delete[]" value="', Filter::escapeHtml($entry), '"> '; |
|
| 105 | + echo Filter::escapeHtml($entry); |
|
| 106 | + echo '</label></li>'; |
|
| 107 | + } |
|
| 108 | + } |
|
| 109 | + $dir->close(); |
|
| 110 | + ?> |
|
| 111 | 111 | </ul> |
| 112 | 112 | </fieldset> |
| 113 | 113 | <button class="btn btn-danger" type="submit"> |
@@ -34,56 +34,56 @@ |
||
| 34 | 34 | $changes = array(); |
| 35 | 35 | |
| 36 | 36 | if ($search && $replace) { |
| 37 | - $rows = Database::prepare( |
|
| 38 | - "SELECT i_id AS xref, i_gedcom AS gedcom" . |
|
| 39 | - " FROM `##individuals`" . |
|
| 40 | - " LEFT JOIN `##change` ON (i_id = xref AND i_file=gedcom_id AND status='pending')" . |
|
| 41 | - " WHERE i_file = ?" . |
|
| 42 | - " AND COALESCE(new_gedcom, i_gedcom) REGEXP CONCAT('\n2 PLAC ([^\n]*, )*', ?, '(\n|$)')" |
|
| 43 | - )->execute(array($WT_TREE->getTreeId(), preg_quote($search)))->fetchAll(); |
|
| 44 | - foreach ($rows as $row) { |
|
| 45 | - $record = Individual::getInstance($row->xref, $WT_TREE, $row->gedcom); |
|
| 46 | - foreach ($record->getFacts() as $fact) { |
|
| 47 | - $old_place = $fact->getAttribute('PLAC'); |
|
| 48 | - if (preg_match('/(^|, )' . preg_quote($search, '/') . '$/i', $old_place)) { |
|
| 49 | - $new_place = preg_replace('/(^|, )' . preg_quote($search, '/') . '$/i', '$1' . $replace, $old_place); |
|
| 50 | - $changes[$old_place] = $new_place; |
|
| 51 | - if ($confirm == 'update') { |
|
| 52 | - $gedcom = preg_replace('/(\n2 PLAC (?:.*, )*)' . preg_quote($search, '/') . '(\n|$)/i', '$1' . $replace . '$2', $fact->getGedcom()); |
|
| 53 | - $record->updateFact($fact->getFactId(), $gedcom, false); |
|
| 54 | - } |
|
| 55 | - } |
|
| 56 | - } |
|
| 57 | - } |
|
| 58 | - $rows = Database::prepare( |
|
| 59 | - "SELECT f_id AS xref, f_gedcom AS gedcom" . |
|
| 60 | - " FROM `##families`" . |
|
| 61 | - " LEFT JOIN `##change` ON (f_id = xref AND f_file=gedcom_id AND status='pending')" . |
|
| 62 | - " WHERE f_file = ?" . |
|
| 63 | - " AND COALESCE(new_gedcom, f_gedcom) REGEXP CONCAT('\n2 PLAC ([^\n]*, )*', ?, '(\n|$)')" |
|
| 64 | - )->execute(array($WT_TREE->getTreeId(), preg_quote($search)))->fetchAll(); |
|
| 65 | - foreach ($rows as $row) { |
|
| 66 | - $record = Family::getInstance($row->xref, $WT_TREE, $row->gedcom); |
|
| 67 | - foreach ($record->getFacts() as $fact) { |
|
| 68 | - $old_place = $fact->getAttribute('PLAC'); |
|
| 69 | - if (preg_match('/(^|, )' . preg_quote($search, '/') . '$/i', $old_place)) { |
|
| 70 | - $new_place = preg_replace('/(^|, )' . preg_quote($search, '/') . '$/i', '$1' . $replace, $old_place); |
|
| 71 | - $changes[$old_place] = $new_place; |
|
| 72 | - if ($confirm == 'update') { |
|
| 73 | - $gedcom = preg_replace('/(\n2 PLAC (?:.*, )*)' . preg_quote($search, '/') . '(\n|$)/i', '$1' . $replace . '$2', $fact->getGedcom()); |
|
| 74 | - $record->updateFact($fact->getFactId(), $gedcom, false); |
|
| 75 | - } |
|
| 76 | - } |
|
| 77 | - } |
|
| 78 | - } |
|
| 37 | + $rows = Database::prepare( |
|
| 38 | + "SELECT i_id AS xref, i_gedcom AS gedcom" . |
|
| 39 | + " FROM `##individuals`" . |
|
| 40 | + " LEFT JOIN `##change` ON (i_id = xref AND i_file=gedcom_id AND status='pending')" . |
|
| 41 | + " WHERE i_file = ?" . |
|
| 42 | + " AND COALESCE(new_gedcom, i_gedcom) REGEXP CONCAT('\n2 PLAC ([^\n]*, )*', ?, '(\n|$)')" |
|
| 43 | + )->execute(array($WT_TREE->getTreeId(), preg_quote($search)))->fetchAll(); |
|
| 44 | + foreach ($rows as $row) { |
|
| 45 | + $record = Individual::getInstance($row->xref, $WT_TREE, $row->gedcom); |
|
| 46 | + foreach ($record->getFacts() as $fact) { |
|
| 47 | + $old_place = $fact->getAttribute('PLAC'); |
|
| 48 | + if (preg_match('/(^|, )' . preg_quote($search, '/') . '$/i', $old_place)) { |
|
| 49 | + $new_place = preg_replace('/(^|, )' . preg_quote($search, '/') . '$/i', '$1' . $replace, $old_place); |
|
| 50 | + $changes[$old_place] = $new_place; |
|
| 51 | + if ($confirm == 'update') { |
|
| 52 | + $gedcom = preg_replace('/(\n2 PLAC (?:.*, )*)' . preg_quote($search, '/') . '(\n|$)/i', '$1' . $replace . '$2', $fact->getGedcom()); |
|
| 53 | + $record->updateFact($fact->getFactId(), $gedcom, false); |
|
| 54 | + } |
|
| 55 | + } |
|
| 56 | + } |
|
| 57 | + } |
|
| 58 | + $rows = Database::prepare( |
|
| 59 | + "SELECT f_id AS xref, f_gedcom AS gedcom" . |
|
| 60 | + " FROM `##families`" . |
|
| 61 | + " LEFT JOIN `##change` ON (f_id = xref AND f_file=gedcom_id AND status='pending')" . |
|
| 62 | + " WHERE f_file = ?" . |
|
| 63 | + " AND COALESCE(new_gedcom, f_gedcom) REGEXP CONCAT('\n2 PLAC ([^\n]*, )*', ?, '(\n|$)')" |
|
| 64 | + )->execute(array($WT_TREE->getTreeId(), preg_quote($search)))->fetchAll(); |
|
| 65 | + foreach ($rows as $row) { |
|
| 66 | + $record = Family::getInstance($row->xref, $WT_TREE, $row->gedcom); |
|
| 67 | + foreach ($record->getFacts() as $fact) { |
|
| 68 | + $old_place = $fact->getAttribute('PLAC'); |
|
| 69 | + if (preg_match('/(^|, )' . preg_quote($search, '/') . '$/i', $old_place)) { |
|
| 70 | + $new_place = preg_replace('/(^|, )' . preg_quote($search, '/') . '$/i', '$1' . $replace, $old_place); |
|
| 71 | + $changes[$old_place] = $new_place; |
|
| 72 | + if ($confirm == 'update') { |
|
| 73 | + $gedcom = preg_replace('/(\n2 PLAC (?:.*, )*)' . preg_quote($search, '/') . '(\n|$)/i', '$1' . $replace . '$2', $fact->getGedcom()); |
|
| 74 | + $record->updateFact($fact->getFactId(), $gedcom, false); |
|
| 75 | + } |
|
| 76 | + } |
|
| 77 | + } |
|
| 78 | + } |
|
| 79 | 79 | } |
| 80 | 80 | |
| 81 | 81 | $controller = new PageController; |
| 82 | 82 | $controller |
| 83 | - ->restrictAccess(Auth::isManager($WT_TREE)) |
|
| 84 | - ->setPageTitle(I18N::translate('Update all the place names in a family tree') . ' — ' . $WT_TREE->getTitleHtml()) |
|
| 85 | - ->addInlineJavascript('autocomplete();') |
|
| 86 | - ->pageHeader(); |
|
| 83 | + ->restrictAccess(Auth::isManager($WT_TREE)) |
|
| 84 | + ->setPageTitle(I18N::translate('Update all the place names in a family tree') . ' — ' . $WT_TREE->getTitleHtml()) |
|
| 85 | + ->addInlineJavascript('autocomplete();') |
|
| 86 | + ->pageHeader(); |
|
| 87 | 87 | ?> |
| 88 | 88 | |
| 89 | 89 | <ol class="breadcrumb small"> |
@@ -33,38 +33,38 @@ discard block |
||
| 33 | 33 | $controller = new FamilyController($record); |
| 34 | 34 | |
| 35 | 35 | if ($controller->record && $controller->record->canShow()) { |
| 36 | - if ($controller->record->isPendingDeletion()) { |
|
| 37 | - if (Auth::isModerator($controller->record->getTree())) { |
|
| 38 | - FlashMessages::addMessage(/* I18N: %1$s is “accept”, %2$s is “reject”. These are links. */ I18N::translate( |
|
| 39 | - 'This family has been deleted. You should review the deletion and then %1$s or %2$s it.', |
|
| 40 | - '<a href="#" onclick="accept_changes(\'' . $controller->record->getXref() . '\');">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'accept') . '</a>', |
|
| 41 | - '<a href="#" onclick="reject_changes(\'' . $controller->record->getXref() . '\');">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'reject') . '</a>' |
|
| 42 | - ) . ' ' . FunctionsPrint::helpLink('pending_changes'), 'warning'); |
|
| 43 | - } elseif (Auth::isEditor($controller->record->getTree())) { |
|
| 44 | - FlashMessages::addMessage(I18N::translate('This family has been deleted. The deletion will need to be reviewed by a moderator.') . ' ' . FunctionsPrint::helpLink('pending_changes'), 'warning'); |
|
| 45 | - } |
|
| 46 | - } elseif ($controller->record->isPendingAddtion()) { |
|
| 47 | - if (Auth::isModerator($controller->record->getTree())) { |
|
| 48 | - FlashMessages::addMessage(/* I18N: %1$s is “accept”, %2$s is “reject”. These are links. */ I18N::translate( |
|
| 49 | - 'This family has been edited. You should review the changes and then %1$s or %2$s them.', |
|
| 50 | - '<a href="#" onclick="accept_changes(\'' . $controller->record->getXref() . '\');">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'accept') . '</a>', |
|
| 51 | - '<a href="#" onclick="reject_changes(\'' . $controller->record->getXref() . '\');">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'reject') . '</a>' |
|
| 52 | - ) . ' ' . FunctionsPrint::helpLink('pending_changes'), 'warning'); |
|
| 53 | - } elseif (Auth::isEditor($controller->record->getTree())) { |
|
| 54 | - FlashMessages::addMessage(I18N::translate('This family has been edited. The changes need to be reviewed by a moderator.') . ' ' . FunctionsPrint::helpLink('pending_changes'), 'warning'); |
|
| 55 | - } |
|
| 56 | - } |
|
| 57 | - $controller->pageHeader(); |
|
| 36 | + if ($controller->record->isPendingDeletion()) { |
|
| 37 | + if (Auth::isModerator($controller->record->getTree())) { |
|
| 38 | + FlashMessages::addMessage(/* I18N: %1$s is “accept”, %2$s is “reject”. These are links. */ I18N::translate( |
|
| 39 | + 'This family has been deleted. You should review the deletion and then %1$s or %2$s it.', |
|
| 40 | + '<a href="#" onclick="accept_changes(\'' . $controller->record->getXref() . '\');">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'accept') . '</a>', |
|
| 41 | + '<a href="#" onclick="reject_changes(\'' . $controller->record->getXref() . '\');">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'reject') . '</a>' |
|
| 42 | + ) . ' ' . FunctionsPrint::helpLink('pending_changes'), 'warning'); |
|
| 43 | + } elseif (Auth::isEditor($controller->record->getTree())) { |
|
| 44 | + FlashMessages::addMessage(I18N::translate('This family has been deleted. The deletion will need to be reviewed by a moderator.') . ' ' . FunctionsPrint::helpLink('pending_changes'), 'warning'); |
|
| 45 | + } |
|
| 46 | + } elseif ($controller->record->isPendingAddtion()) { |
|
| 47 | + if (Auth::isModerator($controller->record->getTree())) { |
|
| 48 | + FlashMessages::addMessage(/* I18N: %1$s is “accept”, %2$s is “reject”. These are links. */ I18N::translate( |
|
| 49 | + 'This family has been edited. You should review the changes and then %1$s or %2$s them.', |
|
| 50 | + '<a href="#" onclick="accept_changes(\'' . $controller->record->getXref() . '\');">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'accept') . '</a>', |
|
| 51 | + '<a href="#" onclick="reject_changes(\'' . $controller->record->getXref() . '\');">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'reject') . '</a>' |
|
| 52 | + ) . ' ' . FunctionsPrint::helpLink('pending_changes'), 'warning'); |
|
| 53 | + } elseif (Auth::isEditor($controller->record->getTree())) { |
|
| 54 | + FlashMessages::addMessage(I18N::translate('This family has been edited. The changes need to be reviewed by a moderator.') . ' ' . FunctionsPrint::helpLink('pending_changes'), 'warning'); |
|
| 55 | + } |
|
| 56 | + } |
|
| 57 | + $controller->pageHeader(); |
|
| 58 | 58 | } elseif ($controller->record && $controller->record->getTree()->getPreference('SHOW_PRIVATE_RELATIONSHIPS')) { |
| 59 | - $controller->pageHeader(); |
|
| 60 | - // Continue - to display the children/parents/grandparents. |
|
| 61 | - // We'll check for showing the details again later |
|
| 59 | + $controller->pageHeader(); |
|
| 60 | + // Continue - to display the children/parents/grandparents. |
|
| 61 | + // We'll check for showing the details again later |
|
| 62 | 62 | } else { |
| 63 | - FlashMessages::addMessage(I18N::translate('This family does not exist or you do not have permission to view it.'), 'danger'); |
|
| 64 | - http_response_code(404); |
|
| 65 | - $controller->pageHeader(); |
|
| 63 | + FlashMessages::addMessage(I18N::translate('This family does not exist or you do not have permission to view it.'), 'danger'); |
|
| 64 | + http_response_code(404); |
|
| 65 | + $controller->pageHeader(); |
|
| 66 | 66 | |
| 67 | - return; |
|
| 67 | + return; |
|
| 68 | 68 | } |
| 69 | 69 | |
| 70 | 70 | ?> |
@@ -85,32 +85,32 @@ discard block |
||
| 85 | 85 | <tr> |
| 86 | 86 | <td colspan="2"> |
| 87 | 87 | <?php |
| 88 | - FunctionsCharts::printFamilyParents($controller->record); |
|
| 89 | - if (Auth::isEditor($controller->record->getTree())) { |
|
| 90 | - $husb = $controller->record->getHusband(); |
|
| 91 | - if (!$husb) { |
|
| 92 | - echo '<a href="#" onclick="return add_spouse_to_family(\'', $controller->record->getXref(), '\', \'HUSB\');">', I18N::translate('Add a father'), '</a><br>'; |
|
| 93 | - } |
|
| 94 | - $wife = $controller->record->getWife(); |
|
| 95 | - if (!$wife) { |
|
| 96 | - echo '<a href="#" onclick="return add_spouse_to_family(\'', $controller->record->getXref(), '\', \'WIFE\');">', I18N::translate('Add a mother'), '</a><br>'; |
|
| 97 | - } |
|
| 98 | - } |
|
| 99 | - ?> |
|
| 88 | + FunctionsCharts::printFamilyParents($controller->record); |
|
| 89 | + if (Auth::isEditor($controller->record->getTree())) { |
|
| 90 | + $husb = $controller->record->getHusband(); |
|
| 91 | + if (!$husb) { |
|
| 92 | + echo '<a href="#" onclick="return add_spouse_to_family(\'', $controller->record->getXref(), '\', \'HUSB\');">', I18N::translate('Add a father'), '</a><br>'; |
|
| 93 | + } |
|
| 94 | + $wife = $controller->record->getWife(); |
|
| 95 | + if (!$wife) { |
|
| 96 | + echo '<a href="#" onclick="return add_spouse_to_family(\'', $controller->record->getXref(), '\', \'WIFE\');">', I18N::translate('Add a mother'), '</a><br>'; |
|
| 97 | + } |
|
| 98 | + } |
|
| 99 | + ?> |
|
| 100 | 100 | </td> |
| 101 | 101 | </tr> |
| 102 | 102 | <tr> |
| 103 | 103 | <td colspan="2"> |
| 104 | 104 | <span class="subheaders"><?php echo I18N::translate('Family group information'); ?></span> |
| 105 | 105 | <?php |
| 106 | - if ($controller->record->canShow()) { |
|
| 107 | - echo '<table class="facts_table">'; |
|
| 108 | - $controller->printFamilyFacts(); |
|
| 109 | - echo '</table>'; |
|
| 110 | - } else { |
|
| 111 | - echo '<p>', I18N::translate('The details of this family are private.'), '</p>'; |
|
| 112 | - } |
|
| 113 | - ?> |
|
| 106 | + if ($controller->record->canShow()) { |
|
| 107 | + echo '<table class="facts_table">'; |
|
| 108 | + $controller->printFamilyFacts(); |
|
| 109 | + echo '</table>'; |
|
| 110 | + } else { |
|
| 111 | + echo '<p>', I18N::translate('The details of this family are private.'), '</p>'; |
|
| 112 | + } |
|
| 113 | + ?> |
|
| 114 | 114 | </td> |
| 115 | 115 | </tr> |
| 116 | 116 | </table> |
@@ -32,8 +32,8 @@ discard block |
||
| 32 | 32 | |
| 33 | 33 | $controller = new PageController; |
| 34 | 34 | $controller |
| 35 | - ->restrictAccess(Auth::isManager($WT_TREE)) |
|
| 36 | - ->setPageTitle(I18N::translate('Changes')); |
|
| 35 | + ->restrictAccess(Auth::isManager($WT_TREE)) |
|
| 36 | + ->setPageTitle(I18N::translate('Changes')); |
|
| 37 | 37 | |
| 38 | 38 | $earliest = Database::prepare("SELECT IFNULL(DATE(MIN(change_time)), CURDATE()) FROM `##change`")->execute(array())->fetchOne(); |
| 39 | 39 | $latest = Database::prepare("SELECT IFNULL(DATE(MAX(change_time)), CURDATE()) FROM `##change`")->execute(array())->fetchOne(); |
@@ -51,197 +51,197 @@ discard block |
||
| 51 | 51 | $search = isset($search['value']) ? $search['value'] : null; |
| 52 | 52 | |
| 53 | 53 | $statuses = array( |
| 54 | - 'accepted' => /* I18N: the status of an edit accepted/rejected/pending */ I18N::translate('accepted'), |
|
| 55 | - 'rejected' => /* I18N: the status of an edit accepted/rejected/pending */ I18N::translate('rejected'), |
|
| 56 | - 'pending' => /* I18N: the status of an edit accepted/rejected/pending */ I18N::translate('pending'), |
|
| 54 | + 'accepted' => /* I18N: the status of an edit accepted/rejected/pending */ I18N::translate('accepted'), |
|
| 55 | + 'rejected' => /* I18N: the status of an edit accepted/rejected/pending */ I18N::translate('rejected'), |
|
| 56 | + 'pending' => /* I18N: the status of an edit accepted/rejected/pending */ I18N::translate('pending'), |
|
| 57 | 57 | ); |
| 58 | 58 | |
| 59 | 59 | if (Auth::isAdmin()) { |
| 60 | - // Administrators can see all logs |
|
| 61 | - $gedc = Filter::get('gedc'); |
|
| 60 | + // Administrators can see all logs |
|
| 61 | + $gedc = Filter::get('gedc'); |
|
| 62 | 62 | } else { |
| 63 | - // Managers can only see logs relating to this gedcom |
|
| 64 | - $gedc = $WT_TREE->getName(); |
|
| 63 | + // Managers can only see logs relating to this gedcom |
|
| 64 | + $gedc = $WT_TREE->getName(); |
|
| 65 | 65 | } |
| 66 | 66 | |
| 67 | 67 | $sql_select = |
| 68 | - "SELECT SQL_CALC_FOUND_ROWS change_id, change_time, status, xref, old_gedcom, new_gedcom, IFNULL(user_name, '<none>') AS user_name, IFNULL(gedcom_name, '<none>') AS gedcom_name" . |
|
| 69 | - " FROM `##change`" . |
|
| 70 | - " LEFT JOIN `##user` USING (user_id)" . // user may be deleted |
|
| 71 | - " LEFT JOIN `##gedcom` USING (gedcom_id)"; // gedcom may be deleted |
|
| 68 | + "SELECT SQL_CALC_FOUND_ROWS change_id, change_time, status, xref, old_gedcom, new_gedcom, IFNULL(user_name, '<none>') AS user_name, IFNULL(gedcom_name, '<none>') AS gedcom_name" . |
|
| 69 | + " FROM `##change`" . |
|
| 70 | + " LEFT JOIN `##user` USING (user_id)" . // user may be deleted |
|
| 71 | + " LEFT JOIN `##gedcom` USING (gedcom_id)"; // gedcom may be deleted |
|
| 72 | 72 | |
| 73 | 73 | $where = " WHERE 1"; |
| 74 | 74 | $args = array(); |
| 75 | 75 | if ($search) { |
| 76 | - $where .= " AND (old_gedcom LIKE CONCAT('%', :search_1, '%') OR new_gedcom LIKE CONCAT('%', :search_2, '%'))"; |
|
| 77 | - $args['search_1'] = $search; |
|
| 78 | - $args['search_2'] = $search; |
|
| 76 | + $where .= " AND (old_gedcom LIKE CONCAT('%', :search_1, '%') OR new_gedcom LIKE CONCAT('%', :search_2, '%'))"; |
|
| 77 | + $args['search_1'] = $search; |
|
| 78 | + $args['search_2'] = $search; |
|
| 79 | 79 | } |
| 80 | 80 | if ($from) { |
| 81 | - $where .= " AND change_time >= :from"; |
|
| 82 | - $args['from'] = $from; |
|
| 81 | + $where .= " AND change_time >= :from"; |
|
| 82 | + $args['from'] = $from; |
|
| 83 | 83 | } |
| 84 | 84 | if ($to) { |
| 85 | - $where .= " AND change_time < TIMESTAMPADD(DAY, 1 , :to)"; // before end of the day |
|
| 86 | - $args['to'] = $to; |
|
| 85 | + $where .= " AND change_time < TIMESTAMPADD(DAY, 1 , :to)"; // before end of the day |
|
| 86 | + $args['to'] = $to; |
|
| 87 | 87 | } |
| 88 | 88 | if ($type) { |
| 89 | - $where .= " AND status = :status"; |
|
| 90 | - $args['status'] = $type; |
|
| 89 | + $where .= " AND status = :status"; |
|
| 90 | + $args['status'] = $type; |
|
| 91 | 91 | } |
| 92 | 92 | if ($oldged) { |
| 93 | - $where .= " AND old_gedcom LIKE CONCAT('%', :old_ged, '%')"; |
|
| 94 | - $args['old_ged'] = $oldged; |
|
| 93 | + $where .= " AND old_gedcom LIKE CONCAT('%', :old_ged, '%')"; |
|
| 94 | + $args['old_ged'] = $oldged; |
|
| 95 | 95 | } |
| 96 | 96 | if ($newged) { |
| 97 | - $where .= " AND new_gedcom LIKE CONCAT('%', :new_ged, '%')"; |
|
| 98 | - $args['new_ged'] = $newged; |
|
| 97 | + $where .= " AND new_gedcom LIKE CONCAT('%', :new_ged, '%')"; |
|
| 98 | + $args['new_ged'] = $newged; |
|
| 99 | 99 | } |
| 100 | 100 | if ($xref) { |
| 101 | - $where .= " AND xref = :xref"; |
|
| 102 | - $args['xref'] = $xref; |
|
| 101 | + $where .= " AND xref = :xref"; |
|
| 102 | + $args['xref'] = $xref; |
|
| 103 | 103 | } |
| 104 | 104 | if ($user) { |
| 105 | - $where .= " AND user_name LIKE CONCAT('%', :user, '%')"; |
|
| 106 | - $args['user'] = $user; |
|
| 105 | + $where .= " AND user_name LIKE CONCAT('%', :user, '%')"; |
|
| 106 | + $args['user'] = $user; |
|
| 107 | 107 | } |
| 108 | 108 | if ($gedc) { |
| 109 | - $where .= " AND gedcom_name LIKE CONCAT('%', :gedc, '%')"; |
|
| 110 | - $args['gedc'] = $gedc; |
|
| 109 | + $where .= " AND gedcom_name LIKE CONCAT('%', :gedc, '%')"; |
|
| 110 | + $args['gedc'] = $gedc; |
|
| 111 | 111 | } |
| 112 | 112 | |
| 113 | 113 | switch ($action) { |
| 114 | 114 | case 'delete': |
| 115 | - $sql_delete = |
|
| 116 | - "DELETE `##change` FROM `##change`" . |
|
| 117 | - " LEFT JOIN `##user` USING (user_id)" . // user may be deleted |
|
| 118 | - " LEFT JOIN `##gedcom` USING (gedcom_id)"; // gedcom may be deleted |
|
| 115 | + $sql_delete = |
|
| 116 | + "DELETE `##change` FROM `##change`" . |
|
| 117 | + " LEFT JOIN `##user` USING (user_id)" . // user may be deleted |
|
| 118 | + " LEFT JOIN `##gedcom` USING (gedcom_id)"; // gedcom may be deleted |
|
| 119 | 119 | |
| 120 | - Database::prepare($sql_delete . $where)->execute($args); |
|
| 121 | - break; |
|
| 120 | + Database::prepare($sql_delete . $where)->execute($args); |
|
| 121 | + break; |
|
| 122 | 122 | |
| 123 | 123 | case 'export': |
| 124 | - header('Content-Type: text/csv'); |
|
| 125 | - header('Content-Disposition: attachment; filename="webtrees-changes.csv"'); |
|
| 126 | - $rows = Database::prepare($sql_select . $where . ' ORDER BY change_id')->execute($args)->fetchAll(); |
|
| 127 | - foreach ($rows as $row) { |
|
| 128 | - echo |
|
| 129 | - '"', $row->change_time, '",', |
|
| 130 | - '"', $row->status, '",', |
|
| 131 | - '"', $row->xref, '",', |
|
| 132 | - '"', str_replace('"', '""', $row->old_gedcom), '",', |
|
| 133 | - '"', str_replace('"', '""', $row->new_gedcom), '",', |
|
| 134 | - '"', str_replace('"', '""', $row->user_name), '",', |
|
| 135 | - '"', str_replace('"', '""', $row->gedcom_name), '"', |
|
| 136 | - "\n"; |
|
| 137 | - } |
|
| 138 | - |
|
| 139 | - return; |
|
| 124 | + header('Content-Type: text/csv'); |
|
| 125 | + header('Content-Disposition: attachment; filename="webtrees-changes.csv"'); |
|
| 126 | + $rows = Database::prepare($sql_select . $where . ' ORDER BY change_id')->execute($args)->fetchAll(); |
|
| 127 | + foreach ($rows as $row) { |
|
| 128 | + echo |
|
| 129 | + '"', $row->change_time, '",', |
|
| 130 | + '"', $row->status, '",', |
|
| 131 | + '"', $row->xref, '",', |
|
| 132 | + '"', str_replace('"', '""', $row->old_gedcom), '",', |
|
| 133 | + '"', str_replace('"', '""', $row->new_gedcom), '",', |
|
| 134 | + '"', str_replace('"', '""', $row->user_name), '",', |
|
| 135 | + '"', str_replace('"', '""', $row->gedcom_name), '"', |
|
| 136 | + "\n"; |
|
| 137 | + } |
|
| 138 | + |
|
| 139 | + return; |
|
| 140 | 140 | case 'load_json': |
| 141 | - $start = Filter::getInteger('start'); |
|
| 142 | - $length = Filter::getInteger('length'); |
|
| 143 | - $order = Filter::getArray('order'); |
|
| 144 | - |
|
| 145 | - if ($order) { |
|
| 146 | - $order_by = " ORDER BY "; |
|
| 147 | - foreach ($order as $key => $value) { |
|
| 148 | - if ($key > 0) { |
|
| 149 | - $order_by .= ','; |
|
| 150 | - } |
|
| 151 | - // Datatables numbers columns 0, 1, 2 |
|
| 152 | - // MySQL numbers columns 1, 2, 3 |
|
| 153 | - switch ($value['dir']) { |
|
| 154 | - case 'asc': |
|
| 155 | - $order_by .= (1 + $value['column']) . " ASC "; |
|
| 156 | - break; |
|
| 157 | - case 'desc': |
|
| 158 | - $order_by .= (1 + $value['column']) . " DESC "; |
|
| 159 | - break; |
|
| 160 | - } |
|
| 161 | - } |
|
| 162 | - } else { |
|
| 163 | - $order_by = " ORDER BY 1 DESC"; |
|
| 164 | - } |
|
| 165 | - |
|
| 166 | - if ($length) { |
|
| 167 | - Auth::user()->setPreference('admin_site_change_page_size', $length); |
|
| 168 | - $limit = " LIMIT :limit OFFSET :offset"; |
|
| 169 | - $args['limit'] = $length; |
|
| 170 | - $args['offset'] = $start; |
|
| 171 | - } else { |
|
| 172 | - $limit = ""; |
|
| 173 | - } |
|
| 174 | - |
|
| 175 | - // This becomes a JSON list, not array, so need to fetch with numeric keys. |
|
| 176 | - $rows = Database::prepare($sql_select . $where . $order_by . $limit)->execute($args)->fetchAll(PDO::FETCH_OBJ); |
|
| 177 | - // Total filtered/unfiltered rows |
|
| 178 | - $recordsFiltered = (int) Database::prepare("SELECT FOUND_ROWS()")->fetchOne(); |
|
| 179 | - $recordsTotal = (int) Database::prepare("SELECT COUNT(*) FROM `##change`")->fetchOne(); |
|
| 180 | - |
|
| 181 | - $data = array(); |
|
| 182 | - $algorithm = new MyersDiff; |
|
| 183 | - |
|
| 184 | - foreach ($rows as $row) { |
|
| 185 | - $old_lines = preg_split('/[\n]+/', $row->old_gedcom, -1, PREG_SPLIT_NO_EMPTY); |
|
| 186 | - $new_lines = preg_split('/[\n]+/', $row->new_gedcom, -1, PREG_SPLIT_NO_EMPTY); |
|
| 187 | - |
|
| 188 | - $differences = $algorithm->calculate($old_lines, $new_lines); |
|
| 189 | - $diff_lines = array(); |
|
| 190 | - |
|
| 191 | - foreach ($differences as $difference) { |
|
| 192 | - switch ($difference[1]) { |
|
| 193 | - case MyersDiff::DELETE: |
|
| 194 | - $diff_lines[] = '<del>' . $difference[0] . '</del>'; |
|
| 195 | - break; |
|
| 196 | - case MyersDiff::INSERT: |
|
| 197 | - $diff_lines[] = '<ins>' . $difference[0] . '</ins>'; |
|
| 198 | - break; |
|
| 199 | - default: |
|
| 200 | - $diff_lines[] = $difference[0]; |
|
| 201 | - } |
|
| 202 | - } |
|
| 203 | - |
|
| 204 | - // Only convert valid xrefs to links |
|
| 205 | - $record = GedcomRecord::getInstance($row->xref, Tree::findByName($gedc)); |
|
| 206 | - $data[] = array( |
|
| 207 | - $row->change_id, |
|
| 208 | - $row->change_time, |
|
| 209 | - I18N::translate($row->status), |
|
| 210 | - $record ? '<a href="' . $record->getHtmlUrl() . '">' . $record->getXref() . '</a>' : $row->xref, |
|
| 211 | - '<div class="gedcom-data" dir="ltr">' . |
|
| 212 | - preg_replace_callback('/@(' . WT_REGEX_XREF . ')@/', |
|
| 213 | - function ($match) use ($gedc) { |
|
| 214 | - $record = GedcomRecord::getInstance($match[1], Tree::findByName($gedc)); |
|
| 215 | - |
|
| 216 | - return $record ? '<a href="#" onclick="return edit_raw(\'' . $match[1] . '\');">' . $match[0] . '</a>' : $match[0]; |
|
| 217 | - }, |
|
| 218 | - implode("\n", $diff_lines) |
|
| 219 | - ) . |
|
| 220 | - '</div>', |
|
| 221 | - $row->user_name, |
|
| 222 | - $row->gedcom_name, |
|
| 223 | - ); |
|
| 224 | - } |
|
| 225 | - |
|
| 226 | - header('Content-type: application/json'); |
|
| 227 | - // See http://www.datatables.net/usage/server-side |
|
| 228 | - echo json_encode(array( |
|
| 229 | - 'draw' => Filter::getInteger('draw'), |
|
| 230 | - 'recordsTotal' => $recordsTotal, |
|
| 231 | - 'recordsFiltered' => $recordsFiltered, |
|
| 232 | - 'data' => $data, |
|
| 233 | - )); |
|
| 234 | - |
|
| 235 | - return; |
|
| 141 | + $start = Filter::getInteger('start'); |
|
| 142 | + $length = Filter::getInteger('length'); |
|
| 143 | + $order = Filter::getArray('order'); |
|
| 144 | + |
|
| 145 | + if ($order) { |
|
| 146 | + $order_by = " ORDER BY "; |
|
| 147 | + foreach ($order as $key => $value) { |
|
| 148 | + if ($key > 0) { |
|
| 149 | + $order_by .= ','; |
|
| 150 | + } |
|
| 151 | + // Datatables numbers columns 0, 1, 2 |
|
| 152 | + // MySQL numbers columns 1, 2, 3 |
|
| 153 | + switch ($value['dir']) { |
|
| 154 | + case 'asc': |
|
| 155 | + $order_by .= (1 + $value['column']) . " ASC "; |
|
| 156 | + break; |
|
| 157 | + case 'desc': |
|
| 158 | + $order_by .= (1 + $value['column']) . " DESC "; |
|
| 159 | + break; |
|
| 160 | + } |
|
| 161 | + } |
|
| 162 | + } else { |
|
| 163 | + $order_by = " ORDER BY 1 DESC"; |
|
| 164 | + } |
|
| 165 | + |
|
| 166 | + if ($length) { |
|
| 167 | + Auth::user()->setPreference('admin_site_change_page_size', $length); |
|
| 168 | + $limit = " LIMIT :limit OFFSET :offset"; |
|
| 169 | + $args['limit'] = $length; |
|
| 170 | + $args['offset'] = $start; |
|
| 171 | + } else { |
|
| 172 | + $limit = ""; |
|
| 173 | + } |
|
| 174 | + |
|
| 175 | + // This becomes a JSON list, not array, so need to fetch with numeric keys. |
|
| 176 | + $rows = Database::prepare($sql_select . $where . $order_by . $limit)->execute($args)->fetchAll(PDO::FETCH_OBJ); |
|
| 177 | + // Total filtered/unfiltered rows |
|
| 178 | + $recordsFiltered = (int) Database::prepare("SELECT FOUND_ROWS()")->fetchOne(); |
|
| 179 | + $recordsTotal = (int) Database::prepare("SELECT COUNT(*) FROM `##change`")->fetchOne(); |
|
| 180 | + |
|
| 181 | + $data = array(); |
|
| 182 | + $algorithm = new MyersDiff; |
|
| 183 | + |
|
| 184 | + foreach ($rows as $row) { |
|
| 185 | + $old_lines = preg_split('/[\n]+/', $row->old_gedcom, -1, PREG_SPLIT_NO_EMPTY); |
|
| 186 | + $new_lines = preg_split('/[\n]+/', $row->new_gedcom, -1, PREG_SPLIT_NO_EMPTY); |
|
| 187 | + |
|
| 188 | + $differences = $algorithm->calculate($old_lines, $new_lines); |
|
| 189 | + $diff_lines = array(); |
|
| 190 | + |
|
| 191 | + foreach ($differences as $difference) { |
|
| 192 | + switch ($difference[1]) { |
|
| 193 | + case MyersDiff::DELETE: |
|
| 194 | + $diff_lines[] = '<del>' . $difference[0] . '</del>'; |
|
| 195 | + break; |
|
| 196 | + case MyersDiff::INSERT: |
|
| 197 | + $diff_lines[] = '<ins>' . $difference[0] . '</ins>'; |
|
| 198 | + break; |
|
| 199 | + default: |
|
| 200 | + $diff_lines[] = $difference[0]; |
|
| 201 | + } |
|
| 202 | + } |
|
| 203 | + |
|
| 204 | + // Only convert valid xrefs to links |
|
| 205 | + $record = GedcomRecord::getInstance($row->xref, Tree::findByName($gedc)); |
|
| 206 | + $data[] = array( |
|
| 207 | + $row->change_id, |
|
| 208 | + $row->change_time, |
|
| 209 | + I18N::translate($row->status), |
|
| 210 | + $record ? '<a href="' . $record->getHtmlUrl() . '">' . $record->getXref() . '</a>' : $row->xref, |
|
| 211 | + '<div class="gedcom-data" dir="ltr">' . |
|
| 212 | + preg_replace_callback('/@(' . WT_REGEX_XREF . ')@/', |
|
| 213 | + function ($match) use ($gedc) { |
|
| 214 | + $record = GedcomRecord::getInstance($match[1], Tree::findByName($gedc)); |
|
| 215 | + |
|
| 216 | + return $record ? '<a href="#" onclick="return edit_raw(\'' . $match[1] . '\');">' . $match[0] . '</a>' : $match[0]; |
|
| 217 | + }, |
|
| 218 | + implode("\n", $diff_lines) |
|
| 219 | + ) . |
|
| 220 | + '</div>', |
|
| 221 | + $row->user_name, |
|
| 222 | + $row->gedcom_name, |
|
| 223 | + ); |
|
| 224 | + } |
|
| 225 | + |
|
| 226 | + header('Content-type: application/json'); |
|
| 227 | + // See http://www.datatables.net/usage/server-side |
|
| 228 | + echo json_encode(array( |
|
| 229 | + 'draw' => Filter::getInteger('draw'), |
|
| 230 | + 'recordsTotal' => $recordsTotal, |
|
| 231 | + 'recordsFiltered' => $recordsFiltered, |
|
| 232 | + 'data' => $data, |
|
| 233 | + )); |
|
| 234 | + |
|
| 235 | + return; |
|
| 236 | 236 | } |
| 237 | 237 | |
| 238 | 238 | $controller |
| 239 | - ->pageHeader() |
|
| 240 | - ->addExternalJavascript(WT_JQUERY_DATATABLES_JS_URL) |
|
| 241 | - ->addExternalJavascript(WT_DATATABLES_BOOTSTRAP_JS_URL) |
|
| 242 | - ->addExternalJavascript(WT_MOMENT_JS_URL) |
|
| 243 | - ->addExternalJavascript(WT_BOOTSTRAP_DATETIMEPICKER_JS_URL) |
|
| 244 | - ->addInlineJavascript(' |
|
| 239 | + ->pageHeader() |
|
| 240 | + ->addExternalJavascript(WT_JQUERY_DATATABLES_JS_URL) |
|
| 241 | + ->addExternalJavascript(WT_DATATABLES_BOOTSTRAP_JS_URL) |
|
| 242 | + ->addExternalJavascript(WT_MOMENT_JS_URL) |
|
| 243 | + ->addExternalJavascript(WT_BOOTSTRAP_DATETIMEPICKER_JS_URL) |
|
| 244 | + ->addInlineJavascript(' |
|
| 245 | 245 | jQuery(".table-site-changes").dataTable( { |
| 246 | 246 | processing: true, |
| 247 | 247 | serverSide: true, |
@@ -280,7 +280,7 @@ discard block |
||
| 280 | 280 | |
| 281 | 281 | $users_array = array(); |
| 282 | 282 | foreach (User::all() as $tmp_user) { |
| 283 | - $users_array[$tmp_user->getUserName()] = $tmp_user->getUserName(); |
|
| 283 | + $users_array[$tmp_user->getUserName()] = $tmp_user->getUserName(); |
|
| 284 | 284 | } |
| 285 | 285 | |
| 286 | 286 | ?> |
@@ -151,12 +151,12 @@ discard block |
||
| 151 | 151 | // Datatables numbers columns 0, 1, 2 |
| 152 | 152 | // MySQL numbers columns 1, 2, 3 |
| 153 | 153 | switch ($value['dir']) { |
| 154 | - case 'asc': |
|
| 155 | - $order_by .= (1 + $value['column']) . " ASC "; |
|
| 156 | - break; |
|
| 157 | - case 'desc': |
|
| 158 | - $order_by .= (1 + $value['column']) . " DESC "; |
|
| 159 | - break; |
|
| 154 | + case 'asc': |
|
| 155 | + $order_by .= (1 + $value['column']) . " ASC "; |
|
| 156 | + break; |
|
| 157 | + case 'desc': |
|
| 158 | + $order_by .= (1 + $value['column']) . " DESC "; |
|
| 159 | + break; |
|
| 160 | 160 | } |
| 161 | 161 | } |
| 162 | 162 | } else { |
@@ -190,14 +190,14 @@ discard block |
||
| 190 | 190 | |
| 191 | 191 | foreach ($differences as $difference) { |
| 192 | 192 | switch ($difference[1]) { |
| 193 | - case MyersDiff::DELETE: |
|
| 194 | - $diff_lines[] = '<del>' . $difference[0] . '</del>'; |
|
| 195 | - break; |
|
| 196 | - case MyersDiff::INSERT: |
|
| 197 | - $diff_lines[] = '<ins>' . $difference[0] . '</ins>'; |
|
| 198 | - break; |
|
| 199 | - default: |
|
| 200 | - $diff_lines[] = $difference[0]; |
|
| 193 | + case MyersDiff::DELETE: |
|
| 194 | + $diff_lines[] = '<del>' . $difference[0] . '</del>'; |
|
| 195 | + break; |
|
| 196 | + case MyersDiff::INSERT: |
|
| 197 | + $diff_lines[] = '<ins>' . $difference[0] . '</ins>'; |
|
| 198 | + break; |
|
| 199 | + default: |
|
| 200 | + $diff_lines[] = $difference[0]; |
|
| 201 | 201 | } |
| 202 | 202 | } |
| 203 | 203 | |
@@ -36,248 +36,248 @@ discard block |
||
| 36 | 36 | |
| 37 | 37 | // Valid values for form variables |
| 38 | 38 | $ALL_EDIT_OPTIONS = array( |
| 39 | - 'none' => /* I18N: Listbox entry; name of a role */ I18N::translate('Visitor'), |
|
| 40 | - 'access' => /* I18N: Listbox entry; name of a role */ I18N::translate('Member'), |
|
| 41 | - 'edit' => /* I18N: Listbox entry; name of a role */ I18N::translate('Editor'), |
|
| 42 | - 'accept' => /* I18N: Listbox entry; name of a role */ I18N::translate('Moderator'), |
|
| 43 | - 'admin' => /* I18N: Listbox entry; name of a role */ I18N::translate('Manager'), |
|
| 39 | + 'none' => /* I18N: Listbox entry; name of a role */ I18N::translate('Visitor'), |
|
| 40 | + 'access' => /* I18N: Listbox entry; name of a role */ I18N::translate('Member'), |
|
| 41 | + 'edit' => /* I18N: Listbox entry; name of a role */ I18N::translate('Editor'), |
|
| 42 | + 'accept' => /* I18N: Listbox entry; name of a role */ I18N::translate('Moderator'), |
|
| 43 | + 'admin' => /* I18N: Listbox entry; name of a role */ I18N::translate('Manager'), |
|
| 44 | 44 | ); |
| 45 | 45 | |
| 46 | 46 | // Form actions |
| 47 | 47 | switch (Filter::post('action')) { |
| 48 | 48 | case 'save': |
| 49 | - if (Filter::checkCsrf()) { |
|
| 50 | - $user_id = Filter::postInteger('user_id'); |
|
| 51 | - $user = User::find($user_id); |
|
| 52 | - $username = Filter::post('username'); |
|
| 53 | - $real_name = Filter::post('real_name'); |
|
| 54 | - $email = Filter::postEmail('email'); |
|
| 55 | - $pass1 = Filter::post('pass1', WT_REGEX_PASSWORD); |
|
| 56 | - $pass2 = Filter::post('pass2', WT_REGEX_PASSWORD); |
|
| 57 | - $theme = Filter::post('theme', implode('|', array_keys(Theme::themeNames())), ''); |
|
| 58 | - $language = Filter::post('language'); |
|
| 59 | - $timezone = Filter::post('timezone'); |
|
| 60 | - $contact_method = Filter::post('contact_method'); |
|
| 61 | - $comment = Filter::post('comment'); |
|
| 62 | - $auto_accept = Filter::postBool('auto_accept'); |
|
| 63 | - $canadmin = Filter::postBool('canadmin'); |
|
| 64 | - $visible_online = Filter::postBool('visible_online'); |
|
| 65 | - $verified = Filter::postBool('verified'); |
|
| 66 | - $approved = Filter::postBool('approved'); |
|
| 67 | - |
|
| 68 | - if ($user_id === 0) { |
|
| 69 | - // Create a new user |
|
| 70 | - if (User::findByUserName($username)) { |
|
| 71 | - FlashMessages::addMessage(I18N::translate('Duplicate username. A user with that username already exists. Please choose another username.')); |
|
| 72 | - } elseif (User::findByEmail($email)) { |
|
| 73 | - FlashMessages::addMessage(I18N::translate('Duplicate email address. A user with that email already exists.')); |
|
| 74 | - } elseif ($pass1 !== $pass2) { |
|
| 75 | - FlashMessages::addMessage(I18N::translate('The passwords do not match.')); |
|
| 76 | - } else { |
|
| 77 | - $user = User::create($username, $real_name, $email, $pass1); |
|
| 78 | - $user->setPreference('reg_timestamp', date('U'))->setPreference('sessiontime', '0'); |
|
| 79 | - Log::addAuthenticationLog('User ->' . $username . '<- created'); |
|
| 80 | - } |
|
| 81 | - } else { |
|
| 82 | - $user = User::find($user_id); |
|
| 83 | - if ($user && $username && $real_name) { |
|
| 84 | - $user->setEmail($email); |
|
| 85 | - $user->setUserName($username); |
|
| 86 | - $user->setRealName($real_name); |
|
| 87 | - if ($pass1 !== null && $pass1 === $pass2) { |
|
| 88 | - $user->setPassword($pass1); |
|
| 89 | - } |
|
| 90 | - } |
|
| 91 | - } |
|
| 92 | - |
|
| 93 | - if ($user) { |
|
| 94 | - // Approving for the first time? Send a confirmation email |
|
| 95 | - if ($approved && !$user->getPreference('verified_by_admin') && $user->getPreference('sessiontime') == 0) { |
|
| 96 | - I18N::init($user->getPreference('language')); |
|
| 97 | - Mail::systemMessage( |
|
| 98 | - $WT_TREE, |
|
| 99 | - $user, |
|
| 100 | - I18N::translate('Approval of account at %s', WT_BASE_URL), |
|
| 101 | - I18N::translate('The administrator at the webtrees site %s has approved your application for an account. You may now sign in by accessing the following link: %s', WT_BASE_URL, WT_BASE_URL) |
|
| 102 | - ); |
|
| 103 | - } |
|
| 104 | - |
|
| 105 | - $user |
|
| 106 | - ->setPreference('theme', $theme) |
|
| 107 | - ->setPreference('language', $language) |
|
| 108 | - ->setPreference('TIMEZONE', $timezone) |
|
| 109 | - ->setPreference('contactmethod', $contact_method) |
|
| 110 | - ->setPreference('comment', $comment) |
|
| 111 | - ->setPreference('auto_accept', $auto_accept ? '1' : '0') |
|
| 112 | - ->setPreference('visibleonline', $visible_online ? '1' : '0') |
|
| 113 | - ->setPreference('verified', $verified ? '1' : '0') |
|
| 114 | - ->setPreference('verified_by_admin', $approved ? '1' : '0'); |
|
| 115 | - |
|
| 116 | - // We cannot change our own admin status. Another admin will need to do it. |
|
| 117 | - if ($user->getUserId() !== Auth::id()) { |
|
| 118 | - $user->setPreference('canadmin', $canadmin ? '1' : '0'); |
|
| 119 | - } |
|
| 120 | - |
|
| 121 | - foreach (Tree::getAll() as $tree) { |
|
| 122 | - $tree->setUserPreference($user, 'gedcomid', Filter::post('gedcomid' . $tree->getTreeId(), WT_REGEX_XREF)); |
|
| 123 | - $tree->setUserPreference($user, 'canedit', Filter::post('canedit' . $tree->getTreeId(), implode('|', array_keys($ALL_EDIT_OPTIONS)))); |
|
| 124 | - if (Filter::post('gedcomid' . $tree->getTreeId(), WT_REGEX_XREF)) { |
|
| 125 | - $tree->setUserPreference($user, 'RELATIONSHIP_PATH_LENGTH', Filter::postInteger('RELATIONSHIP_PATH_LENGTH' . $tree->getTreeId(), 0, 10, 0)); |
|
| 126 | - } else { |
|
| 127 | - // Do not allow a path length to be set if the individual ID is not |
|
| 128 | - $tree->setUserPreference($user, 'RELATIONSHIP_PATH_LENGTH', null); |
|
| 129 | - } |
|
| 130 | - } |
|
| 131 | - } |
|
| 132 | - } |
|
| 133 | - |
|
| 134 | - header('Location: ' . WT_BASE_URL . WT_SCRIPT_NAME); |
|
| 135 | - |
|
| 136 | - return; |
|
| 49 | + if (Filter::checkCsrf()) { |
|
| 50 | + $user_id = Filter::postInteger('user_id'); |
|
| 51 | + $user = User::find($user_id); |
|
| 52 | + $username = Filter::post('username'); |
|
| 53 | + $real_name = Filter::post('real_name'); |
|
| 54 | + $email = Filter::postEmail('email'); |
|
| 55 | + $pass1 = Filter::post('pass1', WT_REGEX_PASSWORD); |
|
| 56 | + $pass2 = Filter::post('pass2', WT_REGEX_PASSWORD); |
|
| 57 | + $theme = Filter::post('theme', implode('|', array_keys(Theme::themeNames())), ''); |
|
| 58 | + $language = Filter::post('language'); |
|
| 59 | + $timezone = Filter::post('timezone'); |
|
| 60 | + $contact_method = Filter::post('contact_method'); |
|
| 61 | + $comment = Filter::post('comment'); |
|
| 62 | + $auto_accept = Filter::postBool('auto_accept'); |
|
| 63 | + $canadmin = Filter::postBool('canadmin'); |
|
| 64 | + $visible_online = Filter::postBool('visible_online'); |
|
| 65 | + $verified = Filter::postBool('verified'); |
|
| 66 | + $approved = Filter::postBool('approved'); |
|
| 67 | + |
|
| 68 | + if ($user_id === 0) { |
|
| 69 | + // Create a new user |
|
| 70 | + if (User::findByUserName($username)) { |
|
| 71 | + FlashMessages::addMessage(I18N::translate('Duplicate username. A user with that username already exists. Please choose another username.')); |
|
| 72 | + } elseif (User::findByEmail($email)) { |
|
| 73 | + FlashMessages::addMessage(I18N::translate('Duplicate email address. A user with that email already exists.')); |
|
| 74 | + } elseif ($pass1 !== $pass2) { |
|
| 75 | + FlashMessages::addMessage(I18N::translate('The passwords do not match.')); |
|
| 76 | + } else { |
|
| 77 | + $user = User::create($username, $real_name, $email, $pass1); |
|
| 78 | + $user->setPreference('reg_timestamp', date('U'))->setPreference('sessiontime', '0'); |
|
| 79 | + Log::addAuthenticationLog('User ->' . $username . '<- created'); |
|
| 80 | + } |
|
| 81 | + } else { |
|
| 82 | + $user = User::find($user_id); |
|
| 83 | + if ($user && $username && $real_name) { |
|
| 84 | + $user->setEmail($email); |
|
| 85 | + $user->setUserName($username); |
|
| 86 | + $user->setRealName($real_name); |
|
| 87 | + if ($pass1 !== null && $pass1 === $pass2) { |
|
| 88 | + $user->setPassword($pass1); |
|
| 89 | + } |
|
| 90 | + } |
|
| 91 | + } |
|
| 92 | + |
|
| 93 | + if ($user) { |
|
| 94 | + // Approving for the first time? Send a confirmation email |
|
| 95 | + if ($approved && !$user->getPreference('verified_by_admin') && $user->getPreference('sessiontime') == 0) { |
|
| 96 | + I18N::init($user->getPreference('language')); |
|
| 97 | + Mail::systemMessage( |
|
| 98 | + $WT_TREE, |
|
| 99 | + $user, |
|
| 100 | + I18N::translate('Approval of account at %s', WT_BASE_URL), |
|
| 101 | + I18N::translate('The administrator at the webtrees site %s has approved your application for an account. You may now sign in by accessing the following link: %s', WT_BASE_URL, WT_BASE_URL) |
|
| 102 | + ); |
|
| 103 | + } |
|
| 104 | + |
|
| 105 | + $user |
|
| 106 | + ->setPreference('theme', $theme) |
|
| 107 | + ->setPreference('language', $language) |
|
| 108 | + ->setPreference('TIMEZONE', $timezone) |
|
| 109 | + ->setPreference('contactmethod', $contact_method) |
|
| 110 | + ->setPreference('comment', $comment) |
|
| 111 | + ->setPreference('auto_accept', $auto_accept ? '1' : '0') |
|
| 112 | + ->setPreference('visibleonline', $visible_online ? '1' : '0') |
|
| 113 | + ->setPreference('verified', $verified ? '1' : '0') |
|
| 114 | + ->setPreference('verified_by_admin', $approved ? '1' : '0'); |
|
| 115 | + |
|
| 116 | + // We cannot change our own admin status. Another admin will need to do it. |
|
| 117 | + if ($user->getUserId() !== Auth::id()) { |
|
| 118 | + $user->setPreference('canadmin', $canadmin ? '1' : '0'); |
|
| 119 | + } |
|
| 120 | + |
|
| 121 | + foreach (Tree::getAll() as $tree) { |
|
| 122 | + $tree->setUserPreference($user, 'gedcomid', Filter::post('gedcomid' . $tree->getTreeId(), WT_REGEX_XREF)); |
|
| 123 | + $tree->setUserPreference($user, 'canedit', Filter::post('canedit' . $tree->getTreeId(), implode('|', array_keys($ALL_EDIT_OPTIONS)))); |
|
| 124 | + if (Filter::post('gedcomid' . $tree->getTreeId(), WT_REGEX_XREF)) { |
|
| 125 | + $tree->setUserPreference($user, 'RELATIONSHIP_PATH_LENGTH', Filter::postInteger('RELATIONSHIP_PATH_LENGTH' . $tree->getTreeId(), 0, 10, 0)); |
|
| 126 | + } else { |
|
| 127 | + // Do not allow a path length to be set if the individual ID is not |
|
| 128 | + $tree->setUserPreference($user, 'RELATIONSHIP_PATH_LENGTH', null); |
|
| 129 | + } |
|
| 130 | + } |
|
| 131 | + } |
|
| 132 | + } |
|
| 133 | + |
|
| 134 | + header('Location: ' . WT_BASE_URL . WT_SCRIPT_NAME); |
|
| 135 | + |
|
| 136 | + return; |
|
| 137 | 137 | } |
| 138 | 138 | |
| 139 | 139 | switch (Filter::get('action')) { |
| 140 | 140 | case 'load_json': |
| 141 | - // Generate an AJAX/JSON response for datatables to load a block of rows |
|
| 142 | - $search = Filter::postArray('search'); |
|
| 143 | - $search = $search['value']; |
|
| 144 | - $start = Filter::postInteger('start'); |
|
| 145 | - $length = Filter::postInteger('length'); |
|
| 146 | - $order = Filter::postArray('order'); |
|
| 147 | - |
|
| 148 | - $sql_select = |
|
| 149 | - "SELECT SQL_CALC_FOUND_ROWS '', u.user_id, user_name, real_name, email, us1.setting_value, us2.setting_value, NULL, us3.setting_value, NULL, us4.setting_value, us5.setting_value" . |
|
| 150 | - " FROM `##user` u" . |
|
| 151 | - " LEFT JOIN `##user_setting` us1 ON (u.user_id=us1.user_id AND us1.setting_name='language')" . |
|
| 152 | - " LEFT JOIN `##user_setting` us2 ON (u.user_id=us2.user_id AND us2.setting_name='reg_timestamp')" . |
|
| 153 | - " LEFT JOIN `##user_setting` us3 ON (u.user_id=us3.user_id AND us3.setting_name='sessiontime')" . |
|
| 154 | - " LEFT JOIN `##user_setting` us4 ON (u.user_id=us4.user_id AND us4.setting_name='verified')" . |
|
| 155 | - " LEFT JOIN `##user_setting` us5 ON (u.user_id=us5.user_id AND us5.setting_name='verified_by_admin')" . |
|
| 156 | - " WHERE u.user_id > 0"; |
|
| 157 | - |
|
| 158 | - $args = array(); |
|
| 159 | - |
|
| 160 | - if ($search) { |
|
| 161 | - $sql_select .= " AND (user_name LIKE CONCAT('%', :search_1, '%') OR real_name LIKE CONCAT('%', :search_2, '%') OR email LIKE CONCAT('%', :search_3, '%'))"; |
|
| 162 | - $args['search_1'] = $search; |
|
| 163 | - $args['search_2'] = $search; |
|
| 164 | - $args['search_3'] = $search; |
|
| 165 | - } |
|
| 166 | - |
|
| 167 | - if ($order) { |
|
| 168 | - $sql_select .= " ORDER BY "; |
|
| 169 | - foreach ($order as $key => $value) { |
|
| 170 | - if ($key > 0) { |
|
| 171 | - $sql_select .= ','; |
|
| 172 | - } |
|
| 173 | - // Datatables numbers columns 0, 1, 2 |
|
| 174 | - // MySQL numbers columns 1, 2, 3 |
|
| 175 | - switch ($value['dir']) { |
|
| 176 | - case 'asc': |
|
| 177 | - $sql_select .= (1 + $value['column']) . " ASC "; |
|
| 178 | - break; |
|
| 179 | - case 'desc': |
|
| 180 | - $sql_select .= (1 + $value['column']) . " DESC "; |
|
| 181 | - break; |
|
| 182 | - } |
|
| 183 | - } |
|
| 184 | - } else { |
|
| 185 | - $sql_select = " ORDER BY 1 ASC"; |
|
| 186 | - } |
|
| 187 | - |
|
| 188 | - if ($length) { |
|
| 189 | - Auth::user()->setPreference('admin_users_page_size', $length); |
|
| 190 | - $sql_select .= " LIMIT :limit OFFSET :offset"; |
|
| 191 | - $args['limit'] = $length; |
|
| 192 | - $args['offset'] = $start; |
|
| 193 | - } |
|
| 194 | - |
|
| 195 | - // This becomes a JSON list, not array, so need to fetch with numeric keys. |
|
| 196 | - $data = Database::prepare($sql_select)->execute($args)->fetchAll(PDO::FETCH_NUM); |
|
| 197 | - |
|
| 198 | - $installed_languages = array(); |
|
| 199 | - foreach (I18N::installedLocales() as $installed_locale) { |
|
| 200 | - $installed_languages[$installed_locale->languageTag()] = $installed_locale->endonym(); |
|
| 201 | - } |
|
| 202 | - |
|
| 203 | - // Reformat various columns for display |
|
| 204 | - foreach ($data as &$datum) { |
|
| 205 | - $user_id = $datum[1]; |
|
| 206 | - $user_name = $datum[2]; |
|
| 207 | - |
|
| 208 | - if ($user_id != Auth::id()) { |
|
| 209 | - $admin_options = '<li><a href="#" onclick="return masquerade(' . $user_id . ')"><i class="fa fa-fw fa-user"></i> ' . /* I18N: Pretend to be another user, by logging in as them */ |
|
| 210 | - I18N::translate('Masquerade as this user') . '</a></li>' . '<li><a href="#" onclick="delete_user(\'' . I18N::translate('Are you sure you want to delete “%s”?', Filter::escapeJs($user_name)) . '\', \'' . Filter::escapeJs($user_id) . '\');"><i class="fa fa-fw fa-trash-o"></i> ' . I18N::translate('Delete') . '</a></li>'; |
|
| 211 | - } else { |
|
| 212 | - // Do not delete ourself! |
|
| 213 | - $admin_options = ''; |
|
| 214 | - } |
|
| 215 | - |
|
| 216 | - $datum[0] = '<div class="btn-group"><button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"><i class="fa fa-pencil"></i> <span class="caret"></span></button><ul class="dropdown-menu" role="menu"><li><a href="?action=edit&user_id=' . $user_id . '"><i class="fa fa-fw fa-pencil"></i> ' . I18N::translate('Edit') . '</a></li><li class="divider"><li><a href="index_edit.php?user_id=' . $user_id . '"><i class="fa fa-fw fa-th-large"></i> ' . I18N::translate('Change the blocks on this user’s “My page”') . '</a></li>' . $admin_options . '</ul></div>'; |
|
| 217 | - // $datum[1] is the user ID |
|
| 218 | - // $datum[3] is the real name |
|
| 219 | - $datum[3] = '<span dir="auto">' . Filter::escapeHtml($datum[3]) . '</span>'; |
|
| 220 | - // $datum[4] is the email address |
|
| 221 | - if ($user_id != Auth::id()) { |
|
| 222 | - $datum[4] = '<a href="#" onclick="return message(\'' . Filter::escapeHtml($datum[2]) . '\', \'\', \'\');">' . Filter::escapeHtml($datum[4]) . '</i></a>'; |
|
| 223 | - } |
|
| 224 | - // $datum[2] is the username |
|
| 225 | - $datum[2] = '<span dir="auto">' . Filter::escapeHtml($datum[2]) . '</span>'; |
|
| 226 | - // $datum[5] is the langauge |
|
| 227 | - if (array_key_exists($datum[5], $installed_languages)) { |
|
| 228 | - $datum[5] = $installed_languages[$datum[5]]; |
|
| 229 | - } |
|
| 230 | - // $datum[6] is the sortable registration timestamp |
|
| 231 | - $datum[7] = $datum[6] ? FunctionsDate::formatTimestamp($datum[6] + WT_TIMESTAMP_OFFSET) : ''; |
|
| 232 | - if (date("U") - $datum[6] > 604800 && !$datum[10]) { |
|
| 233 | - $datum[7] = '<span class="red">' . $datum[7] . '</span>'; |
|
| 234 | - } |
|
| 235 | - // $datum[8] is the sortable last-login timestamp |
|
| 236 | - if ($datum[8]) { |
|
| 237 | - $datum[9] = FunctionsDate::formatTimestamp($datum[8] + WT_TIMESTAMP_OFFSET) . '<br>' . I18N::timeAgo(WT_TIMESTAMP - $datum[8]); |
|
| 238 | - } else { |
|
| 239 | - $datum[9] = I18N::translate('Never'); |
|
| 240 | - } |
|
| 241 | - $datum[10] = $datum[10] ? I18N::translate('yes') : I18N::translate('no'); |
|
| 242 | - $datum[11] = $datum[11] ? I18N::translate('yes') : I18N::translate('no'); |
|
| 243 | - } |
|
| 244 | - |
|
| 245 | - // Total filtered/unfiltered rows |
|
| 246 | - $recordsFiltered = (int) Database::prepare("SELECT FOUND_ROWS()")->fetchOne(); |
|
| 247 | - $recordsTotal = User::count(); |
|
| 248 | - |
|
| 249 | - header('Content-type: application/json'); |
|
| 250 | - // See http://www.datatables.net/usage/server-side |
|
| 251 | - echo json_encode(array( |
|
| 252 | - 'draw' => Filter::getInteger('draw'), |
|
| 253 | - 'recordsTotal' => $recordsTotal, |
|
| 254 | - 'recordsFiltered' => $recordsFiltered, |
|
| 255 | - 'data' => $data, |
|
| 256 | - )); |
|
| 257 | - |
|
| 258 | - return; |
|
| 141 | + // Generate an AJAX/JSON response for datatables to load a block of rows |
|
| 142 | + $search = Filter::postArray('search'); |
|
| 143 | + $search = $search['value']; |
|
| 144 | + $start = Filter::postInteger('start'); |
|
| 145 | + $length = Filter::postInteger('length'); |
|
| 146 | + $order = Filter::postArray('order'); |
|
| 147 | + |
|
| 148 | + $sql_select = |
|
| 149 | + "SELECT SQL_CALC_FOUND_ROWS '', u.user_id, user_name, real_name, email, us1.setting_value, us2.setting_value, NULL, us3.setting_value, NULL, us4.setting_value, us5.setting_value" . |
|
| 150 | + " FROM `##user` u" . |
|
| 151 | + " LEFT JOIN `##user_setting` us1 ON (u.user_id=us1.user_id AND us1.setting_name='language')" . |
|
| 152 | + " LEFT JOIN `##user_setting` us2 ON (u.user_id=us2.user_id AND us2.setting_name='reg_timestamp')" . |
|
| 153 | + " LEFT JOIN `##user_setting` us3 ON (u.user_id=us3.user_id AND us3.setting_name='sessiontime')" . |
|
| 154 | + " LEFT JOIN `##user_setting` us4 ON (u.user_id=us4.user_id AND us4.setting_name='verified')" . |
|
| 155 | + " LEFT JOIN `##user_setting` us5 ON (u.user_id=us5.user_id AND us5.setting_name='verified_by_admin')" . |
|
| 156 | + " WHERE u.user_id > 0"; |
|
| 157 | + |
|
| 158 | + $args = array(); |
|
| 159 | + |
|
| 160 | + if ($search) { |
|
| 161 | + $sql_select .= " AND (user_name LIKE CONCAT('%', :search_1, '%') OR real_name LIKE CONCAT('%', :search_2, '%') OR email LIKE CONCAT('%', :search_3, '%'))"; |
|
| 162 | + $args['search_1'] = $search; |
|
| 163 | + $args['search_2'] = $search; |
|
| 164 | + $args['search_3'] = $search; |
|
| 165 | + } |
|
| 166 | + |
|
| 167 | + if ($order) { |
|
| 168 | + $sql_select .= " ORDER BY "; |
|
| 169 | + foreach ($order as $key => $value) { |
|
| 170 | + if ($key > 0) { |
|
| 171 | + $sql_select .= ','; |
|
| 172 | + } |
|
| 173 | + // Datatables numbers columns 0, 1, 2 |
|
| 174 | + // MySQL numbers columns 1, 2, 3 |
|
| 175 | + switch ($value['dir']) { |
|
| 176 | + case 'asc': |
|
| 177 | + $sql_select .= (1 + $value['column']) . " ASC "; |
|
| 178 | + break; |
|
| 179 | + case 'desc': |
|
| 180 | + $sql_select .= (1 + $value['column']) . " DESC "; |
|
| 181 | + break; |
|
| 182 | + } |
|
| 183 | + } |
|
| 184 | + } else { |
|
| 185 | + $sql_select = " ORDER BY 1 ASC"; |
|
| 186 | + } |
|
| 187 | + |
|
| 188 | + if ($length) { |
|
| 189 | + Auth::user()->setPreference('admin_users_page_size', $length); |
|
| 190 | + $sql_select .= " LIMIT :limit OFFSET :offset"; |
|
| 191 | + $args['limit'] = $length; |
|
| 192 | + $args['offset'] = $start; |
|
| 193 | + } |
|
| 194 | + |
|
| 195 | + // This becomes a JSON list, not array, so need to fetch with numeric keys. |
|
| 196 | + $data = Database::prepare($sql_select)->execute($args)->fetchAll(PDO::FETCH_NUM); |
|
| 197 | + |
|
| 198 | + $installed_languages = array(); |
|
| 199 | + foreach (I18N::installedLocales() as $installed_locale) { |
|
| 200 | + $installed_languages[$installed_locale->languageTag()] = $installed_locale->endonym(); |
|
| 201 | + } |
|
| 202 | + |
|
| 203 | + // Reformat various columns for display |
|
| 204 | + foreach ($data as &$datum) { |
|
| 205 | + $user_id = $datum[1]; |
|
| 206 | + $user_name = $datum[2]; |
|
| 207 | + |
|
| 208 | + if ($user_id != Auth::id()) { |
|
| 209 | + $admin_options = '<li><a href="#" onclick="return masquerade(' . $user_id . ')"><i class="fa fa-fw fa-user"></i> ' . /* I18N: Pretend to be another user, by logging in as them */ |
|
| 210 | + I18N::translate('Masquerade as this user') . '</a></li>' . '<li><a href="#" onclick="delete_user(\'' . I18N::translate('Are you sure you want to delete “%s”?', Filter::escapeJs($user_name)) . '\', \'' . Filter::escapeJs($user_id) . '\');"><i class="fa fa-fw fa-trash-o"></i> ' . I18N::translate('Delete') . '</a></li>'; |
|
| 211 | + } else { |
|
| 212 | + // Do not delete ourself! |
|
| 213 | + $admin_options = ''; |
|
| 214 | + } |
|
| 215 | + |
|
| 216 | + $datum[0] = '<div class="btn-group"><button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"><i class="fa fa-pencil"></i> <span class="caret"></span></button><ul class="dropdown-menu" role="menu"><li><a href="?action=edit&user_id=' . $user_id . '"><i class="fa fa-fw fa-pencil"></i> ' . I18N::translate('Edit') . '</a></li><li class="divider"><li><a href="index_edit.php?user_id=' . $user_id . '"><i class="fa fa-fw fa-th-large"></i> ' . I18N::translate('Change the blocks on this user’s “My page”') . '</a></li>' . $admin_options . '</ul></div>'; |
|
| 217 | + // $datum[1] is the user ID |
|
| 218 | + // $datum[3] is the real name |
|
| 219 | + $datum[3] = '<span dir="auto">' . Filter::escapeHtml($datum[3]) . '</span>'; |
|
| 220 | + // $datum[4] is the email address |
|
| 221 | + if ($user_id != Auth::id()) { |
|
| 222 | + $datum[4] = '<a href="#" onclick="return message(\'' . Filter::escapeHtml($datum[2]) . '\', \'\', \'\');">' . Filter::escapeHtml($datum[4]) . '</i></a>'; |
|
| 223 | + } |
|
| 224 | + // $datum[2] is the username |
|
| 225 | + $datum[2] = '<span dir="auto">' . Filter::escapeHtml($datum[2]) . '</span>'; |
|
| 226 | + // $datum[5] is the langauge |
|
| 227 | + if (array_key_exists($datum[5], $installed_languages)) { |
|
| 228 | + $datum[5] = $installed_languages[$datum[5]]; |
|
| 229 | + } |
|
| 230 | + // $datum[6] is the sortable registration timestamp |
|
| 231 | + $datum[7] = $datum[6] ? FunctionsDate::formatTimestamp($datum[6] + WT_TIMESTAMP_OFFSET) : ''; |
|
| 232 | + if (date("U") - $datum[6] > 604800 && !$datum[10]) { |
|
| 233 | + $datum[7] = '<span class="red">' . $datum[7] . '</span>'; |
|
| 234 | + } |
|
| 235 | + // $datum[8] is the sortable last-login timestamp |
|
| 236 | + if ($datum[8]) { |
|
| 237 | + $datum[9] = FunctionsDate::formatTimestamp($datum[8] + WT_TIMESTAMP_OFFSET) . '<br>' . I18N::timeAgo(WT_TIMESTAMP - $datum[8]); |
|
| 238 | + } else { |
|
| 239 | + $datum[9] = I18N::translate('Never'); |
|
| 240 | + } |
|
| 241 | + $datum[10] = $datum[10] ? I18N::translate('yes') : I18N::translate('no'); |
|
| 242 | + $datum[11] = $datum[11] ? I18N::translate('yes') : I18N::translate('no'); |
|
| 243 | + } |
|
| 244 | + |
|
| 245 | + // Total filtered/unfiltered rows |
|
| 246 | + $recordsFiltered = (int) Database::prepare("SELECT FOUND_ROWS()")->fetchOne(); |
|
| 247 | + $recordsTotal = User::count(); |
|
| 248 | + |
|
| 249 | + header('Content-type: application/json'); |
|
| 250 | + // See http://www.datatables.net/usage/server-side |
|
| 251 | + echo json_encode(array( |
|
| 252 | + 'draw' => Filter::getInteger('draw'), |
|
| 253 | + 'recordsTotal' => $recordsTotal, |
|
| 254 | + 'recordsFiltered' => $recordsFiltered, |
|
| 255 | + 'data' => $data, |
|
| 256 | + )); |
|
| 257 | + |
|
| 258 | + return; |
|
| 259 | 259 | |
| 260 | 260 | case 'edit': |
| 261 | - $user_id = Filter::getInteger('user_id'); |
|
| 262 | - |
|
| 263 | - if ($user_id === 0) { |
|
| 264 | - $controller->setPageTitle(I18N::translate('Add a user')); |
|
| 265 | - $tmp = new \stdClass; |
|
| 266 | - $tmp->user_id = ''; |
|
| 267 | - $tmp->user_name = ''; |
|
| 268 | - $tmp->real_name = ''; |
|
| 269 | - $tmp->email = ''; |
|
| 270 | - $user = new User($tmp); |
|
| 271 | - } else { |
|
| 272 | - $controller->setPageTitle(I18N::translate('Edit the user')); |
|
| 273 | - $user = User::find($user_id); |
|
| 274 | - } |
|
| 275 | - |
|
| 276 | - $controller |
|
| 277 | - ->pageHeader() |
|
| 278 | - ->addExternalJavascript(WT_AUTOCOMPLETE_JS_URL) |
|
| 279 | - ->addInlineJavascript('autocomplete();') |
|
| 280 | - ->addInlineJavascript(' |
|
| 261 | + $user_id = Filter::getInteger('user_id'); |
|
| 262 | + |
|
| 263 | + if ($user_id === 0) { |
|
| 264 | + $controller->setPageTitle(I18N::translate('Add a user')); |
|
| 265 | + $tmp = new \stdClass; |
|
| 266 | + $tmp->user_id = ''; |
|
| 267 | + $tmp->user_name = ''; |
|
| 268 | + $tmp->real_name = ''; |
|
| 269 | + $tmp->email = ''; |
|
| 270 | + $user = new User($tmp); |
|
| 271 | + } else { |
|
| 272 | + $controller->setPageTitle(I18N::translate('Edit the user')); |
|
| 273 | + $user = User::find($user_id); |
|
| 274 | + } |
|
| 275 | + |
|
| 276 | + $controller |
|
| 277 | + ->pageHeader() |
|
| 278 | + ->addExternalJavascript(WT_AUTOCOMPLETE_JS_URL) |
|
| 279 | + ->addInlineJavascript('autocomplete();') |
|
| 280 | + ->addInlineJavascript(' |
|
| 281 | 281 | jQuery(".relpath").change(function() { |
| 282 | 282 | var fieldIDx = jQuery(this).attr("id"); |
| 283 | 283 | var idNum = fieldIDx.replace("RELATIONSHIP_PATH_LENGTH",""); |
@@ -292,7 +292,7 @@ discard block |
||
| 292 | 292 | } |
| 293 | 293 | '); |
| 294 | 294 | |
| 295 | - ?> |
|
| 295 | + ?> |
|
| 296 | 296 | <ol class="breadcrumb small"> |
| 297 | 297 | <li><a href="admin.php"><?php echo I18N::translate('Control panel'); ?></a></li> |
| 298 | 298 | <li><a href="admin_users.php"><?php echo I18N::translate('User administration'); ?></a></li> |
@@ -474,7 +474,7 @@ discard block |
||
| 474 | 474 | <?php echo FunctionsEdit::editFieldContact('contact_method', $user->getPreference('contactmethod')); ?> |
| 475 | 475 | <p class="small text-muted"> |
| 476 | 476 | <?php echo /* I18N: Help text for the “Preferred contact method” configuration setting */ |
| 477 | - I18N::translate('Site members can send each other messages. You can choose to how these messages are sent to you, or choose not receive them at all.'); ?> |
|
| 477 | + I18N::translate('Site members can send each other messages. You can choose to how these messages are sent to you, or choose not receive them at all.'); ?> |
|
| 478 | 478 | </p> |
| 479 | 479 | </div> |
| 480 | 480 | </div> |
@@ -656,15 +656,15 @@ discard block |
||
| 656 | 656 | </form> |
| 657 | 657 | <?php |
| 658 | 658 | |
| 659 | - return; |
|
| 659 | + return; |
|
| 660 | 660 | |
| 661 | 661 | case 'cleanup': |
| 662 | 662 | |
| 663 | - $controller |
|
| 664 | - ->setPageTitle(I18N::translate('Delete inactive users')) |
|
| 665 | - ->pageHeader(); |
|
| 663 | + $controller |
|
| 664 | + ->setPageTitle(I18N::translate('Delete inactive users')) |
|
| 665 | + ->pageHeader(); |
|
| 666 | 666 | |
| 667 | - ?> |
|
| 667 | + ?> |
|
| 668 | 668 | <ol class="breadcrumb small"> |
| 669 | 669 | <li><a href="admin.php"><?php echo I18N::translate('Control panel'); ?></a></li> |
| 670 | 670 | <li><a href="admin_users.php"><?php echo I18N::translate('User administration'); ?></a></li> |
@@ -675,30 +675,30 @@ discard block |
||
| 675 | 675 | <form method="post" action="?action=cleanup2"> |
| 676 | 676 | <table class="table table-bordered"> |
| 677 | 677 | <?php |
| 678 | - // Check for idle users |
|
| 679 | - $month = Filter::getInteger('month', 1, 12, 6); |
|
| 680 | - echo '<tr><th colspan="2">', I18N::translate('Number of months since the last sign-in for a user’s account to be considered inactive: '), '</th>'; |
|
| 681 | - echo '<td><select onchange="document.location=options[selectedIndex].value;">'; |
|
| 682 | - for ($i = 1; $i <= 12; $i++) { |
|
| 683 | - echo '<option value="admin_users.php?action=cleanup&month=' . $i . '" '; |
|
| 684 | - if ($i === $month) { |
|
| 685 | - echo 'selected'; |
|
| 686 | - } |
|
| 687 | - echo '>', $i, '</option>'; |
|
| 688 | - } |
|
| 689 | - echo '</select></td></tr>'; |
|
| 690 | - |
|
| 691 | - // Check users not logged in too long |
|
| 692 | - $ucnt = 0; |
|
| 693 | - foreach (User::all() as $user) { |
|
| 694 | - if ($user->getPreference('sessiontime') === '0') { |
|
| 695 | - $datelogin = (int) $user->getPreference('reg_timestamp'); |
|
| 696 | - } else { |
|
| 697 | - $datelogin = (int) $user->getPreference('sessiontime'); |
|
| 698 | - } |
|
| 699 | - if (mktime(0, 0, 0, (int) date('m') - $month, (int) date('d'), (int) date('Y')) > $datelogin && $user->getPreference('verified') && $user->getPreference('verified_by_admin')) { |
|
| 700 | - $ucnt++; |
|
| 701 | - ?> |
|
| 678 | + // Check for idle users |
|
| 679 | + $month = Filter::getInteger('month', 1, 12, 6); |
|
| 680 | + echo '<tr><th colspan="2">', I18N::translate('Number of months since the last sign-in for a user’s account to be considered inactive: '), '</th>'; |
|
| 681 | + echo '<td><select onchange="document.location=options[selectedIndex].value;">'; |
|
| 682 | + for ($i = 1; $i <= 12; $i++) { |
|
| 683 | + echo '<option value="admin_users.php?action=cleanup&month=' . $i . '" '; |
|
| 684 | + if ($i === $month) { |
|
| 685 | + echo 'selected'; |
|
| 686 | + } |
|
| 687 | + echo '>', $i, '</option>'; |
|
| 688 | + } |
|
| 689 | + echo '</select></td></tr>'; |
|
| 690 | + |
|
| 691 | + // Check users not logged in too long |
|
| 692 | + $ucnt = 0; |
|
| 693 | + foreach (User::all() as $user) { |
|
| 694 | + if ($user->getPreference('sessiontime') === '0') { |
|
| 695 | + $datelogin = (int) $user->getPreference('reg_timestamp'); |
|
| 696 | + } else { |
|
| 697 | + $datelogin = (int) $user->getPreference('sessiontime'); |
|
| 698 | + } |
|
| 699 | + if (mktime(0, 0, 0, (int) date('m') - $month, (int) date('d'), (int) date('Y')) > $datelogin && $user->getPreference('verified') && $user->getPreference('verified_by_admin')) { |
|
| 700 | + $ucnt++; |
|
| 701 | + ?> |
|
| 702 | 702 | <tr> |
| 703 | 703 | <td> |
| 704 | 704 | <a href="?action=edit&user_id=<?php echo $user->getUserId(); ?>"> |
@@ -715,14 +715,14 @@ discard block |
||
| 715 | 715 | </td> |
| 716 | 716 | </tr> |
| 717 | 717 | <?php |
| 718 | - } |
|
| 719 | - } |
|
| 720 | - |
|
| 721 | - // Check unverified users |
|
| 722 | - foreach (User::all() as $user) { |
|
| 723 | - if (((date('U') - (int) $user->getPreference('reg_timestamp')) > 604800) && !$user->getPreference('verified')) { |
|
| 724 | - $ucnt++; |
|
| 725 | - ?> |
|
| 718 | + } |
|
| 719 | + } |
|
| 720 | + |
|
| 721 | + // Check unverified users |
|
| 722 | + foreach (User::all() as $user) { |
|
| 723 | + if (((date('U') - (int) $user->getPreference('reg_timestamp')) > 604800) && !$user->getPreference('verified')) { |
|
| 724 | + $ucnt++; |
|
| 725 | + ?> |
|
| 726 | 726 | <tr> |
| 727 | 727 | <td> |
| 728 | 728 | <a href="?action=edit&user_id=<?php echo $user->getUserId(); ?>"> |
@@ -739,14 +739,14 @@ discard block |
||
| 739 | 739 | </td> |
| 740 | 740 | </tr> |
| 741 | 741 | <?php |
| 742 | - } |
|
| 743 | - } |
|
| 744 | - |
|
| 745 | - // Check users not verified by admin |
|
| 746 | - foreach (User::all() as $user) { |
|
| 747 | - if ($user->getUserId() !== Auth::id() && !$user->getPreference('verified_by_admin') && $user->getPreference('verified')) { |
|
| 748 | - $ucnt++; |
|
| 749 | - ?> |
|
| 742 | + } |
|
| 743 | + } |
|
| 744 | + |
|
| 745 | + // Check users not verified by admin |
|
| 746 | + foreach (User::all() as $user) { |
|
| 747 | + if ($user->getUserId() !== Auth::id() && !$user->getPreference('verified_by_admin') && $user->getPreference('verified')) { |
|
| 748 | + $ucnt++; |
|
| 749 | + ?> |
|
| 750 | 750 | <tr> |
| 751 | 751 | <td> |
| 752 | 752 | <a href="?action=edit&user_id=<?php echo $user->getUserId(); ?>"> |
@@ -763,9 +763,9 @@ discard block |
||
| 763 | 763 | </td> |
| 764 | 764 | </tr> |
| 765 | 765 | <?php |
| 766 | - } |
|
| 767 | - } |
|
| 768 | - ?> |
|
| 766 | + } |
|
| 767 | + } |
|
| 768 | + ?> |
|
| 769 | 769 | </table> |
| 770 | 770 | <p> |
| 771 | 771 | <?php if ($ucnt): ?> |
@@ -776,25 +776,25 @@ discard block |
||
| 776 | 776 | </p> |
| 777 | 777 | </form> |
| 778 | 778 | <?php |
| 779 | - break; |
|
| 779 | + break; |
|
| 780 | 780 | |
| 781 | 781 | case 'cleanup2': |
| 782 | - foreach (User::all() as $user) { |
|
| 783 | - if (Filter::post('del_' . $user->getUserId()) == '1') { |
|
| 784 | - Log::addAuthenticationLog('Deleted user: ' . $user->getUserName()); |
|
| 785 | - $user->delete(); |
|
| 786 | - I18N::translate('The user %s has been deleted.', Filter::escapeHtml($user->getUserName())); |
|
| 787 | - } |
|
| 788 | - } |
|
| 789 | - |
|
| 790 | - header('Location: ' . WT_BASE_URL . WT_SCRIPT_NAME); |
|
| 791 | - break; |
|
| 782 | + foreach (User::all() as $user) { |
|
| 783 | + if (Filter::post('del_' . $user->getUserId()) == '1') { |
|
| 784 | + Log::addAuthenticationLog('Deleted user: ' . $user->getUserName()); |
|
| 785 | + $user->delete(); |
|
| 786 | + I18N::translate('The user %s has been deleted.', Filter::escapeHtml($user->getUserName())); |
|
| 787 | + } |
|
| 788 | + } |
|
| 789 | + |
|
| 790 | + header('Location: ' . WT_BASE_URL . WT_SCRIPT_NAME); |
|
| 791 | + break; |
|
| 792 | 792 | default: |
| 793 | - $controller |
|
| 794 | - ->setPageTitle(I18N::translate('User administration')) |
|
| 795 | - ->addExternalJavascript(WT_JQUERY_DATATABLES_JS_URL) |
|
| 796 | - ->addExternalJavascript(WT_DATATABLES_BOOTSTRAP_JS_URL) |
|
| 797 | - ->addInlineJavascript(' |
|
| 793 | + $controller |
|
| 794 | + ->setPageTitle(I18N::translate('User administration')) |
|
| 795 | + ->addExternalJavascript(WT_JQUERY_DATATABLES_JS_URL) |
|
| 796 | + ->addExternalJavascript(WT_DATATABLES_BOOTSTRAP_JS_URL) |
|
| 797 | + ->addInlineJavascript(' |
|
| 798 | 798 | jQuery(".table-user-list").dataTable({ |
| 799 | 799 | ' . I18N::datatablesI18N() . ', |
| 800 | 800 | stateSave: true, |
@@ -828,9 +828,9 @@ discard block |
||
| 828 | 828 | }) |
| 829 | 829 | .fnFilter("' . Filter::get('filter') . '"); // View the details of a newly created user |
| 830 | 830 | ') |
| 831 | - ->pageHeader(); |
|
| 831 | + ->pageHeader(); |
|
| 832 | 832 | |
| 833 | - ?> |
|
| 833 | + ?> |
|
| 834 | 834 | <ol class="breadcrumb small"> |
| 835 | 835 | <li><a href="admin.php"><?php echo I18N::translate('Control panel'); ?></a></li> |
| 836 | 836 | <li class="active"><?php echo $controller->getPageTitle(); ?></li> |
@@ -858,5 +858,5 @@ discard block |
||
| 858 | 858 | </tbody> |
| 859 | 859 | </table> |
| 860 | 860 | <?php |
| 861 | - break; |
|
| 861 | + break; |
|
| 862 | 862 | } |
@@ -45,95 +45,95 @@ discard block |
||
| 45 | 45 | |
| 46 | 46 | // Form actions |
| 47 | 47 | switch (Filter::post('action')) { |
| 48 | -case 'save': |
|
| 49 | - if (Filter::checkCsrf()) { |
|
| 50 | - $user_id = Filter::postInteger('user_id'); |
|
| 51 | - $user = User::find($user_id); |
|
| 52 | - $username = Filter::post('username'); |
|
| 53 | - $real_name = Filter::post('real_name'); |
|
| 54 | - $email = Filter::postEmail('email'); |
|
| 55 | - $pass1 = Filter::post('pass1', WT_REGEX_PASSWORD); |
|
| 56 | - $pass2 = Filter::post('pass2', WT_REGEX_PASSWORD); |
|
| 57 | - $theme = Filter::post('theme', implode('|', array_keys(Theme::themeNames())), ''); |
|
| 58 | - $language = Filter::post('language'); |
|
| 59 | - $timezone = Filter::post('timezone'); |
|
| 60 | - $contact_method = Filter::post('contact_method'); |
|
| 61 | - $comment = Filter::post('comment'); |
|
| 62 | - $auto_accept = Filter::postBool('auto_accept'); |
|
| 63 | - $canadmin = Filter::postBool('canadmin'); |
|
| 64 | - $visible_online = Filter::postBool('visible_online'); |
|
| 65 | - $verified = Filter::postBool('verified'); |
|
| 66 | - $approved = Filter::postBool('approved'); |
|
| 67 | - |
|
| 68 | - if ($user_id === 0) { |
|
| 69 | - // Create a new user |
|
| 70 | - if (User::findByUserName($username)) { |
|
| 71 | - FlashMessages::addMessage(I18N::translate('Duplicate username. A user with that username already exists. Please choose another username.')); |
|
| 72 | - } elseif (User::findByEmail($email)) { |
|
| 73 | - FlashMessages::addMessage(I18N::translate('Duplicate email address. A user with that email already exists.')); |
|
| 74 | - } elseif ($pass1 !== $pass2) { |
|
| 75 | - FlashMessages::addMessage(I18N::translate('The passwords do not match.')); |
|
| 76 | - } else { |
|
| 77 | - $user = User::create($username, $real_name, $email, $pass1); |
|
| 78 | - $user->setPreference('reg_timestamp', date('U'))->setPreference('sessiontime', '0'); |
|
| 79 | - Log::addAuthenticationLog('User ->' . $username . '<- created'); |
|
| 80 | - } |
|
| 81 | - } else { |
|
| 82 | - $user = User::find($user_id); |
|
| 83 | - if ($user && $username && $real_name) { |
|
| 84 | - $user->setEmail($email); |
|
| 85 | - $user->setUserName($username); |
|
| 86 | - $user->setRealName($real_name); |
|
| 87 | - if ($pass1 !== null && $pass1 === $pass2) { |
|
| 88 | - $user->setPassword($pass1); |
|
| 89 | - } |
|
| 90 | - } |
|
| 91 | - } |
|
| 92 | - |
|
| 93 | - if ($user) { |
|
| 94 | - // Approving for the first time? Send a confirmation email |
|
| 95 | - if ($approved && !$user->getPreference('verified_by_admin') && $user->getPreference('sessiontime') == 0) { |
|
| 96 | - I18N::init($user->getPreference('language')); |
|
| 97 | - Mail::systemMessage( |
|
| 98 | - $WT_TREE, |
|
| 99 | - $user, |
|
| 100 | - I18N::translate('Approval of account at %s', WT_BASE_URL), |
|
| 101 | - I18N::translate('The administrator at the webtrees site %s has approved your application for an account. You may now sign in by accessing the following link: %s', WT_BASE_URL, WT_BASE_URL) |
|
| 102 | - ); |
|
| 103 | - } |
|
| 104 | - |
|
| 105 | - $user |
|
| 106 | - ->setPreference('theme', $theme) |
|
| 107 | - ->setPreference('language', $language) |
|
| 108 | - ->setPreference('TIMEZONE', $timezone) |
|
| 109 | - ->setPreference('contactmethod', $contact_method) |
|
| 110 | - ->setPreference('comment', $comment) |
|
| 111 | - ->setPreference('auto_accept', $auto_accept ? '1' : '0') |
|
| 112 | - ->setPreference('visibleonline', $visible_online ? '1' : '0') |
|
| 113 | - ->setPreference('verified', $verified ? '1' : '0') |
|
| 114 | - ->setPreference('verified_by_admin', $approved ? '1' : '0'); |
|
| 115 | - |
|
| 116 | - // We cannot change our own admin status. Another admin will need to do it. |
|
| 117 | - if ($user->getUserId() !== Auth::id()) { |
|
| 118 | - $user->setPreference('canadmin', $canadmin ? '1' : '0'); |
|
| 119 | - } |
|
| 120 | - |
|
| 121 | - foreach (Tree::getAll() as $tree) { |
|
| 122 | - $tree->setUserPreference($user, 'gedcomid', Filter::post('gedcomid' . $tree->getTreeId(), WT_REGEX_XREF)); |
|
| 123 | - $tree->setUserPreference($user, 'canedit', Filter::post('canedit' . $tree->getTreeId(), implode('|', array_keys($ALL_EDIT_OPTIONS)))); |
|
| 124 | - if (Filter::post('gedcomid' . $tree->getTreeId(), WT_REGEX_XREF)) { |
|
| 125 | - $tree->setUserPreference($user, 'RELATIONSHIP_PATH_LENGTH', Filter::postInteger('RELATIONSHIP_PATH_LENGTH' . $tree->getTreeId(), 0, 10, 0)); |
|
| 126 | - } else { |
|
| 127 | - // Do not allow a path length to be set if the individual ID is not |
|
| 128 | - $tree->setUserPreference($user, 'RELATIONSHIP_PATH_LENGTH', null); |
|
| 129 | - } |
|
| 130 | - } |
|
| 131 | - } |
|
| 132 | - } |
|
| 133 | - |
|
| 134 | - header('Location: ' . WT_BASE_URL . WT_SCRIPT_NAME); |
|
| 135 | - |
|
| 136 | - return; |
|
| 48 | + case 'save': |
|
| 49 | + if (Filter::checkCsrf()) { |
|
| 50 | + $user_id = Filter::postInteger('user_id'); |
|
| 51 | + $user = User::find($user_id); |
|
| 52 | + $username = Filter::post('username'); |
|
| 53 | + $real_name = Filter::post('real_name'); |
|
| 54 | + $email = Filter::postEmail('email'); |
|
| 55 | + $pass1 = Filter::post('pass1', WT_REGEX_PASSWORD); |
|
| 56 | + $pass2 = Filter::post('pass2', WT_REGEX_PASSWORD); |
|
| 57 | + $theme = Filter::post('theme', implode('|', array_keys(Theme::themeNames())), ''); |
|
| 58 | + $language = Filter::post('language'); |
|
| 59 | + $timezone = Filter::post('timezone'); |
|
| 60 | + $contact_method = Filter::post('contact_method'); |
|
| 61 | + $comment = Filter::post('comment'); |
|
| 62 | + $auto_accept = Filter::postBool('auto_accept'); |
|
| 63 | + $canadmin = Filter::postBool('canadmin'); |
|
| 64 | + $visible_online = Filter::postBool('visible_online'); |
|
| 65 | + $verified = Filter::postBool('verified'); |
|
| 66 | + $approved = Filter::postBool('approved'); |
|
| 67 | + |
|
| 68 | + if ($user_id === 0) { |
|
| 69 | + // Create a new user |
|
| 70 | + if (User::findByUserName($username)) { |
|
| 71 | + FlashMessages::addMessage(I18N::translate('Duplicate username. A user with that username already exists. Please choose another username.')); |
|
| 72 | + } elseif (User::findByEmail($email)) { |
|
| 73 | + FlashMessages::addMessage(I18N::translate('Duplicate email address. A user with that email already exists.')); |
|
| 74 | + } elseif ($pass1 !== $pass2) { |
|
| 75 | + FlashMessages::addMessage(I18N::translate('The passwords do not match.')); |
|
| 76 | + } else { |
|
| 77 | + $user = User::create($username, $real_name, $email, $pass1); |
|
| 78 | + $user->setPreference('reg_timestamp', date('U'))->setPreference('sessiontime', '0'); |
|
| 79 | + Log::addAuthenticationLog('User ->' . $username . '<- created'); |
|
| 80 | + } |
|
| 81 | + } else { |
|
| 82 | + $user = User::find($user_id); |
|
| 83 | + if ($user && $username && $real_name) { |
|
| 84 | + $user->setEmail($email); |
|
| 85 | + $user->setUserName($username); |
|
| 86 | + $user->setRealName($real_name); |
|
| 87 | + if ($pass1 !== null && $pass1 === $pass2) { |
|
| 88 | + $user->setPassword($pass1); |
|
| 89 | + } |
|
| 90 | + } |
|
| 91 | + } |
|
| 92 | + |
|
| 93 | + if ($user) { |
|
| 94 | + // Approving for the first time? Send a confirmation email |
|
| 95 | + if ($approved && !$user->getPreference('verified_by_admin') && $user->getPreference('sessiontime') == 0) { |
|
| 96 | + I18N::init($user->getPreference('language')); |
|
| 97 | + Mail::systemMessage( |
|
| 98 | + $WT_TREE, |
|
| 99 | + $user, |
|
| 100 | + I18N::translate('Approval of account at %s', WT_BASE_URL), |
|
| 101 | + I18N::translate('The administrator at the webtrees site %s has approved your application for an account. You may now sign in by accessing the following link: %s', WT_BASE_URL, WT_BASE_URL) |
|
| 102 | + ); |
|
| 103 | + } |
|
| 104 | + |
|
| 105 | + $user |
|
| 106 | + ->setPreference('theme', $theme) |
|
| 107 | + ->setPreference('language', $language) |
|
| 108 | + ->setPreference('TIMEZONE', $timezone) |
|
| 109 | + ->setPreference('contactmethod', $contact_method) |
|
| 110 | + ->setPreference('comment', $comment) |
|
| 111 | + ->setPreference('auto_accept', $auto_accept ? '1' : '0') |
|
| 112 | + ->setPreference('visibleonline', $visible_online ? '1' : '0') |
|
| 113 | + ->setPreference('verified', $verified ? '1' : '0') |
|
| 114 | + ->setPreference('verified_by_admin', $approved ? '1' : '0'); |
|
| 115 | + |
|
| 116 | + // We cannot change our own admin status. Another admin will need to do it. |
|
| 117 | + if ($user->getUserId() !== Auth::id()) { |
|
| 118 | + $user->setPreference('canadmin', $canadmin ? '1' : '0'); |
|
| 119 | + } |
|
| 120 | + |
|
| 121 | + foreach (Tree::getAll() as $tree) { |
|
| 122 | + $tree->setUserPreference($user, 'gedcomid', Filter::post('gedcomid' . $tree->getTreeId(), WT_REGEX_XREF)); |
|
| 123 | + $tree->setUserPreference($user, 'canedit', Filter::post('canedit' . $tree->getTreeId(), implode('|', array_keys($ALL_EDIT_OPTIONS)))); |
|
| 124 | + if (Filter::post('gedcomid' . $tree->getTreeId(), WT_REGEX_XREF)) { |
|
| 125 | + $tree->setUserPreference($user, 'RELATIONSHIP_PATH_LENGTH', Filter::postInteger('RELATIONSHIP_PATH_LENGTH' . $tree->getTreeId(), 0, 10, 0)); |
|
| 126 | + } else { |
|
| 127 | + // Do not allow a path length to be set if the individual ID is not |
|
| 128 | + $tree->setUserPreference($user, 'RELATIONSHIP_PATH_LENGTH', null); |
|
| 129 | + } |
|
| 130 | + } |
|
| 131 | + } |
|
| 132 | + } |
|
| 133 | + |
|
| 134 | + header('Location: ' . WT_BASE_URL . WT_SCRIPT_NAME); |
|
| 135 | + |
|
| 136 | + return; |
|
| 137 | 137 | } |
| 138 | 138 | |
| 139 | 139 | switch (Filter::get('action')) { |
@@ -173,12 +173,12 @@ discard block |
||
| 173 | 173 | // Datatables numbers columns 0, 1, 2 |
| 174 | 174 | // MySQL numbers columns 1, 2, 3 |
| 175 | 175 | switch ($value['dir']) { |
| 176 | - case 'asc': |
|
| 177 | - $sql_select .= (1 + $value['column']) . " ASC "; |
|
| 178 | - break; |
|
| 179 | - case 'desc': |
|
| 180 | - $sql_select .= (1 + $value['column']) . " DESC "; |
|
| 181 | - break; |
|
| 176 | + case 'asc': |
|
| 177 | + $sql_select .= (1 + $value['column']) . " ASC "; |
|
| 178 | + break; |
|
| 179 | + case 'desc': |
|
| 180 | + $sql_select .= (1 + $value['column']) . " DESC "; |
|
| 181 | + break; |
|
| 182 | 182 | } |
| 183 | 183 | } |
| 184 | 184 | } else { |
@@ -770,8 +770,11 @@ |
||
| 770 | 770 | <p> |
| 771 | 771 | <?php if ($ucnt): ?> |
| 772 | 772 | <input type="submit" value="<?php echo I18N::translate('delete'); ?>"> |
| 773 | - <?php else: ?> |
|
| 774 | - <?php echo I18N::translate('Nothing found to cleanup'); ?> |
|
| 773 | + <?php else { |
|
| 774 | + : ?> |
|
| 775 | + <?php echo I18N::translate('Nothing found to cleanup'); |
|
| 776 | +} |
|
| 777 | +?> |
|
| 775 | 778 | <?php endif; ?> |
| 776 | 779 | </p> |
| 777 | 780 | </form> |
@@ -23,218 +23,218 @@ discard block |
||
| 23 | 23 | require './includes/session.php'; |
| 24 | 24 | |
| 25 | 25 | $rules_display = array( |
| 26 | - 'unknown' => I18N::translate('unknown'), |
|
| 27 | - 'allow' => /* I18N: An access rule - allow access to the site */ I18N::translate('allow'), |
|
| 28 | - 'deny' => /* I18N: An access rule - deny access to the site */ I18N::translate('deny'), |
|
| 29 | - 'robot' => /* I18N: http://en.wikipedia.org/wiki/Web_crawler */ I18N::translate('robot'), |
|
| 26 | + 'unknown' => I18N::translate('unknown'), |
|
| 27 | + 'allow' => /* I18N: An access rule - allow access to the site */ I18N::translate('allow'), |
|
| 28 | + 'deny' => /* I18N: An access rule - deny access to the site */ I18N::translate('deny'), |
|
| 29 | + 'robot' => /* I18N: http://en.wikipedia.org/wiki/Web_crawler */ I18N::translate('robot'), |
|
| 30 | 30 | ); |
| 31 | 31 | |
| 32 | 32 | $rules_edit = array( |
| 33 | - 'unknown' => I18N::translate('unknown'), |
|
| 34 | - 'allow' => /* I18N: An access rule - allow access to the site */ I18N::translate('allow'), |
|
| 35 | - 'deny' => /* I18N: An access rule - deny access to the site */ I18N::translate('deny'), |
|
| 36 | - 'robot' => /* I18N: http://en.wikipedia.org/wiki/Web_crawler */ I18N::translate('robot'), |
|
| 33 | + 'unknown' => I18N::translate('unknown'), |
|
| 34 | + 'allow' => /* I18N: An access rule - allow access to the site */ I18N::translate('allow'), |
|
| 35 | + 'deny' => /* I18N: An access rule - deny access to the site */ I18N::translate('deny'), |
|
| 36 | + 'robot' => /* I18N: http://en.wikipedia.org/wiki/Web_crawler */ I18N::translate('robot'), |
|
| 37 | 37 | ); |
| 38 | 38 | |
| 39 | 39 | // Form actions |
| 40 | 40 | switch (Filter::post('action')) { |
| 41 | 41 | case 'save': |
| 42 | - if (Filter::checkCsrf()) { |
|
| 43 | - $site_access_rule_id = Filter::postInteger('site_access_rule_id'); |
|
| 44 | - $ip_address_start = Filter::post('ip_address_start', WT_REGEX_IPV4); |
|
| 45 | - $ip_address_end = Filter::post('ip_address_end', WT_REGEX_IPV4); |
|
| 46 | - $user_agent_pattern = Filter::post('user_agent_pattern'); |
|
| 47 | - $rule = Filter::post('rule', 'allow|deny|robot'); |
|
| 48 | - $comment = Filter::post('comment'); |
|
| 49 | - $user_agent_string = Filter::server('HTTP_USER_AGENT'); |
|
| 50 | - $ip_address = WT_CLIENT_IP; |
|
| 51 | - |
|
| 52 | - if ($ip_address_start !== null && $ip_address_end !== null && $user_agent_pattern !== null && $rule !== null) { |
|
| 53 | - // This doesn't work with named placeholders. The :user_agent_string parameter is not recognised. |
|
| 54 | - $oops = $rule !== 'allow' && Database::prepare( |
|
| 55 | - "SELECT INET_ATON(:ip_address) BETWEEN INET_ATON(:ip_address_start) AND INET_ATON(:ip_address_end)" . |
|
| 56 | - " AND :user_agent_string LIKE :user_agent_pattern" |
|
| 57 | - )->execute(array( |
|
| 58 | - 'ip_address' => $ip_address, |
|
| 59 | - 'ip_address_start' => $ip_address_start, |
|
| 60 | - 'ip_address_end' => $ip_address_end, |
|
| 61 | - 'user_agent_string' => $user_agent_string, |
|
| 62 | - 'user_agent_pattern' => $user_agent_pattern, |
|
| 63 | - ))->fetchOne(); |
|
| 64 | - |
|
| 65 | - if ($oops) { |
|
| 66 | - FlashMessages::addMessage(I18N::translate('You cannot create a rule which would prevent yourself from accessing the website.'), 'danger'); |
|
| 67 | - } elseif ($site_access_rule_id === null) { |
|
| 68 | - Database::prepare( |
|
| 69 | - "INSERT INTO `##site_access_rule` (ip_address_start, ip_address_end, user_agent_pattern, rule, comment) VALUES (INET_ATON(:ip_address_start), INET_ATON(:ip_address_end), :user_agent_pattern, :rule, :comment)" |
|
| 70 | - )->execute(array( |
|
| 71 | - 'ip_address_start' => $ip_address_start, |
|
| 72 | - 'ip_address_end' => $ip_address_end, |
|
| 73 | - 'user_agent_pattern' => $user_agent_pattern, |
|
| 74 | - 'rule' => $rule, |
|
| 75 | - 'comment' => $comment, |
|
| 76 | - )); |
|
| 77 | - FlashMessages::addMessage(I18N::translate('The website access rule has been created.'), 'success'); |
|
| 78 | - } else { |
|
| 79 | - Database::prepare( |
|
| 80 | - "UPDATE `##site_access_rule` SET ip_address_start = INET_ATON(:ip_address_start), ip_address_end = INET_ATON(:ip_address_end), user_agent_pattern = :user_agent_pattern, rule = :rule, comment = :comment WHERE site_access_rule_id = :site_access_rule_id" |
|
| 81 | - )->execute(array( |
|
| 82 | - 'ip_address_start' => $ip_address_start, |
|
| 83 | - 'ip_address_end' => $ip_address_end, |
|
| 84 | - 'user_agent_pattern' => $user_agent_pattern, |
|
| 85 | - 'rule' => $rule, |
|
| 86 | - 'comment' => $comment, |
|
| 87 | - 'site_access_rule_id' => $site_access_rule_id, |
|
| 88 | - )); |
|
| 89 | - FlashMessages::addMessage(I18N::translate('The website access rule has been updated.'), 'success'); |
|
| 90 | - } |
|
| 91 | - } |
|
| 92 | - } |
|
| 93 | - header('Location: ' . WT_BASE_URL . WT_SCRIPT_NAME); |
|
| 94 | - |
|
| 95 | - return; |
|
| 42 | + if (Filter::checkCsrf()) { |
|
| 43 | + $site_access_rule_id = Filter::postInteger('site_access_rule_id'); |
|
| 44 | + $ip_address_start = Filter::post('ip_address_start', WT_REGEX_IPV4); |
|
| 45 | + $ip_address_end = Filter::post('ip_address_end', WT_REGEX_IPV4); |
|
| 46 | + $user_agent_pattern = Filter::post('user_agent_pattern'); |
|
| 47 | + $rule = Filter::post('rule', 'allow|deny|robot'); |
|
| 48 | + $comment = Filter::post('comment'); |
|
| 49 | + $user_agent_string = Filter::server('HTTP_USER_AGENT'); |
|
| 50 | + $ip_address = WT_CLIENT_IP; |
|
| 51 | + |
|
| 52 | + if ($ip_address_start !== null && $ip_address_end !== null && $user_agent_pattern !== null && $rule !== null) { |
|
| 53 | + // This doesn't work with named placeholders. The :user_agent_string parameter is not recognised. |
|
| 54 | + $oops = $rule !== 'allow' && Database::prepare( |
|
| 55 | + "SELECT INET_ATON(:ip_address) BETWEEN INET_ATON(:ip_address_start) AND INET_ATON(:ip_address_end)" . |
|
| 56 | + " AND :user_agent_string LIKE :user_agent_pattern" |
|
| 57 | + )->execute(array( |
|
| 58 | + 'ip_address' => $ip_address, |
|
| 59 | + 'ip_address_start' => $ip_address_start, |
|
| 60 | + 'ip_address_end' => $ip_address_end, |
|
| 61 | + 'user_agent_string' => $user_agent_string, |
|
| 62 | + 'user_agent_pattern' => $user_agent_pattern, |
|
| 63 | + ))->fetchOne(); |
|
| 64 | + |
|
| 65 | + if ($oops) { |
|
| 66 | + FlashMessages::addMessage(I18N::translate('You cannot create a rule which would prevent yourself from accessing the website.'), 'danger'); |
|
| 67 | + } elseif ($site_access_rule_id === null) { |
|
| 68 | + Database::prepare( |
|
| 69 | + "INSERT INTO `##site_access_rule` (ip_address_start, ip_address_end, user_agent_pattern, rule, comment) VALUES (INET_ATON(:ip_address_start), INET_ATON(:ip_address_end), :user_agent_pattern, :rule, :comment)" |
|
| 70 | + )->execute(array( |
|
| 71 | + 'ip_address_start' => $ip_address_start, |
|
| 72 | + 'ip_address_end' => $ip_address_end, |
|
| 73 | + 'user_agent_pattern' => $user_agent_pattern, |
|
| 74 | + 'rule' => $rule, |
|
| 75 | + 'comment' => $comment, |
|
| 76 | + )); |
|
| 77 | + FlashMessages::addMessage(I18N::translate('The website access rule has been created.'), 'success'); |
|
| 78 | + } else { |
|
| 79 | + Database::prepare( |
|
| 80 | + "UPDATE `##site_access_rule` SET ip_address_start = INET_ATON(:ip_address_start), ip_address_end = INET_ATON(:ip_address_end), user_agent_pattern = :user_agent_pattern, rule = :rule, comment = :comment WHERE site_access_rule_id = :site_access_rule_id" |
|
| 81 | + )->execute(array( |
|
| 82 | + 'ip_address_start' => $ip_address_start, |
|
| 83 | + 'ip_address_end' => $ip_address_end, |
|
| 84 | + 'user_agent_pattern' => $user_agent_pattern, |
|
| 85 | + 'rule' => $rule, |
|
| 86 | + 'comment' => $comment, |
|
| 87 | + 'site_access_rule_id' => $site_access_rule_id, |
|
| 88 | + )); |
|
| 89 | + FlashMessages::addMessage(I18N::translate('The website access rule has been updated.'), 'success'); |
|
| 90 | + } |
|
| 91 | + } |
|
| 92 | + } |
|
| 93 | + header('Location: ' . WT_BASE_URL . WT_SCRIPT_NAME); |
|
| 94 | + |
|
| 95 | + return; |
|
| 96 | 96 | |
| 97 | 97 | case 'delete': |
| 98 | - if (Filter::checkCsrf()) { |
|
| 99 | - $site_access_rule_id = Filter::postInteger('site_access_rule_id'); |
|
| 100 | - Database::prepare( |
|
| 101 | - "DELETE FROM `##site_access_rule` WHERE site_access_rule_id = :site_access_rule_id" |
|
| 102 | - )->execute(array( |
|
| 103 | - 'site_access_rule_id' => $site_access_rule_id, |
|
| 104 | - )); |
|
| 105 | - FlashMessages::addMessage(I18N::translate('The website access rule has been deleted.'), 'success'); |
|
| 106 | - } |
|
| 107 | - header('Location: ' . WT_BASE_URL . WT_SCRIPT_NAME); |
|
| 108 | - |
|
| 109 | - return; |
|
| 98 | + if (Filter::checkCsrf()) { |
|
| 99 | + $site_access_rule_id = Filter::postInteger('site_access_rule_id'); |
|
| 100 | + Database::prepare( |
|
| 101 | + "DELETE FROM `##site_access_rule` WHERE site_access_rule_id = :site_access_rule_id" |
|
| 102 | + )->execute(array( |
|
| 103 | + 'site_access_rule_id' => $site_access_rule_id, |
|
| 104 | + )); |
|
| 105 | + FlashMessages::addMessage(I18N::translate('The website access rule has been deleted.'), 'success'); |
|
| 106 | + } |
|
| 107 | + header('Location: ' . WT_BASE_URL . WT_SCRIPT_NAME); |
|
| 108 | + |
|
| 109 | + return; |
|
| 110 | 110 | } |
| 111 | 111 | |
| 112 | 112 | // Delete any "unknown" visitors that are now "known". |
| 113 | 113 | // This could happen every time we create/update a rule. |
| 114 | 114 | Database::exec( |
| 115 | - "DELETE unknown" . |
|
| 116 | - " FROM `##site_access_rule` AS unknown" . |
|
| 117 | - " JOIN `##site_access_rule` AS known ON (unknown.user_agent_pattern LIKE known.user_agent_pattern)" . |
|
| 118 | - " WHERE unknown.rule='unknown' AND known.rule<>'unknown'" . |
|
| 119 | - " AND unknown.ip_address_start BETWEEN known.ip_address_start AND known.ip_address_end" |
|
| 115 | + "DELETE unknown" . |
|
| 116 | + " FROM `##site_access_rule` AS unknown" . |
|
| 117 | + " JOIN `##site_access_rule` AS known ON (unknown.user_agent_pattern LIKE known.user_agent_pattern)" . |
|
| 118 | + " WHERE unknown.rule='unknown' AND known.rule<>'unknown'" . |
|
| 119 | + " AND unknown.ip_address_start BETWEEN known.ip_address_start AND known.ip_address_end" |
|
| 120 | 120 | ); |
| 121 | 121 | |
| 122 | 122 | $controller = new PageController; |
| 123 | 123 | $controller |
| 124 | - ->restrictAccess(Auth::isAdmin()) |
|
| 125 | - ->addExternalJavascript(WT_JQUERY_DATATABLES_JS_URL) |
|
| 126 | - ->addExternalJavascript(WT_DATATABLES_BOOTSTRAP_JS_URL) |
|
| 127 | - ->setPageTitle(I18N::translate('Website access rules')); |
|
| 124 | + ->restrictAccess(Auth::isAdmin()) |
|
| 125 | + ->addExternalJavascript(WT_JQUERY_DATATABLES_JS_URL) |
|
| 126 | + ->addExternalJavascript(WT_DATATABLES_BOOTSTRAP_JS_URL) |
|
| 127 | + ->setPageTitle(I18N::translate('Website access rules')); |
|
| 128 | 128 | |
| 129 | 129 | $action = Filter::get('action'); |
| 130 | 130 | switch ($action) { |
| 131 | 131 | case 'load': |
| 132 | - // AJAX callback for datatables |
|
| 133 | - $search = Filter::get('search'); |
|
| 134 | - $search = $search['value']; |
|
| 135 | - $start = Filter::getInteger('start'); |
|
| 136 | - $length = Filter::getInteger('length'); |
|
| 137 | - |
|
| 138 | - $sql = |
|
| 139 | - "SELECT SQL_CALC_FOUND_ROWS" . |
|
| 140 | - " '', INET_NTOA(ip_address_start), ip_address_start, INET_NTOA(ip_address_end), ip_address_end, user_agent_pattern, rule, comment, site_access_rule_id" . |
|
| 141 | - " FROM `##site_access_rule`"; |
|
| 142 | - $args = array(); |
|
| 143 | - |
|
| 144 | - if ($search) { |
|
| 145 | - $sql .= |
|
| 146 | - " WHERE (INET_ATON(:search_1) BETWEEN ip_address_start AND ip_address_end" . |
|
| 147 | - " OR INET_NTOA(ip_address_start) LIKE CONCAT('%', :search_2, '%')" . |
|
| 148 | - " OR INET_NTOA(ip_address_end) LIKE CONCAT('%', :search_3, '%')" . |
|
| 149 | - " OR user_agent_pattern LIKE CONCAT('%', :search_4, '%')" . |
|
| 150 | - " OR comment LIKE CONCAT('%', :search_5, '%'))"; |
|
| 151 | - $args['search_1'] = Filter::escapeLike($search); |
|
| 152 | - $args['search_2'] = Filter::escapeLike($search); |
|
| 153 | - $args['search_3'] = Filter::escapeLike($search); |
|
| 154 | - $args['search_4'] = Filter::escapeLike($search); |
|
| 155 | - $args['search_5'] = Filter::escapeLike($search); |
|
| 156 | - } |
|
| 157 | - |
|
| 158 | - $order = Filter::getArray('order'); |
|
| 159 | - $sql .= ' ORDER BY'; |
|
| 160 | - if ($order) { |
|
| 161 | - foreach ($order as $key => $value) { |
|
| 162 | - if ($key > 0) { |
|
| 163 | - $sql .= ','; |
|
| 164 | - } |
|
| 165 | - // Datatables numbers columns 0, 1, 2 |
|
| 166 | - // MySQL numbers columns 1, 2, 3 |
|
| 167 | - switch ($value['dir']) { |
|
| 168 | - case 'asc': |
|
| 169 | - $sql .= " :col_" . $key . " ASC"; |
|
| 170 | - break; |
|
| 171 | - case 'desc': |
|
| 172 | - $sql .= " :col_" . $key . " DESC"; |
|
| 173 | - break; |
|
| 174 | - } |
|
| 175 | - $args['col_' . $key] = 1 + $value['column']; |
|
| 176 | - } |
|
| 177 | - } else { |
|
| 178 | - $sql .= ' 1 ASC'; |
|
| 179 | - } |
|
| 180 | - |
|
| 181 | - if ($length > 0) { |
|
| 182 | - $sql .= " LIMIT :length OFFSET :start"; |
|
| 183 | - $args['length'] = $length; |
|
| 184 | - $args['start'] = $start; |
|
| 185 | - } |
|
| 186 | - |
|
| 187 | - // This becomes a JSON list, not a JSON array, so we need numeric keys. |
|
| 188 | - $data = Database::prepare($sql)->execute($args)->fetchAll(PDO::FETCH_NUM); |
|
| 189 | - // Reformat the data for display |
|
| 190 | - foreach ($data as &$datum) { |
|
| 191 | - $site_access_rule_id = $datum[8]; |
|
| 192 | - |
|
| 193 | - $datum[0] = '<div class="btn-group"><button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"><i class="fa fa-pencil"></i> <span class="caret"></span></button><ul class="dropdown-menu" role="menu"><li><a href="?action=edit&site_access_rule_id=' . $site_access_rule_id . '"><i class="fa fa-fw fa-pencil"></i> ' . I18N::translate('Edit') . '</a></li><li class="divider"><li><a href="#" onclick="if (confirm(\'' . I18N::translate('Are you sure you want to delete “%s”?', Filter::escapeJs($datum[5])) . '\')) delete_site_access_rule(' . $site_access_rule_id . '); return false;"><i class="fa fa-fw fa-trash-o"></i> ' . I18N::translate('Delete') . '</a></li></ul></div>'; |
|
| 194 | - $datum[5] = '<span dir="ltr">' . $datum[5] . '</span>'; |
|
| 195 | - $datum[6] = $rules_display[$datum[6]]; |
|
| 196 | - $datum[7] = '<span dir="auto">' . $datum[7] . '</span>'; |
|
| 197 | - } |
|
| 198 | - |
|
| 199 | - // Total filtered/unfiltered rows |
|
| 200 | - $recordsFiltered = Database::prepare("SELECT FOUND_ROWS()")->fetchOne(); |
|
| 201 | - $recordsTotal = Database::prepare("SELECT COUNT(*) FROM `##site_access_rule`")->fetchOne(); |
|
| 202 | - |
|
| 203 | - header('Content-type: application/json'); |
|
| 204 | - // See http://www.datatables.net/usage/server-side |
|
| 205 | - echo json_encode(array( |
|
| 206 | - 'draw' => Filter::getInteger('draw'), |
|
| 207 | - 'recordsTotal' => $recordsTotal, |
|
| 208 | - 'recordsFiltered' => $recordsFiltered, |
|
| 209 | - 'data' => $data, |
|
| 210 | - )); |
|
| 211 | - break; |
|
| 132 | + // AJAX callback for datatables |
|
| 133 | + $search = Filter::get('search'); |
|
| 134 | + $search = $search['value']; |
|
| 135 | + $start = Filter::getInteger('start'); |
|
| 136 | + $length = Filter::getInteger('length'); |
|
| 137 | + |
|
| 138 | + $sql = |
|
| 139 | + "SELECT SQL_CALC_FOUND_ROWS" . |
|
| 140 | + " '', INET_NTOA(ip_address_start), ip_address_start, INET_NTOA(ip_address_end), ip_address_end, user_agent_pattern, rule, comment, site_access_rule_id" . |
|
| 141 | + " FROM `##site_access_rule`"; |
|
| 142 | + $args = array(); |
|
| 143 | + |
|
| 144 | + if ($search) { |
|
| 145 | + $sql .= |
|
| 146 | + " WHERE (INET_ATON(:search_1) BETWEEN ip_address_start AND ip_address_end" . |
|
| 147 | + " OR INET_NTOA(ip_address_start) LIKE CONCAT('%', :search_2, '%')" . |
|
| 148 | + " OR INET_NTOA(ip_address_end) LIKE CONCAT('%', :search_3, '%')" . |
|
| 149 | + " OR user_agent_pattern LIKE CONCAT('%', :search_4, '%')" . |
|
| 150 | + " OR comment LIKE CONCAT('%', :search_5, '%'))"; |
|
| 151 | + $args['search_1'] = Filter::escapeLike($search); |
|
| 152 | + $args['search_2'] = Filter::escapeLike($search); |
|
| 153 | + $args['search_3'] = Filter::escapeLike($search); |
|
| 154 | + $args['search_4'] = Filter::escapeLike($search); |
|
| 155 | + $args['search_5'] = Filter::escapeLike($search); |
|
| 156 | + } |
|
| 157 | + |
|
| 158 | + $order = Filter::getArray('order'); |
|
| 159 | + $sql .= ' ORDER BY'; |
|
| 160 | + if ($order) { |
|
| 161 | + foreach ($order as $key => $value) { |
|
| 162 | + if ($key > 0) { |
|
| 163 | + $sql .= ','; |
|
| 164 | + } |
|
| 165 | + // Datatables numbers columns 0, 1, 2 |
|
| 166 | + // MySQL numbers columns 1, 2, 3 |
|
| 167 | + switch ($value['dir']) { |
|
| 168 | + case 'asc': |
|
| 169 | + $sql .= " :col_" . $key . " ASC"; |
|
| 170 | + break; |
|
| 171 | + case 'desc': |
|
| 172 | + $sql .= " :col_" . $key . " DESC"; |
|
| 173 | + break; |
|
| 174 | + } |
|
| 175 | + $args['col_' . $key] = 1 + $value['column']; |
|
| 176 | + } |
|
| 177 | + } else { |
|
| 178 | + $sql .= ' 1 ASC'; |
|
| 179 | + } |
|
| 180 | + |
|
| 181 | + if ($length > 0) { |
|
| 182 | + $sql .= " LIMIT :length OFFSET :start"; |
|
| 183 | + $args['length'] = $length; |
|
| 184 | + $args['start'] = $start; |
|
| 185 | + } |
|
| 186 | + |
|
| 187 | + // This becomes a JSON list, not a JSON array, so we need numeric keys. |
|
| 188 | + $data = Database::prepare($sql)->execute($args)->fetchAll(PDO::FETCH_NUM); |
|
| 189 | + // Reformat the data for display |
|
| 190 | + foreach ($data as &$datum) { |
|
| 191 | + $site_access_rule_id = $datum[8]; |
|
| 192 | + |
|
| 193 | + $datum[0] = '<div class="btn-group"><button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"><i class="fa fa-pencil"></i> <span class="caret"></span></button><ul class="dropdown-menu" role="menu"><li><a href="?action=edit&site_access_rule_id=' . $site_access_rule_id . '"><i class="fa fa-fw fa-pencil"></i> ' . I18N::translate('Edit') . '</a></li><li class="divider"><li><a href="#" onclick="if (confirm(\'' . I18N::translate('Are you sure you want to delete “%s”?', Filter::escapeJs($datum[5])) . '\')) delete_site_access_rule(' . $site_access_rule_id . '); return false;"><i class="fa fa-fw fa-trash-o"></i> ' . I18N::translate('Delete') . '</a></li></ul></div>'; |
|
| 194 | + $datum[5] = '<span dir="ltr">' . $datum[5] . '</span>'; |
|
| 195 | + $datum[6] = $rules_display[$datum[6]]; |
|
| 196 | + $datum[7] = '<span dir="auto">' . $datum[7] . '</span>'; |
|
| 197 | + } |
|
| 198 | + |
|
| 199 | + // Total filtered/unfiltered rows |
|
| 200 | + $recordsFiltered = Database::prepare("SELECT FOUND_ROWS()")->fetchOne(); |
|
| 201 | + $recordsTotal = Database::prepare("SELECT COUNT(*) FROM `##site_access_rule`")->fetchOne(); |
|
| 202 | + |
|
| 203 | + header('Content-type: application/json'); |
|
| 204 | + // See http://www.datatables.net/usage/server-side |
|
| 205 | + echo json_encode(array( |
|
| 206 | + 'draw' => Filter::getInteger('draw'), |
|
| 207 | + 'recordsTotal' => $recordsTotal, |
|
| 208 | + 'recordsFiltered' => $recordsFiltered, |
|
| 209 | + 'data' => $data, |
|
| 210 | + )); |
|
| 211 | + break; |
|
| 212 | 212 | |
| 213 | 213 | case 'edit': |
| 214 | 214 | case 'create': |
| 215 | - if (Filter::get('action') === 'edit') { |
|
| 216 | - $controller->setPageTitle(I18N::translate('Edit a website access rule')); |
|
| 217 | - } else { |
|
| 218 | - $controller->setPageTitle(I18N::translate('Create a website access rule')); |
|
| 219 | - } |
|
| 220 | - |
|
| 221 | - $controller->pageHeader(); |
|
| 222 | - |
|
| 223 | - $site_access_rule = Database::prepare( |
|
| 224 | - "SELECT site_access_rule_id, INET_NTOA(ip_address_start) AS ip_address_start, INET_NTOA(ip_address_end) AS ip_address_end, user_agent_pattern, rule, comment" . |
|
| 225 | - " FROM `##site_access_rule` WHERE site_access_rule_id = :site_access_rule_id" |
|
| 226 | - )->execute(array( |
|
| 227 | - 'site_access_rule_id' => Filter::getInteger('site_access_rule_id'), |
|
| 228 | - ))->fetchOneRow(); |
|
| 229 | - |
|
| 230 | - $site_access_rule_id = $site_access_rule ? $site_access_rule->site_access_rule_id : null; |
|
| 231 | - $ip_address_start = $site_access_rule ? $site_access_rule->ip_address_start : '0.0.0.0'; |
|
| 232 | - $ip_address_end = $site_access_rule ? $site_access_rule->ip_address_end : '255.255.255.255'; |
|
| 233 | - $user_agent_pattern = $site_access_rule ? $site_access_rule->user_agent_pattern : '%'; |
|
| 234 | - $rule = $site_access_rule ? $site_access_rule->rule : 'allow'; |
|
| 235 | - $comment = $site_access_rule ? $site_access_rule->comment : ''; |
|
| 236 | - |
|
| 237 | - ?> |
|
| 215 | + if (Filter::get('action') === 'edit') { |
|
| 216 | + $controller->setPageTitle(I18N::translate('Edit a website access rule')); |
|
| 217 | + } else { |
|
| 218 | + $controller->setPageTitle(I18N::translate('Create a website access rule')); |
|
| 219 | + } |
|
| 220 | + |
|
| 221 | + $controller->pageHeader(); |
|
| 222 | + |
|
| 223 | + $site_access_rule = Database::prepare( |
|
| 224 | + "SELECT site_access_rule_id, INET_NTOA(ip_address_start) AS ip_address_start, INET_NTOA(ip_address_end) AS ip_address_end, user_agent_pattern, rule, comment" . |
|
| 225 | + " FROM `##site_access_rule` WHERE site_access_rule_id = :site_access_rule_id" |
|
| 226 | + )->execute(array( |
|
| 227 | + 'site_access_rule_id' => Filter::getInteger('site_access_rule_id'), |
|
| 228 | + ))->fetchOneRow(); |
|
| 229 | + |
|
| 230 | + $site_access_rule_id = $site_access_rule ? $site_access_rule->site_access_rule_id : null; |
|
| 231 | + $ip_address_start = $site_access_rule ? $site_access_rule->ip_address_start : '0.0.0.0'; |
|
| 232 | + $ip_address_end = $site_access_rule ? $site_access_rule->ip_address_end : '255.255.255.255'; |
|
| 233 | + $user_agent_pattern = $site_access_rule ? $site_access_rule->user_agent_pattern : '%'; |
|
| 234 | + $rule = $site_access_rule ? $site_access_rule->rule : 'allow'; |
|
| 235 | + $comment = $site_access_rule ? $site_access_rule->comment : ''; |
|
| 236 | + |
|
| 237 | + ?> |
|
| 238 | 238 | <ol class="breadcrumb small"> |
| 239 | 239 | <li><a href="admin.php"><?php echo I18N::translate('Control panel'); ?></a></li> |
| 240 | 240 | <li><a href="admin_site_access.php"><?php echo I18N::translate('Website access rules'); ?></a></li> |
@@ -311,12 +311,12 @@ discard block |
||
| 311 | 311 | </form> |
| 312 | 312 | |
| 313 | 313 | <?php |
| 314 | - break; |
|
| 314 | + break; |
|
| 315 | 315 | |
| 316 | 316 | default: |
| 317 | - $controller |
|
| 318 | - ->pageHeader() |
|
| 319 | - ->addInlineJavascript(' |
|
| 317 | + $controller |
|
| 318 | + ->pageHeader() |
|
| 319 | + ->addInlineJavascript(' |
|
| 320 | 320 | jQuery.fn.dataTableExt.oSort["unicode-asc" ]=function(a,b) {return a.replace(/<[^<]*>/, "").localeCompare(b.replace(/<[^<]*>/, ""))}; |
| 321 | 321 | jQuery.fn.dataTableExt.oSort["unicode-desc"]=function(a,b) {return b.replace(/<[^<]*>/, "").localeCompare(a.replace(/<[^<]*>/, ""))}; |
| 322 | 322 | jQuery(".table-site-access-rules").dataTable({ |
@@ -340,7 +340,7 @@ discard block |
||
| 340 | 340 | }); |
| 341 | 341 | '); |
| 342 | 342 | |
| 343 | - ?> |
|
| 343 | + ?> |
|
| 344 | 344 | <ol class="breadcrumb small"> |
| 345 | 345 | <li><a href="admin.php"><?php echo I18N::translate('Control panel'); ?></a></li> |
| 346 | 346 | <li class="active"><?php echo $controller->getPageTitle(); ?></li> |
@@ -381,5 +381,5 @@ discard block |
||
| 381 | 381 | } |
| 382 | 382 | </script> |
| 383 | 383 | <?php |
| 384 | - break; |
|
| 384 | + break; |
|
| 385 | 385 | } |
@@ -38,75 +38,75 @@ discard block |
||
| 38 | 38 | |
| 39 | 39 | // Form actions |
| 40 | 40 | switch (Filter::post('action')) { |
| 41 | -case 'save': |
|
| 42 | - if (Filter::checkCsrf()) { |
|
| 43 | - $site_access_rule_id = Filter::postInteger('site_access_rule_id'); |
|
| 44 | - $ip_address_start = Filter::post('ip_address_start', WT_REGEX_IPV4); |
|
| 45 | - $ip_address_end = Filter::post('ip_address_end', WT_REGEX_IPV4); |
|
| 46 | - $user_agent_pattern = Filter::post('user_agent_pattern'); |
|
| 47 | - $rule = Filter::post('rule', 'allow|deny|robot'); |
|
| 48 | - $comment = Filter::post('comment'); |
|
| 49 | - $user_agent_string = Filter::server('HTTP_USER_AGENT'); |
|
| 50 | - $ip_address = WT_CLIENT_IP; |
|
| 51 | - |
|
| 52 | - if ($ip_address_start !== null && $ip_address_end !== null && $user_agent_pattern !== null && $rule !== null) { |
|
| 53 | - // This doesn't work with named placeholders. The :user_agent_string parameter is not recognised. |
|
| 54 | - $oops = $rule !== 'allow' && Database::prepare( |
|
| 55 | - "SELECT INET_ATON(:ip_address) BETWEEN INET_ATON(:ip_address_start) AND INET_ATON(:ip_address_end)" . |
|
| 56 | - " AND :user_agent_string LIKE :user_agent_pattern" |
|
| 57 | - )->execute(array( |
|
| 58 | - 'ip_address' => $ip_address, |
|
| 59 | - 'ip_address_start' => $ip_address_start, |
|
| 60 | - 'ip_address_end' => $ip_address_end, |
|
| 61 | - 'user_agent_string' => $user_agent_string, |
|
| 62 | - 'user_agent_pattern' => $user_agent_pattern, |
|
| 63 | - ))->fetchOne(); |
|
| 64 | - |
|
| 65 | - if ($oops) { |
|
| 66 | - FlashMessages::addMessage(I18N::translate('You cannot create a rule which would prevent yourself from accessing the website.'), 'danger'); |
|
| 67 | - } elseif ($site_access_rule_id === null) { |
|
| 68 | - Database::prepare( |
|
| 69 | - "INSERT INTO `##site_access_rule` (ip_address_start, ip_address_end, user_agent_pattern, rule, comment) VALUES (INET_ATON(:ip_address_start), INET_ATON(:ip_address_end), :user_agent_pattern, :rule, :comment)" |
|
| 70 | - )->execute(array( |
|
| 71 | - 'ip_address_start' => $ip_address_start, |
|
| 72 | - 'ip_address_end' => $ip_address_end, |
|
| 73 | - 'user_agent_pattern' => $user_agent_pattern, |
|
| 74 | - 'rule' => $rule, |
|
| 75 | - 'comment' => $comment, |
|
| 76 | - )); |
|
| 77 | - FlashMessages::addMessage(I18N::translate('The website access rule has been created.'), 'success'); |
|
| 78 | - } else { |
|
| 79 | - Database::prepare( |
|
| 80 | - "UPDATE `##site_access_rule` SET ip_address_start = INET_ATON(:ip_address_start), ip_address_end = INET_ATON(:ip_address_end), user_agent_pattern = :user_agent_pattern, rule = :rule, comment = :comment WHERE site_access_rule_id = :site_access_rule_id" |
|
| 81 | - )->execute(array( |
|
| 82 | - 'ip_address_start' => $ip_address_start, |
|
| 83 | - 'ip_address_end' => $ip_address_end, |
|
| 84 | - 'user_agent_pattern' => $user_agent_pattern, |
|
| 85 | - 'rule' => $rule, |
|
| 86 | - 'comment' => $comment, |
|
| 87 | - 'site_access_rule_id' => $site_access_rule_id, |
|
| 88 | - )); |
|
| 89 | - FlashMessages::addMessage(I18N::translate('The website access rule has been updated.'), 'success'); |
|
| 90 | - } |
|
| 91 | - } |
|
| 92 | - } |
|
| 93 | - header('Location: ' . WT_BASE_URL . WT_SCRIPT_NAME); |
|
| 94 | - |
|
| 95 | - return; |
|
| 96 | - |
|
| 97 | -case 'delete': |
|
| 98 | - if (Filter::checkCsrf()) { |
|
| 99 | - $site_access_rule_id = Filter::postInteger('site_access_rule_id'); |
|
| 100 | - Database::prepare( |
|
| 101 | - "DELETE FROM `##site_access_rule` WHERE site_access_rule_id = :site_access_rule_id" |
|
| 102 | - )->execute(array( |
|
| 103 | - 'site_access_rule_id' => $site_access_rule_id, |
|
| 104 | - )); |
|
| 105 | - FlashMessages::addMessage(I18N::translate('The website access rule has been deleted.'), 'success'); |
|
| 106 | - } |
|
| 107 | - header('Location: ' . WT_BASE_URL . WT_SCRIPT_NAME); |
|
| 108 | - |
|
| 109 | - return; |
|
| 41 | + case 'save': |
|
| 42 | + if (Filter::checkCsrf()) { |
|
| 43 | + $site_access_rule_id = Filter::postInteger('site_access_rule_id'); |
|
| 44 | + $ip_address_start = Filter::post('ip_address_start', WT_REGEX_IPV4); |
|
| 45 | + $ip_address_end = Filter::post('ip_address_end', WT_REGEX_IPV4); |
|
| 46 | + $user_agent_pattern = Filter::post('user_agent_pattern'); |
|
| 47 | + $rule = Filter::post('rule', 'allow|deny|robot'); |
|
| 48 | + $comment = Filter::post('comment'); |
|
| 49 | + $user_agent_string = Filter::server('HTTP_USER_AGENT'); |
|
| 50 | + $ip_address = WT_CLIENT_IP; |
|
| 51 | + |
|
| 52 | + if ($ip_address_start !== null && $ip_address_end !== null && $user_agent_pattern !== null && $rule !== null) { |
|
| 53 | + // This doesn't work with named placeholders. The :user_agent_string parameter is not recognised. |
|
| 54 | + $oops = $rule !== 'allow' && Database::prepare( |
|
| 55 | + "SELECT INET_ATON(:ip_address) BETWEEN INET_ATON(:ip_address_start) AND INET_ATON(:ip_address_end)" . |
|
| 56 | + " AND :user_agent_string LIKE :user_agent_pattern" |
|
| 57 | + )->execute(array( |
|
| 58 | + 'ip_address' => $ip_address, |
|
| 59 | + 'ip_address_start' => $ip_address_start, |
|
| 60 | + 'ip_address_end' => $ip_address_end, |
|
| 61 | + 'user_agent_string' => $user_agent_string, |
|
| 62 | + 'user_agent_pattern' => $user_agent_pattern, |
|
| 63 | + ))->fetchOne(); |
|
| 64 | + |
|
| 65 | + if ($oops) { |
|
| 66 | + FlashMessages::addMessage(I18N::translate('You cannot create a rule which would prevent yourself from accessing the website.'), 'danger'); |
|
| 67 | + } elseif ($site_access_rule_id === null) { |
|
| 68 | + Database::prepare( |
|
| 69 | + "INSERT INTO `##site_access_rule` (ip_address_start, ip_address_end, user_agent_pattern, rule, comment) VALUES (INET_ATON(:ip_address_start), INET_ATON(:ip_address_end), :user_agent_pattern, :rule, :comment)" |
|
| 70 | + )->execute(array( |
|
| 71 | + 'ip_address_start' => $ip_address_start, |
|
| 72 | + 'ip_address_end' => $ip_address_end, |
|
| 73 | + 'user_agent_pattern' => $user_agent_pattern, |
|
| 74 | + 'rule' => $rule, |
|
| 75 | + 'comment' => $comment, |
|
| 76 | + )); |
|
| 77 | + FlashMessages::addMessage(I18N::translate('The website access rule has been created.'), 'success'); |
|
| 78 | + } else { |
|
| 79 | + Database::prepare( |
|
| 80 | + "UPDATE `##site_access_rule` SET ip_address_start = INET_ATON(:ip_address_start), ip_address_end = INET_ATON(:ip_address_end), user_agent_pattern = :user_agent_pattern, rule = :rule, comment = :comment WHERE site_access_rule_id = :site_access_rule_id" |
|
| 81 | + )->execute(array( |
|
| 82 | + 'ip_address_start' => $ip_address_start, |
|
| 83 | + 'ip_address_end' => $ip_address_end, |
|
| 84 | + 'user_agent_pattern' => $user_agent_pattern, |
|
| 85 | + 'rule' => $rule, |
|
| 86 | + 'comment' => $comment, |
|
| 87 | + 'site_access_rule_id' => $site_access_rule_id, |
|
| 88 | + )); |
|
| 89 | + FlashMessages::addMessage(I18N::translate('The website access rule has been updated.'), 'success'); |
|
| 90 | + } |
|
| 91 | + } |
|
| 92 | + } |
|
| 93 | + header('Location: ' . WT_BASE_URL . WT_SCRIPT_NAME); |
|
| 94 | + |
|
| 95 | + return; |
|
| 96 | + |
|
| 97 | + case 'delete': |
|
| 98 | + if (Filter::checkCsrf()) { |
|
| 99 | + $site_access_rule_id = Filter::postInteger('site_access_rule_id'); |
|
| 100 | + Database::prepare( |
|
| 101 | + "DELETE FROM `##site_access_rule` WHERE site_access_rule_id = :site_access_rule_id" |
|
| 102 | + )->execute(array( |
|
| 103 | + 'site_access_rule_id' => $site_access_rule_id, |
|
| 104 | + )); |
|
| 105 | + FlashMessages::addMessage(I18N::translate('The website access rule has been deleted.'), 'success'); |
|
| 106 | + } |
|
| 107 | + header('Location: ' . WT_BASE_URL . WT_SCRIPT_NAME); |
|
| 108 | + |
|
| 109 | + return; |
|
| 110 | 110 | } |
| 111 | 111 | |
| 112 | 112 | // Delete any "unknown" visitors that are now "known". |
@@ -128,50 +128,50 @@ discard block |
||
| 128 | 128 | |
| 129 | 129 | $action = Filter::get('action'); |
| 130 | 130 | switch ($action) { |
| 131 | -case 'load': |
|
| 132 | - // AJAX callback for datatables |
|
| 133 | - $search = Filter::get('search'); |
|
| 134 | - $search = $search['value']; |
|
| 135 | - $start = Filter::getInteger('start'); |
|
| 136 | - $length = Filter::getInteger('length'); |
|
| 137 | - |
|
| 138 | - $sql = |
|
| 139 | - "SELECT SQL_CALC_FOUND_ROWS" . |
|
| 140 | - " '', INET_NTOA(ip_address_start), ip_address_start, INET_NTOA(ip_address_end), ip_address_end, user_agent_pattern, rule, comment, site_access_rule_id" . |
|
| 141 | - " FROM `##site_access_rule`"; |
|
| 142 | - $args = array(); |
|
| 143 | - |
|
| 144 | - if ($search) { |
|
| 145 | - $sql .= |
|
| 146 | - " WHERE (INET_ATON(:search_1) BETWEEN ip_address_start AND ip_address_end" . |
|
| 147 | - " OR INET_NTOA(ip_address_start) LIKE CONCAT('%', :search_2, '%')" . |
|
| 148 | - " OR INET_NTOA(ip_address_end) LIKE CONCAT('%', :search_3, '%')" . |
|
| 149 | - " OR user_agent_pattern LIKE CONCAT('%', :search_4, '%')" . |
|
| 150 | - " OR comment LIKE CONCAT('%', :search_5, '%'))"; |
|
| 151 | - $args['search_1'] = Filter::escapeLike($search); |
|
| 152 | - $args['search_2'] = Filter::escapeLike($search); |
|
| 153 | - $args['search_3'] = Filter::escapeLike($search); |
|
| 154 | - $args['search_4'] = Filter::escapeLike($search); |
|
| 155 | - $args['search_5'] = Filter::escapeLike($search); |
|
| 156 | - } |
|
| 157 | - |
|
| 158 | - $order = Filter::getArray('order'); |
|
| 159 | - $sql .= ' ORDER BY'; |
|
| 160 | - if ($order) { |
|
| 161 | - foreach ($order as $key => $value) { |
|
| 162 | - if ($key > 0) { |
|
| 163 | - $sql .= ','; |
|
| 164 | - } |
|
| 165 | - // Datatables numbers columns 0, 1, 2 |
|
| 166 | - // MySQL numbers columns 1, 2, 3 |
|
| 167 | - switch ($value['dir']) { |
|
| 168 | - case 'asc': |
|
| 169 | - $sql .= " :col_" . $key . " ASC"; |
|
| 170 | - break; |
|
| 171 | - case 'desc': |
|
| 172 | - $sql .= " :col_" . $key . " DESC"; |
|
| 173 | - break; |
|
| 174 | - } |
|
| 131 | + case 'load': |
|
| 132 | + // AJAX callback for datatables |
|
| 133 | + $search = Filter::get('search'); |
|
| 134 | + $search = $search['value']; |
|
| 135 | + $start = Filter::getInteger('start'); |
|
| 136 | + $length = Filter::getInteger('length'); |
|
| 137 | + |
|
| 138 | + $sql = |
|
| 139 | + "SELECT SQL_CALC_FOUND_ROWS" . |
|
| 140 | + " '', INET_NTOA(ip_address_start), ip_address_start, INET_NTOA(ip_address_end), ip_address_end, user_agent_pattern, rule, comment, site_access_rule_id" . |
|
| 141 | + " FROM `##site_access_rule`"; |
|
| 142 | + $args = array(); |
|
| 143 | + |
|
| 144 | + if ($search) { |
|
| 145 | + $sql .= |
|
| 146 | + " WHERE (INET_ATON(:search_1) BETWEEN ip_address_start AND ip_address_end" . |
|
| 147 | + " OR INET_NTOA(ip_address_start) LIKE CONCAT('%', :search_2, '%')" . |
|
| 148 | + " OR INET_NTOA(ip_address_end) LIKE CONCAT('%', :search_3, '%')" . |
|
| 149 | + " OR user_agent_pattern LIKE CONCAT('%', :search_4, '%')" . |
|
| 150 | + " OR comment LIKE CONCAT('%', :search_5, '%'))"; |
|
| 151 | + $args['search_1'] = Filter::escapeLike($search); |
|
| 152 | + $args['search_2'] = Filter::escapeLike($search); |
|
| 153 | + $args['search_3'] = Filter::escapeLike($search); |
|
| 154 | + $args['search_4'] = Filter::escapeLike($search); |
|
| 155 | + $args['search_5'] = Filter::escapeLike($search); |
|
| 156 | + } |
|
| 157 | + |
|
| 158 | + $order = Filter::getArray('order'); |
|
| 159 | + $sql .= ' ORDER BY'; |
|
| 160 | + if ($order) { |
|
| 161 | + foreach ($order as $key => $value) { |
|
| 162 | + if ($key > 0) { |
|
| 163 | + $sql .= ','; |
|
| 164 | + } |
|
| 165 | + // Datatables numbers columns 0, 1, 2 |
|
| 166 | + // MySQL numbers columns 1, 2, 3 |
|
| 167 | + switch ($value['dir']) { |
|
| 168 | + case 'asc': |
|
| 169 | + $sql .= " :col_" . $key . " ASC"; |
|
| 170 | + break; |
|
| 171 | + case 'desc': |
|
| 172 | + $sql .= " :col_" . $key . " DESC"; |
|
| 173 | + break; |
|
| 174 | + } |
|
| 175 | 175 | $args['col_' . $key] = 1 + $value['column']; |
| 176 | 176 | } |
| 177 | 177 | } else { |
@@ -210,31 +210,31 @@ discard block |
||
| 210 | 210 | )); |
| 211 | 211 | break; |
| 212 | 212 | |
| 213 | -case 'edit': |
|
| 214 | -case 'create': |
|
| 215 | - if (Filter::get('action') === 'edit') { |
|
| 216 | - $controller->setPageTitle(I18N::translate('Edit a website access rule')); |
|
| 217 | - } else { |
|
| 218 | - $controller->setPageTitle(I18N::translate('Create a website access rule')); |
|
| 219 | - } |
|
| 220 | - |
|
| 221 | - $controller->pageHeader(); |
|
| 222 | - |
|
| 223 | - $site_access_rule = Database::prepare( |
|
| 224 | - "SELECT site_access_rule_id, INET_NTOA(ip_address_start) AS ip_address_start, INET_NTOA(ip_address_end) AS ip_address_end, user_agent_pattern, rule, comment" . |
|
| 225 | - " FROM `##site_access_rule` WHERE site_access_rule_id = :site_access_rule_id" |
|
| 226 | - )->execute(array( |
|
| 227 | - 'site_access_rule_id' => Filter::getInteger('site_access_rule_id'), |
|
| 228 | - ))->fetchOneRow(); |
|
| 229 | - |
|
| 230 | - $site_access_rule_id = $site_access_rule ? $site_access_rule->site_access_rule_id : null; |
|
| 231 | - $ip_address_start = $site_access_rule ? $site_access_rule->ip_address_start : '0.0.0.0'; |
|
| 232 | - $ip_address_end = $site_access_rule ? $site_access_rule->ip_address_end : '255.255.255.255'; |
|
| 233 | - $user_agent_pattern = $site_access_rule ? $site_access_rule->user_agent_pattern : '%'; |
|
| 234 | - $rule = $site_access_rule ? $site_access_rule->rule : 'allow'; |
|
| 235 | - $comment = $site_access_rule ? $site_access_rule->comment : ''; |
|
| 236 | - |
|
| 237 | - ?> |
|
| 213 | + case 'edit': |
|
| 214 | + case 'create': |
|
| 215 | + if (Filter::get('action') === 'edit') { |
|
| 216 | + $controller->setPageTitle(I18N::translate('Edit a website access rule')); |
|
| 217 | + } else { |
|
| 218 | + $controller->setPageTitle(I18N::translate('Create a website access rule')); |
|
| 219 | + } |
|
| 220 | + |
|
| 221 | + $controller->pageHeader(); |
|
| 222 | + |
|
| 223 | + $site_access_rule = Database::prepare( |
|
| 224 | + "SELECT site_access_rule_id, INET_NTOA(ip_address_start) AS ip_address_start, INET_NTOA(ip_address_end) AS ip_address_end, user_agent_pattern, rule, comment" . |
|
| 225 | + " FROM `##site_access_rule` WHERE site_access_rule_id = :site_access_rule_id" |
|
| 226 | + )->execute(array( |
|
| 227 | + 'site_access_rule_id' => Filter::getInteger('site_access_rule_id'), |
|
| 228 | + ))->fetchOneRow(); |
|
| 229 | + |
|
| 230 | + $site_access_rule_id = $site_access_rule ? $site_access_rule->site_access_rule_id : null; |
|
| 231 | + $ip_address_start = $site_access_rule ? $site_access_rule->ip_address_start : '0.0.0.0'; |
|
| 232 | + $ip_address_end = $site_access_rule ? $site_access_rule->ip_address_end : '255.255.255.255'; |
|
| 233 | + $user_agent_pattern = $site_access_rule ? $site_access_rule->user_agent_pattern : '%'; |
|
| 234 | + $rule = $site_access_rule ? $site_access_rule->rule : 'allow'; |
|
| 235 | + $comment = $site_access_rule ? $site_access_rule->comment : ''; |
|
| 236 | + |
|
| 237 | + ?> |
|
| 238 | 238 | <ol class="breadcrumb small"> |
| 239 | 239 | <li><a href="admin.php"><?php echo I18N::translate('Control panel'); ?></a></li> |
| 240 | 240 | <li><a href="admin_site_access.php"><?php echo I18N::translate('Website access rules'); ?></a></li> |
@@ -311,12 +311,12 @@ discard block |
||
| 311 | 311 | </form> |
| 312 | 312 | |
| 313 | 313 | <?php |
| 314 | - break; |
|
| 314 | + break; |
|
| 315 | 315 | |
| 316 | -default: |
|
| 317 | - $controller |
|
| 318 | - ->pageHeader() |
|
| 319 | - ->addInlineJavascript(' |
|
| 316 | + default: |
|
| 317 | + $controller |
|
| 318 | + ->pageHeader() |
|
| 319 | + ->addInlineJavascript(' |
|
| 320 | 320 | jQuery.fn.dataTableExt.oSort["unicode-asc" ]=function(a,b) {return a.replace(/<[^<]*>/, "").localeCompare(b.replace(/<[^<]*>/, ""))}; |
| 321 | 321 | jQuery.fn.dataTableExt.oSort["unicode-desc"]=function(a,b) {return b.replace(/<[^<]*>/, "").localeCompare(a.replace(/<[^<]*>/, ""))}; |
| 322 | 322 | jQuery(".table-site-access-rules").dataTable({ |
@@ -340,7 +340,7 @@ discard block |
||
| 340 | 340 | }); |
| 341 | 341 | '); |
| 342 | 342 | |
| 343 | - ?> |
|
| 343 | + ?> |
|
| 344 | 344 | <ol class="breadcrumb small"> |
| 345 | 345 | <li><a href="admin.php"><?php echo I18N::translate('Control panel'); ?></a></li> |
| 346 | 346 | <li class="active"><?php echo $controller->getPageTitle(); ?></li> |
@@ -381,5 +381,5 @@ discard block |
||
| 381 | 381 | } |
| 382 | 382 | </script> |
| 383 | 383 | <?php |
| 384 | - break; |
|
| 384 | + break; |
|
| 385 | 385 | } |
@@ -35,20 +35,20 @@ discard block |
||
| 35 | 35 | * Send a “Not found” error as an image |
| 36 | 36 | */ |
| 37 | 37 | function send404AsImage() { |
| 38 | - $error = I18N::translate('The media file was not found in this family tree.'); |
|
| 38 | + $error = I18N::translate('The media file was not found in this family tree.'); |
|
| 39 | 39 | |
| 40 | - $width = mb_strlen($error) * 6.5 + 50; |
|
| 41 | - $height = 60; |
|
| 42 | - $im = imagecreatetruecolor($width, $height); /* Create a black image */ |
|
| 43 | - $bgc = imagecolorallocate($im, 255, 255, 255); /* set background color */ |
|
| 44 | - imagefilledrectangle($im, 2, 2, $width - 4, $height - 4, $bgc); /* create a rectangle, leaving 2 px border */ |
|
| 40 | + $width = mb_strlen($error) * 6.5 + 50; |
|
| 41 | + $height = 60; |
|
| 42 | + $im = imagecreatetruecolor($width, $height); /* Create a black image */ |
|
| 43 | + $bgc = imagecolorallocate($im, 255, 255, 255); /* set background color */ |
|
| 44 | + imagefilledrectangle($im, 2, 2, $width - 4, $height - 4, $bgc); /* create a rectangle, leaving 2 px border */ |
|
| 45 | 45 | |
| 46 | - embedText($im, $error, 100, '255, 0, 0', WT_ROOT . Config::FONT_DEJAVU_SANS_TTF, 'top', 'left'); |
|
| 46 | + embedText($im, $error, 100, '255, 0, 0', WT_ROOT . Config::FONT_DEJAVU_SANS_TTF, 'top', 'left'); |
|
| 47 | 47 | |
| 48 | - http_response_code(404); |
|
| 49 | - header('Content-Type: image/png'); |
|
| 50 | - imagepng($im); |
|
| 51 | - imagedestroy($im); |
|
| 48 | + http_response_code(404); |
|
| 49 | + header('Content-Type: image/png'); |
|
| 50 | + imagepng($im); |
|
| 51 | + imagedestroy($im); |
|
| 52 | 52 | } |
| 53 | 53 | |
| 54 | 54 | /** |
@@ -62,31 +62,31 @@ discard block |
||
| 62 | 62 | * @return resource |
| 63 | 63 | */ |
| 64 | 64 | function applyWatermark($im, Tree $tree) { |
| 65 | - // text to watermark with |
|
| 66 | - $word1_text = $tree->getTitle(); |
|
| 67 | - // maximum font size for “word1” ; will be automaticaly reduced to fit in the image |
|
| 68 | - $word1_maxsize = 100; |
|
| 69 | - // rgb color codes for text |
|
| 70 | - $word1_color = '0,0,0'; |
|
| 71 | - // ttf font file to use |
|
| 72 | - $word1_font = WT_ROOT . Config::FONT_DEJAVU_SANS_TTF; |
|
| 73 | - // vertical position for the text to past; possible values are: top, middle or bottom, across |
|
| 74 | - $word1_vpos = 'across'; |
|
| 75 | - // horizontal position for the text to past in media file; possible values are: left, right, top2bottom, bottom2top |
|
| 76 | - // this value is used only if $word1_vpos=across |
|
| 77 | - $word1_hpos = 'left'; |
|
| 78 | - |
|
| 79 | - $word2_text = $_SERVER['HTTP_HOST']; |
|
| 80 | - $word2_maxsize = 20; |
|
| 81 | - $word2_color = '0,0,0'; |
|
| 82 | - $word2_font = WT_ROOT . Config::FONT_DEJAVU_SANS_TTF; |
|
| 83 | - $word2_vpos = 'top'; |
|
| 84 | - $word2_hpos = 'top2bottom'; |
|
| 85 | - |
|
| 86 | - embedText($im, $word1_text, $word1_maxsize, $word1_color, $word1_font, $word1_vpos, $word1_hpos); |
|
| 87 | - embedText($im, $word2_text, $word2_maxsize, $word2_color, $word2_font, $word2_vpos, $word2_hpos); |
|
| 88 | - |
|
| 89 | - return $im; |
|
| 65 | + // text to watermark with |
|
| 66 | + $word1_text = $tree->getTitle(); |
|
| 67 | + // maximum font size for “word1” ; will be automaticaly reduced to fit in the image |
|
| 68 | + $word1_maxsize = 100; |
|
| 69 | + // rgb color codes for text |
|
| 70 | + $word1_color = '0,0,0'; |
|
| 71 | + // ttf font file to use |
|
| 72 | + $word1_font = WT_ROOT . Config::FONT_DEJAVU_SANS_TTF; |
|
| 73 | + // vertical position for the text to past; possible values are: top, middle or bottom, across |
|
| 74 | + $word1_vpos = 'across'; |
|
| 75 | + // horizontal position for the text to past in media file; possible values are: left, right, top2bottom, bottom2top |
|
| 76 | + // this value is used only if $word1_vpos=across |
|
| 77 | + $word1_hpos = 'left'; |
|
| 78 | + |
|
| 79 | + $word2_text = $_SERVER['HTTP_HOST']; |
|
| 80 | + $word2_maxsize = 20; |
|
| 81 | + $word2_color = '0,0,0'; |
|
| 82 | + $word2_font = WT_ROOT . Config::FONT_DEJAVU_SANS_TTF; |
|
| 83 | + $word2_vpos = 'top'; |
|
| 84 | + $word2_hpos = 'top2bottom'; |
|
| 85 | + |
|
| 86 | + embedText($im, $word1_text, $word1_maxsize, $word1_color, $word1_font, $word1_vpos, $word1_hpos); |
|
| 87 | + embedText($im, $word2_text, $word2_maxsize, $word2_color, $word2_font, $word2_vpos, $word2_hpos); |
|
| 88 | + |
|
| 89 | + return $im; |
|
| 90 | 90 | } |
| 91 | 91 | |
| 92 | 92 | /** |
@@ -101,96 +101,96 @@ discard block |
||
| 101 | 101 | * @param string $hpos |
| 102 | 102 | */ |
| 103 | 103 | function embedText($im, $text, $maxsize, $color, $font, $vpos, $hpos) { |
| 104 | - global $useTTF; |
|
| 105 | - |
|
| 106 | - // there are two ways to embed text with PHP |
|
| 107 | - // (preferred) using GD and FreeType you can embed text using any True Type font |
|
| 108 | - // (fall back) if that is not available, you can insert basic monospaced text |
|
| 109 | - |
|
| 110 | - $col = explode(',', $color); |
|
| 111 | - $textcolor = imagecolorallocate($im, $col[0], $col[1], $col[2]); |
|
| 112 | - |
|
| 113 | - // make adjustments to settings that imagestring and imagestringup can’t handle |
|
| 114 | - if (!$useTTF) { |
|
| 115 | - // imagestringup only writes up, can’t use top2bottom |
|
| 116 | - if ($hpos === 'top2bottom') { |
|
| 117 | - $hpos = 'bottom2top'; |
|
| 118 | - } |
|
| 119 | - } |
|
| 120 | - |
|
| 121 | - $text = I18N::reverseText($text); |
|
| 122 | - $height = imagesy($im); |
|
| 123 | - $width = imagesx($im); |
|
| 124 | - $calc_angle = rad2deg(atan($height / $width)); |
|
| 125 | - $hypoth = $height / sin(deg2rad($calc_angle)); |
|
| 126 | - |
|
| 127 | - // vertical and horizontal position of the text |
|
| 128 | - switch ($vpos) { |
|
| 129 | - default: |
|
| 130 | - case 'top': |
|
| 131 | - $taille = textlength($maxsize, $width, $text); |
|
| 132 | - $pos_y = $height * 0.15 + $taille; |
|
| 133 | - $pos_x = $width * 0.15; |
|
| 134 | - $rotation = 0; |
|
| 135 | - break; |
|
| 136 | - case 'middle': |
|
| 137 | - $taille = textlength($maxsize, $width, $text); |
|
| 138 | - $pos_y = ($height + $taille) / 2; |
|
| 139 | - $pos_x = $width * 0.15; |
|
| 140 | - $rotation = 0; |
|
| 141 | - break; |
|
| 142 | - case 'bottom': |
|
| 143 | - $taille = textlength($maxsize, $width, $text); |
|
| 144 | - $pos_y = ($height * .85 - $taille); |
|
| 145 | - $pos_x = $width * 0.15; |
|
| 146 | - $rotation = 0; |
|
| 147 | - break; |
|
| 148 | - case 'across': |
|
| 149 | - switch ($hpos) { |
|
| 150 | - default: |
|
| 151 | - case 'left': |
|
| 152 | - $taille = textlength($maxsize, $hypoth, $text); |
|
| 153 | - $pos_y = ($height * .85 - $taille); |
|
| 154 | - $pos_x = $width * 0.15; |
|
| 155 | - $rotation = $calc_angle; |
|
| 156 | - break; |
|
| 157 | - case 'right': |
|
| 158 | - $taille = textlength($maxsize, $hypoth, $text); |
|
| 159 | - $pos_y = ($height * .15 - $taille); |
|
| 160 | - $pos_x = $width * 0.85; |
|
| 161 | - $rotation = $calc_angle + 180; |
|
| 162 | - break; |
|
| 163 | - case 'top2bottom': |
|
| 164 | - $taille = textlength($maxsize, $height, $text); |
|
| 165 | - $pos_y = ($height * .15 - $taille); |
|
| 166 | - $pos_x = ($width * .90 - $taille); |
|
| 167 | - $rotation = -90; |
|
| 168 | - break; |
|
| 169 | - case 'bottom2top': |
|
| 170 | - $taille = textlength($maxsize, $height, $text); |
|
| 171 | - $pos_y = $height * 0.85; |
|
| 172 | - $pos_x = $width * 0.15; |
|
| 173 | - $rotation = 90; |
|
| 174 | - break; |
|
| 175 | - } |
|
| 176 | - break; |
|
| 177 | - } |
|
| 178 | - |
|
| 179 | - // apply the text |
|
| 180 | - if ($useTTF) { |
|
| 181 | - // if imagettftext throws errors, catch them with a custom error handler |
|
| 182 | - set_error_handler('\Fisharebest\Webtrees\\imagettftextErrorHandler'); |
|
| 183 | - imagettftext($im, $taille, $rotation, $pos_x, $pos_y, $textcolor, $font, $text); |
|
| 184 | - restore_error_handler(); |
|
| 185 | - } |
|
| 186 | - // Don’t use an ‘else’ here since imagettftextErrorHandler may have changed the value of $useTTF from true to false |
|
| 187 | - if (!$useTTF) { |
|
| 188 | - if ($rotation !== 90) { |
|
| 189 | - imagestring($im, 5, $pos_x, $pos_y, $text, $textcolor); |
|
| 190 | - } else { |
|
| 191 | - imagestringup($im, 5, $pos_x, $pos_y, $text, $textcolor); |
|
| 192 | - } |
|
| 193 | - } |
|
| 104 | + global $useTTF; |
|
| 105 | + |
|
| 106 | + // there are two ways to embed text with PHP |
|
| 107 | + // (preferred) using GD and FreeType you can embed text using any True Type font |
|
| 108 | + // (fall back) if that is not available, you can insert basic monospaced text |
|
| 109 | + |
|
| 110 | + $col = explode(',', $color); |
|
| 111 | + $textcolor = imagecolorallocate($im, $col[0], $col[1], $col[2]); |
|
| 112 | + |
|
| 113 | + // make adjustments to settings that imagestring and imagestringup can’t handle |
|
| 114 | + if (!$useTTF) { |
|
| 115 | + // imagestringup only writes up, can’t use top2bottom |
|
| 116 | + if ($hpos === 'top2bottom') { |
|
| 117 | + $hpos = 'bottom2top'; |
|
| 118 | + } |
|
| 119 | + } |
|
| 120 | + |
|
| 121 | + $text = I18N::reverseText($text); |
|
| 122 | + $height = imagesy($im); |
|
| 123 | + $width = imagesx($im); |
|
| 124 | + $calc_angle = rad2deg(atan($height / $width)); |
|
| 125 | + $hypoth = $height / sin(deg2rad($calc_angle)); |
|
| 126 | + |
|
| 127 | + // vertical and horizontal position of the text |
|
| 128 | + switch ($vpos) { |
|
| 129 | + default: |
|
| 130 | + case 'top': |
|
| 131 | + $taille = textlength($maxsize, $width, $text); |
|
| 132 | + $pos_y = $height * 0.15 + $taille; |
|
| 133 | + $pos_x = $width * 0.15; |
|
| 134 | + $rotation = 0; |
|
| 135 | + break; |
|
| 136 | + case 'middle': |
|
| 137 | + $taille = textlength($maxsize, $width, $text); |
|
| 138 | + $pos_y = ($height + $taille) / 2; |
|
| 139 | + $pos_x = $width * 0.15; |
|
| 140 | + $rotation = 0; |
|
| 141 | + break; |
|
| 142 | + case 'bottom': |
|
| 143 | + $taille = textlength($maxsize, $width, $text); |
|
| 144 | + $pos_y = ($height * .85 - $taille); |
|
| 145 | + $pos_x = $width * 0.15; |
|
| 146 | + $rotation = 0; |
|
| 147 | + break; |
|
| 148 | + case 'across': |
|
| 149 | + switch ($hpos) { |
|
| 150 | + default: |
|
| 151 | + case 'left': |
|
| 152 | + $taille = textlength($maxsize, $hypoth, $text); |
|
| 153 | + $pos_y = ($height * .85 - $taille); |
|
| 154 | + $pos_x = $width * 0.15; |
|
| 155 | + $rotation = $calc_angle; |
|
| 156 | + break; |
|
| 157 | + case 'right': |
|
| 158 | + $taille = textlength($maxsize, $hypoth, $text); |
|
| 159 | + $pos_y = ($height * .15 - $taille); |
|
| 160 | + $pos_x = $width * 0.85; |
|
| 161 | + $rotation = $calc_angle + 180; |
|
| 162 | + break; |
|
| 163 | + case 'top2bottom': |
|
| 164 | + $taille = textlength($maxsize, $height, $text); |
|
| 165 | + $pos_y = ($height * .15 - $taille); |
|
| 166 | + $pos_x = ($width * .90 - $taille); |
|
| 167 | + $rotation = -90; |
|
| 168 | + break; |
|
| 169 | + case 'bottom2top': |
|
| 170 | + $taille = textlength($maxsize, $height, $text); |
|
| 171 | + $pos_y = $height * 0.85; |
|
| 172 | + $pos_x = $width * 0.15; |
|
| 173 | + $rotation = 90; |
|
| 174 | + break; |
|
| 175 | + } |
|
| 176 | + break; |
|
| 177 | + } |
|
| 178 | + |
|
| 179 | + // apply the text |
|
| 180 | + if ($useTTF) { |
|
| 181 | + // if imagettftext throws errors, catch them with a custom error handler |
|
| 182 | + set_error_handler('\Fisharebest\Webtrees\\imagettftextErrorHandler'); |
|
| 183 | + imagettftext($im, $taille, $rotation, $pos_x, $pos_y, $textcolor, $font, $text); |
|
| 184 | + restore_error_handler(); |
|
| 185 | + } |
|
| 186 | + // Don’t use an ‘else’ here since imagettftextErrorHandler may have changed the value of $useTTF from true to false |
|
| 187 | + if (!$useTTF) { |
|
| 188 | + if ($rotation !== 90) { |
|
| 189 | + imagestring($im, 5, $pos_x, $pos_y, $text, $textcolor); |
|
| 190 | + } else { |
|
| 191 | + imagestringup($im, 5, $pos_x, $pos_y, $text, $textcolor); |
|
| 192 | + } |
|
| 193 | + } |
|
| 194 | 194 | |
| 195 | 195 | } |
| 196 | 196 | |
@@ -204,16 +204,16 @@ discard block |
||
| 204 | 204 | * @return int |
| 205 | 205 | */ |
| 206 | 206 | function textlength($t, $mxl, $text) { |
| 207 | - $taille_c = $t; |
|
| 208 | - $len = mb_strlen($text); |
|
| 209 | - while (($taille_c - 2) * $len > $mxl) { |
|
| 210 | - $taille_c--; |
|
| 211 | - if ($taille_c == 2) { |
|
| 212 | - break; |
|
| 213 | - } |
|
| 214 | - } |
|
| 215 | - |
|
| 216 | - return $taille_c; |
|
| 207 | + $taille_c = $t; |
|
| 208 | + $len = mb_strlen($text); |
|
| 209 | + while (($taille_c - 2) * $len > $mxl) { |
|
| 210 | + $taille_c--; |
|
| 211 | + if ($taille_c == 2) { |
|
| 212 | + break; |
|
| 213 | + } |
|
| 214 | + } |
|
| 215 | + |
|
| 216 | + return $taille_c; |
|
| 217 | 217 | } |
| 218 | 218 | |
| 219 | 219 | /** |
@@ -226,14 +226,14 @@ discard block |
||
| 226 | 226 | * @return bool |
| 227 | 227 | */ |
| 228 | 228 | function imagettftextErrorHandler($errno, $errstr) { |
| 229 | - global $useTTF, $serverFilename; |
|
| 230 | - // log the error |
|
| 231 | - Log::addErrorLog('Media Firewall error: >' . $errno . '/' . $errstr . '< while processing file >' . $serverFilename . '<'); |
|
| 229 | + global $useTTF, $serverFilename; |
|
| 230 | + // log the error |
|
| 231 | + Log::addErrorLog('Media Firewall error: >' . $errno . '/' . $errstr . '< while processing file >' . $serverFilename . '<'); |
|
| 232 | 232 | |
| 233 | - // change value of useTTF to false so the fallback watermarking can be used. |
|
| 234 | - $useTTF = false; |
|
| 233 | + // change value of useTTF to false so the fallback watermarking can be used. |
|
| 234 | + $useTTF = false; |
|
| 235 | 235 | |
| 236 | - return true; |
|
| 236 | + return true; |
|
| 237 | 237 | } |
| 238 | 238 | |
| 239 | 239 | /** |
@@ -244,19 +244,19 @@ discard block |
||
| 244 | 244 | * @return string|false |
| 245 | 245 | */ |
| 246 | 246 | function isImageTypeSupported($reqtype) { |
| 247 | - $supportByGD = array('jpg' => 'jpeg', 'jpeg' => 'jpeg', 'gif' => 'gif', 'png' => 'png'); |
|
| 248 | - $reqtype = strtolower($reqtype); |
|
| 247 | + $supportByGD = array('jpg' => 'jpeg', 'jpeg' => 'jpeg', 'gif' => 'gif', 'png' => 'png'); |
|
| 248 | + $reqtype = strtolower($reqtype); |
|
| 249 | 249 | |
| 250 | - if (empty($supportByGD[$reqtype])) { |
|
| 251 | - return false; |
|
| 252 | - } |
|
| 253 | - $type = $supportByGD[$reqtype]; |
|
| 250 | + if (empty($supportByGD[$reqtype])) { |
|
| 251 | + return false; |
|
| 252 | + } |
|
| 253 | + $type = $supportByGD[$reqtype]; |
|
| 254 | 254 | |
| 255 | - if (function_exists('imagecreatefrom' . $type) && function_exists('image' . $type)) { |
|
| 256 | - return $type; |
|
| 257 | - } |
|
| 255 | + if (function_exists('imagecreatefrom' . $type) && function_exists('image' . $type)) { |
|
| 256 | + return $type; |
|
| 257 | + } |
|
| 258 | 258 | |
| 259 | - return false; |
|
| 259 | + return false; |
|
| 260 | 260 | } |
| 261 | 261 | |
| 262 | 262 | // this needs to be a global variable so imagettftextErrorHandler can set it |
@@ -264,24 +264,24 @@ discard block |
||
| 264 | 264 | |
| 265 | 265 | // Media object missing/private? |
| 266 | 266 | if (!$media || !$media->canShow()) { |
| 267 | - send404AsImage(); |
|
| 267 | + send404AsImage(); |
|
| 268 | 268 | |
| 269 | - return; |
|
| 269 | + return; |
|
| 270 | 270 | } |
| 271 | 271 | // media file somewhere else? |
| 272 | 272 | if ($media->isExternal()) { |
| 273 | - header('Location: ' . $media->getFilename()); |
|
| 273 | + header('Location: ' . $media->getFilename()); |
|
| 274 | 274 | |
| 275 | - return; |
|
| 275 | + return; |
|
| 276 | 276 | } |
| 277 | 277 | |
| 278 | 278 | $which = $thumb ? 'thumb' : 'main'; |
| 279 | 279 | $serverFilename = $media->getServerFilename($which); |
| 280 | 280 | |
| 281 | 281 | if (!file_exists($serverFilename)) { |
| 282 | - send404AsImage(); |
|
| 282 | + send404AsImage(); |
|
| 283 | 283 | |
| 284 | - return; |
|
| 284 | + return; |
|
| 285 | 285 | } |
| 286 | 286 | |
| 287 | 287 | $mimetype = $media->mimeType(); |
@@ -290,7 +290,7 @@ discard block |
||
| 290 | 290 | $filetimeHeader = gmdate('D, d M Y H:i:s', $filetime) . ' GMT'; |
| 291 | 291 | $expireOffset = 3600 * 24; // tell browser to cache this image for 24 hours |
| 292 | 292 | if (Filter::get('cb')) { |
| 293 | - $expireOffset = $expireOffset * 7; |
|
| 293 | + $expireOffset = $expireOffset * 7; |
|
| 294 | 294 | } // if cb parameter was sent, cache for 7 days |
| 295 | 295 | $expireHeader = gmdate('D, d M Y H:i:s', WT_TIMESTAMP + $expireOffset) . ' GMT'; |
| 296 | 296 | |
@@ -298,46 +298,46 @@ discard block |
||
| 298 | 298 | $usewatermark = false; |
| 299 | 299 | // if this image supports watermarks and the watermark module is intalled... |
| 300 | 300 | if ($type) { |
| 301 | - // if this is not a thumbnail, or WATERMARK_THUMB is true |
|
| 302 | - if (($which === 'main') || $WT_TREE->getPreference('WATERMARK_THUMB')) { |
|
| 303 | - // if the user’s priv’s justify it... |
|
| 304 | - if (Auth::accessLevel($WT_TREE) > $WT_TREE->getPreference('SHOW_NO_WATERMARK')) { |
|
| 305 | - // add a watermark |
|
| 306 | - $usewatermark = true; |
|
| 307 | - } |
|
| 308 | - } |
|
| 301 | + // if this is not a thumbnail, or WATERMARK_THUMB is true |
|
| 302 | + if (($which === 'main') || $WT_TREE->getPreference('WATERMARK_THUMB')) { |
|
| 303 | + // if the user’s priv’s justify it... |
|
| 304 | + if (Auth::accessLevel($WT_TREE) > $WT_TREE->getPreference('SHOW_NO_WATERMARK')) { |
|
| 305 | + // add a watermark |
|
| 306 | + $usewatermark = true; |
|
| 307 | + } |
|
| 308 | + } |
|
| 309 | 309 | } |
| 310 | 310 | |
| 311 | 311 | // determine whether we have enough memory to watermark this image |
| 312 | 312 | if ($usewatermark) { |
| 313 | - if (!FunctionsMedia::hasMemoryForImage($serverFilename)) { |
|
| 314 | - // not enough memory to watermark this file |
|
| 315 | - $usewatermark = false; |
|
| 316 | - } |
|
| 313 | + if (!FunctionsMedia::hasMemoryForImage($serverFilename)) { |
|
| 314 | + // not enough memory to watermark this file |
|
| 315 | + $usewatermark = false; |
|
| 316 | + } |
|
| 317 | 317 | } |
| 318 | 318 | |
| 319 | 319 | $watermarkfile = ''; |
| 320 | 320 | $generatewatermark = false; |
| 321 | 321 | |
| 322 | 322 | if ($usewatermark) { |
| 323 | - if ($which === 'thumb') { |
|
| 324 | - $watermarkfile = WT_DATA_DIR . $WT_TREE->getPreference('MEDIA_DIRECTORY') . 'watermark/' . $WT_TREE->getName() . '/thumb/' . $media->getFilename(); |
|
| 325 | - } else { |
|
| 326 | - $watermarkfile = WT_DATA_DIR . $WT_TREE->getPreference('MEDIA_DIRECTORY') . 'watermark/' . $WT_TREE->getName() . '/' . $media->getFilename(); |
|
| 327 | - } |
|
| 328 | - |
|
| 329 | - if (!file_exists($watermarkfile)) { |
|
| 330 | - // no saved watermark file exists |
|
| 331 | - // generate the watermark file |
|
| 332 | - $generatewatermark = true; |
|
| 333 | - } else { |
|
| 334 | - $watermarktime = filemtime($watermarkfile); |
|
| 335 | - if ($filetime > $watermarktime) { |
|
| 336 | - // if the original image was updated after the saved file was created |
|
| 337 | - // generate the watermark file |
|
| 338 | - $generatewatermark = true; |
|
| 339 | - } |
|
| 340 | - } |
|
| 323 | + if ($which === 'thumb') { |
|
| 324 | + $watermarkfile = WT_DATA_DIR . $WT_TREE->getPreference('MEDIA_DIRECTORY') . 'watermark/' . $WT_TREE->getName() . '/thumb/' . $media->getFilename(); |
|
| 325 | + } else { |
|
| 326 | + $watermarkfile = WT_DATA_DIR . $WT_TREE->getPreference('MEDIA_DIRECTORY') . 'watermark/' . $WT_TREE->getName() . '/' . $media->getFilename(); |
|
| 327 | + } |
|
| 328 | + |
|
| 329 | + if (!file_exists($watermarkfile)) { |
|
| 330 | + // no saved watermark file exists |
|
| 331 | + // generate the watermark file |
|
| 332 | + $generatewatermark = true; |
|
| 333 | + } else { |
|
| 334 | + $watermarktime = filemtime($watermarkfile); |
|
| 335 | + if ($filetime > $watermarktime) { |
|
| 336 | + // if the original image was updated after the saved file was created |
|
| 337 | + // generate the watermark file |
|
| 338 | + $generatewatermark = true; |
|
| 339 | + } |
|
| 340 | + } |
|
| 341 | 341 | } |
| 342 | 342 | |
| 343 | 343 | $etag = $media->getEtag($which); |
@@ -345,13 +345,13 @@ discard block |
||
| 345 | 345 | // parse IF_MODIFIED_SINCE header from client |
| 346 | 346 | $if_modified_since = 'x'; |
| 347 | 347 | if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) { |
| 348 | - $if_modified_since = preg_replace('/;.*$/', '', $_SERVER['HTTP_IF_MODIFIED_SINCE']); |
|
| 348 | + $if_modified_since = preg_replace('/;.*$/', '', $_SERVER['HTTP_IF_MODIFIED_SINCE']); |
|
| 349 | 349 | } |
| 350 | 350 | |
| 351 | 351 | // parse IF_NONE_MATCH header from client |
| 352 | 352 | $if_none_match = 'x'; |
| 353 | 353 | if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) { |
| 354 | - $if_none_match = str_replace('"', '', $_SERVER['HTTP_IF_NONE_MATCH']); |
|
| 354 | + $if_none_match = str_replace('"', '', $_SERVER['HTTP_IF_NONE_MATCH']); |
|
| 355 | 355 | } |
| 356 | 356 | |
| 357 | 357 | // add caching headers. allow browser to cache file, but not proxy |
@@ -363,12 +363,12 @@ discard block |
||
| 363 | 363 | // if this file is already in the user’s cache, don’t resend it |
| 364 | 364 | // first check if the if_modified_since param matches |
| 365 | 365 | if ($if_modified_since === $filetimeHeader) { |
| 366 | - // then check if the etag matches |
|
| 367 | - if ($if_none_match === $etag) { |
|
| 368 | - http_response_code(304); |
|
| 366 | + // then check if the etag matches |
|
| 367 | + if ($if_none_match === $etag) { |
|
| 368 | + http_response_code(304); |
|
| 369 | 369 | |
| 370 | - return; |
|
| 371 | - } |
|
| 370 | + return; |
|
| 371 | + } |
|
| 372 | 372 | } |
| 373 | 373 | |
| 374 | 374 | // send headers for the image |
@@ -376,41 +376,41 @@ discard block |
||
| 376 | 376 | header('Content-Disposition: filename="' . addslashes(basename($media->getFilename())) . '"'); |
| 377 | 377 | |
| 378 | 378 | if ($generatewatermark) { |
| 379 | - // generate the watermarked image |
|
| 380 | - $imCreateFunc = 'imagecreatefrom' . $type; |
|
| 381 | - $imSendFunc = 'image' . $type; |
|
| 382 | - |
|
| 383 | - if (function_exists($imCreateFunc) && function_exists($imSendFunc)) { |
|
| 384 | - $im = $imCreateFunc($serverFilename); |
|
| 385 | - $im = applyWatermark($im, $WT_TREE); |
|
| 386 | - |
|
| 387 | - // save the image, if preferences allow |
|
| 388 | - if ($which === 'thumb' && $WT_TREE->getPreference('SAVE_WATERMARK_THUMB') || $which === 'main' && $WT_TREE->getPreference('SAVE_WATERMARK_IMAGE')) { |
|
| 389 | - // make sure the folder exists |
|
| 390 | - File::mkdir(dirname($watermarkfile)); |
|
| 391 | - // save the image |
|
| 392 | - $imSendFunc($im, $watermarkfile); |
|
| 393 | - } |
|
| 394 | - |
|
| 395 | - // send the image |
|
| 396 | - $imSendFunc($im); |
|
| 397 | - imagedestroy($im); |
|
| 398 | - |
|
| 399 | - return; |
|
| 400 | - } else { |
|
| 401 | - // this image is defective. log it |
|
| 402 | - Log::addMediaLog('Media Firewall error: >' . I18N::translate('This media file is broken and cannot be watermarked.') . '< in file >' . $serverFilename . '< memory used: ' . memory_get_usage()); |
|
| 403 | - |
|
| 404 | - // set usewatermark to false so image will simply be passed through below |
|
| 405 | - $usewatermark = false; |
|
| 406 | - } |
|
| 379 | + // generate the watermarked image |
|
| 380 | + $imCreateFunc = 'imagecreatefrom' . $type; |
|
| 381 | + $imSendFunc = 'image' . $type; |
|
| 382 | + |
|
| 383 | + if (function_exists($imCreateFunc) && function_exists($imSendFunc)) { |
|
| 384 | + $im = $imCreateFunc($serverFilename); |
|
| 385 | + $im = applyWatermark($im, $WT_TREE); |
|
| 386 | + |
|
| 387 | + // save the image, if preferences allow |
|
| 388 | + if ($which === 'thumb' && $WT_TREE->getPreference('SAVE_WATERMARK_THUMB') || $which === 'main' && $WT_TREE->getPreference('SAVE_WATERMARK_IMAGE')) { |
|
| 389 | + // make sure the folder exists |
|
| 390 | + File::mkdir(dirname($watermarkfile)); |
|
| 391 | + // save the image |
|
| 392 | + $imSendFunc($im, $watermarkfile); |
|
| 393 | + } |
|
| 394 | + |
|
| 395 | + // send the image |
|
| 396 | + $imSendFunc($im); |
|
| 397 | + imagedestroy($im); |
|
| 398 | + |
|
| 399 | + return; |
|
| 400 | + } else { |
|
| 401 | + // this image is defective. log it |
|
| 402 | + Log::addMediaLog('Media Firewall error: >' . I18N::translate('This media file is broken and cannot be watermarked.') . '< in file >' . $serverFilename . '< memory used: ' . memory_get_usage()); |
|
| 403 | + |
|
| 404 | + // set usewatermark to false so image will simply be passed through below |
|
| 405 | + $usewatermark = false; |
|
| 406 | + } |
|
| 407 | 407 | } |
| 408 | 408 | |
| 409 | 409 | // pass the image through without manipulating it |
| 410 | 410 | |
| 411 | 411 | if ($usewatermark) { |
| 412 | - // the stored watermarked image is good, lets use it |
|
| 413 | - $serverFilename = $watermarkfile; |
|
| 412 | + // the stored watermarked image is good, lets use it |
|
| 413 | + $serverFilename = $watermarkfile; |
|
| 414 | 414 | } |
| 415 | 415 | |
| 416 | 416 | // determine filesize of image (could be original or watermarked version) |
@@ -421,15 +421,15 @@ discard block |
||
| 421 | 421 | |
| 422 | 422 | // Some servers disable fpassthru() and readfile() |
| 423 | 423 | if (function_exists('readfile')) { |
| 424 | - readfile($serverFilename); |
|
| 424 | + readfile($serverFilename); |
|
| 425 | 425 | } else { |
| 426 | - $fp = fopen($serverFilename, 'rb'); |
|
| 427 | - if (function_exists('fpassthru')) { |
|
| 428 | - fpassthru($fp); |
|
| 429 | - } else { |
|
| 430 | - while (!feof($fp)) { |
|
| 431 | - echo fread($fp, 65536); |
|
| 432 | - } |
|
| 433 | - } |
|
| 434 | - fclose($fp); |
|
| 426 | + $fp = fopen($serverFilename, 'rb'); |
|
| 427 | + if (function_exists('fpassthru')) { |
|
| 428 | + fpassthru($fp); |
|
| 429 | + } else { |
|
| 430 | + while (!feof($fp)) { |
|
| 431 | + echo fread($fp, 65536); |
|
| 432 | + } |
|
| 433 | + } |
|
| 434 | + fclose($fp); |
|
| 435 | 435 | } |
@@ -126,53 +126,53 @@ |
||
| 126 | 126 | |
| 127 | 127 | // vertical and horizontal position of the text |
| 128 | 128 | switch ($vpos) { |
| 129 | - default: |
|
| 130 | - case 'top': |
|
| 131 | - $taille = textlength($maxsize, $width, $text); |
|
| 132 | - $pos_y = $height * 0.15 + $taille; |
|
| 133 | - $pos_x = $width * 0.15; |
|
| 134 | - $rotation = 0; |
|
| 135 | - break; |
|
| 136 | - case 'middle': |
|
| 137 | - $taille = textlength($maxsize, $width, $text); |
|
| 138 | - $pos_y = ($height + $taille) / 2; |
|
| 139 | - $pos_x = $width * 0.15; |
|
| 140 | - $rotation = 0; |
|
| 141 | - break; |
|
| 142 | - case 'bottom': |
|
| 143 | - $taille = textlength($maxsize, $width, $text); |
|
| 144 | - $pos_y = ($height * .85 - $taille); |
|
| 145 | - $pos_x = $width * 0.15; |
|
| 146 | - $rotation = 0; |
|
| 147 | - break; |
|
| 148 | - case 'across': |
|
| 149 | - switch ($hpos) { |
|
| 150 | - default: |
|
| 151 | - case 'left': |
|
| 152 | - $taille = textlength($maxsize, $hypoth, $text); |
|
| 153 | - $pos_y = ($height * .85 - $taille); |
|
| 154 | - $pos_x = $width * 0.15; |
|
| 155 | - $rotation = $calc_angle; |
|
| 156 | - break; |
|
| 157 | - case 'right': |
|
| 158 | - $taille = textlength($maxsize, $hypoth, $text); |
|
| 159 | - $pos_y = ($height * .15 - $taille); |
|
| 160 | - $pos_x = $width * 0.85; |
|
| 161 | - $rotation = $calc_angle + 180; |
|
| 162 | - break; |
|
| 163 | - case 'top2bottom': |
|
| 164 | - $taille = textlength($maxsize, $height, $text); |
|
| 165 | - $pos_y = ($height * .15 - $taille); |
|
| 166 | - $pos_x = ($width * .90 - $taille); |
|
| 167 | - $rotation = -90; |
|
| 168 | - break; |
|
| 169 | - case 'bottom2top': |
|
| 170 | - $taille = textlength($maxsize, $height, $text); |
|
| 171 | - $pos_y = $height * 0.85; |
|
| 172 | - $pos_x = $width * 0.15; |
|
| 173 | - $rotation = 90; |
|
| 174 | - break; |
|
| 175 | - } |
|
| 129 | + default: |
|
| 130 | + case 'top': |
|
| 131 | + $taille = textlength($maxsize, $width, $text); |
|
| 132 | + $pos_y = $height * 0.15 + $taille; |
|
| 133 | + $pos_x = $width * 0.15; |
|
| 134 | + $rotation = 0; |
|
| 135 | + break; |
|
| 136 | + case 'middle': |
|
| 137 | + $taille = textlength($maxsize, $width, $text); |
|
| 138 | + $pos_y = ($height + $taille) / 2; |
|
| 139 | + $pos_x = $width * 0.15; |
|
| 140 | + $rotation = 0; |
|
| 141 | + break; |
|
| 142 | + case 'bottom': |
|
| 143 | + $taille = textlength($maxsize, $width, $text); |
|
| 144 | + $pos_y = ($height * .85 - $taille); |
|
| 145 | + $pos_x = $width * 0.15; |
|
| 146 | + $rotation = 0; |
|
| 147 | + break; |
|
| 148 | + case 'across': |
|
| 149 | + switch ($hpos) { |
|
| 150 | + default: |
|
| 151 | + case 'left': |
|
| 152 | + $taille = textlength($maxsize, $hypoth, $text); |
|
| 153 | + $pos_y = ($height * .85 - $taille); |
|
| 154 | + $pos_x = $width * 0.15; |
|
| 155 | + $rotation = $calc_angle; |
|
| 156 | + break; |
|
| 157 | + case 'right': |
|
| 158 | + $taille = textlength($maxsize, $hypoth, $text); |
|
| 159 | + $pos_y = ($height * .15 - $taille); |
|
| 160 | + $pos_x = $width * 0.85; |
|
| 161 | + $rotation = $calc_angle + 180; |
|
| 162 | + break; |
|
| 163 | + case 'top2bottom': |
|
| 164 | + $taille = textlength($maxsize, $height, $text); |
|
| 165 | + $pos_y = ($height * .15 - $taille); |
|
| 166 | + $pos_x = ($width * .90 - $taille); |
|
| 167 | + $rotation = -90; |
|
| 168 | + break; |
|
| 169 | + case 'bottom2top': |
|
| 170 | + $taille = textlength($maxsize, $height, $text); |
|
| 171 | + $pos_y = $height * 0.85; |
|
| 172 | + $pos_x = $width * 0.15; |
|
| 173 | + $rotation = 90; |
|
| 174 | + break; |
|
| 175 | + } |
|
| 176 | 176 | break; |
| 177 | 177 | } |
| 178 | 178 | |
@@ -34,7 +34,8 @@ discard block |
||
| 34 | 34 | /** |
| 35 | 35 | * Send a “Not found” error as an image |
| 36 | 36 | */ |
| 37 | -function send404AsImage() { |
|
| 37 | +function send404AsImage() |
|
| 38 | +{ |
|
| 38 | 39 | $error = I18N::translate('The media file was not found in this family tree.'); |
| 39 | 40 | |
| 40 | 41 | $width = mb_strlen($error) * 6.5 + 50; |
@@ -61,7 +62,8 @@ discard block |
||
| 61 | 62 | * |
| 62 | 63 | * @return resource |
| 63 | 64 | */ |
| 64 | -function applyWatermark($im, Tree $tree) { |
|
| 65 | +function applyWatermark($im, Tree $tree) |
|
| 66 | +{ |
|
| 65 | 67 | // text to watermark with |
| 66 | 68 | $word1_text = $tree->getTitle(); |
| 67 | 69 | // maximum font size for “word1” ; will be automaticaly reduced to fit in the image |
@@ -100,7 +102,8 @@ discard block |
||
| 100 | 102 | * @param string $vpos |
| 101 | 103 | * @param string $hpos |
| 102 | 104 | */ |
| 103 | -function embedText($im, $text, $maxsize, $color, $font, $vpos, $hpos) { |
|
| 105 | +function embedText($im, $text, $maxsize, $color, $font, $vpos, $hpos) |
|
| 106 | +{ |
|
| 104 | 107 | global $useTTF; |
| 105 | 108 | |
| 106 | 109 | // there are two ways to embed text with PHP |
@@ -203,7 +206,8 @@ discard block |
||
| 203 | 206 | * |
| 204 | 207 | * @return int |
| 205 | 208 | */ |
| 206 | -function textlength($t, $mxl, $text) { |
|
| 209 | +function textlength($t, $mxl, $text) |
|
| 210 | +{ |
|
| 207 | 211 | $taille_c = $t; |
| 208 | 212 | $len = mb_strlen($text); |
| 209 | 213 | while (($taille_c - 2) * $len > $mxl) { |
@@ -225,7 +229,8 @@ discard block |
||
| 225 | 229 | * |
| 226 | 230 | * @return bool |
| 227 | 231 | */ |
| 228 | -function imagettftextErrorHandler($errno, $errstr) { |
|
| 232 | +function imagettftextErrorHandler($errno, $errstr) |
|
| 233 | +{ |
|
| 229 | 234 | global $useTTF, $serverFilename; |
| 230 | 235 | // log the error |
| 231 | 236 | Log::addErrorLog('Media Firewall error: >' . $errno . '/' . $errstr . '< while processing file >' . $serverFilename . '<'); |
@@ -243,7 +248,8 @@ discard block |
||
| 243 | 248 | * |
| 244 | 249 | * @return string|false |
| 245 | 250 | */ |
| 246 | -function isImageTypeSupported($reqtype) { |
|
| 251 | +function isImageTypeSupported($reqtype) |
|
| 252 | +{ |
|
| 247 | 253 | $supportByGD = array('jpg' => 'jpeg', 'jpeg' => 'jpeg', 'gif' => 'gif', 'png' => 'png'); |
| 248 | 254 | $reqtype = strtolower($reqtype); |
| 249 | 255 | |