Skip to content

Commit

Permalink
Added Craft Commerce product type support to sitemap
Browse files Browse the repository at this point in the history
  • Loading branch information
Tam committed Aug 9, 2016
1 parent aa097e4 commit ebf3e6c
Show file tree
Hide file tree
Showing 13 changed files with 273 additions and 19 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ All parameters are optional.


## TODO
- [ ] Add locale support for custom sitemap urls
- [ ] Add redirect support for .htaccess & web.config to improve performance
- [ ] Add hooks for plugin support
- [ ] Include more fields in snippet (i.e. Type, Image, etc.)
Expand All @@ -88,6 +89,10 @@ All parameters are optional.

## Changelog

### 1.2.3
- Added Craft Commerce product types to Sitemap.
- Sitemap and Redirects are now stored in their own database tables, fixing the issue with the ~194 limit.

### 1.1.3
- Fixed #15 - Fixed bug where global settings undefined on new install

Expand Down
18 changes: 16 additions & 2 deletions SeoPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
*/
class SeoPlugin extends BasePlugin {

public static $commerceInstalled = false;

public function getName()
{
return 'SEO';
Expand All @@ -24,12 +26,12 @@ public function getDescription()

public function getVersion()
{
return '1.2.1';
return '1.2.3';
}

public function getSchemaVersion()
{
return '0.0.11';
return '0.0.12';
}

public function getDeveloper()
Expand Down Expand Up @@ -102,6 +104,18 @@ public function registerUserPermissions()
public function init()
{

$commerce = craft()->db->createCommand()
->select('id')
->from('plugins')
->where("class = 'Commerce'")
->queryScalar();

if ($commerce) {
SeoPlugin::$commerceInstalled = true;
}

// TODO: On category / section update, update sitemap

if (craft()->request->isSiteRequest() && !craft()->request->isLivePreview())
{
craft()->onException = function(\CExceptionEvent $event)
Expand Down
7 changes: 3 additions & 4 deletions controllers/SeoController.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,10 @@ public function actionSitemapPage ()
],

// Sitemap
'sitemap' => craft()->seo->getData('sitemap'),
'sitemap' => craft()->seo_sitemap->getSitemap(),
'sections' => craft()->seo_sitemap->getValidSections(),
'categories' => craft()->seo_sitemap->getValidCategories(),
'productTypes' => craft()->seo_sitemap->getValidProductTypes(),
));
}

Expand All @@ -92,8 +93,6 @@ public function actionRedirectsPage ()
craft()->templates->includeJsResource('seo/js/seo-settings.js');
craft()->templates->includeJs("new SeoSettings('{$namespace}', 'redirects');");

$redirects = craft()->seo_redirect->getAllRedirects();

$this->renderTemplate('seo/redirects', array(
// Global
'namespace' => $namespace,
Expand All @@ -106,7 +105,7 @@ public function actionRedirectsPage ()
],

// Redirecs
'redirects' => $redirects,
'redirects' => craft()->seo_redirect->getAllRedirects(),
));
}

Expand Down
36 changes: 34 additions & 2 deletions controllers/Seo_SitemapController.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,28 @@ class Seo_SitemapController extends BaseController

public function init()
{
$this->sitemap = craft()->seo->getData('sitemap');
$this->sitemap = craft()->seo_sitemap->getSitemap();
parent::init();
}

public function actionSaveSitemap ()
{
$this->requirePostRequest();

if (craft()->seo_sitemap->saveSitemap(craft()->request->getRequiredPost('data'))) {
craft()->userSession->setNotice(Craft::t('Sitemap updated.'));
} else {
craft()->userSession->setError(Craft::t('Couldn’t update sitemap.'));
}

$this->redirectToPostedUrl();
}

public function actionGenerate ()
{
$sectionUrls = $this->_generateSections();
$categoryUrls = $this->_generateCategories();
$productTypeUrls = $this->_generateProductTypes();

HeaderHelper::setContentTypeByExtension('xml');
HeaderHelper::setHeader(array('charset' => 'utf-8'));
Expand All @@ -28,6 +42,7 @@ public function actionGenerate ()
$this->renderTemplate('_sitemap', array(
'sectionUrls' => $sectionUrls,
'categoryUrls' => $categoryUrls,
'productTypeUrls' => $productTypeUrls,
'customUrls' => array_key_exists('customUrls', $this->sitemap) ? $this->sitemap['customUrls'] : [],
));
}
Expand Down Expand Up @@ -62,6 +77,23 @@ private function _generateCategories ()
return $urls;
}

private function _generateProductTypes ()
{
if (!SeoPlugin::$commerceInstalled) return array();

$urls = [];

if (array_key_exists('productTypes', $this->sitemap) && !empty($this->sitemap['productTypes'])) {
foreach ($this->sitemap['productTypes'] as $productTypeId => $productType)
{
if ($productType['enabled'])
$urls = array_merge($urls, $this->_generateUrls($productTypeId, $productType, 'Commerce_Product'));
}
}

return $urls;
}

private function _generateUrls ($id, $section, $elemType)
{
$urls = [];
Expand All @@ -77,7 +109,7 @@ private function _generateUrls ($id, $section, $elemType)

if (is_array($elem->locales) && count($elem->locales) > 1) {
foreach ($elem->locales as $locale => $settings) {
$locale = $elemType == ElementType::Category ? $settings : $locale;
$locale = ($elemType == ElementType::Category) || ($elemType == 'Commerce_Product') ? $settings : $locale;

if ($locale !== craft()->language) {
$urlAlts[] = [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php
namespace Craft;

/**
* The class name is the UTC timestamp in the format of mYYMMDD_HHMMSS_pluginHandle_migrationName
*/
class m160809_144009_seo_AddProductTypeToSitemapGroupColumn extends BaseMigration
{
/**
* Any migration code in here is wrapped inside of a transaction.
*
* @return bool
*/
public function safeUp()
{
craft()->db->createCommand()
->alterColumn('seo_sitemaps', 'group', array('values' => 'sections,categories,customUrls,productTypes', 'column' => 'enum', 'required' => true));

return true;
}
}
2 changes: 1 addition & 1 deletion records/Seo_SitemapRecord.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public function primaryKey()
public function defineAttributes()
{
return [
'group' => array(AttributeType::Enum, 'values' => "sections,categories,customUrls", 'required' => true),
'group' => array(AttributeType::Enum, 'values' => "sections,categories,customUrls,productTypes", 'required' => true),
'url' => array(AttributeType::String, 'required' => true),
'frequency' => array(AttributeType::Enum, 'values' => "always,hourly,daily,weekly,monthly,yearly,never", 'required' => true),
'priority' => array(AttributeType::Number, 'required' => true, 'decimals' => 1),
Expand Down
5 changes: 3 additions & 2 deletions releases.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,11 @@
]
},
{
"version": "1.2.1",
"downloadUrl": "https://github.com/ethercreative/seo/archive/v1.2.1.zip",
"version": "1.2.3",
"downloadUrl": "https://github.com/ethercreative/seo/archive/v1.2.3.zip",
"date": "2016-08-09T11:00:00-08:00",
"notes": [
"[Added] Added Craft Commerce product types to Sitemap.",
"[Improvement] Sitemap and Redirects are now stored in their own database tables, fixing the issue with the ~194 limit."
]
}
Expand Down
2 changes: 2 additions & 0 deletions resources/js/seo-settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ SeoSettings.EditableTable.prototype.addRow = function () {

var newRow = this.row.cloneNode(true);

newRow.innerHTML = newRow.innerHTML.replace(/\{i}/g, this.table.childNodes.length - 2);

newRow.getElementsByClassName('delete')[0].addEventListener('click', function () {
newRow.remove();
self.rowCb();
Expand Down
2 changes: 1 addition & 1 deletion resources/js/seo-settings.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions services/Seo_RedirectService.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ public function saveAllRedirects ($data)
$record->save();
}

// TODO: Add redirects to .htaccess / web.config to improve performance

return true;
}

Expand Down
101 changes: 101 additions & 0 deletions services/Seo_SitemapService.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,98 @@
class Seo_SitemapService extends BaseApplicationComponent
{

public function getSitemap ()
{
$sitemapRaw = Seo_SitemapRecord::model()->findAll();
$sitemap = [];

foreach ($sitemapRaw as $row)
{
if (!array_key_exists($row['group'], $sitemap)) $sitemap[$row['group']] = [];

if ($row['group'] == 'customUrls') {
$sitemap[$row['group']][] = $row;
} else {
$sitemap[$row['group']][$row['url']] = $row;
}
}

return $sitemap;
}

public function saveSitemap ($data)
{
$oldSitemap = $this->getSitemap();
$newSitemap = $data;

// Delete removed rows
$newById = [];
$oldById = [];

$newRecordsRaw = [];

foreach ($newSitemap as $group => $rows)
{
foreach ($rows as $new)
{
$new['group'] = $group;

if ($new['id'] != "-1") $newById[$new['id']] = $new;
else $newRecordsRaw[] = $new;
}
}

$idsToDelete = [];
foreach ($oldSitemap as $group => $rows)
{
foreach ($rows as $old)
{
if (array_key_exists($old['id'], $newById)) {
$oldById[$old['id']] = $old;
} else {
$idsToDelete[] = $old['id'];
}
}
}

if (!empty($idsToDelete)) {
craft()->db->createCommand()->delete('seo_sitemaps', array('in', 'id', $idsToDelete));
}

// Update current rows
foreach ($newById as $new)
{
$old = $oldById[$new['id']];

if (
$old['url'] !== $new['url'] ||
$old['frequency'] !== $new['frequency'] ||
$old['priority'] !== $new['priority'] ||
$old['enabled'] !== !!$new['enabled']
) {
$old->setAttribute('url', $new['url']);
$old->setAttribute('frequency', $new['frequency']);
$old->setAttribute('priority', $new['priority']);
$old->setAttribute('enabled', !!$new['enabled']);
$old->save();
}
}

// Add new rows
foreach ($newRecordsRaw as $new)
{
$record = new Seo_SitemapRecord();
$record->setAttribute('url', $new['url']);
$record->setAttribute('frequency', $new['frequency']);
$record->setAttribute('priority', $new['priority']);
$record->setAttribute('enabled', !!$new['enabled']);
$record->setAttribute('group', $new['group']);
$record->save();
}

return true;
}

public function getValidSections ()
{
return array_filter(craft()->sections->allSections, function ($section) {
Expand All @@ -19,4 +111,13 @@ public function getValidCategories ()
});
}

public function getValidProductTypes ()
{
if (!SeoPlugin::$commerceInstalled) return array();

return array_filter(craft()->commerce_productTypes->getAllProductTypes(), function ($productType) {
return $productType->hasUrls;
});
}

}
21 changes: 17 additions & 4 deletions templates/_sitemap.twig
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

{# Sections #}

{% for section in sectionUrls %}
{% for section in sectionUrls -%}
<url>
<loc>{{ url(section.url) }}</loc>
<lastmod>{{ section.lastmod }}</lastmod>
Expand All @@ -17,7 +17,7 @@

{# Categories #}

{% for category in categoryUrls %}
{% for category in categoryUrls -%}
<url>
<loc>{{ url(category.url) }}</loc>
<lastmod>{{ category.lastmod }}</lastmod>
Expand All @@ -28,10 +28,23 @@
</url>
{% endfor %}

{# Products #}

{% for category in productTypeUrls -%}
<url>
<loc>{{ url(category.url) }}</loc>
<lastmod>{{ category.lastmod }}</lastmod>
<changefreq>{{ category.frequency }}</changefreq>
<priority>{{ category.priority }}</priority>
{% for alt in category.urlAlts %}<xhtml:link rel="alternate" hreflang="{{ alt.locale }}" href="{{ alt.url }}" />
{% endfor %}
</url>
{% endfor %}

{# Custom Urls #}

{% for custom in customUrls %}
{% if custom.enabled %}
{% for custom in customUrls -%}
{%- if custom.enabled -%}
<url>
<loc>{{ url(custom.url) }}</loc>
<changefreq>{{ custom.frequency }}</changefreq>
Expand Down
Loading

0 comments on commit ebf3e6c

Please sign in to comment.