summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/Controller/FamilyController.php44
-rw-r--r--app/Controller/IndividualController.php56
-rw-r--r--app/Controller/MediaController.php74
-rw-r--r--app/Controller/NoteController.php26
-rw-r--r--app/Controller/RepositoryController.php36
-rw-r--r--app/Controller/SourceController.php38
-rw-r--r--app/Menu.php85
-rw-r--r--app/Module/AbstractModule.php2
-rw-r--r--app/Module/AlbumModule.php28
-rw-r--r--app/Module/GoogleMapsModule.php1
-rw-r--r--app/Module/InteractiveTreeModule.php1
-rw-r--r--app/Report/ReportBaseFootnote.php2
-rw-r--r--app/Report/ReportHtml.php1
-rw-r--r--app/Stats.php18
-rw-r--r--app/Theme/AbstractTheme.php24
-rw-r--r--app/Theme/AdministrationTheme.php8
16 files changed, 245 insertions, 199 deletions
diff --git a/app/Controller/FamilyController.php b/app/Controller/FamilyController.php
index 0fcbaeb33a..1eb274d4f1 100644
--- a/app/Controller/FamilyController.php
+++ b/app/Controller/FamilyController.php
@@ -88,53 +88,53 @@ class FamilyController extends GedcomRecordController {
if (Auth::isEditor($this->record->getTree())) {
// edit_fam / members
- $submenu = new Menu(I18N::translate('Change family members'), '#', 'menu-fam-change');
- $submenu->setOnclick("return change_family_members('" . $this->record->getXref() . "');");
- $menu->addSubmenu($submenu);
+ $menu->addSubmenu(new Menu(I18N::translate('Change family members'), '#', 'menu-fam-change', array(
+ 'onclick' => 'return change_family_members("' . $this->record->getXref() . '");',
+ )));
// edit_fam / add child
- $submenu = new Menu(I18N::translate('Add a child to this family'), '#', 'menu-fam-addchil');
- $submenu->setOnclick("return add_child_to_family('" . $this->record->getXref() . "', 'U');");
- $menu->addSubmenu($submenu);
+ $menu->addSubmenu(new Menu(I18N::translate('Add a child to this family'), '#', 'menu-fam-addchil', array(
+ 'onclick' => 'return add_child_to_family("' . $this->record->getXref() . '", "U");',
+ )));
// edit_fam / reorder_children
if ($this->record->getNumberOfChildren() > 1) {
- $submenu = new Menu(I18N::translate('Re-order children'), '#', 'menu-fam-orderchil');
- $submenu->setOnclick("return reorder_children('" . $this->record->getXref() . "');");
- $menu->addSubmenu($submenu);
+ $menu->addSubmenu(new Menu(I18N::translate('Re-order children'), '#', 'menu-fam-orderchil', array(
+ 'onclick' => 'return reorder_children("' . $this->record->getXref() . '");',
+ )));
}
}
// delete
if (Auth::isEditor($this->record->getTree())) {
- $submenu = new Menu(I18N::translate('Delete'), '#', 'menu-fam-del');
- $submenu->setOnclick("return delete_family('" . I18N::translate('Deleting the family will unlink all of the individuals from each other but will leave the individuals in place. Are you sure you want to delete this family?') . "', '" . $this->record->getXref() . "');");
- $menu->addSubmenu($submenu);
+ $menu->addSubmenu(new Menu(I18N::translate('Delete'), '#', 'menu-fam-del', array(
+ 'onclick' => 'return delete_family("' . I18N::translate('Deleting the family will unlink all of the individuals from each other but will leave the individuals in place. Are you sure you want to delete this family?') . '", "' . $this->record->getXref() . '");',
+ )));
}
// edit raw
if (Auth::isAdmin() || Auth::isEditor($this->record->getTree()) && $this->record->getTree()->getPreference('SHOW_GEDCOM_RECORD')) {
- $submenu = new Menu(I18N::translate('Edit raw GEDCOM'), '#', 'menu-fam-editraw');
- $submenu->setOnclick("return edit_raw('" . $this->record->getXref() . "');");
- $menu->addSubmenu($submenu);
+ $menu->addSubmenu(new Menu(I18N::translate('Edit raw GEDCOM'), '#', 'menu-fam-editraw', array(
+ 'onclick' => 'return edit_raw("' . $this->record->getXref() . '");',
+ )));
}
// add to favorites
if (Module::getModuleByName('user_favorites')) {
- $submenu = new Menu(
- /* I18N: Menu option. Add [the current page] to the list of favorites */ I18N::translate('Add to favorites'),
+ $menu->addSubmenu(new Menu(
+ /* I18N: Menu option. Add [the current page] to the list of favorites */ I18N::translate('Add to favorites'),
'#',
- 'menu-fam-addfav'
- );
- $submenu->setOnclick("jQuery.post('module.php?mod=user_favorites&mod_action=menu-add-favorite',{xref:'" . $this->record->getXref() . "'},function(){location.reload();})");
- $menu->addSubmenu($submenu);
+ 'menu-fam-addfav',
+ array(
+ 'onclick' => 'jQuery.post("module.php?mod=user_favorites&mod_action=menu-add-favorite",{xref:"' . $this->record->getXref() . '"},function(){location.reload();})',
+ )));
}
// Get the link for the first submenu and set it as the link for the main menu
if ($menu->getSubmenus()) {
$submenus = $menu->getSubmenus();
$menu->setLink($submenus[0]->getLink());
- $menu->setOnClick($submenus[0]->getOnClick());
+ $menu->setAttrs($submenus[0]->getAttrs());
}
return $menu;
diff --git a/app/Controller/IndividualController.php b/app/Controller/IndividualController.php
index b5a0629ae4..0c3777e738 100644
--- a/app/Controller/IndividualController.php
+++ b/app/Controller/IndividualController.php
@@ -279,68 +279,72 @@ class IndividualController extends GedcomRecordController {
return null;
}
// edit menu
- $menu = new Menu(I18N::translate('Edit'), '#', 'menu-indi');
+ $menu = new Menu(I18N::translate('Edit'), '#', 'menu-indi', array(
+ 'onclick' => 'return false;',
+ ));
// What behaviour shall we give the main menu? If we leave it blank, the framework
// will copy the first submenu - which may be edit-raw or delete.
// As a temporary solution, make it edit the name
- $menu->setOnclick("return false;");
if (Auth::isEditor($this->record->getTree())) {
foreach ($this->record->getFacts() as $fact) {
if ($fact->getTag() === 'NAME' && $fact->canEdit()) {
- $menu->setOnclick("return edit_name('" . $this->record->getXref() . "', '" . $fact->getFactId() . "');");
+ $menu->setAttrs(array(
+ 'onclick' => 'return edit_name("' . $this->record->getXref() . '", "' . $fact->getFactId() . '");',
+ ));
break;
}
}
- $submenu = new Menu(I18N::translate('Add a new name'), '#', 'menu-indi-addname');
- $submenu->setOnclick("return add_name('" . $this->record->getXref() . "');");
- $menu->addSubmenu($submenu);
+ $menu->addSubmenu(new Menu(I18N::translate('Add a new name'), '#', 'menu-indi-addname', array(
+ 'onclick' => 'return add_name("' . $this->record->getXref() . '");',
+ )));
$has_sex_record = false;
- $submenu = new Menu(I18N::translate('Edit gender'), '#', 'menu-indi-editsex');
foreach ($this->record->getFacts() as $fact) {
- if ($fact->getTag() == 'SEX' && $fact->canEdit()) {
- $submenu->setOnclick("return edit_record('" . $this->record->getXref() . "', '" . $fact->getFactId() . "');");
+ if ($fact->getTag() === 'SEX' && $fact->canEdit()) {
+ $menu->addSubmenu(new Menu(I18N::translate('Edit gender'), '#', 'menu-indi-editsex', array(
+ 'onclick' => 'return edit_record("' . $this->record->getXref() . '", "' . $fact->getFactId() . '");',
+ )));
$has_sex_record = true;
break;
}
}
if (!$has_sex_record) {
- $submenu->setOnclick("return add_new_record('" . $this->record->getXref() . "', 'SEX');");
+ $menu->addSubmenu(new Menu(I18N::translate('Edit gender'), '#', 'menu-indi-editsex', array(
+ 'return add_new_record("' . $this->record->getXref() . '", "SEX");',
+ )));
}
- $menu->addSubmenu($submenu);
if (count($this->record->getSpouseFamilies()) > 1) {
- $submenu = new Menu(I18N::translate('Re-order families'), '#', 'menu-indi-orderfam');
- $submenu->setOnclick("return reorder_families('" . $this->record->getXref() . "');");
- $menu->addSubmenu($submenu);
+ $menu->addSubmenu(new Menu(I18N::translate('Re-order families'), '#', 'menu-indi-orderfam', array(
+ 'onclick' => 'return reorder_families("' . $this->record->getXref() . '");',
+ )));
}
}
// delete
if (Auth::isEditor($this->record->getTree())) {
- $submenu = new Menu(I18N::translate('Delete'), '#', 'menu-indi-del');
- $submenu->setOnclick("return delete_individual('" . I18N::translate('Are you sure you want to delete “%s”?', Filter::escapeJS(Filter::unescapeHtml($this->record->getFullName()))) . "', '" . $this->record->getXref() . "');");
- $menu->addSubmenu($submenu);
+ $menu->addSubmenu(new Menu(I18N::translate('Delete'), '#', 'menu-indi-del', array(
+ 'onclick' => 'return delete_individual("' . I18N::translate('Are you sure you want to delete “%s”?', Filter::escapeJS(Filter::unescapeHtml($this->record->getFullName()))) . '", "' . $this->record->getXref() . '");',
+ )));
}
// edit raw
if (Auth::isAdmin() || Auth::isEditor($this->record->getTree()) && $this->record->getTree()->getPreference('SHOW_GEDCOM_RECORD')) {
- $submenu = new Menu(I18N::translate('Edit raw GEDCOM'), '#', 'menu-indi-editraw');
- $submenu->setOnclick("return edit_raw('" . $this->record->getXref() . "');");
- $menu->addSubmenu($submenu);
+ $menu->addSubmenu(new Menu(I18N::translate('Edit raw GEDCOM'), '#', 'menu-indi-editraw', array(
+ 'onclick' => 'return edit_raw("' . $this->record->getXref() . '");',
+ )));
}
// add to favorites
if (Module::getModuleByName('user_favorites')) {
- $submenu = new Menu(
- /* I18N: Menu option. Add [the current page] to the list of favorites */ I18N::translate('Add to favorites'),
+ $menu->addSubmenu(new Menu(
+ /* I18N: Menu option. Add [the current page] to the list of favorites */ I18N::translate('Add to favorites'),
'#',
- 'menu-indi-addfav'
- );
- $submenu->setOnclick("jQuery.post('module.php?mod=user_favorites&mod_action=menu-add-favorite',{xref:'" . $this->record->getXref() . "'},function(){location.reload();})");
- $menu->addSubmenu($submenu);
+ 'menu-indi-addfav', array(
+ 'onclick' => 'jQuery.post("module.php?mod=user_favorites&mod_action=menu-add-favorite",{xref:"' . $this->record->getXref() . '"},function(){location.reload();})',
+ )));
}
return $menu;
diff --git a/app/Controller/MediaController.php b/app/Controller/MediaController.php
index 9fa31934bf..3dbda13666 100644
--- a/app/Controller/MediaController.php
+++ b/app/Controller/MediaController.php
@@ -52,61 +52,61 @@ class MediaController extends GedcomRecordController {
$menu = new Menu(I18N::translate('Edit'), '#', 'menu-obje');
if (Auth::isEditor($this->record->getTree())) {
- $submenu = new Menu(I18N::translate('Edit media object'), '#', 'menu-obje-edit');
- $submenu->setOnclick("window.open('addmedia.php?action=editmedia&pid={$this->record->getXref()}', '_blank', edit_window_specs)");
- $menu->addSubmenu($submenu);
+ $menu->addSubmenu(new Menu(I18N::translate('Edit media object'), '#', 'menu-obje-edit', array(
+ 'onclick' => 'window.open("addmedia.php?action=editmedia&pid=' . $this->record->getXref() . '", "_blank", edit_window_specs)',
+ )));
// main link displayed on page
if (Module::getModuleByName('GEDFact_assistant')) {
- $submenu = new Menu(I18N::translate('Manage links'), '#', 'menu-obje-link');
- $submenu->setOnclick("return ilinkitem('" . $this->record->getXref() . "','manage');");
- $menu->addSubmenu($submenu);
+ $menu->addSubmenu(new Menu(I18N::translate('Manage links'), '#', 'menu-obje-link', array(
+ 'onclick' => 'return ilinkitem("' . $this->record->getXref() . '","manage");',
+ )));
} else {
- $submenu = new Menu(I18N::translate('Link this media object to an individual'), '#', 'menu-obje-link-indi');
- $submenu->setOnclick("return ilinkitem('" . $this->record->getXref() . "','person');");
- $menu->addSubmenu($submenu);
+ $menu->addSubmenu(new Menu(I18N::translate('Link this media object to an individual'), '#', 'menu-obje-link-indi', array(
+ 'onclick' => 'return ilinkitem("' . $this->record->getXref() . '","person");',
+ )));
- $submenu = new Menu(I18N::translate('Link this media object to a family'), '#', 'menu-obje-link-fam');
- $submenu->setOnclick("return ilinkitem('" . $this->record->getXref() . "','family');");
- $menu->addSubmenu($submenu);
+ $menu->addSubmenu(new Menu(I18N::translate('Link this media object to a family'), '#', 'menu-obje-link-fam', array(
+ 'onclick' => 'return ilinkitem("' . $this->record->getXref() . '","family");',
+ )));
- $submenu = new Menu(I18N::translate('Link this media object to a source'), '#', 'menu-obje-link-sour');
- $submenu->setOnclick("return ilinkitem('" . $this->record->getXref() . "','source');");
- $menu->addSubmenu($submenu);
+ $menu->addSubmenu(new Menu(I18N::translate('Link this media object to a source'), '#', 'menu-obje-link-sour', array(
+ 'onclick' => 'return ilinkitem("' . $this->record->getXref() . '","source");',
+ )));
}
}
// delete
if (Auth::isEditor($this->record->getTree())) {
- $submenu = new Menu(I18N::translate('Delete'), '#', 'menu-obje-del');
- $submenu->setOnclick("return delete_media('" . I18N::translate('Are you sure you want to delete “%s”?', Filter::escapeJS(Filter::unescapeHtml($this->record->getFullName()))) . "', '" . $this->record->getXref() . "');");
- $menu->addSubmenu($submenu);
+ $menu->addSubmenu(new Menu(I18N::translate('Delete'), '#', 'menu-obje-del', array(
+ 'onlcick' => 'return delete_media("' . I18N::translate('Are you sure you want to delete “%s”?', Filter::escapeJS(Filter::unescapeHtml($this->record->getFullName()))) . '", "' . $this->record->getXref() . '");',
+ )));
}
// edit raw
if (Auth::isAdmin() || Auth::isEditor($this->record->getTree()) && $this->record->getTree()->getPreference('SHOW_GEDCOM_RECORD')) {
- $submenu = new Menu(I18N::translate('Edit raw GEDCOM'), '#', 'menu-obje-editraw');
- $submenu->setOnclick("return edit_raw('" . $this->record->getXref() . "');");
- $menu->addSubmenu($submenu);
+ $menu->addSubmenu(new Menu(I18N::translate('Edit raw GEDCOM'), '#', 'menu-obje-editraw', array(
+ 'onclick' => 'return edit_raw("' . $this->record->getXref() . '");',
+ )));
}
// add to favorites
if (Module::getModuleByName('user_favorites')) {
- $submenu = new Menu(
+ $menu->addSubmenu(new Menu(
/* I18N: Menu option. Add [the current page] to the list of favorites */
I18N::translate('Add to favorites'),
'#',
- 'menu-obje-addfav'
- );
- $submenu->setOnclick("jQuery.post('module.php?mod=user_favorites&mod_action=menu-add-favorite',{xref:'" . $this->record->getXref() . "'},function(){location.reload();})");
- $menu->addSubmenu($submenu);
+ 'menu-obje-addfav',
+ array(
+ 'onclick' => 'jQuery.post("module.php?mod=user_favorites&mod_action=menu-add-favorite",{xref:"' . $this->record->getXref() . '"},function(){location.reload();})',
+ )));
}
// Get the link for the first submenu and set it as the link for the main menu
if ($menu->getSubmenus()) {
$submenus = $menu->getSubmenus();
$menu->setLink($submenus[0]->getLink());
- $menu->setOnClick($submenus[0]->getOnClick());
+ $menu->setAttrs($submenus[0]->getAttrs());
}
return $menu;
@@ -146,13 +146,23 @@ class MediaController extends GedcomRecordController {
public static function getMediaListMenu(Media $mediaobject) {
$html = '';
- $menu = new Menu(I18N::translate('Edit details'), '#', 'lb-image_edit', "return window.open('addmedia.php?action=editmedia&pid=" . $mediaobject->getXref() . "', '_blank', edit_window_specs);");
+ $menu = new Menu(I18N::translate('Edit details'), '#', 'lb-image_edit', array(
+ 'onclick' => 'return window.open("addmedia.php?action=editmedia&pid=' . $mediaobject->getXref() . '", "_blank", edit_window_specs);',
+ ));
$html .= '<ul class="makeMenu lb-menu">' . $menu->getMenuAsList() . '</ul>';
- $menu = new Menu(I18N::translate('Manage links'), '#', 'lb-image_link', "return ilinkitem('" . $mediaobject->getXref() . "','person')", array(
- new Menu(I18N::translate('Link this media object to an individual'), '#', '', "return ilinkitem('" . $mediaobject->getXref() . "','person')"),
- new Menu(I18N::translate('Link this media object to a family'), '#', '', "return ilinkitem('" . $mediaobject->getXref() . "','family')"),
- new Menu(I18N::translate('Link this media object to a source'), '#', '', "return ilinkitem('" . $mediaobject->getXref() . "','source')"),
+ $menu = new Menu(I18N::translate('Manage links'), '#', 'lb-image_link', array(
+ 'onclick' => 'return false;',
+ ), array(
+ new Menu(I18N::translate('Link this media object to an individual'), '#', '', array(
+ 'onclick' => 'return ilinkitem("' . $mediaobject->getXref() . '","person");',
+ )),
+ new Menu(I18N::translate('Link this media object to a family'), '#', '', array(
+ 'onclick' => 'return ilinkitem("' . $mediaobject->getXref() . '","family");',
+ )),
+ new Menu(I18N::translate('Link this media object to a source'), '#', '', array(
+ 'onclick' => 'return ilinkitem("' . $mediaobject->getXref() . '","source");',
+ )),
));
$html .= '<ul class="makeMenu lb-menu">' . $menu->getMenuAsList() . '</ul>';
diff --git a/app/Controller/NoteController.php b/app/Controller/NoteController.php
index f314a7bcaf..3bb19b6954 100644
--- a/app/Controller/NoteController.php
+++ b/app/Controller/NoteController.php
@@ -50,34 +50,34 @@ class NoteController extends GedcomRecordController {
$menu = new Menu(I18N::translate('Edit'), '#', 'menu-note');
if (Auth::isEditor($this->record->getTree())) {
- $submenu = new Menu(I18N::translate('Edit note'), '#', 'menu-note-edit');
- $submenu->setOnclick('return edit_note(\'' . $this->record->getXref() . '\');');
- $menu->addSubmenu($submenu);
+ $menu->addSubmenu(new Menu(I18N::translate('Edit note'), '#', 'menu-note-edit', array(
+ 'onclick' => 'return edit_note("' . $this->record->getXref() . '");',
+ )));
}
// delete
if (Auth::isEditor($this->record->getTree())) {
- $submenu = new Menu(I18N::translate('Delete'), '#', 'menu-note-del');
- $submenu->setOnclick("return delete_note('" . I18N::translate('Are you sure you want to delete “%s”?', Filter::escapeJS(Filter::unescapeHtml($this->record->getFullName()))) . "', '" . $this->record->getXref() . "');");
- $menu->addSubmenu($submenu);
+ $menu->addSubmenu(new Menu(I18N::translate('Delete'), '#', 'menu-note-del', array(
+ 'onclick' => 'return delete_note("' . I18N::translate('Are you sure you want to delete “%s”?', Filter::escapeJS(Filter::unescapeHtml($this->record->getFullName()))) . '", "' . $this->record->getXref() . '");',
+ )));
}
// add to favorites
if (Module::getModuleByName('user_favorites')) {
- $submenu = new Menu(
- /* I18N: Menu option. Add [the current page] to the list of favorites */ I18N::translate('Add to favorites'),
+ $menu->addSubmenu(new Menu(
+ /* I18N: Menu option. Add [the current page] to the list of favorites */ I18N::translate('Add to favorites'),
'#',
- 'menu-note-addfav'
- );
- $submenu->setOnclick("jQuery.post('module.php?mod=user_favorites&amp;mod_action=menu-add-favorite',{xref:'" . $this->record->getXref() . "'},function(){location.reload();})");
- $menu->addSubmenu($submenu);
+ 'menu-note-addfav',
+ array(
+ 'onclick' => 'jQuery.post("module.php?mod=user_favorites&mod_action=menu-add-favorite",{xref:"' . $this->record->getXref() . '"},function(){location.reload();})',
+ )));
}
// Get the link for the first submenu and set it as the link for the main menu
if ($menu->getSubmenus()) {
$submenus = $menu->getSubmenus();
$menu->setLink($submenus[0]->getLink());
- $menu->setOnClick($submenus[0]->getOnClick());
+ $menu->setAttrs($submenus[0]->getAttrs());
}
return $menu;
diff --git a/app/Controller/RepositoryController.php b/app/Controller/RepositoryController.php
index 820e6a8e9d..802c4da6a8 100644
--- a/app/Controller/RepositoryController.php
+++ b/app/Controller/RepositoryController.php
@@ -51,47 +51,49 @@ class RepositoryController extends GedcomRecordController {
if (Auth::isEditor($this->record->getTree())) {
$fact = $this->record->getFirstFact('NAME');
- $submenu = new Menu(I18N::translate('Edit repository'), '#', 'menu-repo-edit');
if ($fact) {
// Edit existing name
- $submenu->setOnclick('return edit_record(\'' . $this->record->getXref() . '\', \'' . $fact->getFactId() . '\');');
+ $menu->addSubmenu(new Menu(I18N::translate('Edit repository'), '#', 'menu-repo-edit', array(
+ 'onclick' => 'return edit_record("' . $this->record->getXref() . '", "' . $fact->getFactId() . '");',
+ )));
} else {
// Add new name
- $submenu->setOnclick('return add_fact(\'' . $this->record->getXref() . '\', \'NAME\');');
+ $menu->addSubmenu(new Menu(I18N::translate('Edit repository'), '#', 'menu-repo-edit', array(
+ 'onclick' => 'return add_fact("' . $this->record->getXref() . '", "NAME");',
+ )));
}
- $menu->addSubmenu($submenu);
}
// delete
if (Auth::isEditor($this->record->getTree())) {
- $submenu = new Menu(I18N::translate('Delete'), '#', 'menu-repo-del');
- $submenu->setOnclick("return delete_repository('" . I18N::translate('Are you sure you want to delete “%s”?', Filter::escapeJS(Filter::unescapeHtml($this->record->getFullName()))) . "', '" . $this->record->getXref() . "');");
- $menu->addSubmenu($submenu);
+ $menu->addSubmenu(new Menu(I18N::translate('Delete'), '#', 'menu-repo-del', array(
+ 'onclick' => 'return delete_repository("' . I18N::translate('Are you sure you want to delete “%s”?', Filter::escapeJS(Filter::unescapeHtml($this->record->getFullName()))) . '", "' . $this->record->getXref() . '");',
+ )));
}
// edit raw
if (Auth::isAdmin() || Auth::isEditor($this->record->getTree()) && $this->record->getTree()->getPreference('SHOW_GEDCOM_RECORD')) {
- $submenu = new Menu(I18N::translate('Edit raw GEDCOM'), '#', 'menu-repo-editraw');
- $submenu->setOnclick("return edit_raw('" . $this->record->getXref() . "');");
- $menu->addSubmenu($submenu);
+ $menu->addSubmenu(new Menu(I18N::translate('Edit raw GEDCOM'), '#', 'menu-repo-editraw', array(
+ 'onclick' => 'return edit_raw("' . $this->record->getXref() . '");',
+ )));
}
// add to favorites
if (Module::getModuleByName('user_favorites')) {
- $submenu = new Menu(
- /* I18N: Menu option. Add [the current page] to the list of favorites */ I18N::translate('Add to favorites'),
+ $menu->addSubmenu(new Menu(
+ /* I18N: Menu option. Add [the current page] to the list of favorites */ I18N::translate('Add to favorites'),
'#',
- 'menu-repo-addfav'
- );
- $submenu->setOnclick("jQuery.post('module.php?mod=user_favorites&amp;mod_action=menu-add-favorite',{xref:'" . $this->record->getXref() . "'},function(){location.reload();})");
- $menu->addSubmenu($submenu);
+ 'menu-repo-addfav',
+ array(
+ 'onclick' => 'jQuery.post("module.php?mod=user_favorites&mod_action=menu-add-favorite" ,{xref:"' . $this->record->getXref() . '"},function(){location.reload();})',
+ )));
}
// Get the link for the first submenu and set it as the link for the main menu
if ($menu->getSubmenus()) {
$submenus = $menu->getSubmenus();
$menu->setLink($submenus[0]->getLink());
- $menu->setOnClick($submenus[0]->getOnClick());
+ $menu->setAttrs($submenus[0]->getAttrs());
}
return $menu;
diff --git a/app/Controller/SourceController.php b/app/Controller/SourceController.php
index 5f7c794f4d..2d81723f24 100644
--- a/app/Controller/SourceController.php
+++ b/app/Controller/SourceController.php
@@ -50,48 +50,50 @@ class SourceController extends GedcomRecordController {
$menu = new Menu(I18N::translate('Edit'), '#', 'menu-sour');
if (Auth::isEditor($this->record->getTree())) {
- $fact = $this->record->getFirstFact('TITL');
- $submenu = new Menu(I18N::translate('Edit source'), '#', 'menu-sour-edit');
+ $fact = $this->record->getFirstFact('TITL');
if ($fact) {
// Edit existing name
- $submenu->setOnclick('return edit_record(\'' . $this->record->getXref() . '\', \'' . $fact->getFactId() . '\');');
+ $menu->addSubmenu(new Menu(I18N::translate('Edit source'), '#', 'menu-sour-edit', array(
+ 'onclick' => 'return edit_record("' . $this->record->getXref() . '", "' . $fact->getFactId() . '");',
+ )));
} else {
// Add new name
- $submenu->setOnclick('return add_fact(\'' . $this->record->getXref() . '\', \'TITL\');');
+ $menu->addSubmenu(new Menu(I18N::translate('Edit source'), '#', 'menu-sour-edit', array(
+ 'onclick' => 'return add_fact("' . $this->record->getXref() . '", "TITL");',
+ )));
}
- $menu->addSubmenu($submenu);
}
// delete
if (Auth::isEditor($this->record->getTree())) {
- $submenu = new Menu(I18N::translate('Delete'), '#', 'menu-sour-del');
- $submenu->setOnclick("return delete_source('" . I18N::translate('Are you sure you want to delete “%s”?', Filter::escapeJS(Filter::unescapeHtml($this->record->getFullName()))) . "', '" . $this->record->getXref() . "');");
- $menu->addSubmenu($submenu);
+ $menu->addSubmenu(new Menu(I18N::translate('Delete'), '#', 'menu-sour-del', array(
+ 'onclick' => "return delete_source('" . I18N::translate('Are you sure you want to delete “%s”?', Filter::escapeJS(Filter::unescapeHtml($this->record->getFullName()))) . "', '" . $this->record->getXref() . "');",
+ )));
}
// edit raw
if (Auth::isAdmin() || Auth::isEditor($this->record->getTree()) && $this->record->getTree()->getPreference('SHOW_GEDCOM_RECORD')) {
- $submenu = new Menu(I18N::translate('Edit raw GEDCOM'), '#', 'menu-sour-editraw');
- $submenu->setOnclick("return edit_raw('" . $this->record->getXref() . "');");
- $menu->addSubmenu($submenu);
+ $menu->addSubmenu(new Menu(I18N::translate('Edit raw GEDCOM'), '#', 'menu-sour-editraw', array(
+ 'onclick' => 'return edit_raw("' . $this->record->getXref() . '");',
+ )));
}
// add to favorites
if (Module::getModuleByName('user_favorites')) {
- $submenu = new Menu(
- /* I18N: Menu option. Add [the current page] to the list of favorites */ I18N::translate('Add to favorites'),
+ $menu->addSubmenu(new Menu(
+ /* I18N: Menu option. Add [the current page] to the list of favorites */ I18N::translate('Add to favorites'),
'#',
- 'menu-sour-addfav'
- );
- $submenu->setOnclick("jQuery.post('module.php?mod=user_favorites&amp;mod_action=menu-add-favorite',{xref:'" . $this->record->getXref() . "'},function(){location.reload();})");
- $menu->addSubmenu($submenu);
+ 'menu-sour-addfav',
+ array(
+ 'onlick' => 'jQuery.post("module.php?mod=user_favorites&amp;mod_action=menu-add-favorite",{xref:"' . $this->record->getXref() . '"},function(){location.reload();})',
+ )));
}
// Get the link for the first submenu and set it as the link for the main menu
if ($menu->getSubmenus()) {
$submenus = $menu->getSubmenus();
$menu->setLink($submenus[0]->getLink());
- $menu->setOnClick($submenus[0]->getOnClick());
+ $menu->setAttrs($submenus[0]->getAttrs());
}
return $menu;
diff --git a/app/Menu.php b/app/Menu.php
index bd64c31be1..a4790a4a66 100644
--- a/app/Menu.php
+++ b/app/Menu.php
@@ -30,8 +30,8 @@ class Menu {
/** @var string The CSS class used to style this menu item */
private $class;
- /** @var string An onclick action, typically used with a link of "#" */
- private $onclick;
+ /** @var string[] A list of optional HTML attributes, such as onclick or data-xxx */
+ private $attrs;
/** @var Menu[] An optional list of sub-menus. */
private $submenus;
@@ -48,18 +48,18 @@ class Menu {
/**
* Constructor for the menu class
*
- * @param string $label The label for the menu item
- * @param string $link The target URL
- * @param string $class An CSS class
- * @param string $onclick A javascript onclick handler
- * @param Menu[] $submenus Any submenus
+ * @param string $label The label for the menu item
+ * @param string $link The target URL
+ * @param string $class A CSS class
+ * @param string[] $attrs Optional attributes, such as onclick or data-xxx
+ * @param Menu[] $submenus Any submenus
*/
- public function __construct($label, $link = '#', $class = '', $onclick = '', $submenus = array()) {
+ public function __construct($label, $link = '#', $class = '', array $attrs = array(), array $submenus = array()) {
$this
->setLabel($label)
->setLink($link)
->setClass($class)
- ->setOnclick($onclick)
+ ->setAttrs($attrs)
->setSubmenus($submenus);
}
@@ -95,17 +95,38 @@ class Menu {
'</ul>' .
'</li>';
} else {
- if ($this->onclick) {
- $onclick = ' onclick="' . $this->onclick . '"';
- } else {
- $onclick = '';
+ $attrs = '';
+ foreach ($this->attrs as $key => $value) {
+ $attrs .= ' ' . $key . '="' . Filter::escapeHtml($value) . '"';
}
- return '<li class="' . $this->class . '"><a href="' . $this->link . '"' . $onclick . '>' . $this->label . '</a></li>';
+ return '<li class="' . $this->class . '"><a href="' . $this->link . '"' . $attrs . '>' . $this->label . '</a></li>';
}
}
/**
+ * Get the optional attributes.
+ *
+ * @return string[]
+ */
+ public function getAttrs() {
+ return $this->attrs;
+ }
+
+ /**
+ * Set the optional attributes.
+ *
+ * @param string[] $attrs
+ *
+ * @return $this
+ */
+ public function setAttrs(array $attrs) {
+ $this->attrs = $attrs;
+
+ return $this;
+ }
+
+ /**
* Set the CSS classes for the (legacy) javascript menus
*
* @param string $menuclass
@@ -162,6 +183,7 @@ class Menu {
/**
* Get the link.
+ *
* @return string
*/
public function getLink() {
@@ -182,28 +204,6 @@ class Menu {
}
/**
- * Get the click handler.
- *
- * @return string
- */
- public function getOnclick() {
- return $this->onclick;
- }
-
- /**
- * Set the click handler.
- *
- * @param string $onclick
- *
- * @return $this
- */
- public function setOnclick($onclick) {
- $this->onclick = $onclick;
-
- return $this;
- }
-
- /**
* Add a submenu to this menu
*
* @param Menu $menu
@@ -226,8 +226,8 @@ class Menu {
$sub_menu_id = 'sub-' . $menu_id;
$html = '<a href="' . $this->link . '"';
- if ($this->onclick) {
- $html .= ' onclick="' . $this->onclick . '"';
+ foreach ($this->attrs as $key => $value) {
+ $html .= ' ' . $key . '="' . Filter::escapeHtml($value) . '"';
}
if (!empty($this->submenus)) {
$html .= ' onmouseover="show_submenu(\'' . $sub_menu_id . '\', \'' . $menu_id . '\');"';
@@ -256,17 +256,16 @@ class Menu {
* @return string
*/
public function getMenuAsList() {
- if ($this->onclick) {
- $onclick = ' onclick="' . $this->onclick . '"';
- } else {
- $onclick = '';
+ $attrs = '';
+ foreach ($this->attrs as $key => $value) {
+ $attrs .= ' ' . $key . '="' . Filter::escapeHtml($value) . '"';
}
if ($this->link) {
$link = ' href="' . $this->link . '"';
} else {
$link = '';
}
- $html = '<a' . $link . $onclick . '>' . $this->label . '</a>';
+ $html = '<a' . $link . $attrs . '>' . $this->label . '</a>';
if ($this->submenus) {
$html .= '<ul>';
foreach ($this->submenus as $submenu) {
diff --git a/app/Module/AbstractModule.php b/app/Module/AbstractModule.php
index 4d05479b5f..9edea5d7d0 100644
--- a/app/Module/AbstractModule.php
+++ b/app/Module/AbstractModule.php
@@ -44,7 +44,7 @@ abstract class AbstractModule {
/**
* Get a block setting.
- *
+ *
* @param int $block_id
* @param string $setting_name
* @param string|null $default_value
diff --git a/app/Module/AlbumModule.php b/app/Module/AlbumModule.php
index 4beb7e3f95..d08bfa981e 100644
--- a/app/Module/AlbumModule.php
+++ b/app/Module/AlbumModule.php
@@ -133,7 +133,9 @@ class AlbumModule extends AbstractModule implements ModuleTabInterface {
// View Notes
if (strpos($media->getGedcom(), "\n1 NOTE")) {
- $submenu = new Menu(I18N::translate('View notes'), '#', '', "modalNotes('" . Filter::escapeJs($notes) . "','" . I18N::translate('View notes') . "'); return false;");
+ $submenu = new Menu(I18N::translate('View notes'), '#', '', array(
+ 'onclick' => 'modalNotes("' . Filter::escapeJs($notes) . '","' . I18N::translate('View notes') . '"); return false;',
+ ));
$submenu->addClass("submenuitem");
$menu->addSubmenu($submenu);
}
@@ -154,28 +156,40 @@ class AlbumModule extends AbstractModule implements ModuleTabInterface {
if (Auth::isEditor($media->getTree())) {
// Edit Media
- $submenu = new Menu(I18N::translate('Edit media'), '#', '', "return window.open('addmedia.php?action=editmedia&amp;pid=" . $media->getXref() . "', '_blank', edit_window_specs);");
+ $submenu = new Menu(I18N::translate('Edit media'), '#', '', array(
+ 'onclick' => 'return window.open("addmedia.php?action=editmedia&pid=' . $media->getXref() . '", "_blank", edit_window_specs);',
+ ));
$submenu->addClass("submenuitem");
$menu->addSubmenu($submenu);
if (Auth::isAdmin()) {
if (Module::getModuleByName('GEDFact_assistant')) {
- $submenu = new Menu(I18N::translate('Manage links'), '#', '', "return window.open('inverselink.php?mediaid=" . $media->getXref() . "&amp;linkto=manage', '_blank', find_window_specs);");
+ $submenu = new Menu(I18N::translate('Manage links'), '#', '', array(
+ 'onclick' => 'return window.open("inverselink.php?mediaid=' . $media->getXref() . '&linkto=manage", "_blank", find_window_specs);',
+ ));
$submenu->addClass("submenuitem");
$menu->addSubmenu($submenu);
} else {
- $submenu = new Menu(I18N::translate('Link this media object to an individual'), '#', 'menu-obje-link-indi', "return ilinkitem('" . $media->getXref() . "','person');");
+ $submenu = new Menu(I18N::translate('Link this media object to an individual'), '#', 'menu-obje-link-indi', array(
+ 'onclick' => 'return ilinkitem("' . $media->getXref() . '","person");',
+ ));
$submenu->addClass('submenuitem');
$menu->addSubmenu($submenu);
- $submenu = new Menu(I18N::translate('Link this media object to a family'), '#', 'menu-obje-link-fam', "return ilinkitem('" . $media->getXref() . "','family');");
+ $submenu = new Menu(I18N::translate('Link this media object to a family'), '#', 'menu-obje-link-fam', array(
+ 'onclick' => 'return ilinkitem("' . $media->getXref() . '","family");',
+ ));
$submenu->addClass('submenuitem');
$menu->addSubmenu($submenu);
- $submenu = new Menu(I18N::translate('Link this media object to a source'), '#', 'menu-obje-link-sour', "return ilinkitem('" . $media->getXref() . "','source');");
+ $submenu = new Menu(I18N::translate('Link this media object to a source'), '#', 'menu-obje-link-sour', array(
+ 'onclick' => 'return ilinkitem("' . $media->getXref() . '","source");',
+ ));
$submenu->addClass('submenuitem');
$menu->addSubmenu($submenu);
}
- $submenu = new Menu(I18N::translate('Unlink media'), '#', '', "return unlink_media('" . I18N::translate('Are you sure you want to remove links to this media object?') . "', '" . $controller->record->getXref() . "', '" . $media->getXref() . "');");
+ $submenu = new Menu(I18N::translate('Unlink media'), '#', '', array(
+ 'onclick' => 'return unlink_media("' . I18N::translate('Are you sure you want to remove links to this media object?') . '", "' . $controller->record->getXref() . '", "' . $media->getXref() . '");',
+ ));
$submenu->addClass("submenuitem");
$menu->addSubmenu($submenu);
}
diff --git a/app/Module/GoogleMapsModule.php b/app/Module/GoogleMapsModule.php
index c044851f06..ce9df582e6 100644
--- a/app/Module/GoogleMapsModule.php
+++ b/app/Module/GoogleMapsModule.php
@@ -515,7 +515,6 @@ class GoogleMapsModule extends AbstractModule implements ModuleConfigInterface,
/**
* Select a flag.
- *
*/
private function flags() {
global $WT_TREE;
diff --git a/app/Module/InteractiveTreeModule.php b/app/Module/InteractiveTreeModule.php
index 8cb5450e01..bd0dfac167 100644
--- a/app/Module/InteractiveTreeModule.php
+++ b/app/Module/InteractiveTreeModule.php
@@ -150,6 +150,7 @@ class InteractiveTreeModule extends AbstractModule implements ModuleTabInterface
/**
* URL for our style sheet.
+ *
* @return string
*/
public function css() {
diff --git a/app/Report/ReportBaseFootnote.php b/app/Report/ReportBaseFootnote.php
index 61736ffbec..f6732206a4 100644
--- a/app/Report/ReportBaseFootnote.php
+++ b/app/Report/ReportBaseFootnote.php
@@ -123,7 +123,7 @@ class ReportBaseFootnote extends ReportBaseElement {
/**
* Add a link.
- *
+ *
* @param $a
*
* @return int
diff --git a/app/Report/ReportHtml.php b/app/Report/ReportHtml.php
index 47ab83efcf..994c368c0c 100644
--- a/app/Report/ReportHtml.php
+++ b/app/Report/ReportHtml.php
@@ -418,6 +418,7 @@ class ReportHtml extends ReportBase {
/**
* Create an HTML element.
+ *
* @param $tag
* @param $attrs
*
diff --git a/app/Stats.php b/app/Stats.php
index e73b08c463..c2568509a0 100644
--- a/app/Stats.php
+++ b/app/Stats.php
@@ -2084,6 +2084,7 @@ class Stats {
/**
* Find the earliest birth place.
+ *
* @return string
*/
public function firstBirthPlace() {
@@ -2092,6 +2093,7 @@ class Stats {
/**
* Find the latest birth.
+ *
* @return string
*/
public function lastBirth() {
@@ -2201,6 +2203,7 @@ class Stats {
/**
* Find the place of the latest death.
+ *
* @return string
*/
public function lastDeathPlace() {
@@ -2837,6 +2840,7 @@ class Stats {
/**
* Find the name of the longest lived male.
+ *
* @return string
*/
public function longestLifeMaleName() {
@@ -2856,6 +2860,7 @@ class Stats {
/**
* Find the longest lived males.
+ *
* @param string[] $params
*
* @return string
@@ -2866,6 +2871,7 @@ class Stats {
/**
* Find the longest lived living males.
+ *
* @param string[] $params
*
* @return string
@@ -2997,6 +3003,7 @@ class Stats {
/**
* Find the type of the earliest event.
+ *
* @return string
*/
public function firstEventType() {
@@ -3005,6 +3012,7 @@ class Stats {
/**
* Find the name of the individual with the earliest event.
+ *
* @return string
*/
public function firstEventName() {
@@ -3013,6 +3021,7 @@ class Stats {
/**
* Find the location of the earliest event.
+ *
* @return string
*/
public function firstEventPlace() {
@@ -3039,6 +3048,7 @@ class Stats {
/**
* Find the type of the latest event.
+ *
* @return string
*/
public function lastEventType() {
@@ -3047,6 +3057,7 @@ class Stats {
/**
* Find the name of the individual with the latest event.
+ *
* @return string
*/
public function lastEventName() {
@@ -3055,6 +3066,7 @@ class Stats {
/**
* FInd the location of the latest event.
+ *
* @return string
*/
public function lastEventPlace() {
@@ -3690,6 +3702,7 @@ class Stats {
/**
* Find the names of spouses of the latest marriage.
+ *
* @return string
*/
public function lastMarriageName() {
@@ -3698,6 +3711,7 @@ class Stats {
/**
* Find the location of the latest marriage.
+ *
* @return string
*/
public function lastMarriagePlace() {
@@ -6048,6 +6062,7 @@ class Stats {
/**
* Get the current user's ID.
+ *
* @return null|string
*/
public function userId() {
@@ -6215,6 +6230,7 @@ class Stats {
/**
* Create a link to contact the genealogy contact.
+ *
* @return string
*/
public function contactGedcom() {
@@ -6247,6 +6263,7 @@ class Stats {
/**
* What is the current time on the server (in 24 hour clock)?
+ *
* @return string
*/
public function serverTime24() {
@@ -6282,6 +6299,7 @@ class Stats {
/**
* What is the browser's tiemzone.
+ *
* @return string
*/
public function browserTimezone() {
diff --git a/app/Theme/AbstractTheme.php b/app/Theme/AbstractTheme.php
index 816da2ac3a..c91c5f1194 100644
--- a/app/Theme/AbstractTheme.php
+++ b/app/Theme/AbstractTheme.php
@@ -1302,19 +1302,16 @@ abstract class AbstractTheme {
case 'NOTE':
$obj = GedcomRecord::getInstance($favorite['gid'], $this->tree);
if ($obj && $obj->canShowName()) {
- $submenu = new Menu($obj->getFullName(), $obj->getHtmlUrl());
- $menu->addSubmenu($submenu);
+ $menu->addSubmenu(new Menu($obj->getFullName(), $obj->getHtmlUrl()));
}
break;
}
}
- if ($show_user_favorites) {
- if (isset($controller->record) && $controller->record instanceof GedcomRecord) {
- $submenu = new Menu(I18N::translate('Add to favorites'), '#');
- $submenu->setOnclick("jQuery.post('module.php?mod=user_favorites&amp;mod_action=menu-add-favorite',{xref:'" . $controller->record->getXref() . "'},function(){location.reload();})");
- $menu->addSubmenu($submenu);
- }
+ if ($show_user_favorites && isset($controller->record) && $controller->record instanceof GedcomRecord) {
+ $menu->addSubmenu(new Menu(I18N::translate('Add to favorites'), '#', '', array(
+ 'onclick' => 'jQuery.post("module.php?mod=user_favorites&mod_action=menu-add-favorite", {xref:"' . $controller->record->getXref() . '"},function(){location.reload();})',
+ )));
}
return $menu;
@@ -1346,7 +1343,7 @@ abstract class AbstractTheme {
$label = I18N::translate('Family trees');
}
- return new Menu($label, 'index.php?ctype=gedcom&amp;' . $this->tree_url, 'menu-tree', null, $submenus);
+ return new Menu($label, 'index.php?ctype=gedcom&amp;' . $this->tree_url, 'menu-tree', array(), $submenus);
}
/**
@@ -1593,7 +1590,7 @@ abstract class AbstractTheme {
*/
protected function menuMyPages() {
if (Auth::id()) {
- return new Menu(I18N::translate('My pages'), '#', 'menu-mymenu', null, array_filter(array(
+ return new Menu(I18N::translate('My pages'), '#', 'menu-mymenu', array(), array_filter(array(
$this->menuMyPage(),
$this->menuMyIndividualRecord(),
$this->menuMyPedigree(),
@@ -1635,8 +1632,7 @@ abstract class AbstractTheme {
*/
protected function menuPendingChanges() {
if ($this->pendingChangesExist()) {
- $menu = new Menu(I18N::translate('Pending changes'), '#', 'menu-pending');
- $menu->setOnclick('window.open(\'edit_changes.php\', \'_blank\', chan_window_specs); return false;');
+ $menu = new Menu(I18N::translate('Pending changes'), '#', 'menu-pending', array('onclick' => 'window.open("edit_changes.php", "_blank", chan_window_specs); return false;'));
return $menu;
} else {
@@ -1658,7 +1654,7 @@ abstract class AbstractTheme {
}
if ($submenus) {
- return new Menu(I18N::translate('Reports'), 'reportengine.php?' . $this->tree_url, 'menu-report', null, $submenus);
+ return new Menu(I18N::translate('Reports'), 'reportengine.php?' . $this->tree_url, 'menu-report', array(), $submenus);
} else {
return null;
}
@@ -1715,7 +1711,7 @@ abstract class AbstractTheme {
return I18N::strcasecmp($x->getLabel(), $y->getLabel());
});
- $menu = new Menu(I18N::translate('Theme'), '#', 'menu-theme', '', $submenus);
+ $menu = new Menu(I18N::translate('Theme'), '#', 'menu-theme', array(), $submenus);
return $menu;
} else {
diff --git a/app/Theme/AdministrationTheme.php b/app/Theme/AdministrationTheme.php
index c017857d94..f77dcf5610 100644
--- a/app/Theme/AdministrationTheme.php
+++ b/app/Theme/AdministrationTheme.php
@@ -103,7 +103,7 @@ class AdministrationTheme extends AbstractTheme implements ThemeInterface {
* @return Menu
*/
protected function menuAdminTrees() {
- return new Menu(/* I18N: Menu entry */ I18N::translate('Family trees'), '#', '', '', array_filter(array(
+ return new Menu(/* I18N: Menu entry */ I18N::translate('Family trees'), '#', '', array(), array_filter(array(
$this->menuAdminTreesManage(),
$this->menuAdminTreesSetDefault(),
$this->menuAdminTreesMerge(),
@@ -151,7 +151,7 @@ class AdministrationTheme extends AbstractTheme implements ThemeInterface {
* @return Menu
*/
protected function menuAdminUsers() {
- return new Menu(/* I18N: Menu entry */ I18N::translate('Users'), '#', '', '', array(
+ return new Menu(/* I18N: Menu entry */ I18N::translate('Users'), '#', '', array(), array(
new Menu(/* I18N: Menu entry */ I18N::translate('User administration'), 'admin_users.php'),
new Menu(/* I18N: Menu entry */ I18N::translate('Add a new user'), 'admin_users.php?action=edit'),
new Menu(/* I18N: Menu entry */ I18N::translate('Send broadcast messages'), 'admin_users_bulk.php'),
@@ -166,7 +166,7 @@ class AdministrationTheme extends AbstractTheme implements ThemeInterface {
* @return Menu
*/
protected function menuAdminMedia() {
- return new Menu(/* I18N: Menu entry */ I18N::translate('Media'), '#', '', '', array(
+ return new Menu(/* I18N: Menu entry */ I18N::translate('Media'), '#', '', array(), array(
new Menu(/* I18N: Menu entry */ I18N::translate('Manage media'), 'admin_media.php'),
new Menu(/* I18N: Menu entry */ I18N::translate('Upload media files'), 'admin_media_upload.php'),
));
@@ -178,7 +178,7 @@ class AdministrationTheme extends AbstractTheme implements ThemeInterface {
* @return Menu
*/
protected function menuAdminModules() {
- return new Menu(/* I18N: Menu entry */ I18N::translate('Modules'), '#', '', '', array(
+ return new Menu(/* I18N: Menu entry */ I18N::translate('Modules'), '#', '', array(), array(
new Menu(/* I18N: Menu entry */ I18N::translate('Module administration'), 'admin_modules.php'),
new Menu(/* I18N: Menu entry */ I18N::translate('Menus'), 'admin_module_menus.php'),
new Menu(/* I18N: Menu entry */ I18N::translate('Tabs'), 'admin_module_tabs.php'),