Skip to content

Instantly share code, notes, and snippets.

@n9iels
Last active April 2, 2019 11:17
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save n9iels/e0add7304b1ac36180869a6d191d7aec to your computer and use it in GitHub Desktop.
Save n9iels/e0add7304b1ac36180869a6d191d7aec to your computer and use it in GitHub Desktop.
CLI script to recreate all urls in articles on a Joomla! website and create redirects for the old urls.
<?php
/**
* @package Joomla.Cli
*
* @copyright Copyright (C) 2018 Niels van der Veer. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
/**
* This is a CRON script which should be called from the command-line, not the
* web. For example something like:
* /usr/bin/php /path/to/site/cli/update_cron.php
*/
// Set flag that this is a parent file.
const _JEXEC = 1;
error_reporting(E_ALL | E_NOTICE);
ini_set('display_errors', 1);
// Load system defines
if (file_exists(dirname(__DIR__) . '/defines.php'))
{
require_once dirname(__DIR__) . '/defines.php';
}
if (!defined('_JDEFINES'))
{
define('JPATH_BASE', dirname(__DIR__));
require_once JPATH_BASE . '/includes/defines.php';
}
require_once JPATH_LIBRARIES . '/import.legacy.php';
require_once JPATH_LIBRARIES . '/cms.php';
// Load the configuration
require_once JPATH_CONFIGURATION . '/configuration.php';
JLoader::register('ContentHelperRoute', JPATH_ROOT . '/components/com_content/helpers/route.php');
/**
* This script will fetch the update information for all extensions and store
* them in the database, speeding up your administrator.
*
* @since 2.5
*/
class MigrateUrlsCli extends JApplicationCli
{
/**
* Entry point for the script
*
* @return void
*
* @since 2.5
*/
public function doExecute()
{
$articles = $this->getAllArticles();
foreach ($articles as $article) {
$replacedText = $article->introtext;
preg_match_all('~<a(.*?)href="([^"]+)"(.*?)>~', $article->introtext, $matches);
foreach ($matches[2] as $key => $match) {
$url = $this->recreateUrl($match);
$html = $matches[0][$key];
if ($url != null) {
$replacedText = str_replace($html, '<a href="' . $url . '">', $replacedText);
}
}
$this->updateArticleText($article->id, $replacedText);
// Use this method to create a redirect for a old url to a new url. Write some custom logic here to get the correct category and url that fit your needs.
// $this->addRedirect('/' . $article->alias, '/' . $category . '/' . $article->alias);
}
}
/**
* Parse a found url in the article
*
* @param $url string Url to parse`
*
* @since 1.0.0
* @return boolean
*/
private function recreateUrl($url)
{
if (strpos($url, "index.php") === false)
{
return null;
}
// Parse url and query
$parsedUrl = parse_url(str_replace("&amp;", "&", $url));
parse_str($parsedUrl['query'], $parsedQuery);
// If the link has no id, print and skip
if(!array_key_exists("id", $parsedQuery)) {
$this->out("No id found in: " . $url);
return null;
}
// If the id contains a alias, remove it
if (strpos($parsedQuery["id"], ":") !== false)
{
$parsedQuery["id"] = preg_split("/:/", $parsedQuery["id"])[0];
}
// Get the article and create a new url
$article = $this->getArticle($parsedQuery['id']);
if ($article == null)
{
$this->out("no article found for id: " . $parsedQuery["id"]);
return null;
}
return htmlspecialchars(ContentHelperRoute::getArticleRoute($article->id, $article->catid, '*'));
}
/**
* Get a single article by ID
*
* @param $id int id of the article
* @return stdClass
*/
private function getArticle($id)
{
$db = \Joomla\CMS\Factory::getDbo();
$q = $db->getQuery(true)
->select("*")
->from($db->qn("#__content"))
->where($db->qn("id") . '=' . (int) $id);
$db->setQuery($q);
return $db->loadObject();
}
/**
* Get all articles in the database
*
* @return mixed
*/
private function getAllArticles()
{
$db = \Joomla\CMS\Factory::getDbo();
$q = $db->getQuery(true)
->select("*")
->from($db->qn("#__content"));
$db->setQuery($q);
return $db->loadObjectList();
}
/**
* Update the article text of a article
*
* @param $id int Article id
* @param $text string New article text
*
* @return void
*/
private function updateArticleText($id, $text)
{
$db = \Joomla\CMS\Factory::getDbo();
$query = $db->getQuery(true);
// Fields to update.
$fields = array(
$db->quoteName('introtext') . ' = ' . $db->quote($text)
);
// Conditions for which records should be updated.
$conditions = array(
$db->quoteName('id') . ' = ' . (int) $id
);
$query->update($db->quoteName('#__content'))->set($fields)->where($conditions);
$db->setQuery($query);
$db->execute();
}
/**
* Add a 301 redirect
*
* $oldUrl string The old url to redirect
* $newUrl string The new url
*/
private function addRedirect($oldUrl, $newUrl)
{
$date = \Joomla\CMS\Factory::getDate();
$db = \Joomla\CMS\Factory::getDbo();
// Create a new query object.
$query = $db->getQuery(true);
// Insert columns.
$columns = array('old_url', 'new_url', 'published', 'header', 'created_date', 'modified_date');
// Insert values.
$values = array($db->quote($oldUrl), $db->quote($newUrl), 1, 301, $db->quote($date->toSql()), $db->quote($date->toSql()));
// Prepare the insert query.
$query
->insert($db->quoteName('#__redirect_links'))
->columns($db->quoteName($columns))
->values(implode(',', $values));
// Set the query using our newly populated query object and execute it.
$db->setQuery($query);
$db->execute();
}
}
JApplicationCli::getInstance('MigrateUrlsCli')->execute();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment