Exemplo n.º 1
0
 /**
  * Startup activity
  */
 public function __construct()
 {
     global $WT_TREE;
     $xref = Filter::get('mid', WT_REGEX_XREF);
     $this->record = Media::getInstance($xref, $WT_TREE);
     parent::__construct();
 }
Exemplo n.º 2
0
    public function pageBody()
    {
        $tmp_dir = WT_DATA_DIR . 'ftv_pdf_tmp/';
        define('_JPGRAPH_PATH', $tmp_dir);
        define('_MPDF_TEMP_PATH', $tmp_dir);
        define('_MPDF_TTFONTDATAPATH', $tmp_dir);
        require_once WT_MODULES_DIR . $this->getName() . '/mpdf/mpdf.php';
        $stylesheet = file_get_contents($this->directory . '/css/style.css');
        $stylesheet_rtl = file_get_contents($this->directory . '/css/style-rtl.css');
        $html = Filter::post('pdfContent');
        $header = '<header>=== ' . $this->tree()->getTitleHtml() . ' ===</header>';
        $footer = '<footer>' . '<table><tr>' . '<td class="left">' . WT_BASE_URL . '</td>' . '<td class="center">{DATE d-m-Y}</td>' . '<td class="right">{PAGENO}</td>' . '</tr></table>' . '</footer>';
        $mpdf = new mPDF();
        $mpdf->simpleTables = true;
        $mpdf->shrink_tables_to_fit = 1;
        $mpdf->autoScriptToLang = true;
        $mpdf->baseScript = 1;
        $mpdf->autoVietnamese = true;
        $mpdf->autoArabic = true;
        $mpdf->autoLangToFont = true;
        if (I18N::direction() === 'rtl') {
            $mpdf->SetDirectionality('rtl');
            $mpdf->WriteHTML($stylesheet_rtl, 1);
        } else {
            $mpdf->WriteHTML($stylesheet, 1);
        }
        $mpdf->setAutoTopMargin = 'stretch';
        $mpdf->setAutoBottomMargin = 'stretch';
        $mpdf->autoMarginPadding = 5;
        $admin = User::find($this->tree()->getPreference('WEBMASTER_USER_ID'))->getRealName();
        $mpdf->setCreator($this->getTitle() . ' - a webtrees module by justcarmen.nl');
        $mpdf->SetTitle(Filter::get('title'));
        $mpdf->setAuthor($admin);
        $mpdf->SetHTMLHeader($header);
        $mpdf->setHTMLFooter($footer);
        $html_chunks = explode("\n", $html);
        $chunks = count($html_chunks);
        $i = 1;
        foreach ($html_chunks as $html_chunk) {
            // write html body parts only (option 2);
            if ($i === 1) {
                // first chunk (initialize all buffers - init=true)
                $mpdf->WriteHTML($html_chunk, 2, true, false);
            } elseif ($i === $chunks) {
                // last chunck (close all buffers - close=true)
                $mpdf->WriteHTML($html_chunk, 2, false, true);
            } else {
                // all other parts (keep the buffer open)
                $mpdf->WriteHTML($html_chunk, 2, false, false);
            }
            $i++;
        }
        $index = '
				<pagebreak type="next-odd" />
				<h2>' . I18N::translate('Index') . '</h2>
				<columns column-count="2" column-gap="5" />
				<indexinsert usedivletters="on" links="on" collation="' . WT_LOCALE . '.utf8" collationgroup="' . I18N::collation() . '" />';
        $mpdf->writeHTML($index);
        $mpdf->Output($tmp_dir . Filter::get('title') . '.pdf', 'F');
    }
Exemplo n.º 3
0
 /**
  * Create the chart controller
  *
  * @param int $show_full needed for use by charts module
  */
 public function __construct($show_full = 1)
 {
     global $WT_TREE;
     parent::__construct();
     $rootid = Filter::get('rootid', WT_REGEX_XREF);
     $this->root = Individual::getInstance($rootid, $WT_TREE);
     if (!$this->root) {
         // Missing root individual? Show the chart for someone.
         $this->root = $this->getSignificantIndividual();
     }
     if (!$this->root || !$this->root->canShowName()) {
         http_response_code(404);
         $this->error_message = I18N::translate('This individual does not exist or you do not have permission to view it.');
     }
     // Extract parameter from form
     if ($show_full) {
         $this->show_full = Filter::getInteger('show_full', 0, 1, $WT_TREE->getPreference('PEDIGREE_FULL_DETAILS'));
     } else {
         $this->show_full = 0;
     }
     $this->box = new \stdClass();
     if ($this->showFull()) {
         $this->box->width = Theme::theme()->parameter('chart-box-x');
         $this->box->height = Theme::theme()->parameter('chart-box-y');
     } else {
         $this->box->width = Theme::theme()->parameter('compact-chart-box-x');
         $this->box->height = Theme::theme()->parameter('compact-chart-box-y');
     }
 }
Exemplo n.º 4
0
    public function pageBody()
    {
        $cache_dir = WT_DATA_DIR . 'ftv_cache/';
        define("_JPGRAPH_PATH", $cache_dir);
        define("_MPDF_TEMP_PATH", $cache_dir);
        define('_MPDF_TTFONTDATAPATH', $cache_dir);
        require_once WT_MODULES_DIR . $this->getName() . '/packages/mpdf60/mpdf.php';
        $tmpfile = $cache_dir . 'fancy-treeview-tmp.txt';
        if (file_exists($cache_dir) && is_readable($tmpfile)) {
            $stylesheet = file_get_contents($this->directory . '/css/pdf/style.css');
            $stylesheet_rtl = file_get_contents($this->directory . '/css/pdf/style-rtl.css');
            $html = file_get_contents($tmpfile);
            $header = '<header>=== ' . $this->tree->getTitleHtml() . ' ===</header>';
            $footer = '<footer>' . '<table><tr>' . '<td class="left">' . WT_BASE_URL . '</td>' . '<td class="center">{DATE d-m-Y}</td>' . '<td class="right">{PAGENO}</td>' . '</tr></table>' . '</footer>';
            $mpdf = new mPDF();
            $mpdf->simpleTables = true;
            $mpdf->shrink_tables_to_fit = 1;
            $mpdf->autoScriptToLang = true;
            if (I18N::direction() === 'rtl') {
                $mpdf->SetDirectionality('rtl');
            }
            if (I18N::direction() === 'rtl') {
                $mpdf->WriteHTML($stylesheet_rtl, 1);
            } else {
                $mpdf->WriteHTML($stylesheet, 1);
            }
            $mpdf->setAutoTopMargin = 'stretch';
            $mpdf->setAutoBottomMargin = 'stretch';
            $mpdf->autoMarginPadding = 5;
            $admin = User::find($this->tree->getPreference('WEBMASTER_USER_ID'))->getRealName();
            $mpdf->setCreator($this->getTitle() . ' - a webtrees module by justcarmen.nl');
            $mpdf->SetTitle(Filter::get('title'));
            $mpdf->setAuthor($admin);
            $mpdf->SetHTMLHeader($header);
            $mpdf->setHTMLFooter($footer);
            $html_chunks = explode("\n", $html);
            $chunks = count($html_chunks);
            $i = 1;
            foreach ($html_chunks as $html_chunk) {
                if ($i === 1) {
                    $mpdf->WriteHTML($html_chunk, 2, true, false);
                } elseif ($i === $chunks) {
                    $mpdf->WriteHTML($html_chunk, 2, false, false);
                } else {
                    $mpdf->WriteHTML($html_chunk, 2, false, true);
                }
                $i++;
            }
            $index = '
				<pagebreak type="next-odd" />
				<h2>' . I18N::translate('Index') . '</h2>
				<columns column-count="2" column-gap="5" />
				<indexinsert usedivletters="on" links="on" collation="' . WT_LOCALE . '.utf8" collationgroup="' . I18N::collation() . '" />';
            $mpdf->writeHTML($index);
            $mpdf->Output(Filter::get('title') . '.pdf', 'D');
        } else {
            echo $this->addMessage('alert', 'danger', false, I18N::translate('Error: the pdf file could not be generated.'));
        }
    }
Exemplo n.º 5
0
 public function __construct()
 {
     parent::__construct('modulename');
     $this->directory = WT_MODULES_DIR . $this->getName();
     $this->action = Filter::get('mod_action');
     // register the namespaces
     $loader = new ClassLoader();
     $loader->addPsr4('vendor\\WebtreesModules\\modulename\\', $this->directory);
     $loader->register();
 }
Exemplo n.º 6
0
 /**
  * Generate the HTML content of this block.
  *
  * @param int      $block_id
  * @param bool     $template
  * @param string[] $cfg
  *
  * @return string
  */
 public function getBlock($block_id, $template = true, $cfg = array())
 {
     global $ctype, $WT_TREE;
     switch (Filter::get('action')) {
         case 'deletenews':
             $news_id = Filter::get('news_id');
             if ($news_id) {
                 Database::prepare("DELETE FROM `##news` WHERE news_id = ?")->execute(array($news_id));
             }
             break;
     }
     $more_news = Filter::getInteger('more_news');
     $limit = 5 * (1 + $more_news);
     $articles = Database::prepare("SELECT SQL_CACHE news_id, user_id, gedcom_id, UNIX_TIMESTAMP(updated) + :offset AS updated, subject, body FROM `##news` WHERE gedcom_id = :tree_id ORDER BY updated DESC LIMIT :limit")->execute(array('offset' => WT_TIMESTAMP_OFFSET, 'tree_id' => $WT_TREE->getTreeId(), 'limit' => $limit))->fetchAll();
     $count = Database::prepare("SELECT SQL_CACHE COUNT(*) FROM `##news` WHERE gedcom_id = :tree_id")->execute(array('tree_id' => $WT_TREE->getTreeId()))->fetchOne();
     $id = $this->getName() . $block_id;
     $class = $this->getName() . '_block';
     $title = $this->getTitle();
     $content = '';
     if (empty($articles)) {
         $content .= I18N::translate('No news articles have been submitted.');
     }
     foreach ($articles as $article) {
         $content .= '<div class="news_box">';
         $content .= '<div class="news_title">' . Filter::escapeHtml($article->subject) . '</div>';
         $content .= '<div class="news_date">' . FunctionsDate::formatTimestamp($article->updated) . '</div>';
         if ($article->body == strip_tags($article->body)) {
             $article->body = nl2br($article->body, false);
         }
         $content .= $article->body;
         if (Auth::isManager($WT_TREE)) {
             $content .= '<hr>';
             $content .= '<a href="#" onclick="window.open(\'editnews.php?news_id=\'+' . $article->news_id . ', \'_blank\', news_window_specs); return false;">' . I18N::translate('Edit') . '</a>';
             $content .= ' | ';
             $content .= '<a href="index.php?action=deletenews&amp;news_id=' . $article->news_id . '&amp;ctype=' . $ctype . '&amp;ged=' . $WT_TREE->getNameHtml() . '" onclick="return confirm(\'' . I18N::translate('Are you sure you want to delete “%s”?', Filter::escapeHtml($article->subject)) . "');\">" . I18N::translate('Delete') . '</a><br>';
         }
         $content .= '</div>';
     }
     if (Auth::isManager($WT_TREE)) {
         $content .= '<a href="#" onclick="window.open(\'editnews.php?gedcom_id=' . $WT_TREE->getTreeId() . '\', \'_blank\', news_window_specs); return false;">' . I18N::translate('Add a news article') . '</a>';
     }
     if ($count > $limit) {
         if (Auth::isManager($WT_TREE)) {
             $content .= ' | ';
         }
         $content .= '<a href="#" onclick="jQuery(\'#' . $id . '\').load(\'index.php?ctype=gedcom&amp;ged=' . $WT_TREE->getNameUrl() . '&amp;block_id=' . $block_id . '&amp;action=ajax&amp;more_news=' . ($more_news + 1) . '\'); return false;">' . I18N::translate('More news articles') . "</a>";
     }
     if ($template) {
         return Theme::theme()->formatBlock($id, $title, $class, $content);
     } else {
         return $content;
     }
 }
Exemplo n.º 7
0
 /**
  * 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':
             $this->admin();
             break;
         case 'generate':
             $this->generate(Filter::get('file'));
             break;
         default:
             http_response_code(404);
     }
 }
Exemplo n.º 8
0
 /**
  * Generate the HTML content of this block.
  *
  * @param int      $block_id
  * @param bool     $template
  * @param string[] $cfg
  *
  * @return string
  */
 public function getBlock($block_id, $template = true, $cfg = array())
 {
     global $ctype, $WT_TREE;
     switch (Filter::get('action')) {
         case 'deletenews':
             $news_id = Filter::getInteger('news_id');
             if ($news_id) {
                 Database::prepare("DELETE FROM `##news` WHERE news_id = ?")->execute(array($news_id));
             }
             break;
     }
     $block = $this->getBlockSetting($block_id, 'block', '1');
     foreach (array('block') as $name) {
         if (array_key_exists($name, $cfg)) {
             ${$name} = $cfg[$name];
         }
     }
     $usernews = Database::prepare("SELECT SQL_CACHE news_id, user_id, gedcom_id, UNIX_TIMESTAMP(updated) AS updated, subject, body FROM `##news` WHERE user_id = ? ORDER BY updated DESC")->execute(array(Auth::id()))->fetchAll();
     $id = $this->getName() . $block_id;
     $class = $this->getName() . '_block';
     $title = '';
     $title .= $this->getTitle();
     $content = '';
     if (!$usernews) {
         $content .= I18N::translate('You have not created any journal items.');
     }
     foreach ($usernews as $news) {
         $content .= '<div class="journal_box">';
         $content .= '<div class="news_title">' . $news->subject . '</div>';
         $content .= '<div class="news_date">' . FunctionsDate::formatTimestamp($news->updated) . '</div>';
         if ($news->body == strip_tags($news->body)) {
             // No HTML?
             $news->body = nl2br($news->body, false);
         }
         $content .= $news->body . '<br><br>';
         $content .= '<a href="#" onclick="window.open(\'editnews.php?news_id=\'+' . $news->news_id . ', \'_blank\', indx_window_specs); return false;">' . I18N::translate('Edit') . '</a> | ';
         $content .= '<a href="index.php?action=deletenews&amp;news_id=' . $news->news_id . '&amp;ctype=' . $ctype . '&amp;ged=' . $WT_TREE->getNameHtml() . '" onclick="return confirm(\'' . I18N::translate('Are you sure you want to delete “%s”?', Filter::escapeHtml($news->subject)) . "');\">" . I18N::translate('Delete') . '</a><br>';
         $content .= "</div><br>";
     }
     $content .= '<br><a href="#" onclick="window.open(\'editnews.php?user_id=' . Auth::id() . '\', \'_blank\', indx_window_specs); return false;">' . I18N::translate('Add a new journal entry') . '</a>';
     if ($template) {
         if ($block) {
             $class .= ' small_inner_block';
         }
         return Theme::theme()->formatBlock($id, $title, $class, $content);
     } else {
         return $content;
     }
 }
Exemplo n.º 9
0
 /**
  * Create a branches list controller
  */
 public function __construct()
 {
     global $WT_TREE;
     parent::__construct();
     $this->surname = Filter::get('surname');
     $this->soundex_std = Filter::getBool('soundex_std');
     $this->soundex_dm = Filter::getBool('soundex_dm');
     if ($this->surname) {
         $this->setPageTitle(I18N::translate('Branches of the %s family', Filter::escapeHtml($this->surname)));
         $this->loadIndividuals();
         $self = Individual::getInstance($WT_TREE->getUserPreference(Auth::user(), 'gedcomid'), $WT_TREE);
         if ($self) {
             $this->loadAncestors($self, 1);
         }
     } else {
         $this->setPageTitle(I18N::translate('Branches'));
     }
 }
 /** {@inheritdoc} */
 public function getSidebarAjaxContent()
 {
     global $WT_TREE;
     $alpha = Filter::get('alpha');
     // All surnames beginning with this letter where "@"=unknown and ","=none
     $surname = Filter::get('surname');
     // All indis with this surname.
     $search = Filter::get('search');
     if ($search) {
         return $this->search($WT_TREE, $search);
     } elseif ($alpha == '@' || $alpha == ',' || $surname) {
         return $this->getSurnameIndis($WT_TREE, $alpha, $surname);
     } elseif ($alpha) {
         return $this->getAlphaSurnames($WT_TREE, $alpha);
     } else {
         return '';
     }
 }
Exemplo n.º 11
0
 /**
  * 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)
 {
     global $WT_TREE;
     header('Content-Type: text/html; charset=UTF-8');
     switch ($mod_action) {
         case 'search':
             $search = Filter::get('search');
             echo $this->search($search, $WT_TREE);
             break;
         case 'descendants':
             $individual = Individual::getInstance(Filter::get('xref', WT_REGEX_XREF), $WT_TREE);
             if ($individual) {
                 echo $this->loadSpouses($individual, 1);
             }
             break;
         default:
             http_response_code(404);
             break;
     }
 }
Exemplo n.º 12
0
 /**
  * Generate the HTML content of this block.
  *
  * @param int      $block_id
  * @param bool     $template
  * @param string[] $cfg
  *
  * @return string
  */
 public function getBlock($block_id, $template = true, $cfg = array())
 {
     global $ctype, $WT_TREE;
     switch (Filter::get('action')) {
         case 'deletenews':
             $news_id = Filter::getInteger('news_id');
             if ($news_id) {
                 Database::prepare("DELETE FROM `##news` WHERE news_id = ?")->execute(array($news_id));
             }
             break;
     }
     $articles = Database::prepare("SELECT SQL_CACHE news_id, user_id, gedcom_id, UNIX_TIMESTAMP(updated) + :offset AS updated, subject, body FROM `##news` WHERE user_id = :user_id ORDER BY updated DESC")->execute(array('offset' => WT_TIMESTAMP_OFFSET, 'user_id' => Auth::id()))->fetchAll();
     $id = $this->getName() . $block_id;
     $class = $this->getName() . '_block';
     $title = $this->getTitle();
     $content = '';
     if (empty($articles)) {
         $content .= '<p>' . I18N::translate('You have not created any journal items.') . '</p>';
     }
     foreach ($articles as $article) {
         $content .= '<div class="journal_box">';
         $content .= '<div class="news_title">' . Filter::escapeHtml($article->subject) . '</div>';
         $content .= '<div class="news_date">' . FunctionsDate::formatTimestamp($article->updated) . '</div>';
         if ($article->body == strip_tags($article->body)) {
             $article->body = nl2br($article->body, false);
         }
         $content .= $article->body;
         $content .= '<a href="#" onclick="window.open(\'editnews.php?news_id=\'+' . $article->news_id . ', \'_blank\', indx_window_specs); return false;">' . I18N::translate('Edit') . '</a>';
         $content .= ' | ';
         $content .= '<a href="index.php?action=deletenews&amp;news_id=' . $article->news_id . '&amp;ctype=' . $ctype . '&amp;ged=' . $WT_TREE->getNameHtml() . '" onclick="return confirm(\'' . I18N::translate('Are you sure you want to delete “%s”?', Filter::escapeHtml($article->subject)) . "');\">" . I18N::translate('Delete') . '</a><br>';
         $content .= '</div><br>';
     }
     $content .= '<p><a href="#" onclick="window.open(\'editnews.php?user_id=' . Auth::id() . '\', \'_blank\', indx_window_specs); return false;">' . I18N::translate('Add a journal entry') . '</a></p>';
     if ($template) {
         return Theme::theme()->formatBlock($id, $title, $class, $content);
     } else {
         return $content;
     }
 }
Exemplo n.º 13
0
 /**
  * Piwik@index
  */
 public function index()
 {
     $ctrl = new AjaxController();
     $data = new ViewBag();
     $data->set('has_stats', false);
     $block_id = Filter::get('block_id');
     if ($block_id) {
         $cached_item = Cache::get('piwikCountYear', $this->module);
         $visitCountYear = $cached_item->get();
         if (!$cached_item->isHit()) {
             $visitCountYear = $this->getNumberOfVisitsPiwik($block_id);
             Cache::save($cached_item, $visitCountYear);
         }
         if ($visitCountYear) {
             $visitCountToday = max(0, $this->getNumberOfVisitsPiwik($block_id, 'day'));
             $visitCountYear = max(0, $visitCountYear);
             $data->set('has_stats', true);
             $data->set('visits_today', $visitCountToday);
             $data->set('visits_year', $visitCountYear + $visitCountToday);
         }
     }
     ViewFactory::make('PiwikStats', $this, $ctrl, $data)->render();
 }
Exemplo n.º 14
0
use Fisharebest\Webtrees\Date\JalaliDate;
use Fisharebest\Webtrees\Date\JewishDate;
use Fisharebest\Webtrees\Date\JulianDate;
use Fisharebest\Webtrees\Functions\FunctionsDb;
use Fisharebest\Webtrees\Functions\FunctionsPrint;
define('WT_SCRIPT_NAME', 'calendar.php');
require './includes/session.php';
$CALENDAR_FORMAT = $WT_TREE->getPreference('CALENDAR_FORMAT');
$cal = Filter::get('cal', '@#D[A-Z ]+@');
$day = Filter::get('day', '\\d\\d?');
$month = Filter::get('month', '[A-Z]{3,5}');
$year = Filter::get('year', '\\d{1,4}(?: B\\.C\\.)?|\\d\\d\\d\\d\\/\\d\\d|\\d+(-\\d+|[?]+)?');
$view = Filter::get('view', 'day|month|year', 'day');
$filterev = Filter::get('filterev', '[_A-Z-]+', 'BIRT-MARR-DEAT');
$filterof = Filter::get('filterof', 'all|living|recent', 'all');
$filtersx = Filter::get('filtersx', '[MF]', '');
if ($cal . $day . $month . $year === '') {
    // No date specified? Use the most likely calendar
    $cal = I18N::defaultCalendar()->gedcomCalendarEscape();
}
// Create a CalendarDate from the parameters
// We cannot display new-style/old-style years, so convert to new style
if (preg_match('/^(\\d\\d)\\d\\d\\/(\\d\\d)$/', $year, $match)) {
    $year = $match[1] . $match[2];
}
// advanced-year "year range"
if (preg_match('/^(\\d+)-(\\d+)$/', $year, $match)) {
    if (strlen($match[1]) > strlen($match[2])) {
        $match[2] = substr($match[1], 0, strlen($match[1]) - strlen($match[2])) . $match[2];
    }
    $ged_date = new Date("FROM {$cal} {$match[1]} TO {$cal} {$match[2]}");
Exemplo n.º 15
0
 /**
  * Handle AJAX requests - to generate the tab content
  */
 public function ajaxRequest()
 {
     // Search engines should not make AJAX requests
     if (Auth::isSearchEngine()) {
         http_response_code(403);
         exit;
     }
     // Initialise tabs
     $tab = Filter::get('module');
     // A request for a non-existant tab?
     if (array_key_exists($tab, $this->tabs)) {
         $mod = $this->tabs[$tab];
     } else {
         http_response_code(404);
         exit;
     }
     header("Content-Type: text/html; charset=UTF-8");
     // AJAX calls do not have the meta tag headers and need this set
     header("X-Robots-Tag: noindex,follow");
     // AJAX pages should not show up in search results, any links can be followed though
     echo $mod->getTabContent();
     if (WT_DEBUG_SQL) {
         echo Database::getQueryLog();
     }
 }
Exemplo n.º 16
0
 private function moveDown()
 {
     global $WT_TREE;
     if (webtrees\Auth::isManager($WT_TREE)) {
         $block_id = webtrees\Filter::get('block_id');
         $block_order = webtrees\Database::prepare("SELECT block_order FROM `##block` WHERE block_id=?")->execute(array($block_id))->fetchOne();
         $swap_block = webtrees\Database::prepare("SELECT block_order, block_id" . " FROM `##block`" . " WHERE block_order=(" . "  SELECT MIN(block_order) FROM `##block` WHERE block_order>? AND module_name=?" . " ) AND module_name=?" . " LIMIT 1")->execute(array($block_order, $this->getName(), $this->getName()))->fetchOneRow();
         if ($swap_block) {
             webtrees\Database::prepare("UPDATE `##block` SET block_order=? WHERE block_id=?")->execute(array($swap_block->block_order, $block_id));
             webtrees\Database::prepare("UPDATE `##block` SET block_order=? WHERE block_id=?")->execute(array($block_order, $swap_block->block_id));
         }
     } else {
         header('Location: ' . WT_BASE_URL);
         exit;
     }
 }
Exemplo n.º 17
0
 /**
  * Startup activity
  */
 public function __construct()
 {
     global $WT_TREE;
     parent::__construct();
     $this->setPageTitle(I18N::translate('Lifespans'));
     $this->facts = explode('|', WT_EVENTS_BIRT . '|' . WT_EVENTS_DEAT . '|' . WT_EVENTS_MARR . '|' . WT_EVENTS_DIV);
     $tmp = explode('\\', get_class(I18N::defaultCalendar()));
     $cal = strtolower(array_pop($tmp));
     $this->defaultCalendar = str_replace('calendar', '', $cal);
     $filterPids = false;
     // Request parameters
     $clear = Filter::getBool('clear');
     $newpid = Filter::get('newpid', WT_REGEX_XREF);
     $addfam = Filter::getBool('addFamily');
     $this->place = Filter::get('place');
     $this->beginYear = Filter::getInteger('beginYear', 0, PHP_INT_MAX, null);
     $this->endYear = Filter::getInteger('endYear', 0, PHP_INT_MAX, null);
     $this->calendar = Filter::get('calendar', null, $this->defaultCalendar);
     $this->strictDate = Filter::getBool('strictDate');
     // Set up base color parameters
     $this->colors['M'] = new ColorGenerator(240, self::SATURATION, self::LIGHTNESS, self::ALPHA, self::RANGE * -1);
     $this->colors['F'] = new ColorGenerator(00, self::SATURATION, self::LIGHTNESS, self::ALPHA, self::RANGE);
     // Build a list of people based on the input parameters
     if ($clear) {
         // Empty list & reset form
         $xrefs = array();
         $this->place = null;
         $this->beginYear = null;
         $this->endYear = null;
         $this->calendar = $this->defaultCalendar;
     } elseif ($this->place) {
         // Get all individual & family records found for a place
         $this->place_obj = new Place($this->place, $WT_TREE);
         $xrefs = Database::prepare("SELECT DISTINCT `i_id` FROM `##placelinks`" . " JOIN `##individuals` ON `pl_gid`=`i_id` AND `pl_file`=`i_file`" . " WHERE `i_file`=:tree_id" . " AND `pl_p_id`=:place_id" . " UNION" . " SELECT DISTINCT `f_id` FROM `##placelinks`" . " JOIN `##families` ON `pl_gid`=`f_id` AND `pl_file`=`f_file`" . " WHERE `f_file`=:tree_id" . " AND `pl_p_id`=:place_id")->execute(array('tree_id' => $WT_TREE->getTreeId(), 'place_id' => $this->place_obj->getPlaceId()))->fetchOneColumn();
     } else {
         // Modify an existing list of records
         $xrefs = Session::get(self::SESSION_DATA, array());
         if ($newpid) {
             $xrefs = array_merge($xrefs, $this->addFamily(Individual::getInstance($newpid, $WT_TREE), $addfam));
             $xrefs = array_unique($xrefs);
         } elseif (!$xrefs) {
             $xrefs = $this->addFamily($this->getSignificantIndividual(), false);
         }
     }
     $tmp = $this->getCalendarDate(unixtojd());
     $this->currentYear = $tmp->today()->y;
     $tmp = strtoupper(strtr($this->calendar, array('jewish' => 'hebrew', 'french' => 'french r')));
     $this->calendarEscape = sprintf('@#D%s@', $tmp);
     if ($xrefs) {
         // ensure date ranges are valid in preparation for filtering list
         if ($this->beginYear || $this->endYear) {
             $filterPids = true;
             if (!$this->beginYear) {
                 $tmp = new Date($this->calendarEscape . ' 1');
                 $this->beginYear = $tmp->minimumDate()->y;
             }
             if (!$this->endYear) {
                 $this->endYear = $this->currentYear;
             }
             $this->startDate = new Date($this->calendarEscape . $this->beginYear);
             $this->endDate = new Date($this->calendarEscape . $this->endYear);
         }
         // Test each xref to see if the search criteria are met
         foreach ($xrefs as $key => $xref) {
             $valid = false;
             $person = Individual::getInstance($xref, $WT_TREE);
             if ($person) {
                 if ($person->canShow()) {
                     foreach ($person->getFacts() as $fact) {
                         if ($this->checkFact($fact)) {
                             $this->people[] = $person;
                             $valid = true;
                             break;
                         }
                     }
                 }
             } else {
                 $family = Family::getInstance($xref, $WT_TREE);
                 if ($family && $family->canShow() && $this->checkFact($family->getMarriage())) {
                     $valid = true;
                     $this->people[] = $family->getHusband();
                     $this->people[] = $family->getWife();
                 }
             }
             if (!$valid) {
                 unset($xrefs[$key]);
                 // no point in storing a xref if we can't use it
             }
         }
         Session::put(self::SESSION_DATA, $xrefs);
     } else {
         Session::forget(self::SESSION_DATA);
     }
     $this->people = array_filter(array_unique($this->people));
     $count = count($this->people);
     if ($count) {
         // Build the subtitle
         if ($this->place && $filterPids) {
             $this->subtitle = I18N::plural('%s individual with events in %s between %s and %s', '%s individuals with events in %s between %s and %s', $count, I18N::number($count), $this->place, $this->startDate->display(false, '%Y'), $this->endDate->display(false, '%Y'));
         } elseif ($this->place) {
             $this->subtitle = I18N::plural('%s individual with events in %s', '%s individuals with events in %s', $count, I18N::number($count), $this->place);
         } elseif ($filterPids) {
             $this->subtitle = I18N::plural('%s individual with events between %s and %s', '%s individuals with events between %s and %s', $count, I18N::number($count), $this->startDate->display(false, '%Y'), $this->endDate->display(false, '%Y'));
         } else {
             $this->subtitle = I18N::plural('%s individual', '%s individuals', $count, I18N::number($count));
         }
         // Sort the array in order of birth year
         usort($this->people, function (Individual $a, Individual $b) {
             return Date::compare($a->getEstimatedBirthDate(), $b->getEstimatedBirthDate());
         });
         //Find the mimimum birth year and maximum death year from the individuals in the array.
         $bdate = $this->getCalendarDate($this->people[0]->getEstimatedBirthDate()->minimumJulianDay());
         $minyear = $bdate->y;
         $that = $this;
         // PHP5.3 cannot access $this inside a closure
         $maxyear = array_reduce($this->people, function ($carry, Individual $item) use($that) {
             $date = $that->getCalendarDate($item->getEstimatedDeathDate()->maximumJulianDay());
             return max($carry, $date->y);
         }, 0);
     } elseif ($filterPids) {
         $minyear = $this->endYear;
         $maxyear = $this->endYear;
     } else {
         $minyear = $this->currentYear;
         $maxyear = $this->currentYear;
     }
     $maxyear = min($maxyear, $this->currentYear);
     // Limit maximum year to current year as we can't forecast the future
     $minyear = min($minyear, $maxyear - $WT_TREE->getPreference('MAX_ALIVE_AGE'));
     // Set default minimum chart length
     $this->timelineMinYear = (int) floor($minyear / 10) * 10;
     // round down to start of the decade
     $this->timelineMaxYear = (int) ceil($maxyear / 10) * 10;
     // round up to start of next decade
 }
Exemplo n.º 18
0
$block = Database::prepare("SELECT SQL_CACHE * FROM `##block` WHERE block_id=?")->execute(array($block_id))->fetchOneRow();
// Check access. (1) the block must exist and be enabled, (2) gedcom blocks require
// managers, (3) user blocks require the user or an admin
$blocks = Module::getActiveBlocks($WT_TREE);
if (!$block || !array_key_exists($block->module_name, $blocks) || $block->gedcom_id && !Auth::isManager(Tree::findById($block->gedcom_id)) || $block->user_id && $block->user_id != Auth::id() && !Auth::isAdmin()) {
    header('Location: ' . WT_BASE_URL);
    return;
}
$block = $blocks[$block->module_name];
if (Filter::post('save')) {
    $ctype = Filter::post('ctype', 'user', 'gedcom');
    header('Location: ' . WT_BASE_URL . 'index.php?ctype=' . $ctype . '&ged=' . $WT_TREE->getNameUrl());
    $block->configureBlock($block_id);
    return;
}
$ctype = Filter::get('ctype', 'user', 'gedcom');
$controller = new PageController();
$controller->setPageTitle($block->getTitle() . ' — ' . I18N::translate('Preferences'))->pageHeader();
if (Module::getModuleByName('ckeditor')) {
    CkeditorModule::enableEditor($controller);
}
?>
<h2><?php 
echo $controller->getPageTitle();
?>
</h2>

<form name="block" method="post" action="?block_id=<?php 
echo $block_id;
?>
">
Exemplo n.º 19
0
	<input type="hidden" name="type" value="source">
	<input type="hidden" name="callback" value="', $callback, '">
	<input type="hidden" name="subclick">
	<span>', I18N::translate('Source contains'), '</span>
	<input type="text" name="filter" value="';
    if ($filter) {
        echo $filter;
    }
    echo '" autofocus>
	<p><input type="submit" name="search" value="', I18N::translate('Filter'), '" onclick="this.form.subclick.value=this.name">
	<input type="submit" name="all" value="', I18N::translate('Display all'), '" onclick="this.form.subclick.value=this.name">
	</p></form></div>';
}
// Show specialchar and hide the rest
if ($type == 'specialchar') {
    $language_filter = Filter::get('language_filter', null, Auth::user()->getPreference('default_language_filter'));
    $specialchar_languages = SpecialChars::allLanguages();
    if (!array_key_exists($language_filter, $specialchar_languages)) {
        $language_filter = 'en';
    }
    Auth::user()->setPreference('default_language_filter', $language_filter);
    $action = 'filter';
    echo '<div id="find-header">
	<form name="filterspecialchar" method="get" action="find.php">
	<input type="hidden" name="action" value="filter">
	<input type="hidden" name="type" value="specialchar">
	<input type="hidden" name="callback" value="' . $callback . '">
	<p><select id="language_filter" name="language_filter" onchange="submit();">';
    foreach (SpecialChars::allLanguages() as $lanuguage_tag => $language_name) {
        echo '<option value="' . $lanuguage_tag . '" ';
        if ($lanuguage_tag === $language_filter) {
Exemplo n.º 20
0
				columns: [
					/* details           */ { sortable: false },
					/* user-id           */ { visible: false },
					/* user_name         */ null,
					/* real_name         */ null,
					/* email             */ null,
					/* language          */ null,
					/* registered (sort) */ { visible: false },
					/* registered        */ { dataSort: 7 },
					/* last_login (sort) */ { visible: false },
					/* last_login        */ { dataSort: 9 },
					/* verified          */ null,
					/* approved          */ null
				]
			})
			.fnFilter("' . Filter::get('filter') . '"); // View the details of a newly created user
		')->pageHeader();
        ?>
	<ol class="breadcrumb small">
		<li><a href="admin.php"><?php 
        echo I18N::translate('Control panel');
        ?>
</a></li>
		<li class="active"><?php 
        echo $controller->getPageTitle();
        ?>
</li>
	</ol>
	<h1><?php 
        echo $controller->getPageTitle();
        ?>
Exemplo n.º 21
0
    /**
     * 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)
    {
        global $controller, $WT_TREE;
        switch ($mod_action) {
            case 'treeview':
                $controller = new ChartController();
                $tv = new TreeView('tv');
                ob_start();
                $person = $controller->getSignificantIndividual();
                list($html, $js) = $tv->drawViewport($person, 4);
                $controller->setPageTitle(I18N::translate('Interactive tree of %s', $person->getFullName()))->pageHeader()->addExternalJavascript($this->js())->addExternalJavascript(WT_JQUERYUI_TOUCH_PUNCH_URL)->addInlineJavascript($js)->addInlineJavascript('
					if (document.createStyleSheet) {
						document.createStyleSheet("' . $this->css() . '"); // For Internet Explorer
					} else {
						jQuery("head").append(\'<link rel="stylesheet" type="text/css" href="' . $this->css() . '">\');
					}
				');
                echo $html;
                break;
            case 'getDetails':
                header('Content-Type: text/html; charset=UTF-8');
                $pid = Filter::get('pid', WT_REGEX_XREF);
                $i = Filter::get('instance');
                $tv = new TreeView($i);
                $individual = Individual::getInstance($pid, $WT_TREE);
                if ($individual) {
                    echo $tv->getDetails($individual);
                }
                break;
            case 'getPersons':
                header('Content-Type: text/html; charset=UTF-8');
                $q = Filter::get('q');
                $i = Filter::get('instance');
                $tv = new TreeView($i);
                echo $tv->getPersons($q);
                break;
            default:
                http_response_code(404);
                break;
        }
    }
Exemplo n.º 22
0
 /**
  * Startup activity
  */
 public function __construct()
 {
     global $WT_TREE;
     parent::__construct();
     $this->setPageTitle(I18N::translate('Timeline'));
     $this->baseyear = (int) date('Y');
     $pids = Filter::getArray('pids', WT_REGEX_XREF);
     $remove = Filter::get('remove', WT_REGEX_XREF);
     foreach (array_unique($pids) as $pid) {
         if ($pid !== $remove) {
             $person = Individual::getInstance($pid, $WT_TREE);
             if ($person && $person->canShow()) {
                 $this->people[] = $person;
             }
         }
     }
     $this->pidlinks = '';
     foreach ($this->people as $indi) {
         // setup string of valid pids for links
         $this->pidlinks .= 'pids%5B%5D=' . $indi->getXref() . '&amp;';
         $bdate = $indi->getBirthDate();
         if ($bdate->isOK()) {
             $date = new GregorianDate($bdate->minimumJulianDay());
             $this->birthyears[$indi->getXref()] = $date->y;
             $this->birthmonths[$indi->getXref()] = max(1, $date->m);
             $this->birthdays[$indi->getXref()] = max(1, $date->d);
         }
         // find all the fact information
         $facts = $indi->getFacts();
         foreach ($indi->getSpouseFamilies() as $family) {
             foreach ($family->getFacts() as $fact) {
                 $facts[] = $fact;
             }
         }
         foreach ($facts as $event) {
             // get the fact type
             $fact = $event->getTag();
             if (!in_array($fact, $this->nonfacts)) {
                 // check for a date
                 $date = $event->getDate();
                 if ($date->isOK()) {
                     $date = new GregorianDate($date->minimumJulianDay());
                     $this->baseyear = min($this->baseyear, $date->y);
                     $this->topyear = max($this->topyear, $date->y);
                     if (!$indi->isDead()) {
                         $this->topyear = max($this->topyear, (int) date('Y'));
                     }
                     // do not add the same fact twice (prevents marriages from being added multiple times)
                     if (!in_array($event, $this->indifacts, true)) {
                         $this->indifacts[] = $event;
                     }
                 }
             }
         }
     }
     $scale = Filter::getInteger('scale', 0, 200);
     if ($scale === 0) {
         $this->scale = (int) (($this->topyear - $this->baseyear) / 20 * count($this->indifacts) / 4);
         if ($this->scale < 6) {
             $this->scale = 6;
         }
     } else {
         $this->scale = $scale;
     }
     if ($this->scale < 2) {
         $this->scale = 2;
     }
     $this->baseyear -= 5;
     $this->topyear += 5;
 }
Exemplo n.º 23
0
                // Add new FAMC link
                $new_child->createFact('1 FAMC @' . $family->getXref() . '@', !$keep_chan);
                // Add new CHIL link
                $family->createFact('1 CHIL @' . $new_child->getXref() . '@', !$keep_chan);
            }
        }
        $controller->addInlineJavascript('closePopupAndReloadParent();');
        break;
        ////////////////////////////////////////////////////////////////////////////////
        // Change the order of FAMS records within an INDI record
        ////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////
    // Change the order of FAMS records within an INDI record
    ////////////////////////////////////////////////////////////////////////////////
    case 'reorder_fams':
        $xref = Filter::post('xref', WT_REGEX_XREF, Filter::get('xref', WT_REGEX_XREF));
        $option = Filter::post('option');
        $person = Individual::getInstance($xref, $WT_TREE);
        check_record_access($person);
        $controller->addInlineJavascript('jQuery("#reorder_list").sortable({forceHelperSize: true, forcePlaceholderSize: true, opacity: 0.7, cursor: "move", axis: "y"});')->addInlineJavascript('jQuery("#reorder_list").bind("sortupdate", function(event, ui) { jQuery("#"+jQuery(this).attr("id")+" input").each( function (index, value) { value.value = index+1; }); });')->setPageTitle(I18N::translate('Re-order families'))->pageHeader();
        $fams = $person->getSpouseFamilies();
        if ($option === 'bymarriage') {
            usort($fams, '\\Fisharebest\\Webtrees\\Family::compareMarrDate');
        }
        ?>
	<div id="edit_interface-page">
	<h4><?php 
        echo $controller->getPageTitle();
        ?>
</h4>
	<form name="reorder_form" method="post" action="edit_interface.php">
Exemplo n.º 24
0
$latest = Database::prepare("SELECT DATE(MAX(change_time)) FROM `##change`")->execute(array())->fetchOne();
// Filtering
$action = Filter::get('action');
$from = Filter::get('from', '\\d\\d\\d\\d-\\d\\d-\\d\\d', $earliest);
$to = Filter::get('to', '\\d\\d\\d\\d-\\d\\d-\\d\\d', $latest);
$type = Filter::get('type', 'accepted|rejected|pending');
$oldged = Filter::get('oldged');
$newged = Filter::get('newged');
$xref = Filter::get('xref', WT_REGEX_XREF);
$user = Filter::get('user');
$search = Filter::get('search');
$search = isset($search['value']) ? $search['value'] : null;
$statuses = array('' => '', 'accepted' => I18N::translate('accepted'), 'rejected' => I18N::translate('rejected'), 'pending' => I18N::translate('pending'));
if (Auth::isAdmin()) {
    // Administrators can see all logs
    $gedc = Filter::get('gedc');
} else {
    // Managers can only see logs relating to this gedcom
    $gedc = $WT_TREE->getName();
}
$sql_select = "SELECT SQL_CACHE 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" . " FROM `##change`" . " LEFT JOIN `##user` USING (user_id)" . " LEFT JOIN `##gedcom` USING (gedcom_id)";
// gedcom may be deleted
$where = " WHERE 1";
$args = array();
if ($search) {
    $where .= " AND (old_gedcom LIKE CONCAT('%', :search_1, '%') OR new_gedcom LIKE CONCAT('%', :search_2, '%'))";
    $args['search_1'] = $search;
    $args['search_2'] = $search;
}
if ($from) {
    $where .= " AND change_time >= :from";
Exemplo n.º 25
0
 * @global Tree $WT_TREE
 */
global $WT_TREE;
use Fisharebest\Webtrees\Controller\PageController;
use Fisharebest\Webtrees\Functions\FunctionsExport;
use PclZip;
define('WT_SCRIPT_NAME', 'admin_trees_download.php');
require './includes/session.php';
$controller = new PageController();
$controller->setPageTitle(I18N::translate($WT_TREE->getTitleHtml()) . ' — ' . I18N::translate('Export a GEDCOM file'))->restrictAccess(Auth::isManager($WT_TREE));
// Validate user parameters
$action = Filter::get('action', 'download');
$convert = Filter::get('convert', 'yes|no', 'no');
$zip = Filter::get('zip', 'yes|no', 'no');
$conv_path = Filter::get('conv_path');
$privatize_export = Filter::get('privatize_export', 'none|visitor|user|gedadmin');
if ($action === 'download') {
    $exportOptions = array('privatize' => $privatize_export, 'toANSI' => $convert, 'path' => $conv_path);
    // What to call the downloaded file
    $download_filename = $WT_TREE->getName();
    if (strtolower(substr($download_filename, -4, 4)) != '.ged') {
        $download_filename .= '.ged';
    }
    if ($zip === 'yes') {
        $temp_dir = WT_DATA_DIR . 'tmp-' . $WT_TREE->getName() . '-' . date('YmdHis') . '/';
        $zip_file = $download_filename . '.zip';
        if (!File::mkdir($temp_dir)) {
            echo "Error : Could not create temporary path!";
            return;
        }
        // Create the unzipped GEDCOM on disk, so we can ZIP it.
Exemplo n.º 26
0
    /**
     * Places administration.
     */
    private function adminPlaces()
    {
        global $WT_TREE;
        $action = Filter::get('action');
        $parent = Filter::get('parent');
        $inactive = Filter::getBool('inactive');
        $deleteRecord = Filter::get('deleteRecord');
        if (!isset($parent)) {
            $parent = 0;
        }
        $controller = new PageController();
        $controller->restrictAccess(Auth::isAdmin());
        if ($action == 'ExportFile' && Auth::isAdmin()) {
            $tmp = $this->placeIdToHierarchy($parent);
            $maxLevel = $this->getHighestLevel();
            if ($maxLevel > 8) {
                $maxLevel = 8;
            }
            $tmp[0] = 'places';
            $outputFileName = preg_replace('/[:;\\/\\\\(\\)\\{\\}\\[\\] $]/', '_', implode('-', $tmp)) . '.csv';
            header('Content-Type: application/octet-stream');
            header('Content-Disposition: attachment; filename="' . $outputFileName . '"');
            echo '"', I18N::translate('Level'), '";"', I18N::translate('Country'), '";';
            if ($maxLevel > 0) {
                echo '"', I18N::translate('State'), '";';
            }
            if ($maxLevel > 1) {
                echo '"', I18N::translate('County'), '";';
            }
            if ($maxLevel > 2) {
                echo '"', I18N::translate('City'), '";';
            }
            if ($maxLevel > 3) {
                echo '"', I18N::translate('Place'), '";';
            }
            if ($maxLevel > 4) {
                echo '"', I18N::translate('Place'), '";';
            }
            if ($maxLevel > 5) {
                echo '"', I18N::translate('Place'), '";';
            }
            if ($maxLevel > 6) {
                echo '"', I18N::translate('Place'), '";';
            }
            if ($maxLevel > 7) {
                echo '"', I18N::translate('Place'), '";';
            }
            echo '"', I18N::translate('Longitude'), '";"', I18N::translate('Latitude'), '";';
            echo '"', I18N::translate('Zoom level'), '";"', I18N::translate('Icon'), '";', WT_EOL;
            $this->outputLevel($parent);
            exit;
        }
        $controller->setPageTitle(I18N::translate('Google Maps™'))->pageHeader();
        ?>
		<ol class="breadcrumb small">
			<li><a href="admin.php"><?php 
        echo I18N::translate('Control panel');
        ?>
</a></li>
			<li><a href="admin_modules.php"><?php 
        echo I18N::translate('Module administration');
        ?>
</a></li>
			<li class="active"><?php 
        echo $controller->getPageTitle();
        ?>
</li>
		</ol>

		<ul class="nav nav-tabs nav-justified" role="tablist">
			<li role="presentation">
				<a href="?mod=googlemap&amp;mod_action=admin_config" role="tab">
					<?php 
        echo I18N::translate('Google Maps™ preferences');
        ?>
				</a>
			</li>
			<li role="presentation" class="active">
				<a href="#">
					<?php 
        echo I18N::translate('Geographic data');
        ?>
				</a>
			</li>
			<li role="presentation">
				<a href="?mod=googlemap&amp;mod_action=admin_placecheck">
					<?php 
        echo I18N::translate('Place check');
        ?>
				</a>
			</li>
		</ul>

		<h2><?php 
        echo I18N::translate('Geographic data');
        ?>
</h2>
		<?php 
        if ($action == 'ImportGedcom') {
            $placelist = array();
            $j = 0;
            $gedcom_records = Database::prepare("SELECT i_gedcom FROM `##individuals` WHERE i_file=? UNION ALL SELECT f_gedcom FROM `##families` WHERE f_file=?")->execute(array($WT_TREE->getTreeId(), $WT_TREE->getTreeId()))->fetchOneColumn();
            foreach ($gedcom_records as $gedrec) {
                $i = 1;
                $placerec = Functions::getSubRecord(2, '2 PLAC', $gedrec, $i);
                while (!empty($placerec)) {
                    if (preg_match("/2 PLAC (.+)/", $placerec, $match)) {
                        $placelist[$j] = array();
                        $placelist[$j]['place'] = trim($match[1]);
                        if (preg_match("/4 LATI (.*)/", $placerec, $match)) {
                            $placelist[$j]['lati'] = trim($match[1]);
                            if ($placelist[$j]['lati'][0] != 'N' && $placelist[$j]['lati'][0] != 'S') {
                                if ($placelist[$j]['lati'] < 0) {
                                    $placelist[$j]['lati'][0] = 'S';
                                } else {
                                    $placelist[$j]['lati'] = 'N' . $placelist[$j]['lati'];
                                }
                            }
                        } else {
                            $placelist[$j]['lati'] = null;
                        }
                        if (preg_match("/4 LONG (.*)/", $placerec, $match)) {
                            $placelist[$j]['long'] = trim($match[1]);
                            if ($placelist[$j]['long'][0] != 'E' && $placelist[$j]['long'][0] != 'W') {
                                if ($placelist[$j]['long'] < 0) {
                                    $placelist[$j]['long'][0] = 'W';
                                } else {
                                    $placelist[$j]['long'] = 'E' . $placelist[$j]['long'];
                                }
                            }
                        } else {
                            $placelist[$j]['long'] = null;
                        }
                        $j = $j + 1;
                    }
                    $i = $i + 1;
                    $placerec = Functions::getSubRecord(2, '2 PLAC', $gedrec, $i);
                }
            }
            asort($placelist);
            $prevPlace = '';
            $prevLati = '';
            $prevLong = '';
            $placelistUniq = array();
            $j = 0;
            foreach ($placelist as $k => $place) {
                if ($place['place'] != $prevPlace) {
                    $placelistUniq[$j] = array();
                    $placelistUniq[$j]['place'] = $place['place'];
                    $placelistUniq[$j]['lati'] = $place['lati'];
                    $placelistUniq[$j]['long'] = $place['long'];
                    $j = $j + 1;
                } elseif ($place['place'] == $prevPlace && ($place['lati'] != $prevLati || $place['long'] != $prevLong)) {
                    if ($placelistUniq[$j - 1]['lati'] == 0 || $placelistUniq[$j - 1]['long'] == 0) {
                        $placelistUniq[$j - 1]['lati'] = $place['lati'];
                        $placelistUniq[$j - 1]['long'] = $place['long'];
                    } elseif ($place['lati'] != '0' || $place['long'] != '0') {
                        echo 'Difference: previous value = ', $prevPlace, ', ', $prevLati, ', ', $prevLong, ' current = ', $place['place'], ', ', $place['lati'], ', ', $place['long'], '<br>';
                    }
                }
                $prevPlace = $place['place'];
                $prevLati = $place['lati'];
                $prevLong = $place['long'];
            }
            $highestIndex = $this->getHighestIndex();
            $default_zoom_level = array(4, 7, 10, 12);
            foreach ($placelistUniq as $k => $place) {
                $parent = preg_split('/ *, */', $place['place']);
                $parent = array_reverse($parent);
                $parent_id = 0;
                for ($i = 0; $i < count($parent); $i++) {
                    if (!isset($default_zoom_level[$i])) {
                        $default_zoom_level[$i] = $default_zoom_level[$i - 1];
                    }
                    $escparent = $parent[$i];
                    if ($escparent == '') {
                        $escparent = 'Unknown';
                    }
                    $row = Database::prepare("SELECT pl_id, pl_long, pl_lati, pl_zoom FROM `##placelocation` WHERE pl_level=? AND pl_parent_id=? AND pl_place LIKE ?")->execute(array($i, $parent_id, $escparent))->fetchOneRow();
                    if ($i < count($parent) - 1) {
                        // Create higher-level places, if necessary
                        if (empty($row)) {
                            $highestIndex++;
                            Database::prepare("INSERT INTO `##placelocation` (pl_id, pl_parent_id, pl_level, pl_place, pl_zoom) VALUES (?, ?, ?, ?, ?)")->execute(array($highestIndex, $parent_id, $i, $escparent, $default_zoom_level[$i]));
                            echo Filter::escapeHtml($escparent), '<br>';
                            $parent_id = $highestIndex;
                        } else {
                            $parent_id = $row->pl_id;
                        }
                    } else {
                        // Create lowest-level place, if necessary
                        if (empty($row->pl_id)) {
                            $highestIndex++;
                            Database::prepare("INSERT INTO `##placelocation` (pl_id, pl_parent_id, pl_level, pl_place, pl_long, pl_lati, pl_zoom) VALUES (?, ?, ?, ?, ?, ?, ?)")->execute(array($highestIndex, $parent_id, $i, $escparent, $place['long'], $place['lati'], $default_zoom_level[$i]));
                            echo Filter::escapeHtml($escparent), '<br>';
                        } else {
                            if (empty($row->pl_long) && empty($row->pl_lati) && $place['lati'] != '0' && $place['long'] != '0') {
                                Database::prepare("UPDATE `##placelocation` SET pl_lati=?, pl_long=? WHERE pl_id=?")->execute(array($place['lati'], $place['long'], $row->pl_id));
                                echo Filter::escapeHtml($escparent), '<br>';
                            }
                        }
                    }
                }
            }
            $parent = 0;
        }
        if ($action === 'ImportFile') {
            $placefiles = $this->findFiles(WT_MODULES_DIR . 'googlemap/extra');
            sort($placefiles);
            ?>
		<form class="form-horizontal" method="post" enctype="multipart/form-data" id="importfile" name="importfile" action="module.php?mod=googlemap&amp;mod_action=admin_places&amp;action=ImportFile2">

			<!-- PLACES FILE -->
			<div class="form-group">
				<label class="control-label col-sm-4" for="placesfile">
					<?php 
            echo I18N::translate('File containing places (CSV)');
            ?>
				</label>
				<div class="col-sm-8">
					<div class="btn btn-default">
					<input id="placesfile" type="file" name="placesfile">
					</div>
				</div>
			</div>

			<!-- LOCAL FILE -->
			<?php 
            if (count($placefiles) > 0) {
                ?>
			<div class="form-group">
				<label class="control-label col-sm-4" for="localfile">
					<?php 
                echo I18N::translate('Server file containing places (CSV)');
                ?>
				</label>
				<div class="col-sm-8">
					<div class="input-group">
						<span class="input-group-addon">
							<?php 
                echo WT_MODULES_DIR . 'googlemap/extra/';
                ?>
						</span>
						<?php 
                foreach ($placefiles as $p => $placefile) {
                    unset($placefiles[$p]);
                    $p = Filter::escapeHtml($placefile);
                    if (substr($placefile, 0, 1) == "/") {
                        $placefiles[$p] = substr($placefile, 1);
                    } else {
                        $placefiles[$p] = $placefile;
                    }
                }
                echo FunctionsEdit::selectEditControl('localfile', $placefiles, '', '', 'class="form-control"');
                ?>
					</div>
				</div>
			</div>
			<?php 
            }
            ?>

			<!-- CLEAR DATABASE -->
			<fieldset class="form-group">
				<legend class="control-label col-sm-4">
					<?php 
            echo I18N::translate('Delete all existing geographic data before importing the file.');
            ?>
				</legend>
				<div class="col-sm-8">
					<?php 
            echo FunctionsEdit::editFieldYesNo('cleardatabase', 0, 'class="radio-inline"');
            ?>
				</div>
			</fieldset>

			<!-- UPDATE ONLY -->
			<fieldset class="form-group">
				<legend class="control-label col-sm-4">
					<?php 
            echo I18N::translate('Do not create new locations, just import coordinates for existing locations.');
            ?>
				</legend>
				<div class="col-sm-8">
					<?php 
            echo FunctionsEdit::editFieldYesNo('updateonly', 0, 'class="radio-inline"');
            ?>
				</div>
			</fieldset>

			<!-- OVERWRITE DATA -->
			<fieldset class="form-group">
				<legend class="control-label col-sm-4">
					<?php 
            echo I18N::translate('Overwrite existing coordinates.');
            ?>
				</legend>
				<div class="col-sm-8">
					<?php 
            echo FunctionsEdit::editFieldYesNo('overwritedata', 0, 'class="radio-inline"');
            ?>
				</div>
			</fieldset>

			<!-- SAVE BUTTON -->
			<div class="form-group">
				<div class="col-sm-offset-4 col-sm-8">
					<button type="submit" class="btn btn-primary">
						<i class="fa fa-check"></i>
						<?php 
            echo I18N::translate('Continue adding');
            ?>
					</button>
				</div>
			</div>
		</form>
		<?php 
            exit;
        }
        if ($action === 'ImportFile2') {
            $country_names = array();
            $stats = new Stats($WT_TREE);
            foreach ($stats->iso3166() as $key => $value) {
                $country_names[$key] = I18N::translate($key);
            }
            if (Filter::postBool('cleardatabase')) {
                Database::exec("DELETE FROM `##placelocation` WHERE 1=1");
            }
            if (!empty($_FILES['placesfile']['tmp_name'])) {
                $lines = file($_FILES['placesfile']['tmp_name']);
            } elseif (!empty($_REQUEST['localfile'])) {
                $lines = file(WT_MODULES_DIR . 'googlemap/extra' . $_REQUEST['localfile']);
            }
            // Strip BYTE-ORDER-MARK, if present
            if (!empty($lines[0]) && substr($lines[0], 0, 3) === WT_UTF8_BOM) {
                $lines[0] = substr($lines[0], 3);
            }
            asort($lines);
            $highestIndex = $this->getHighestIndex();
            $placelist = array();
            $j = 0;
            $maxLevel = 0;
            foreach ($lines as $p => $placerec) {
                $fieldrec = explode(';', $placerec);
                if ($fieldrec[0] > $maxLevel) {
                    $maxLevel = $fieldrec[0];
                }
            }
            $fields = count($fieldrec);
            $set_icon = true;
            if (!is_dir(WT_MODULES_DIR . 'googlemap/places/flags/')) {
                $set_icon = false;
            }
            foreach ($lines as $p => $placerec) {
                $fieldrec = explode(';', $placerec);
                if (is_numeric($fieldrec[0]) && $fieldrec[0] <= $maxLevel) {
                    $placelist[$j] = array();
                    $placelist[$j]['place'] = '';
                    for ($ii = $fields - 4; $ii > 1; $ii--) {
                        if ($fieldrec[0] > $ii - 2) {
                            $placelist[$j]['place'] .= $fieldrec[$ii] . ',';
                        }
                    }
                    foreach ($country_names as $countrycode => $countryname) {
                        if ($countrycode == strtoupper($fieldrec[1])) {
                            $fieldrec[1] = $countryname;
                            break;
                        }
                    }
                    $placelist[$j]['place'] .= $fieldrec[1];
                    $placelist[$j]['long'] = $fieldrec[$fields - 4];
                    $placelist[$j]['lati'] = $fieldrec[$fields - 3];
                    $placelist[$j]['zoom'] = $fieldrec[$fields - 2];
                    if ($set_icon) {
                        $placelist[$j]['icon'] = trim($fieldrec[$fields - 1]);
                    } else {
                        $placelist[$j]['icon'] = '';
                    }
                    $j = $j + 1;
                }
            }
            $prevPlace = '';
            $prevLati = '';
            $prevLong = '';
            $placelistUniq = array();
            $j = 0;
            foreach ($placelist as $k => $place) {
                if ($place['place'] != $prevPlace) {
                    $placelistUniq[$j] = array();
                    $placelistUniq[$j]['place'] = $place['place'];
                    $placelistUniq[$j]['lati'] = $place['lati'];
                    $placelistUniq[$j]['long'] = $place['long'];
                    $placelistUniq[$j]['zoom'] = $place['zoom'];
                    $placelistUniq[$j]['icon'] = $place['icon'];
                    $j = $j + 1;
                } elseif ($place['place'] == $prevPlace && ($place['lati'] != $prevLati || $place['long'] != $prevLong)) {
                    if ($placelistUniq[$j - 1]['lati'] == 0 || $placelistUniq[$j - 1]['long'] == 0) {
                        $placelistUniq[$j - 1]['lati'] = $place['lati'];
                        $placelistUniq[$j - 1]['long'] = $place['long'];
                        $placelistUniq[$j - 1]['zoom'] = $place['zoom'];
                        $placelistUniq[$j - 1]['icon'] = $place['icon'];
                    } elseif ($place['lati'] != '0' || $place['long'] != '0') {
                        echo 'Difference: previous value = ', $prevPlace, ', ', $prevLati, ', ', $prevLong, ' current = ', $place['place'], ', ', $place['lati'], ', ', $place['long'], '<br>';
                    }
                }
                $prevPlace = $place['place'];
                $prevLati = $place['lati'];
                $prevLong = $place['long'];
            }
            $default_zoom_level = array();
            $default_zoom_level[0] = 4;
            $default_zoom_level[1] = 7;
            $default_zoom_level[2] = 10;
            $default_zoom_level[3] = 12;
            foreach ($placelistUniq as $k => $place) {
                $parent = explode(',', $place['place']);
                $parent = array_reverse($parent);
                $parent_id = 0;
                for ($i = 0; $i < count($parent); $i++) {
                    $escparent = $parent[$i];
                    if ($escparent == '') {
                        $escparent = 'Unknown';
                    }
                    $row = Database::prepare("SELECT pl_id, pl_long, pl_lati, pl_zoom, pl_icon FROM `##placelocation` WHERE pl_level=? AND pl_parent_id=? AND pl_place LIKE ? ORDER BY pl_place")->execute(array($i, $parent_id, $escparent))->fetchOneRow();
                    if (empty($row)) {
                        // this name does not yet exist: create entry
                        if (!Filter::postBool('updateonly')) {
                            $highestIndex = $highestIndex + 1;
                            if ($i + 1 == count($parent)) {
                                $zoomlevel = $place['zoom'];
                            } elseif (isset($default_zoom_level[$i])) {
                                $zoomlevel = $default_zoom_level[$i];
                            } else {
                                $zoomlevel = $this->getSetting('GM_MAX_ZOOM');
                            }
                            if ($place['lati'] == '0' || $place['long'] == '0' || $i + 1 < count($parent)) {
                                Database::prepare("INSERT INTO `##placelocation` (pl_id, pl_parent_id, pl_level, pl_place, pl_zoom, pl_icon) VALUES (?, ?, ?, ?, ?, ?)")->execute(array($highestIndex, $parent_id, $i, $escparent, $zoomlevel, $place['icon']));
                            } else {
                                //delete leading zero
                                $pl_lati = str_replace(array('N', 'S', ','), array('', '-', '.'), $place['lati']);
                                $pl_long = str_replace(array('E', 'W', ','), array('', '-', '.'), $place['long']);
                                if ($pl_lati >= 0) {
                                    $place['lati'] = 'N' . abs($pl_lati);
                                } elseif ($pl_lati < 0) {
                                    $place['lati'] = 'S' . abs($pl_lati);
                                }
                                if ($pl_long >= 0) {
                                    $place['long'] = 'E' . abs($pl_long);
                                } elseif ($pl_long < 0) {
                                    $place['long'] = 'W' . abs($pl_long);
                                }
                                Database::prepare("INSERT INTO `##placelocation` (pl_id, pl_parent_id, pl_level, pl_place, pl_long, pl_lati, pl_zoom, pl_icon) VALUES (?, ?, ?, ?, ?, ?, ?, ?)")->execute(array($highestIndex, $parent_id, $i, $escparent, $place['long'], $place['lati'], $zoomlevel, $place['icon']));
                            }
                            $parent_id = $highestIndex;
                        }
                    } else {
                        $parent_id = $row->pl_id;
                        if (Filter::postBool('overwritedata') && $i + 1 == count($parent)) {
                            Database::prepare("UPDATE `##placelocation` SET pl_lati = ?, pl_long = ?, pl_zoom = ?, pl_icon = ? WHERE pl_id = ?")->execute(array($place['lati'], $place['long'], $place['zoom'], $place['icon'], $parent_id));
                        } else {
                            // Update only if existing data is missing
                            if (!$row->pl_long && !$row->pl_lati) {
                                Database::prepare("UPDATE `##placelocation` SET pl_lati = ?, pl_long = ? WHERE pl_id = ?")->execute(array($place['lati'], $place['long'], $parent_id));
                            }
                            if (!$row->pl_icon && $place['icon']) {
                                Database::prepare("UPDATE `##placelocation` SET pl_icon = ? WHERE pl_id = ?")->execute(array($place['icon'], $parent_id));
                            }
                        }
                    }
                }
            }
            $parent = 0;
        }
        if ($action == 'DeleteRecord') {
            $exists = Database::prepare("SELECT 1 FROM `##placelocation` WHERE pl_parent_id=?")->execute(array($deleteRecord))->fetchOne();
            if (!$exists) {
                Database::prepare("DELETE FROM `##placelocation` WHERE pl_id=?")->execute(array($deleteRecord));
            } else {
                echo '<table class="facts_table"><tr><td>', I18N::translate('Location not removed: this location contains sub-locations'), '</td></tr></table>';
            }
        }
        ?>
		<script>
		function updateList(inactive) {
			window.location.href='<?php 
        if (strstr($_SERVER['REQUEST_URI'], '&inactive', true)) {
            $uri = strstr($_SERVER['REQUEST_URI'], '&inactive', true);
        } else {
            $uri = $_SERVER['REQUEST_URI'];
        }
        echo $uri, '&inactive=';
        ?>
'+inactive;
		}

		function edit_place_location(placeid) {
			window.open('module.php?mod=googlemap&mod_action=places_edit&action=update&placeid='+placeid, '_blank', gmap_window_specs);
			return false;
		}

		function add_place_location(placeid) {
			window.open('module.php?mod=googlemap&mod_action=places_edit&action=add&placeid='+placeid, '_blank', gmap_window_specs);
			return false;
		}

		function delete_place(placeid) {
			var answer=confirm('<?php 
        echo I18N::translate('Remove this location?');
        ?>
');
			if (answer == true) {
				window.location = '<?php 
        echo Functions::getQueryUrl(array('action' => 'DeleteRecord'));
        ?>
&action=DeleteRecord&deleteRecord=' + placeid;
			}
		}
		</script>
		<p id="gm_breadcrumb">
			<?php 
        $where_am_i = $this->placeIdToHierarchy($parent);
        foreach (array_reverse($where_am_i, true) as $id => $place) {
            if ($id == $parent) {
                if ($place != 'Unknown') {
                    echo Filter::escapeHtml($place);
                } else {
                    echo I18N::translate('unknown');
                }
            } else {
                echo '<a href="module.php?mod=googlemap&mod_action=admin_places&parent=', $id, '&inactive=', $inactive, '">';
                if ($place != 'Unknown') {
                    echo Filter::escapeHtml($place), '</a>';
                } else {
                    echo I18N::translate('unknown'), '</a>';
                }
            }
            echo ' - ';
        }
        ?>
			<a href="module.php?mod=googlemap&mod_action=admin_places&parent=0&inactive=', $inactive, '"><?php 
        echo I18N::translate('Top level');
        ?>
</a>
		</p>

		<form class="form-inline" name="active" method="post" action="module.php?mod=googlemap&mod_action=admin_places&parent=', $parent, '&inactive=', $inactive, '">
			<div class="checkbox">
				<label for="inactive">
				   <?php 
        echo FunctionsEdit::checkbox('inactive', $inactive, 'onclick="updateList(this.checked)"');
        ?>
				   <?php 
        echo I18N::translate('Show inactive places');
        ?>
				</label>
			</div>
			<p class="small text-muted">
				<?php 
        echo I18N::translate('By default, the list shows only those places which can be found in your family trees.  You may have details for other places, such as those imported in bulk from an external file.  Selecting this option will show all places, including ones that are not currently used.');
        ?>
				<?php 
        echo I18N::translate('If you have a large number of inactive places, it can be slow to generate the list.');
        ?>
			</p>
		</form>

		<?php 
        $placelist = $this->getPlaceListLocation($parent, $inactive);
        echo '<div class="gm_plac_edit">';
        echo '<table class="table table-bordered table-condensed table-hover"><tr>';
        echo '<th>', GedcomTag::getLabel('PLAC'), '</th>';
        echo '<th>', GedcomTag::getLabel('LATI'), '</th>';
        echo '<th>', GedcomTag::getLabel('LONG'), '</th>';
        echo '<th>', I18N::translate('Zoom level'), '</th>';
        echo '<th>', I18N::translate('Icon'), '</th>';
        echo '<th>';
        echo I18N::translate('Edit'), '</th><th>', I18N::translate('Delete'), '</th></tr>';
        if (count($placelist) == 0) {
            echo '<tr><td colspan="7">', I18N::translate('No places found'), '</td></tr>';
        }
        foreach ($placelist as $place) {
            echo '<tr><td><a href="module.php?mod=googlemap&mod_action=admin_places&parent=', $place['place_id'], '&inactive=', $inactive, '">';
            if ($place['place'] != 'Unknown') {
                echo Filter::escapeHtml($place['place']), '</a></td>';
            } else {
                echo I18N::translate('unknown'), '</a></td>';
            }
            echo '<td>', $place['lati'], '</td>';
            echo '<td>', $place['long'], '</td>';
            echo '<td>', $place['zoom'], '</td>';
            echo '<td>';
            if ($place['icon']) {
                echo '<img src="', WT_STATIC_URL, WT_MODULES_DIR, 'googlemap/', $place['icon'], '" width="25" height="15">';
            } else {
                if ($place['lati'] || $place['long']) {
                    echo '<img src="', WT_STATIC_URL, WT_MODULES_DIR, 'googlemap/images/mm_20_red.png">';
                } else {
                    echo '<img src="', WT_STATIC_URL, WT_MODULES_DIR, 'googlemap/images/mm_20_yellow.png">';
                }
            }
            echo '</td>';
            echo '<td class="narrow"><a href="#" onclick="edit_place_location(', $place['place_id'], ');return false;" class="icon-edit" title="', I18N::translate('Edit'), '"></a></td>';
            $noRows = Database::prepare("SELECT COUNT(pl_id) FROM `##placelocation` WHERE pl_parent_id=?")->execute(array($place['place_id']))->fetchOne();
            if ($noRows == 0) {
                ?>
				<td><a href="#" onclick="delete_place(<?php 
                echo $place['place_id'];
                ?>
);return false;" class="icon-delete" title="<?php 
                echo I18N::translate('Remove');
                ?>
"></a></td>
		<?php 
            } else {
                ?>
				<td><i class="icon-delete-grey"></i></td>
		<?php 
            }
            ?>
			</tr>
			<?php 
        }
        ?>
		</table>
		</div>

		<hr>
		<form class="form-horizontal" action="?" onsubmit="add_place_location(this.parent_id.options[this.parent_id.selectedIndex].value); return false;">
			<div class="form-group">
				<label class="form-control-static col-sm-4" for="parent_id">
					<?php 
        echo I18N::translate('Add a new geographic location');
        ?>
				</label>
				<div class="col-sm-8">
					<div class="col-sm-6">
						<?php 
        echo FunctionsEdit::selectEditControl('parent_id', $where_am_i, I18N::translate('Top level'), $parent, 'class="form-control"');
        ?>
					</div>
					<button type="submit" class="btn btn-default">
						<i class="fa fa-plus"></i>
						<?php 
        echo I18N::translate('Add');
        ?>
					</button>
				</div>
			</div>
		</form>

		<form class="form-horizontal" action="module.php" method="get">
			<input type="hidden" name="mod" value="googlemap">
			<input type="hidden" name="mod_action" value="admin_places">
			<input type="hidden" name="action" value="ImportGedcom">
			<div class="form-group">
				<label class="form-control-static col-sm-4" for="ged">
					<?php 
        echo I18N::translate('Import all places from a family tree');
        ?>
				</label>
				<div class="col-sm-8">
					<div class="col-sm-6">
						<?php 
        echo FunctionsEdit::selectEditControl('ged', Tree::getNameList(), null, $WT_TREE->getName(), 'class="form-control"');
        ?>
					</div>
					<button type="submit" class="btn btn-default">
						<i class="fa fa-upload"></i>
						<?php 
        echo I18N::translate('Import');
        ?>
					</button>
				</div>
			</div>
		</form>

		<form class="form-horizontal" action="module.php" method="get">
			<input type="hidden" name="mod" value="googlemap">
			<input type="hidden" name="mod_action" value="admin_places">
			<input type="hidden" name="action" value="ImportFile">
			<div class="form-group">
				<label class="form-control-static col-sm-4">
					<?php 
        echo I18N::translate('Upload geographic data');
        ?>
				</label>
				<div class="col-sm-8">
					<div class="col-sm-6">
						<button type="submit" class="btn btn-default">
							<i class="fa fa-upload"></i>
							<?php 
        echo I18N::translate('Upload');
        ?>
						</button>
					</div>
				</div>
			</div>
		</form>

		<form class="form-horizontal" action="module.php" method="get">
			<input type="hidden" name="mod" value="googlemap">
			<input type="hidden" name="mod_action" value="admin_places">
			<input type="hidden" name="action" value="ExportFile">
			<div class="form-group">
				<label class="form-control-static col-sm-4">
					<?php 
        echo I18N::translate('Download geographic data');
        ?>
				</label>
				<div class="col-sm-8">
					<div class="col-sm-6">
						<?php 
        echo FunctionsEdit::selectEditControl('parent', $where_am_i, I18N::translate('All'), $WT_TREE->getTreeId(), 'class="form-control"');
        ?>
					</div>
					<button type="submit" class="btn btn-default">
						<i class="fa fa-download"></i>
						<?php 
        echo I18N::translate('Download');
        ?>
					</button>
				</div>
			</div>
		</form>
		<?php 
    }
Exemplo n.º 27
0
 /**
  * Startup activity
  */
 public function __construct()
 {
     global $WT_TREE;
     parent::__construct();
     // $action comes from GET (search) or POST (replace)
     if (Filter::post('action')) {
         $this->action = Filter::post('action', 'replace', 'general');
         $this->query = Filter::post('query');
         $this->replace = Filter::post('replace');
         $this->replaceNames = Filter::post('replaceNames', 'checked', '');
         $this->replacePlaces = Filter::post('replacePlaces', 'checked', '');
         $this->replacePlacesWord = Filter::post('replacePlacesWord', 'checked', '');
         $this->replaceAll = Filter::post('replaceAll', 'checked', '');
     } else {
         $this->action = Filter::get('action', 'advanced|general|soundex|replace|header', 'general');
         $this->query = Filter::get('query');
         $this->replace = Filter::get('replace');
         $this->replaceNames = Filter::get('replaceNames', 'checked', '');
         $this->replacePlaces = Filter::get('replacePlaces', 'checked', '');
         $this->replacePlacesWord = Filter::get('replacePlacesWord', 'checked', '');
         $this->replaceAll = Filter::get('replaceAll', 'checked', '');
     }
     // Only editors can use search/replace
     if ($this->action === 'replace' && !Auth::isEditor($WT_TREE)) {
         $this->action = 'general';
     }
     $this->srindi = Filter::get('srindi', 'checked', '');
     $this->srfams = Filter::get('srfams', 'checked', '');
     $this->srsour = Filter::get('srsour', 'checked', '');
     $this->srnote = Filter::get('srnote', 'checked', '');
     $this->soundex = Filter::get('soundex', 'DaitchM|Russell', 'DaitchM');
     $this->showasso = Filter::get('showasso');
     $this->firstname = Filter::get('firstname');
     $this->lastname = Filter::get('lastname');
     $this->place = Filter::get('place');
     $this->year = Filter::get('year');
     // If no record types specified, search individuals
     if (!$this->srfams && !$this->srsour && !$this->srnote) {
         $this->srindi = 'checked';
     }
     // If no replace types specifiied, replace full records
     if (!$this->replaceNames && !$this->replacePlaces && !$this->replacePlacesWord) {
         $this->replaceAll = 'checked';
     }
     // Trees to search
     if (Site::getPreference('ALLOW_CHANGE_GEDCOM')) {
         foreach (Tree::getAll() as $search_tree) {
             if (Filter::get('tree_' . $search_tree->getTreeId())) {
                 $this->search_trees[] = $search_tree;
             }
         }
         if (!$this->search_trees) {
             $this->search_trees[] = $WT_TREE;
         }
     } else {
         $this->search_trees[] = $WT_TREE;
     }
     // If we want to show associated persons, build the list
     switch ($this->action) {
         case 'header':
             // We can type in an XREF into the header search, and jump straight to it.
             // Otherwise, the header search is the same as the general search
             if (preg_match('/' . WT_REGEX_XREF . '/', $this->query)) {
                 $record = GedcomRecord::getInstance($this->query, $WT_TREE);
                 if ($record && $record->canShowName()) {
                     header('Location: ' . WT_BASE_URL . $record->getRawUrl());
                     exit;
                 }
             }
             $this->action = 'general';
             $this->srindi = 'checked';
             $this->srfams = 'checked';
             $this->srsour = 'checked';
             $this->srnote = 'checked';
             $this->setPageTitle(I18N::translate('General search'));
             $this->generalSearch();
             break;
         case 'general':
             $this->setPageTitle(I18N::translate('General search'));
             $this->generalSearch();
             break;
         case 'soundex':
             // Create a dummy search query to use as a title to the results list
             $this->query = trim($this->firstname . ' ' . $this->lastname . ' ' . $this->place);
             $this->setPageTitle(I18N::translate('Phonetic search'));
             $this->soundexSearch();
             break;
         case 'replace':
             $this->setPageTitle(I18N::translate('Search and replace'));
             $this->search_trees = array($WT_TREE);
             $this->srindi = 'checked';
             $this->srfams = 'checked';
             $this->srsour = 'checked';
             $this->srnote = 'checked';
             if (Filter::post('query')) {
                 $this->searchAndReplace($WT_TREE);
                 header('Location: ' . WT_BASE_URL . WT_SCRIPT_NAME . '?action=replace&query=' . Filter::escapeUrl($this->query) . '&replace=' . Filter::escapeUrl($this->replace) . '&replaceAll=' . $this->replaceAll . '&replaceNames=' . $this->replaceNames . '&replacePlaces=' . $this->replacePlaces . '&replacePlacesWord=' . $this->replacePlacesWord);
                 exit;
             }
     }
 }
Exemplo n.º 28
0
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
namespace Fisharebest\Webtrees;

/**
 * Defined in session.php
 *
 * @global Tree $WT_TREE
 */
global $WT_TREE;
use Fisharebest\Webtrees\Controller\FamilyController;
use Fisharebest\Webtrees\Functions\FunctionsCharts;
use Fisharebest\Webtrees\Functions\FunctionsPrint;
define('WT_SCRIPT_NAME', 'family.php');
require './includes/session.php';
$record = Family::getInstance(Filter::get('famid', WT_REGEX_XREF), $WT_TREE);
$controller = new FamilyController($record);
if ($controller->record && $controller->record->canShow()) {
    $controller->pageHeader();
    if ($controller->record->isPendingDeletion()) {
        if (Auth::isModerator($controller->record->getTree())) {
            echo '<p class="ui-state-highlight">', I18N::translate('This family has been deleted.  You should review the deletion and then %1$s or %2$s it.', '<a href="#" onclick="accept_changes(\'' . $controller->record->getXref() . '\');">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'accept') . '</a>', '<a href="#" onclick="reject_changes(\'' . $controller->record->getXref() . '\');">' . I18N::translateContext('You should review the deletion and then accept or reject it.', 'reject') . '</a>'), ' ', FunctionsPrint::helpLink('pending_changes'), '</p>';
        } elseif (Auth::isEditor($controller->record->getTree())) {
            echo '<p class="ui-state-highlight">', I18N::translate('This family has been deleted.  The deletion will need to be reviewed by a moderator.'), ' ', FunctionsPrint::helpLink('pending_changes'), '</p>';
        }
    } elseif ($controller->record->isPendingAddtion()) {
        if (Auth::isModerator($controller->record->getTree())) {
            echo '<p class="ui-state-highlight">', I18N::translate('This family has been edited.  You should review the changes and then %1$s or %2$s them.', '<a href="#" onclick="accept_changes(\'' . $controller->record->getXref() . '\');">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'accept') . '</a>', '<a href="#" onclick="reject_changes(\'' . $controller->record->getXref() . '\');">' . I18N::translateContext('You should review the changes and then accept or reject them.', 'reject') . '</a>'), ' ', FunctionsPrint::helpLink('pending_changes'), '</p>';
        } elseif (Auth::isEditor($controller->record->getTree())) {
            echo '<p class="ui-state-highlight">', I18N::translate('This family has been edited.  The changes need to be reviewed by a moderator.'), ' ', FunctionsPrint::helpLink('pending_changes'), '</p>';
        }
Exemplo n.º 29
0
define('WT_DEBUG_SQL', false);
define('WT_REQUIRED_MYSQL_VERSION', '5.0.13');
define('WT_REQUIRED_PHP_VERSION', '5.3.2');
define('WT_MODULES_DIR', 'modules_v3/');
define('WT_ROOT', '');
define('WT_CLIENT_IP', $_SERVER['REMOTE_ADDR']);
if (file_exists(WT_DATA_DIR . WT_CONFIG_FILE)) {
    header('Location: index.php');
    return;
}
if (version_compare(PHP_VERSION, WT_REQUIRED_PHP_VERSION) < 0) {
    echo '<h1>Sorry, the setup wizard cannot start.</h1>', '<p>This server is running PHP version ', PHP_VERSION, '</p>', '<p>PHP ', WT_REQUIRED_PHP_VERSION, ' (or any later version) is required</p>';
    return;
}
Session::start();
define('WT_LOCALE', I18N::init(Filter::post('lang', '[a-zA-Z-]+', Filter::get('lang', '[a-zA-Z-]+'))));
header('Content-Type: text/html; charset=UTF-8');
?>
<!DOCTYPE html>
<html <?php 
echo I18N::htmlAttributes();
?>
>
<head>
	<meta charset="UTF-8">
	<title>
		webtrees setup wizard
	</title>
	<style type="text/css">
		body {color: black; background-color: white; font: 14px tahoma, arial, helvetica, sans-serif; padding:10px; }
		a {color: black; font-weight: normal; text-decoration: none;}
 /**
  * Process the user-supplied options.
  */
 public function getOptions()
 {
     parent::getOptions();
     $this->search = Filter::get('search');
     $this->replace = Filter::get('replace');
     $this->method = Filter::get('method', 'exact|words|wildcards|regex', 'exact');
     $this->case = Filter::get('case', 'i');
     $this->error = '';
     switch ($this->method) {
         case 'exact':
             $this->regex = preg_quote($this->search, '/');
             break;
         case 'words':
             $this->regex = '\\b' . preg_quote($this->search, '/') . '\\b';
             break;
         case 'wildcards':
             $this->regex = '\\b' . str_replace(array('\\*', '\\?'), array('.*', '.'), preg_quote($this->search, '/')) . '\\b';
             break;
         case 'regex':
             $this->regex = $this->search;
             // Check for invalid regular expressions.
             // A valid regex on a null string returns zero.
             // An invalid regex on a null string returns false and throws a warning.
             try {
                 preg_match('/' . $this->search . '/', null);
             } catch (\ErrorException $ex) {
                 $this->error = '<div class="alert alert-danger">' . I18N::translate('The regex appears to contain an error.  It can’t be used.') . '</div>';
             }
             break;
     }
 }