Files
2024-12-31 11:07:09 +01:00

413 lines
11 KiB
PHP

<?php
/**
* @package Advanced Custom Fields
* @version 2.8.8 Pro
*
* @author Tassos Marinos <info@tassos.gr>
* @link http://www.tassos.gr
* @copyright Copyright © 2021 Tassos Marinos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
defined('_JEXEC') or die('Restricted access');
use NRFramework\Extension;
use Joomla\Registry\Registry;
use Joomla\Filesystem\Path;
use Joomla\CMS\Factory;
class ACFMigrator
{
/**
* Application object.
*
* @var object
*/
private $app;
/**
* Database object.
*
* @var object
*/
private $db;
/**
* Database object.
*
* @var object
*/
private $dbDestination;
/**
* The currently installed version.
*
* @var string
*/
private $installedVersion;
/**
* Class constructor
*
* @param string $installedVersion The current extension version
*/
public function __construct($installedVersion, $dbSource = null, $dbDestination = null)
{
$this->app = Factory::getApplication();
$this->db = $dbSource ? $dbSource : Factory::getDbo();
$this->dbDestination = $dbDestination ? $dbDestination : Factory::getDbo();
$this->installedVersion = $installedVersion;
}
public function do()
{
if (version_compare($this->installedVersion, '1.3.0', '<='))
{
$this->uploadFieldConvertBasenameToRelativePaths();
}
if (version_compare($this->installedVersion, '2.1', '<='))
{
$this->migratePublishingRulesToConditionBuilder();
}
if (version_compare($this->installedVersion, '2.7.2', '<='))
{
$this->updateMapMaximumMarkers();
}
if (version_compare($this->installedVersion, '2.7.3', '<='))
{
$this->updateAddressDefaultMarkerImage();
$this->updateMapValue();
}
}
/**
* ACF Address used the default marker image from the ACF OSM custom field.
*
* Old path: media/plg_fields_acfosm/img/marker.png
*
* However, since the ACF OSM map is now removed from the build, we must update it
* to point to the same file but from the ACF Address custom field.
*
* New value: media/plg_fields_acfaddress/img/marker.png
*/
public function updateAddressDefaultMarkerImage()
{
// Get all custom fields.
$db = $this->db;
$query = $db->getQuery(true)
->select('*')
->from($db->quoteName('#__fields'))
->where($db->quoteName('type') . ' = ' . $db->q('acfaddress'));
$db->setQuery($query);
if (!$fields = $db->loadObjectList())
{
return;
}
foreach ($fields as $key => $field)
{
if (!isset($field->fieldparams))
{
continue;
}
$params = json_decode($field->fieldparams);
$markerImage = $params->marker_image;
if ($markerImage !== 'media/plg_fields_acfosm/img/marker.png')
{
continue;
}
$params->marker_image = 'media/plg_fields_acfaddress/img/marker.png';
// Update field `param` with new value
$dbDestination = $this->dbDestination;
$query = $dbDestination->getQuery(true)
->update($dbDestination->quoteName('#__fields'))
->set($dbDestination->quoteName('fieldparams') . '=' . $dbDestination->quote(json_encode($params)))
->where($dbDestination->quoteName('id') . '=' . $dbDestination->quote($field->id));
$dbDestination->setQuery($query);
$dbDestination->execute();
}
}
public function updateMapValue()
{
// Get all custom fields.
$db = $this->db;
$query = $db->getQuery(true)
->select('*')
->from($db->quoteName('#__fields'))
->where($db->quoteName('type') . ' = ' . $db->q('acfmap'));
$db->setQuery($query);
if (!$fields = $db->loadObjectList())
{
return;
}
$count = 0;
foreach ($fields as $key => $field)
{
// Find now all field values
$query = $db->getQuery(true)
->select('*')
->from($db->quoteName('#__fields_values'))
->where($db->quoteName('field_id') . ' = ' . $field->id);
$db->setQuery($query);
if (!$values = $db->loadObjectList())
{
return;
}
foreach ($values as $value)
{
if (!$decoded_value = json_decode($value->value, true))
{
continue;
}
if (!isset($decoded_value['markers']))
{
continue;
}
$newValue = $decoded_value['markers'];
$query = $db->getQuery(true);
$fields = [
$db->quoteName('value') . ' = ' . $db->q($newValue)
];
$conditions = [
$db->quoteName('field_id') . ' = ' . $value->field_id,
$db->quoteName('item_id') . ' = ' . $db->quote($value->item_id),
$db->quoteName('value') . ' = ' . $db->quote($value->value)
];
$query->update($db->quoteName('#__fields_values'))->set($fields)->where($conditions);
$db->setQuery($query);
$db->execute();
$count++;
}
}
return $count;
}
public function updateMapMaximumMarkers()
{
// Get all custom fields.
$db = $this->db;
$query = $db->getQuery(true)
->select('*')
->from($db->quoteName('#__fields'))
->where($db->quoteName('type') . ' = ' . $db->q('acfmap'));
$db->setQuery($query);
if (!$fields = $db->loadObjectList())
{
return;
}
foreach ($fields as $key => $field)
{
if (!isset($field->fieldparams))
{
continue;
}
$params = json_decode($field->fieldparams);
if (isset($params->maximum_markers))
{
continue;
}
$params->maximum_markers = 0;
// Update field `param` with new value
$dbDestination = $this->dbDestination;
$query = $dbDestination->getQuery(true)
->update($dbDestination->quoteName('#__fields'))
->set($dbDestination->quoteName('fieldparams') . '=' . $dbDestination->quote(json_encode($params)))
->where($dbDestination->quoteName('id') . '=' . $dbDestination->quote($field->id));
$dbDestination->setQuery($query);
$dbDestination->execute();
}
}
public function migratePublishingRulesToConditionBuilder()
{
// Get all custom fields.
$db = $this->db;
$query = $db->getQuery(true)
->select('*')
->from($db->quoteName('#__fields'));
$db->setQuery($query);
if (!$fields = $db->loadObjectList())
{
return;
}
foreach ($fields as $key => $field)
{
if (!isset($field->params))
{
continue;
}
$params = new Registry($field->params);
\NRFramework\Conditions\Migrator::run($params);
if (!isset($params['rules']) || empty($params['rules']))
{
continue;
}
// Update field `param` with new value
$dbDestination = $this->dbDestination;
$query = $dbDestination->getQuery(true)
->update($dbDestination->quoteName('#__fields'))
->set($dbDestination->quoteName('params') . '=' . $dbDestination->quote(json_encode($params)))
->where($dbDestination->quoteName('id') . '=' . $dbDestination->quote($field->id));
$dbDestination->setQuery($query);
$dbDestination->execute();
}
}
/**
* Since v1.3.0, the File Upload field is no longer storing just the file's name in the database but the full relative path to Joomla's root.
*
* This migration tasks, loops through all file values in the database and prepends to them the Upload Folder as configured in the Field settings.
*
* Previous value: myAwesomePhoto.jpg
* New value: media/myimages/myAwesomePhoto.jpg
*
* @return mixed Null when the migrationt ask doesn't run, Integer when the migration run.
*/
public function uploadFieldConvertBasenameToRelativePaths()
{
// Get all upload fields.
$db = $this->db;
$query = $db->getQuery(true)
->select('*')
->from($db->quoteName('#__fields'))
->where($db->quoteName('type') . ' = ' . $db->q('acfupload'));
$db->setQuery($query);
if (!$fields = $db->loadObjectList())
{
return;
}
$count = 0;
foreach ($fields as $key => $field)
{
if (!isset($field->fieldparams))
{
continue;
}
$params = json_decode($field->fieldparams);
if (!isset($params->upload_folder))
{
continue;
}
$upload_folder = $params->upload_folder;
// Find now all field values
$query = $db->getQuery(true)
->select('*')
->from($db->quoteName('#__fields_values'))
->where($db->quoteName('field_id') . ' = ' . $field->id);
$db->setQuery($query);
if (!$values = $db->loadObjectList())
{
return;
}
foreach ($values as $value)
{
if (!isset($value->value) || empty($value->value))
{
continue;
}
// If the path has a slash, consider it as already fixed.
if (strpos($value->value, DIRECTORY_SEPARATOR) !== false)
{
continue;
}
$newValue = trim(Path::clean($upload_folder . '/' . $value->value));
$query = $db->getQuery(true);
$fields = [
$db->quoteName('value') . ' = ' . $db->q($newValue)
];
$conditions = [
$db->quoteName('field_id') . ' = ' . $value->field_id,
$db->quoteName('item_id') . ' = ' . $db->quote($value->item_id),
$db->quoteName('value') . ' = ' . $db->quote($value->value)
];
$query->update($db->quoteName('#__fields_values'))->set($fields)->where($conditions);
$db->setQuery($query);
$db->execute();
$count++;
}
}
return $count;
}
}