diff --git a/_build/build.transport.php b/_build/build.transport.php
index d1f211b..799d6dd 100644
--- a/_build/build.transport.php
+++ b/_build/build.transport.php
@@ -14,7 +14,7 @@
/* define package names */
define('PKG_NAME','Redirector');
define('PKG_NAME_LOWER','redirector');
-define('PKG_VERSION','1.0.3');
+define('PKG_VERSION','1.0.4');
define('PKG_RELEASE','pl');
/* define build paths */
@@ -65,6 +65,13 @@
'priority' => 0,
'propertyset' => 0,
),'',true,true);
+ $events['OnSiteRefresh'] = $modx->newObject('modPluginEvent');
+ $events['OnSiteRefresh']->fromArray(array(
+ 'event' => 'OnSiteRefresh',
+ 'priority' => 0,
+ 'propertyset' => 0,
+ ),'',true,true);
+
$plugin->addMany($events);
unset($events);
diff --git a/_build/data/transport.plugins.php b/_build/data/transport.plugins.php
deleted file mode 100644
index 019c8d2..0000000
--- a/_build/data/transport.plugins.php
+++ /dev/null
@@ -1,25 +0,0 @@
-newObject('modPlugin');
-$plugins[1]->fromArray(array(
- 'id' => 1,
- 'name' => 'Redirector',
- 'description' => 'Handles site redirects.',
- 'plugincode' => file_get_contents($sources['elements'].'plugins/plugin.redirector.php'),
-),'',true,true);
- $events = array();
- $events['OnPageNotFound']= $modx->newObject('modPluginEvent');
- $events['OnPageNotFound']->fromArray(array(
- 'event' => 'OnPageNotFound',
- 'priority' => 0,
- 'propertyset' => 0,
- ),'',true,true);
- $plugins[1]->addMany($events);
- unset($events);
-
-return $plugins;
\ No newline at end of file
diff --git a/_build/resolvers/resolve.tables.php b/_build/resolvers/resolve.tables.php
index 4769d84..267713b 100644
--- a/_build/resolvers/resolve.tables.php
+++ b/_build/resolvers/resolve.tables.php
@@ -15,6 +15,7 @@
$manager = $modx->getManager();
$manager->createObjectContainer('modRedirect');
+ $manager->createObjectContainer('modRedirectPageNotFound');
break;
case xPDOTransport::ACTION_UPGRADE:
diff --git a/assets/components/redirector/js/mgr/widgets/home.panel.js b/assets/components/redirector/js/mgr/widgets/home.panel.js
index d11ea02..3e5473b 100644
--- a/assets/components/redirector/js/mgr/widgets/home.panel.js
+++ b/assets/components/redirector/js/mgr/widgets/home.panel.js
@@ -19,6 +19,16 @@ Redi.panel.Home = function(config) {
return {activeTab:this.items.indexOf(this.getActiveTab())};
}
,items: [{
+ title: _('redirector.errors')
+ ,defaults: { autoHeight: true }
+ ,items: [{
+ html: '
'+_('redirector.pnfdesc')+'
'
+ ,border: false
+ },{
+ xtype: 'redirector-grid-pagenotfound'
+ ,preventRender: true
+ }]
+ },{
title: _('redirector.redirects')
,defaults: { autoHeight: true }
,items: [{
diff --git a/assets/components/redirector/js/mgr/widgets/pagenotfound.grid.js b/assets/components/redirector/js/mgr/widgets/pagenotfound.grid.js
new file mode 100644
index 0000000..593270e
--- /dev/null
+++ b/assets/components/redirector/js/mgr/widgets/pagenotfound.grid.js
@@ -0,0 +1,138 @@
+Redi.grid.PageNotFound = function(config) {
+ config = config || {};
+ Ext.applyIf(config,{
+ id: 'redirector-grid-pagenotfound'
+ ,url: Redi.config.connector_url
+ ,baseParams: { action: 'mgr/errors/getList' }
+ ,fields: ['id','url','times','firsttime','lasttime','menu']
+ ,paging: true
+ ,autosave: true
+ ,remoteSort: true
+ ,anchor: '97%'
+ ,autoExpandColumn: 'url'
+ ,columns: [{
+ header: _('redirector.url')
+ ,dataIndex: 'url'
+ ,sortable: false
+ ,width: 200
+ ,editor: { xtype: 'textfield' }
+ },{
+ header: _('redirector.times')
+ ,dataIndex: 'times'
+ ,sortable: true
+ ,width: 40
+ ,editor: { xtype: 'textfield' }
+ },{
+ header: _('redirector.firsttime')
+ ,dataIndex: 'firsttime'
+ ,sortable: true
+ ,width: 100
+ ,editor: { xtype: 'textfield' }
+ },{
+ header: _('redirector.lasttime')
+ ,dataIndex: 'lasttime'
+ ,sortable: true
+ ,width: 100
+ ,editor: { xtype: 'textfield' }
+ }]
+ ,tbar: [{
+ xtype: 'textfield'
+ ,id: 'redirector-search-filter'
+ ,emptyText: _('redirector.search...')
+ ,listeners: {
+ 'change': {fn:this.search,scope:this}
+ ,'render': {fn: function(cmp) {
+ new Ext.KeyMap(cmp.getEl(), {
+ key: Ext.EventObject.ENTER
+ ,fn: function() {
+ this.fireEvent('change',this.getValue());
+ this.blur();
+ return true; }
+ ,scope: cmp
+ });
+ },scope:this}
+ }
+ }]
+ });
+ Redi.grid.PageNotFound.superclass.constructor.call(this,config)
+};
+Ext.extend(Redi.grid.PageNotFound,MODx.grid.Grid,{
+ search: function(tf,nv,ov) {
+ var s = this.getStore();
+ s.baseParams.query = tf.getValue();
+ this.getBottomToolbar().changePage(1);
+ this.refresh();
+ }
+
+ ,removeRedirectPageNotFound: function() {
+ MODx.msg.confirm({
+ title: _('redirector.redirect_remove_page_not_found')
+ ,text: _('redirector.redirect_remove_confirm')
+ ,url: this.config.url
+ ,params: {
+ action: 'mgr/errors/remove'
+ ,id: this.menu.record.id
+ }
+ ,listeners: {
+ 'success': {fn:this.refresh,scope:this}
+ }
+ });
+
+ }
+ ,createRedirectPageNotFound: function(btn,e){
+ if (!this.createRedirectPNFWindow) {
+ this.createRedirectPNFWindow = MODx.load({
+ xtype: 'redirector-window-redirect-create-from-pnf'
+ ,record: {
+ pattern : this.menu.record.url.replace(/^\//, '')
+ ,target: ''
+ ,active: 1
+ ,isregexp: 0
+ }
+ ,listeners: {
+ 'success': {fn:this.refresh,scope:this}
+ }
+ });
+ }
+ this.createRedirectPNFWindow.setValues(this.menu.record);
+ this.createRedirectPNFWindow.show(e.target);
+ }
+});
+Ext.reg('redirector-grid-pagenotfound',Redi.grid.PageNotFound);
+
+//
+Redi.window.CreateRedirectPageNotFound = function(config) {
+ config = config || {};
+ Ext.applyIf(config,{
+ title: _('redirector.redirect_create')
+ ,url: Redi.config.connector_url
+ ,baseParams: {
+ action: 'mgr/redirect/create'
+ }
+ ,fields: [{
+ xtype: 'textfield'
+ ,fieldLabel: _('redirector.pattern')
+ ,name: 'pattern'
+ ,width: 300
+ },{
+ xtype: 'textfield'
+ ,fieldLabel: _('redirector.target')
+ ,name: 'target'
+ ,width: 300
+ },{
+ xtype: 'checkbox'
+ ,fieldLabel: _('redirector.active')
+ ,name: 'active'
+ ,inputValue: 1
+ ,checked: true
+ },{
+ xtype: 'checkbox'
+ ,fieldLabel: _('redirector.isregexp')
+ ,name: 'isregexp'
+ ,inputValue: 1
+ }]
+ });
+ Redi.window.CreateRedirectPageNotFound.superclass.constructor.call(this,config);
+};
+Ext.extend(Redi.window.CreateRedirectPageNotFound,MODx.Window);
+Ext.reg('redirector-window-redirect-create-from-pnf',Redi.window.CreateRedirectPageNotFound);
\ No newline at end of file
diff --git a/assets/components/redirector/js/mgr/widgets/redirects.grid.js b/assets/components/redirector/js/mgr/widgets/redirects.grid.js
index 455f7be..67a2bab 100644
--- a/assets/components/redirector/js/mgr/widgets/redirects.grid.js
+++ b/assets/components/redirector/js/mgr/widgets/redirects.grid.js
@@ -3,35 +3,53 @@ Redi.grid.Redirects = function(config) {
var cb = new Ext.ux.grid.CheckColumn({
header: _('redirector.active')
,dataIndex: 'active'
- ,width: 40
+ ,width: 30
,sortable: true
,onMouseDown: this.saveCheckbox
});
+ var re = new Ext.ux.grid.CheckColumn({
+ header: _('redirector.isregexp')
+ ,dataIndex: 'isregexp'
+ ,width: 30
+ ,sortable: true
+ ,onMouseDown: this.saveCheckbox
+ });
+
Ext.applyIf(config,{
id: 'redirector-grid-redirects'
,url: Redi.config.connector_url
- ,baseParams: { action: 'mgr/redirect/getList' }
+ ,baseParams: { action: 'mgr/redirect/getList', limit: 0, start: 0 }
,save_action: 'mgr/redirect/updateFromGrid'
- ,fields: ['id','pattern','target','active','menu']
- ,paging: true
+ ,fields: ['id','pattern','target','active','isregexp','sortorder','menu']
+ ,paging: false
+ ,limit: 0
,autosave: true
,remoteSort: true
,anchor: '97%'
- ,autoExpandColumn: 'name'
- ,plugins: [cb]
+ ,enableDragDrop: true
+ ,ddGroup: 'redirect-dd'
+ ,ddText: 'Yeah ! You\'re dragging me'
+ ,plugins: [cb,re]
,columns: [{
header: _('redirector.pattern')
,dataIndex: 'pattern'
,sortable: true
- ,width: 200
+ ,width: 150
,editor: { xtype: 'textfield' }
},{
header: _('redirector.target')
,dataIndex: 'target'
,sortable: false
- ,width: 200
+ ,width: 150
,editor: { xtype: 'textfield' }
- },cb]
+ },cb,re,
+ {
+ header: _('redirector.priority')
+ ,dataIndex: 'sortorder'
+ ,sortable: true
+ ,width: 30
+ ,editor: { xtype: 'numberfield' }
+ }]
,tbar: [{
xtype: 'textfield'
,id: 'redirector-search-filter'
@@ -53,11 +71,66 @@ Redi.grid.Redirects = function(config) {
text: _('redirector.redirect_create')
,handler: { xtype: 'redirector-window-redirect-create' ,blankValues: true }
}]
+ ,listeners:{
+ "render": {
+ scope: this,
+ fn: function(grid){
+ var ddrow = new Ext.dd.DropTarget(grid.container, {
+ ddGroup : 'redirect-dd',
+ copy:false,
+ notifyDrop : function(dd, e, data){
+ var ds = grid.store;
+ var sm = grid.getSelectionModel();
+ var rows = sm.getSelections();
+ if(dd.getDragData(e)) {
+ var cindex=dd.getDragData(e).rowIndex;
+ if(typeof(cindex) != "undefined") {
+ for(i = 0; i < rows.length; i++) {
+ ds.remove(ds.getById(rows[i].id));
+ }
+ ds.insert(cindex,data.selections);
+ sm.clearSelections();
+ }
+ }
+ grid.collectItems();
+ }
+ });
+
+ this.setWidth('99%');
+ }
+ }
+ }
});
+
+
Redi.grid.Redirects.superclass.constructor.call(this,config)
};
Ext.extend(Redi.grid.Redirects,MODx.grid.Grid,{
- search: function(tf,nv,ov) {
+ collectItems: function(){
+ var items=[];
+ // read jsons from grid-store-items
+ var griddata=this.store.data;
+ for(i = 0; i < griddata.length; i++) {
+ items.push(griddata.items[i].json);
+ }
+
+ items = Ext.util.JSON.encode(items);
+ MODx.Ajax.request({
+ url: Redi.config.connector_url
+ ,params: {
+ action: 'mgr/redirect/sort'
+ ,items: items
+ ,start: this.start
+ ,limit: this.limit
+ }
+ ,listeners: {
+ 'success': {fn:function(r) {
+ this.refresh();
+ },scope:this}
+ }
+ });
+ }
+ ,search: function(tf,nv,ov) {
var s = this.getStore();
s.baseParams.query = tf.getValue();
this.getBottomToolbar().changePage(1);
@@ -148,6 +221,11 @@ Redi.window.CreateRedirect = function(config) {
,name: 'active'
,inputValue: 1
,checked: true
+ },{
+ xtype: 'checkbox'
+ ,fieldLabel: _('redirector.isregexp')
+ ,name: 'isregexp'
+ ,inputValue: 1
}]
});
Redi.window.CreateRedirect.superclass.constructor.call(this,config);
@@ -182,6 +260,11 @@ Redi.window.UpdateRedirect = function(config) {
,fieldLabel: _('redirector.active')
,name: 'active'
,inputValue: 1
+ },{
+ xtype: 'checkbox'
+ ,fieldLabel: _('redirector.isregexp')
+ ,name: 'isregexp'
+ ,inputValue: 1
}]
});
Redi.window.UpdateRedirect.superclass.constructor.call(this,config);
diff --git a/core/components/redirector/controllers/mgr/index.php b/core/components/redirector/controllers/mgr/index.php
index 131a998..78b130f 100644
--- a/core/components/redirector/controllers/mgr/index.php
+++ b/core/components/redirector/controllers/mgr/index.php
@@ -5,6 +5,7 @@
* @package redirector
* @subpackage controllers
*/
+$modx->regClientStartupScript($redirector->config['jsUrl'].'mgr/widgets/pagenotfound.grid.js');
$modx->regClientStartupScript($redirector->config['jsUrl'].'mgr/widgets/redirects.grid.js');
$modx->regClientStartupScript($redirector->config['jsUrl'].'mgr/widgets/home.panel.js');
$modx->regClientStartupScript($redirector->config['jsUrl'].'mgr/sections/index.js');
diff --git a/core/components/redirector/docs/changelog.txt b/core/components/redirector/docs/changelog.txt
index 8f1194f..c1f2f14 100644
--- a/core/components/redirector/docs/changelog.txt
+++ b/core/components/redirector/docs/changelog.txt
@@ -1,5 +1,11 @@
Changelog file for Redirector component.
+Redirector 1.0.4
+====================================
+- Add Regular Expression support
+- Add 404 logging and easy way to create redirection from them
+- Add priority for Redirection Rules
+
Redirector 1.0.3
====================================
- Add sqlsrv support
diff --git a/core/components/redirector/docs/readme.txt b/core/components/redirector/docs/readme.txt
index 0fd2d5d..bc4df49 100644
--- a/core/components/redirector/docs/readme.txt
+++ b/core/components/redirector/docs/readme.txt
@@ -1,8 +1,15 @@
--------------------
3PC: Redirector
--------------------
-Version: 1.0
+Version: 1.0.4
Since: April 21st, 2010
-Author: Shaun McCormick and Jason Coward
+Author: Shaun McCormick , Jason Coward and Emmanuel Prochasson
-Handles 301 redirects for your site.
+Handles 301 redirects for your site. Logs 404 error to allow quick integration of new redirect rules if required.
+
+You can create two kinds of rule. Plain text (default) will perform exact match on the pattern and redirect to the target.
+Regexp will perform Regular Expression matching and Replacing.
+
+Rules are applied in their priority order, however, plain text rules are always tried before the Regexp ones.
+
+IT IS VERY EASY TO GENERATE INFINITE REDIRECTION LOOP, so use with caution.
\ No newline at end of file
diff --git a/core/components/redirector/elements/plugins/plugin.redirector.php b/core/components/redirector/elements/plugins/plugin.redirector.php
index fa7e854..3e8f3c7 100644
--- a/core/components/redirector/elements/plugins/plugin.redirector.php
+++ b/core/components/redirector/elements/plugins/plugin.redirector.php
@@ -1,4 +1,6 @@
getService('redirector','Redirector',$corePath.'model/redirector/',$scriptProperties);
if (!($redirector instanceof Redirector)) return '';
-/* handle redirects */
-$search = $_SERVER['REQUEST_URI'];
-$baseUrl = $modx->getOption('base_url',null,MODX_BASE_URL);
-if (!empty($baseUrl) && $baseUrl != '/' && $baseUrl != ' ') {
- $search = str_replace($baseUrl,'',$search);
-}
-$search = ltrim($search,'/');
-$extPos = strrpos($search, '.');
-if ($extPos) {
- if ($search) {
- $redirect = $modx->getObject('modRedirect', array(
- 'pattern' => $search,
- 'active' => 1,
- ));
- if ($redirect) {
- $target = $redirect->get('target');
- $modx->parser->processElementTags('', $target, true, true);
- if ($target != $modx->resourceIdentifier && $target != $search) {
- if (!strpos($target, '://')) {
- $target = $modx->getOption('site_url').$target;
- }
- $modx->log(modX::LOG_LEVEL_INFO, 'Redirector plugin redirecting request for ' . $search . ' to ' . $target);
- header('HTTP/1.1 301 Moved Permanently');
- $modx->sendRedirect($target);
- }
+
+switch($modx->event->name){
+ case 'OnPageNotFound':
+ /* handle redirects */
+ $search = $_SERVER['REQUEST_URI'];
+ $originalRequest = $search;
+ $baseUrl = $modx->getOption('base_url',null,MODX_BASE_URL);
+ if (!empty($baseUrl) && $baseUrl != '/' && $baseUrl != ' ') {
+ $search = str_replace($baseUrl,'',$search);
+ $originalRequest = $search;
}
- }
- $search = substr($search, 0, $extPos);
-}
-if ($search) {
- $redirect = $modx->getObject('modRedirect', array('pattern' => $search, 'active' => 1));
- if ($redirect) {
- $target = $redirect->get('target');
- $modx->parser->processElementTags('', $target, true, true);
- if ($target != $modx->resourceIdentifier && $target != $search) {
- if (!strpos($target, '://')) {
- $target = $modx->getOption('site_url').$target;
+ $search = ltrim($search,'/');
+
+ $extPos = strrpos($search, '.');
+
+ if ($extPos) {
+ if ($search) {
+ $redirector->getRedirect($search);
}
- $modx->log(modX::LOG_LEVEL_INFO, 'Redirector plugin redirecting request for ' . $search . ' to ' . $target);
- header('HTTP/1.1 301 Moved Permanently');
- $modx->sendRedirect($target);
+ $search = substr($search, 0, $extPos);
}
- }
+ if ($search) {
+ $redirector->getRedirect($search);
+ }
+
+ $redirector->record404($originalRequest);
+ return;
+ break;
+ case 'OnSiteRefresh':
+ $redirector->clearRedirectCache();
+ return;
+ break;
}
-return;
\ No newline at end of file
diff --git a/core/components/redirector/lexicon/de/default.inc.php b/core/components/redirector/lexicon/de/default.inc.php
index df72584..948d0e5 100644
--- a/core/components/redirector/lexicon/de/default.inc.php
+++ b/core/components/redirector/lexicon/de/default.inc.php
@@ -26,4 +26,14 @@
$_lang['redirector.pattern'] = 'Muster';
$_lang['redirector.search...'] = 'Suche...';
$_lang['redirector.target'] = 'Ziel';
-
+$_lang['redirector.priority'] = 'Priority';
+$_lang['redirector.isregexp'] = 'Regexp?';
+$_lang['redirector.errors'] = 'Pages Not Found';
+$_lang['redirector.pnfdesc'] = 'Manage pages not found';
+$_lang['redirector.url'] = 'Url';
+$_lang['redirector.times'] = 'Occurrences';
+$_lang['redirector.firsttime'] = 'First Occurrence';
+$_lang['redirector.lasttime'] = 'Last Occurrence';
+$_lang['redirector.remove_page_not_found'] = 'Remove this entry';
+$_lang['redirector.ignore_page_not_found'] = 'Ignore this entry';
+$_lang['redirector.create_rule'] = 'Create Redirect Rule From This Entry';
diff --git a/core/components/redirector/lexicon/en/default.inc.php b/core/components/redirector/lexicon/en/default.inc.php
index e015a1a..6205a34 100644
--- a/core/components/redirector/lexicon/en/default.inc.php
+++ b/core/components/redirector/lexicon/en/default.inc.php
@@ -25,4 +25,15 @@
$_lang['redirector.pattern'] = 'Pattern';
$_lang['redirector.search...'] = 'Search...';
$_lang['redirector.target'] = 'Target';
+$_lang['redirector.priority'] = 'Priority';
+$_lang['redirector.isregexp'] = 'Regexp?';
+$_lang['redirector.errors'] = 'Pages Not Found';
+$_lang['redirector.pnfdesc'] = 'Manage pages not found';
+$_lang['redirector.url'] = 'Url';
+$_lang['redirector.times'] = 'Occurrences';
+$_lang['redirector.firsttime'] = 'First Occurrence';
+$_lang['redirector.lasttime'] = 'Last Occurrence';
+$_lang['redirector.remove_page_not_found'] = 'Remove this entry';
+$_lang['redirector.ignore_page_not_found'] = 'Ignore this entry';
+$_lang['redirector.create_rule'] = 'Create Redirect Rule From This Entry';
diff --git a/core/components/redirector/lexicon/fr/default.inc.php b/core/components/redirector/lexicon/fr/default.inc.php
index 8bdbde1..f1e695d 100755
--- a/core/components/redirector/lexicon/fr/default.inc.php
+++ b/core/components/redirector/lexicon/fr/default.inc.php
@@ -24,4 +24,15 @@
$_lang['redirector.menu_desc'] = 'Gérez vos redirections.';
$_lang['redirector.pattern'] = 'Modèle';
$_lang['redirector.search...'] = 'Chercher…';
-$_lang['redirector.target'] = 'Cible';
\ No newline at end of file
+$_lang['redirector.target'] = 'Cible';
+$_lang['redirector.isregexp'] = 'Regexp?';
+$_lang['redirector.priority'] = 'Priorité';
+$_lang['redirector.errors'] = 'Pages Manquantes';
+$_lang['redirector.pnfdesc'] = 'Gestion des erreurs 404';
+$_lang['redirector.url'] = 'Url';
+$_lang['redirector.times'] = 'Occurrences';
+$_lang['redirector.firsttime'] = 'Première Occurrence';
+$_lang['redirector.lasttime'] = 'Dernière Occurrence';
+$_lang['redirector.remove_page_not_found'] = 'Supprimer cette entrée';
+$_lang['redirector.ignore_page_not_found'] = 'Ignorer cette entrée';
+$_lang['redirector.create_rule'] = 'Créer une redirection à partir de cette entrée';
diff --git a/core/components/redirector/lexicon/nl/default.inc.php b/core/components/redirector/lexicon/nl/default.inc.php
index 34a5e48..a8827d6 100644
--- a/core/components/redirector/lexicon/nl/default.inc.php
+++ b/core/components/redirector/lexicon/nl/default.inc.php
@@ -25,4 +25,14 @@
$_lang['redirector.pattern'] = 'Patroon';
$_lang['redirector.search...'] = 'Zoeken...';
$_lang['redirector.target'] = 'Doel';
-
+$_lang['redirector.priority'] = 'Priority';
+$_lang['redirector.isregexp'] = 'Regexp?';
+$_lang['redirector.errors'] = 'Pages Not Found';
+$_lang['redirector.pnfdesc'] = 'Manage pages not found';
+$_lang['redirector.url'] = 'Url';
+$_lang['redirector.times'] = 'Occurrences';
+$_lang['redirector.firsttime'] = 'First Occurrence';
+$_lang['redirector.lasttime'] = 'Last Occurrence';
+$_lang['redirector.remove_page_not_found'] = 'Remove this entry';
+$_lang['redirector.ignore_page_not_found'] = 'Ignore this entry';
+$_lang['redirector.create_rule'] = 'Create Redirect Rule From This Entry';
diff --git a/core/components/redirector/lexicon/ru/default.inc.php b/core/components/redirector/lexicon/ru/default.inc.php
index cfb8ffe..e0adfb6 100755
--- a/core/components/redirector/lexicon/ru/default.inc.php
+++ b/core/components/redirector/lexicon/ru/default.inc.php
@@ -25,4 +25,14 @@
$_lang['redirector.pattern'] = 'Шаблон';
$_lang['redirector.search...'] = 'Поиск...';
$_lang['redirector.target'] = 'Цель';
-
+$_lang['redirector.priority'] = 'Priority';
+$_lang['redirector.isregexp'] = 'Regexp?';
+$_lang['redirector.errors'] = 'Pages Not Found';
+$_lang['redirector.pnfdesc'] = 'Manage pages not found';
+$_lang['redirector.url'] = 'Url';
+$_lang['redirector.times'] = 'Occurrences';
+$_lang['redirector.firsttime'] = 'First Occurrence';
+$_lang['redirector.lasttime'] = 'Last Occurrence';
+$_lang['redirector.remove_page_not_found'] = 'Remove this entry';
+$_lang['redirector.ignore_page_not_found'] = 'Ignore this entry';
+$_lang['redirector.create_rule'] = 'Create Redirect Rule From This Entry';
diff --git a/core/components/redirector/model/redirector/metadata.mysql.php b/core/components/redirector/model/redirector/metadata.mysql.php
new file mode 100644
index 0000000..d1b583a
--- /dev/null
+++ b/core/components/redirector/model/redirector/metadata.mysql.php
@@ -0,0 +1,9 @@
+
+ array (
+ 0 => 'modRedirect',
+ 1 => 'modRedirectPageNotFound',
+ ),
+);
\ No newline at end of file
diff --git a/core/components/redirector/model/redirector/metadata.sqlsrv.php b/core/components/redirector/model/redirector/metadata.sqlsrv.php
new file mode 100644
index 0000000..1ce2540
--- /dev/null
+++ b/core/components/redirector/model/redirector/metadata.sqlsrv.php
@@ -0,0 +1,8 @@
+
+ array (
+ 0 => 'modRedirect',
+ ),
+);
\ No newline at end of file
diff --git a/core/components/redirector/model/redirector/modredirect.class.php b/core/components/redirector/model/redirector/modredirect.class.php
index b1ea792..1fc11b0 100644
--- a/core/components/redirector/model/redirector/modredirect.class.php
+++ b/core/components/redirector/model/redirector/modredirect.class.php
@@ -3,5 +3,16 @@
* @package redirector
*/
class modRedirect extends xPDOSimpleObject {
-
-}
\ No newline at end of file
+ function modRedirect(& $xpdo) {
+ $this->__construct($xpdo);
+ }
+ function __construct(& $xpdo) {
+ parent :: __construct($xpdo);
+ }
+
+ function save(){
+ $this->xpdo->cacheManager->refresh(array('Redirector' => array()));
+ return parent::save();
+ }
+}
+?>
\ No newline at end of file
diff --git a/core/components/redirector/model/redirector/modredirectpagenotfound.class.php b/core/components/redirector/model/redirector/modredirectpagenotfound.class.php
new file mode 100644
index 0000000..1e42a03
--- /dev/null
+++ b/core/components/redirector/model/redirector/modredirectpagenotfound.class.php
@@ -0,0 +1,13 @@
+__construct($xpdo);
+ }
+ function __construct(& $xpdo) {
+ parent :: __construct($xpdo);
+ }
+}
+?>
\ No newline at end of file
diff --git a/core/components/redirector/model/redirector/mysql/modredirect.class.php b/core/components/redirector/model/redirector/mysql/modredirect.class.php
index 8e5ed17..68d62d7 100644
--- a/core/components/redirector/model/redirector/mysql/modredirect.class.php
+++ b/core/components/redirector/model/redirector/mysql/modredirect.class.php
@@ -3,4 +3,12 @@
* @package redirector
*/
require_once (strtr(realpath(dirname(dirname(__FILE__))), '\\', '/') . '/modredirect.class.php');
-class modRedirect_mysql extends modRedirect {}
\ No newline at end of file
+class modRedirect_mysql extends modRedirect {
+ function modRedirect_mysql(& $xpdo) {
+ $this->__construct($xpdo);
+ }
+ function __construct(& $xpdo) {
+ parent :: __construct($xpdo);
+ }
+}
+?>
\ No newline at end of file
diff --git a/core/components/redirector/model/redirector/mysql/modredirect.map.inc.php b/core/components/redirector/model/redirector/mysql/modredirect.map.inc.php
index 26e89b4..19dde9c 100644
--- a/core/components/redirector/model/redirector/mysql/modredirect.map.inc.php
+++ b/core/components/redirector/model/redirector/mysql/modredirect.map.inc.php
@@ -4,11 +4,15 @@
*/
$xpdo_meta_map['modRedirect']= array (
'package' => 'redirector',
+ 'version' => NULL,
'table' => 'redirects',
+ 'extends' => 'xPDOSimpleObject',
'fields' =>
array (
'pattern' => '',
'target' => '',
+ 'sortorder' => 0,
+ 'isregexp' => 0,
'active' => 1,
),
'fieldMeta' =>
@@ -31,6 +35,23 @@
'default' => '',
'index' => 'index',
),
+ 'sortorder' =>
+ array (
+ 'dbtype' => 'int',
+ 'precision' => '10',
+ 'phptype' => 'integer',
+ 'null' => false,
+ 'default' => 0,
+ ),
+ 'isregexp' =>
+ array (
+ 'dbtype' => 'tinyint',
+ 'precision' => '1',
+ 'attributes' => 'unsigned',
+ 'phptype' => 'boolean',
+ 'null' => false,
+ 'default' => 0,
+ ),
'active' =>
array (
'dbtype' => 'tinyint',
diff --git a/core/components/redirector/model/redirector/mysql/modredirectpagenotfound.class.php b/core/components/redirector/model/redirector/mysql/modredirectpagenotfound.class.php
new file mode 100644
index 0000000..cd7154a
--- /dev/null
+++ b/core/components/redirector/model/redirector/mysql/modredirectpagenotfound.class.php
@@ -0,0 +1,14 @@
+__construct($xpdo);
+ }
+ function __construct(& $xpdo) {
+ parent :: __construct($xpdo);
+ }
+}
+?>
\ No newline at end of file
diff --git a/core/components/redirector/model/redirector/mysql/modredirectpagenotfound.map.inc.php b/core/components/redirector/model/redirector/mysql/modredirectpagenotfound.map.inc.php
new file mode 100644
index 0000000..27450fc
--- /dev/null
+++ b/core/components/redirector/model/redirector/mysql/modredirectpagenotfound.map.inc.php
@@ -0,0 +1,59 @@
+ 'redirector',
+ 'version' => NULL,
+ 'table' => 'pagesnotfound',
+ 'extends' => 'xPDOSimpleObject',
+ 'fields' =>
+ array (
+ 'url' => NULL,
+ 'times' => 0,
+ 'firsttime' => 0,
+ 'lasttime' => 0,
+ 'visible' => 1,
+ ),
+ 'fieldMeta' =>
+ array (
+ 'url' =>
+ array (
+ 'dbtype' => 'text',
+ 'phptype' => 'string',
+ ),
+ 'times' =>
+ array (
+ 'dbtype' => 'int',
+ 'precision' => '10',
+ 'phptype' => 'integer',
+ 'null' => false,
+ 'default' => 0,
+ ),
+ 'firsttime' =>
+ array (
+ 'dbtype' => 'int',
+ 'precision' => '100',
+ 'phptype' => 'integer',
+ 'null' => true,
+ 'default' => 0,
+ ),
+ 'lasttime' =>
+ array (
+ 'dbtype' => 'int',
+ 'precision' => '100',
+ 'phptype' => 'integer',
+ 'null' => true,
+ 'default' => 0,
+ ),
+ 'visible' =>
+ array (
+ 'dbtype' => 'tinyint',
+ 'precision' => '1',
+ 'attributes' => 'unsigned',
+ 'phptype' => 'boolean',
+ 'null' => false,
+ 'default' => 1,
+ ),
+ ),
+);
diff --git a/core/components/redirector/model/redirector/redirector.class.php b/core/components/redirector/model/redirector/redirector.class.php
index 2bea1aa..56e72e3 100644
--- a/core/components/redirector/model/redirector/redirector.class.php
+++ b/core/components/redirector/model/redirector/redirector.class.php
@@ -26,9 +26,113 @@ function __construct(modX &$modx,array $config = array()) {
'connectorUrl' => $assetsUrl.'connector.php',
),$config);
+
+ $this->cacheName = 'Redirector';
+ $this->cache = $this->modx->cacheManager->getCacheProvider($this->cacheName, array(
+ xPDO::OPT_CACHE_KEY => $this->cacheName
+ ));
+
$this->modx->addPackage('redirector',$this->config['modelPath']);
}
+
+ /**
+ * Given a search parameter, look in the cache for a match. If none found, look for a matching pattern. If found,
+ * redirect. Otherwise do nothing.
+ * @param $search
+ */
+ public function getRedirect($search){
+ // Look for a target in the cache
+ $redirect = $this->cache->get(md5($search));
+ if($redirect){
+ $this->doRedirect($redirect, $search, 'Cache');
+ exit();
+ }
+
+ // No entry in the cache. Try to match a pattern.
+
+ // Exact text match
+ $pattern = $this->modx->getObject('modRedirect', array(
+ 'pattern' => $search
+ ,'active' => 1
+ ));
+ if($pattern){
+ $target = $pattern->get('target');
+ $this->doRedirect($target, $search, 'Plain Text');
+ exit();
+ }
+
+ // No luck ? Check the regexp.
+ $query = $this->modx->newQuery('modRedirect');
+ $query->where(array('active' => 1, 'isregexp' => 1));
+ $query->sortby('sortorder', 'ASC');
+ $patterns = $this->modx->getCollection('modRedirect', $query);
+ foreach($patterns as $pattern){
+ $pat = $pattern->get('pattern');
+ if(preg_match("~$pat~", $search)){
+ $target = $pattern->get('target');
+ $target = preg_replace("~$pat~", $target, preg_replace('/[\[\]]/', '',$search));
+ $this->doRedirect($target, $search, 'Regexp');
+ exit();
+ }
+ }
+ }
+
+ /**
+ * Prepare the new URL and redirect the user (and cache the redirect).
+ *
+ * @param $target String target recorded in the database
+ * @param $search String the search string used
+ */
+ private function doRedirect($target, $search='', $type='Plain Text'){
+ $this->modx->parser->processElementTags('', $target, true, true);
+ if ($target != $this->modx->resourceIdentifier && $target != $search) {
+ $short_target = $target;
+ if (!strpos($target, '://')) {
+ $target = $this->modx->getOption('site_url').$target;
+ }
+ $this->modx->log(modX::LOG_LEVEL_INFO, 'Redirector plugin redirecting request for ' . $search . ' to ' . $target. 'Rule: '.$type);
+
+ // Cache the new redirect
+ $this->cache->set(md5($search), $short_target);
+
+ // Perform the redirect.
+ header('HTTP/1.1 301 Moved Permanently');
+ $this->modx->sendRedirect($target);
+ exit();
+ }
+ }
+
+
+ public function record404($search){
+ $error = $this->modx->getObject('modRedirectPageNotFound', array('url' => $search));
+ $now = time();
+ if(!empty($error)){ // We've encountered this one before.
+ $count = $error->get('times');
+ $count += 1;
+ $error->set('times', $count);
+ $error->set('lasttime', $now);
+ $error->save();
+ } else {
+ $error = $this->modx->newObject('modRedirectPageNotFound');
+ $error->set('url', $search);
+ $error->set('firsttime', $now);
+ $error->set('lasttime', $now);
+ $error->set('times', 1);
+ $error->set('visible', 1);
+ $error->save();
+ }
+ }
+
+
+ /**
+ * Clear the Redirect cache
+ * @access public
+ */
+ public function clearRedirectCache(){
+ $this->modx->cacheManager->refresh(array($this->cacheName => array()));
+ }
+
/**
* Initializes the class into the proper context
*
@@ -45,14 +149,14 @@ public function initialize($ctx = 'web') {
}
$this->request = new redirectorControllerRequest($this);
return $this->request->handleRequest();
- break;
+ break;
case 'connector':
if (!$this->modx->loadClass('redirector.request.redirectorConnectorRequest',$this->config['modelPath'],true,true)) {
echo 'Could not load connector request handler.'; die();
}
$this->request = new redirectorConnectorRequest($this);
return $this->request->handle();
- break;
+ break;
default: break;
}
return true;
diff --git a/core/components/redirector/model/redirector/sqlsrv/modredirect.map.inc.php b/core/components/redirector/model/redirector/sqlsrv/modredirect.map.inc.php
index cc0098d..965b605 100644
--- a/core/components/redirector/model/redirector/sqlsrv/modredirect.map.inc.php
+++ b/core/components/redirector/model/redirector/sqlsrv/modredirect.map.inc.php
@@ -4,7 +4,9 @@
*/
$xpdo_meta_map['modRedirect']= array (
'package' => 'redirector',
+ 'version' => NULL,
'table' => 'redirects',
+ 'extends' => 'xPDOSimpleObject',
'fields' =>
array (
'pattern' => '',
diff --git a/core/components/redirector/model/schema/redirector.mysql.schema.xml b/core/components/redirector/model/schema/redirector.mysql.schema.xml
index 7aeb785..43402c9 100644
--- a/core/components/redirector/model/schema/redirector.mysql.schema.xml
+++ b/core/components/redirector/model/schema/redirector.mysql.schema.xml
@@ -3,6 +3,16 @@
+
+
\ No newline at end of file
diff --git a/core/components/redirector/processors/mgr/errors/getlist.php b/core/components/redirector/processors/mgr/errors/getlist.php
new file mode 100644
index 0000000..a18c2cb
--- /dev/null
+++ b/core/components/redirector/processors/mgr/errors/getlist.php
@@ -0,0 +1,56 @@
+getOption('start',$_REQUEST,0);
+$limit = $modx->getOption('limit',$_REQUEST,20);
+$sort = $modx->getOption('sort',$_REQUEST,'times');
+$dir = $modx->getOption('dir',$_REQUEST,'DESC');
+$query = $modx->getOption('query',$_REQUEST,'');
+
+/* build query */
+$c = $modx->newQuery('modRedirectPageNotFound');
+
+if (!empty($query)) {
+ $c->where(array(
+ 'url:LIKE' => '%'.$query.'%',
+ ));
+}
+
+$count = $modx->getCount('modRedirectPageNotFound',$c);
+$c->sortby($sort,$dir);
+if ($isLimit) $c->limit($limit,$start);
+$redirects= $modx->getCollection('modRedirectPageNotFound', $c);
+
+/* iterate */
+$list = array();
+foreach ($redirects as $redirect) {
+
+ // Format dates
+ $a = $redirect->toArray();
+ $a['firsttime'] = strftime('%c', $a['firsttime']);
+ $a['lasttime'] = strftime('%c', $a['lasttime']);
+
+ $redirectArray = $a;
+
+ $redirectArray['menu'][] = array(
+ 'text' => $modx->lexicon('redirector.create_rule'),
+ 'handler' => 'this.createRedirectPageNotFound',
+ );
+
+ $redirectArray['menu'][] = '-';
+
+ $redirectArray['menu'][] = array(
+ 'text' => $modx->lexicon('redirector.remove_page_not_found'),
+ 'handler' => 'this.removeRedirectPageNotFound',
+ );
+
+
+ $list[]= $redirectArray;
+}
+return $this->outputArray($list,$count);
\ No newline at end of file
diff --git a/core/components/redirector/processors/mgr/errors/remove.php b/core/components/redirector/processors/mgr/errors/remove.php
new file mode 100644
index 0000000..bfb2ed7
--- /dev/null
+++ b/core/components/redirector/processors/mgr/errors/remove.php
@@ -0,0 +1,17 @@
+error->failure($modx->lexicon('redirector.redirect_err_ns'));
+$redirect = $modx->getObject('modRedirectPageNotFound',$scriptProperties['id']);
+if (empty($redirect)) return $modx->error->failure($modx->lexicon('redirector.redirect_err_nf'));
+
+/* remove */
+if ($redirect->remove() == false) {
+ return $modx->error->failure($modx->lexicon('redirector.redirect_err_remove'));
+}
+
+return $modx->error->success('',$redirect);
\ No newline at end of file
diff --git a/core/components/redirector/processors/mgr/errors/update.php b/core/components/redirector/processors/mgr/errors/update.php
new file mode 100644
index 0000000..63ea711
--- /dev/null
+++ b/core/components/redirector/processors/mgr/errors/update.php
@@ -0,0 +1,26 @@
+error->failure($modx->lexicon('redirector.redirect_err_ns'));
+$redirect = $modx->getObject('modRedirectPageNotFound',$scriptProperties['id']);
+if (empty($redirect)) return $modx->error->failure($modx->lexicon('redirector.redirect_err_nf'));
+
+/* put checkbox to 0 if not present in the array */
+if(!array_key_exists('visible', $scriptProperties))
+ $scriptProperties['visible'] = '0';
+
+/* set fields */
+$redirect->fromArray($scriptProperties);
+
+/* save */
+if ($redirect->save() == false) {
+
+ return $modx->error->failure($modx->lexicon('redirector.redirect_err_save'));
+}
+
+
+return $modx->error->success('',$redirect);
\ No newline at end of file
diff --git a/core/components/redirector/processors/mgr/redirect/getlist.php b/core/components/redirector/processors/mgr/redirect/getlist.php
index 35bc438..cf0b595 100644
--- a/core/components/redirector/processors/mgr/redirect/getlist.php
+++ b/core/components/redirector/processors/mgr/redirect/getlist.php
@@ -8,8 +8,8 @@
/* setup default properties */
$isLimit = !empty($_REQUEST['limit']);
$start = $modx->getOption('start',$_REQUEST,0);
-$limit = $modx->getOption('limit',$_REQUEST,20);
-$sort = $modx->getOption('sort',$_REQUEST,'pattern');
+$limit = $modx->getOption('limit',$_REQUEST,0);
+$sort = $modx->getOption('sort',$_REQUEST,'sortorder');
$dir = $modx->getOption('dir',$_REQUEST,'ASC');
$query = $modx->getOption('query',$_REQUEST,'');
@@ -27,7 +27,7 @@
$count = $modx->getCount('modRedirect',$c);
$c->sortby($sort,$dir);
-if ($isLimit) $c->limit($limit,$start);
+//if ($isLimit) $c->limit($limit,$start); //Ignore the limit
$redirects= $modx->getCollection('modRedirect', $c);
/* iterate */
diff --git a/core/components/redirector/processors/mgr/redirect/sort.php b/core/components/redirector/processors/mgr/redirect/sort.php
new file mode 100644
index 0000000..361d30e
--- /dev/null
+++ b/core/components/redirector/processors/mgr/redirect/sort.php
@@ -0,0 +1,15 @@
+fromJSON($scriptProperties['items']);
+
+if(is_array($items)){
+ foreach($items as $sortorder => $fields){
+ if($image = $modx->getObject('modRedirect', $fields['id'])){
+ $image->fromArray($fields);
+ $image->set('sortorder', ($sortorder));
+ $image->save();
+ }
+ }
+}
+
+return $modx->error->success();
\ No newline at end of file
diff --git a/core/components/redirector/processors/mgr/redirect/update.php b/core/components/redirector/processors/mgr/redirect/update.php
index f21c7a1..922fe7b 100644
--- a/core/components/redirector/processors/mgr/redirect/update.php
+++ b/core/components/redirector/processors/mgr/redirect/update.php
@@ -13,11 +13,17 @@
if(!array_key_exists('active', $scriptProperties))
$scriptProperties['active'] = '0';
+/* same with isregexp */
+if(!array_key_exists('isregexp', $scriptProperties))
+ $scriptProperties['isregexp'] = '0';
+
+
/* set fields */
$redirect->fromArray($scriptProperties);
/* save */
if ($redirect->save() == false) {
+
return $modx->error->failure($modx->lexicon('redirector.redirect_err_save'));
}