Index: /extensions/linked_pages/admin.php
===================================================================
--- /extensions/linked_pages/admin.php	(revision 17882)
+++ /extensions/linked_pages/admin.php	(revision 17882)
@@ -0,0 +1,151 @@
+<?php
+if(!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
+ 
+global $template, $page, $conf;
+
+if (strpos($_GET['tab'], 'album-') !== false)
+{
+  $_GET['cat_id'] = substr($_GET['tab'], 6);
+}
+else
+{
+  die('Hacking attempt!');
+}
+
+// +-----------------------------------------------------------------------+
+// | Basic checks                                                          |
+// +-----------------------------------------------------------------------+
+check_status(ACCESS_ADMINISTRATOR);
+
+check_input_parameter('cat_id', $_GET, false, PATTERN_ID);
+
+$admin_album_base_url = get_root_url().'admin.php?page=album-'.$_GET['cat_id'];
+$self_url = LINKEDPAGES_ADMIN.'-album-'.$_GET['cat_id'];
+
+
+// +-----------------------------------------------------------------------+
+// | Init                                                                  |
+// +-----------------------------------------------------------------------+
+$query = '
+SELECT *
+  FROM '.CATEGORIES_TABLE.'
+  WHERE id = '.$_GET['cat_id'].'
+;';
+$category = pwg_db_fetch_assoc(pwg_query($query));
+
+if (!isset($category['id']))
+{
+  die("unknown album");
+}
+
+include_once(PHPWG_ROOT_PATH.'admin/include/tabsheet.class.php');
+$tabsheet = new tabsheet();
+$tabsheet->set_id('album');
+$tabsheet->select('linked_pages');
+$tabsheet->assign();
+
+load_language('plugin.lang', AP_PATH);
+$languages = get_languages();
+
+
+// +-----------------------------------------------------------------------+
+// | Save pages                                                            |
+// +-----------------------------------------------------------------------+
+if (isset($_POST['save_pages']))
+{
+  $query = '
+DELETE FROM '.LINKEDPAGES_TABLE.'
+  WHERE category_id = '.$_GET['cat_id'].'
+;';
+  pwg_query($query);
+  
+  if (isset($_POST['position']))
+  {
+    $inserts = array();
+    foreach ($_POST['position'] as $page_id => $pos)
+    {
+      array_push($inserts, array(
+        'category_id' => $_GET['cat_id'],
+        'page_id' => $page_id,
+        'pos' => $pos,
+        ));
+    }
+    
+    mass_inserts_ignore(
+      LINKEDPAGES_TABLE, 
+      array('category_id','page_id','pos'), 
+      $inserts
+      );
+  }
+}
+
+// +-----------------------------------------------------------------------+
+// | Get pages                                                             |
+// +-----------------------------------------------------------------------+
+$query = '
+SELECT
+    lp.*,
+    ap.lang,
+    ap.title,
+    ap.standalone,
+    ap.permalink
+  FROM '.LINKEDPAGES_TABLE.' AS lp
+    INNER JOIN '.ADD_PAGES_TABLE.' AS ap
+    ON lp.page_id = ap.id
+  WHERE category_id = '.$_GET['cat_id'].'
+  ORDER BY lp.pos
+';
+$result = pwg_query($query);
+
+$cat_pages = array();
+while ($row = pwg_db_fetch_assoc($result))
+{
+  $row['U_PAGE'] = make_index_url(array('section'=>'page')).'/'.(isset($row['permalink']) ? $row['permalink'] : $row['page_id']);
+  $row['title'] = trigger_event('AP_render_title', $row['title']);
+  $row['language'] = @$languages[$row['lang']];
+  $cat_pages[$row['page_id']] = $row;
+}
+$template->assign('cat_pages', $cat_pages);
+
+$query = '
+SELECT
+    id,
+    lang,
+    title,
+    standalone,
+    permalink
+  FROM '.ADD_PAGES_TABLE.'
+  '.(!empty($conf['AP']['homepage']) ? 'WHERE id != '.$conf['AP']['homepage'] : null).'
+  ORDER BY title ASC
+;';
+$result = pwg_query($query);
+
+while ($row = pwg_db_fetch_assoc($result))
+{
+  if (array_key_exists($row['id'], $cat_pages))
+  {
+    $row['disabled'] = 'disabled="disabled"';
+  }
+  $row['U_PAGE'] = make_index_url(array('section'=>'page')).'/'.(isset($row['permalink']) ? $row['permalink'] : $row['id']);
+  $row['title'] = trigger_event('AP_render_title', $row['title']);
+  $row['language'] = @$languages[$row['lang']];
+  $template->append('pages', $row);
+}
+
+
+// +-----------------------------------------------------------------------+
+// | Template                                                             |
+// +-----------------------------------------------------------------------+
+$template->assign(array(
+  'F_ACTION' => $self_url,
+  'CATEGORIES_NAV' => get_cat_display_name_cache(
+    $category['uppercats'],
+    LINKEDPAGES_ADMIN.'-album-'
+    ),
+  'LINKEDPAGES_PATH'=> get_root_url() . LINKEDPAGES_PATH,
+  ));
+ 
+$template->set_filename('linked_pages_content', realpath(LINKEDPAGES_PATH . 'template/admin_album.tpl'));
+$template->assign_var_from_handle('ADMIN_CONTENT', 'linked_pages_content');
+
+?>
Index: /extensions/linked_pages/include/functions.inc.php
===================================================================
--- /extensions/linked_pages/include/functions.inc.php	(revision 17882)
+++ /extensions/linked_pages/include/functions.inc.php	(revision 17882)
@@ -0,0 +1,111 @@
+<?php
+if (!defined('LINKEDPAGES_PATH')) die('Hacking attempt!');
+
+/**
+ * add a tab on album properties page
+ */
+function linked_pages_tabsheet_before_select($sheets, $id)
+{
+  if ($id == 'album')
+  {
+    $sheets['linked_pages'] = array(
+      'caption' => l10n('Linked Pages'),
+      'url' => LINKEDPAGES_ADMIN.'-album-'.$_GET['cat_id'],
+      );
+  }
+  
+  return $sheets;
+}
+
+/**
+ * display menu a album page/additional page
+ */
+function linked_pages_loc_end_index()
+{
+  global $page, $user, $template;
+  
+
+  if ( isset($page['section']) and $page['section']=='categories' and isset($page['category']) )
+  {
+    $query = '
+SELECT
+    lp.*,
+    ap.lang,
+    ap.title,
+    ap.standalone,
+    ap.permalink
+  FROM '.LINKEDPAGES_TABLE.' AS lp
+    INNER JOIN '.ADD_PAGES_TABLE.' AS ap
+    ON lp.page_id = ap.id
+  WHERE category_id = '.$page['category']['id'].'
+  ORDER BY lp.pos
+;';
+    $result = pwg_query($query);
+    
+    if (!pwg_db_num_rows($result))
+    {
+      return;
+    }
+    
+    while ($row = pwg_db_fetch_assoc($result))
+    {
+      if ( isset($row['lang']) and $row['lang'] != $user['language'] ) return;
+      $row['U_PAGE'] = make_index_url(array('section'=>'page')).'/'.(isset($row['permalink']) ? $row['permalink'] : $row['page_id']);
+      $row['TITLE'] = trigger_event('AP_render_title', $row['title']);
+      $template->append('category_pages', $row);
+    }
+    
+    $template->assign('LINKEDPAGES_PATH', LINKEDPAGES_PATH);
+    $template->set_prefilter('index', 'linked_pages_prefilter_index');
+    
+  }
+  else if ( isset($page['section']) and $page['section']=='additional_page' and isset($page['additional_page']) )
+  {
+    $query = '
+SELECT
+    lp.*,
+    cat.name,
+    cat.permalink
+  FROM '.LINKEDPAGES_TABLE.' AS lp
+    INNER JOIN '.CATEGORIES_TABLE.' AS cat
+    ON lp.category_id = cat.id
+  WHERE page_id = '.$page['additional_page']['id'].'
+  ORDER BY lp.pos
+;';
+    $result = pwg_query($query);
+    
+    if (!pwg_db_num_rows($result))
+    {
+      return;
+    }
+    
+    while ($row = pwg_db_fetch_assoc($result))
+    {
+      $row['U_PAGE'] = make_index_url(
+        array(
+          'category' => array(
+            'id' => $row['category_id'], 
+            'name' => $row['name'], 
+            'permalink' => $row['permalink'],
+            )
+          )
+        );
+      $row['TITLE'] = trigger_event('render_category_name', $row['name']);
+      $template->append('category_pages', $row);
+    }
+    
+    $template->assign('LINKEDPAGES_PATH', LINKEDPAGES_PATH);
+    $template->set_filename('linked_pages_content', realpath(LINKEDPAGES_PATH . 'template/index_menu.tpl'));
+    $template->assign('PLUGIN_INDEX_CONTENT_BEGIN', $template->parse('linked_pages_content',true).$template->get_template_vars('PLUGIN_INDEX_CONTENT_BEGIN'));
+  }
+}
+
+function linked_pages_prefilter_index($content)
+{
+  $search = '#(</div>{\* <!-- titrePage --> \*}|<div id="subcontent">|<div class="subcontent">)#';
+  $replace = "$1\n".file_get_contents(LINKEDPAGES_PATH . 'template/index_menu.tpl');
+  return preg_replace($search, $replace, $content);
+}
+
+
+?>
Index: /extensions/linked_pages/include/index.php
===================================================================
--- /extensions/linked_pages/include/index.php	(revision 17882)
+++ /extensions/linked_pages/include/index.php	(revision 17882)
@@ -0,0 +1,7 @@
+<?php
+$url = '../';
+header( 'Request-URI: '.$url );
+header( 'Content-Location: '.$url );
+header( 'Location: '.$url );
+exit();
+?>
Index: /extensions/linked_pages/include/install.inc.php
===================================================================
--- /extensions/linked_pages/include/install.inc.php	(revision 17882)
+++ /extensions/linked_pages/include/install.inc.php	(revision 17882)
@@ -0,0 +1,18 @@
+<?php
+if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
+
+function linked_pages_install() 
+{
+  global $prefixeTable;
+  
+	pwg_query('
+CREATE TABLE IF NOT EXISTS `'.$prefixeTable.'linked_pages` (
+  `page_id` smallint(5) unsigned NOT NULL,
+  `category_id` smallint(5) unsigned NOT NULL,
+  `pos` smallint(5) unsigned NOT NULL,
+  UNIQUE KEY `UNIQUE`(`page_id`,`category_id`)
+) DEFAULT CHARSET=utf8
+;');
+}
+
+?>
Index: /extensions/linked_pages/index.php
===================================================================
--- /extensions/linked_pages/index.php	(revision 17882)
+++ /extensions/linked_pages/index.php	(revision 17882)
@@ -0,0 +1,7 @@
+<?php
+$url = '../';
+header( 'Request-URI: '.$url );
+header( 'Content-Location: '.$url );
+header( 'Location: '.$url );
+exit();
+?>
Index: /extensions/linked_pages/language/en_UK/description.txt
===================================================================
--- /extensions/linked_pages/language/en_UK/description.txt	(revision 17882)
+++ /extensions/linked_pages/language/en_UK/description.txt	(revision 17882)
@@ -0,0 +1,1 @@
+Link Additional Pages to albums.
Index: /extensions/linked_pages/language/en_UK/index.php
===================================================================
--- /extensions/linked_pages/language/en_UK/index.php	(revision 17882)
+++ /extensions/linked_pages/language/en_UK/index.php	(revision 17882)
@@ -0,0 +1,7 @@
+<?php
+$url = '../';
+header( 'Request-URI: '.$url );
+header( 'Content-Location: '.$url );
+header( 'Location: '.$url );
+exit();
+?>
Index: /extensions/linked_pages/language/fr_FR/description.txt
===================================================================
--- /extensions/linked_pages/language/fr_FR/description.txt	(revision 17882)
+++ /extensions/linked_pages/language/fr_FR/description.txt	(revision 17882)
@@ -0,0 +1,1 @@
+Liez des pages additionnelles aux albums.
Index: /extensions/linked_pages/language/fr_FR/index.php
===================================================================
--- /extensions/linked_pages/language/fr_FR/index.php	(revision 17882)
+++ /extensions/linked_pages/language/fr_FR/index.php	(revision 17882)
@@ -0,0 +1,7 @@
+<?php
+$url = '../';
+header( 'Request-URI: '.$url );
+header( 'Content-Location: '.$url );
+header( 'Location: '.$url );
+exit();
+?>
Index: /extensions/linked_pages/language/index.php
===================================================================
--- /extensions/linked_pages/language/index.php	(revision 17882)
+++ /extensions/linked_pages/language/index.php	(revision 17882)
@@ -0,0 +1,7 @@
+<?php
+$url = '../';
+header( 'Request-URI: '.$url );
+header( 'Content-Location: '.$url );
+header( 'Location: '.$url );
+exit();
+?>
Index: /extensions/linked_pages/main.inc.php
===================================================================
--- /extensions/linked_pages/main.inc.php	(revision 17882)
+++ /extensions/linked_pages/main.inc.php	(revision 17882)
@@ -0,0 +1,81 @@
+<?php 
+/*
+Plugin Name: Linked Pages
+Version: auto
+Description: Link Additional Pages to albums.
+Plugin URI: http://piwigo.org/ext/extension_view.php?eid=635
+Author: Mistic
+Author URI: http://www.strangeplanet.fr
+*/
+
+if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
+
+global $prefixeTable;
+
+// +-----------------------------------------------------------------------+
+// | Define plugin constants                                               |
+// +-----------------------------------------------------------------------+
+define('LINKEDPAGES_PATH' ,   PHPWG_PLUGINS_PATH . 'linked_pages/');
+define('LINKEDPAGES_TABLE',   $prefixeTable . 'linked_pages');
+define('LINKEDPAGES_ADMIN',   get_root_url() . 'admin.php?page=plugin-linked_pages');
+define('LINKEDPAGES_VERSION', '1.0.0');
+
+
+// +-----------------------------------------------------------------------+
+// | Add event handlers                                                    |
+// +-----------------------------------------------------------------------+
+// init the plugin
+add_event_handler('init', 'linked_pages_init');
+
+if (defined('IN_ADMIN'))
+{
+  add_event_handler('tabsheet_before_select', 'linked_pages_tabsheet_before_select', EVENT_HANDLER_PRIORITY_NEUTRAL, 2);
+}
+else
+{
+  add_event_handler('loc_end_index', 'linked_pages_loc_end_index', EVENT_HANDLER_PRIORITY_NEUTRAL+20);
+}
+
+include_once(LINKEDPAGES_PATH . 'include/functions.inc.php');
+
+
+
+/**
+ * plugin initialization
+ */
+function linked_pages_init()
+{
+  global $conf, $pwg_loaded_plugins;
+  
+  if (!isset($pwg_loaded_plugins['AdditionalPages']))
+  {
+    return;
+  }
+  
+  if (
+    $pwg_loaded_plugins['linked_pages']['version'] == 'auto' or
+    version_compare($pwg_loaded_plugins['linked_pages']['version'], LINKEDPAGES_VERSION, '<')
+  )
+  {
+    include_once(LINKEDPAGES_PATH . 'include/install.inc.php');
+    linked_pages_install();
+    
+    if ($pwg_loaded_plugins['linked_pages']['version'] != 'auto')
+    {
+      $query = '
+UPDATE '. PLUGINS_TABLE .'
+SET version = "'. LINKEDPAGES_VERSION .'"
+WHERE id = "linked_pages"';
+      pwg_query($query);
+      
+      $pwg_loaded_plugins['linked_pages']['version'] = LINKEDPAGES_VERSION;
+      
+      if (defined('IN_ADMIN'))
+      {
+        $_SESSION['page_infos'][] = 'Skeleton updated to version '. LINKEDPAGES_VERSION;
+      }
+    }
+  }
+}
+
+?>
Index: /extensions/linked_pages/maintain.inc.php
===================================================================
--- /extensions/linked_pages/maintain.inc.php	(revision 17882)
+++ /extensions/linked_pages/maintain.inc.php	(revision 17882)
@@ -0,0 +1,30 @@
+<?php
+if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
+
+include_once(PHPWG_PLUGINS_PATH . 'linked_pages/include/install.inc.php');
+
+
+function plugin_install() 
+{
+  linked_pages_install();
+  define('linked_pages_installed', true);
+}
+
+
+function plugin_activate()
+{
+  if (!defined('linked_pages_installed'))
+  {
+    linked_pages_install();
+  }
+}
+
+
+function plugin_uninstall() 
+{
+  global $prefixeTable;
+  
+  pwg_query('DROP TABLE `'.$prefixeTable.'linked_pages`;');
+}
+
+?>
Index: /extensions/linked_pages/template/admin_album.tpl
===================================================================
--- /extensions/linked_pages/template/admin_album.tpl	(revision 17882)
+++ /extensions/linked_pages/template/admin_album.tpl	(revision 17882)
@@ -0,0 +1,112 @@
+{footer_script require='jquery.ui.sortable'}{literal}
+function init_handlers() {
+  jQuery(".menuPos").hide();
+  jQuery(".drag_button").show();
+  jQuery(".menuLi").css("cursor","move");
+  jQuery(".menuUl").sortable({
+    axis: "y",
+    opacity: 0.8
+  });
+  
+  jQuery("#menuOrdering").submit(function(){
+    ar = jQuery('.menuUl').sortable('toArray');
+    for(i=0;i<ar.length;i++) {
+      men = ar[i].split('menu_');
+      document.getElementsByName('position[' + men[1] + ']')[0].value = i;
+    }
+  });
+  
+  $("a.deletePage").click(function() {
+    id = $(this).parents("li.menuLi").attr("id").split("menu_")[1];
+    $(this).parents("li.menuLi").remove();
+    $("select[name='add_page'] option[value='"+ id +"']").removeAttr("disabled");
+  });
+}
+
+$("select[name='add_page']").change(function() {
+  if ($(this).val() != -1) {
+    $option = $(this).children("option:selected");
+    $("ul.menuUl").append(
+      ' <li class="menuLi" id="menu_'+ $(this).val() +'">'+
+        ' <p>'+
+        {/literal}
+          ' <span style="margin:2px 5px;">'+
+            ' <a href="#" class="deletePage"><img src="{$ROOT_URL}{$themeconf.admin_icon_dir}/category_delete.png" alt="{'delete'|@translate}" title="{'delete'|@translate}"></a>'+
+          ' </span>'+
+
+          ' <img src="{$themeconf.admin_icon_dir}/cat_move.png" class="button drag_button" style="display:none;" alt="{'Drag to re-order'|@translate}" title="{'Drag to re-order'|@translate}">'+
+        {literal}
+          ' '+ $option.data("content") +
+        ' </p>'+
+
+        ' <p class="menuPos">'+
+          ' <label>'+
+            ' {/literal}{'Position'|@translate}{literal} :'+
+            ' <input type="text" size="4" name="position['+ $(this).val() +']" maxlength="4" value="0">'+
+          ' </label>'+
+        ' </p>'+
+      ' </li>');
+
+    $option.attr("disabled","disabled");
+    $(this).val(-1);
+    init_handlers();
+  }
+});
+
+init_handlers();
+{/literal}{/footer_script}
+
+{html_head}{literal}
+<style type="text/css">#menuOrdering a:hover { border:none; }</style>
+{/literal}{/html_head}
+
+
+<div class="titrePage">
+  <h2><span style="letter-spacing:0">{$CATEGORIES_NAV}</span> &#8250; {'Edit album'|@translate} {$TABSHEET_TITLE}</h2>
+</div>
+
+<form id="menuOrdering" action="{$F_ACTION}" method="post">
+{if count($pages)}
+  <p style="margin-bottom:15px;">
+    {'ap_add_page'|@translate}
+    <select name="add_page">
+      <option value="-1" selected="selected">------------</option>
+      {foreach from=$pages item=page}
+      <option value="{$page.id}" {$page.disabled} data-content="<b><a href='{$page.U_PAGE}'>{$page.title}</a></b>{if $page.standalone == 'true'} - {'ap_standalone_page'|@translate}{/if}{if !empty($page.language)} <i>({$page.language})</i>{/if}">
+        {$page.title}
+      </option>
+      {/foreach}
+    </select>
+  </p>
+{/if}
+    
+    
+  <ul class="menuUl">
+    {foreach from=$cat_pages item=page}
+    <li class="menuLi" id="menu_{$page.page_id}">
+      <p>
+        <span style="margin:2px 5px;">
+          <a href="#" class="deletePage"><img src="{$ROOT_URL}{$themeconf.admin_icon_dir}/category_delete.png" alt="{'delete'|@translate}" title="{'delete'|@translate}"></a>
+        </span>
+
+        <img src="{$themeconf.admin_icon_dir}/cat_move.png" class="button drag_button" style="display:none;" alt="{'Drag to re-order'|@translate}" title="{'Drag to re-order'|@translate}">
+        <b><a href="{$page.U_PAGE}">{$page.title}</a></b>
+        {if $page.standalone == 'true'} - {'ap_standalone_page'|@translate}{/if}
+        {if !empty($page.language)}<i>({$page.language})</i>{/if}
+      </p>
+
+      <p class="menuPos">
+        <label>
+          {'Position'|@translate} :
+          <input type="text" size="4" name="position[{$page.page_id}]" maxlength="4" value="{$page.pos}">
+        </label>
+      </p>
+    </li>
+    {/foreach}
+  </ul>
+  <p class="menuSubmit">
+    <input type="submit" name="save_pages" value="{'Submit'|@translate}">
+    <input type="submit" name="reset" value="{'Reset'|@translate}">
+  </p>
+
+</form>
Index: /extensions/linked_pages/template/index.php
===================================================================
--- /extensions/linked_pages/template/index.php	(revision 17882)
+++ /extensions/linked_pages/template/index.php	(revision 17882)
@@ -0,0 +1,7 @@
+<?php
+$url = '../';
+header( 'Request-URI: '.$url );
+header( 'Content-Location: '.$url );
+header( 'Location: '.$url );
+exit();
+?>
Index: /extensions/linked_pages/template/index_menu.tpl
===================================================================
--- /extensions/linked_pages/template/index_menu.tpl	(revision 17882)
+++ /extensions/linked_pages/template/index_menu.tpl	(revision 17882)
@@ -0,0 +1,7 @@
+{combine_css path=$LINKEDPAGES_PATH|@cat:"template/style.css"}
+
+<ul id="linked_pages">
+{foreach from=$category_pages item=page name=foo}
+  <li id="linked_page_{$page.page_id}" class="row_{$smarty.foreach.foo.index}"><a href="{$page.U_PAGE}">{$page.TITLE}</a></li>
+{/foreach}
+</ul>
Index: /extensions/linked_pages/template/style.css
===================================================================
--- /extensions/linked_pages/template/style.css	(revision 17882)
+++ /extensions/linked_pages/template/style.css	(revision 17882)
@@ -0,0 +1,19 @@
+#linked_pages {
+  list-style:none;
+  padding:0;
+  margin:20px 20px 10px 20px;
+}
+  #linked_pages li {
+    display:inline-block;
+    padding:0;
+  }
+  #linked_pages li a {
+    padding:4px 8px;
+    border-width:1px;
+    border-style:dotted;
+    border-radius:2px;
+    background-color:rgba(0, 180, 255, 0.05);
+  }
+  #linked_pages li a:hover {
+    border-style:solid;
+  }
