Skip to content

Commit

Permalink
Added the ability to add additional sitemaps that exist out of the CM…
Browse files Browse the repository at this point in the history
…S into the `sitemap.xml` via Site Settings -> Sitemap as well as via plugin

Signed-off-by: Andrew Welch <andrew@nystudio107.com>
  • Loading branch information
khalwat committed Dec 10, 2018
1 parent 7b21206 commit 4ecdc2a
Show file tree
Hide file tree
Showing 11 changed files with 333 additions and 106 deletions.
3 changes: 3 additions & 0 deletions src/Seomatic.php
Original file line number Diff line number Diff line change
Expand Up @@ -978,6 +978,9 @@ protected function customAdminCpPermissions(): array
'seomatic:site-settings:social' => [
'label' => Craft::t('seomatic', 'Social Media'),
],
'seomatic:site-settings:sitemap' => [
'label' => Craft::t('seomatic', 'Sitemap'),
],
'seomatic:site-settings:miscellaneous' => [
'label' => Craft::t('seomatic', 'Miscellaneous'),
],
Expand Down
2 changes: 1 addition & 1 deletion src/events/RegisterSitemapUrlsEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class RegisterSitemapUrlsEvent extends Event
/**
* @var array The registered sitemap URLs.
*/
public $sitemapUrls = [];
public $sitemaps = [];

/**
* @var int The site id
Expand Down
35 changes: 35 additions & 0 deletions src/events/RegisterSitemapsEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php
/**
* SEOmatic plugin for Craft CMS 3.x
*
* A turnkey SEO implementation for Craft CMS that is comprehensive, powerful,
* and flexible
*
* @link https://nystudio107.com
* @copyright Copyright (c) 2017 nystudio107
*/

namespace nystudio107\seomatic\events;

use yii\base\Event;

/**
* @author nystudio107
* @package Seomatic
* @since 3.1.0
*/
class RegisterSitemapsEvent extends Event
{
// Properties
// =========================================================================

/**
* @var array The registered sitemaps.
*/
public $sitemaps = [];

/**
* @var int The site id
*/
public $siteId;
}
20 changes: 19 additions & 1 deletion src/models/MetaSiteVars.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace nystudio107\seomatic\models;

use craft\helpers\DateTimeHelper;
use nystudio107\seomatic\base\VarsModel;
use nystudio107\seomatic\helpers\Json as JsonHelper;

Expand Down Expand Up @@ -109,7 +110,7 @@ public static function create(array $config = [])
public $siteLinksQueryInput = '';

/**
* @var array Array of additional sitemap URLs
* @var array Array of additional custom sitemap URLs
*/
public $additionalSitemapUrls = [];

Expand All @@ -118,6 +119,11 @@ public static function create(array $config = [])
*/
public $additionalSitemapUrlsDateUpdated;

/**
* @var array Array of additional sitemaps
*/
public $additionalSitemaps = [];

// Public Methods
// =========================================================================

Expand Down Expand Up @@ -173,6 +179,7 @@ public function rules(): array
[
'sameAsLinks',
'additionalSitemapUrls',
'additionalSitemaps',
],
ArrayValidator::class,
],
Expand Down Expand Up @@ -205,6 +212,17 @@ public function normalizeData()
$this->$property = JsonHelper::decodeIfJson($value);
}
}
// Convert our date attributes in the additionalSitemaps array
if (!empty($this->additionalSitemaps)) {
$index = 0;
foreach ($this->additionalSitemaps as $additionalSitemap) {
if (!empty($additionalSitemap['lastmod'])) {
$this->additionalSitemaps[$index]['lastmod']
= DateTimeHelper::toDateTime($additionalSitemap['lastmod']);
}
$index++;
}
}
// Make sure these are strings
if (!empty($this->facebookProfileId)) {
$this->facebookProfileId = (string)$this->facebookProfileId;
Expand Down
4 changes: 2 additions & 2 deletions src/models/SitemapCustomTemplate.php
Original file line number Diff line number Diff line change
Expand Up @@ -156,11 +156,11 @@ public function render(array $params = []): string
$additionalSitemapUrls = empty($additionalSitemapUrls) ? [] : $additionalSitemapUrls;
// Allow plugins/modules to add custom URLs
$event = new RegisterSitemapUrlsEvent([
'sitemapUrls' => $additionalSitemapUrls,
'sitemaps' => $additionalSitemapUrls,
'siteId' => $metaBundle->sourceSiteId,
]);
$this->trigger(self::EVENT_REGISTER_SITEMAP_URLS, $event);
$additionalSitemapUrls = array_filter($event->sitemapUrls);
$additionalSitemapUrls = array_filter($event->sitemaps);
// Output the sitemap entry
foreach ($additionalSitemapUrls as $additionalSitemapUrl) {
$url = UrlHelper::siteUrl(
Expand Down
156 changes: 119 additions & 37 deletions src/models/SitemapIndexTemplate.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use nystudio107\seomatic\base\FrontendTemplate;
use nystudio107\seomatic\base\SitemapInterface;
use nystudio107\seomatic\events\RegisterSitemapUrlsEvent;
use nystudio107\seomatic\events\RegisterSitemapsEvent;
use nystudio107\seomatic\models\SitemapCustomTemplate;

use Craft;
Expand All @@ -35,6 +36,25 @@ class SitemapIndexTemplate extends FrontendTemplate implements SitemapInterface
// Constants
// =========================================================================

/**
* @event RegisterSitemapsEvent The event that is triggered when registering
* additional sitemaps for the sitemap index.
*
* ---
* ```php
* use nystudio107\seomatic\events\RegisterSitemapsEvent;
* use nystudio107\seomatic\models\SitemapIndexTemplate;
* use yii\base\Event;
* Event::on(SitemapIndexTemplate::class, SitemapIndexTemplate::EVENT_REGISTER_SITEMAPS, function(RegisterSitemapsEvent $e) {
* $e->sitemaps[] = [
* 'loc' => $url,
* 'lastmod' => $lastMod,
* ];
* });
* ```
*/
const EVENT_REGISTER_SITEMAPS = 'registerSitemaps';

const TEMPLATE_TYPE = 'SitemapIndexTemplate';

const CACHE_KEY = 'seomatic_sitemap_index';
Expand All @@ -52,10 +72,10 @@ class SitemapIndexTemplate extends FrontendTemplate implements SitemapInterface
public static function create(array $config = [])
{
$defaults = [
'path' => 'sitemaps/<groupId:\d+>/sitemap.xml',
'template' => '',
'path' => 'sitemaps/<groupId:\d+>/sitemap.xml',
'template' => '',
'controller' => 'sitemap',
'action' => 'sitemap-index',
'action' => 'sitemap-index',
];
$config = array_merge($config, $defaults);

Expand Down Expand Up @@ -154,40 +174,8 @@ public function render(array $params = []): string
foreach ($groupSiteIds as $groupSiteId) {
$metaBundle = Seomatic::$plugin->metaBundles->getGlobalMetaBundle($groupSiteId, false);
if ($metaBundle !== null) {
$additionalSitemapUrls = $metaBundle->metaSiteVars->additionalSitemapUrls;
$additionalSitemapUrls = empty($additionalSitemapUrls) ? [] : $additionalSitemapUrls;
// Allow plugins/modules to add custom URLs
$event = new RegisterSitemapUrlsEvent([
'sitemapUrls' => $additionalSitemapUrls,
'siteId' => $groupSiteId,
]);
Event::trigger(SitemapCustomTemplate::class, SitemapCustomTemplate::EVENT_REGISTER_SITEMAP_URLS, $event);
$additionalSitemapUrls = array_filter($event->sitemapUrls);
// Output the sitemap index
if (!empty($additionalSitemapUrls)) {
$sitemapUrl = Seomatic::$plugin->sitemaps->sitemapCustomUrlForSiteId(
$groupSiteId
);
$lines[] = ' <sitemap>';
$lines[] = ' <loc>';
$lines[] = ' '.Html::encode($sitemapUrl);
$lines[] = ' </loc>';
// Find the most recent date
$dateUpdated = $metaBundle->metaSiteVars->additionalSitemapUrlsDateUpdated
?? new \DateTime;
foreach ($additionalSitemapUrls as $additionalSitemapUrl) {
if (!empty($additionalSitemapUrl['lastmod']) && $additionalSitemapUrl['lastmod'] > $dateUpdated) {
$dateUpdated = $additionalSitemapUrl['lastmod'];
}
}
$dateUpdated = $metaBundle->metaSiteVars->additionalSitemapUrlsDateUpdated;
if ($dateUpdated !== null) {
$lines[] = ' <lastmod>';
$lines[] = ' '.$dateUpdated->format(\DateTime::W3C);
$lines[] = ' </lastmod>';
}
$lines[] = ' </sitemap>';
}
$this->addAdditionalSitemapUrls($metaBundle, $groupSiteId, $lines);
$this->addAdditionalSitemaps($metaBundle, $groupSiteId, $lines);
}
}
// Sitemap index closing tag
Expand All @@ -209,4 +197,98 @@ public function invalidateCache()
__METHOD__
);
}

// Protected Methods
// =========================================================================

/**
* Add an additional sitemaps to the sitemap index, coming from the global
* meta bundle metaSiteVars->additionalSitemaps
*
* @param MetaBundle $metaBundle
* @param int $groupSiteId
* @param array $lines
*
* @throws \Exception
*/
protected function addAdditionalSitemaps(MetaBundle $metaBundle, int $groupSiteId, array &$lines)
{
$additionalSitemaps = $metaBundle->metaSiteVars->additionalSitemaps;
$additionalSitemaps = empty($additionalSitemaps) ? [] : $additionalSitemaps;
// Allow plugins/modules to add custom URLs
$event = new RegisterSitemapsEvent([
'sitemaps' => $additionalSitemaps,
'siteId' => $groupSiteId,
]);
Event::trigger(SitemapCustomTemplate::class, SitemapCustomTemplate::EVENT_REGISTER_SITEMAP_URLS, $event);
$additionalSitemaps = array_filter($event->sitemaps);
// Output the sitemap index
if (!empty($additionalSitemaps)) {
foreach ($additionalSitemaps as $additionalSitemap) {
if (!empty($additionalSitemap['loc'])) {
$lines[] = ' <sitemap>';
$lines[] = ' <loc>';
$lines[] = ' '.Html::encode($additionalSitemap['loc']);
$lines[] = ' </loc>';
// Find the most recent date
$dateUpdated = !empty($additionalSitemap['lastmod'])
? $additionalSitemap['lastmod']
: new \DateTime;
$lines[] = ' <lastmod>';
$lines[] = ' '.$dateUpdated->format(\DateTime::W3C);
$lines[] = ' </lastmod>';
$lines[] = ' </sitemap>';
}
}
}
}

/**
* Add an additional "custom" sitemap to the sitemap index, with URLs coming from
* the global meta bundle metaSiteVars->additionalSitemapUrls
*
* @param MetaBundle $metaBundle
* @param int $groupSiteId
* @param array $lines
*
* @throws \Exception
*/
protected function addAdditionalSitemapUrls(MetaBundle $metaBundle, int $groupSiteId, array &$lines)
{
$additionalSitemapUrls = $metaBundle->metaSiteVars->additionalSitemapUrls;
$additionalSitemapUrls = empty($additionalSitemapUrls) ? [] : $additionalSitemapUrls;
// Allow plugins/modules to add custom URLs
$event = new RegisterSitemapUrlsEvent([
'sitemaps' => $additionalSitemapUrls,
'siteId' => $groupSiteId,
]);
Event::trigger(SitemapCustomTemplate::class, SitemapCustomTemplate::EVENT_REGISTER_SITEMAP_URLS, $event);
$additionalSitemapUrls = array_filter($event->sitemaps);
// Output the sitemap index
if (!empty($additionalSitemapUrls)) {
$sitemapUrl = Seomatic::$plugin->sitemaps->sitemapCustomUrlForSiteId(
$groupSiteId
);
$lines[] = ' <sitemap>';
$lines[] = ' <loc>';
$lines[] = ' '.Html::encode($sitemapUrl);
$lines[] = ' </loc>';
// Find the most recent date
$dateUpdated = $metaBundle->metaSiteVars->additionalSitemapUrlsDateUpdated
?? new \DateTime;
foreach ($additionalSitemapUrls as $additionalSitemapUrl) {
if (!empty($additionalSitemapUrl['lastmod'])) {
if ($additionalSitemapUrl['lastmod'] > $dateUpdated) {
$dateUpdated = $additionalSitemapUrl['lastmod'];
}
}
}
if ($dateUpdated !== null) {
$lines[] = ' <lastmod>';
$lines[] = ' '.$dateUpdated->format(\DateTime::W3C);
$lines[] = ' </lastmod>';
}
$lines[] = ' </sitemap>';
}
}
}
2 changes: 2 additions & 0 deletions src/seomatic-config/globalmeta/SiteVars.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,5 +84,7 @@
'siteLinksQueryInput' => '',
'additionalSitemapUrls' => [
],
'additionalSitemaps' => [
],
],
];
7 changes: 7 additions & 0 deletions src/templates/_layouts/siteSettings.twig
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@
},
}) %}
{% endif %}
{% if currentUser.can("seomatic:site-settings:sitemap") %}
{% set navItems = navItems |merge({
sitemap: {
title: "Sitemap"|t("seomatic"),
},
}) %}
{% endif %}
{% if currentUser.can("seomatic:site-settings:miscellaneous") %}
{% set navItems = navItems |merge({
miscellaneous: {
Expand Down
Loading

0 comments on commit 4ecdc2a

Please sign in to comment.