. */ namespace Fisharebest\Webtrees\Module; use Fisharebest\Webtrees\Auth; use Fisharebest\Webtrees\Controller\PageController; use Fisharebest\Webtrees\Database; use Fisharebest\Webtrees\Family; use Fisharebest\Webtrees\Filter; use Fisharebest\Webtrees\Functions\FunctionsEdit; use Fisharebest\Webtrees\GedcomRecord; use Fisharebest\Webtrees\I18N; use Fisharebest\Webtrees\Individual; use Fisharebest\Webtrees\Media; use Fisharebest\Webtrees\Module\BatchUpdate\BatchUpdateBasePlugin; use Fisharebest\Webtrees\Note; use Fisharebest\Webtrees\Repository; use Fisharebest\Webtrees\Source; use Fisharebest\Webtrees\Tree; /** * Class BatchUpdateModule */ class BatchUpdateModule extends AbstractModule implements ModuleConfigInterface { /** @var string Form parameter: chosen plugin*/ private $plugin; /** @var string Form parameter: record to update */ private $xref; /** @var string Form parameter: how to update record */ private $action; /** @var string Form parameter: additional details for $action */ private $data; /** @var BatchUpdateBasePlugin[] All available plugins */ private $plugins; /** @var BatchUpdateBasePlugin The current plugin */ private $PLUGIN; /** @var string[] n array of all xrefs that might need to be updated */ private $all_xrefs; /** @var string The previous xref to process */ private $prev_xref; /** @var String The current xref being process */ private $curr_xref; /** @var string The next xref to process */ private $next_xref; /** @var GedcomRecord The record corresponding to $curr_xref */ private $record; /** * How should this module be labelled on tabs, menus, etc.? * * @return string */ public function getTitle() { return /* I18N: Name of a module */ I18N::translate('Batch update'); } /** * A sentence describing what this module does. * * @return string */ public function getDescription() { return /* I18N: Description of the “Batch update” module */ I18N::translate('Apply automatic corrections to your genealogy data.'); } /** * This is a general purpose hook, allowing modules to respond to routes * of the form module.php?mod=FOO&mod_action=BAR * * @param string $mod_action */ public function modAction($mod_action) { switch ($mod_action) { case 'admin_batch_update': echo $this->main(); break; default: http_response_code(404); break; } } /** * Main entry point * * @return string */ private function main() { global $WT_TREE; $this->plugins = $this->getPluginList(); // List of available plugins $this->plugin = Filter::get('plugin'); // User parameters $this->xref = Filter::get('xref', WT_REGEX_XREF); $this->action = Filter::get('action'); $this->data = Filter::get('data'); // Don't do any processing until a plugin is chosen. if ($this->plugin && array_key_exists($this->plugin, $this->plugins)) { $this->PLUGIN = new $this->plugin; $this->PLUGIN->getOptions(); $this->getAllXrefs(); switch ($this->action) { case 'update': $record = self::getLatestRecord($this->xref, $this->all_xrefs[$this->xref]); if ($this->PLUGIN->doesRecordNeedUpdate($this->xref, $record)) { $newrecord = $this->PLUGIN->updateRecord($this->xref, $record); if ($newrecord != $record) { if ($newrecord) { GedcomRecord::getInstance($this->xref, $WT_TREE)->updateRecord($newrecord, $this->PLUGIN->chan); } else { GedcomRecord::getInstance($this->xref, $WT_TREE)->deleteRecord(); } } } $this->xref = $this->findNextXref($this->xref); break; case 'update_all': foreach ($this->all_xrefs as $xref => $type) { $record = self::getLatestRecord($xref, $type); if ($this->PLUGIN->doesRecordNeedUpdate($xref, $record)) { $newrecord = $this->PLUGIN->updateRecord($xref, $record); if ($newrecord != $record) { if ($newrecord) { GedcomRecord::getInstance($xref, $WT_TREE)->updateRecord($newrecord, $this->PLUGIN->chan); } else { GedcomRecord::getInstance($xref, $WT_TREE)->deleteRecord(); } } } } $this->xref = ''; break; } // Make sure that our requested record really does need updating. // It may have been updated in another session, or may not have // been specified at all. if (array_key_exists($this->xref, $this->all_xrefs) && $this->PLUGIN->doesRecordNeedUpdate($this->xref, self::getLatestRecord($this->xref, $this->all_xrefs[$this->xref]))) { $this->curr_xref = $this->xref; } // The requested record doesn't need updating - find one that does if (!$this->curr_xref) { $this->curr_xref = $this->findNextXref($this->xref); } if (!$this->curr_xref) { $this->curr_xref = $this->findPrevXref($this->xref); } // If we've found a record to update, get details and look for the next/prev if ($this->curr_xref) { $this->prev_xref = $this->findPrevXref($this->curr_xref); $this->next_xref = $this->findNextXref($this->curr_xref); } } // HTML common to all pages $controller = new PageController; $controller ->setPageTitle(I18N::translate('Batch update')) ->restrictAccess(Auth::isAdmin()) ->pageHeader(); echo $this->getJavascript(); ?>

getPageTitle(); ?>

getName(), 'class="form-control" onchange="reset_reload();"') ?>
PLUGIN): ?>

PLUGIN->getDescription() ?>

getPreference('auto_accept')): ?>
PLUGIN): ?> PLUGIN->getOptionsForm(); ?> action, -4) == '_all'): ?>
curr_xref): ?> record = GedcomRecord::getInstance($this->curr_xref, $WT_TREE); ?>
prev_xref) ?> next_xref) ?>
record->getFullName(); ?> PLUGIN->getActionPreview($this->record); ?>
PLUGIN->getActionButtons($this->curr_xref, $this->record)); ?>
all_xrefs) as $key) { if ($key > $xref) { $record = self::getLatestRecord($key, $this->all_xrefs[$key]); if ($this->PLUGIN->doesRecordNeedUpdate($key, $record)) { return $key; } } } return null; } /** * Find the previous record that needs to be updated. * * @param string $xref * * @return string|null */ private function findPrevXref($xref) { foreach (array_reverse(array_keys($this->all_xrefs)) as $key) { if ($key < $xref) { $record = self::getLatestRecord($key, $this->all_xrefs[$key]); if ($this->PLUGIN->doesRecordNeedUpdate($key, $record)) { return $key; } } } return null; } /** * Generate a list of all XREFs. */ private function getAllXrefs() { global $WT_TREE; $sql = array(); $vars = array(); foreach ($this->PLUGIN->getRecordTypesToUpdate() as $type) { switch ($type) { case 'INDI': $sql[] = "SELECT i_id, 'INDI' FROM `##individuals` WHERE i_file=?"; $vars[] = $WT_TREE->getTreeId(); break; case 'FAM': $sql[] = "SELECT f_id, 'FAM' FROM `##families` WHERE f_file=?"; $vars[] = $WT_TREE->getTreeId(); break; case 'SOUR': $sql[] = "SELECT s_id, 'SOUR' FROM `##sources` WHERE s_file=?"; $vars[] = $WT_TREE->getTreeId(); break; case 'OBJE': $sql[] = "SELECT m_id, 'OBJE' FROM `##media` WHERE m_file=?"; $vars[] = $WT_TREE->getTreeId(); break; default: $sql[] = "SELECT o_id, ? FROM `##other` WHERE o_type=? AND o_file=?"; $vars[] = $type; $vars[] = $type; $vars[] = $WT_TREE->getTreeId(); break; } } $this->all_xrefs = Database::prepare(implode(' UNION ', $sql) . ' ORDER BY 1 ASC') ->execute($vars) ->fetchAssoc(); } /** * Scan the plugin folder for a list of plugins * * @return BatchUpdateBasePlugin[] */ private function getPluginList() { $plugins = array(); $dir_handle = opendir(__DIR__ . '/BatchUpdate'); while (($file = readdir($dir_handle)) !== false) { if (substr($file, -10) == 'Plugin.php' && $file !== 'BatchUpdateBasePlugin.php') { $class = '\Fisharebest\Webtrees\Module\BatchUpdate\\' . basename($file, '.php'); $plugins[$class] = new $class; } } closedir($dir_handle); return $plugins; } /** * Javascript that gets included on every page * * @return string */ private function getJavascript() { return ''; } /** * Create a submit button for our form * * @param string $text * @param string $xref * @param string $action * @param string $data * * @return string */ public static function createSubmitButton($text, $xref, $action = '', $data = '') { return ''; } /** * Get the current view of a record, allowing for pending changes * * @param string $xref * @param string $type * * @return string */ public static function getLatestRecord($xref, $type) { global $WT_TREE; switch ($type) { case 'INDI': return Individual::getInstance($xref, $WT_TREE)->getGedcom(); case 'FAM': return Family::getInstance($xref, $WT_TREE)->getGedcom(); case 'SOUR': return Source::getInstance($xref, $WT_TREE)->getGedcom(); case 'REPO': return Repository::getInstance($xref, $WT_TREE)->getGedcom(); case 'OBJE': return Media::getInstance($xref, $WT_TREE)->getGedcom(); case 'NOTE': return Note::getInstance($xref, $WT_TREE)->getGedcom(); default: return GedcomRecord::getInstance($xref, $WT_TREE)->getGedcom(); } } /** * The URL to a page where the user can modify the configuration of this module. * These links are displayed in the admin page menu. * * @return string */ public function getConfigLink() { return 'module.php?mod=' . $this->getName() . '&mod_action=admin_batch_update'; } }