Initial commit
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright notice
|
||||
*
|
||||
* (c) 2015 Markus Blaschke <typo3@markus-blaschke.de> (metaseo)
|
||||
* (c) 2013 Markus Blaschke (TEQneers GmbH & Co. KG) <blaschke@teqneers.de> (tq_seo)
|
||||
* All rights reserved
|
||||
*
|
||||
* This script is part of the TYPO3 project. The TYPO3 project is
|
||||
* free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* The GNU General Public License can be found at
|
||||
* http://www.gnu.org/copyleft/gpl.html.
|
||||
*
|
||||
* This script is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* This copyright notice MUST APPEAR in all copies of the script!
|
||||
*/
|
||||
|
||||
namespace Metaseo\Metaseo\Hook\Extension;
|
||||
|
||||
/**
|
||||
* EXT:news hook for metatags
|
||||
*/
|
||||
class NewsExtension
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright notice
|
||||
*
|
||||
* (c) 2015 Markus Blaschke <typo3@markus-blaschke.de> (metaseo)
|
||||
* (c) 2013 Markus Blaschke (TEQneers GmbH & Co. KG) <blaschke@teqneers.de> (tq_seo)
|
||||
* All rights reserved
|
||||
*
|
||||
* This script is part of the TYPO3 project. The TYPO3 project is
|
||||
* free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* The GNU General Public License can be found at
|
||||
* http://www.gnu.org/copyleft/gpl.html.
|
||||
*
|
||||
* This script is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* This copyright notice MUST APPEAR in all copies of the script!
|
||||
*/
|
||||
|
||||
namespace Metaseo\Metaseo\Hook\Extension;
|
||||
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Frontend\Plugin\AbstractPlugin;
|
||||
|
||||
/**
|
||||
* EXT:tt_news hook for metatags
|
||||
*/
|
||||
class TtnewsExtension
|
||||
{
|
||||
|
||||
/**
|
||||
* Extra item marker hook for metatag fetching
|
||||
*
|
||||
* @param array $markerArray Marker array
|
||||
* @param array $row Current tt_news row
|
||||
* @param array $lConf Local configuration
|
||||
* @param AbstractPlugin $ttnewsObj Pi-object from tt_news
|
||||
*
|
||||
* @return array Marker array (not changed)
|
||||
*/
|
||||
public function extraItemMarkerProcessor(array $markerArray, array $row, array $lConf, AbstractPlugin $ttnewsObj)
|
||||
{
|
||||
$theCode = (string)strtoupper(trim($ttnewsObj->theCode));
|
||||
|
||||
$connector = GeneralUtility::makeInstance('Metaseo\\Metaseo\\Connector');
|
||||
|
||||
switch ($theCode) {
|
||||
case 'SINGLE':
|
||||
case 'SINGLE2':
|
||||
// Title
|
||||
if (!empty($row['title'])) {
|
||||
$connector->setMetaTag('title', $row['title']);
|
||||
}
|
||||
|
||||
// Description
|
||||
if (!empty($row['short'])) {
|
||||
$connector->setMetaTag('description', $row['short']);
|
||||
}
|
||||
|
||||
// Keywords
|
||||
if (!empty($row['keywords'])) {
|
||||
$connector->setMetaTag('keywords', $row['keywords']);
|
||||
}
|
||||
|
||||
// Short/Description
|
||||
if (!empty($row['short'])) {
|
||||
$connector->setMetaTag('description', $row['short']);
|
||||
}
|
||||
|
||||
// Author
|
||||
if (!empty($row['author'])) {
|
||||
$connector->setMetaTag('author', $row['author']);
|
||||
}
|
||||
|
||||
// E-Mail
|
||||
if (!empty($row['author_email'])) {
|
||||
$connector->setMetaTag('email', $row['author_email']);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return $markerArray;
|
||||
}
|
||||
}
|
||||
128
typo3conf/ext/metaseo/Classes/Hook/HttpHook.php
Normal file
128
typo3conf/ext/metaseo/Classes/Hook/HttpHook.php
Normal file
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright notice
|
||||
*
|
||||
* (c) 2015 Markus Blaschke <typo3@markus-blaschke.de> (metaseo)
|
||||
* (c) 2013 Markus Blaschke (TEQneers GmbH & Co. KG) <blaschke@teqneers.de> (tq_seo)
|
||||
* All rights reserved
|
||||
*
|
||||
* This script is part of the TYPO3 project. The TYPO3 project is
|
||||
* free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* The GNU General Public License can be found at
|
||||
* http://www.gnu.org/copyleft/gpl.html.
|
||||
*
|
||||
* This script is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* This copyright notice MUST APPEAR in all copies of the script!
|
||||
*/
|
||||
|
||||
namespace Metaseo\Metaseo\Hook;
|
||||
|
||||
use Metaseo\Metaseo\Utility\FrontendUtility;
|
||||
use Metaseo\Metaseo\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Http Header generator
|
||||
*/
|
||||
class HttpHook
|
||||
{
|
||||
|
||||
/**
|
||||
* Add HTTP Headers
|
||||
*/
|
||||
public function main()
|
||||
{
|
||||
// INIT
|
||||
$tsSetup = $GLOBALS['TSFE']->tmpl->setup;
|
||||
$headers = array();
|
||||
|
||||
// don't send any headers if headers are already sent
|
||||
if (headers_sent()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Init caches
|
||||
$cacheIdentification = sprintf(
|
||||
'%s_%s_http',
|
||||
$GLOBALS['TSFE']->id,
|
||||
substr(sha1(FrontendUtility::getCurrentUrl()), 10, 30)
|
||||
);
|
||||
|
||||
/** @var \TYPO3\CMS\Core\Cache\CacheManager $cacheManager */
|
||||
$objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
|
||||
'TYPO3\\CMS\\Extbase\\Object\\ObjectManager'
|
||||
);
|
||||
$cacheManager = $objectManager->get('TYPO3\\CMS\\Core\\Cache\\CacheManager');
|
||||
$cache = $cacheManager->getCache('cache_pagesection');
|
||||
|
||||
if (!empty($GLOBALS['TSFE']->tmpl->loaded)) {
|
||||
// ##################################
|
||||
// Non-Cached page
|
||||
// ##################################
|
||||
|
||||
if (!empty($tsSetup['plugin.']['metaseo.']['metaTags.'])) {
|
||||
$tsSetupSeo = $tsSetup['plugin.']['metaseo.']['metaTags.'];
|
||||
|
||||
// ##################################
|
||||
// W3C P3P Tags
|
||||
// ##################################
|
||||
$p3pCP = null;
|
||||
$p3pPolicyUrl = null;
|
||||
|
||||
if (!empty($tsSetupSeo['p3pCP'])) {
|
||||
$p3pCP = $tsSetupSeo['p3pCP'];
|
||||
}
|
||||
|
||||
if (!empty($tsSetupSeo['p3pPolicyUrl'])) {
|
||||
$p3pPolicyUrl = $tsSetupSeo['p3pPolicyUrl'];
|
||||
}
|
||||
|
||||
if (!empty($p3pCP) || !empty($p3pPolicyUrl)) {
|
||||
$p3pHeader = array();
|
||||
|
||||
if (!empty($p3pCP)) {
|
||||
$p3pHeader[] = 'CP="' . $p3pCP . '"';
|
||||
}
|
||||
|
||||
if (!empty($p3pPolicyUrl)) {
|
||||
$p3pHeader[] = 'policyref="' . $p3pPolicyUrl . '"';
|
||||
}
|
||||
|
||||
$headers['P3P'] = implode(' ', $p3pHeader);
|
||||
}
|
||||
}
|
||||
|
||||
// Store headers into cache
|
||||
$cache->set($cacheIdentification, $headers, array('pageId_' . $GLOBALS['TSFE']->id));
|
||||
} else {
|
||||
// #####################################
|
||||
// Cached page
|
||||
// #####################################
|
||||
|
||||
// Fetched cached headers
|
||||
$cachedHeaders = $cache->get($cacheIdentification);
|
||||
|
||||
if (!empty($cachedHeaders)) {
|
||||
$headers = $cachedHeaders;
|
||||
}
|
||||
}
|
||||
|
||||
// Call hook
|
||||
GeneralUtility::callHookAndSignal(__CLASS__, 'httpHeaderOutput', $this, $headers);
|
||||
|
||||
// #####################################
|
||||
// Sender headers
|
||||
// #####################################
|
||||
if (!empty($headers['P3P'])) {
|
||||
header('P3P: ' . $headers['P3P']);
|
||||
}
|
||||
}
|
||||
}
|
||||
290
typo3conf/ext/metaseo/Classes/Hook/SitemapIndexHook.php
Normal file
290
typo3conf/ext/metaseo/Classes/Hook/SitemapIndexHook.php
Normal file
@@ -0,0 +1,290 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright notice
|
||||
*
|
||||
* (c) 2015 Markus Blaschke <typo3@markus-blaschke.de> (metaseo)
|
||||
* (c) 2013 Markus Blaschke (TEQneers GmbH & Co. KG) <blaschke@teqneers.de> (tq_seo)
|
||||
* All rights reserved
|
||||
*
|
||||
* This script is part of the TYPO3 project. The TYPO3 project is
|
||||
* free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* The GNU General Public License can be found at
|
||||
* http://www.gnu.org/copyleft/gpl.html.
|
||||
*
|
||||
* This script is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* This copyright notice MUST APPEAR in all copies of the script!
|
||||
*/
|
||||
|
||||
namespace Metaseo\Metaseo\Hook;
|
||||
|
||||
use Metaseo\Metaseo\Utility\FrontendUtility;
|
||||
use Metaseo\Metaseo\Utility\GeneralUtility;
|
||||
use Metaseo\Metaseo\Utility\SitemapUtility;
|
||||
use TYPO3\CMS\Core\SingletonInterface;
|
||||
|
||||
/**
|
||||
* Sitemap Indexer
|
||||
*/
|
||||
abstract class SitemapIndexHook implements SingletonInterface
|
||||
{
|
||||
|
||||
// ########################################################################
|
||||
// Attributes
|
||||
// ########################################################################
|
||||
|
||||
/**
|
||||
* List of blacklisted page doktypes
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $doktypeBlacklist = array();
|
||||
|
||||
/**
|
||||
* List of blacklisted page types (Setup PAGE object typeNum)
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $pageTypeBlacklist = array();
|
||||
|
||||
/**
|
||||
* Page index status
|
||||
*
|
||||
* @var null|boolean
|
||||
*/
|
||||
protected $pageIndexFlag;
|
||||
|
||||
/**
|
||||
* MetaSEO configuration
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $conf = array();
|
||||
|
||||
/**
|
||||
* Blacklist configuration
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $blacklistConf = array();
|
||||
|
||||
/**
|
||||
* File extension list
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fileExtList = array();
|
||||
|
||||
/**
|
||||
* Sitemap entry expiration
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
protected $indexExpiration;
|
||||
|
||||
|
||||
/**
|
||||
* Object manager
|
||||
*
|
||||
* @var \TYPO3\CMS\Extbase\Object\ObjectManager
|
||||
*/
|
||||
protected $objectManager;
|
||||
|
||||
|
||||
// ########################################################################
|
||||
// Methods
|
||||
// ########################################################################
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
/** @var \TYPO3\CMS\Extbase\Object\ObjectManager $objectManager */
|
||||
$this->objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
|
||||
'TYPO3\\CMS\\Extbase\\Object\\ObjectManager'
|
||||
);
|
||||
|
||||
$this->initConfiguration();
|
||||
}
|
||||
|
||||
/**
|
||||
* Init configuration
|
||||
*/
|
||||
protected function initConfiguration()
|
||||
{
|
||||
// Get configuration
|
||||
if (!empty($GLOBALS['TSFE']->tmpl->setup['plugin.']['metaseo.'])) {
|
||||
$this->conf = $GLOBALS['TSFE']->tmpl->setup['plugin.']['metaseo.'];
|
||||
}
|
||||
|
||||
// Store blacklist configuration
|
||||
if (!empty($this->conf['sitemap.']['index.']['blacklist.'])) {
|
||||
$this->blacklistConf = $this->conf['sitemap.']['index.']['blacklist.'];
|
||||
}
|
||||
|
||||
// Store blacklist configuration
|
||||
if (!empty($this->conf['sitemap.']['index.']['fileExtension.'])) {
|
||||
# File extensions can be a comma separated list
|
||||
foreach ($this->conf['sitemap.']['index.']['fileExtension.'] as $fileExtListRaw) {
|
||||
$fileExtList = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $fileExtListRaw);
|
||||
$this->fileExtList = array_merge($this->fileExtList, $fileExtList);
|
||||
};
|
||||
}
|
||||
|
||||
// Get expiration
|
||||
$expirationInDays = 60;
|
||||
if (!empty($this->conf['sitemap.']['expiration'])) {
|
||||
$expirationInDays = abs($this->conf['sitemap.']['expiration']);
|
||||
}
|
||||
|
||||
$this->indexExpiration = $_SERVER['REQUEST_TIME'] + ($expirationInDays * 24 * 60 * 60);
|
||||
|
||||
// Init blacklist for doktype (from table pages)
|
||||
$this->doktypeBlacklist = SitemapUtility::getDoktypeBlacklist();
|
||||
|
||||
// Init blacklist for PAGE typenum
|
||||
$this->pageTypeBlacklist = SitemapUtility::getPageTypeBlacklist();
|
||||
}
|
||||
|
||||
/**
|
||||
* Process/Clear link url
|
||||
*
|
||||
* @param string $linkUrl Link url
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function processLinkUrl($linkUrl)
|
||||
{
|
||||
static $absRefPrefix = null;
|
||||
static $absRefPrefixLength = 0;
|
||||
$ret = $linkUrl;
|
||||
|
||||
// Fetch abs ref prefix if available/set
|
||||
if ($absRefPrefix === null) {
|
||||
if (!empty($GLOBALS['TSFE']->tmpl->setup['config.']['absRefPrefix'])) {
|
||||
$absRefPrefix = $GLOBALS['TSFE']->tmpl->setup['config.']['absRefPrefix'];
|
||||
$absRefPrefixLength = strlen($absRefPrefix);
|
||||
} else {
|
||||
$absRefPrefix = false;
|
||||
}
|
||||
}
|
||||
|
||||
// remove abs ref prefix
|
||||
if ($absRefPrefix !== false && strpos($ret, $absRefPrefix) === 0) {
|
||||
$ret = substr($ret, $absRefPrefixLength);
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return page change frequency
|
||||
*
|
||||
* @param array $page Page data
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
protected function getPageChangeFrequency(array $page)
|
||||
{
|
||||
$ret = 0;
|
||||
|
||||
if (!empty($page['tx_metaseo_change_frequency'])) {
|
||||
$ret = (int)$page['tx_metaseo_change_frequency'];
|
||||
} elseif (!empty($this->conf['sitemap.']['changeFrequency'])) {
|
||||
$ret = (int)$this->conf['sitemap.']['changeFrequency'];
|
||||
}
|
||||
|
||||
if (empty($pageChangeFrequency)) {
|
||||
$ret = 0;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if sitemap indexing is enabled
|
||||
*
|
||||
* @param string $indexingType Indexing type (page or typolink)
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function checkIfSitemapIndexingIsEnabled($indexingType)
|
||||
{
|
||||
// check if sitemap is enabled in root
|
||||
if (!GeneralUtility::getRootSettingValue('is_sitemap', true)
|
||||
|| !GeneralUtility::getRootSettingValue('is_sitemap_' . $indexingType . '_indexer', true)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check current page
|
||||
if (!$this->checkIfCurrentPageIsIndexable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if current page is indexable
|
||||
*
|
||||
* Will do following checks:
|
||||
* - REQUEST_METHOD (must be GET)
|
||||
* - If there is a feuser session
|
||||
* - Page type blacklisting
|
||||
* - If page is static cacheable
|
||||
* - If no_cache is not set
|
||||
*
|
||||
* (checks will be cached)
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function checkIfCurrentPageIsIndexable()
|
||||
{
|
||||
// check caching status
|
||||
if ($this->pageIndexFlag !== null) {
|
||||
return $this->pageIndexFlag;
|
||||
}
|
||||
|
||||
// by default page is not cacheable
|
||||
$this->pageIndexFlag = false;
|
||||
|
||||
// ############################
|
||||
// Basic checks
|
||||
// ############################
|
||||
|
||||
$cacheConf = array(
|
||||
'allowNoStaticCachable' => (bool)$this->conf['sitemap.']['index.']['allowNoStaticCachable'],
|
||||
'allowNoCache' => (bool)$this->conf['sitemap.']['index.']['allowNoCache']
|
||||
);
|
||||
|
||||
|
||||
if (!FrontendUtility::isCacheable($cacheConf)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for type blacklisting (from typoscript PAGE object)
|
||||
if (in_array($GLOBALS['TSFE']->type, $this->pageTypeBlacklist)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for doktype blacklisting (from current page record)
|
||||
if (in_array((int)$GLOBALS['TSFE']->page['doktype'], $this->doktypeBlacklist)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// all checks successful, page is cacheable
|
||||
$this->pageIndexFlag = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
294
typo3conf/ext/metaseo/Classes/Hook/SitemapIndexLinkHook.php
Normal file
294
typo3conf/ext/metaseo/Classes/Hook/SitemapIndexLinkHook.php
Normal file
@@ -0,0 +1,294 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright notice
|
||||
*
|
||||
* (c) 2015 Markus Blaschke <typo3@markus-blaschke.de> (metaseo)
|
||||
* (c) 2013 Markus Blaschke (TEQneers GmbH & Co. KG) <blaschke@teqneers.de> (tq_seo)
|
||||
* All rights reserved
|
||||
*
|
||||
* This script is part of the TYPO3 project. The TYPO3 project is
|
||||
* free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* The GNU General Public License can be found at
|
||||
* http://www.gnu.org/copyleft/gpl.html.
|
||||
*
|
||||
* This script is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* This copyright notice MUST APPEAR in all copies of the script!
|
||||
*/
|
||||
|
||||
namespace Metaseo\Metaseo\Hook;
|
||||
|
||||
use Metaseo\Metaseo\Utility\GeneralUtility;
|
||||
use Metaseo\Metaseo\Utility\SitemapUtility;
|
||||
|
||||
/**
|
||||
* Sitemap Indexer
|
||||
*/
|
||||
class SitemapIndexLinkHook extends SitemapIndexHook
|
||||
{
|
||||
|
||||
|
||||
// ########################################################################
|
||||
// HOOKS
|
||||
// ########################################################################
|
||||
|
||||
/**
|
||||
* Hook: Link Parser
|
||||
*
|
||||
* @param array $pObj Object
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function hook_linkParse(array &$pObj)
|
||||
{
|
||||
if (!$this->checkIfSitemapIndexingIsEnabled('typolink')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check
|
||||
if (empty($pObj['finalTagParts']) || empty($pObj['conf']) || empty($pObj['finalTagParts']['url'])) {
|
||||
// no valid link
|
||||
return;
|
||||
}
|
||||
|
||||
// Init link information
|
||||
$linkConf = $pObj['conf'];
|
||||
$linkUrl = $pObj['finalTagParts']['url'];
|
||||
list($linkPageUid, $linkType) = $this->parseLinkConf($pObj);
|
||||
$linkUrl = $this->processLinkUrl($linkUrl);
|
||||
|
||||
if ($linkType === null || empty($linkPageUid)) {
|
||||
// no valid link
|
||||
return;
|
||||
}
|
||||
|
||||
// check blacklisting
|
||||
if (GeneralUtility::checkUrlForBlacklisting($linkUrl, $this->blacklistConf)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// ####################################
|
||||
// Init
|
||||
// ####################################
|
||||
|
||||
$addParameters = array();
|
||||
if (!empty($linkConf['additionalParams'])) {
|
||||
parse_str($linkConf['additionalParams'], $addParameters);
|
||||
}
|
||||
|
||||
// #####################################
|
||||
// Check if link is cacheable
|
||||
// #####################################
|
||||
$isValid = false;
|
||||
|
||||
// check if conf is valid
|
||||
if (!empty($linkConf['useCacheHash'])) {
|
||||
$isValid = true;
|
||||
}
|
||||
|
||||
// check for typical typo3 params
|
||||
$addParamsCache = $addParameters;
|
||||
unset($addParamsCache['L']);
|
||||
unset($addParamsCache['type']);
|
||||
|
||||
if (empty($addParamsCache)) {
|
||||
$isValid = true;
|
||||
}
|
||||
|
||||
if (!$isValid) {
|
||||
// page is not cacheable, skip it
|
||||
return;
|
||||
}
|
||||
|
||||
// #####################################
|
||||
// Rootline
|
||||
// #####################################
|
||||
$rootline = GeneralUtility::getRootLine($linkPageUid);
|
||||
|
||||
if (empty($rootline)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// #####################################
|
||||
// Page settings
|
||||
// #####################################
|
||||
|
||||
// Fetch sysLanguage
|
||||
if (isset($addParameters['L'])) {
|
||||
$pageLanguage = (int)$addParameters['L'];
|
||||
} else {
|
||||
$pageLanguage = (int)GeneralUtility::getLanguageId();
|
||||
}
|
||||
|
||||
// Index link
|
||||
$pageData = $this->generateSitemapPageData($linkUrl, $linkPageUid, $rootline, $pageLanguage, $linkType);
|
||||
if (!empty($pageData)) {
|
||||
SitemapUtility::index($pageData);
|
||||
}
|
||||
}
|
||||
|
||||
// ########################################################################
|
||||
// Methods
|
||||
// ########################################################################
|
||||
|
||||
/**
|
||||
* Generate sitemap page data
|
||||
*
|
||||
* @param string $linkUrl Link of current url
|
||||
* @param integer $linkPageUid Link target page id
|
||||
* @param array $rootline Rootline of link
|
||||
* @param integer $pageLanguage Language id
|
||||
* @param integer $linkType Link type
|
||||
*
|
||||
* @return array
|
||||
* @internal param string $pageUrl Page url
|
||||
*
|
||||
*/
|
||||
protected function generateSitemapPageData($linkUrl, $linkPageUid, array $rootline, $pageLanguage, $linkType)
|
||||
{
|
||||
$tstamp = $_SERVER['REQUEST_TIME'];
|
||||
|
||||
$rootPid = $rootline[0]['uid'];
|
||||
|
||||
// Get page data from rootline
|
||||
$page = reset($rootline);
|
||||
|
||||
$ret = array(
|
||||
'tstamp' => $tstamp,
|
||||
'crdate' => $tstamp,
|
||||
'page_rootpid' => $rootPid,
|
||||
'page_uid' => $linkPageUid,
|
||||
'page_language' => $pageLanguage,
|
||||
'page_url' => $this->getPageUrl($linkUrl),
|
||||
'page_depth' => count($rootline),
|
||||
'page_change_frequency' => $this->getPageChangeFrequency($page),
|
||||
'page_type' => $linkType,
|
||||
'expire' => $this->indexExpiration,
|
||||
);
|
||||
|
||||
// Call hook
|
||||
GeneralUtility::callHookAndSignal(__CLASS__, 'sitemapIndexLink', $this, $ret);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse uid and type from generated link (from config array)
|
||||
*
|
||||
* @param array $conf Generated Link config array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function parseLinkConf(array $conf)
|
||||
{
|
||||
$uid = null;
|
||||
$type = null;
|
||||
|
||||
// Check link type
|
||||
switch ($conf['finalTagParts']['TYPE']) {
|
||||
// ##############
|
||||
// Page URL
|
||||
// ##############
|
||||
case 'page':
|
||||
// TODO: Add support for more parameter checks
|
||||
if (is_numeric($conf['conf']['parameter'])) {
|
||||
$uid = $conf['conf']['parameter'];
|
||||
}
|
||||
|
||||
$type = SitemapUtility::SITEMAP_TYPE_PAGE;
|
||||
break;
|
||||
|
||||
// ##############
|
||||
// File URL
|
||||
// ##############
|
||||
case 'file':
|
||||
$fileUrl = $conf['finalTagParts']['url'];
|
||||
|
||||
if ($this->checkIfFileIsWhitelisted($fileUrl)) {
|
||||
// File will be registered from the root page
|
||||
// to prevent duplicate urls
|
||||
$uid = GeneralUtility::getRootPid();
|
||||
$type = SitemapUtility::SITEMAP_TYPE_FILE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return array($uid, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if file is whitelisted
|
||||
*
|
||||
* Configuration specified in
|
||||
* plugin.metaseo.sitemap.index.fileExtension
|
||||
*
|
||||
* @param string $url Url to file
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
protected function checkIfFileIsWhitelisted($url)
|
||||
{
|
||||
$ret = false;
|
||||
|
||||
// check for valid url
|
||||
if (empty($url)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// parse url to extract only path
|
||||
$urlParts = parse_url($url);
|
||||
$filePath = $urlParts['path'];
|
||||
|
||||
// Extract last file extension
|
||||
if (preg_match('/\.([^\.]+)$/', $filePath, $matches)) {
|
||||
$fileExt = trim(strtolower($matches[1]));
|
||||
|
||||
// Check if file extension is whitelisted
|
||||
foreach ($this->fileExtList as $allowedFileExt) {
|
||||
if ($allowedFileExt === $fileExt) {
|
||||
// File is whitelisted, not blacklisted
|
||||
$ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current page url
|
||||
*
|
||||
* @param string $linkUrl Link url
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
protected function getPageUrl($linkUrl)
|
||||
{
|
||||
$linkParts = parse_url($linkUrl);
|
||||
|
||||
// Remove left / (but only if not root page)
|
||||
if ($linkParts['path'] === '/') {
|
||||
// Link points to root page
|
||||
$ret = '/';
|
||||
} else {
|
||||
// Link points to another page, strip left /
|
||||
$ret = ltrim($linkParts['path'], '/');
|
||||
}
|
||||
|
||||
// Add query
|
||||
if (!empty($linkParts['query'])) {
|
||||
$ret .= '?' . $linkParts['query'];
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
168
typo3conf/ext/metaseo/Classes/Hook/SitemapIndexPageHook.php
Normal file
168
typo3conf/ext/metaseo/Classes/Hook/SitemapIndexPageHook.php
Normal file
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright notice
|
||||
*
|
||||
* (c) 2015 Markus Blaschke <typo3@markus-blaschke.de> (metaseo)
|
||||
* (c) 2013 Markus Blaschke (TEQneers GmbH & Co. KG) <blaschke@teqneers.de> (tq_seo)
|
||||
* All rights reserved
|
||||
*
|
||||
* This script is part of the TYPO3 project. The TYPO3 project is
|
||||
* free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* The GNU General Public License can be found at
|
||||
* http://www.gnu.org/copyleft/gpl.html.
|
||||
*
|
||||
* This script is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* This copyright notice MUST APPEAR in all copies of the script!
|
||||
*/
|
||||
|
||||
namespace Metaseo\Metaseo\Hook;
|
||||
|
||||
use Metaseo\Metaseo\Utility\FrontendUtility;
|
||||
use Metaseo\Metaseo\Utility\GeneralUtility;
|
||||
use Metaseo\Metaseo\Utility\SitemapUtility;
|
||||
|
||||
/**
|
||||
* Sitemap Indexer
|
||||
*/
|
||||
class SitemapIndexPageHook extends SitemapIndexHook
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Init configuration
|
||||
*/
|
||||
protected function initConfiguration()
|
||||
{
|
||||
parent::initConfiguration();
|
||||
|
||||
// Check custom index expiration (from connector)
|
||||
/** @var \Metaseo\Metaseo\Connector $connector */
|
||||
$connector = $this->objectManager->get('Metaseo\\Metaseo\\Connector');
|
||||
$sitemapStore = $connector->getStore('sitemap');
|
||||
|
||||
// Set new expiration date
|
||||
if (!empty($sitemapStore['expiration'])) {
|
||||
$this->indexExpiration = $_SERVER['REQUEST_TIME'] + ($sitemapStore['expiration'] * 24 * 60 * 60);
|
||||
}
|
||||
}
|
||||
|
||||
// ########################################################################
|
||||
// HOOKS
|
||||
// ########################################################################
|
||||
|
||||
/**
|
||||
* Hook: Index Page Content
|
||||
*/
|
||||
public function hook_indexContent()
|
||||
{
|
||||
$this->addPageToSitemapIndex();
|
||||
|
||||
$possibility = (int)GeneralUtility::getExtConf('sitemap_clearCachePossibility', 0);
|
||||
|
||||
if ($possibility > 0) {
|
||||
$clearCacheChance = ceil(mt_rand(0, $possibility));
|
||||
if ($clearCacheChance == 1) {
|
||||
SitemapUtility::expire();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ########################################################################
|
||||
// Methods
|
||||
// ########################################################################
|
||||
|
||||
/**
|
||||
* Add Page to sitemap table
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addPageToSitemapIndex()
|
||||
{
|
||||
if (!$this->checkIfSitemapIndexingIsEnabled('page')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$pageUrl = $this->getPageUrl();
|
||||
|
||||
// check blacklisting
|
||||
if (GeneralUtility::checkUrlForBlacklisting($pageUrl, $this->blacklistConf)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Index page
|
||||
$pageData = $this->generateSitemapPageData($pageUrl);
|
||||
if (!empty($pageData)) {
|
||||
SitemapUtility::index($pageData);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate sitemap page data
|
||||
*
|
||||
* @param string $pageUrl Page url
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function generateSitemapPageData($pageUrl)
|
||||
{
|
||||
$page = $GLOBALS['TSFE']->page;
|
||||
|
||||
$tstamp = $_SERVER['REQUEST_TIME'];
|
||||
|
||||
$ret = array(
|
||||
'tstamp' => $tstamp,
|
||||
'crdate' => $tstamp,
|
||||
'page_rootpid' => GeneralUtility::getRootPid(),
|
||||
'page_uid' => $GLOBALS['TSFE']->id,
|
||||
'page_language' => GeneralUtility::getLanguageId(),
|
||||
'page_url' => $pageUrl,
|
||||
'page_depth' => count($GLOBALS['TSFE']->rootLine),
|
||||
'page_change_frequency' => $this->getPageChangeFrequency($page),
|
||||
'page_type' => SitemapUtility::SITEMAP_TYPE_PAGE,
|
||||
'expire' => $this->indexExpiration,
|
||||
);
|
||||
|
||||
// Call hook
|
||||
GeneralUtility::callHookAndSignal(__CLASS__, 'sitemapIndexPage', $this, $ret);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current page url
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
protected function getPageUrl()
|
||||
{
|
||||
// Fetch chash
|
||||
$pageHash = null;
|
||||
if (!empty($GLOBALS['TSFE']->cHash)) {
|
||||
$pageHash = $GLOBALS['TSFE']->cHash;
|
||||
}
|
||||
|
||||
|
||||
// Fetch pageUrl
|
||||
if ($pageHash !== null) {
|
||||
$ret = FrontendUtility::getCurrentUrl();
|
||||
} else {
|
||||
$linkConf = array(
|
||||
'parameter' => $GLOBALS['TSFE']->id,
|
||||
);
|
||||
|
||||
$ret = $GLOBALS['TSFE']->cObj->typoLink_URL($linkConf);
|
||||
$ret = $this->processLinkUrl($ret);
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
154
typo3conf/ext/metaseo/Classes/Hook/TCA/RobotsTxtDefault.php
Normal file
154
typo3conf/ext/metaseo/Classes/Hook/TCA/RobotsTxtDefault.php
Normal file
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright notice
|
||||
*
|
||||
* (c) 2015 Markus Blaschke <typo3@markus-blaschke.de> (metaseo)
|
||||
* (c) 2013 Markus Blaschke (TEQneers GmbH & Co. KG) <blaschke@teqneers.de> (tq_seo)
|
||||
* All rights reserved
|
||||
*
|
||||
* This script is part of the TYPO3 project. The TYPO3 project is
|
||||
* free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* The GNU General Public License can be found at
|
||||
* http://www.gnu.org/copyleft/gpl.html.
|
||||
*
|
||||
* This script is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* This copyright notice MUST APPEAR in all copies of the script!
|
||||
*/
|
||||
|
||||
namespace Metaseo\Metaseo\Hook\TCA;
|
||||
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Extbase\Configuration\ConfigurationManager;
|
||||
|
||||
/**
|
||||
* TCA Hook: Robots.txt default content
|
||||
*/
|
||||
class RobotsTxtDefault
|
||||
{
|
||||
|
||||
/**
|
||||
* TYPO3 Object manager
|
||||
*
|
||||
* @var \TYPO3\CMS\Extbase\Object\ObjectManager
|
||||
*/
|
||||
protected $objectManager;
|
||||
|
||||
/**
|
||||
* TYPO3 configuration manager
|
||||
*
|
||||
* @var ConfigurationManager
|
||||
*/
|
||||
protected $configurationManager;
|
||||
|
||||
/**
|
||||
* TYPO3 Content object renderer
|
||||
*
|
||||
* @var \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
|
||||
*/
|
||||
protected $cObj;
|
||||
|
||||
/**
|
||||
* Render default Robots.txt from TypoScript Setup
|
||||
*
|
||||
* @param array $data TCE Information array
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function main(array $data)
|
||||
{
|
||||
// ############################
|
||||
// Init
|
||||
// ############################
|
||||
|
||||
/** @var \TYPO3\CMS\Extbase\Object\ObjectManager objectManager */
|
||||
$this->objectManager = GeneralUtility::makeInstance(
|
||||
'TYPO3\\CMS\\Extbase\\Object\\ObjectManager'
|
||||
);
|
||||
|
||||
/** @var ConfigurationManager configurationManager */
|
||||
$this->configurationManager = $this->objectManager->get(
|
||||
'TYPO3\\CMS\\Extbase\\Configuration\\ConfigurationManager'
|
||||
);
|
||||
|
||||
/** @var \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer cObj */
|
||||
$this->cObj = $this->objectManager->get('TYPO3\\CMS\\Frontend\\ContentObject\\ContentObjectRenderer');
|
||||
|
||||
// ############################
|
||||
// Init TSFE
|
||||
// ############################
|
||||
$rootPageId = $data['row']['pid'];
|
||||
|
||||
/** @var \TYPO3\CMS\Core\TimeTracker\NullTimeTracker $timeTracker */
|
||||
$timeTracker = $this->objectManager->get('TYPO3\\CMS\\Core\\TimeTracker\\NullTimeTracker');
|
||||
|
||||
$GLOBALS['TT'] = $timeTracker;
|
||||
$GLOBALS['TT']->start();
|
||||
|
||||
/** @var \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController $tsfeController */
|
||||
$tsfeController = $this->objectManager->get(
|
||||
'TYPO3\\CMS\\Frontend\\Controller\\TypoScriptFrontendController',
|
||||
$GLOBALS['TYPO3_CONF_VARS'],
|
||||
$rootPageId,
|
||||
0
|
||||
);
|
||||
|
||||
$GLOBALS['TSFE'] = $tsfeController;
|
||||
|
||||
// ############################
|
||||
// Render default robots.txt content
|
||||
// ############################
|
||||
|
||||
// Fetch TypoScript setup
|
||||
$tsSetup = $this->configurationManager->getConfiguration(
|
||||
ConfigurationManager::CONFIGURATION_TYPE_FULL_TYPOSCRIPT,
|
||||
'metaseo',
|
||||
'plugin'
|
||||
);
|
||||
|
||||
$content = '';
|
||||
if (!empty($tsSetup['plugin.']['metaseo.']['robotsTxt.'])) {
|
||||
$content = $this->cObj->cObjGetSingle(
|
||||
$tsSetup['plugin.']['metaseo.']['robotsTxt.']['default'],
|
||||
$tsSetup['plugin.']['metaseo.']['robotsTxt.']['default.']
|
||||
);
|
||||
}
|
||||
|
||||
$content = htmlspecialchars($content);
|
||||
$content = nl2br($content);
|
||||
|
||||
/**
|
||||
* instanciation of TypoScriptFrontendController instanciates PageRenderer which
|
||||
* sets backPath to TYPO3_mainDir which is very bad in the Backend. Therefore,
|
||||
* we must set it back to null to not get frontend-prefixed asset URLs. See #150.
|
||||
*/
|
||||
$this->cleanUpPageRendererBackPath();
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets backPath of PageRenderer back to null (for Backend)
|
||||
*/
|
||||
protected function cleanUpPageRendererBackPath()
|
||||
{
|
||||
$pageRenderer = $this->getPageRenderer();
|
||||
$pageRenderer->setBackPath(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \TYPO3\CMS\Core\Page\PageRenderer
|
||||
*/
|
||||
protected function getPageRenderer()
|
||||
{
|
||||
return GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Page\\PageRenderer');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user