PDA

View Full Version : Exhibit Engine Google XML Sitemap Generator


segal3
17th of February 2009 (Tue), 03:04
Had some time this weekend to correspond with another EE user and fellow underwater photographer, Linda Cline (http://www.dancingfish.com/), about using Exhibit Engine to generate a google XML sitemap without having to worry about recursive uncookied paths or similar.

Our end results were very similar, despite our different approaches. I chose to tear away the framework and deconstruct the very useful sitemap.php in the gallery base directory, while Linda built up the link generation using the snippetdemo example.

Note that both codes print all public exhibitions, and public photos linked with each of those exhibitions. I've made adjustments to also print last-modified dates for photos in both codes, and print last-modified dates for exhibitions in the snippets-buildup code.

Neither of us have used groups with nested exhibitions in our structure, so while I prefer a modified version of Linda's code (variation 1) in the end, my code (variation 2) may be useful for printing group listing page links without modification (untested!). That being said, it shouldn't be too difficult to add group links to the former.

Both codes also look for a file "general_site.php" containing links to pages on your site outside of Exhibit Engine. Follow the same standard XML framework if adding this file.

Variation 1: Snippet build-up
Prints all modification dates with links
Does not print group links
Place in gallery root directory (usually /gallery) with 755 permissions

sitemap_snippet.php
<?php
// XML Sitemap Generator for Exhibit Engine v2.x
// v1.0 by Linda Cline http://www.dancingfish.com/ , Matt Segal http://www.carbonos.com/

header('Content-type: application/xhtml+xml');

$toroot2 = "./"; //Fix for your own localhost path

error_reporting(0);

ob_start ("ob_gzhandler");

$amount="";
$exhibition="all";
$includecategory="";
$excludecategory = "";

//@require_once ($toroot2 . "./ee_snip_func2.php");
@include_once ($toroot2 . "./basecode/SCRIPT_slashwork.php");
@include_once ($toroot2 . "./basecode/SECURITY_datacleaner.php");
@include ($toroot2 . "./basecode/SETUP_settings.php");
@include ($toroot2 . "./basecode/SCRIPT_connect.php");
@include_once ($toroot2 . "./basecode/SCRIPT_language.php");
@include_once ($toroot2 . "./basecode/SCRIPT_uncookied.php");

$user_id = "0"; // public only, change to user id X to show data using user id X's privileges (BEWARE SECURITY)

@include ($toroot2 . "./basecode/SCRIPT_language.php");
@require ($toroot2 . "./basecode/SECURITY_check_exhibition_validity.php");
@include_once ($toroot2 . "./basecode/SCRIPT_common_functions.php");
@include_once ($toroot2 . "./basecode/SCRIPT_fetchsettings.php");
@include ($toroot2 . "./basecode/SCRIPT_indexfunctions.php");
@require($toroot2 . "./basecode/SCRIPT_get_structure.php");

$s_ee_html_root = $s_galleryroot;

if ($exhibition == "all") $exhibition = $all_exhibitions_combined;
$exhib_where = "";
if ($exhibition != $all_exhibitions_combined) {
$exhib_where = " AND ee_exhibition.ee_exhibition_id = {$exhibition} ";
}

/*
$catfrom = "";
$catwhere = "";
$catwhere_end = "";
$orlist = "";
$betweenors = "";
$exlorlist = "";
$ors = array();
$exlors = array();

error_reporting(0);

if ($includecategory != "" OR $excludecategory != "") {
$catwhere_end = ") ";
$catfrom = "ee_category_{$lazylang},
ee_photo_to_category,";

$catwhere = "
AND ee_photo_to_category.ee_category_id = ee_category_{$lazylang}.ee_category_id
AND ee_photo_to_category.ee_photo_id = ee_photo.ee_photo_id AND (
";
}

if ($includecategory != "") {

$orlist = "";
$inccats = explode("|",$includecategory);
foreach ($inccats as $key) {
$cat = trim($key);
$ors[] = " ee_photo_to_category.ee_category_id = '{$cat}' ";
}
$orlist = implode(" OR ",$ors);
}

$exlcatfrom = "";
if ($excludecategory != "") {

$exlorlist = "";
$exlcats = explode("|",$excludecategory);
foreach ($exlcats as $key) {
$cat = trim($key);
$exlors[] = " ee_photo_to_category.ee_category_id <> '{$cat}' ";
}
$exlorlist = implode(" AND ",$exlors);
$exlorlist = " (" . $exlorlist . ")";
}
$betweenors = "";
if (@$orlist != "" AND @$exlorlist != "") {
$betweenors = " AND ";
}
*/

// Gather exhibit list
$exhibs_sql = "
SELECT
ee_exhibition_{$ee_lang}.ee_exhibition_id,
DATE_FORMAT(ee_exhibition.ee_exhibition_sql_modifi ed, '%Y-%m-%dT%H:%i:%S+01:00') AS exhib_modified_date
FROM
ee_exhibition_{$ee_lang},
ee_exhibition
WHERE
ee_exhibition.ee_exhibition_id = ee_exhibition_{$ee_lang}.ee_exhibition_id
{$and_exhibition_ids_are}
ORDER BY
ee_exhibition.ee_exhibition_sql_modified DESC
";
$exhibs = mysql_query($exhibs_sql);
ee_error ($exhibs,"exhibs","snippets.php",$exhibs_sql);


// Gather photo list
$sitemap_sql = "
SELECT
ee_photo.ee_photo_id,
ee_exhibition.ee_exhibition_id,
DATE_FORMAT(ee_photo.ee_photo_sql_modified, '%Y-%m-%dT%H:%i:%S+01:00') AS photo_modified_date
FROM
ee_photo_{$lazylang},
ee_photo,
ee_photo_to_exhibition,
{$catfrom}
ee_exhibition
WHERE
ee_photo.ee_photo_for_www = '1'
AND ee_photo_to_exhibition.ee_photo_id = ee_photo.ee_photo_id
AND ee_photo_to_exhibition.ee_exhibition_id = ee_exhibition.ee_exhibition_id
AND ee_photo.ee_photo_id = ee_photo_{$lazylang}.ee_photo_id
{$catwhere}
{$orlist}
{$betweenors}
{$exlorlist}
{$catwhere_end}
{$exhib_where}
{$and_exhibition_ids_are}
GROUP BY
ee_photo.ee_photo_id
ORDER BY
ee_photo.ee_photo_sql_modified DESC
";
$sitemap_photos = mysql_query($sitemap_sql);
ee_error ($sitemap_photos,"sitemap_photos","snippets.php",$sitemap_sql);

// Generate exhibition URL string array
ob_start();
while ($data = mysql_fetch_array($exhibs)) {
print "<url>\n<loc>{$s_ee_html_root}list.php?exhibition=" . $data["ee_exhibition_id"] . "</loc>\n<lastmod>" . $data["exhib_modified_date"] . "</lastmod>\n</url>\n";
}
$sitemap_exhibitions = ob_get_contents();
ob_end_clean();

// Generate photo URL string array
$most_recent_recorded = 0;
ob_start();
$thumbarraylist = array();
while ($row = mysql_fetch_array($sitemap_photos)) {
$exhib = $row["ee_exhibition_id"];
$id = $row["ee_photo_id"];
$photo_mod = $row["photo_modified_date"];
$thumbarraylist[] = array(
"photo" => $id,
"exhibition" => $exhib,
"modified" => $photo_mod
);
if ($most_recent_recorded == 0){
$most_recently_modified = $row["photo_modified_date"];
$most_recent_recorded = 1;
}
print "<url>\n<loc>{$s_ee_html_root}photo.php?photo={$id}&amp;exhibition= {$exhib}</loc>\n<lastmod>{$photo_mod}</lastmod>\n</url>\n";
}
$sitemap_photos = ob_get_contents();
ob_end_clean();

@mysql_close();

// Output
print "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; // Print header declarations
print "<urlset xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd\" xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n";
@include ("./general_site.php"); // General site content links outside of Exhibit Engine - follow xml <url><loc></loc></url> format
print "<url><loc>{$s_ee_html_root}</loc>\n<lastmod>{$most_recently_modified}</lastmod>\n</url>\n"; // Exhibit Engine base directory - uses most recent photo-modification date
print $sitemap_exhibitions; // Exhibition URLs (sorted most-recently modified newest to oldest)
print $sitemap_photos; // Photo URLs, tied to exhibitions (sorted most-recently modified to oldest)
print "</urlset>\n"; // Footer

ob_end_flush();
?>

Variation 2 - Sitemap.php deconstruction
Prints all photo modification dates with links
Potentially prints group links correctly (untested!)
Place sitemap_xml.php gallery root directory (usually /gallery) and SCRIPT_structure_ul_xml.php in /gallery/basecode , both with 755 permissions

sitemap_xml.php
<?php
// XML Sitemap Generator for Exhibit Engine v2.x
// v1.0 by Matt Segal http://www.carbonos.com/ , Linda Cline http://www.dancingfish.com/
// Original framework by Pekka Saarinen

header('Content-type: application/xhtml+xml');

error_reporting(0);
$toroot = "./";
$currentpage = "sitemap";
$this_is_index = "1";

ob_start ("ob_gzhandler");

@include ("./basecode/SCRIPT_slashwork.php");
@include ("./basecode/SECURITY_datacleaner.php");
@include ("./basecode/SETUP_settings.php");
@include ("./basecode/SCRIPT_connect.php");
@include ("./basecode/SCRIPT_uncookied.php");

@include ("./basecode/SCRIPT_language.php");
@require ("./basecode/SECURITY_check_user_authorization.php");
@require ("./basecode/SECURITY_check_exhibition_validity.php");
@include ("./basecode/SCRIPT_common_functions.php");
@require ("./basecode/SCRIPT_fetchsettings.php");
@require ("./basecode/SCRIPT_get_structure.php");

$s_ee_html_root = $s_galleryroot;

$name = "";
ob_start();

$showit = "1";
$listtype = "text";
$sitemap_x = "20";
$sitemap_y = "20";
$maptype = "2";

@require ("./basecode/SCRIPT_structure_ul_xml.php");
ee_build_structure_ul (
"1", // under group_id 1 (1) or spread out (0)
"", // main CSS id
"", // main CSS class
$s_max_sitemap_exhibitions, // maximum number of exhibitions shown per group (leave empty for all)
@$group_lang_array[$ee_lang]["1"]["name"], // title for main UL link (group_id 1)
"", // <li> CSS indexlink
"", // CSS class for index link
"", // <li> CSS class for exhibitions
"", // CSS class for exhibition links
"", // <li> CSS class for groups
"", // CSS class for group links
"", // <li> CSS class for links
"", // CSS class for link link
"", // <ul> CSS class
"\n", // <li> line feed character
"", // CSS class for current group
"", // CSS class for current exhibition
$showit, // sitemap specific (show items)
$listtype, // sitemap specific (item type)
$s_ee_html_root // base directory
);

$sitemap_html = ob_get_contents();
ob_end_clean();

// Print header
print "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
print "<urlset xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd\" xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n";
@include ("./general_site.php"); //General site content
print $sitemap_html; // Exhibit Engine links

mysql_close ();

print "</urlset>";

ob_end_flush();

?>/basecode/SCRIPT_structure_ul_xml.php
<?php
// XML Sitemap Generator for Exhibit Engine v2.x
// v1.0 by Matt Segal http://www.carbonos.com/ , Linda Cline http://www.dancingfish.com/
// Original framework by Pekka Saarinen

error_reporting(0);
include ("toroot.php");

$sitemap_ul = "";
$sitemap_ul_menu = "";


if (!function_exists("ee_2nbsp")) {
function ee_2nbsp ($data) {
//$data = str_replace(" ", "&nbsp;", $data);
return ($data);
}
}


if (!function_exists("ee_build_structure_ul")) {
function ee_build_structure_ul (
$has_header = "0",
$id = "",
$class = "",
$max_exhibs_per_group = "",
$header = "",
$header_li = "",
$header_link = "",
$exhibition_li = "",
$exhibition_link = "",
$group_li = "",
$group_link = "",
$link_li = "",
$link_link = "",
$ulclass = "",
$linefeed = "",
$showgroup = "",
$showexhibition = "",
$showallphotos = "0",
$photolinks = "text",
$s_ee_html_root = ""
) {

global $safe_structure_array;
global $grouptree;
global $sitemap_x;
global $sitemap_y;
global $ee_lang;
global $uncookied_base_id;

if (!isset($uncookied_base_id)) {
$uncookied_base_id = "";
}

$validarray = array();
$isheader = "0";

if ($has_header == "1") {
print "<url>{$linefeed}<loc>{$s_ee_html_root}index.php</loc>{$linefeed}</url>";
}

ee_get_menu_ul (1,$grouptree,$linefeed,$exhibition_li,$group_li,$ ulclass,$exhibition_link,$group_link, $isheader,$showallphotos,$photolinks,$link_link,$m ax_exhibs_per_group,$link_li,$showgroup,$showexhib ition,$s_ee_html_root);
return TRUE;

}
}

if (!function_exists("ee_get_photonames")) {
function ee_get_photonames ($exhibition) {

global $lazylang;

$get_photonames_sql = "
SELECT
ee_photo.ee_photo_id,
ee_photo.ee_photo_filename,
DATE_FORMAT(ee_photo.ee_photo_sql_modified, '%Y-%m-%dT%H:%i:%S+01:00') AS photo_modified_date
FROM
ee_photo_{$lazylang},
ee_photo,
ee_photo_to_exhibition,
ee_exhibition,
ee_photo_to_category
WHERE
ee_photo.ee_photo_for_www = '1'
AND ee_photo_{$lazylang}.ee_photo_id = ee_photo.ee_photo_id
AND ee_photo_to_exhibition.ee_photo_id = ee_photo.ee_photo_id
AND ee_photo_to_exhibition.ee_exhibition_id = ee_exhibition.ee_exhibition_id
AND ee_exhibition.ee_exhibition_id = '$exhibition'
AND ee_photo_to_category.ee_category_id = '1'
AND ee_photo_to_category.ee_photo_id = ee_photo.ee_photo_id
ORDER BY
ee_photo.ee_photo_id DESC
";
$result = mysql_query($get_photonames_sql);
ee_error ($result,"result","function ee_get_photonames",$get_photonames_sql);
if (!$result) return FALSE;
return($result);
}
}

if (!function_exists("ee_get_menu_ul")) {
function ee_get_menu_ul ($parent,$grouptree,$linefeed,$exhibition_li,$grou p_li,$ulclass,$exhibition_link,$group_link,$ishead er,$showallphotos,$photolinks,$link_link,$max_exhi bs_per_group,$link_li,$showgroup,$showexhibition,$ s_ee_html_root) {

global $safe_structure_array;
global $exhibition_array;
global $exhibition_lang_array;
global $group_array;
global $link_array;
global $group_lang_array;
global $link_lang_array;
global $lazylang;
global $show_group_ids;
global $show_exhibition_ids;
global $sitemap_x;
global $sitemap_y;
global $uncookied_base_id;
global $ee_lang;
global $s_lazy_language_override_exhibition_name;
global $s_lazy_language_override_exhibition_description;
global $s_ee_division_character;
global $s_max_photonames_per_exhibition;
global $s_lazy_language_override_group_name;
global $s_lazy_language_override_link_name;
global $translated;

print "{$linefeed}";

$mark = 0;

$display_max_exhibitions = 1;


if (@$safe_structure_array[$parent]) {
foreach ($safe_structure_array[$parent]["exhibitions"] as $key) {

$photocount = "0";
$photocount = $exhibition_array[$key]["photos"];
if ($photocount == "1") {
$pho = "photo";
} else {
$pho = "photos";
}

$photocount_text = "";

$exhibition_name = ee_2nbsp($exhibition_lang_array[$lazylang][$key]["name"]);
if ($s_lazy_language_override_exhibition_name == "1") {
$exhibition_name = @ee_2nbsp($exhibition_lang_array[$ee_lang][$key]["name"]);
}
$exhibition_description = @$exhibition_lang_array[$lazylang][$key]["description"];
if ($s_lazy_language_override_exhibition_description == "1") {
$exhibition_description = @$exhibition_lang_array[$ee_lang][$key]["description"];
}

print "<url>{$linefeed}<loc>{$s_ee_html_root}list.php?exhibition={$key}</loc>{$linefeed}</url>{$linefeed}";


if ($showallphotos == "1") {
if ($photonames = ee_get_photonames ($key)) {
if ($photolinks == "text") {
if ($photocount == 0) {
} else {
$printcount = 0;
while ($row = mysql_fetch_array($photonames)) {

print "<url>{$linefeed}<loc>{$s_ee_html_root}photo.php?exhibition={$key}&amp;photo =" . $row["ee_photo_id"] . "</loc>{$linefeed}<lastmod>" . $row["photo_modified_date"] ."</lastmod>{$linefeed}</url>{$linefeed}";
$printcount++;
}
}
}

} else {
}
}

$mark = 1;
$display_max_exhibitions++;

}
}


if (is_array($grouptree)) {
foreach ($grouptree as $key => $k) {
if ($k["parent"] == $parent) {
$showid = "";
if ($show_group_ids == 1) {
$showid = $k["child"] . ". ";
}

$groupname = ee_2nbsp($group_lang_array[$lazylang][$k["child"]]["name"]);
if ($s_lazy_language_override_group_name == "1") {
$groupname = ee_2nbsp($group_lang_array[$ee_lang][$k["child"]]["name"]);
}
print "<url>{$linefeed}<loc>{$s_ee_html_root}index.php?groupid=" . $k["child"] . "</loc>{$linefeed}</url>"; //<li>
ee_get_menu_ul ($k["child"],$grouptree,$linefeed,$exhibition_li,$group_li,$ul class,$exhibition_link,$group_link,$isheader,$show allphotos,$photolinks,$link_link,$max_exhibs_per_g roup,$link_li,$showgroup,$showexhibition,$s_ee_htm l_root);
print "{$linefeed}";
$mark = 1;
}

}
}
return TRUE;
}
}
?>Hope this helps those of you out there trying to implement sitemaps - please let us know if we overlooked something obvious!

wkitty42
17th of February 2009 (Tue), 11:35
is either of these to replace or add to the existing sitemap stuff?

i'm still stuck, just like i was several years ago, with trying to find a way to create external sitemap(s) for the rest of my site/domains :?

segal3
17th of February 2009 (Tue), 16:14
The existing sitemap/"Gallery map" page (here (http://www.carbonos.com/gallery/sitemap.php), for example) in Exhibit Engine v2.x is primarily for the user.

This new code generates an XML sitemap independent of uncookied paths for search engine usage, as per the Sitemap specifications (http://sitemaps.org/).

jeronimo
14th of March 2009 (Sat), 05:09
I am willing to try this out with nested groups etc.

However it's not realy clear to me how this works. I should make a file named sitemap_snippet.php (for code 1) or sitemap_xml.php (code 2) and then let google link to that file?

---- edit below ----

Ok i've tried out, seams to work for now;
http://www.landmarks.nl/sitemap_xml.php

I miss the links to news/gear/contact etc. Should I add them in a custom made general_site.php or is there a way to let them appear by default? (e.g. would be nice to have a complete listing to all the news entries)

UweB
15th of March 2009 (Sun), 05:19
I've found that EE2 is really good to let search engines find all information within the galleries pages. What i did was inserting proper meta tags, description, and using key words on most of my pictures. It only takes a couple of days and it is in the index of search engines...

I even did some tests with words that do not exist... depending on how often my meta tags and keyword are used in the internet i'm usually listed on the first few pages of search engines.

What am i missing from your sitemap versus the default functions of EE2?

jeronimo
15th of March 2009 (Sun), 08:16
Well google has a function specialy designed for webmasters. Here you can add files with an xml sitemaps. This complete file then read and added to the google index.

A bit offtopic; how do you make all the keywords? On your pc, using...?

UweB
15th of March 2009 (Sun), 11:18
But is this not too Google centric? A while ago i thought about sitemaps for search engine indexing as well and then i found that there is not 1 standard which fits all search engines.

My keywords and meta tags? I type them in for every single photo just as creativity comes or if it fits for many at once, for example a location, i do it with my photo DB. That' s a job for rainy days... ;-)

Pekka
16th of March 2009 (Mon), 18:05
EE2 indexes well with default settings because Google does change and adapt their engine to modern www which uses url parameters. They actually prefer url parameters to SEO optimised static urls: http://googlewebmastercentral.blogspot.com/2008/09/dynamic-urls-vs-static-urls.html

Sitemaps should be considered as additional info for Google, as laid our in http://www.google.com/support/webmasters/bin/answer.py?answer=40318

Google sitemap blogs: http://googlewebmastercentral.blogspot.com/search/label/sitemaps

malum
4th of May 2010 (Tue), 14:50
Hi in your first bit of code (sitemap_snippet.php)
Is there a way to have it collect links to other languages?
At the moment it collects just links to the main language.

Many thanks