Sterc / SEOTab

SEO assistance for MODX — Optimize your MODX Revolution pages for the best Search Engine performance. Follow https://twitter.com/sterc for tips and updates.
https://www.sterc.com/modx/extras/
25 stars 31 forks source link

Redirects with query params #184

Open ic3m3n opened 5 years ago

ic3m3n commented 5 years ago

Hey, I recently modified your plugin StercSEO to generate and save 301 redirects without respecting the query parameters. The reason was, to make redirects running independent of query parameters.

It would be great if there would be a setting to respect, ignore or simply pass query parameters to the target url.

Here's the full modified plugin code.

<?php
/**
 * SEO Tab
 *
 * Copyright 2013 by Sterc internet & marketing <modx@sterc.nl>
 *
 * This file is part of SEO Tab.
 *
 * SEO Tab is free software; you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * SEO Tab is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * SEO Tab; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
 * Suite 330, Boston, MA 02111-1307 USA
 *
 * @package stercseo
 */
/**
 * SEO Tab Plugin
 *
 *
 * Events:
 * OnDocFormPrerender,OnDocFormSave,OnHandleRequest,OnPageNotFound, OnResourceDuplicate, OnEmptyThrash, OnResourceBeforeSort
 *
 * @author Sterc internet & marketing <modx@sterc.nl>
 *
 * @package stercseo
 *
 */
$stercseo = $modx->getService('stercseo', 'StercSEO', $modx->getOption('stercseo.core_path', null, $modx->getOption('core_path').'components/stercseo/').'model/stercseo/', array());

if (!($stercseo instanceof StercSEO)) {
    return;
}

switch ($modx->event->name) {
    case 'OnDocFormPrerender':
        if (!$stercseo->checkUserAccess()) {
            return;
        }

        $resource =& $modx->event->params['resource'];
        if ($resource) {
            $stercseo->setWorkingContext($resource->get('context_key'));

            //First check if SEO Tab is allowed in this context
            if (!$stercseo->isAllowed($resource->get('context_key'))) {
                return;
            }
            $properties = $resource->getProperties('stercseo');
            $urls = $modx->getCollection('seoUrl', array('resource' => $resource->get('id')));
        } elseif (isset($_GET['context_key'])) {
            $stercseo->setWorkingContext($_GET['context_key']);
        }

        if (empty($properties)) {
            $properties = array(
                'index' => $stercseo->getOption('stercseo.index', null, '1'),
                'follow' => $stercseo->getOption('stercseo.follow', null, '1'),
                'sitemap' => $stercseo->getOption('stercseo.sitemap', null, '1'),
                'priority' => $stercseo->getOption('stercseo.priority', null, '0.5'),
                'changefreq' => $stercseo->getOption('stercseo.changefreq', null, 'weekly'),
                'searchable' => $stercseo->getOption('search_default', null, '1')
            );
        } elseif ($resource) {
            $properties['searchable'] = $resource->get('searchable');
        }

        $properties['urls'] = '';
        // Fetch urls from seoUrl collection
        if ($urls && is_object($urls)) {
            foreach ($urls as $url) {
                $properties['urls'][]['url'] = urldecode($url->get('url'));
            }
        }

        $modx->regClientStartupHTMLBlock('<script type="text/javascript">
        Ext.onReady(function() {
            StercSEO.config = '.$modx->toJSON($stercseo->config).';
            StercSEO.config.connector_url = "'.$stercseo->config['connectorUrl'].'";
            StercSEO.record = '.$modx->toJSON($properties).';
        });
        </script>');
        $version = $modx->getVersionData();

        /* include CSS and JS*/
        if ($version['version'] == 2 && $version['major_version'] == 2) {
            $modx->regClientCSS($stercseo->config['cssUrl'].'stercseo.css');
        }
        $modx->regClientStartupScript($stercseo->config['jsUrl'].'mgr/stercseo.js');
        $modx->regClientStartupScript($stercseo->config['jsUrl'].'mgr/sections/resource.js');
        $modx->regClientStartupScript($stercseo->config['jsUrl'].'mgr/widgets/resource.grid.js');
        $modx->regClientStartupScript($stercseo->config['jsUrl'].'mgr/widgets/resource.vtabs.js');

        //add lexicon
        $modx->controller->addLexiconTopic('stercseo:default');

        break;

    case 'OnBeforeDocFormSave':
        $oldResource = ($mode == 'upd') ? $modx->getObject('modResource', $resource->get('id')) : $resource;
        if (!$stercseo->isAllowed($oldResource->get('context_key'))) {
            return;
        }

        $stercseo->setWorkingContext($resource->get('context_key'));

        /* If freeze URI is set, checks if a redirect already exists for the freeze URI and returns error if a redirect has been found. */
        $stercseo->checkIfFreezeUriExistsAsRedirect($resource);

        $properties = $oldResource->getProperties('stercseo');
        if (isset($_POST['urls'])) {
            $urls = $modx->fromJSON($_POST['urls']);
            foreach ($urls as $url) {
                $check = $modx->getObject('seoUrl', array( 'url' => urlencode($url['url']), 'resource' => $oldResource->get('id'), 'context_key' => $oldResource->get('context_key')));
                if (!$check) {
                    $redirect = $modx->newObject('seoUrl');
                    $data = array(
                        'url' => urlencode($url['url']),
                        'resource' => $oldResource->get('id'),
                        'context_key' => $oldResource->get('context_key'),
                    );
                    $redirect->fromArray($data);
                    $redirect->save();
                }
            }
        }

        if ($mode == 'upd') {
            $newProperties = array(
                'index' => (isset($_POST['index']) ? $_POST['index'] : $properties['index']),
                'follow' => (isset($_POST['follow']) ? $_POST['follow'] : $properties['follow']),
                'sitemap' => (isset($_POST['sitemap']) ? $_POST['sitemap'] : $properties['sitemap']),
                'priority' => (isset($_POST['priority']) ? $_POST['priority'] : $properties['priority']),
                'changefreq' => (isset($_POST['changefreq']) ? $_POST['changefreq'] : $properties['changefreq'])
            );
        } else {
            $newProperties = array(
                'index' => (isset($_POST['index']) ? $_POST['index'] : $stercseo->getOption('stercseo.index', null, '1')),
                'follow' => (isset($_POST['follow']) ? $_POST['follow'] : $stercseo->getOption('stercseo.follow', null, '1')),
                'sitemap' => (isset($_POST['sitemap']) ? $_POST['sitemap'] : $stercseo->getOption('stercseo.sitemap', null, '1')),
                'priority' => (isset($_POST['priority']) ? $_POST['priority'] : $stercseo->getOption('stercseo.priority', null, '0.5')),
                'changefreq' => (isset($_POST['changefreq']) ? $_POST['changefreq'] : $stercseo->getOption('stercseo.changefreq', null, 'weekly'))
            );
        }

        // If uri is changed or alias (with freeze uri off) has changed, add a new redirect
        if ((
                $oldResource->get('uri') != $resource->get('uri') ||
                (
                    $oldResource->get('uri_override') == 0
                    && $oldResource->get('alias') != $resource->get('alias')
                )
            )
            && $oldResource->get('uri') != ''
        ) {
            $site_url = $modx->getOption('site_url');
            if ($stercseo->getOption('site_url')) {
                $site_url = $stercseo->getOption('site_url');
            }

            $url = urlencode($site_url.$oldResource->get('uri'));
            if (!$modx->getCount('seoUrl', array('url' => $url))) {
                $data = array(
                    'url' => $url,
                    'resource' => $resource->get('id'),
                    'context_key' => $resource->get('context_key'),
                );
                $redirect = $modx->newObject('seoUrl');
                $redirect->fromArray($data);
                $redirect->save();
            }

            // Recursive set all children resources as redirects
            if ($modx->getOption('use_alias_path')) {
                $resourceOldBasePath = $oldResource->getAliasPath($oldResource->get('alias'), $oldResource->toArray() + array('isfolder' => 1));
                $resourceNewBasePath = $resource->getAliasPath($resource->get('alias'), $resource->toArray() + array('isfolder' => 1));
                $childResources = $modx->getIterator('modResource', array(
                    'uri:LIKE' => $resourceOldBasePath . '%',
                    'uri_override' => '0',
                    'published' => '1',
                    'deleted' => '0',
                    'context_key' => $resource->get('context_key')
                ));
                foreach ($childResources as $childResource) {
                    $url = urlencode($site_url.$childResource->get('uri'));
                    if (!$modx->getCount('seoUrl', array('url' => $url))) {
                        $data = array(
                            'url' => $url,
                            'resource' => $childResource->get('id'),
                            'context_key' => $resource->get('context_key'),
                        );
                        $redirect = $modx->newObject('seoUrl');
                        $redirect->fromArray($data);
                        $redirect->save();
                    }
                }
            }
        }
        $resource->setProperties($newProperties, 'stercseo');
        break;

    case 'OnDocFormSave':
        if (!$stercseo->isAllowed($resource->context_key)) {
            return;
        }

        /* Tmp overwrite the cache_alias_map setting to prevent that a redirect is removed again. */
        $cacheAliasMap = $modx->getOption('cache_alias_map', true);
        $modx->setOption('cache_alias_map', false);

        $url       = urlencode($modx->makeUrl($resource->id, $resource->context_key, '', 'full'));
        $urlExists = $modx->getObject('seoUrl', array(
            'url'         => $url,
            'context_key' => $resource->context_key
        ));

        if ($urlExists) {
            $modx->removeObject('seoUrl', array(
                'url'         => $url,
                'context_key' => $resource->context_key
            ));
        }

        $modx->setOption('cache_alias_map', $cacheAliasMap);
        break;

    case 'OnLoadWebDocument':
        if ($modx->resource) {
            if (!$stercseo->isAllowed($modx->resource->get('context_key'))) {
                return;
            }
            $properties = $modx->resource->getProperties('stercseo');
            if (empty($properties)) {
                // Properties not available
                // This means an this resource has nog SEO Tab properties, which means it is a pre-SEO Tab resource
                // Fallback to system defaults
                $properties = array(
                    'index' => $modx->getOption('stercseo.index', null, 1),
                    'follow' => $modx->getOption('stercseo.follow', null, 1)
                );
            }
            $metaContent = array(
                (int)$properties['index'] ? 'index' : 'noindex',
                (int)$properties['follow'] ? 'follow' : 'nofollow'
            );

            $modx->setPlaceholder('seoTab.robotsTag', implode(',', $metaContent));
        }
        break;

    case 'OnPageNotFound':
        $options = array();
        $query   = $modx->newQuery('seoUrl');
        $url     = $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
        $url_parsed   = parse_url($url);
        $convertedUrl = $url_parsed['host'].$url_parsed['path'];

        $url_props = array(
            'url' => $url,
            'query' => $url_parsed['query'],
            'fragment' => $url_parsed['fragment']
        );

        $query->where(array(
            array(
                'url' => urlencode('http://' . $convertedUrl)
            ),
            array(
                'url' => urlencode('https://' . $convertedUrl)
            )
        ),xPDOQuery::SQL_OR);

         if ($modx->getOption('stercseo.context-aware-alias', null, '0')) {
             $query->where(
                 array(
                     'context_key' => $modx->context->key
                 )
             );
         }

        $alreadyExists = $modx->getObject('seoUrl', $query);
        if (isset($alreadyExists) && ($modx->context->key !== $alreadyExists->get('context_key'))) {
            $q = $modx->newQuery('modContextSetting');
            $q->where(array(
                'context_key' => $alreadyExists->get('context_key'),
                'key'         => 'site_url'
            ));
            $q->prepare();

            $siteUrl = $modx->getObject('modContextSetting', $q);
            if ($siteUrl) {
                $options['site_url'] = $siteUrl->get('value');
            }
        }

        if ($alreadyExists) {
            $url = $modx->makeUrl($alreadyExists->get('resource'), $alreadyExists->get('context_key'), '', 'full', $options);

            if(!empty($url_props['query'])) {
                $url = $url.'?'.$url_props['query'];
            }
            if(!empty($url_props['fragment'])) {
                $url = $url.'#'.$url_props['fragment'];
            }

            $modx->sendRedirect($url, 0, 'REDIRECT_HEADER', 'HTTP/1.1 301 Moved Permanently');
        }
        break;

    case 'OnResourceBeforeSort':
        list($sourceCtx, $resource) = explode('_', $modx->getOption('source', $_POST));
        list($targetCtx, $target) = explode('_', $modx->getOption('target', $_POST));
        switch ($modx->getOption('point', $_POST)) {
            case 'above':
            case 'below':
                $tmpRes = $modx->getObject('modResource', $target);
                if ($tmpRes) {
                    $target = $tmpRes->get('parent');
                    unset($tmpRes);
                }
                break;
        }
        $oldResource = $modx->getObject('modResource', $resource);
        $resource = $modx->getObject('modResource', $resource);
        if ($oldResource && $resource) {
            $resource->set('parent', $target);
            $resource->set('uri', '');
            $uriChanged = false;
            if ($oldResource->get('uri') != $resource->get('uri') && $oldResource->get('uri') != '') {
                $uriChanged = true;
            }

            if ($oldResource->get('alias') != $resource->get('alias') && $oldResource->get('alias') != '') {
                $newProperties['urls'][] = array('url' => $oldResource->get('uri'));
                $uriChanged              = true;
            }

            // Recursive set redirects for drag/dropped resource, and its children (where uri_override is not set)
            if ($uriChanged && $modx->getOption('use_alias_path')) {
                $oldResource->set('isfolder', true);
                $resourceOldBasePath = $oldResource->getAliasPath(
                    $oldResource->get('alias'),
                    $oldResource->toArray()
                );
                $resourceNewBasePath = $resource->getAliasPath(
                    $resource->get('alias'),
                    $resource->toArray() + array('isfolder' => 1)
                );
                $cond = $modx->newQuery('modResource');
                $cond->where(array(
                    array(
                        'uri:LIKE' => $resourceOldBasePath . '%',
                        'OR:id:=' => $oldResource->id
                    ),
                    'uri_override' => '0',
                    'published' => '1',
                    'deleted' => '0',
                    'context_key' => $resource->get('context_key')
                ));

                $stercseo->setWorkingContext($resource->get('context_key'));

                $site_url = $stercseo->getOption('site_url', '', $modx->getOption('site_url'));

                $childResources = $modx->getIterator('modResource', $cond);
                foreach ($childResources as $childResource) {
                    $url = urlencode($site_url . $childResource->get('uri'));
                    if (!$modx->getCount('seoUrl', array('url' => $url))) {
                        $data = array(
                            'url' => $url,
                            'resource' => $childResource->get('id'),
                            'context_key' => $targetCtx
                        );
                        $redirect = $modx->newObject('seoUrl');
                        $redirect->fromArray($data);
                        $redirect->save();
                    }
                }
            } // endif $uriChanged
        } // endif $oldResource && $resource
        break;

    case 'OnResourceDuplicate':
        if (!$stercseo->isAllowed($newResource->get('context_key'))) {
            return;
        }
        $props = $newResource->getProperties('stercseo');
        $newResource->setProperties($props, 'stercseo');
        $newResource->save();
        break;

    case 'OnManagerPageBeforeRender':
        if (!$stercseo->checkUserAccess()) {
            return;
        }
        // If migration status is false, show migrate alert message bar in manager
        if (!$stercseo->redirectMigrationStatus()) {
            $modx->regClientStartupHTMLBlock($stercseo->getChunk('migrate/alert', array('message' => $modx->lexicon('stercseo.migrate_alert'))));
            $modx->regClientCSS($stercseo->config['cssUrl'].'migrate.css');
        }
        break;

    case 'OnEmptyTrash':
        if (count($ids) > 0) {
            foreach ($ids as $id) {
                $modx->removeCollection('seoUrl', array(
                    'resource' => $id
                ));
            }
        }
}
return;
zenotds commented 3 years ago

Life saver! ❤️