sh404SEF SEF/URL component (Weeblr), vetted clean from live; upstream gated and discontinued for Joomla 3 -> deployed files. Signed-off-by: LÁZÁR Imre <imre@illusion.hu> Assisted-by: claude-code@claude-opus-4-8
1211 lines
42 KiB
PHP
1211 lines
42 KiB
PHP
<?php
|
|
/**
|
|
* sh404SEF - SEO extension for Joomla!
|
|
*
|
|
* @author Yannick Gaultier
|
|
* @copyright (c) Yannick Gaultier 2014
|
|
* @package sh404SEF
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU/GPL
|
|
* @version 4.4.4.1791
|
|
* @date 2014-07-01
|
|
*/
|
|
|
|
defined('_JEXEC') or die('Restricted access');
|
|
|
|
// V 1.2.4.t check if sh404SEF is running
|
|
if (defined('SH404SEF_IS_RUNNING'))
|
|
{
|
|
|
|
// support for improved TITLE, DESCRIPTION, KEYWORDS and ROBOTS head tag
|
|
global $shCustomTitleTag, $shCustomDescriptionTag, $shCustomKeywordsTag, $shCustomRobotsTag, $shCustomLangTag, $shCanonicalTag;
|
|
// these variables can be set throughout your php code in components, bots or other modules
|
|
// the last one wins !
|
|
|
|
function shCleanUpTitle($title)
|
|
{
|
|
$title = JString::trim(JString::trim(stripslashes(html_entity_decode($title))), '"');
|
|
return $title;
|
|
}
|
|
|
|
function shProtectPageTitle($title)
|
|
{
|
|
// in case there are some $nn in the title
|
|
$title = ShlSystem_Strings::pr('#\$([0-9]*)#u', '\\\$${1}', $title);
|
|
return $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("'", '\'', $desc);
|
|
$desc = str_replace("'", '\'', $desc);
|
|
$desc = str_replace('"', '\'', $desc);
|
|
$desc = str_replace("\r\n", ' ', $desc);
|
|
$desc = str_replace("\n\r", ' ', $desc);
|
|
$desc = str_replace("\r", ' ', $desc);
|
|
$desc = str_replace("\n", ' ', $desc);
|
|
return JString::substr(JString::trim($desc), 0, 512);
|
|
}
|
|
|
|
function shIncludeMetaPlugin()
|
|
{
|
|
|
|
$option = JRequest::getCmd('option');
|
|
|
|
// get extension plugin
|
|
$extPlugin = &Sh404sefFactory::getExtensionPlugin($option);
|
|
|
|
// which plugin file are we supposed to use?
|
|
$extPluginPath = $extPlugin->getMetaPluginPath(Sh404sefFactory::getPageInfo()->currentNonSefUrl);
|
|
|
|
if (!empty($extPluginPath))
|
|
{
|
|
include $extPluginPath;
|
|
}
|
|
|
|
}
|
|
|
|
// 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 shPregInsertCustomTagInBuffer($buffer, $tag, $where, $value, $firstOnly, $rawPattern = false)
|
|
{
|
|
if (!$buffer || !$tag || !$value)
|
|
return $buffer;
|
|
$pattern = $rawPattern ? $tag : '#(' . $tag . ')#iUsu';
|
|
|
|
switch ($where)
|
|
{
|
|
case 'instead':
|
|
$replacement = $value;
|
|
break;
|
|
case 'after':
|
|
$replacement = '$1' . $value;
|
|
break;
|
|
default:
|
|
$replacement = $value . '$1';
|
|
break;
|
|
}
|
|
|
|
$result = preg_replace($pattern, $replacement, $buffer, $firstOnly ? 1 : 0);
|
|
if (empty($result))
|
|
{
|
|
$result = $buffer;
|
|
ShlSystem_Log::error('shlib', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__,
|
|
'RegExp failed: invalid character on page ' . Sh404sefFactory::getPageInfo()->currentSefUrl);
|
|
}
|
|
|
|
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%% [%%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>)/isuU', $bits[1], $titleBits); // extract title-may still have <h1> tags
|
|
$title = JString::trim(JString::trim(stripslashes(html_entity_decode(JString::trim($titleBits[1])))), '"');
|
|
}
|
|
else
|
|
{ // title is not linked
|
|
$titleBits = array();
|
|
preg_match('/(.*)(<script|<a\s*href=|<\/td>)/iusU', $matches[1], $titleBits); // extract title-may still have <h1> tags
|
|
$title = str_replace('<h1>', '', $titleBits[1]);
|
|
$title = str_replace('</h1>', '', $title);
|
|
$title = JString::trim(JString::trim(stripslashes(html_entity_decode(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], Sh404sefFactory::getPageInfo()->getDefaultFrontLiveSite()) === false)
|
|
{
|
|
$mask = '<a href="' . Sh404sefFactory::getPageInfo()->getDefaultFrontLiveSite()
|
|
. '/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 = &Sh404sefFactory::getPageInfo();
|
|
$sefConfig = &Sh404sefFactory::getConfig();
|
|
|
|
if (substr($link, 0, strlen($shPageInfo->getDefaultFrontLiveSite())) != $shPageInfo->getDefaultFrontLiveSite()
|
|
&& (substr($link, 0, 7) == 'http://' || substr($link, 0, 7) == 'https://')
|
|
&& (empty($shPageInfo->basePath) || substr($link, 0, strlen($shPageInfo->basePath)) != $shPageInfo->basePath)
|
|
&& strpos($link, 'pinterest.com') === false)
|
|
{
|
|
|
|
$mask = '%%shM1%%href="%%shM2%%" %%shM3%% >%%shM4%%<img border="0" alt="%%shM5%%" src="' . $shPageInfo->getDefaultFrontLiveSite()
|
|
. '/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 shGetCustomMetaData($nonSef)
|
|
{
|
|
|
|
static $_tags;
|
|
|
|
if (is_null($_tags))
|
|
{
|
|
$_tags = JTable::getInstance('metas', 'Sh404sefTable');
|
|
// now read manually setup tags
|
|
try
|
|
{
|
|
$data = ShlDbHelper::selectObject('#__sh404sef_metas', '*', array('newurl' => $nonSef));
|
|
}
|
|
catch (Exception $e)
|
|
{
|
|
ShlSystem_Log::error('sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage());
|
|
}
|
|
if (!empty($data))
|
|
{
|
|
$_tags->bind($data);
|
|
}
|
|
}
|
|
return $_tags;
|
|
}
|
|
|
|
function shGetCurrentNonSef()
|
|
{
|
|
// remove Google tracking vars, would prevent us to find the correct meta tags
|
|
$nonSef = Sh404sefHelperUrl::stripTrackingVarsFromNonSef(Sh404sefFactory::getPageInfo()->currentNonSefUrl);
|
|
|
|
// Virtuemart hack
|
|
// VM 2.x actually sets JRequest variables to communicate between view.html.php and layouts!
|
|
// so the current non-sef url is modified (showall=1 is added) which prevent
|
|
// all meta data associated with this non-sef to be properly retrieved
|
|
$isVm = Sh404sefHelperUrl::getUrlVar($nonSef, 'option', null) == 'com_virtuemart';
|
|
$isProductDetails = $isVm && Sh404sefHelperUrl::getUrlVar($nonSef, 'view', null) == 'productdetails';
|
|
if ($isProductDetails)
|
|
{
|
|
$nonSef = str_replace('&showall=1', '', $nonSef);
|
|
}
|
|
|
|
// normalize, set variables in alpha order
|
|
return Sh404sefHelperUrl::sortUrl($nonSef);
|
|
}
|
|
|
|
function shDoTitleTags(&$buffer)
|
|
{
|
|
// Replace TITLE and DESCRIPTION and KEYWORDS
|
|
if (empty($buffer))
|
|
return;
|
|
global $shCustomTitleTag, $shCustomDescriptionTag, $shCustomKeywordsTag, $shCustomRobotsTag, $shCustomLangTag, $shCanonicalTag;
|
|
|
|
$database = ShlDbHelper::getDb();
|
|
$shPageInfo = &Sh404sefFactory::getPageInfo();
|
|
$sefConfig = &Sh404sefFactory::getConfig();
|
|
$document = JFactory::getDocument();
|
|
$headData = $document->getHeadData();
|
|
|
|
// 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->currentNonSefUrl))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// check if there is a manually created set of tags from tags file
|
|
// need to get them from DB
|
|
if ($sefConfig->shMetaManagementActivated)
|
|
{
|
|
|
|
shIncludeMetaPlugin();
|
|
|
|
// is this homepage ? set flag for future use
|
|
// V 1.2.4.t make sure we have lang info and properly sorted params
|
|
if (!preg_match('/(&|\?)lang=[a-zA-Z]{2,3}/iuU', $shPageInfo->currentNonSefUrl))
|
|
{
|
|
// no lang string, let's add default
|
|
$shTemp = explode('-', $shPageInfo->currentLanguageTag);
|
|
$shLangTemp = $shTemp[0] ? $shTemp[0] : 'en';
|
|
$shPageInfo->currentNonSefUrl .= '&lang=' . $shLangTemp;
|
|
}
|
|
|
|
$nonSef = shGetCurrentNonSef();
|
|
$isHome = $nonSef == Sh404sefHelperUrl::sortUrl(shCleanUpAnchor(Sh404sefFactory::getPageInfo()->homeLink));
|
|
$shCustomTags = shGetCustomMetaData($isHome ? sh404SEF_HOMEPAGE_CODE : $nonSef);
|
|
|
|
// J! 2.5 finder canonical handling/hack
|
|
$highlight = Sh404sefHelperUrl::getUrlVar($nonSef, 'highlight', null);
|
|
if (!empty($highlight) && empty($shCanonicalTag))
|
|
{
|
|
$searchCanoNonSef = str_replace('?highlight=' . $highlight, '', $nonSef);
|
|
$searchCanoNonSef = str_replace('&highlight=' . $highlight, '', $searchCanoNonSef);
|
|
$shCanonicalTag = JRoute::_($searchCanoNonSef);
|
|
}
|
|
|
|
// splash page hack
|
|
$splash = Sh404sefHelperUrl::getUrlVar($nonSef, 'sh404sef_splash', null);
|
|
if (!empty($splash) && empty($shCanonicalTag))
|
|
{
|
|
$shCanonicalTag = $sefConfig->shForcedHomePage;
|
|
}
|
|
|
|
// group new tags insertion, better perf
|
|
$tagsToInsert = '';
|
|
|
|
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;
|
|
$shCanonicalTag = !empty($shCustomTags->canonical) ? $shCustomTags->canonical : $shCanonicalTag;
|
|
}
|
|
|
|
// then insert them in page
|
|
if (empty($shCustomTitleTag))
|
|
{
|
|
$shCustomTitleTag = $document->getTitle();
|
|
}
|
|
|
|
if (!empty($shCustomTitleTag))
|
|
{
|
|
$prepend = $isHome ? '' : $sefConfig->prependToPageTitle;
|
|
$append = $isHome ? '' : $sefConfig->appendToPageTitle;
|
|
$shPageInfo->pageTitle = htmlspecialchars(shCleanUpTitle($prepend . $shCustomTitleTag . $append), ENT_COMPAT, 'UTF-8');
|
|
$shPageInfo->pageTitlePr = shProtectPageTitle($shPageInfo->pageTitle);
|
|
|
|
$buffer = ShlSystem_Strings::pr('/\<\s*title\s*\>.*\<\s*\/title\s*\>/isuU', '<title>' . $shPageInfo->pageTitlePr . '</title>', $buffer);
|
|
$buffer = ShlSystem_Strings::pr('/\<\s*meta\s+name\s*=\s*"title.*\/\>/isuU', '', $buffer); // remove any title meta
|
|
|
|
}
|
|
|
|
if (!is_null($shCustomDescriptionTag))
|
|
{
|
|
$t = htmlspecialchars(shCleanUpDesc($shCustomDescriptionTag), ENT_COMPAT, 'UTF-8');
|
|
$shPageInfo->pageDescription = ShlSystem_Strings::pr('#\$([0-9]*)#u', '\\\$${1}', $t);
|
|
if (strpos($buffer, '<meta name="description" content=') !== false)
|
|
{
|
|
$buffer = ShlSystem_Strings::pr('/\<\s*meta\s+name\s*=\s*"description.*\/\>/isUu',
|
|
'<meta name="description" content="' . $shPageInfo->pageDescription . '" />', $buffer);
|
|
}
|
|
else
|
|
{
|
|
$tagsToInsert .= "\n" . '<meta name="description" content="' . $shPageInfo->pageDescription . '" />';
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// read Joomla! description if none set by us
|
|
if (empty($shPageInfo->pageDescription))
|
|
{
|
|
$shPageInfo->pageDescription = empty($headData['description']) ? ''
|
|
: htmlspecialchars(shCleanUpDesc($headData['description']), ENT_COMPAT, 'UTF-8');
|
|
}
|
|
}
|
|
|
|
if (!is_null($shCustomKeywordsTag))
|
|
{
|
|
$t = htmlspecialchars(shCleanUpDesc($shCustomKeywordsTag), ENT_COMPAT, 'UTF-8');
|
|
$shPageInfo->pageKeywords = ShlSystem_Strings::pr('#\$([0-9]*)#u', '\\\$${1}', $t);
|
|
if (strpos($buffer, '<meta name="keywords" content=') !== false)
|
|
{
|
|
$buffer = ShlSystem_Strings::pr('/\<\s*meta\s+name\s*=\s*"keywords.*\/\>/isUu',
|
|
'<meta name="keywords" content="' . $shPageInfo->pageKeywords . '" />', $buffer);
|
|
}
|
|
else
|
|
{
|
|
$tagsToInsert .= "\n" . '<meta name="keywords" content="' . $shPageInfo->pageKeywords . '" />';
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// read Joomla! description if none set by us
|
|
if (empty($shPageInfo->pageKeywords))
|
|
{
|
|
$shPageInfo->pageKeywords = empty($headData['metaTags']['standard']['keywords']) ? ''
|
|
: htmlspecialchars(shCleanUpDesc($headData['metaTags']['standard']['keywords']), ENT_COMPAT, 'UTF-8');
|
|
}
|
|
}
|
|
|
|
if (!is_null($shCustomRobotsTag))
|
|
{
|
|
$shPageInfo->pageRobotsTag = $shCustomRobotsTag;
|
|
if (strpos($buffer, '<meta name="robots" content="') !== false)
|
|
{
|
|
$buffer = ShlSystem_Strings::pr('/\<\s*meta\s+name\s*=\s*"robots.*\/\>/isUu',
|
|
'<meta name="robots" content="' . $shCustomRobotsTag . '" />', $buffer);
|
|
}
|
|
else if (!empty($shCustomRobotsTag))
|
|
{
|
|
$tagsToInsert .= "\n" . '<meta name="robots" content="' . $shCustomRobotsTag . '" />';
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// read Joomla! description if none set by us
|
|
if (empty($shPageInfo->pageRobotsTag))
|
|
{
|
|
$shPageInfo->pageRobotsTag = empty($headData['metaTags']['standard']['robots']) ? ''
|
|
: htmlspecialchars(shCleanUpDesc($headData['metaTags']['standard']['robots']), ENT_COMPAT, 'UTF-8');
|
|
}
|
|
}
|
|
|
|
if (!is_null($shCustomLangTag))
|
|
{
|
|
$shLang = $shCustomLangTag;
|
|
$shPageInfo->pageLangTag = $shCustomLangTag;
|
|
if (strpos($buffer, '<meta http-equiv="Content-Language"') !== false)
|
|
{
|
|
$buffer = ShlSystem_Strings::pr('/\<\s*meta\s+http-equiv\s*=\s*"Content-Language".*\/\>/isUu',
|
|
'<meta http-equiv="Content-Language" content="' . $shCustomLangTag . '" />', $buffer);
|
|
}
|
|
else
|
|
{
|
|
$tagsToInsert .= "\n" . '<meta http-equiv="Content-Language" content="' . $shCustomLangTag . '" />';
|
|
}
|
|
}
|
|
|
|
// custom handling of canonical
|
|
$canonicalPattern = '/\<\s*link[^>]+rel\s*=\s*"canonical[^>]+\/\>/isUu';
|
|
$matches = array();
|
|
$canonicalCount = preg_match_all($canonicalPattern, $buffer, $matches);
|
|
// more than one canonical already: kill them all
|
|
if ($canonicalCount > 1 && Sh404sefFactory::getConfig()->removeOtherCanonicals)
|
|
{
|
|
$buffer = ShlSystem_Strings::pr($canonicalPattern, '', $buffer);
|
|
$canonicalCount = 0;
|
|
|
|
}
|
|
// more than one and J3: must be the one inserted by J3 SEF plugin
|
|
if ($canonicalCount > 0 && Sh404sefFactory::getConfig()->removeOtherCanonicals && version_compare(JVERSION, '3.0', 'ge'))
|
|
{
|
|
// kill it, if asked to
|
|
$buffer = ShlSystem_Strings::pr($canonicalPattern, '', $buffer);
|
|
$canonicalCount = 0;
|
|
}
|
|
|
|
// make sure canonical is absolute, to avoid users complaining despite links being totally fine see #342
|
|
if(!empty($shCanonicalTag) && substr($shCanonicalTag, 0, 1) == '/')
|
|
{
|
|
$basePath = Juri::base(true);
|
|
$baseFull = JUri::base(false);
|
|
$shCanonicalTag = trim($baseFull, '/') . str_replace($basePath, '', $shCanonicalTag);
|
|
}
|
|
|
|
// if there' a custom canonical for that page, insert it, or replace any existing ones
|
|
if (!empty($shCanonicalTag) && $canonicalCount == 0)
|
|
{
|
|
// insert a new canonical
|
|
$tagsToInsert .= "\n" . '<link href="' . htmlspecialchars($shCanonicalTag, ENT_COMPAT, 'UTF-8') . '" rel="canonical" />' . "\n";
|
|
}
|
|
else if (!empty($shCanonicalTag))
|
|
{
|
|
// replace existing canonical
|
|
$buffer = ShlSystem_Strings::pr($canonicalPattern,
|
|
'<link href="' . htmlspecialchars($shCanonicalTag, ENT_COMPAT, 'UTF-8') . '" rel="canonical" />', $buffer);
|
|
}
|
|
|
|
// insert all tags in one go
|
|
if (!empty($tagsToInsert))
|
|
{
|
|
$buffer = shInsertCustomTagInBuffer($buffer, '<head>', 'after', $tagsToInsert, 'first');
|
|
}
|
|
|
|
// remove Generator tag
|
|
if ($sefConfig->shRemoveGeneratorTag)
|
|
{
|
|
$buffer = ShlSystem_Strings::pr('/<meta\s*name="generator"\s*content=".*\/>/isUu', '', $buffer);
|
|
}
|
|
|
|
// put <h1> tags around content elements titles
|
|
if ($sefConfig->shPutH1Tags)
|
|
{
|
|
if (strpos($buffer, 'class="componentheading') !== false)
|
|
{
|
|
$buffer = ShlSystem_Strings::pr('/<div class="componentheading([^>]*)>\s*(.*)\s*<\/div>/isUu',
|
|
'<div class="componentheading$1><h1>$2</h1></div>', $buffer);
|
|
$buffer = ShlSystem_Strings::pr('/<td class="contentheading([^>]*)>\s*(.*)\s*<\/td>/isUu',
|
|
'<td class="contentheading$1><h2>$2</h2></td>', $buffer);
|
|
}
|
|
else
|
|
{ // replace contentheading by h1
|
|
$buffer = ShlSystem_Strings::pr('/<td class="contentheading([^>]*)>\s*(.*)\s*<\/td>/isUu',
|
|
'<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)
|
|
{
|
|
$tmp = preg_replace_callback('/<\s*a\s*href\s*=\s*"(.*)"/isUu', 'shDoRedirectOutboundLinksCallback', $buffer);
|
|
if (empty($tmp))
|
|
{
|
|
ShlSystem_Log::error('shlib', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__,
|
|
'RegExp failed: invalid character on page ' . Sh404sefFactory::getPageInfo()->currentSefUrl);
|
|
}
|
|
else
|
|
{
|
|
$buffer = $tmp;
|
|
}
|
|
}
|
|
|
|
// V 1.3.1 : add symbol to outbounds links
|
|
if ($sefConfig->shInsertOutboundLinksImage)
|
|
{
|
|
$tmp = preg_replace_callback("/<\s*a\s*href\s*=\s*(\"|').*(\"|')\s*>.*<\/a>/isUu", 'shDoInsertOutboundLinksImageCallback', $buffer);
|
|
if (empty($tmp))
|
|
{
|
|
ShlSystem_Log::error('shlib', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__,
|
|
'RegExp failed: invalid character on page ' . Sh404sefFactory::getPageInfo()->currentSefUrl);
|
|
}
|
|
else
|
|
{
|
|
$buffer = $tmp;
|
|
}
|
|
}
|
|
|
|
// all done
|
|
return $buffer;
|
|
}
|
|
}
|
|
|
|
function shDoAnalytics(&$buffer)
|
|
{
|
|
// get sh404sef config
|
|
$config = &Sh404sefFactory::getConfig();
|
|
|
|
// check if set to insert snippet
|
|
if (!Sh404sefHelperAnalytics::isEnabled())
|
|
{
|
|
return;
|
|
}
|
|
|
|
// calculate params
|
|
$className = 'Sh404sefAdapterAnalytics' . strtolower($config->analyticsType);
|
|
$handler = new $className();
|
|
|
|
// do insert
|
|
$snippet = $handler->getSnippet();
|
|
if (empty($snippet))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// use page rewrite utility function to insert as needed
|
|
if ($config->analyticsEdition != 'gtm')
|
|
{
|
|
$buffer = shInsertCustomTagInBuffer($buffer, '</head>', 'before', $snippet, $firstOnly = 'first');
|
|
}
|
|
else
|
|
{
|
|
$buffer = shPregInsertCustomTagInBuffer($buffer, '<\s*body[^>]*>', 'after', $snippet, $firstOnly = 'first');
|
|
}
|
|
}
|
|
|
|
function shDoSocialButtons(&$buffer)
|
|
{
|
|
// get sh404sef config
|
|
$sefConfig = &Sh404sefFactory::getConfig();
|
|
|
|
// fire event so that social plugin can attach required external js
|
|
$dispatcher = ShlSystem_factory::dispatcher();
|
|
$dispatcher->trigger('onSh404sefInsertFBJavascriptSDK', array(&$buffer, $sefConfig));
|
|
|
|
// fire event so that social plugin can attach required external js and css
|
|
$dispatcher->trigger('onSh404sefInsertSocialButtons', array(&$buffer, $sefConfig));
|
|
}
|
|
|
|
function shDoSocialAnalytics(&$buffer)
|
|
{
|
|
// get sh404sef config
|
|
$sefConfig = &Sh404sefFactory::getConfig();
|
|
|
|
// check if set to insert snippet
|
|
if (!Sh404sefHelperAnalytics::isEnabled())
|
|
{
|
|
return;
|
|
}
|
|
|
|
// fire event so that social plugin can attach required external js
|
|
$dispatcher = ShlSystem_factory::dispatcher();
|
|
$dispatcher->trigger('onSh404sefInsertFBJavascriptSDK', array(&$buffer, $sefConfig));
|
|
}
|
|
|
|
function shDoShURL(&$buffer)
|
|
{
|
|
|
|
// get sh404sef config
|
|
$sefConfig = &Sh404sefFactory::getConfig();
|
|
|
|
// check if shURLs are enabled
|
|
if (!$sefConfig->Enabled || !$sefConfig->enablePageId)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// get current page information
|
|
$shPageInfo = &Sh404sefFactory::getPageInfo();
|
|
|
|
// insert shURL if tag found, except if editing item on frontend
|
|
if (strpos($buffer, '{sh404sef_pageid}') !== false || strpos($buffer, '{sh404sef_shurl}') !== false)
|
|
{
|
|
// pull out contents of editor to prevent URL changes inside edit area
|
|
//$editor =JFactory::getEditor();
|
|
//$regex = '#'.$editor->_tagForSEF['start'].'(.*)'.$editor->_tagForSEF['end'].'#Us';
|
|
//preg_match_all($regex, $buffer, $editContents, PREG_PATTERN_ORDER);
|
|
|
|
// create an array to hold the placeholder text (in case there are more than one editor areas)
|
|
//$placeholders = array();
|
|
//for ($i = 0; $i < count($editContents[0]); $i++) {
|
|
// $placeholders[] = $editor->_tagForSEF['start'].$i.$editor->_tagForSEF['end'];
|
|
//}
|
|
|
|
// replace editor contents with placeholder text
|
|
//$buffer = str_replace($editContents[0], $placeholders, $buffer);
|
|
$buffer = str_replace(array('{sh404sef_pageid}', '{sh404sef_shurl}'), $shPageInfo->shURL, $buffer);
|
|
// restore the editor contents
|
|
//$buffer = str_replace($placeholders, $editContents[0], $buffer);
|
|
|
|
}
|
|
}
|
|
|
|
function shInsertOpenGraphData(&$buffer)
|
|
{
|
|
|
|
// get sh404sef config
|
|
$sefConfig = &Sh404sefFactory::getConfig();
|
|
$pageInfo = &Sh404sefFactory::getPageInfo();
|
|
|
|
if (empty($sefConfig->shMetaManagementActivated) || !isset($sefConfig) || empty($pageInfo->currentNonSefUrl)
|
|
|| (!empty($pageInfo->httpStatus) && $pageInfo->httpStatus == 404))
|
|
{
|
|
return;
|
|
}
|
|
|
|
$nonSef = shGetCurrentNonSef();
|
|
$customData = shGetCustomMetaData($nonSef);
|
|
|
|
// user can disable per url
|
|
if ($customData->og_enable == SH404SEF_OPTION_VALUE_NO
|
|
|| (empty($sefConfig->enableOpenGraphData) && $customData->og_enable == SH404SEF_OPTION_VALUE_USE_DEFAULT))
|
|
{
|
|
return;
|
|
}
|
|
|
|
$openGraphData = '';
|
|
$ogNameSpace = '';
|
|
$fbNameSpace = '';
|
|
|
|
// add locale - FB use underscore in language tags
|
|
$locale = str_replace('-', '_', JFactory::getLanguage()->getTag());
|
|
$openGraphData .= "\n" . ' <meta property="og:locale" content="' . $locale . '" />';
|
|
|
|
// insert title
|
|
if (!empty($pageInfo->pageTitle))
|
|
{
|
|
$openGraphData .= "\n" . ' <meta property="og:title" content="' . $pageInfo->pageTitle . '" />';
|
|
}
|
|
|
|
// insert description
|
|
if ((($sefConfig->ogEnableDescription && $customData->og_enable_description == SH404SEF_OPTION_VALUE_USE_DEFAULT)
|
|
|| $customData->og_enable_description == SH404SEF_OPTION_VALUE_YES) && !empty($pageInfo->pageDescription))
|
|
{
|
|
$openGraphData .= "\n" . ' <meta property="og:description" content="' . $pageInfo->pageDescription . '" />';
|
|
}
|
|
|
|
// insert type
|
|
$content = $customData->og_type == SH404SEF_OPTION_VALUE_USE_DEFAULT ? $sefConfig->ogType : $customData->og_type;
|
|
if (!empty($content))
|
|
{
|
|
$openGraphData .= "\n" . ' <meta property="og:type" content="' . $content . '" />';
|
|
}
|
|
|
|
// insert url. If any, we insert the canonical url rather than current, to consolidate
|
|
$content = empty($pageInfo->pageCanonicalUrl) ? $pageInfo->currentSefUrl : $pageInfo->pageCanonicalUrl;
|
|
$content = Sh404sefHelperUrl::stripTrackingVarsFromSef($content);
|
|
$openGraphData .= "\n" . ' <meta property="og:url" content="' . htmlspecialchars($content, ENT_COMPAT, 'UTF-8') . '" />';
|
|
|
|
// insert image
|
|
$content = empty($customData->og_image) ? $sefConfig->ogImage : $customData->og_image;
|
|
if (!empty($content))
|
|
{
|
|
$content = JURI::root(false, '') . JString::ltrim($content, '/');
|
|
$openGraphData .= "\n" . ' <meta property="og:image" content="' . $content . '" />';
|
|
}
|
|
|
|
// insert site name
|
|
if (($sefConfig->ogEnableSiteName && $customData->og_enable_site_name == SH404SEF_OPTION_VALUE_USE_DEFAULT)
|
|
|| $customData->og_enable_site_name == SH404SEF_OPTION_VALUE_YES)
|
|
{
|
|
$content = empty($customData->og_site_name) ? $sefConfig->ogSiteName : $customData->og_site_name;
|
|
$content = empty($content) ? JFactory::getApplication()->getCfg('sitename') : $content;
|
|
if (!empty($content))
|
|
{
|
|
$content = htmlspecialchars(shCleanUpDesc($content), ENT_COMPAT, 'UTF-8');
|
|
$openGraphData .= "\n" . ' <meta property="og:site_name" content="' . $content . '" />';
|
|
}
|
|
}
|
|
|
|
// insert location
|
|
// disabled: Facebook removed all of that after reducing number of object types to bare minimum
|
|
if (false
|
|
&& (($sefConfig->ogEnableLocation && $customData->og_enable_location == SH404SEF_OPTION_VALUE_USE_DEFAULT)
|
|
|| $customData->og_enable_location == SH404SEF_OPTION_VALUE_YES))
|
|
{
|
|
$content = empty($customData->og_latitude) ? $sefConfig->ogLatitude : $customData->og_latitude;
|
|
if (!empty($content))
|
|
{
|
|
$content = htmlspecialchars(shCleanUpDesc($content), ENT_COMPAT, 'UTF-8');
|
|
$openGraphData .= "\n" . ' <meta property="og:latitude" content="' . $content . '" />';
|
|
}
|
|
$content = empty($customData->og_longitude) ? $sefConfig->ogLongitude : $customData->og_longitude;
|
|
if (!empty($content))
|
|
{
|
|
$content = htmlspecialchars(shCleanUpDesc($content), ENT_COMPAT, 'UTF-8');
|
|
$openGraphData .= "\n" . ' <meta property="og:longitude" content="' . $content . '" />';
|
|
}
|
|
$content = empty($customData->og_street_address) ? $sefConfig->ogStreetAddress : $customData->og_street_address;
|
|
if (!empty($content))
|
|
{
|
|
$content = htmlspecialchars(shCleanUpDesc($content), ENT_COMPAT, 'UTF-8');
|
|
$openGraphData .= "\n" . ' <meta property="og:street-address" content="' . $content . '" />';
|
|
}
|
|
$content = empty($customData->og_locality) ? $sefConfig->ogLocality : $customData->og_locality;
|
|
if (!empty($content))
|
|
{
|
|
$content = htmlspecialchars(shCleanUpDesc($content), ENT_COMPAT, 'UTF-8');
|
|
$openGraphData .= "\n" . ' <meta property="og:locality" content="' . $content . '" />';
|
|
}
|
|
$content = empty($customData->og_postal_code) ? $sefConfig->ogPostalCode : $customData->og_postal_code;
|
|
if (!empty($content))
|
|
{
|
|
$content = htmlspecialchars(shCleanUpDesc($content), ENT_COMPAT, 'UTF-8');
|
|
$openGraphData .= "\n" . ' <meta property="og:postal-code" content="' . $content . '" />';
|
|
}
|
|
$content = empty($customData->og_region) ? $sefConfig->ogRegion : $customData->og_region;
|
|
if (!empty($content))
|
|
{
|
|
$content = htmlspecialchars(shCleanUpDesc($content), ENT_COMPAT, 'UTF-8');
|
|
$openGraphData .= "\n" . ' <meta property="og:region" content="' . $content . '" />';
|
|
}
|
|
$content = empty($customData->og_country_name) ? $sefConfig->ogCountryName : $customData->og_country_name;
|
|
if (!empty($content))
|
|
{
|
|
$content = htmlspecialchars(shCleanUpDesc($content), ENT_COMPAT, 'UTF-8');
|
|
$openGraphData .= "\n" . ' <meta property="og:country-name" content="' . $content . '" />';
|
|
}
|
|
|
|
}
|
|
|
|
// insert contact
|
|
// disabled: Facebook removed all of that after reducing number of object types to bare minimum
|
|
if (false
|
|
&& (($sefConfig->ogEnableContact && $customData->og_enable_contact == SH404SEF_OPTION_VALUE_USE_DEFAULT)
|
|
|| $customData->og_enable_contact == SH404SEF_OPTION_VALUE_YES))
|
|
{
|
|
$content = empty($customData->og_email) ? $sefConfig->ogEmail : $customData->og_email;
|
|
if (!empty($content))
|
|
{
|
|
$content = htmlspecialchars(shCleanUpDesc($content), ENT_COMPAT, 'UTF-8');
|
|
$openGraphData .= "\n" . ' <meta property="og:email" content="' . $content . '" />';
|
|
}
|
|
$content = empty($customData->og_phone_number) ? $sefConfig->ogPhoneNumber : $customData->og_phone_number;
|
|
if (!empty($content))
|
|
{
|
|
$content = htmlspecialchars(shCleanUpDesc($content), ENT_COMPAT, 'UTF-8');
|
|
$openGraphData .= "\n" . ' <meta property="og:phone_number" content="' . $content . '" />';
|
|
}
|
|
$content = empty($customData->og_fax_number) ? $sefConfig->ogFaxNumber : $customData->og_fax_number;
|
|
if (!empty($content))
|
|
{
|
|
$content = htmlspecialchars(shCleanUpDesc($content), ENT_COMPAT, 'UTF-8');
|
|
$openGraphData .= "\n" . ' <meta property="og:fax_number" content="' . $content . '" />';
|
|
}
|
|
}
|
|
|
|
if (!empty($openGraphData))
|
|
{
|
|
$ogNameSpace = 'xmlns:og="http://ogp.me/ns#"';
|
|
}
|
|
|
|
// insert fb admin id
|
|
if ((!empty($sefConfig->fbAdminIds) && $customData->og_enable_fb_admin_ids == SH404SEF_OPTION_VALUE_USE_DEFAULT)
|
|
|| $customData->og_enable_fb_admin_ids == SH404SEF_OPTION_VALUE_YES)
|
|
{
|
|
$content = empty($customData->fb_admin_ids) ? $sefConfig->fbAdminIds : $customData->fb_admin_ids;
|
|
if ($customData->og_enable_fb_admin_ids != SH404SEF_OPTION_VALUE_NO && !empty($content))
|
|
{
|
|
$openGraphData .= "\n" . ' <meta property="fb:admins" content="' . $content . '" />';
|
|
$fbNameSpace = 'xmlns:fb="https://www.facebook.com/2008/fbml"';
|
|
}
|
|
}
|
|
// actually insert the tags
|
|
if (!empty($openGraphData))
|
|
{
|
|
$buffer = shInsertCustomTagInBuffer($buffer, '<head>', 'after', $openGraphData, 'first');
|
|
}
|
|
|
|
if (!empty($fbNameSpace) || !empty($ogNameSpace))
|
|
{
|
|
// insert as well namespaces
|
|
$buffer = str_replace('<html ', '<html ' . $ogNameSpace . ' ' . $fbNameSpace . ' ', $buffer);
|
|
}
|
|
|
|
}
|
|
|
|
function shInsertGoogleAuthorshipData(&$buffer)
|
|
{
|
|
// quick check, do we have a createdBy field on the page?
|
|
if (strpos($buffer, '<dd class="createdby">') === false)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// get sh404sef config
|
|
$sefConfig = Sh404sefFactory::getConfig();
|
|
$pageInfo = Sh404sefFactory::getPageInfo();
|
|
|
|
if (empty($sefConfig->shMetaManagementActivated) || !isset($sefConfig) || empty($pageInfo->currentNonSefUrl)
|
|
|| (!empty($pageInfo->httpStatus) && $pageInfo->httpStatus == 404))
|
|
{
|
|
return;
|
|
}
|
|
|
|
$nonSef = shGetCurrentNonSef();
|
|
$customData = shGetCustomMetaData($nonSef);
|
|
|
|
// user can disable per url
|
|
if (isset($customData->google_authorship_enable) && $customData->google_authorship_enable == SH404SEF_OPTION_VALUE_NO
|
|
|| (empty($sefConfig->enableGoogleAuthorship)
|
|
&& (!isset($customData->google_authorship_enable) || $customData->google_authorship_enable == SH404SEF_OPTION_VALUE_USE_DEFAULT)))
|
|
{
|
|
return;
|
|
}
|
|
// figure out if we should insert authorship info: only on article page
|
|
if (!shShouldInsertMeta($input = null, $sefConfig->googleAuthorshipCategories))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// site
|
|
$authorUrl = empty($customData->google_authorship_author_profile) ? $sefConfig->googleAuthorshipAuthorProfile
|
|
: $customData->google_authorship_author_profile;
|
|
$authorUrl = JString::trim($authorUrl, '/');
|
|
$authorName = empty($customData->google_authorship_author_name) ? $sefConfig->googleAuthorshipAuthorName
|
|
: $customData->google_authorship_author_name;
|
|
|
|
if (empty($authorUrl) || empty($authorName))
|
|
{
|
|
return;
|
|
}
|
|
$authorUrl = 'https://plus.google.com/' . htmlspecialchars($authorUrl, ENT_COMPAT, 'UTF-8') . '?rel=author';
|
|
$authorName = htmlspecialchars($authorName, ENT_COMPAT, 'UTF-8');
|
|
|
|
$googleAuthorshipData = JText::sprintf('COM_CONTENT_WRITTEN_BY', JHtml::_('link', $authorUrl, $authorName));
|
|
|
|
// actually insert the tags
|
|
if (!empty($googleAuthorshipData))
|
|
{
|
|
$buffer = ShlSystem_Strings::pr('#\<dd\s*class="createdby"\s*\>.*\<\/dd\>#iUsu',
|
|
'<dd class="createdby">' . $googleAuthorshipData . '</dd>', $buffer);
|
|
}
|
|
}
|
|
|
|
function shInsertGooglePublisherData(&$buffer)
|
|
{
|
|
// don't insert head link to publisher page if there's
|
|
// already a visible badge (see sh404sef core social plugin
|
|
if(strpos( $buffer, 'rel=\'publisher\'') !== false)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// get sh404sef config
|
|
$sefConfig = Sh404sefFactory::getConfig();
|
|
$pageInfo = Sh404sefFactory::getPageInfo();
|
|
|
|
if (empty($sefConfig->shMetaManagementActivated) || !isset($sefConfig) || empty($pageInfo->currentNonSefUrl)
|
|
|| (!empty($pageInfo->httpStatus) && $pageInfo->httpStatus == 404))
|
|
{
|
|
return;
|
|
}
|
|
|
|
$nonSef = shGetCurrentNonSef();
|
|
$customData = shGetCustomMetaData($nonSef);
|
|
|
|
// user can disable per url
|
|
if (isset($customData->google_publisher_enable) && $customData->google_publisher_enable == SH404SEF_OPTION_VALUE_NO
|
|
|| (empty($sefConfig->enableGooglePublisher)
|
|
&& (!isset($customData->google_publisher_enable) || $customData->google_publisher_enable == SH404SEF_OPTION_VALUE_USE_DEFAULT)))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// site
|
|
$publisherUrl = empty($customData->google_publisher_url) ? $sefConfig->googlePublisherUrl
|
|
: $customData->google_publisher_url;
|
|
$publisherUrl = JString::trim($publisherUrl, '/');
|
|
|
|
if (empty($publisherUrl))
|
|
{
|
|
return;
|
|
}
|
|
$publisherUrl = 'https://plus.google.com/' . htmlspecialchars($publisherUrl, ENT_COMPAT, 'UTF-8');
|
|
$publisherTag = sprintf( ' <link href="%s" rel="publisher" />' , $publisherUrl);
|
|
|
|
// actually insert the tags
|
|
if (!empty($publisherTag))
|
|
{
|
|
$buffer = shInsertCustomTagInBuffer($buffer, '<head>', 'after', "\n" . $publisherTag . "\n", 'first');
|
|
}
|
|
}
|
|
|
|
function shShouldInsertMeta($input = null, $categories = array())
|
|
{
|
|
$input = empty($input) ? JFactory::getApplication()->input : $input;
|
|
$shouldInsertMeta = false;
|
|
|
|
// get request details
|
|
$component = $input->getCmd('option');
|
|
$view = $input->getCmd('view');
|
|
$printing = $input->getInt('print');
|
|
|
|
// we are set to only display on canonical page for an item
|
|
// this can only be true if context and current request matches
|
|
if (empty($component) && empty($view))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
switch ($component)
|
|
{
|
|
case 'com_content':
|
|
// only display if on an article page
|
|
$shouldInsertMeta = ($view == 'article' || $view == 'featured') && empty($printing);
|
|
// check category
|
|
if ($shouldInsertMeta)
|
|
{
|
|
if (!empty($categories) && ($categories[0] != 'show_on_all'))
|
|
{
|
|
// find about article category
|
|
$catid = $input->getInt('catid', 0);
|
|
if (empty($catid))
|
|
{
|
|
$id = $input->getInt('id', 0);
|
|
if ($id)
|
|
{
|
|
$article = JTable::getInstance('content');
|
|
$article->load($id);
|
|
$catid = $article->catid;
|
|
}
|
|
}
|
|
if (!empty($catid))
|
|
{
|
|
$shouldInsertMeta = in_array($catid, $categories);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$shouldInsertMeta = true;
|
|
}
|
|
}
|
|
break;
|
|
case 'com_k2':
|
|
$shouldInsertMeta = $view == 'item';
|
|
break;
|
|
default:
|
|
$shouldInsertMeta = true;
|
|
break;
|
|
}
|
|
|
|
return $shouldInsertMeta;
|
|
}
|
|
|
|
function shInsertTwitterCardsData(&$buffer)
|
|
{
|
|
|
|
// get sh404sef config
|
|
$sefConfig = Sh404sefFactory::getConfig();
|
|
$pageInfo = Sh404sefFactory::getPageInfo();
|
|
|
|
if (empty($sefConfig->shMetaManagementActivated) || !isset($sefConfig) || empty($pageInfo->currentNonSefUrl)
|
|
|| (!empty($pageInfo->httpStatus) && $pageInfo->httpStatus == 404))
|
|
{
|
|
return;
|
|
}
|
|
|
|
$nonSef = shGetCurrentNonSef();
|
|
$customData = shGetCustomMetaData($nonSef);
|
|
|
|
// user can disable per url
|
|
if (isset($customData->twittercards_enable) && $customData->twittercards_enable == SH404SEF_OPTION_VALUE_NO
|
|
|| (empty($sefConfig->enableTwitterCards)
|
|
&& (!isset($customData->twittercards_enable) || $customData->twittercards_enable == SH404SEF_OPTION_VALUE_USE_DEFAULT)))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// check categories
|
|
if (!shShouldInsertMeta($input = null, $sefConfig->twitterCardsCategories))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// prepare data
|
|
$twitterCardsData = '';
|
|
|
|
// card type
|
|
$twitterCardsData .= "\n" . ' <meta name="twitter:card" content="summary" />';
|
|
|
|
// site
|
|
$siteAccount = !isset($customData->twittercards_site_account) || empty($customData->twittercards_site_account)
|
|
? $sefConfig->twitterCardsSiteAccount : $customData->twittercards_site_account;
|
|
if (!empty($siteAccount))
|
|
{
|
|
$twitterCardsData .= "\n" . ' <meta name="twitter:site" content="' . $siteAccount . '" />';
|
|
}
|
|
|
|
// creator
|
|
$creatorAccount = empty($customData->twittercards_creator_account) ? $sefConfig->twitterCardsCreatorAccount
|
|
: $customData->twittercards_creator_account;
|
|
if (!empty($creatorAccount))
|
|
{
|
|
$twitterCardsData .= "\n" . ' <meta name="twitter:creator" content="' . $creatorAccount . '" />';
|
|
}
|
|
|
|
// title
|
|
if (!empty($pageInfo->pageTitle))
|
|
{
|
|
$twitterCardsData .= "\n" . ' <meta name="twitter:title" content="' . $pageInfo->pageTitle . '" />';
|
|
}
|
|
|
|
// description
|
|
if (!empty($pageInfo->pageDescription))
|
|
{
|
|
$twitterCardsData .= "\n" . ' <meta name="twitter:description" content="' . $pageInfo->pageDescription . '" />';
|
|
}
|
|
|
|
// image : we share with OpenGraph image
|
|
$image = empty($customData->og_image) ? $sefConfig->ogImage : $customData->og_image;
|
|
if (!empty($image))
|
|
{
|
|
$image = JURI::root(false, '') . JString::ltrim($image, '/');
|
|
$twitterCardsData .= "\n" . ' <meta name="twitter:image" content="' . $image . '" />';
|
|
}
|
|
|
|
// actually insert the tags
|
|
if (!empty($twitterCardsData))
|
|
{
|
|
$buffer = shInsertCustomTagInBuffer($buffer, '<head>', 'after', $twitterCardsData, 'first');
|
|
}
|
|
}
|
|
|
|
function shDoHeadersChanges()
|
|
{
|
|
|
|
global $shCanonicalTag;
|
|
|
|
$sefConfig = &Sh404sefFactory::getConfig();
|
|
|
|
if (!isset($sefConfig) || empty($sefConfig->shMetaManagementActivated) || empty($pageInfo->currentNonSefUrl))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// include plugin to build canonical if needed
|
|
shIncludeMetaPlugin();
|
|
|
|
// issue headers for canonical
|
|
if (!empty($shCanonicalTag))
|
|
{
|
|
jimport('joomla.utilities.string');
|
|
$link = JURI::root(false, '') . ltrim($sefConfig->shRewriteStrings[$sefConfig->shRewriteMode], '/')
|
|
. JString::ltrim($shCanonicalTag, '/');
|
|
JResponse::setHeader('Link', '<' . htmlspecialchars($link, ENT_COMPAT, 'UTF-8') . '>; rel="canonical"');
|
|
}
|
|
|
|
}
|
|
|
|
function shAddPaginationHeaderLinks(&$buffer)
|
|
{
|
|
|
|
$sefConfig = &Sh404sefFactory::getConfig();
|
|
|
|
if (!isset($sefConfig) || empty($sefConfig->shMetaManagementActivated) || empty($sefConfig->insertPaginationTags))
|
|
{
|
|
return;
|
|
}
|
|
|
|
$pageInfo = &Sh404sefFactory::getPageInfo();
|
|
|
|
// handle pagination
|
|
if (!empty($pageInfo->paginationNextLink))
|
|
{
|
|
$link = "\n " . '<link rel="next" href="' . $pageInfo->paginationNextLink . '" />';
|
|
$buffer = shInsertCustomTagInBuffer($buffer, '<head>', 'after', $link, 'first');
|
|
}
|
|
|
|
if (!empty($pageInfo->paginationPrevLink))
|
|
{
|
|
$link = "\n " . '<link rel="prev" href="' . $pageInfo->paginationPrevLink . '" />';
|
|
$buffer = shInsertCustomTagInBuffer($buffer, '<head>', 'after', $link, 'first');
|
|
}
|
|
|
|
}
|
|
|
|
// 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);
|
|
|
|
// insert analytics snippet
|
|
shDoAnalytics($shPage);
|
|
shDoSocialAnalytics($shPage);
|
|
shDoSocialButtons($shPage);
|
|
|
|
// insert short urls stuff
|
|
shDoShURL($shPage);
|
|
|
|
// Google autoriship
|
|
shInsertGoogleAuthorshipData($shPage);
|
|
shInsertGooglePublisherData($shPage);
|
|
|
|
// Twitter cards data
|
|
shInsertTwitterCardsData($shPage);
|
|
|
|
// Open Graph data
|
|
shInsertOpenGraphData($shPage);
|
|
|
|
// pagination links for lists
|
|
shAddPaginationHeaderLinks($shPage);
|
|
|
|
if (Sh404sefFactory::getConfig()->displayUrlCacheStats)
|
|
{
|
|
$shPage .= Sh404sefHelperCache::getCacheStats();
|
|
}
|
|
|
|
JResponse::setBody($shPage);
|
|
}
|
|
else
|
|
{
|
|
shDoHeadersChanges();
|
|
}
|
|
|
|
}
|