ConLite/conlite/plugins/chains/createmetatags/classes/class.metatag.creator.html5...

480 Zeilen
16 KiB
PHP

<?php
/**
* File:
* class.metatag.creator.html5.php
*
* Description:
* Check and/or create metatags for html5
*
* @package Core
* @subpackage Chains
* @version $Rev$
* @since 2.0.0
* @author Ortwin Pinke <o.pinke@conlite.org>
* @copyright (c) 2012-2013, ConLite Team <www.conlite.org>
* @license http://www.gnu.de/documents/gpl.en.html GPL v3 (english version)
* @license http://www.gnu.de/documents/gpl.de.html GPL v3 (deutsche Version)
* @link http://www.conlite.org ConLite.org
*
* $Id$
*/
// security check
defined('CON_FRAMEWORK') or die('Illegal call');
/**
* Description of class
*
* @author Ortwin Pinke <o.pinke@conlite.org>
*/
class MetaTagCreatorHtml5 {
/**
*
* @var array
*/
protected static $_MetaExtensions = null;
/**
*
* @var array default values for meta names
*/
protected $_aDefinedMeta = array('application-name','author','description','generator','keywords');
/**
* Holds all config vars for metatag-creator
* You may add custom-settings using client-setting
* meta_tag_creator_html5 | [name of setting] | [value]
*
* possible names|values are
* only_html5|boolean (default:true) ,if set to true non-valide metas are deleted
* add_article_meta|boolean (default:true), if set to true metas set in article conf will overwrite existing meta
* use_cache|boolean (default:true) use cache/cachefile or not
* cachetime|[seconds]
* cachedir|[path to writable cache dir]
*
* @var array predefined config array
*/
protected $_aConfig = array(
'only_html5' => true,
'add_article_meta' => true,
'use_cache' => true
);
/**
*
* @var string path/filename of cachefile
*/
protected $_sCacheFile = null;
/**
* Incoming and Outgoing MetaTags
*
* @var array holds all metatags
*/
protected $_aMetaTags = array();
/**
* New created MetaTags
*
* @var array
*/
protected $_aCreatedMetaTags = array();
/**
*
* @var boolean switch on debugging output
*/
protected $_bDebug = false;
/**
* Object of the current article
*
* @var Article
*/
protected $_oArticle = NULL;
/**
* Constructor
*
* @global int $idart
* @global int $client
* @global int $lang
* @param array $aMTags given array of metatags
* @param array $aConfig configuration array
*
* @return void
*/
public function __construct($aMTags, $aConfig) {
global $idart, $client, $lang;
$this->_iIdart = (int) $idart;
$this->_iClient = (int) $client;
$this->_iLang = (int) $lang;
if(is_null(self::$_MetaExtensions)) {
$file = dirname(dirname(__FILE__))."/conf/MetaExtension.php";
if ($aTmp = include_once($file)) {
self::$_MetaExtensions = $aTmp;
}
self::$_MetaExtensions = array_merge(self::$_MetaExtensions, $this->_aDefinedMeta);
}
if(is_array($aConfig) && count($aConfig) > 0) {
$this->_aConfig = array_merge($this->_aConfig, $aConfig);
}
$aCustomConfig = getEffectiveSettingsByType("meta_tag_creator_html5");
if(is_array($aCustomConfig) && count($aCustomConfig) > 0) {
$this->_aConfig = array_merge($this->_aConfig, $aCustomConfig);
}
if(is_array($aMTags) && count($aMTags) > 0) {
$this->_aMetaTags = array_merge($this->_aMetaTags, $aMTags);
}
if($this->_bDebug) {
echo "<pre>";
print_r($this->_aMetaTags);
}
$this->_createCacheFileHash();
}
/**
*
* @return array generated cached metatag array
*/
public function generateMetaTags() {
if($this->_aConfig['use_cache'] && $this->_checkCacheFile()) {
return $this->_getCacheFile();
}
// add metatags
$this->_addArticleMeta();
$this->_addFacebookMetaTags();
$this->_mergeNewMetaTags();
if(count($this->_aMetaTags) > 0) {
$this->_checkForHtml5Tags();
}
if($this->_bDebug) {
echo "<pre>";
print_r($this->_aMetaTags);
}
if($this->_aConfig['use_cache'] && $this->_createCacheFile()) {
return $this->_getCacheFile();
}
return $this->_aMetaTags;
}
/**
* Adds article meta to meta array
*
* @global int $lang
* @global array $encoding
* @return void
*/
protected function _addArticleMeta() {
global $lang, $encoding;
if($this->_aConfig['add_article_meta'] === false) return false;
if(is_null($this->_oArticle) || !is_object($this->_oArticle)) {
$this->_oArticle = new Article($this->_iIdart, $this->_iClient, $this->_iLang);
}
$aHeadLines = $this->_checkAndMergeArrays($this->_oArticle->getContent("htmlhead"),
$this->_oArticle->getContent("head"));
$aText = $this->_checkAndMergeArrays($this->_oArticle->getContent("html"),
$this->_oArticle->getContent("text"));
$sHead = $this->_getFirstArrayValue($aHeadLines);
$sText = $this->_getFirstArrayValue($aText);
if($sHead) {
$sHead = substr(str_replace(chr(13).chr(10),' ',strip_tags($sHead)),0,100);
$this->_addMeta('description', $sHead);
}
if($sText) {
$sText = keywordDensity($sHead, strip_tags(urldecode($sText)), $encoding[$lang]);
$this->_addMeta('keywords', $sText);
}
// get custom meta from article conf
$aAvailableMeta = conGetAvailableMetaTagTypes();
foreach($aAvailableMeta as $iIdMeta=>$aValue) {
if($aValue['fieldname'] != 'name') continue;
if($this->_isHtml5Ext($aValue['name'])) {
$sTmpContent = conGetMetaValue($this->_oArticle->getIdArtLang(), $iIdMeta);
if(empty($sTmpContent)) continue;
$this->_addMeta($aValue['name'], $sTmpContent);
}
}
unset($oArticle);
}
/**
*
*
* <!-- Facebook Meta Data -->
* <meta property="og:image" content="http://www.conlite.org/uploads/fb_thumbs/sample.jpg"/>
* <meta property="og:locality" content="Eltmann"/>
* <meta property="og:country-name" content="Germany"/>
* <meta property="og:latitude" content="49.9718"/>
* <meta property="og:longitude" content="10.6666"/>
* <meta property="og:type" content="blog"/>
* <meta property="og:title" content="Virgin Atlantic Advert 2010"/>
* <meta property="og:url" content="http://www.conlite.org/de/sample-article/"/>
* <meta property="og:site_name" content="ConLite Portal"/>
* <meta property="fb:admins" content="123456789,234567891"/>
* <meta property="fb:page_id" content="200185198887" />
*
* @return boolean
*/
protected function _addFacebookMetaTags() {
if(empty($this->_aConfig['add_facebook_meta'])) return;
// add always article data, cause they needed for fb-meta
if($this->_aConfig['add_article_meta'] === false) {
$this->_aConfig['add_article_meta'] = true;
$this->_addArticleMeta();
}
$aAllowedFbMetas = array("og:image","og:locality","og:country-name","og:latitude","og:longitude",
"og:type","og:title","og:url","og:site_name","fb_admins","fb:page_id");
$this->_aDefinedMeta = array_merge($this->_aDefinedMeta, $aAllowedFbMetas);
$aFbSystemSettings = getEffectiveSettingsByType('facebook');
$bHasSysSettings = (count($aFbSystemSettings) > 0)?true:false;
foreach ($aAllowedFbMetas as $sMetaName) {
if($sProp = $this->_oArticle->getProperty('facebook', $sMetaName)) {
if(empty($sProp)) {
continue;
} else {
$this->_addPropertyMeta($sMetaName, $sProp);
}
}
if($bHasSysSettings) {
if(array_key_exists($sMetaName, $aFbSystemSettings)) {
$this->_addPropertyMeta($sMetaName, $aFbSystemSettings[$sMetaName]);
}
}
switch ($sMetaName) {
case "og:url":
$aParams = array ('idcat' => $this->_iIdart,'lang' => $this->_iLang);
$sUrl = Contenido_Url::getInstance()->build($aParams, true);
$this->_addPropertyMeta($sMetaName, $sUrl);
break;
case "og:title":
$sTitle = $this->_oArticle->getField("title");
$this->_addPropertyMeta($sMetaName, $sTitle);
break;
case "og:image":
if(!isset($this->_aCreatedMetaTags[$sMetaName])) {
$aImages = $this->_oArticle->getContent("img");
$iImg = 0;
if(is_array($aImages) && count($aImages) > 0) {
if(isset($aFbSystemSettings['cms_img_no'])
&& (int)$aFbSystemSettings['cms_img_no'] > 0
&& array_key_exists($aFbSystemSettings['cms_img_no'], $aImages)) {
$iImg = $aFbSystemSettings['cms_img_no'];
} else {
$iImg = 1;
}
if($iImg && $aFbSystemSettings['use_cms_img']) {
/* @var $oImg UploadItem */
$oImg = new UploadItem($iImg);
$sImgHtmlPath = $oImg->getField("url");
unset($oImg);
}
}
}
break;
}
}
}
protected function _mergeNewMetaTags() {
if(count($this->_aCreatedMetaTags) > 0) {
foreach($this->_aCreatedMetaTags as $iKey=>$aValue) {
$iKey = $this->_inMetaArray($aValue['name'], $this->_aMetaTags);
if($iKey !== false) {
$this->_aMetaTags[$iKey]['content'] = $aValue['content'];
} else {
array_push($this->_aMetaTags, $aValue);
}
}
}
}
/**
* Check meta array for valid html5 meta tags
*
* @todo add support for other meta tags than name
* @return void
*/
protected function _checkForHtml5Tags() {
if(!$this->_aConfig['only_html5']) return;
foreach($this->_aMetaTags as $iKey => $aValue) {
if(key_exists('name', $aValue)) {
if($this->_isHtml5Ext($aValue['name'])) continue;
unset($this->_aMetaTags[$iKey]);
}
}
}
/**
* Check if extensions is registered
*
* @uses $_MetaExtensions Array of default and registered extensions
* @param string $sExt
* @return boolean
*/
protected function _isHtml5Ext($sExt) {
$sExt = strtolower($sExt);
// check standard tags first
if(in_array($sExt, $this->_aDefinedMeta)) return true;
// check only names to save time
if(in_array($sExt, self::$_MetaExtensions['names'])) return true;
// now check keys with deeper arrays
if(array_key_exists($sExt, self::$_MetaExtensions)) return true;
// parts
foreach(self::$_MetaExtensions as $sKey=>$aValue) {
if($sKey === $sExt) return true;
if(stristr($sKey, $sExt)) return true;
}
return false;
}
/**
* Cachefile exists and not outdated
*
* @return boolean
*/
protected function _checkCacheFile() {
if(file_exists($this->_sCacheFile)) {
$iDiff = time() - filemtime($this->_sCacheFile);
if($iDiff < $this->_aConfig['cachetime']) {
return true;
}
}
return false;
}
/**
* Get meta-array from cachefile
*
* @return array
*/
protected function _getCacheFile() {
return unserialize(file_get_contents($this->_sCacheFile));
}
/**
* Create cachefile
*
* @return boolean
*/
protected function _createCacheFile() {
if(empty($this->_sCacheFile)) {
return false;
}
return (file_put_contents($this->_sCacheFile, serialize($this->_aMetaTags)) === false)?false:true;
}
/**
* Create path to cachefile with hashed filename
*
* @global int $idart
* @global int $lang
* @return void
*/
protected function _createCacheFileHash() {
global $idart, $lang;
if(isset($this->_aConfig['cachedir'])
&& !empty($this->_aConfig['cachedir'])
&& is_dir($this->_aConfig['cachedir'])
&& is_writable($this->_aConfig['cachedir'])) {
$hash = 'metatag_'.md5($idart.'/'.$lang);
$this->_sCacheFile = $this->_aConfig['cachedir'].$hash.'.tmp';
}
}
/**
* Merge 2 arrays
*
* @param array $aArr1
* @param array $aArr2
* @return array merged array
*/
protected function _checkAndMergeArrays($aArr1, $aArr2) {
if(!is_array($aArr1)) {
$aArr1 = array();
}
if(!is_array($aArr2)) {
$aArr2 = array();
}
return array_merge($aArr1, $aArr2);
}
/**
*
* @param type $aArr
* @return mixed text as string or false
*/
protected function _getFirstArrayValue($aArr) {
$sText = "";
foreach ($aArr as $key => $value) {
if ($value != '') {
$sText = $value;
break;
}
}
return (empty($sText))?false:$sText;
}
/**
* Add new meta to meta-array
* overwrite if exist
*
* @param string $sName
* @param string $sValue
* @return void
*/
protected function _addMeta($sName, $sValue) {
$aTmp = array(
'name' => $sName,
'content' => $sValue
);
$iTmpKey = $this->_inMetaArray($sName, $this->_aCreatedMetaTags);
if(false !== $iTmpKey) {
$this->_aCreatedMetaTags[$iTmpKey]['content'] = $sValue;
} else {
array_push($this->_aCreatedMetaTags, $aTmp);
}
}
protected function _addPropertyMeta($sName, $sValue) {
$aTmp = array(
'property' => $sName,
'content' => $sValue
);
$iTmpKey = $this->_inMetaArray($sName, $this->_aCreatedMetaTags);
if(false !== $iTmpKey) {
$this->_aCreatedMetaTags[$iTmpKey]['content'] = $sValue;
} else {
array_push($this->_aCreatedMetaTags, $aTmp);
}
}
/**
* Search in meta-array for a name/content
* returns the key if the needle is found
*
* @param string $sNeedle
* @param array $aHaystack
* @param boolean $bStrict
* @return mixed key_number in haystack or false if nothing was found
*/
protected function _inMetaArray($sNeedle, $aHaystack, $bStrict = false) {
foreach($aHaystack as $iKey=>$aValue) {
if(in_array($sNeedle, $aValue)) return $iKey;
}
return false;
}
}
?>