Новости Joomla

Компонент Joomla 6: Генератор LLMs.txt.

Компонент Joomla 6: Генератор LLMs.txt.

Компонент Joomla 6: Генератор LLMs.txt.

Ещё один генератор ИИ-файлов llms.txt и llms-full.txt.

Основные особенности/возможности компонента:

  • Генерация по стандарту: Автоматическое создание файла-визитки llms.txt и расширенной версии llms-full.txt с аннотированным списком материалов.
  • Интеллектуальная работа с контентом: Компонент использует мета-описания (Meta Description) из статей и пунктов меню, превращая SEO-настройки сайта в качественный контекст для нейросетей.
  • Просмотреть результат генерации файлов можно сразу в рабочей области компонента. После внесения корректив (через Настройки компонента. При отладке лучше открыть три вкладки в браузере: Настройка — Геренация/Превью — Список Материалов/Категории/Меню.) — проводим перегенерацию, смотрим результат до полной «победы».
  • Автоматизация и безопасность: Синхронизация с sitemap.xml, группировка по категориям и автоматическое создание резервных копий (.bak) при каждой генерации.
  • Гибкое управление: Возможность исключения определенных категорий и/или статей и/или пунктов меню, а также простая настройка через стандартную админпанель Joomla.
  • Подробное руководство/справка: Пошаговая инструкция для пользователя в Настройках компонента для редакторов с базовым знанием администрирования Joomla.

👉 Важно учесть.
1️⃣ Компонент Генератор LLMs.txt изначально составляет базовый список ссылок на основе sitemap.xml и сверяется с ним на предмет: запрета индексации url в robots.txt, тегов noinex/nofollow. Это экономит время на проверку «закрыть от индексации», поскольку компонент генерации Sitemap.xml уже реализовал эту задачу. Посему, формирование ссылок для ИИ имеет комплексный подход, составление грамотного/валидного/релевантного sitemap.xml никто не отменял.

2️⃣ Тексты-описания ссылок формируются из Meta Description com_content (только компонент Материалы) и выбранных пользователем Меню сайта. Важно, чтобы Meta Description были уникальными и релевантными, соответствовали базовому seo. Составленные «на отшибись» Description для ИИ — «не катит» (впрочем, для поисковых систем они тоже «не канали»).

Разработчик - участник нашего сообщества Александр Кузнецов (@newvksan).

Страница расширения

@joomlafeed

#joomla #ии #ai

👩‍💻 WT LLMs для Joomla: llms.txt, llms.json для AI-агентов.

👩‍💻 WT LLMs для Joomla: llms.txt, llms.json для AI-агентов.

Это Joomla-компонент для публикации AI-ready карты сайта и автоматической генерации файлов llms.txt, llms-full.txt и llms.json по концепции llmstxt.org.  Также о концепции llms.txt говорит Google в своей справке Lighthouse. Решение помогает LLM-моделям, AI-агентам, GEO/AI SEO-процессам и внутренним автоматизациям получать структурированные данные о сайте без ручной сборки JSON и Markdown.

С помощью WT LLMs можно:
- создать структурированное описание сайта для AI-агентов;
- управлять профилем сайта, картой интентов и каноническими страницами для этих интентов из админки Joomla;
- генерировать llms.txt и llms.json;
- использовать REST API для автоматического заполнения данных;
- отдавать публичную schema-инструкцию для AI-агентов;

В комплект компонента входит плагин markdown-версии страниц Joomla. Системный плагин Joomla, который добавляет альтернативное Markdown-представление страниц сайта. Он позволяет отдавать содержимое страницы в более чистом текстовом формате, удобном для AI-агентов, LLM, поисковых систем и технических интеграций.
Плагин добавляет в ссылки на AI-файлы.

Пакет подходит для сайтов на Joomla 5+, которым важно сделать контент понятнее для LLM, AI-поиска, ассистентов и будущих систем машинного чтения.

Видео:
- ВК Видео
- RuTube
- YouTube

Ссылки:
Страница расширения
GitHub

@joomlafeed

0 Пользователей и 1 Гость просматривают эту тему.
  • 19 Ответов
  • 16453 Просмотров
*

PaLyCH

  • Давно я тут
  • 958
  • 146 / 19
  • Менеджер проектов
Транслитерация title в sh404
« : 03.08.2009, 16:11:34 »
Заметил на двух последних сайтах. Sh404 транслитирует title страниц в латиницу. Особенно заметно для компонентов com_contact, com_user и com_docman
То есть страница должна имеет название
 Авторизация
А отображается
 Log-in

Версия sh404 1.0.20_Beta - build_237
Joomla 1.5.14

Как исправить?
« Последнее редактирование: 03.08.2009, 16:29:18 от PaLyCH »
*

PaLyCH

  • Давно я тут
  • 958
  • 146 / 19
  • Менеджер проектов
Re: Транслитерация title в sh404
« Ответ #1 : 03.08.2009, 16:27:33 »
Так. Решение найдено и весьма банальное.
Для сторонних компонентов есть отдельные языковые файлы, находятся в папке 
administrator/components/com_sh404sef/language/plugins/
Проблема - Отсутствуют русские переводы для переменных.

Решение - Необходимо внести поправки для русского языка.

Постепенно переведу и выложу
*

voland

  • Легенда
  • 11026
  • 588 / 112
  • Эта строка съедает место на вашем мониторе
Re: Транслитерация title в sh404
« Ответ #2 : 03.08.2009, 17:20:20 »
Хм.. ну это не транслитерация а перевод. Я так понял включен режим замены тайтлов?
*

PaLyCH

  • Давно я тут
  • 958
  • 146 / 19
  • Менеджер проектов
Re: Транслитерация title в sh404
« Ответ #3 : 03.08.2009, 17:28:58 »
Хм.. ну это не транслитерация а перевод. Я так понял включен режим замены тайтлов?
Нет. не совсем так. Замена тайтлов отключено. При дефолтных настройках вот такая фигня.

Re: Транслитерация title в sh404
« Ответ #4 : 04.08.2009, 11:10:58 »
Заметил на двух последних сайтах. Sh404 транслитирует title страниц в латиницу. Особенно заметно для компонентов com_contact, com_user и com_docman
То есть страница должна имеет название
  Авторизация
А отображается
  Log-in

Версия sh404 1.0.20_Beta - build_237
Joomla 1.5.14

Как исправить?

Можно немного не в тему?

Вы сказали про докмен. Он у вас нормально работает? А именно в каталоге страницы когда перелистываете он нормально переходит?

Можно ваши настроки компонента касаемо докман увидеть... Заранее спасибо.
*

asdlsd

  • Осваиваюсь на форуме
  • 15
  • 0 / 0
Re: Транслитерация title в sh404
« Ответ #5 : 05.08.2009, 10:51:46 »
*

PaLyCH

  • Давно я тут
  • 958
  • 146 / 19
  • Менеджер проектов
Re: Транслитерация title в sh404
« Ответ #6 : 06.08.2009, 15:50:20 »
Да. Подтверждаю Данное решение работает. Приведу его здесь, на всякий случай
Открываем файл
Код
components/com_sh404sef/shPageRewrite.php
Ищем строку
Код: php
(!is_null($shCustomTitleTag)) {
$buffer = preg_replace( '/\<\s*title\s*\>.*\<\s*\/title\s*\>/isU', '<title>'
.shCleanUpTitle($sefConfig->prependToPageTitle.$shCustomTitleTag.$sefConfig->appendToPageTitle).'</title>', $buffer);
$buffer = preg_replace( '/\<\s*meta\s+name\s*=\s*"title.*\/\>/isU', '', $buffer); // remove Joomla title meta
}
Заменяем на
Код: php
/**if (!is_null($shCustomTitleTag)) {
$buffer = preg_replace( '/\<\s*title\s*\>.*\<\s*\/title\s*\>/isU', '<title>'
.shCleanUpTitle($sefConfig->prependToPageTitle.$shCustomTitleTag.$sefConfig->appendToPageTitle).'</title>', $buffer);
$buffer = preg_replace( '/\<\s*meta\s+name\s*=\s*"title.*\/\>/isU', '', $buffer); // remove Joomla title meta
}**/
И все тайтлы нормальные
*

MwG

  • Осваиваюсь на форуме
  • 11
  • 0 / 0
Re: Транслитерация title в sh404
« Ответ #7 : 30.08.2009, 05:17:14 »
Все хорошо работает, правда, жаль не отображаются секция и категория в тайтле. На фаерборде не пробовал.
« Последнее редактирование: 20.09.2009, 17:15:53 от MwG »
*

Duveloper

  • Захожу иногда
  • 197
  • 2 / 0
  • Зырк
Re: Транслитерация title в sh404
« Ответ #8 : 16.09.2009, 12:56:16 »
Решение не идеально, у меня на форуме Firebord при заходе в разделы и темы после этого внизу 3 ошибки висят, правда после обновления страницы они чудом пропали =/
*

Stiglitz

  • Новичок
  • 7
  • 0 / 0
  • Joomla - I love this game
Re: Транслитерация title в sh404
« Ответ #9 : 05.10.2009, 02:04:12 »
послед этого изменения, у меня не получается самостоятельно редактировать тайтлы , хотя дескрипшн и кейвордс редактируется
уже бросил в топку описание своей проблемы
после данных изменений .
« Последнее редактирование: 06.10.2009, 00:03:47 от Stiglitz »
*

MUft

  • Новичок
  • 5
  • 0 / 2
Re: Транслитерация title в sh404
« Ответ #10 : 10.10.2009, 22:12:22 »
Я решил эту проблему так:
Отключил автоматический мета-менеджмент в sh404SEF чтобы работал следующий пунтк - (все равно мне гораздо проще и логичнее проставлять самому для каждого материала)
поставил плагин SeoSimple
 :D
Работает на ура :)
*

PaLyCH

  • Давно я тут
  • 958
  • 146 / 19
  • Менеджер проектов
Re: Транслитерация title в sh404
« Ответ #11 : 10.10.2009, 23:29:19 »
Я решил эту проблему так:
Отключил автоматический мета-менеджмент в sh404SEF чтобы работал следующий пунтк - (все равно мне гораздо проще и логичнее проставлять самому для каждого материала)
поставил плагин SeoSimple
 :D
Работает на ура :)
В новой версии по моей просьбе эта ошибка исправлена
*

voland

  • Легенда
  • 11026
  • 588 / 112
  • Эта строка съедает место на вашем мониторе
Re: Транслитерация title в sh404
« Ответ #12 : 16.10.2009, 16:23:41 »
В новой версии по моей просьбе эта ошибка исправлена
в какой именно?
*

PaLyCH

  • Давно я тут
  • 958
  • 146 / 19
  • Менеджер проектов
Re: Транслитерация title в sh404
« Ответ #13 : 16.10.2009, 18:24:44 »
в какой именно?
билд от 2009-09-25 и соотвественно все новые версии имеют испарвления
*

Ernesto

  • Осваиваюсь на форуме
  • 35
  • 0 / 0
Re: Транслитерация title в sh404
« Ответ #14 : 02.12.2009, 19:18:28 »
билд от 2009-09-25 и соотвественно все новые версии имеют испарвления
Вот приложил данный файл от последней версии 1.5.4.302 - нет там никаких исправлений.
*

Ernesto

  • Осваиваюсь на форуме
  • 35
  • 0 / 0
Re: Транслитерация title в sh404
« Ответ #15 : 02.12.2009, 19:27:24 »
Не смог отправить пишет:
Цитировать
Папка upload заполнена.
Вот файл shPageRewrite.php с последней версии 1.5.4.302:
Код: php
<?php
/**
 * shCustomTags Joomla module : php module
 * Copyright (C) 2006-2007 Yannick Gaultier (shumisha). All rights reserved.
 * Released under the http://www.gnu.org/copyleft/gpl.html GNU/GPL, doc/license and credits.txt
 * This is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses.
 *
 */

defined( '_JEXEC' ) or die( 'Restricted access' );

// V 1.2.4.t  check if sh404SEF is running
if (function_exists('shLoadPluginlanguage')) {

// support for improved TITLE, DESCRIPTION, KEYWORDS and ROBOTS head tag
global $shCustomTitleTag, $shCustomDescriptionTag, $shCustomKeywordsTag,
$shCustomRobotsTag, $shCustomLangTag;
// these variables can be set throughout your php code in components, bots or other modules
// the last one wins !


function shCleanUpTitle( $title) {
return JString::trim(JString::trim(stripslashes(html_entity_decode($title))), '"');
}

function shCleanUpDesc( $desc) {
$desc = stripslashes(html_entity_decode(strip_tags($desc, '<br><br /><p></p>'), ENT_NOQUOTES));
$desc = str_replace('<br>',' - ', $desc);  // otherwise, one word<br >another becomes onewordanother
$desc = str_replace('<br />',' - ', $desc);
$desc = str_replace('<p>',' - ', $desc);
$desc = str_replace('</p>',' - ', $desc);
while (strpos($desc, ' -  - ')!== false) {
$desc = str_replace(' -  - ', ' - ', $desc);
}
$desc = str_replace("&#39;",'\'', $desc);
$desc = str_replace("&#039;",'\'', $desc);
$desc = str_replace('"', '\'', $desc);
$desc = str_replace("\r",'', $desc);
$desc = str_replace("\n",'', $desc);
return JString::substr( JString::trim($desc), 0, 512);
}

// utility function to insert data into an HTML buffer, after, instead or before
// one or more instances of a tag. If last parameter is 'first', then only the
// first occurence of the tag is replaced, or the new value is inserted only
// after or before the first occurence of the tag

function shInsertCustomTagInBuffer( $buffer, $tag, $where, $value, $firstOnly) {
if (!$buffer || !$tag || !$value) return $buffer;
$bits = explode($tag, $buffer);
if (count($bits) < 2) return $buffer;
$result = $bits[0];
$maxCount = count($bits)-1;
switch ($where) {
case 'instead' :
for ($i=0; $i < $maxCount; $i++) {
$result .= ($firstOnly == 'first' ? ($i==0 ? $value:$tag):$value).$bits[$i+1];
}
break;
case 'after' :
for ($i=0; $i < $maxCount; $i++) {
$result .= $tag.($firstOnly == 'first' ? ($i==0 ? $value:$tag):$value).$bits[$i+1];
}
break;
default :
for ($i=0; $i < $maxCount; $i++) {
$result .= ($firstOnly == 'first' ? ($i==0 ? $value:$tag):$value).$tag.$bits[$i+1];
}
break;
}
return $result;
}

function shDoLinkReadMoreCallback($matches) {
if (count($matches)!= 3) return empty($matches)? '' : $matches[0];
$mask = '<td class="contentheading" width="100%">%%shM1%%title="%%shTitle%%" class="readon">%%shM2%%&nbsp;[%%shTitle%%]</a>';
$result = str_replace('%%shM2%%', $matches[2], $mask);
// we may have captured more than we want, if there are several articles, but only the last one has
// a Read more link (first ones may be intro-only articles). Need to make sure we are fetching the right title
$otherArticles = explode( '<td class="contentheading" width="100%">', $matches[1]);
$articlesCount = count ($otherArticles);
$matches[1] = $otherArticles[$articlesCount-1];
unset($otherArticles[$articlesCount-1]);

$bits = explode ('class="contentpagetitle">', $matches[1]);
if (count ($bits) > 1) {  // there is a linked title
$titleBits = array();
preg_match('/(.*)(<script|<\/a>)/isU', $bits[1], $titleBits); // extract title-may still have <h1> tags
$title = shCleanUpTitle( JString::trim($titleBits[1]));
} else {  // title is not linked
$titleBits = array();
preg_match('/(.*)(<script|<a\s*href=|<\/td>)/isU', $matches[1], $titleBits); // extract title-may still have <h1> tags
$title = str_replace('<h1>', '', $titleBits[1]);
$title = str_replace('</h1>', '', $title);
$title = shCleanUpTitle( JString::trim($title));
}
$result = str_replace('%%shTitle%%', $title, $result);
// restore possible additionnal articles
$articles = implode( '<td class="contentheading" width="100%">', $otherArticles);
$matches[1] = (empty($articles)? '': $articles . '<td class="contentheading" width="100%">'). $matches[1];
$result = str_replace('%%shM1%%', $matches[1], $result);
$result = str_replace('%%shM2%%', $matches[2], $result);
$result = str_replace( 'class="contentpagetitle">', 'title="'.$title.'" class="contentpagetitle">', $result);
return $result;
}

function shDoRedirectOutboundLinksCallback($matches) {
if (count($matches)!= 2) return empty($matches)? '' : $matches[0];
if (strpos($matches[1], $GLOBALS['shConfigLiveSite']) === false){
$mask = '<a href="'.$GLOBALS['shConfigLiveSite'].'/index.php?option=com_sh404sef&shtask=redirect&shtarget=%%shM1%%"';
$result = str_replace('%%shM1%%', $matches[1], $mask);
} else $result = $matches[0];
return $result;
}


function shDoInsertOutboundLinksImageCallback($matches) {
//if (count($matches)!= 2 && count($matches)!= 3) return empty($matches)? '' : $matches[0];
$orig = $matches[0];
$bits = explode('href=', $orig);
$part2 = $bits[1];  // 2nd part, after the href=
$sep = substr($part2, 0, 1);  // " or ' ?
$link = JString::trim($part2, $sep);  // remove first " or '
if (empty($sep)) { // this should not happen, but it happens (Fireboard)
$result = $matches[0];
return $result;
}
$link = explode($sep, $link);
$link = $link[0]; // keep only the link

$shPageInfo = & shRouter::shPageInfo();
$sefConfig = & shRouter::shGetConfig();

if ( substr($link, 0, strlen($GLOBALS['shConfigLiveSite']))!= $GLOBALS['shConfigLiveSite']
&& substr($link, 0, 7) == 'http://'
&& substr($link, 0, strlen($shPageInfo->base))!= $shPageInfo->base){

$mask = '%%shM1%%href="%%shM2%%" %%shM3%% >%%shM4%%<img border="0" alt="%%shM5%%" src="'
.$GLOBALS['shConfigLiveSite'].'/components/com_sh404sef/images/'
.$sefConfig->shImageForOutboundLinks
.'"/></a>';

$result = str_replace('%%shM1%%', $bits[0], $mask);
$result = str_replace('%%shM2%%', $link, $result);

$m3 = str_replace($sep.$link.$sep, '', str_replace('</a>', '', $part2)); // remove link from part 2
$bits2 = explode('>', $m3);
$m3 = $bits2[0];
$result = str_replace('%%shM3%%', $m3, $result);

array_shift($bits2); // remove first bit
$m4 = implode($bits2, '>');
$result = str_replace('%%shM4%%', $m4, $result);

$m5 = strip_tags($m4);
$result = str_replace('%%shM5%%', $m5, $result);

} else $result = $matches[0];
return $result;
}

function shDoTitleTags( &$buffer) {
// Replace TITLE and DESCRIPTION and KEYWORDS
if (empty($buffer)) return;
global $shCustomTitleTag, $shCustomDescriptionTag, $shCustomKeywordsTag,
$shCustomRobotsTag, $shCustomLangTag, $shHomeLink,
$shMosConfig_lang, $shMosConfig_locale;

$database = & JFactory::getDBO();
$sefConfig = & shRouter::shGetConfig();
$shPageInfo = & shRouter::shPageInfo();  // get page details gathered by system plugin

// V 1.2.4.t protect against error if using shCustomtags without sh404SEF activated
// this should not happen, so we simply do nothing
if (!isset($sefConfig) || empty( $shPageInfo->shCurrentPageNonSef)) {
return;
}

// fix bug in Joomla search
//$shUri = null;
//$shOriginalUri = null;
//$buffer = str_replace( 'action="index.php"', 'action="'.shSefRelToabs('index.php', '', $shUri, $shUri, $shOriginalUri).'"', $buffer);

// check if there is a manually created set of tags from tags file
// need to get them from DB
if ($sefConfig->shMetaManagementActivated) {

// get header data set through Joomla
$document = & JFactory::getDocument();
$joomlaHead = $document->getHeadData();
$joomlaMetaData = $joomlaHead['metaTags']['standard'];

//  plugin system to automatically build title and description tags on a component per component basis
$option = JRequest::getVar( 'option');
$shDoNotOverride = in_array( str_replace('com_', '', $option), $sefConfig->shDoNotOverrideOwnSef);

if ((file_exists(sh404SEF_ABS_PATH.'components/'.$option.'/meta_ext/'.$option.'.php'))
&& ($shDoNotOverride                   // and param said do not override
|| (!$shDoNotOverride              // or param said override, but we don't have a plugin
&& !file_exists(sh404SEF_ABS_PATH.'components/com_sh404sef/meta_ext/'.$option.'.php'))  )) {
_log('Loading component own meta plugin');  // Load the plug-in file
include(sh404SEF_ABS_PATH.'components/'.$option.'/meta_ext/'.$option.'.php');
} // then look for sh404SEF own plugin
else if (file_exists(sh404SEF_ABS_PATH.'components/com_sh404sef/meta_ext/'.$option.'.php')) {
_log('Loading built-in meta plugin');
include(sh404SEF_ABS_PATH.'components/com_sh404sef/meta_ext/'.$option.'.php');
}

// now read manually setup tags
if (shSortUrl($shPageInfo->shCurrentPageNonSef) == shCleanUpAnchor($shHomeLink)) { // V 1.2.4.t homepage custom tags
$sql = 'SELECT id, metadesc, metakey, metatitle, metalang, metarobots FROM #__sh404SEF_meta WHERE newurl = \''.sh404SEF_HOMEPAGE_CODE.'\'';
} else {
// V 1.2.4.t make sure we have lang info and properly sorted params
if (!preg_match( '/(&|\?) lang=[a-zA-Z]{2,3}/iU', $shPageInfo->shCurrentPageNonSef)) {  // no lang string, let's add default
$shTemp = explode( '_', $GLOBALS['shMosConfig_locale']);
$shLangTemp = $shTemp[0] ? $shTemp[0] : 'en';
$shPageInfo->shCurrentPageNonSef .= '&lang='.$shLangTemp;
}
$shPageInfo->shCurrentPageNonSef = shSortUrl($shPageInfo->shCurrentPageNonSef);
$sql = 'SELECT id, metadesc, metakey, metatitle, metalang, metarobots FROM #__sh404SEF_meta WHERE newurl = \''.ltrim($shPageInfo->shCurrentPageNonSef, '/').'\'';
}
$shCustomTags = null;
$database->setQuery($sql);
$shCustomTags = $database->loadObject();
if ( !empty($shCustomTags)) {
$shCustomTitleTag = !empty($shCustomTags->metatitle)? $shCustomTags->metatitle : $shCustomTitleTag;
$shCustomDescriptionTag = !empty($shCustomTags->metadesc)? $shCustomTags->metadesc : $shCustomDescriptionTag;
$shCustomKeywordsTag = !empty($shCustomTags->metakey)? $shCustomTags->metakey : $shCustomKeywordsTag;
$shCustomRobotsTag = !empty($shCustomTags->metarobots)? $shCustomTags->metarobots : $shCustomRobotsTag;
$shCustomLangTag = !empty($shCustomTags->metalang)? $shCustomTags->metalang : $shCustomLangTag;
}

// then insert them in page
if (!is_null($shCustomTitleTag)) {
$buffer = preg_replace( '/\<\s*title\s*\>.*\<\s*\/title\s*\>/isU', '<title>'
.shCleanUpTitle($sefConfig->prependToPageTitle.$shCustomTitleTag.$sefConfig->appendToPageTitle).'</title>', $buffer);
$buffer = preg_replace( '/\<\s*meta\s+name\s*=\s*"title.*\/\>/isU', '', $buffer); // remove Joomla title meta
}
if (!is_null($shCustomDescriptionTag)) {
$buffer = preg_replace( '/\<\s*meta\s+name\s*=\s*"description.*\/\>/isU', '<meta name="description" content="'
.shCleanUpDesc($shCustomDescriptionTag).'" />', $buffer);
}
if (!is_null($shCustomKeywordsTag)) {
$buffer = preg_replace( '/\<\s*meta\s+name\s*=\s*"keywords.*\/\>/isU', '<meta name="keywords" content="'
.shCleanUpDesc($shCustomKeywordsTag).'" />', $buffer);
}
if (!is_null($shCustomRobotsTag)) {
if (strpos($buffer, '<meta name="robots" content="')!== false) {
$buffer = preg_replace( '/\<\s*meta\s+name\s*=\s*"robots.*\/\>/isU', '<meta name="robots" content="'
.$shCustomRobotsTag.'" />', $buffer);
}
else if (!empty($shCustomRobotsTag)) {
$buffer = shInsertCustomTagInBuffer( $buffer, '</head>', 'before', '<meta name="robots" content="'
.$shCustomRobotsTag.'" />', 'first');
}
}
if (!is_null($shCustomLangTag)) {
$shLang = $shCustomLangTag;
}
else {
$shLang = $shMosConfig_locale;
}
if (strpos($buffer, '<meta http-equiv="Content-Language"')!== false) {
$buffer = preg_replace( '/\<\s*meta\s+http-equiv\s*=\s*"Content-Language".*\/\>/isU', '<meta http-equiv="Content-Language" content="'.$shLang.'" />', $buffer);
}
else if (!empty($shCustomLangTag)) {
$buffer = shInsertCustomTagInBuffer( $buffer, '</head>', 'before', '<meta http-equiv="Content-Language" content="'.$shLang.'" />', 'first');
}

// remove Generator tag
if ($sefConfig->shRemoveGeneratorTag) {
$buffer = preg_replace( '/<meta\s*name="Generator"\s*content=".*\/>/isU','', $buffer);
}


// version x : add title to read on link
if ($sefConfig->shInsertReadMorePageTitle) {
if (strpos( $buffer, 'class="readon"')!== false) {
$buffer = preg_replace_callback( '/<td class="contentheading" width="100%">(.*) class="readon">(.*)<\/a>/isU',
'shDoLinkReadMoreCallback', $buffer);
}
}
// put <h1> tags around content elements titles
if ($sefConfig->shPutH1Tags) {
if (strpos($buffer, 'class="componentheading')!== false) {
$buffer = preg_replace( '/<div class="componentheading([^>]*)>\s*(.*)\s*<\/div>/isU',
                              '<div class="componentheading<?php
/**
 * shCustomTags Joomla module : php module
 * Copyright (C) 2006-2007 Yannick Gaultier (shumisha). All rights reserved.
 * Released under the http://www.gnu.org/copyleft/gpl.html GNU/GPL, doc/license and credits.txt
 * This is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses.
 *
 */

defined( '_JEXEC' ) or die( 'Restricted access' );

// V 1.2.4.t  check if sh404SEF is running
if (function_exists('shLoadPluginlanguage')) {

// support for improved TITLE, DESCRIPTION, KEYWORDS and ROBOTS head tag
global $shCustomTitleTag, $shCustomDescriptionTag, $shCustomKeywordsTag,
$shCustomRobotsTag, $shCustomLangTag;
// these variables can be set throughout your php code in components, bots or other modules
// the last one wins !


function shCleanUpTitle( $title) {
return JString::trim(JString::trim(stripslashes(html_entity_decode($title))), '"');
}

function shCleanUpDesc( $desc) {
$desc = stripslashes(html_entity_decode(strip_tags($desc, '<br><br /><p></p>'), ENT_NOQUOTES));
$desc = str_replace('<br>',' - ', $desc);  // otherwise, one word<br >another becomes onewordanother
$desc = str_replace('<br />',' - ', $desc);
$desc = str_replace('<p>',' - ', $desc);
$desc = str_replace('</p>',' - ', $desc);
while (strpos($desc, ' -  - ')!== false) {
$desc = str_replace(' -  - ', ' - ', $desc);
}
$desc = str_replace("&#39;",'\'', $desc);
$desc = str_replace("&#039;",'\'', $desc);
$desc = str_replace('"', '\'', $desc);
$desc = str_replace("\r",'', $desc);
$desc = str_replace("\n",'', $desc);
return JString::substr( JString::trim($desc), 0, 512);
}

// utility function to insert data into an HTML buffer, after, instead or before
// one or more instances of a tag. If last parameter is 'first', then only the
// first occurence of the tag is replaced, or the new value is inserted only
// after or before the first occurence of the tag

function shInsertCustomTagInBuffer( $buffer, $tag, $where, $value, $firstOnly) {
if (!$buffer || !$tag || !$value) return $buffer;
$bits = explode($tag, $buffer);
if (count($bits) < 2) return $buffer;
$result = $bits[0];
$maxCount = count($bits)-1;
switch ($where) {
case 'instead' :
for ($i=0; $i < $maxCount; $i++) {
$result .= ($firstOnly == 'first' ? ($i==0 ? $value:$tag):$value).$bits[$i+1];
}
break;
case 'after' :
for ($i=0; $i < $maxCount; $i++) {
$result .= $tag.($firstOnly == 'first' ? ($i==0 ? $value:$tag):$value).$bits[$i+1];
}
break;
default :
for ($i=0; $i < $maxCount; $i++) {
$result .= ($firstOnly == 'first' ? ($i==0 ? $value:$tag):$value).$tag.$bits[$i+1];
}
break;
}
return $result;
}

function shDoLinkReadMoreCallback($matches) {
if (count($matches)!= 3) return empty($matches)? '' : $matches[0];
$mask = '<td class="contentheading" width="100%">%%shM1%%title="%%shTitle%%" class="readon">%%shM2%%&nbsp;[%%shTitle%%]</a>';
$result = str_replace('%%shM2%%', $matches[2], $mask);
// we may have captured more than we want, if there are several articles, but only the last one has
// a Read more link (first ones may be intro-only articles). Need to make sure we are fetching the right title
$otherArticles = explode( '<td class="contentheading" width="100%">', $matches[1]);
$articlesCount = count ($otherArticles);
$matches[1] = $otherArticles[$articlesCount-1];
unset($otherArticles[$articlesCount-1]);

$bits = explode ('class="contentpagetitle">', $matches[1]);
if (count ($bits) > 1) {  // there is a linked title
$titleBits = array();
preg_match('/(.*)(<script|<\/a>)/isU', $bits[1], $titleBits); // extract title-may still have <h1> tags
$title = shCleanUpTitle( JString::trim($titleBits[1]));
} else {  // title is not linked
$titleBits = array();
preg_match('/(.*)(<script|<a\s*href=|<\/td>)/isU', $matches[1], $titleBits); // extract title-may still have <h1> tags
$title = str_replace('<h1>', '', $titleBits[1]);
$title = str_replace('</h1>', '', $title);
$title = shCleanUpTitle( JString::trim($title));
}
$result = str_replace('%%shTitle%%', $title, $result);
// restore possible additionnal articles
$articles = implode( '<td class="contentheading" width="100%">', $otherArticles);
$matches[1] = (empty($articles)? '': $articles . '<td class="contentheading" width="100%">'). $matches[1];
$result = str_replace('%%shM1%%', $matches[1], $result);
$result = str_replace('%%shM2%%', $matches[2], $result);
$result = str_replace( 'class="contentpagetitle">', 'title="'.$title.'" class="contentpagetitle">', $result);
return $result;
}

function shDoRedirectOutboundLinksCallback($matches) {
if (count($matches)!= 2) return empty($matches)? '' : $matches[0];
if (strpos($matches[1], $GLOBALS['shConfigLiveSite']) === false){
$mask = '<a href="'.$GLOBALS['shConfigLiveSite'].'/index.php?option=com_sh404sef&shtask=redirect&shtarget=%%shM1%%"';
$result = str_replace('%%shM1%%', $matches[1], $mask);
} else $result = $matches[0];
return $result;
}


function shDoInsertOutboundLinksImageCallback($matches) {
//if (count($matches)!= 2 && count($matches)!= 3) return empty($matches)? '' : $matches[0];
$orig = $matches[0];
$bits = explode('href=', $orig);
$part2 = $bits[1];  // 2nd part, after the href=
$sep = substr($part2, 0, 1);  // " or ' ?
$link = JString::trim($part2, $sep);  // remove first " or '
if (empty($sep)) { // this should not happen, but it happens (Fireboard)
$result = $matches[0];
return $result;
}
$link = explode($sep, $link);
$link = $link[0]; // keep only the link

$shPageInfo = & shRouter::shPageInfo();
$sefConfig = & shRouter::shGetConfig();

if ( substr($link, 0, strlen($GLOBALS['shConfigLiveSite']))!= $GLOBALS['shConfigLiveSite']
&& substr($link, 0, 7) == 'http://'
&& substr($link, 0, strlen($shPageInfo->base))!= $shPageInfo->base){

$mask = '%%shM1%%href="%%shM2%%" %%shM3%% >%%shM4%%<img border="0" alt="%%shM5%%" src="'
.$GLOBALS['shConfigLiveSite'].'/components/com_sh404sef/images/'
.$sefConfig->shImageForOutboundLinks
.'"/></a>';

$result = str_replace('%%shM1%%', $bits[0], $mask);
$result = str_replace('%%shM2%%', $link, $result);

$m3 = str_replace($sep.$link.$sep, '', str_replace('</a>', '', $part2)); // remove link from part 2
$bits2 = explode('>', $m3);
$m3 = $bits2[0];
$result = str_replace('%%shM3%%', $m3, $result);

array_shift($bits2); // remove first bit
$m4 = implode($bits2, '>');
$result = str_replace('%%shM4%%', $m4, $result);

$m5 = strip_tags($m4);
$result = str_replace('%%shM5%%', $m5, $result);

} else $result = $matches[0];
return $result;
}

function shDoTitleTags( &$buffer) {
// Replace TITLE and DESCRIPTION and KEYWORDS
if (empty($buffer)) return;
global $shCustomTitleTag, $shCustomDescriptionTag, $shCustomKeywordsTag,
$shCustomRobotsTag, $shCustomLangTag, $shHomeLink,
$shMosConfig_lang, $shMosConfig_locale;

$database = & JFactory::getDBO();
$sefConfig = & shRouter::shGetConfig();
$shPageInfo = & shRouter::shPageInfo();  // get page details gathered by system plugin

// V 1.2.4.t protect against error if using shCustomtags without sh404SEF activated
// this should not happen, so we simply do nothing
if (!isset($sefConfig) || empty( $shPageInfo->shCurrentPageNonSef)) {
return;
}

// fix bug in Joomla search
//$shUri = null;
//$shOriginalUri = null;
//$buffer = str_replace( 'action="index.php"', 'action="'.shSefRelToabs('index.php', '', $shUri, $shUri, $shOriginalUri).'"', $buffer);

// check if there is a manually created set of tags from tags file
// need to get them from DB
if ($sefConfig->shMetaManagementActivated) {

// get header data set through Joomla
$document = & JFactory::getDocument();
$joomlaHead = $document->getHeadData();
$joomlaMetaData = $joomlaHead['metaTags']['standard'];

//  plugin system to automatically build title and description tags on a component per component basis
$option = JRequest::getVar( 'option');
$shDoNotOverride = in_array( str_replace('com_', '', $option), $sefConfig->shDoNotOverrideOwnSef);

if ((file_exists(sh404SEF_ABS_PATH.'components/'.$option.'/meta_ext/'.$option.'.php'))
&& ($shDoNotOverride                   // and param said do not override
|| (!$shDoNotOverride              // or param said override, but we don't have a plugin
&& !file_exists(sh404SEF_ABS_PATH.'components/com_sh404sef/meta_ext/'.$option.'.php'))  )) {
_log('Loading component own meta plugin');  // Load the plug-in file
include(sh404SEF_ABS_PATH.'components/'.$option.'/meta_ext/'.$option.'.php');
} // then look for sh404SEF own plugin
else if (file_exists(sh404SEF_ABS_PATH.'components/com_sh404sef/meta_ext/'.$option.'.php')) {
_log('Loading built-in meta plugin');
include(sh404SEF_ABS_PATH.'components/com_sh404sef/meta_ext/'.$option.'.php');
}

// now read manually setup tags
if (shSortUrl($shPageInfo->shCurrentPageNonSef) == shCleanUpAnchor($shHomeLink)) { // V 1.2.4.t homepage custom tags
$sql = 'SELECT id, metadesc, metakey, metatitle, metalang, metarobots FROM #__sh404SEF_meta WHERE newurl = \''.sh404SEF_HOMEPAGE_CODE.'\'';
} else {
// V 1.2.4.t make sure we have lang info and properly sorted params
if (!preg_match( '/(&|\?) lang=[a-zA-Z]{2,3}/iU', $shPageInfo->shCurrentPageNonSef)) {  // no lang string, let's add default
$shTemp = explode( '_', $GLOBALS['shMosConfig_locale']);
$shLangTemp = $shTemp[0] ? $shTemp[0] : 'en';
$shPageInfo->shCurrentPageNonSef .= '&lang='.$shLangTemp;
}
$shPageInfo->shCurrentPageNonSef = shSortUrl($shPageInfo->shCurrentPageNonSef);
$sql = 'SELECT id, metadesc, metakey, metatitle, metalang, metarobots FROM #__sh404SEF_meta WHERE newurl = \''.ltrim($shPageInfo->shCurrentPageNonSef, '/').'\'';
}
$shCustomTags = null;
$database->setQuery($sql);
$shCustomTags = $database->loadObject();
if ( !empty($shCustomTags)) {
$shCustomTitleTag = !empty($shCustomTags->metatitle)? $shCustomTags->metatitle : $shCustomTitleTag;
$shCustomDescriptionTag = !empty($shCustomTags->metadesc)? $shCustomTags->metadesc : $shCustomDescriptionTag;
$shCustomKeywordsTag = !empty($shCustomTags->metakey)? $shCustomTags->metakey : $shCustomKeywordsTag;
$shCustomRobotsTag = !empty($shCustomTags->metarobots)? $shCustomTags->metarobots : $shCustomRobotsTag;
$shCustomLangTag = !empty($shCustomTags->metalang)? $shCustomTags->metalang : $shCustomLangTag;
}

// then insert them in page
if (!is_null($shCustomTitleTag)) {
$buffer = preg_replace( '/\<\s*title\s*\>.*\<\s*\/title\s*\>/isU', '<title>'
.shCleanUpTitle($sefConfig->prependToPageTitle.$shCustomTitleTag.$sefConfig->appendToPageTitle).'</title>', $buffer);
$buffer = preg_replace( '/\<\s*meta\s+name\s*=\s*"title.*\/\>/isU', '', $buffer); // remove Joomla title meta
}
if (!is_null($shCustomDescriptionTag)) {
$buffer = preg_replace( '/\<\s*meta\s+name\s*=\s*"description.*\/\>/isU', '<meta name="description" content="'
.shCleanUpDesc($shCustomDescriptionTag).'" />', $buffer);
}
if (!is_null($shCustomKeywordsTag)) {
$buffer = preg_replace( '/\<\s*meta\s+name\s*=\s*"keywords.*\/\>/isU', '<meta name="keywords" content="'
.shCleanUpDesc($shCustomKeywordsTag).'" />', $buffer);
}
if (!is_null($shCustomRobotsTag)) {
if (strpos($buffer, '<meta name="robots" content="')!== false) {
$buffer = preg_replace( '/\<\s*meta\s+name\s*=\s*"robots.*\/\>/isU', '<meta name="robots" content="'
.$shCustomRobotsTag.'" />', $buffer);
}
else if (!empty($shCustomRobotsTag)) {
$buffer = shInsertCustomTagInBuffer( $buffer, '</head>', 'before', '<meta name="robots" content="'
.$shCustomRobotsTag.'" />', 'first');
}
}
if (!is_null($shCustomLangTag)) {
$shLang = $shCustomLangTag;
}
else {
$shLang = $shMosConfig_locale;
}
if (strpos($buffer, '<meta http-equiv="Content-Language"')!== false) {
$buffer = preg_replace( '/\<\s*meta\s+http-equiv\s*=\s*"Content-Language".*\/\>/isU', '<meta http-equiv="Content-Language" content="'.$shLang.'" />', $buffer);
}
else if (!empty($shCustomLangTag)) {
$buffer = shInsertCustomTagInBuffer( $buffer, '</head>', 'before', '<meta http-equiv="Content-Language" content="'.$shLang.'" />', 'first');
}

// remove Generator tag
if ($sefConfig->shRemoveGeneratorTag) {
$buffer = preg_replace( '/<meta\s*name="Generator"\s*content=".*\/>/isU','', $buffer);
}


// version x : add title to read on link
if ($sefConfig->shInsertReadMorePageTitle) {
if (strpos( $buffer, 'class="readon"')!== false) {
$buffer = preg_replace_callback( '/<td class="contentheading" width="100%">(.*) class="readon">(.*)<\/a>/isU',
'shDoLinkReadMoreCallback', $buffer);
}
}
// put <h1> tags around content elements titles
if ($sefConfig->shPutH1Tags) {
if (strpos($buffer, 'class="componentheading')!== false) {
$buffer = preg_replace( '/<div class="componentheading([^>]*)>\s*(.*)\s*<\/div>/isU',
                              '<div class="componentheading$1><h1>$2</h1></div>', $buffer);   
$buffer = preg_replace( '/<td class="contentheading([^>]*)>\s*(.*)\s*<\/td>/isU',
                              '<td class="contentheading$1><h2>$2</h2></td>', $buffer);
} else {  // replace contentheading by h1
$buffer = preg_replace( '/<td class="contentheading([^>]*)>\s*(.*)\s*<\/td>/isU',
                              '<td class="contentheading$1><h1>$2</h1></td>', $buffer);
}
}

// version x : if multiple h1 headings, replace them by h2
if ($sefConfig->shMultipleH1ToH2 && substr_count( JString::strtolower($buffer), '<h1>') > 1) {
$buffer = str_replace( '<h1>', '<h2>', $buffer);
$buffer = str_replace( '<H1>', '<h2>', $buffer);
$buffer = str_replace( '</h1>', '</h2>', $buffer);
$buffer = str_replace( '</H1>', '</h2>', $buffer);
}

// V 1.3.1 : replace outbounds links by internal redirects
if (sh404SEF_REDIRECT_OUTBOUND_LINKS) {
$buffer = preg_replace_callback( '/<\s*a\s*href\s*=\s*"(.*)"/isU',
'shDoRedirectOutboundLinksCallback', $buffer);
}

// V 1.3.1 : add symbol to outbounds links
if ($sefConfig->shInsertOutboundLinksImage) {
$buffer = preg_replace_callback( "/<\s*a\s*href\s*=\s*(\"|').*(\"|')\s*>.*<\/a>/isU",
'shDoInsertOutboundLinksImageCallback', $buffer);
}

// all done
return $buffer;
}
}

// begin main output --------------------------------------------------------

// check we are outputting document for real
$document = &JFactory::getDocument();
if ($document->getType() == 'html') {
$shPage = JResponse::getBody();

// do TITLE and DESCRIPTION and KEYWORDS and ROBOTS tags replacement
shDoTitleTags( $shPage);

if (SH_SHOW_CACHE_STATS)
$shPage .= shShowCacheStats();

JResponse::setBody($shPage);
}
// }
}

?>
><h1>php</h1></div>', $buffer);   
$buffer = preg_replace( '/<td class="contentheading([^>]*)>\s*(.*)\s*<\/td>/isU',
                              '<td class="contentheading<?php
/**
 * shCustomTags Joomla module : php module
 * Copyright (C) 2006-2007 Yannick Gaultier (shumisha). All rights reserved.
 * Released under the http://www.gnu.org/copyleft/gpl.html GNU/GPL, doc/license and credits.txt
 * This is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses.
 *
 */

defined( '_JEXEC' ) or die( 'Restricted access' );

// V 1.2.4.t  check if sh404SEF is running
if (function_exists('shLoadPluginlanguage')) {

// support for improved TITLE, DESCRIPTION, KEYWORDS and ROBOTS head tag
global $shCustomTitleTag, $shCustomDescriptionTag, $shCustomKeywordsTag,
$shCustomRobotsTag, $shCustomLangTag;
// these variables can be set throughout your php code in components, bots or other modules
// the last one wins !


function shCleanUpTitle( $title) {
return JString::trim(JString::trim(stripslashes(html_entity_decode($title))), '"');
}

function shCleanUpDesc( $desc) {
$desc = stripslashes(html_entity_decode(strip_tags($desc, '<br><br /><p></p>'), ENT_NOQUOTES));
$desc = str_replace('<br>',' - ', $desc);  // otherwise, one word<br >another becomes onewordanother
$desc = str_replace('<br />',' - ', $desc);
$desc = str_replace('<p>',' - ', $desc);
$desc = str_replace('</p>',' - ', $desc);
while (strpos($desc, ' -  - ')!== false) {
$desc = str_replace(' -  - ', ' - ', $desc);
}
$desc = str_replace("&#39;",'\'', $desc);
$desc = str_replace("&#039;",'\'', $desc);
$desc = str_replace('"', '\'', $desc);
$desc = str_replace("\r",'', $desc);
$desc = str_replace("\n",'', $desc);
return JString::substr( JString::trim($desc), 0, 512);
}

// utility function to insert data into an HTML buffer, after, instead or before
// one or more instances of a tag. If last parameter is 'first', then only the
// first occurence of the tag is replaced, or the new value is inserted only
// after or before the first occurence of the tag

function shInsertCustomTagInBuffer( $buffer, $tag, $where, $value, $firstOnly) {
if (!$buffer || !$tag || !$value) return $buffer;
$bits = explode($tag, $buffer);
if (count($bits) < 2) return $buffer;
$result = $bits[0];
$maxCount = count($bits)-1;
switch ($where) {
case 'instead' :
for ($i=0; $i < $maxCount; $i++) {
$result .= ($firstOnly == 'first' ? ($i==0 ? $value:$tag):$value).$bits[$i+1];
}
break;
case 'after' :
for ($i=0; $i < $maxCount; $i++) {
$result .= $tag.($firstOnly == 'first' ? ($i==0 ? $value:$tag):$value).$bits[$i+1];
}
break;
default :
for ($i=0; $i < $maxCount; $i++) {
$result .= ($firstOnly == 'first' ? ($i==0 ? $value:$tag):$value).$tag.$bits[$i+1];
}
break;
}
return $result;
}

function shDoLinkReadMoreCallback($matches) {
if (count($matches)!= 3) return empty($matches)? '' : $matches[0];
$mask = '<td class="contentheading" width="100%">%%shM1%%title="%%shTitle%%" class="readon">%%shM2%%&nbsp;[%%shTitle%%]</a>';
$result = str_replace('%%shM2%%', $matches[2], $mask);
// we may have captured more than we want, if there are several articles, but only the last one has
// a Read more link (first ones may be intro-only articles). Need to make sure we are fetching the right title
$otherArticles = explode( '<td class="contentheading" width="100%">', $matches[1]);
$articlesCount = count ($otherArticles);
$matches[1] = $otherArticles[$articlesCount-1];
unset($otherArticles[$articlesCount-1]);

$bits = explode ('class="contentpagetitle">', $matches[1]);
if (count ($bits) > 1) {  // there is a linked title
$titleBits = array();
preg_match('/(.*)(<script|<\/a>)/isU', $bits[1], $titleBits); // extract title-may still have <h1> tags
$title = shCleanUpTitle( JString::trim($titleBits[1]));
} else {  // title is not linked
$titleBits = array();
preg_match('/(.*)(<script|<a\s*href=|<\/td>)/isU', $matches[1], $titleBits); // extract title-may still have <h1> tags
$title = str_replace('<h1>', '', $titleBits[1]);
$title = str_replace('</h1>', '', $title);
$title = shCleanUpTitle( JString::trim($title));
}
$result = str_replace('%%shTitle%%', $title, $result);
// restore possible additionnal articles
$articles = implode( '<td class="contentheading" width="100%">', $otherArticles);
$matches[1] = (empty($articles)? '': $articles . '<td class="contentheading" width="100%">'). $matches[1];
$result = str_replace('%%shM1%%', $matches[1], $result);
$result = str_replace('%%shM2%%', $matches[2], $result);
$result = str_replace( 'class="contentpagetitle">', 'title="'.$title.'" class="contentpagetitle">', $result);
return $result;
}

function shDoRedirectOutboundLinksCallback($matches) {
if (count($matches)!= 2) return empty($matches)? '' : $matches[0];
if (strpos($matches[1], $GLOBALS['shConfigLiveSite']) === false){
$mask = '<a href="'.$GLOBALS['shConfigLiveSite'].'/index.php?option=com_sh404sef&shtask=redirect&shtarget=%%shM1%%"';
$result = str_replace('%%shM1%%', $matches[1], $mask);
} else $result = $matches[0];
return $result;
}


function shDoInsertOutboundLinksImageCallback($matches) {
//if (count($matches)!= 2 && count($matches)!= 3) return empty($matches)? '' : $matches[0];
$orig = $matches[0];
$bits = explode('href=', $orig);
$part2 = $bits[1];  // 2nd part, after the href=
$sep = substr($part2, 0, 1);  // " or ' ?
$link = JString::trim($part2, $sep);  // remove first " or '
if (empty($sep)) { // this should not happen, but it happens (Fireboard)
$result = $matches[0];
return $result;
}
$link = explode($sep, $link);
$link = $link[0]; // keep only the link

$shPageInfo = & shRouter::shPageInfo();
$sefConfig = & shRouter::shGetConfig();

if ( substr($link, 0, strlen($GLOBALS['shConfigLiveSite']))!= $GLOBALS['shConfigLiveSite']
&& substr($link, 0, 7) == 'http://'
&& substr($link, 0, strlen($shPageInfo->base))!= $shPageInfo->base){

$mask = '%%shM1%%href="%%shM2%%" %%shM3%% >%%shM4%%<img border="0" alt="%%shM5%%" src="'
.$GLOBALS['shConfigLiveSite'].'/components/com_sh404sef/images/'
.$sefConfig->shImageForOutboundLinks
.'"/></a>';

$result = str_replace('%%shM1%%', $bits[0], $mask);
$result = str_replace('%%shM2%%', $link, $result);

$m3 = str_replace($sep.$link.$sep, '', str_replace('</a>', '', $part2)); // remove link from part 2
$bits2 = explode('>', $m3);
$m3 = $bits2[0];
$result = str_replace('%%shM3%%', $m3, $result);

array_shift($bits2); // remove first bit
$m4 = implode($bits2, '>');
$result = str_replace('%%shM4%%', $m4, $result);

$m5 = strip_tags($m4);
$result = str_replace('%%shM5%%', $m5, $result);

} else $result = $matches[0];
return $result;
}

function shDoTitleTags( &$buffer) {
// Replace TITLE and DESCRIPTION and KEYWORDS
if (empty($buffer)) return;
global $shCustomTitleTag, $shCustomDescriptionTag, $shCustomKeywordsTag,
$shCustomRobotsTag, $shCustomLangTag, $shHomeLink,
$shMosConfig_lang, $shMosConfig_locale;

$database = & JFactory::getDBO();
$sefConfig = & shRouter::shGetConfig();
$shPageInfo = & shRouter::shPageInfo();  // get page details gathered by system plugin

// V 1.2.4.t protect against error if using shCustomtags without sh404SEF activated
// this should not happen, so we simply do nothing
if (!isset($sefConfig) || empty( $shPageInfo->shCurrentPageNonSef)) {
return;
}

// fix bug in Joomla search
//$shUri = null;
//$shOriginalUri = null;
//$buffer = str_replace( 'action="index.php"', 'action="'.shSefRelToabs('index.php', '', $shUri, $shUri, $shOriginalUri).'"', $buffer);

// check if there is a manually created set of tags from tags file
// need to get them from DB
if ($sefConfig->shMetaManagementActivated) {

// get header data set through Joomla
$document = & JFactory::getDocument();
$joomlaHead = $document->getHeadData();
$joomlaMetaData = $joomlaHead['metaTags']['standard'];

//  plugin system to automatically build title and description tags on a component per component basis
$option = JRequest::getVar( 'option');
$shDoNotOverride = in_array( str_replace('com_', '', $option), $sefConfig->shDoNotOverrideOwnSef);

if ((file_exists(sh404SEF_ABS_PATH.'components/'.$option.'/meta_ext/'.$option.'.php'))
&& ($shDoNotOverride                   // and param said do not override
|| (!$shDoNotOverride              // or param said override, but we don't have a plugin
&& !file_exists(sh404SEF_ABS_PATH.'components/com_sh404sef/meta_ext/'.$option.'.php'))  )) {
_log('Loading component own meta plugin');  // Load the plug-in file
include(sh404SEF_ABS_PATH.'components/'.$option.'/meta_ext/'.$option.'.php');
} // then look for sh404SEF own plugin
else if (file_exists(sh404SEF_ABS_PATH.'components/com_sh404sef/meta_ext/'.$option.'.php')) {
_log('Loading built-in meta plugin');
include(sh404SEF_ABS_PATH.'components/com_sh404sef/meta_ext/'.$option.'.php');
}

// now read manually setup tags
if (shSortUrl($shPageInfo->shCurrentPageNonSef) == shCleanUpAnchor($shHomeLink)) { // V 1.2.4.t homepage custom tags
$sql = 'SELECT id, metadesc, metakey, metatitle, metalang, metarobots FROM #__sh404SEF_meta WHERE newurl = \''.sh404SEF_HOMEPAGE_CODE.'\'';
} else {
// V 1.2.4.t make sure we have lang info and properly sorted params
if (!preg_match( '/(&|\?) lang=[a-zA-Z]{2,3}/iU', $shPageInfo->shCurrentPageNonSef)) {  // no lang string, let's add default
$shTemp = explode( '_', $GLOBALS['shMosConfig_locale']);
$shLangTemp = $shTemp[0] ? $shTemp[0] : 'en';
$shPageInfo->shCurrentPageNonSef .= '&lang='.$shLangTemp;
}
$shPageInfo->shCurrentPageNonSef = shSortUrl($shPageInfo->shCurrentPageNonSef);
$sql = 'SELECT id, metadesc, metakey, metatitle, metalang, metarobots FROM #__sh404SEF_meta WHERE newurl = \''.ltrim($shPageInfo->shCurrentPageNonSef, '/').'\'';
}
$shCustomTags = null;
$database->setQuery($sql);
$shCustomTags = $database->loadObject();
if ( !empty($shCustomTags)) {
$shCustomTitleTag = !empty($shCustomTags->metatitle)? $shCustomTags->metatitle : $shCustomTitleTag;
$shCustomDescriptionTag = !empty($shCustomTags->metadesc)? $shCustomTags->metadesc : $shCustomDescriptionTag;
$shCustomKeywordsTag = !empty($shCustomTags->metakey)? $shCustomTags->metakey : $shCustomKeywordsTag;
$shCustomRobotsTag = !empty($shCustomTags->metarobots)? $shCustomTags->metarobots : $shCustomRobotsTag;
$shCustomLangTag = !empty($shCustomTags->metalang)? $shCustomTags->metalang : $shCustomLangTag;
}

// then insert them in page
if (!is_null($shCustomTitleTag)) {
$buffer = preg_replace( '/\<\s*title\s*\>.*\<\s*\/title\s*\>/isU', '<title>'
.shCleanUpTitle($sefConfig->prependToPageTitle.$shCustomTitleTag.$sefConfig->appendToPageTitle).'</title>', $buffer);
$buffer = preg_replace( '/\<\s*meta\s+name\s*=\s*"title.*\/\>/isU', '', $buffer); // remove Joomla title meta
}
if (!is_null($shCustomDescriptionTag)) {
$buffer = preg_replace( '/\<\s*meta\s+name\s*=\s*"description.*\/\>/isU', '<meta name="description" content="'
.shCleanUpDesc($shCustomDescriptionTag).'" />', $buffer);
}
if (!is_null($shCustomKeywordsTag)) {
$buffer = preg_replace( '/\<\s*meta\s+name\s*=\s*"keywords.*\/\>/isU', '<meta name="keywords" content="'
.shCleanUpDesc($shCustomKeywordsTag).'" />', $buffer);
}
if (!is_null($shCustomRobotsTag)) {
if (strpos($buffer, '<meta name="robots" content="')!== false) {
$buffer = preg_replace( '/\<\s*meta\s+name\s*=\s*"robots.*\/\>/isU', '<meta name="robots" content="'
.$shCustomRobotsTag.'" />', $buffer);
}
else if (!empty($shCustomRobotsTag)) {
$buffer = shInsertCustomTagInBuffer( $buffer, '</head>', 'before', '<meta name="robots" content="'
.$shCustomRobotsTag.'" />', 'first');
}
}
if (!is_null($shCustomLangTag)) {
$shLang = $shCustomLangTag;
}
else {
$shLang = $shMosConfig_locale;
}
if (strpos($buffer, '<meta http-equiv="Content-Language"')!== false) {
$buffer = preg_replace( '/\<\s*meta\s+http-equiv\s*=\s*"Content-Language".*\/\>/isU', '<meta http-equiv="Content-Language" content="'.$shLang.'" />', $buffer);
}
else if (!empty($shCustomLangTag)) {
$buffer = shInsertCustomTagInBuffer( $buffer, '</head>', 'before', '<meta http-equiv="Content-Language" content="'.$shLang.'" />', 'first');
}

// remove Generator tag
if ($sefConfig->shRemoveGeneratorTag) {
$buffer = preg_replace( '/<meta\s*name="Generator"\s*content=".*\/>/isU','', $buffer);
}


// version x : add title to read on link
if ($sefConfig->shInsertReadMorePageTitle) {
if (strpos( $buffer, 'class="readon"')!== false) {
$buffer = preg_replace_callback( '/<td class="contentheading" width="100%">(.*) class="readon">(.*)<\/a>/isU',
'shDoLinkReadMoreCallback', $buffer);
}
}
// put <h1> tags around content elements titles
if ($sefConfig->shPutH1Tags) {
if (strpos($buffer, 'class="componentheading')!== false) {
$buffer = preg_replace( '/<div class="componentheading([^>]*)>\s*(.*)\s*<\/div>/isU',
                              '<div class="componentheading$1><h1>$2</h1></div>', $buffer);   
$buffer = preg_replace( '/<td class="contentheading([^>]*)>\s*(.*)\s*<\/td>/isU',
                              '<td class="contentheading$1><h2>$2</h2></td>', $buffer);
} else {  // replace contentheading by h1
$buffer = preg_replace( '/<td class="contentheading([^>]*)>\s*(.*)\s*<\/td>/isU',
                              '<td class="contentheading$1><h1>$2</h1></td>', $buffer);
}
}

// version x : if multiple h1 headings, replace them by h2
if ($sefConfig->shMultipleH1ToH2 && substr_count( JString::strtolower($buffer), '<h1>') > 1) {
$buffer = str_replace( '<h1>', '<h2>', $buffer);
$buffer = str_replace( '<H1>', '<h2>', $buffer);
$buffer = str_replace( '</h1>', '</h2>', $buffer);
$buffer = str_replace( '</H1>', '</h2>', $buffer);
}

// V 1.3.1 : replace outbounds links by internal redirects
if (sh404SEF_REDIRECT_OUTBOUND_LINKS) {
$buffer = preg_replace_callback( '/<\s*a\s*href\s*=\s*"(.*)"/isU',
'shDoRedirectOutboundLinksCallback', $buffer);
}

// V 1.3.1 : add symbol to outbounds links
if ($sefConfig->shInsertOutboundLinksImage) {
$buffer = preg_replace_callback( "/<\s*a\s*href\s*=\s*(\"|').*(\"|')\s*>.*<\/a>/isU",
'shDoInsertOutboundLinksImageCallback', $buffer);
}

// all done
return $buffer;
}
}

// begin main output --------------------------------------------------------

// check we are outputting document for real
$document = &JFactory::getDocument();
if ($document->getType() == 'html') {
$shPage = JResponse::getBody();

// do TITLE and DESCRIPTION and KEYWORDS and ROBOTS tags replacement
shDoTitleTags( $shPage);

if (SH_SHOW_CACHE_STATS)
$shPage .= shShowCacheStats();

JResponse::setBody($shPage);
}
// }
}

?>
><h2>php</h2></td>', $buffer);
} else {  // replace contentheading by h1
$buffer = preg_replace( '/<td class="contentheading([^>]*)>\s*(.*)\s*<\/td>/isU',
                              '<td class="contentheading<?php
/**
 * shCustomTags Joomla module : php module
 * Copyright (C) 2006-2007 Yannick Gaultier (shumisha). All rights reserved.
 * Released under the http://www.gnu.org/copyleft/gpl.html GNU/GPL, doc/license and credits.txt
 * This is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses.
 *
 */

defined( '_JEXEC' ) or die( 'Restricted access' );

// V 1.2.4.t  check if sh404SEF is running
if (function_exists('shLoadPluginlanguage')) {

// support for improved TITLE, DESCRIPTION, KEYWORDS and ROBOTS head tag
global $shCustomTitleTag, $shCustomDescriptionTag, $shCustomKeywordsTag,
$shCustomRobotsTag, $shCustomLangTag;
// these variables can be set throughout your php code in components, bots or other modules
// the last one wins !


function shCleanUpTitle( $title) {
return JString::trim(JString::trim(stripslashes(html_entity_decode($title))), '"');
}

function shCleanUpDesc( $desc) {
$desc = stripslashes(html_entity_decode(strip_tags($desc, '<br><br /><p></p>'), ENT_NOQUOTES));
$desc = str_replace('<br>',' - ', $desc);  // otherwise, one word<br >another becomes onewordanother
$desc = str_replace('<br />',' - ', $desc);
$desc = str_replace('<p>',' - ', $desc);
$desc = str_replace('</p>',' - ', $desc);
while (strpos($desc, ' -  - ')!== false) {
$desc = str_replace(' -  - ', ' - ', $desc);
}
$desc = str_replace("&#39;",'\'', $desc);
$desc = str_replace("&#039;",'\'', $desc);
$desc = str_replace('"', '\'', $desc);
$desc = str_replace("\r",'', $desc);
$desc = str_replace("\n",'', $desc);
return JString::substr( JString::trim($desc), 0, 512);
}

// utility function to insert data into an HTML buffer, after, instead or before
// one or more instances of a tag. If last parameter is 'first', then only the
// first occurence of the tag is replaced, or the new value is inserted only
// after or before the first occurence of the tag

function shInsertCustomTagInBuffer( $buffer, $tag, $where, $value, $firstOnly) {
if (!$buffer || !$tag || !$value) return $buffer;
$bits = explode($tag, $buffer);
if (count($bits) < 2) return $buffer;
$result = $bits[0];
$maxCount = count($bits)-1;
switch ($where) {
case 'instead' :
for ($i=0; $i < $maxCount; $i++) {
$result .= ($firstOnly == 'first' ? ($i==0 ? $value:$tag):$value).$bits[$i+1];
}
break;
case 'after' :
for ($i=0; $i < $maxCount; $i++) {
$result .= $tag.($firstOnly == 'first' ? ($i==0 ? $value:$tag):$value).$bits[$i+1];
}
break;
default :
for ($i=0; $i < $maxCount; $i++) {
$result .= ($firstOnly == 'first' ? ($i==0 ? $value:$tag):$value).$tag.$bits[$i+1];
}
break;
}
return $result;
}

function shDoLinkReadMoreCallback($matches) {
if (count($matches)!= 3) return empty($matches)? '' : $matches[0];
$mask = '<td class="contentheading" width="100%">%%shM1%%title="%%shTitle%%" class="readon">%%shM2%%&nbsp;[%%shTitle%%]</a>';
$result = str_replace('%%shM2%%', $matches[2], $mask);
// we may have captured more than we want, if there are several articles, but only the last one has
// a Read more link (first ones may be intro-only articles). Need to make sure we are fetching the right title
$otherArticles = explode( '<td class="contentheading" width="100%">', $matches[1]);
$articlesCount = count ($otherArticles);
$matches[1] = $otherArticles[$articlesCount-1];
unset($otherArticles[$articlesCount-1]);

$bits = explode ('class="contentpagetitle">', $matches[1]);
if (count ($bits) > 1) {  // there is a linked title
$titleBits = array();
preg_match('/(.*)(<script|<\/a>)/isU', $bits[1], $titleBits); // extract title-may still have <h1> tags
$title = shCleanUpTitle( JString::trim($titleBits[1]));
} else {  // title is not linked
$titleBits = array();
preg_match('/(.*)(<script|<a\s*href=|<\/td>)/isU', $matches[1], $titleBits); // extract title-may still have <h1> tags
$title = str_replace('<h1>', '', $titleBits[1]);
$title = str_replace('</h1>', '', $title);
$title = shCleanUpTitle( JString::trim($title));
}
$result = str_replace('%%shTitle%%', $title, $result);
// restore possible additionnal articles
$articles = implode( '<td class="contentheading" width="100%">', $otherArticles);
$matches[1] = (empty($articles)? '': $articles . '<td class="contentheading" width="100%">'). $matches[1];
$result = str_replace('%%shM1%%', $matches[1], $result);
$result = str_replace('%%shM2%%', $matches[2], $result);
$result = str_replace( 'class="contentpagetitle">', 'title="'.$title.'" class="contentpagetitle">', $result);
return $result;
}

function shDoRedirectOutboundLinksCallback($matches) {
if (count($matches)!= 2) return empty($matches)? '' : $matches[0];
if (strpos($matches[1], $GLOBALS['shConfigLiveSite']) === false){
$mask = '<a href="'.$GLOBALS['shConfigLiveSite'].'/index.php?option=com_sh404sef&shtask=redirect&shtarget=%%shM1%%"';
$result = str_replace('%%shM1%%', $matches[1], $mask);
} else $result = $matches[0];
return $result;
}


function shDoInsertOutboundLinksImageCallback($matches) {
//if (count($matches)!= 2 && count($matches)!= 3) return empty($matches)? '' : $matches[0];
$orig = $matches[0];
$bits = explode('href=', $orig);
$part2 = $bits[1];  // 2nd part, after the href=
$sep = substr($part2, 0, 1);  // " or ' ?
$link = JString::trim($part2, $sep);  // remove first " or '
if (empty($sep)) { // this should not happen, but it happens (Fireboard)
$result = $matches[0];
return $result;
}
$link = explode($sep, $link);
$link = $link[0]; // keep only the link

$shPageInfo = & shRouter::shPageInfo();
$sefConfig = & shRouter::shGetConfig();

if ( substr($link, 0, strlen($GLOBALS['shConfigLiveSite']))!= $GLOBALS['shConfigLiveSite']
&& substr($link, 0, 7) == 'http://'
&& substr($link, 0, strlen($shPageInfo->base))!= $shPageInfo->base){

$mask = '%%shM1%%href="%%shM2%%" %%shM3%% >%%shM4%%<img border="0" alt="%%shM5%%" src="'
.$GLOBALS['shConfigLiveSite'].'/components/com_sh404sef/images/'
.$sefConfig->shImageForOutboundLinks
.'"/></a>';

$result = str_replace('%%shM1%%', $bits[0], $mask);
$result = str_replace('%%shM2%%', $link, $result);

$m3 = str_replace($sep.$link.$sep, '', str_replace('</a>', '', $part2)); // remove link from part 2
$bits2 = explode('>', $m3);
$m3 = $bits2[0];
$result = str_replace('%%shM3%%', $m3, $result);

array_shift($bits2); // remove first bit
$m4 = implode($bits2, '>');
$result = str_replace('%%shM4%%', $m4, $result);

$m5 = strip_tags($m4);
$result = str_replace('%%shM5%%', $m5, $result);

} else $result = $matches[0];
return $result;
}

function shDoTitleTags( &$buffer) {
// Replace TITLE and DESCRIPTION and KEYWORDS
if (empty($buffer)) return;
global $shCustomTitleTag, $shCustomDescriptionTag, $shCustomKeywordsTag,
$shCustomRobotsTag, $shCustomLangTag, $shHomeLink,
$shMosConfig_lang, $shMosConfig_locale;

$database = & JFactory::getDBO();
$sefConfig = & shRouter::shGetConfig();
$shPageInfo = & shRouter::shPageInfo();  // get page details gathered by system plugin

// V 1.2.4.t protect against error if using shCustomtags without sh404SEF activated
// this should not happen, so we simply do nothing
if (!isset($sefConfig) || empty( $shPageInfo->shCurrentPageNonSef)) {
return;
}

// fix bug in Joomla search
//$shUri = null;
//$shOriginalUri = null;
//$buffer = str_replace( 'action="index.php"', 'action="'.shSefRelToabs('index.php', '', $shUri, $shUri, $shOriginalUri).'"', $buffer);

// check if there is a manually created set of tags from tags file
// need to get them from DB
if ($sefConfig->shMetaManagementActivated) {

// get header data set through Joomla
$document = & JFactory::getDocument();
$joomlaHead = $document->getHeadData();
$joomlaMetaData = $joomlaHead['metaTags']['standard'];

//  plugin system to automatically build title and description tags on a component per component basis
$option = JRequest::getVar( 'option');
$shDoNotOverride = in_array( str_replace('com_', '', $option), $sefConfig->shDoNotOverrideOwnSef);

if ((file_exists(sh404SEF_ABS_PATH.'components/'.$option.'/meta_ext/'.$option.'.php'))
&& ($shDoNotOverride                   // and param said do not override
|| (!$shDoNotOverride              // or param said override, but we don't have a plugin
&& !file_exists(sh404SEF_ABS_PATH.'components/com_sh404sef/meta_ext/'.$option.'.php'))  )) {
_log('Loading component own meta plugin');  // Load the plug-in file
include(sh404SEF_ABS_PATH.'components/'.$option.'/meta_ext/'.$option.'.php');
} // then look for sh404SEF own plugin
else if (file_exists(sh404SEF_ABS_PATH.'components/com_sh404sef/meta_ext/'.$option.'.php')) {
_log('Loading built-in meta plugin');
include(sh404SEF_ABS_PATH.'components/com_sh404sef/meta_ext/'.$option.'.php');
}

// now read manually setup tags
if (shSortUrl($shPageInfo->shCurrentPageNonSef) == shCleanUpAnchor($shHomeLink)) { // V 1.2.4.t homepage custom tags
$sql = 'SELECT id, metadesc, metakey, metatitle, metalang, metarobots FROM #__sh404SEF_meta WHERE newurl = \''.sh404SEF_HOMEPAGE_CODE.'\'';
} else {
// V 1.2.4.t make sure we have lang info and properly sorted params
if (!preg_match( '/(&|\?) lang=[a-zA-Z]{2,3}/iU', $shPageInfo->shCurrentPageNonSef)) {  // no lang string, let's add default
$shTemp = explode( '_', $GLOBALS['shMosConfig_locale']);
$shLangTemp = $shTemp[0] ? $shTemp[0] : 'en';
$shPageInfo->shCurrentPageNonSef .= '&lang='.$shLangTemp;
}
$shPageInfo->shCurrentPageNonSef = shSortUrl($shPageInfo->shCurrentPageNonSef);
$sql = 'SELECT id, metadesc, metakey, metatitle, metalang, metarobots FROM #__sh404SEF_meta WHERE newurl = \''.ltrim($shPageInfo->shCurrentPageNonSef, '/').'\'';
}
$shCustomTags = null;
$database->setQuery($sql);
$shCustomTags = $database->loadObject();
if ( !empty($shCustomTags)) {
$shCustomTitleTag = !empty($shCustomTags->metatitle)? $shCustomTags->metatitle : $shCustomTitleTag;
$shCustomDescriptionTag = !empty($shCustomTags->metadesc)? $shCustomTags->metadesc : $shCustomDescriptionTag;
$shCustomKeywordsTag = !empty($shCustomTags->metakey)? $shCustomTags->metakey : $shCustomKeywordsTag;
$shCustomRobotsTag = !empty($shCustomTags->metarobots)? $shCustomTags->metarobots : $shCustomRobotsTag;
$shCustomLangTag = !empty($shCustomTags->metalang)? $shCustomTags->metalang : $shCustomLangTag;
}

// then insert them in page
if (!is_null($shCustomTitleTag)) {
$buffer = preg_replace( '/\<\s*title\s*\>.*\<\s*\/title\s*\>/isU', '<title>'
.shCleanUpTitle($sefConfig->prependToPageTitle.$shCustomTitleTag.$sefConfig->appendToPageTitle).'</title>', $buffer);
$buffer = preg_replace( '/\<\s*meta\s+name\s*=\s*"title.*\/\>/isU', '', $buffer); // remove Joomla title meta
}
if (!is_null($shCustomDescriptionTag)) {
$buffer = preg_replace( '/\<\s*meta\s+name\s*=\s*"description.*\/\>/isU', '<meta name="description" content="'
.shCleanUpDesc($shCustomDescriptionTag).'" />', $buffer);
}
if (!is_null($shCustomKeywordsTag)) {
$buffer = preg_replace( '/\<\s*meta\s+name\s*=\s*"keywords.*\/\>/isU', '<meta name="keywords" content="'
.shCleanUpDesc($shCustomKeywordsTag).'" />', $buffer);
}
if (!is_null($shCustomRobotsTag)) {
if (strpos($buffer, '<meta name="robots" content="')!== false) {
$buffer = preg_replace( '/\<\s*meta\s+name\s*=\s*"robots.*\/\>/isU', '<meta name="robots" content="'
.$shCustomRobotsTag.'" />', $buffer);
}
else if (!empty($shCustomRobotsTag)) {
$buffer = shInsertCustomTagInBuffer( $buffer, '</head>', 'before', '<meta name="robots" content="'
.$shCustomRobotsTag.'" />', 'first');
}
}
if (!is_null($shCustomLangTag)) {
$shLang = $shCustomLangTag;
}
else {
$shLang = $shMosConfig_locale;
}
if (strpos($buffer, '<meta http-equiv="Content-Language"')!== false) {
$buffer = preg_replace( '/\<\s*meta\s+http-equiv\s*=\s*"Content-Language".*\/\>/isU', '<meta http-equiv="Content-Language" content="'.$shLang.'" />', $buffer);
}
else if (!empty($shCustomLangTag)) {
$buffer = shInsertCustomTagInBuffer( $buffer, '</head>', 'before', '<meta http-equiv="Content-Language" content="'.$shLang.'" />', 'first');
}

// remove Generator tag
if ($sefConfig->shRemoveGeneratorTag) {
$buffer = preg_replace( '/<meta\s*name="Generator"\s*content=".*\/>/isU','', $buffer);
}


// version x : add title to read on link
if ($sefConfig->shInsertReadMorePageTitle) {
if (strpos( $buffer, 'class="readon"')!== false) {
$buffer = preg_replace_callback( '/<td class="contentheading" width="100%">(.*) class="readon">(.*)<\/a>/isU',
'shDoLinkReadMoreCallback', $buffer);
}
}
// put <h1> tags around content elements titles
if ($sefConfig->shPutH1Tags) {
if (strpos($buffer, 'class="componentheading')!== false) {
$buffer = preg_replace( '/<div class="componentheading([^>]*)>\s*(.*)\s*<\/div>/isU',
                              '<div class="componentheading$1><h1>$2</h1></div>', $buffer);   
$buffer = preg_replace( '/<td class="contentheading([^>]*)>\s*(.*)\s*<\/td>/isU',
                              '<td class="contentheading$1><h2>$2</h2></td>', $buffer);
} else {  // replace contentheading by h1
$buffer = preg_replace( '/<td class="contentheading([^>]*)>\s*(.*)\s*<\/td>/isU',
                              '<td class="contentheading$1><h1>$2</h1></td>', $buffer);
}
}

// version x : if multiple h1 headings, replace them by h2
if ($sefConfig->shMultipleH1ToH2 && substr_count( JString::strtolower($buffer), '<h1>') > 1) {
$buffer = str_replace( '<h1>', '<h2>', $buffer);
$buffer = str_replace( '<H1>', '<h2>', $buffer);
$buffer = str_replace( '</h1>', '</h2>', $buffer);
$buffer = str_replace( '</H1>', '</h2>', $buffer);
}

// V 1.3.1 : replace outbounds links by internal redirects
if (sh404SEF_REDIRECT_OUTBOUND_LINKS) {
$buffer = preg_replace_callback( '/<\s*a\s*href\s*=\s*"(.*)"/isU',
'shDoRedirectOutboundLinksCallback', $buffer);
}

// V 1.3.1 : add symbol to outbounds links
if ($sefConfig->shInsertOutboundLinksImage) {
$buffer = preg_replace_callback( "/<\s*a\s*href\s*=\s*(\"|').*(\"|')\s*>.*<\/a>/isU",
'shDoInsertOutboundLinksImageCallback', $buffer);
}

// all done
return $buffer;
}
}

// begin main output --------------------------------------------------------

// check we are outputting document for real
$document = &JFactory::getDocument();
if ($document->getType() == 'html') {
$shPage = JResponse::getBody();

// do TITLE and DESCRIPTION and KEYWORDS and ROBOTS tags replacement
shDoTitleTags( $shPage);

if (SH_SHOW_CACHE_STATS)
$shPage .= shShowCacheStats();

JResponse::setBody($shPage);
}
// }
}

?>
><h1>php</h1></td>', $buffer);
}
}

// version x : if multiple h1 headings, replace them by h2
if ($sefConfig->shMultipleH1ToH2 && substr_count( JString::strtolower($buffer), '<h1>') > 1) {
$buffer = str_replace( '<h1>', '<h2>', $buffer);
$buffer = str_replace( '<H1>', '<h2>', $buffer);
$buffer = str_replace( '</h1>', '</h2>', $buffer);
$buffer = str_replace( '</H1>', '</h2>', $buffer);
}

// V 1.3.1 : replace outbounds links by internal redirects
if (sh404SEF_REDIRECT_OUTBOUND_LINKS) {
$buffer = preg_replace_callback( '/<\s*a\s*href\s*=\s*"(.*)"/isU',
'shDoRedirectOutboundLinksCallback', $buffer);
}

// V 1.3.1 : add symbol to outbounds links
if ($sefConfig->shInsertOutboundLinksImage) {
$buffer = preg_replace_callback( "/<\s*a\s*href\s*=\s*(\"|').*(\"|')\s*>.*<\/a>/isU",
'shDoInsertOutboundLinksImageCallback', $buffer);
}

// all done
return $buffer;
}
}

// begin main output --------------------------------------------------------

// check we are outputting document for real
$document = &JFactory::getDocument();
if ($document->getType() == 'html') {
$shPage = JResponse::getBody();

// do TITLE and DESCRIPTION and KEYWORDS and ROBOTS tags replacement
shDoTitleTags( $shPage);

if (SH_SHOW_CACHE_STATS)
$shPage .= shShowCacheStats();

JResponse::setBody($shPage);
}
// }
}

?>
*

Funkdoobiest

  • Захожу иногда
  • 244
  • 25 / 13
Re: Транслитерация title в sh404
« Ответ #16 : 15.12.2009, 16:33:26 »
Такая же петрушка на компоненте СОБИ2. Если комментирую кусок кода как пишет Палыч то появляется синтакс ошибка. Стоит 1.0.20_Beta - build_237
На сколько я понял, по рецепту Палыча получится так что все тайтлы что создает SEF (а именно цепочку статья \ категория \ секция \ название сайта) пропадет, и будут стандартные титлы от жумлы?
*

k_morgan

  • Захожу иногда
  • 59
  • 1 / 0
Re: Транслитерация title в sh404
« Ответ #17 : 27.03.2010, 17:57:27 »
Цитировать
и будут стандартные титлы от жумлы?

Ну, да. Так и будет.

Лучше, менять следующим путем.

Код
      if ( !empty($shCustomTags)) {
$shCustomTitleTag = !empty($shCustomTags->metatitle)? $shCustomTags->metatitle : NULL;
$shCustomDescriptionTag = !empty($shCustomTags->metadesc)? $shCustomTags->metadesc : $shCustomDescriptionTag;
$shCustomKeywordsTag = !empty($shCustomTags->metakey)? $shCustomTags->metakey : $shCustomKeywordsTag;
$shCustomRobotsTag = !empty($shCustomTags->metarobots)? $shCustomTags->metarobots : $shCustomRobotsTag;
$shCustomLangTag = !empty($shCustomTags->metalang)? $shCustomTags->metalang : $shCustomLangTag;
} else $shCustomTitleTag=NULL;

Хотя это тоже не выход. Так можно задавать свой Title для выбранной страницы, но нельзя воспользоваться опциями добавить строку до заголовка и после.

Обидно, что никто это не победил...
*

k_morgan

  • Захожу иногда
  • 59
  • 1 / 0
Re: Транслитерация title в sh404
« Ответ #18 : 31.03.2010, 01:58:33 »
Я правда у себя if после предыдущего куска переделал. Чтобы можно было добавлять ко всем тайтлам, либо в начало, либо в конец какую- нибудь запись. А если заменил тайтл в новом Мета, то там и делай эту добавку ручками.

         
Код
// then insert them in page
if (!is_null($shCustomTitleTag)) {
$buffer = preg_replace( '/\<\s*title\s*\>.*\<\s*\/title\s*\>/isU', '<title>'
.shCleanUpTitle($shCustomTitleTag).'</title>', $buffer);
$buffer = preg_replace( '/\<\s*meta\s+name\s*=\s*"title.*\/\>/isU', '', $buffer); // remove Joomla title meta
}
else
{
                                $shCustomTitleTag=html_entity_decode($document->getTitle());
$buffer = preg_replace( '/\<\s*title\s*\>.*\<\s*\/title\s*\>/isU', '<title>'
.shCleanUpTitle($sefConfig->prependToPageTitle.$shCustomTitleTag.$sefConfig->appendToPageTitle).'</title>', $buffer);
$buffer = preg_replace( '/\<\s*meta\s+name\s*=\s*"title.*\/\>/isU', '', $buffer); // remove Joomla title meta
}
         
*

k_morgan

  • Захожу иногда
  • 59
  • 1 / 0
Re: Транслитерация title в sh404
« Ответ #19 : 31.03.2010, 02:02:21 »
Hi!

А что стоит ли включать в Мета
1) Убрать тег Joomla Generator?
2) Use table-less output?
3) Вставлять теги h1?
4) Change multiple h1 in h2?
5) Insert title in Read more ... links?
6) Insert outbound links symbol?
Чтобы оставить сообщение,
Вам необходимо Войти или Зарегистрироваться
 

После обновления sh404 до версии 2.5 к страницам 404 добавился "?tmpl=index"

Автор Dim

Ответов: 0
Просмотров: 4205
Последний ответ 04.12.2018, 15:31:39
от Dim
JSitemap vs sh404

Автор dav1as

Ответов: 4
Просмотров: 4867
Последний ответ 12.12.2017, 13:58:40
от wishlight
Title динамических страниц

Автор foseg

Ответов: 0
Просмотров: 1966
Последний ответ 19.03.2015, 11:31:08
от foseg
Скачет title - то из sh404SEF берет, то из бызы данных

Автор artis72

Ответов: 3
Просмотров: 3121
Последний ответ 11.12.2014, 17:07:20
от artis72
Глуюк в Virtumart 2 + мультиязычность + sh404

Автор alexshab

Ответов: 0
Просмотров: 1997
Последний ответ 27.09.2014, 15:52:27
от alexshab