src/fields/SeoField.php
public function getInputHtml ($value, ElementInterface $element = null): string
	{
		if (!$element) return '';

		// Variables
		// ---------------------------------------------------------------------
		$craft = \Craft::$app;
		$namespaceId = $craft->view->namespaceInputId($this->id);

		$settings = $this->getSettings();
		$settingsGlobal = Seo::$i->getSettings();

		$hasPreview = false;
		$section = null;
		$isEntry = false;
		$isCalendar = false;
		$isHome = false;
		$isNew = $element->getId() === null;
		$isSingle = false;
		$previewAction = null;

		switch (get_class($element)) {
			case 'craft\\elements\\Entry':
				/** @var Entry $element */
				try {
					$isEntry = true;
					$section = $element->getSection();
				} catch (InvalidConfigException $e) {}
				$previewAction = $craft->getSecurity()->hashData(
					'entries/preview-entry'
				);
				break;
			case 'craft\\elements\\Category':
				$previewAction = $craft->getSecurity()->hashData(
					'categories/preview-category'
				);
				break;
			case 'craft\\commerce\\elements\\Product':
				$previewAction = $craft->getSecurity()->hashData(
					'commerce/products-preview/preview-product'
				);
				break;
			case 'Solspace\\Calendar\\Elements\\Event':
				/** @var $element \Solspace\Calendar\Elements\Event */
				$isCalendar = true;
				$previewAction = $craft->getSecurity()->hashData(
					'calendar/events/preview'
				);
				$hasPreview = \Solspace\Calendar\Calendar::getInstance()->calendars->isEventTemplateValid(
					$element->getCalendar(),
					$element->siteId
				);
				break;
			default:
				/** @var ElementInterface $element */
		}

		if ($section) {
			$hasPreview = $craft->sections->isSectionTemplateValid(
				$section,
				$element->siteId
			) && $previewAction !== null;

			$isSingle = $section->type === Section::TYPE_SINGLE;
		}

		// URL & Title Suffix
		// ---------------------------------------------------------------------

		$titleTemplate = $settings['title'] ?? $settingsGlobal['title'];

		$url = $element->getUrl();

		if ($hasPreview && $isEntry && !$isHome && !$isSingle)
			$url = substr($url, 0, strrpos( $url, '/')) . '/';

		if ($element->slug)
			$url = str_replace($element->slug, '', $url);

		// Social URL
		// ---------------------------------------------------------------------

		$socialPreviewUrl = null;

		if ($craft->sites->currentSite->baseUrl) {
			preg_match(
				"((http?s?:\/\/)?(www.)?(.*)\/)",
				\Craft::parseEnv($craft->sites->currentSite->baseUrl),
				$socialPreviewUrl
			);
			$socialPreviewUrl = $socialPreviewUrl[3];
		}

		// Advanced
		// ---------------------------------------------------------------------

		$defaultRobots = array_key_exists('robots', $settings)
			? $settings['robots']
			: [];

		// Render
		// ---------------------------------------------------------------------

		$hideSocial = array_key_exists('hideSocial', $settings)
			? $settings['hideSocial']
			: false;

		$renderData = [
			'elementType' => get_class($element),
			'elementId' => $element->id,
			'siteId' => $element->siteId,
			'seoHandle' => $this->handle,
		];

		if ($element instanceof Category)
			$renderData['groupId'] = $element->groupId;
		elseif ($isCalendar)
			$renderData['calendarId'] = $element->calendarId;
		else
			$renderData['typeId'] = $element->typeId;

		$seoOptions = Json::encode(compact(
			'hasPreview',
			'previewAction',
			'isNew',
			'renderData'
		));

		$craft->view->registerAssetBundle(SeoFieldAsset::class);
		$craft->view->registerJs(
			"new SeoField('{$namespaceId}', {$seoOptions})"
		);

		return $craft->view->renderTemplate(
			'seo/_seo/fieldtype',
			[
				'id' => $this->id,
				'name' => $this->handle,
				'value' => $value,
				'titleTemplate' => $titleTemplate,
				'hasPreview' => $hasPreview,
				'url' => $url,
				'isPro' => true,

				'isNew' => $isNew,
				'isHome' => $isHome,
				'isSingle' => $isSingle,

				'socialPreviewUrl' => $socialPreviewUrl,
				'hideSocial' => $hideSocial,

				'defaultRobots' => $defaultRobots,
			]
		);
	}
public function getInputHtml ($value, ElementInterface $element = null): string
	{
		if (!$element) return '';

		// Variables
		// ---------------------------------------------------------------------
		$craft = \Craft::$app;
		$namespaceId = $craft->view->namespaceInputId($this->id);

		$settings = $this->getSettings();
		$settingsGlobal = Seo::$i->getSettings();

		$hasPreview = false;
		$section = null;
		$isEntry = false;
		$isCalendar = false;
		$isHome = false;
		$isNew = $element->getId() === null;
		$isSingle = false;
		$previewAction = null;

		switch (get_class($element)) {
			case 'craft\\elements\\Entry':
				/** @var Entry $element */
				try {
					$isEntry = true;
					$section = $element->getSection();
				} catch (InvalidConfigException $e) {}
				$previewAction = $craft->getSecurity()->hashData(
					'entries/preview-entry'
				);
				break;
			case 'craft\\elements\\Category':
				$previewAction = $craft->getSecurity()->hashData(
					'categories/preview-category'
				);
				break;
			case 'craft\\commerce\\elements\\Product':
				$previewAction = $craft->getSecurity()->hashData(
					'commerce/products-preview/preview-product'
				);
				break;
			case 'Solspace\\Calendar\\Elements\\Event':
				/** @var $element \Solspace\Calendar\Elements\Event */
				$isCalendar = true;
				$previewAction = $craft->getSecurity()->hashData(
					'calendar/events/preview'
				);
				$hasPreview = \Solspace\Calendar\Calendar::getInstance()->calendars->isEventTemplateValid(
					$element->getCalendar(),
					$element->siteId
				);
				break;
			default:
				/** @var ElementInterface $element */
		}

		if ($section) {
			$hasPreview = $craft->sections->isSectionTemplateValid(
				$section,
				$element->siteId
			) && $previewAction !== null;

			$isSingle = $section->type === Section::TYPE_SINGLE;
		}

		// URL & Title Suffix
		// ---------------------------------------------------------------------

		$titleTemplate = $settings['title'] ?? $settingsGlobal['title'];

		$url = $element->getUrl();

		if ($hasPreview && $isEntry && !$isHome && !$isSingle)
			$url = substr($url, 0, strrpos( $url, '/')) . '/';

		if ($element->slug)
			$url = str_replace($element->slug, '', $url);

		// Social URL
		// ---------------------------------------------------------------------

		$socialPreviewUrl = null;

		if ($craft->sites->currentSite->baseUrl) {
			preg_match(
				"((http?s?:\/\/)?(www.)?(.*)\/)",
				\Craft::parseEnv($craft->sites->currentSite->baseUrl),
				$socialPreviewUrl
			);
			$socialPreviewUrl = $socialPreviewUrl[3];
		}

		// Advanced
		// ---------------------------------------------------------------------

		$defaultRobots = array_key_exists('robots', $settings)
			? $settings['robots']
			: [];

		// Render
		// ---------------------------------------------------------------------

		$hideSocial = array_key_exists('hideSocial', $settings)
			? $settings['hideSocial']
			: false;

		$renderData = [
			'elementType' => get_class($element),
			'elementId' => $element->id,
			'siteId' => $element->siteId,
			'seoHandle' => $this->handle,
		];

		if ($element instanceof Category)
			$renderData['groupId'] = $element->groupId;
		elseif ($isCalendar)
			$renderData['calendarId'] = $element->calendarId;
		else
			$renderData['typeId'] = $element->typeId;

		$seoOptions = Json::encode(compact(
			'hasPreview',
			'previewAction',
			'isNew',
			'renderData'
		));

		$craft->view->registerAssetBundle(SeoFieldAsset::class);
		$craft->view->registerJs(
			"new SeoField('{$namespaceId}', {$seoOptions})"
		);

		return $craft->view->renderTemplate(
			'seo/_seo/fieldtype',
			[
				'id' => $this->id,
				'name' => $this->handle,
				'value' => $value,
				'titleTemplate' => $titleTemplate,
				'hasPreview' => $hasPreview,
				'url' => $url,
				'isPro' => true,

				'isNew' => $isNew,
				'isHome' => $isHome,
				'isSingle' => $isSingle,

				'socialPreviewUrl' => $socialPreviewUrl,
				'hideSocial' => $hideSocial,

				'defaultRobots' => $defaultRobots,
			]
		);
	}
@param SeoData               $value
@param ElementInterface|null $element

@return string
@throws InvalidConfigException
@throws \Twig_Error_Loader
@throws \yii\base\Exception