Your IP : 216.73.216.43


Current Path : /home/cbequiperp/www/plugins/system/cccsocialmedia/
Upload File :
Current File : /home/cbequiperp/www/plugins/system/cccsocialmedia/cccsocialmedia.php

<?php
/**
 * @package    cccsocialmedia
 *
 * @author     COOLCAT creations - Elisa Foltyn <mail@coolcat-creations.com>
 * @copyright  COOLCAT creations - Elisa Foltyn
 * @license    GNU General Public License version 2 or later; see LICENSE.txt
 * @link       https://coolcat-creations.com
 */

use Joomla\CMS\Application\CMSApplication;
use Joomla\CMS\Document\Document;
use Joomla\CMS\Factory;
use Joomla\CMS\Form\Form;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\Table\Content;
use Joomla\CMS\Uri\Uri;
use Joomla\Database\DatabaseDriver;
use Joomla\Registry\Registry;

defined('_JEXEC') or die;

/**
 * CCC Socialmedia plugin.
 *
 * @package  CCC socialmedia
 * @since    1.0
 */
class plgSystemCccsocialmedia extends CMSPlugin
{
	public const GOOGLE    = 'google';
	public const FACEBOOK  = 'facebook';
	public const PINTEREST = 'pinterest';
	public const NONE      = '';

	/**
	 * Application object
	 *
	 * The application is injected by parent constructor
	 *
	 * @var    CMSApplication
	 * @since  1.0
	 */
	protected $app;

	/**
	 * Database object
	 *
	 * The database is injected by parent constructor
	 *
	 * @var    DatabaseDriver|\JDatabaseDriver
	 * @since  1.0
	 */
	protected $db;

	/**
	 * Affects constructor behavior. If true, language files will be loaded automatically.
	 *
	 * @var    boolean
	 * @since  1.0
	 */
	protected $autoloadLanguage = true;

	/**
	 * Add fields for the OpenGraph data to the form
	 *
	 * @param   \Joomla\CMS\Form\Form  $form
	 *
	 * @return boolean
	 * @since  1.0
	 */
	public function onContentPrepareForm(Form $form): bool
	{
		$option = $this->app->input->get('option');
		$client = $this->app->getName();

		$whereToRun = $this->params->get('whereToRun', 'both');
		if (($whereToRun === 'administrator' || $whereToRun === 'site')
			&& $client !== $whereToRun)
		{
			return true;
		}

		switch ("$option.$client")
		{
			case 'com_menus.administrator':
			{
				$form::addFormPath(__DIR__ . '/forms');
				$form->loadFile('cccsocialmedia_menu', false);

				break;
			}

			case 'com_content.administrator':
			case 'com_content.site':
			{
				$form::addFormPath(__DIR__ . '/forms');
				$form->loadFile('cccsocialmedia_article', false);

				break;
			}
		}

		return true;
	}

	/**
	 * Prepare the OpenGraph metadata for rendeering
	 *
	 * @return bool
	 * @since  1.0
	 */
	public function onBeforeCompileHead(): bool
	{
		$input  = $this->app->input;
		$option = $input->get('option', '', 'cmd');
		$view   = $input->get('view', '', 'cmd');

		if (($option . '.' . $view) === 'com_finder.indexer')
		{
			return true;
		}

		if ($input->get('format', '', 'cmd') === 'feed')
		{
			return true;
		}

		$uniqueArticle = true;
		if(is_array($input->get('id', 0, 'int'))){
			$uniqueArticle = false;
		}

		if (!$this->app->isClient('site'))
		{
			return true;
		}

		/** @var \Joomla\CMS\Document\Document $document */
		$document       = $this->app->getDocument();

		if($uniqueArticle) {
			$article        = $this->getArticle($input->get('id', 0, 'int'));
		} else {
			$article        = false;
		}

		$menuParams     = $this->getMenuParams();
		$articleAttribs = new Registry($article->attribs ?? '{}');
		$articleImages  = new Registry($article->images ?? '{}');
		$userAgent      = $this->getBot();

		$this->combineSettings($this->params, $articleAttribs, $menuParams);
		$this->addImageFallback($this->params, $articleImages, $view, $userAgent);
		$this->addTitleFallback($this->params, $articleAttribs, $menuParams, $document);
		$this->addDescriptionFallback($this->params, $menuParams, $document, $view);

		if($uniqueArticle) {
			$this->addPublishedFallback($this->params, $article);
		}
		
		$this->injectOpenGraphData($document, $this->params);

		return true;
	}

	/**
	 * @param   \Joomla\Registry\Registry  $params
	 * @param   \Joomla\Registry\Registry  $articleAttribs
	 * @param   \Joomla\Registry\Registry  $menuParams
	 *
	 * @return void
	 * @since  2.0.0
	 */
	private function combineSettings(Registry $params, Registry $articleAttribs, Registry $menuParams): void
	{
		static $settings = array(
			'og_title',
			'og_type',
			'og_description',
			'og_image',
			'og_image_fb',
			'og_image_pi',
			'og_image_alt',
			'og_article_published_time',
			'og_article_author',
			'og_product_availability',
			'og_product_price_currency',
			'og_product_price_amount',
			'tw_title',
			'tw_description',
			'tw_image',
			'tw_image_alt',
			'tw_site',
			'tw_type',
			'tw_creator'
		);

		$config = Factory::getConfig();

		if ($config === null)
		{
			throw new \RuntimeException('Unable to load global configuration');
		}

		$params->set('sitename', $config->get('sitename'));
		$params->set('base_url', Uri::base());
		$params->set('url', Uri::getInstance());

		foreach ($settings as $setting)
		{
			$params->set(
				$setting,
				// Priority A - Menu parameters
				$menuParams->get(
					$setting,
					// Priority B - Article parameters
					$articleAttribs->get(
						$setting,
						// Priority C - Module parameters
						$params->get(
							$setting,
							''
						)
					)
				)
			);
		}
	}

	/**
	 * @param   \Joomla\Registry\Registry  $params
	 * @param   \Joomla\Registry\Registry  $articleImages
	 * @param   string                     $view
	 * @param   string                     $userAgent
	 *
	 * @return void
	 * @since  2.0.0
	 */
	private function addImageFallback(Registry $params, Registry $articleImages, string $view, string $userAgent): void
	{

		$alt = $params->get('og_image_alt');

		if ($userAgent === self::FACEBOOK && $params->get('og_image_fb') > '')
		{
			$image = $params->get('og_image_fb');
		}
		elseif ($userAgent === self::GOOGLE && $params->get('og_image') > '')
		{
			$image = $params->get('og_image');
		}
		elseif ($userAgent === self::PINTEREST && $params->get('og_image_pi') > '')
		{
			$image = $params->get('og_image_pi');
		}
		elseif ($params->get('og_image_fb') > '')
		{
			$image = $params->get('og_image_fb');
		}
		else
		{
			[$image, $alt] = $this->getArticleImage($articleImages);
		}

		$params->set('og_image', $image);
		$params->set('og_image_alt', $alt);
		$params->set('tw_image', $image);
		$params->set('tw_image_alt', $alt);
	}

	/**
	 * @param   \Joomla\Registry\Registry      $params
	 * @param   \Joomla\Registry\Registry      $articleAttribs
	 * @param   \Joomla\Registry\Registry      $menuParams
	 * @param   \Joomla\CMS\Document\Document  $document
	 *
	 * @return void
	 * @since  2.0.0
	 */
	private function addTitleFallback(
		Registry $params,
		Registry $articleAttribs,
		Registry $menuParams,
		Document $document
	): void {
		$title = $this->getTitle($articleAttribs, $menuParams, $document);

		$params->def('og_title', $title);
		$params->def('tw_title', $title);
	}

	/**
	 * @param   \Joomla\Registry\Registry       $params
	 * @param   \Joomla\Registry\Registry       $menuParams
	 * @param   \Joomla\CMS\Document\Document   $document
	 * @param                                   $view
	 *
	 * @return void
	 * @since  2.0.0
	 */
	private function addDescriptionFallback(Registry $params, Registry $menuParams, Document $document, $view): void
	{
		$description = $this->getDescription($menuParams, $document, $view);

		$params->def('og_description', $description);
		$params->def('tw_description', $description);
	}

	/**
	 * @param   \Joomla\Registry\Registry  $params
	 * @param   \Joomla\CMS\Table\Content  $article
	 *
	 * @return void
	 * @since  2.0.0
	 */
	private function addPublishedFallback(Registry $params, Content $article): void
	{
		$params->def('og_article_published_time', $article->created ?? '');
	}

	/**
	 * Get the article with the given ID
	 *
	 * @param   int  $id
	 *
	 * @return \Joomla\CMS\Table\Content
	 * @since  2.0.0
	 */
	private function getArticle(int $id): Content
	{
		$article = new Content($this->db);
		$article->load($id);

		return $article;
	}

	/**
	 * @param   \Joomla\Registry\Registry  $articleImages
	 *
	 * @return array
	 * @since  2.0.0
	 */
	private function getArticleImage(Registry $articleImages): array
	{
		$image = $alt = '';

		if ($articleImages->get('image_intro') > '') {
			// get part before # in image if # exists
			if (strpos($articleImages->get('image_intro'), '#') !== false) {
				$image = substr($articleImages->get('image_intro'), 0, strpos($articleImages->get('image_intro'), '#'));
			} else {
				$image = $articleImages->get('image_intro');
			}

			$alt = $articleImages->get('image_intro_alt', '');

		}
		if ($articleImages->get('image_fulltext') > '') {

			if (strpos($articleImages->get('image_fulltext'), '#') !== false) {
				$image = substr($articleImages->get('image_fulltext'), 0, strpos($articleImages->get('image_fulltext'), '#'));
			} else {
				$image = $articleImages->get('image_fulltext');
			}

			$alt = $articleImages->get('image_fulltext_alt', '');

		}

		return array($image, $alt);
	}

	/**
	 * @param   \Joomla\Registry\Registry      $articleAttribs
	 * @param   \Joomla\Registry\Registry      $menuParams
	 * @param   \Joomla\CMS\Document\Document  $document
	 *
	 * @return string
	 * @since  2.0.0
	 */
	private function getTitle(Registry $articleAttribs, Registry $menuParams, Document $document): string
	{
		return $articleAttribs->get(
			'article_page_title',
			$menuParams->get(
				'page_title',
				$document->title ?? ''
			)
		);
	}

	/**
	 * @param   \Joomla\Registry\Registry      $menuParams
	 * @param   \Joomla\CMS\Document\Document  $document
	 * @param                                  $view
	 *
	 * @return string
	 * @since  2.0.0
	 */
	private function getDescription(Registry $menuParams, Document $document, $view): string
	{
		if ($view === 'category')
		{
			$description = $menuParams->get(
				'menu-meta_description',
				$menuParams->get(
					'page_description',
					$document->description ?? ''
				)
			);
		}
		else
		{
			$description = $document->description ?? '';
		}

		return $description;
	}

	/**
	 * Get the bot, if any
	 *
	 * If the bot is self::FACEBOOK, gzip compression is turned off.
	 *
	 * @return string One of this class' constants
	 * @since  2.0.0
	 */
	private function getBot(): string
	{
		static $userAgents = [
			self::GOOGLE    => ['googlebot'],
			self::FACEBOOK  => ['facebot', 'facebook', 'LinkedInBot'],
			self::PINTEREST => ['pinterest'],
		];

		$bot       = self::NONE;
		$useragent = null;

		if ($_SERVER['HTTP_USER_AGENT'])
		{
			$useragent = $_SERVER['HTTP_USER_AGENT'];
		}

		if (!empty($useragent))
		{
			foreach ($userAgents as $key => $subStrings)
			{
				foreach ($subStrings as $subString)
				{
					if (stripos($useragent, $subString) !== false)
					{
						$bot = $key;
						break 2;
					}
				}
			}

			if ($bot === self::FACEBOOK)
			{
				$this->app->set('gzip', 0);
			}
		}

		return $bot;
	}

	/**
	 * Get the parameters associated with the active menu item
	 *
	 * @return \Joomla\Registry\Registry
	 * @since  2.0.0
	 */
	private function getMenuParams(): Registry
	{
		$menu   = $this->app->getMenu();

		if ($menu === null)
		{
			return new Registry([]);
		}

		$active = $menu->getActive();

		if ($active === null)
		{
			return new Registry([]);
		}

		$itemId = $active->id;

		return $menu->getParams($itemId);
	}

	/**
	 * Add OpenGraph data to document
	 *
	 * @param   \Joomla\CMS\Document\Document  $document
	 * @param   string|null                    $image
	 * @param   string|null                    $alt
	 * @param   string|null                    $baseUrl
	 *
	 * @return void
	 * @since  2.0.0
	 */
	private function setOpenGraphImage(
		Document $document,
		?string $image = '',
		?string $alt = '',
		?string $baseUrl = ''
	): void {
		if (empty($image) || !empty($document->getMetaData('og:image')))
		{
			return;
		}

		$image = preg_replace('~^([\w\-./\\\]+).*$~', '$1', $image);

		if (!file_exists($image))
		{
			return;
		}

		$url = empty($baseUrl) ? '' : rtrim($baseUrl, '/') . '/';
		$url .= $image;

		$this->setMetaData($document, 'og:image', $url, 'property');
		$this->setMetaData($document, 'og:image:secure_url', $url, 'property');
		$this->setMetaData($document, 'og:image:alt', $alt, 'property');
		$this->setMetaDataIfNotSet($document, 'twitter:image', $url, 'name');
		$this->setMetaDataIfNotSet($document, 'twitter:image:alt', $alt, 'name');

		$info = getimagesize($image);

		if (\is_array($info))
		{
			$this->setMetaData($document, 'og:image:type', $info['mime'], 'property');
			$this->setMetaData($document, 'og:image:height', $info[1]);
			$this->setMetaData($document, 'og:image:width', $info[0]);
		}
	}

	/**
	 * @param   \Joomla\CMS\Document\Document  $document
	 * @param   string|null                    $type
	 * @param   string|null                    $price
	 * @param   string|null                    $currency
	 * @param   string|null                    $availability
	 *
	 * @return void
	 * @since  2.0.0
	 */
	private function setProduct(
		Document $document,
		?string $type = '',
		?string $price = '',
		?string $currency = '',
		?string $availability = ''
	): void {
		if ($type === 'product')
		{
			$this->setMetaDataIfNotSet($document, 'product:price:amount', $price, 'property');
			$this->setMetaDataIfNotSet($document, 'product:price:currency', $currency, 'property');
			$this->setMetaDataIfNotSet($document, 'og:availability', $availability, 'property');
		}
	}

	/**
	 * Set metadata in document only if not already set
	 *
	 * @param   \Joomla\CMS\Document\Document  $document
	 * @param   string                         $key
	 * @param   string|null                    $value
	 * @param   string                         $attribute
	 *
	 * @return void
	 * @since  2.0.0
	 */
	private function setMetaDataIfNotSet(
		Document $document,
		string $key,
		?string $value = '',
		string $attribute = 'name'
	): void {
		if (!empty($value) && empty($document->getMetaData($key)))
		{
			$this->setMetaData($document, $key, $value, $attribute);
		}
	}

	/**
	 * Set metadata in document regardless previous content
	 *
	 * @param   \Joomla\CMS\Document\Document  $document
	 * @param   string                         $key
	 * @param   string|null                    $value
	 * @param   string                         $attribute
	 *
	 * @return void
	 * @since  2.0.0
	 */
	private function setMetaData(Document $document, string $key, ?string $value = '', string $attribute = 'name'): void
	{
		$document->setMetaData($key, $value, $attribute);
	}

	/**
	 * @param   \Joomla\CMS\Document\Document  $document
	 * @param   \Joomla\Registry\Registry      $params
	 *
	 * @return void
	 * @since  2.0.0
	 */
	private function injectOpenGraphData(Document $document, Registry $params): void
	{
		$this->setMetaData($document, 'og:url', $params->get('url'), 'property');

		$this->setMetaData($document, 'og:site_name', $params->get('sitename'), 'property');
		$this->setMetaDataIfNotSet($document, 'twitter:site', $params->get('tw_site'), 'name');

		$this->setMetaDataIfNotSet($document, 'og:type', $params->get('og_type'), 'property');
		$this->setMetaDataIfNotSet($document, 'twitter:card', $params->get('tw_type'), 'name');

		$this->setMetaDataIfNotSet($document, 'og:title', $params->get('og_title'), 'property');
		$this->setMetaDataIfNotSet($document, 'twitter:title', $params->get('tw_title'), 'name');

		$this->setMetaDataIfNotSet($document, 'og:description', $params->get('og_description'), 'property');
		$this->setMetaDataIfNotSet($document, 'twitter:description', $params->get('tw_description'), 'name');

		$this->setMetaDataIfNotSet($document, 'article:author', $params->get('og_article_author'), 'property');
		$this->setMetaDataIfNotSet($document, 'twitter:creator', $params->get('tw_creator'), 'name');

		$this->setMetaDataIfNotSet(
			$document,
			'article:published_time',
			$params->get('og_article_published_time'),
			'property'
		);

		$this->setOpenGraphImage(
			$document,
			$params->get('og_image'),
			$params->get('og_image_alt'),
			$params->get('base_url')
		);

		$this->setProduct(
			$document,
			$params->get('og_type'),
			$params->get('og_product_price'),
			$params->get('og_product_currency'),
			$params->get('og_product_availability')
		);
	}
}