Skip to content

Commit

Permalink
Redirects now stored in database (needs stress-testing)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tam committed Aug 9, 2016
1 parent d88b5e7 commit aa097e4
Show file tree
Hide file tree
Showing 13 changed files with 291 additions and 23 deletions.
4 changes: 2 additions & 2 deletions SeoPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ public function getDescription()

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

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

public function getDeveloper()
Expand Down
3 changes: 1 addition & 2 deletions controllers/SeoController.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,7 @@ public function actionRedirectsPage ()
craft()->templates->includeJsResource('seo/js/seo-settings.js');
craft()->templates->includeJs("new SeoSettings('{$namespace}', 'redirects');");

$redirects = craft()->seo->getData('redirects') ? craft()->seo->getData('redirects')['redirects'] : array();
if (is_string($redirects)) $redirects = json_decode($redirects, true);
$redirects = craft()->seo_redirect->getAllRedirects();

$this->renderTemplate('seo/redirects', array(
// Global
Expand Down
21 changes: 21 additions & 0 deletions controllers/Seo_RedirectsController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace Craft;

class Seo_RedirectsController extends BaseController
{

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

if (craft()->seo_redirect->saveAllRedirects(craft()->request->getRequiredPost('data'))) {
craft()->userSession->setNotice(Craft::t('Redirects updated.'));
} else {
craft()->userSession->setError(Craft::t('Couldn’t update redirects.'));
}

$this->redirectToPostedUrl();
}

}
2 changes: 1 addition & 1 deletion controllers/Seo_SitemapController.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public function actionGenerate ()
HeaderHelper::setHeader(array('charset' => 'utf-8'));

$path = craft()->path->getPluginsPath() . 'seo/templates';
craft()->path->setTemplatesPath($path);
craft()->templates->setTemplatesPath($path);

$this->renderTemplate('_sitemap', array(
'sectionUrls' => $sectionUrls,
Expand Down
33 changes: 33 additions & 0 deletions migrations/m160809_101113_seo_CreateRedirectsAndSitemapsTables.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php
namespace Craft;

/**
* The class name is the UTC timestamp in the format of mYYMMDD_HHMMSS_pluginHandle_migrationName
*/
class m160809_101113_seo_CreateRedirectsAndSitemapsTables extends BaseMigration
{
/**
* Any migration code in here is wrapped inside of a transaction.
*
* @return bool
*/
public function safeUp()
{
// Create the craft_seo_redirects table
craft()->db->createCommand()->createTable('seo_redirects', array(
'uri' => array('required' => true),
'to' => array('required' => true),
'type' => array('values' => '301,302', 'column' => 'enum', 'required' => true),
), null, true);

// Create the craft_seo_sitemaps table
craft()->db->createCommand()->createTable('seo_sitemaps', array(
'group' => array('values' => 'sections,categories,customUrls', 'column' => 'enum', 'required' => true),
'url' => array('required' => true),
'frequency' => array('values' => 'always,hourly,daily,weekly,monthly,yearly,never', 'column' => 'enum', 'required' => true),
'priority' => array('maxLength' => 10, 'decimals' => 1, 'required' => true, 'unsigned' => false, 'length' => 11, 'column' => 'decimal'),
), null, true);

return true;
}
}
85 changes: 85 additions & 0 deletions migrations/m160809_102830_seo_AddEnabledColumnToSitemapsTable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php
namespace Craft;

/**
* The class name is the UTC timestamp in the format of mYYMMDD_HHMMSS_pluginHandle_migrationName
*/
class m160809_102830_seo_AddEnabledColumnToSitemapsTable extends BaseMigration
{
/**
* Any migration code in here is wrapped inside of a transaction.
*
* @return bool
*/
public function safeUp()
{
craft()->db->createCommand()->addColumn('seo_sitemaps', 'enabled', AttributeType::Bool);

$this->_transferData();

return true;
}

private function _transferData()
{

// Transfer Redirects
$redirects = craft()->seo->getData('redirects') ? craft()->seo->getData('redirects')['redirects'] : array();
if (is_string($redirects)) $redirects = json_decode($redirects, true);

foreach ($redirects as $redirect)
{
$record = new Seo_RedirectRecord();
$record->setAttribute('uri', $redirect['uri']);
$record->setAttribute('to', $redirect['to']);
$record->setAttribute('type', $redirect['type']);
$record->save();
}

// Transfer Sitemap
$sitemap = craft()->seo->getData('sitemap');

// Sections
if (array_key_exists('sections', $sitemap) && !empty($sitemap['sections'])) {
foreach ($sitemap['sections'] as $sectionId => $section)
{
$record = new Seo_SitemapRecord();
$record->setAttribute('group', 'sections');
$record->setAttribute('url', $sectionId);
$record->setAttribute('frequency', $section['frequency']);
$record->setAttribute('priority', $section['priority']);
$record->setAttribute('enabled', $section['enabled']);
$record->save();
}
}

// Categories
if (array_key_exists('categories', $sitemap) && !empty($sitemap['categories'])) {
foreach ($sitemap['categories'] as $sectionId => $section)
{
$record = new Seo_SitemapRecord();
$record->setAttribute('group', 'categories');
$record->setAttribute('url', $sectionId);
$record->setAttribute('frequency', $section['frequency']);
$record->setAttribute('priority', $section['priority']);
$record->setAttribute('enabled', $section['enabled']);
$record->save();
}
}

// Custom URLS
if (array_key_exists('customUrls', $sitemap) && !empty($sitemap['customUrls'])) {
foreach ($sitemap['customUrls'] as $sectionId => $section)
{
$record = new Seo_SitemapRecord();
$record->setAttribute('group', 'customUrls');
$record->setAttribute('url', $section['url']);
$record->setAttribute('frequency', $section['frequency']);
$record->setAttribute('priority', $section['priority']);
$record->setAttribute('enabled', $section['enabled']);
$record->save();
}
}

}
}
30 changes: 30 additions & 0 deletions records/Seo_RedirectRecord.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Craft;

class Seo_RedirectRecord extends BaseRecord
{
/**
* Returns the name of the associated database table.
*
* @return string
*/
public function getTableName()
{
return 'seo_redirects';
}

public function primaryKey()
{
return 'id';
}

public function defineAttributes()
{
return [
'uri' => array(AttributeType::String, 'required' => true),
'to' => array(AttributeType::String, 'required' => true),
'type' => array(AttributeType::Enum, 'values' => "301,302", 'required' => true),
];
}
}
32 changes: 32 additions & 0 deletions records/Seo_SitemapRecord.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace Craft;

class Seo_SitemapRecord extends BaseRecord
{
/**
* Returns the name of the associated database table.
*
* @return string
*/
public function getTableName()
{
return 'seo_sitemaps';
}

public function primaryKey()
{
return 'id';
}

public function defineAttributes()
{
return [
'group' => array(AttributeType::Enum, 'values' => "sections,categories,customUrls", '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),
'enabled' => array(AttributeType::Bool, 'default' => true),
];
}
}
8 changes: 8 additions & 0 deletions releases.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,5 +89,13 @@
"notes": [
"- Fixed #15 - Fixed bug where global settings undefined on new install"
]
},
{
"version": "1.2.1",
"downloadUrl": "https://github.com/ethercreative/seo/archive/v1.2.1.zip",
"date": "2016-08-09T11:00:00-08:00",
"notes": [
"[Improvement] Sitemap and Redirects are now stored in their own database tables, fixing the issue with the ~194 limit."
]
}
]
16 changes: 6 additions & 10 deletions resources/js/seo-settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,14 @@ SeoSettings.prototype.sitemapName = function () {
// REDIRECTS
SeoSettings.prototype.redirectsForm = function (table, field) {
function parseRedirectForm() {
var o = {};
var o = [];
[].slice.call(table.querySelectorAll('tbody tr:not(.hidden)')).forEach(function (el) {
o[+el.getAttribute('data-id')] = {
o.push({
'id': +el.getAttribute('data-id'),
'uri': el.querySelector('[data-name="redirects-uri"]').value.trim(),
'to': el.querySelector('[data-name="redirects-to"]').value.trim(),
'type': el.querySelector('[data-name="redirects-type"]').value
};
});
});

field.value = JSON.stringify(o).replace(/\\n/g, "\\n")
Expand Down Expand Up @@ -81,18 +82,13 @@ SeoSettings.EditableTable = function (tableId, addButtonId, rowCb) {
};

SeoSettings.EditableTable.prototype.addRow = function () {
var i = 1;

if (this.table.getElementsByTagName('tr').length > 0) {
i = parseInt(this.table.lastElementChild.getAttribute('data-id')) + 1;
}
var self = this;

var newRow = this.row.cloneNode(true);
newRow.setAttribute('data-id', i);
// newRow.innerHTML = newRow.innerHTML.replace(new RegExp('{i}', 'g'), i);

newRow.getElementsByClassName('delete')[0].addEventListener('click', function () {
newRow.remove();
self.rowCb();
});

this.table.appendChild(newRow);
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.

71 changes: 68 additions & 3 deletions services/Seo_RedirectService.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,75 @@
class Seo_RedirectService extends BaseApplicationComponent
{

public function getAllRedirects ()
{
return Seo_RedirectRecord::model()->findAll();
}

public function saveAllRedirects ($data)
{
$oldRedirects = $this->getAllRedirects();
$newRedirects = json_decode($data['redirects'], true);

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

$newRecordsRaw = [];

foreach ($newRedirects as $new)
{
if ($new['id'] !== -1) $newById[$new['id']] = $new;
else $newRecordsRaw[] = $new;
}

$idsToDelete = [];
foreach ($oldRedirects 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_redirects', array('in', 'id', $idsToDelete));
}

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

if (
$old['uri'] !== $new['uri'] ||
$old['to'] !== $new['to'] ||
$old['type'] !== $new['type']
) {
$old->setAttribute('uri', $new['uri']);
$old->setAttribute('to', $new['to']);
$old->setAttribute('type', $new['type']);
$old->save();
}
}

// Add new redirects
foreach ($newRecordsRaw as $new)
{
$record = new Seo_RedirectRecord();
$record->setAttribute('uri', $new['uri']);
$record->setAttribute('to', $new['to']);
$record->setAttribute('type', $new['type']);
$record->save();
}

return true;
}

public function findRedirectByPath ($path)
{
$redirects = craft()->seo->getData('redirects') ? craft()->seo->getData('redirects')['redirects'] : array();
if (is_string($redirects)) $redirects = json_decode($redirects, true);
$redirects = $this->getAllRedirects();

foreach ($redirects as $redirect)
{
Expand All @@ -28,7 +93,7 @@ public function findRedirectByPath ($path)
if ($to)
{
return [
'to' => strpos($to, 'http') !== false ? $to : UrlHelper::getSiteUrl($to),
'to' => strpos($to, '://') !== false ? $to : UrlHelper::getSiteUrl($to),
'type' => $redirect['type']
];
}
Expand Down
Loading

0 comments on commit aa097e4

Please sign in to comment.