Last active
April 2, 2019 11:17
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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("&", "&", $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