Your IP : 18.118.82.92


Current Path : /var/www/admin_ftp_12/data/www/httpdocs/bitrix/modules/landing/lib/assets/preprocessing/
Upload File :
Current File : /var/www/admin_ftp_12/data/www/httpdocs/bitrix/modules/landing/lib/assets/preprocessing/icon.php

<?php
namespace Bitrix\Landing\Assets\PreProcessing;

use \Bitrix\Landing\Block;
use \Bitrix\Landing\Node;
use \Bitrix\Landing\Config;
use \Bitrix\Landing\Manager;
use \Bitrix\Landing\Assets;
use \Bitrix\Landing\Internals\BlockTable;
use \Bitrix\Main\IO\File;

class Icon
{
	/**
	 * File name with icon content.
	 */
	const CONTENT_ICON_FILE_NAME = 'content.css';

	/**
	 * File name with icon css rules.
	 */
	const RULE_ICON_FILE_NAME = 'style.css';

	/**
	 * File names of two types of fonts
	 */
	const ICON_FONT_FILE_NAME = 'font.woff';
	const ICON_FONT_FILE_NAME_2 = 'font.woff2';

	protected const VENDOR_UPDATES = [
		'fa' => 'far',
	];
	protected const ICON_UPDATES = [
		'fa' => [
			'fa-500px' => ['vendor' => 'fab'],
			'fa-adn' => ['vendor' => 'fab'],
			'fa-amazon' => ['vendor' => 'fab'],
			'fa-android' => ['vendor' => 'fab'],
			'fa-angellist' => ['vendor' => 'fab'],
			'fa-apple' => ['vendor' => 'fab'],
			'fa-bandcamp' => ['vendor' => 'fab'],
			'fa-behance' => ['vendor' => 'fab'],
			'fa-behance-square' => ['vendor' => 'fab'],
			'fa-bitbucket' => ['vendor' => 'fab'],
			'fa-bitbucket-square' => [
				'vendor' => 'fab',
				'content' => '\\f171',
			],
			'fa-bitcoin' => [
				'vendor' => 'fab',
				'content' => '\\f379',
			],
			'fa-black-tie' => ['vendor' => 'fab'],
			'fa-bluetooth' => ['vendor' => 'fab'],
			'fa-bluetooth-b' => ['vendor' => 'fab'],
			'fa-btc' => ['vendor' => 'fab'],
			'fa-buysellads' => ['vendor' => 'fab'],
			'fa-cc-amex' => ['vendor' => 'fab'],
			'fa-cc-diners-club' => ['vendor' => 'fab'],
			'fa-cc-discover' => ['vendor' => 'fab'],
			'fa-cc-jcb' => ['vendor' => 'fab'],
			'fa-cc-mastercard' => ['vendor' => 'fab'],
			'fa-cc-paypal' => ['vendor' => 'fab'],
			'fa-cc-stripe' => ['vendor' => 'fab'],
			'fa-cc-visa' => ['vendor' => 'fab'],
			'fa-chrome' => ['vendor' => 'fab'],
			'fa-codepen' => ['vendor' => 'fab'],
			'fa-codiepie' => ['vendor' => 'fab'],
			'fa-connectdevelop' => ['vendor' => 'fab'],
			'fa-contao' => ['vendor' => 'fab'],
			'fa-creative-commons' => ['vendor' => 'fab'],
			'fa-css3' => ['vendor' => 'fab'],
			'fa-dashcube' => ['vendor' => 'fab'],
			'fa-delicious' => ['vendor' => 'fab'],
			'fa-deviantart' => ['vendor' => 'fab'],
			'fa-digg' => ['vendor' => 'fab'],
			'fa-dribbble' => ['vendor' => 'fab'],
			'fa-dropbox' => ['vendor' => 'fab'],
			'fa-drupal' => ['vendor' => 'fab'],
			'fa-edge' => ['vendor' => 'fab'],
			'fa-eercast' => [
				'vendor' => 'fab',
				'content' => '\\f2da',
			],
			'fa-empire' => ['vendor' => 'fab'],
			'fa-envira' => ['vendor' => 'fab'],
			'fa-etsy' => ['vendor' => 'fab'],
			'fa-expeditedssl' => ['vendor' => 'fab'],
			'fa-fa' => [
				'vendor' => 'fab',
				'content' => '\\f2b4',
			],
			'fa-facebook' => ['vendor' => 'fab'],
			'fa-facebook-f' => [
				'vendor' => 'fab',
				'content' => '\\f39e',
			],
			'fa-facebook-official' => [
				'vendor' => 'fab',
				'content' => '\\f09a',
			],
			'fa-facebook-square' => ['vendor' => 'fab'],
			'fa-firefox' => ['vendor' => 'fab'],
			'fa-first-order' => ['vendor' => 'fab'],
			'fa-flickr' => ['vendor' => 'fab'],
			'fa-font-awesome' => ['vendor' => 'fab'],
			'fa-fonticons' => ['vendor' => 'fab'],
			'fa-fort-awesome' => ['vendor' => 'fab'],
			'fa-forumbee' => ['vendor' => 'fab'],
			'fa-foursquare' => ['vendor' => 'fab'],
			'fa-free-code-camp' => ['vendor' => 'fab'],
			'fa-ge' => [
				'vendor' => 'fab',
				'content' => '\\f1d1',
			],
			'fa-get-pocket' => ['vendor' => 'fab'],
			'fa-gg' => ['vendor' => 'fab'],
			'fa-gg-circle' => ['vendor' => 'fab'],
			'fa-git' => ['vendor' => 'fab'],
			'fa-git-square' => ['vendor' => 'fab'],
			'fa-github' => ['vendor' => 'fab'],
			'fa-github-alt' => ['vendor' => 'fab'],
			'fa-github-square' => ['vendor' => 'fab'],
			'fa-gitlab' => ['vendor' => 'fab'],
			'fa-gittip' => [
				'vendor' => 'fab',
				'content' => '\\f184',
			],
			'fa-glide' => ['vendor' => 'fab'],
			'fa-glide-g' => ['vendor' => 'fab'],
			'fa-google' => ['vendor' => 'fab'],
			'fa-google-plus' => [
				'vendor' => 'fab',
				'content' => '\\f2b3',
			],
			'fa-google-plus-circle' => [
				'vendor' => 'fab',
				'content' => '\\f2b3',
			],
			'fa-google-plus-official' => [
				'vendor' => 'fab',
				'content' => '\\f2b3',
			],
			'fa-google-plus-square' => ['vendor' => 'fab'],
			'fa-google-wallet' => ['vendor' => 'fab'],
			'fa-gratipay' => ['vendor' => 'fab'],
			'fa-grav' => ['vendor' => 'fab'],
			'fa-hacker-news' => ['vendor' => 'fab'],
			'fa-houzz' => ['vendor' => 'fab'],
			'fa-html5' => ['vendor' => 'fab'],
			'fa-imdb' => ['vendor' => 'fab'],
			'fa-instagram' => ['vendor' => 'fab'],
			'fa-internet-explorer' => ['vendor' => 'fab'],
			'fa-ioxhost' => ['vendor' => 'fab'],
			'fa-joomla' => ['vendor' => 'fab'],
			'fa-jsfiddle' => ['vendor' => 'fab'],
			'fa-lastfm' => ['vendor' => 'fab'],
			'fa-lastfm-square' => ['vendor' => 'fab'],
			'fa-leanpub' => ['vendor' => 'fab'],
			'fa-linkedin' => [
				'vendor' => 'fab',
				'content' => '\\f08c',
			],
			'fa-linkedin-square' => [
				'vendor' => 'fab',
				'content' => '\\f08c',
			],
			'fa-linode' => ['vendor' => 'fab'],
			'fa-linux' => ['vendor' => 'fab'],
			'fa-maxcdn' => ['vendor' => 'fab'],
			'fa-meanpath' => [
				'vendor' => 'fab',
				'content' => '\\f2b4',
			],
			'fa-medium' => ['vendor' => 'fab'],
			'fa-meetup' => ['vendor' => 'fab'],
			'fa-mixcloud' => ['vendor' => 'fab'],
			'fa-modx' => ['vendor' => 'fab'],
			'fa-odnoklassniki' => ['vendor' => 'fab'],
			'fa-odnoklassniki-square' => ['vendor' => 'fab'],
			'fa-opencart' => ['vendor' => 'fab'],
			'fa-openid' => ['vendor' => 'fab'],
			'fa-opera' => ['vendor' => 'fab'],
			'fa-optin-monster' => ['vendor' => 'fab'],
			'fa-pagelines' => ['vendor' => 'fab'],
			'fa-paypal' => ['vendor' => 'fab'],
			'fa-pied-piper' => ['vendor' => 'fab'],
			'fa-pied-piper-alt' => ['vendor' => 'fab'],
			'fa-pied-piper-pp' => ['vendor' => 'fab'],
			'fa-pinterest' => ['vendor' => 'fab'],
			'fa-pinterest-p' => ['vendor' => 'fab'],
			'fa-pinterest-square' => ['vendor' => 'fab'],
			'fa-product-hunt' => ['vendor' => 'fab'],
			'fa-qq' => ['vendor' => 'fab'],
			'fa-quora' => ['vendor' => 'fab'],
			'fa-ra' => [
				'vendor' => 'fab',
				'content' => '\\f1d0',
			],
			'fa-ravelry' => ['vendor' => 'fab'],
			'fa-rebel' => ['vendor' => 'fab'],
			'fa-reddit' => ['vendor' => 'fab'],
			'fa-reddit-alien' => ['vendor' => 'fab'],
			'fa-reddit-square' => ['vendor' => 'fab'],
			'fa-renren' => ['vendor' => 'fab'],
			'fa-resistance' => [
				'vendor' => 'fab',
				'content' => '\\f1d0',
			],
			'fa-safari' => ['vendor' => 'fab'],
			'fa-scribd' => ['vendor' => 'fab'],
			'fa-sellsy' => ['vendor' => 'fab'],
			'fa-shirtsinbulk' => ['vendor' => 'fab'],
			'fa-simplybuilt' => ['vendor' => 'fab'],
			'fa-skyatlas' => ['vendor' => 'fab'],
			'fa-skype' => ['vendor' => 'fab'],
			'fa-slack' => ['vendor' => 'fab'],
			'fa-slideshare' => ['vendor' => 'fab'],
			'fa-snapchat' => ['vendor' => 'fab'],
			'fa-snapchat-ghost' => [
				'vendor' => 'fab',
				'content' => '\\f2ab',
			],
			'fa-snapchat-square' => ['vendor' => 'fab'],
			'fa-soundcloud' => ['vendor' => 'fab'],
			'fa-spotify' => ['vendor' => 'fab'],
			'fa-stack-exchange' => ['vendor' => 'fab'],
			'fa-stack-overflow' => ['vendor' => 'fab'],
			'fa-steam' => ['vendor' => 'fab'],
			'fa-steam-square' => ['vendor' => 'fab'],
			'fa-stumbleupon' => ['vendor' => 'fab'],
			'fa-stumbleupon-circle' => ['vendor' => 'fab'],
			'fa-superpowers' => ['vendor' => 'fab'],
			'fa-telegram' => ['vendor' => 'fab'],
			'fa-tencent-weibo' => ['vendor' => 'fab'],
			'fa-themeisle' => ['vendor' => 'fab'],
			'fa-trello' => ['vendor' => 'fab'],
			'fa-tumblr' => ['vendor' => 'fab'],
			'fa-tumblr-square' => ['vendor' => 'fab'],
			'fa-twitch' => ['vendor' => 'fab'],
			'fa-twitter' => ['vendor' => 'fab'],
			'fa-twitter-square' => ['vendor' => 'fab'],
			'fa-usb' => ['vendor' => 'fab'],
			'fa-viacoin' => ['vendor' => 'fab'],
			'fa-viadeo' => ['vendor' => 'fab'],
			'fa-viadeo-square' => ['vendor' => 'fab'],
			'fa-vimeo' => [
				'vendor' => 'fab',
				'content' => '\\f40a',
			],
			'fa-vimeo-square' => ['vendor' => 'fab'],
			'fa-vine' => ['vendor' => 'fab'],
			'fa-vk' => ['vendor' => 'fab'],
			'fa-wechat' => [
				'vendor' => 'fab',
				'content' => '\\f1d7',
			],
			'fa-weibo' => ['vendor' => 'fab'],
			'fa-weixin' => ['vendor' => 'fab'],
			'fa-whatsapp' => ['vendor' => 'fab'],
			'fa-wikipedia-w' => ['vendor' => 'fab'],
			'fa-windows' => ['vendor' => 'fab'],
			'fa-wordpress' => ['vendor' => 'fab'],
			'fa-wpbeginner' => ['vendor' => 'fab'],
			'fa-wpexplorer' => ['vendor' => 'fab'],
			'fa-wpforms' => ['vendor' => 'fab'],
			'fa-xing' => ['vendor' => 'fab'],
			'fa-xing-square' => ['vendor' => 'fab'],
			'fa-y-combinator' => ['vendor' => 'fab'],
			'fa-y-combinator-square' => [
				'vendor' => 'fab',
				'content' => '\\f1d4',
			],
			'fa-yahoo' => ['vendor' => 'fab'],
			'fa-yc' => [
				'vendor' => 'fab',
				'content' => '\\f1d4',
			],
			'fa-yc-square' => [
				'vendor' => 'fab',
				'content' => '\\f1d4',
			],
			'fa-yelp' => ['vendor' => 'fab'],
			'fa-yoast' => ['vendor' => 'fab'],
			'fa-youtube' => ['vendor' => 'fab'],
			'fa-youtube-play' => [
				'vendor' => 'fab',
				'content' => '\\f167',
			],
			'fa-youtube-square' => [
				'vendor' => 'fab',
				'content' => '\\f431',
			],

			'fa-plus' => ['content' => '\2b'],
			'fa-usd' => ['content' => '\24'],
			'fa-dollar' => ['content' => '\24'],
			'fa-rupee' => ['content' => '\e1bc'],
			'fa-inr' => ['content' => '\e1bc'],
			'fa-wheelchair-alt' => ['content' => '\\e2ce',],
		],
	];

	/**
	 * Tries to resolve and returns icon file path.
	 * @param string $vendorName Vendor folder code.
	 * @return string|null
	 */
	protected static function getIconsPath(string $vendorName): ?string
	{
		$iconSrc = Config::get('icon_src');
		$iconSrc = Manager::getDocRoot() . $iconSrc . $vendorName;
		if (is_dir($iconSrc))
		{
			return $iconSrc;
		}

		return null;
	}

	/**
	 * Parses icon file and returns content for each icon class.
	 * @param string $vendorName Vendor folder code.
	 * @return array
	 */
	protected static function getIconsContentByVendor(string $vendorName): array
	{
		static $vendorContent = [];

		if (!array_key_exists($vendorName, $vendorContent))
		{
			$vendorContent[$vendorName] = [];
			$path = self::getIconsPath($vendorName);
			if ($path)
			{
				$cssFileName = $path . '/' . self::CONTENT_ICON_FILE_NAME;
				if (File::isFileExists($cssFileName))
				{
					$cssContent = File::getFileContents($cssFileName);
					if ($cssContent)
					{
						$classPrefix = $vendorName;
						$iconVendorsConfig = Config::get('icon_vendors_config');
						if ($iconVendorsConfig && isset ($iconVendorsConfig[$vendorName]['class_prefix']))
						{
							$classPrefix = $iconVendorsConfig[$vendorName]['class_prefix'];
						}
						$found = preg_match_all(
							'/\.(' . $classPrefix . '-[^:]+):{1,2}before\s*{\s*content:\s*["\']((?:\\\\.|[^\\\\])*?)["\'];\s*}/',
							$cssContent,
							$matches
						);
						if ($found)
						{
							foreach ($matches[1] as $i => $match)
							{
								$vendorContent[$vendorName][$match] = $matches[2][$i];
							}
						}
					}
				}
			}
		}

		return $vendorContent[$vendorName];
	}

	/**
	 * Returns icon css content.
	 * @param string $className Class name.
	 * @param string $vendorName Vendor folder code.
	 * @return string|null
	 */
	protected static function getIconContentByClass(string $className, string $vendorName): ?string
	{
		$contentAll = self::getIconsContentByVendor($vendorName);

		return $contentAll[$className] ?? null;
	}

	/**
	 * Tries to find any icons and save them assets to the block.
	 * @param Block $block Bock instance.
	 * @return void
	 */
	protected static function saveAssets(Block $block): void
	{
		$iconSrc = Config::get('icon_src');
		$iconVendors = Config::get('icon_vendors');
		$blockContent = $block->getContent();

		if (!$iconSrc || !$iconVendors || !$blockContent)
		{
			return;
		}

		$assetsIcon = [];
		$iconVendors = (array)$iconVendors;
		$vendorsStr = '(' . implode('|', $iconVendors) . ')';
		$prefixesStr = $vendorsStr;
		// special vendors
		$iconVendorsConfig = Config::get('icon_vendors_config');
		if ($iconVendorsConfig && !empty($iconVendorsConfig))
		{
			$classPrefixes = $iconVendors;
			foreach ($iconVendorsConfig as $vendor => $config)
			{
				$classPrefixes[array_search($vendor, $classPrefixes, true)] = $config['class_prefix'];
			}
			$prefixesStr = '(' . implode('|', array_unique($classPrefixes)) . ')';
		}
		$found = preg_match_all(
			'/(?<=[\s"])' . $vendorsStr . '?\s*(' . $prefixesStr . '-([^\s"\/\\\]+))/s',
			$blockContent,
			$matches
		);
		if ($found)
		{
			foreach ($matches[0] as $i => $full)
			{
				$vendor = $matches[1][$i]
					? trim($matches[1][$i])
					: trim($matches[3][$i]);
				$class = trim($matches[2][$i]);
				[$vendor, $class] = self::updateIconsBeforeSave($vendor, $class);
				if (!isset($assetsIcon[$vendor]))
				{
					$assetsIcon[$vendor] = [];
				}
				$assetsIcon[$vendor][$class] = self::getIconContentByClass(
					$class,
					$vendor
				);
				if ($assetsIcon[$vendor][$class] === null)
				{
					unset($assetsIcon[$vendor][$class]);
				}
				if (!$assetsIcon[$vendor])
				{
					unset($assetsIcon[$vendor]);
				}
			}
		}

		$block->saveAssets([
			'icon' => $assetsIcon
		]);
	}

	/**
	 * Processing icons in the block content.
	 * @param Block $block Block instance.
	 * @return void
	 */
	public static function processing(Block $block): void
	{
		// find assets always, because block can use icon not only as icon-node, but also just in html
		self::saveAssets($block);
	}

	/**
	 * Processing entire landing.
	 * @param int $landingId Landing id.
	 * @return void
	 */
	public static function processingLanding(int $landingId): void
	{
		$res = BlockTable::getList([
			'select' => [
				'ID'
			],
			'filter' => [
				'LID' => $landingId,
				'=DELETED' => 'N'
			]
		]);
		while ($row = $res->fetch())
		{
			$block = new Block($row['ID']);
			self::processing($block);
			$block->save();
		}
	}

	/**
	 * Shows icons styles on the block output.
	 * @param Block $block Block instance.
	 * @return void
	 */
	public static function view(Block $block): void
	{
		$blockAssets = $block->getAssets();
		if (isset($blockAssets['icon']) && !empty($blockAssets['icon']))
		{
			$assetsManager = Assets\Manager::getInstance();
			$iconSrc = Config::get('icon_src');
			if (!$iconSrc)
			{
				return;
			}
			$stylesString = '<style>';
			$blockAssets['icon'] = self::updateIconsBeforeView($blockAssets['icon']);
			foreach ($blockAssets['icon'] as $vendorName => $icons)
			{
				$fontFile = $iconSrc . $vendorName . '/' . self::ICON_FONT_FILE_NAME;
				$assetsManager->addAsset($fontFile);
				$fontFile2 = $iconSrc . $vendorName . '/' . self::ICON_FONT_FILE_NAME_2;
				$assetsManager->addAsset($fontFile2);

				$stylesFile = $iconSrc . $vendorName . '/' . self::RULE_ICON_FILE_NAME;
				$assetsManager->addAsset($stylesFile);

				foreach ($icons as $className => $content)
				{
					$stylesString .= '.' . $className . ':before{content:"' . $content . '";}';
				}
			}
			$stylesString .= '</style>';
			$assetsManager->addString($stylesString);
		}
	}

	protected static function updateIconsBeforeView($iconData): array
	{
		$newIcons = $iconData;

		foreach ($iconData as $vendor => $icons)
		{
			if (!isset(self::VENDOR_UPDATES[$vendor]))
			{
				continue;
			}

			$newVendor = self::VENDOR_UPDATES[$vendor];

			foreach ($icons as $icon => $content)
			{
				if (isset(self::ICON_UPDATES[$vendor]))
				{
					$currVendor = self::ICON_UPDATES[$vendor][$icon]['vendor'] ?? $newVendor;
					$newContent = self::ICON_UPDATES[$vendor][$icon]['content'] ?? $content;
					$newIcons[$currVendor][$icon] = $newContent;

					unset($newIcons[$vendor][$icon]);
					if (empty($newIcons[$vendor]))
					{
						unset($newIcons[$vendor]);
					}
				}
			}
		}

		return $newIcons;
	}

	protected static function updateIconsBeforeSave(string $vendor, string $class): array
	{
		$newVendor = self::VENDOR_UPDATES[$vendor] ?? $vendor;
		$newClass = $class;
		if (isset(self::ICON_UPDATES[$vendor]))
		{
			$newVendor = self::ICON_UPDATES[$vendor][$class]['vendor'] ?? $newVendor;
		}

		return [$newVendor, $newClass];
	}
}