src/services/SitemapService.php
public function core (array $variables)
	{
		$this->_createDocument();
		$sitemapData = $this->getSitemap();
		$craft = \Craft::$app;

		if (!array_key_exists($variables['section'], $sitemapData))
			goto out;

		$sitemapSection = $sitemapData[$variables['section']];

		if (!array_key_exists($variables['id'], $sitemapSection))
			goto out;

		$sitemapSectionById = $sitemapSection[$variables['id']];

		if (!$sitemapSectionById['enabled'])
			goto out;

		/** @var Element|null $type */
		$type = null;
		$idHandle = null;

		switch ($variables['section'])
		{
			case 'sections':
				$type = Entry::instance();
				$idHandle = 'sectionId';
				break;

			case 'categories':
				$type = Category::instance();
				$idHandle = 'groupId';
				break;

			default:
				goto out;
		}

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

		$elements = $type::find();
		$elements->{$idHandle} = $variables['id'];
		$elements->siteId = \Craft::$app->sites->currentSite->id;
		$elements->limit = $settings->sitemapLimit;
		$elements->offset = $settings->sitemapLimit * $variables['page'];

		$currentLocale = $craft->locale->id;
		$availableLocales = $craft->i18n->getSiteLocaleIds();

		if (($key = array_search($currentLocale, $availableLocales)) !== false)
			unset($availableLocales[$key]);

		$seoFieldHandle = null;
		if ($first = $elements->one())
		{
			$fieldLayout =
				$variables['section'] === 'categories'
					? $first->fieldLayout
					: $first->type->fieldLayout;

			foreach ($fieldLayout->getFields() as $field)
				if (get_class($field) === SeoField::class)
					$seoFieldHandle = $field->handle;
		}

		foreach ($elements->all() as $item)
		{
			if ($item->url === null)
				continue;

			if ($seoFieldHandle !== null) {
				/** @var SeoData $seoField */
				$seoField = $item->$seoFieldHandle;
				if ($robots = $seoField->advanced['robots'])
					if (in_array('noindex', $robots))
						continue;
			}

			$url = $this->_document->createElement('url');
			$this->_urlSet->appendChild($url);

			$loc = $this->_document->createElement(
				'loc',
				$item->url
			);

			$mod = $this->_document->createElement(
				'lastmod',
				DateTimeHelper::toIso8601($item->dateUpdated)
			);

			$freq = $this->_document->createElement(
				'changefreq',
				$sitemapSectionById['frequency']
			);

			$priority = $this->_document->createElement(
				'priority',
				$sitemapSectionById['priority']
			);

			$url->appendChild($loc);
			$url->appendChild($mod);
			$url->appendChild($freq);
			$url->appendChild($priority);

			$enabledLookup =
				(new Query())->select(['siteId', 'uri'])
				             ->from('{{%elements_sites}}')
				             ->where('[[elementId]] = ' . $item->id)
				             ->andWhere('enabled = true')
				             ->all();

			$enabledLookup = array_reduce(
				$enabledLookup,
				function ($a, $b) {
					$uri = $b['uri'];
					$a[$b['siteId']] = $uri === '__home__' ? '' : $uri;
					return $a;
				},
				[]
			);

			foreach ($item->supportedSites as $siteId)
			{
				$id = is_numeric($siteId) ? $siteId : $siteId['siteId'];
				$site = $id ? $craft->sites->getSiteById($id) : \Craft::$app->sites->currentSite;
				$lang = $site->language;

				if (!in_array($lang, $availableLocales))
					continue;

				if (!array_key_exists($id, $enabledLookup))
					continue;

				$link = UrlHelper::siteUrl($enabledLookup[$id], null, null, $id);

				$alt = $this->_document->createElement('xhtml:link');
				$alt->setAttribute('rel', 'alternate');
				$alt->setAttribute(
					'hreflang',
					str_replace('_', '-', $lang)
				);
				$alt->setAttribute('href', $link);

				$url->appendChild($alt);
			}
		}

		out:
		return $this->_document->saveXML();
	}
public function core (array $variables)
	{
		$this->_createDocument();
		$sitemapData = $this->getSitemap();
		$craft = \Craft::$app;

		if (!array_key_exists($variables['section'], $sitemapData))
			goto out;

		$sitemapSection = $sitemapData[$variables['section']];

		if (!array_key_exists($variables['id'], $sitemapSection))
			goto out;

		$sitemapSectionById = $sitemapSection[$variables['id']];

		if (!$sitemapSectionById['enabled'])
			goto out;

		/** @var Element|null $type */
		$type = null;
		$idHandle = null;

		switch ($variables['section'])
		{
			case 'sections':
				$type = Entry::instance();
				$idHandle = 'sectionId';
				break;

			case 'categories':
				$type = Category::instance();
				$idHandle = 'groupId';
				break;

			default:
				goto out;
		}

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

		$elements = $type::find();
		$elements->{$idHandle} = $variables['id'];
		$elements->siteId = \Craft::$app->sites->currentSite->id;
		$elements->limit = $settings->sitemapLimit;
		$elements->offset = $settings->sitemapLimit * $variables['page'];

		$currentLocale = $craft->locale->id;
		$availableLocales = $craft->i18n->getSiteLocaleIds();

		if (($key = array_search($currentLocale, $availableLocales)) !== false)
			unset($availableLocales[$key]);

		$seoFieldHandle = null;
		if ($first = $elements->one())
		{
			$fieldLayout =
				$variables['section'] === 'categories'
					? $first->fieldLayout
					: $first->type->fieldLayout;

			foreach ($fieldLayout->getFields() as $field)
				if (get_class($field) === SeoField::class)
					$seoFieldHandle = $field->handle;
		}

		foreach ($elements->all() as $item)
		{
			if ($item->url === null)
				continue;

			if ($seoFieldHandle !== null) {
				/** @var SeoData $seoField */
				$seoField = $item->$seoFieldHandle;
				if ($robots = $seoField->advanced['robots'])
					if (in_array('noindex', $robots))
						continue;
			}

			$url = $this->_document->createElement('url');
			$this->_urlSet->appendChild($url);

			$loc = $this->_document->createElement(
				'loc',
				$item->url
			);

			$mod = $this->_document->createElement(
				'lastmod',
				DateTimeHelper::toIso8601($item->dateUpdated)
			);

			$freq = $this->_document->createElement(
				'changefreq',
				$sitemapSectionById['frequency']
			);

			$priority = $this->_document->createElement(
				'priority',
				$sitemapSectionById['priority']
			);

			$url->appendChild($loc);
			$url->appendChild($mod);
			$url->appendChild($freq);
			$url->appendChild($priority);

			$enabledLookup =
				(new Query())->select(['siteId', 'uri'])
				             ->from('{{%elements_sites}}')
				             ->where('[[elementId]] = ' . $item->id)
				             ->andWhere('enabled = true')
				             ->all();

			$enabledLookup = array_reduce(
				$enabledLookup,
				function ($a, $b) {
					$uri = $b['uri'];
					$a[$b['siteId']] = $uri === '__home__' ? '' : $uri;
					return $a;
				},
				[]
			);

			foreach ($item->supportedSites as $siteId)
			{
				$id = is_numeric($siteId) ? $siteId : $siteId['siteId'];
				$site = $id ? $craft->sites->getSiteById($id) : \Craft::$app->sites->currentSite;
				$lang = $site->language;

				if (!in_array($lang, $availableLocales))
					continue;

				if (!array_key_exists($id, $enabledLookup))
					continue;

				$link = UrlHelper::siteUrl($enabledLookup[$id], null, null, $id);

				$alt = $this->_document->createElement('xhtml:link');
				$alt->setAttribute('rel', 'alternate');
				$alt->setAttribute(
					'hreflang',
					str_replace('_', '-', $lang)
				);
				$alt->setAttribute('href', $link);

				$url->appendChild($alt);
			}
		}

		out:
		return $this->_document->saveXML();
	}
@param array $variables

@return string
@throws \yii\base\Exception